annotate transform/ModelTransformer.h @ 1211:5a1198083d9a piper

Pull out model creation into the transformer thread run(), so that all communications with the plugin server happen on a single thread. Then make the model accessor wait for them to be created (which still happens right at the start of processing) before returning.
author Chris Cannam
date Mon, 17 Oct 2016 14:18:23 +0100
parents 6ea7761a418b
children 1b888a85983b
rev   line source
Chris@320 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@320 2
Chris@320 3 /*
Chris@320 4 Sonic Visualiser
Chris@320 5 An audio file viewer and annotation editor.
Chris@320 6 Centre for Digital Music, Queen Mary, University of London.
Chris@320 7 This file copyright 2006 Chris Cannam.
Chris@320 8
Chris@320 9 This program is free software; you can redistribute it and/or
Chris@320 10 modify it under the terms of the GNU General Public License as
Chris@320 11 published by the Free Software Foundation; either version 2 of the
Chris@320 12 License, or (at your option) any later version. See the file
Chris@320 13 COPYING included with this distribution for more information.
Chris@320 14 */
Chris@320 15
Chris@329 16 #ifndef _TRANSFORMER_H_
Chris@329 17 #define _TRANSFORMER_H_
Chris@320 18
Chris@320 19 #include "base/Thread.h"
Chris@320 20
Chris@320 21 #include "data/model/Model.h"
Chris@320 22
Chris@350 23 #include "Transform.h"
Chris@350 24
Chris@320 25 /**
Chris@331 26 * A ModelTransformer turns one data model into another.
Chris@320 27 *
Chris@331 28 * Typically in this application, a ModelTransformer might have a
Chris@320 29 * DenseTimeValueModel as its input (e.g. an audio waveform) and a
Chris@320 30 * SparseOneDimensionalModel (e.g. detected beats) as its output.
Chris@320 31 *
Chris@331 32 * The ModelTransformer typically runs in the background, as a
Chris@331 33 * separate thread populating the output model. The model is
Chris@331 34 * available to the user of the ModelTransformer immediately, but may
Chris@331 35 * be initially empty until the background thread has populated it.
Chris@320 36 */
Chris@320 37
Chris@331 38 class ModelTransformer : public Thread
Chris@320 39 {
Chris@320 40 public:
Chris@331 41 virtual ~ModelTransformer();
Chris@320 42
Chris@849 43 typedef std::vector<Model *> Models;
Chris@849 44
Chris@350 45 class Input {
Chris@350 46 public:
Chris@350 47 Input(Model *m) : m_model(m), m_channel(-1) { }
Chris@350 48 Input(Model *m, int c) : m_model(m), m_channel(c) { }
Chris@350 49
Chris@350 50 Model *getModel() const { return m_model; }
Chris@350 51 void setModel(Model *m) { m_model = m; }
Chris@350 52
Chris@350 53 int getChannel() const { return m_channel; }
Chris@350 54 void setChannel(int c) { m_channel = c; }
Chris@350 55
Chris@350 56 protected:
Chris@350 57 Model *m_model;
Chris@350 58 int m_channel;
Chris@350 59 };
Chris@350 60
Chris@361 61 /**
Chris@361 62 * Hint to the processing thread that it should give up, for
Chris@361 63 * example because the process is going to exit or we want to get
Chris@361 64 * rid of the input model. Caller should still wait() and/or
Chris@361 65 * delete the transform before assuming its input and output
Chris@361 66 * models are no longer required.
Chris@361 67 */
Chris@320 68 void abandon() { m_abandoned = true; }
Chris@320 69
Chris@361 70 /**
Chris@1079 71 * Return true if the processing thread is being or has been
Chris@1079 72 * abandoned, i.e. if abandon() has been called.
Chris@1079 73 */
Chris@1079 74 bool isAbandoned() const { return m_abandoned; }
Chris@1079 75
Chris@1079 76 /**
Chris@361 77 * Return the input model for the transform.
Chris@361 78 */
Chris@350 79 Model *getInputModel() { return m_input.getModel(); }
Chris@361 80
Chris@361 81 /**
Chris@361 82 * Return the input channel spec for the transform.
Chris@361 83 */
Chris@350 84 int getInputChannel() { return m_input.getChannel(); }
Chris@350 85
Chris@361 86 /**
Chris@849 87 * Return the set of output models created by the transform or
Chris@849 88 * transforms. Returns an empty list if any transform could not
Chris@849 89 * be initialised; an error message may be available via
Chris@849 90 * getMessage() in this situation.
Chris@361 91 */
Chris@1211 92 Models getOutputModels() {
Chris@1211 93 awaitOutputModels();
Chris@1211 94 return m_outputs;
Chris@1211 95 }
Chris@361 96
Chris@361 97 /**
Chris@849 98 * Return the set of output models, also detaching them from the
Chris@849 99 * transformer so that they will not be deleted when the
Chris@849 100 * transformer is. The caller takes ownership of the models.
Chris@361 101 */
Chris@1211 102 Models detachOutputModels() {
Chris@1211 103 awaitOutputModels();
Chris@877 104 m_detached = true;
Chris@1211 105 return m_outputs;
Chris@877 106 }
Chris@877 107
Chris@877 108 /**
Chris@877 109 * Return any additional models that were created during
Chris@877 110 * processing. This might happen if, for example, a transform was
Chris@877 111 * configured to split a multi-bin output into separate single-bin
Chris@877 112 * models as it processed. These should not be queried until after
Chris@877 113 * the transform has completed.
Chris@877 114 */
Chris@877 115 virtual Models getAdditionalOutputModels() { return Models(); }
Chris@877 116
Chris@877 117 /**
Chris@877 118 * Return true if the current transform is one that may produce
Chris@877 119 * additional models (to be retrieved through
Chris@877 120 * getAdditionalOutputModels above).
Chris@877 121 */
Chris@877 122 virtual bool willHaveAdditionalOutputModels() { return false; }
Chris@877 123
Chris@877 124 /**
Chris@877 125 * Return the set of additional models, also detaching them from
Chris@877 126 * the transformer. The caller takes ownership of the models.
Chris@877 127 */
Chris@877 128 virtual Models detachAdditionalOutputModels() {
Chris@877 129 m_detachedAdd = true;
Chris@877 130 return getAdditionalOutputModels();
Chris@877 131 }
Chris@320 132
Chris@361 133 /**
Chris@361 134 * Return a warning or error message. If getOutputModel returned
Chris@361 135 * a null pointer, this should contain a fatal error message for
Chris@361 136 * the transformer; otherwise it may contain a warning to show to
Chris@361 137 * the user about e.g. suboptimal block size or whatever.
Chris@361 138 */
Chris@361 139 QString getMessage() const { return m_message; }
Chris@361 140
Chris@320 141 protected:
Chris@350 142 ModelTransformer(Input input, const Transform &transform);
Chris@849 143 ModelTransformer(Input input, const Transforms &transforms);
Chris@320 144
Chris@1211 145 virtual void awaitOutputModels() = 0;
Chris@1211 146
Chris@849 147 Transforms m_transforms;
Chris@350 148 Input m_input; // I don't own the model in this
Chris@849 149 Models m_outputs; // I own this, unless...
Chris@320 150 bool m_detached; // ... this is true.
Chris@877 151 bool m_detachedAdd;
Chris@320 152 bool m_abandoned;
Chris@361 153 QString m_message;
Chris@320 154 };
Chris@320 155
Chris@320 156 #endif