~marcustomlinson/dspatchables/trunk

« back to all changes in this revision

Viewing changes to include/dspatch/DspComponent.h

  • Committer: Marcus Tomlinson
  • Date: 2015-04-05 22:25:24 UTC
  • mfrom: (1.1.10 trunk)
  • Revision ID: marcus.tomlinson@canonical.com-20150405222524-urntp725s5hbk2im
Merged add_basic_components

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/************************************************************************
 
2
DSPatch - Cross-Platform, Object-Oriented, Flow-Based Programming Library
 
3
Copyright (c) 2012-2015 Marcus Tomlinson
 
4
 
 
5
This file is part of DSPatch.
 
6
 
 
7
GNU Lesser General Public License Usage
 
8
This file may be used under the terms of the GNU Lesser General Public
 
9
License version 3.0 as published by the Free Software Foundation and
 
10
appearing in the file LGPLv3.txt included in the packaging of this
 
11
file. Please review the following information to ensure the GNU Lesser
 
12
General Public License version 3.0 requirements will be met:
 
13
http://www.gnu.org/copyleft/lgpl.html.
 
14
 
 
15
Other Usage
 
16
Alternatively, this file may be used in accordance with the terms and
 
17
conditions contained in a signed written agreement between you and
 
18
Marcus Tomlinson.
 
19
 
 
20
DSPatch is distributed in the hope that it will be useful,
 
21
but WITHOUT ANY WARRANTY; without even the implied warranty of
 
22
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 
23
************************************************************************/
 
24
 
 
25
#ifndef DSPCOMPONENT_H
 
26
#define DSPCOMPONENT_H
 
27
 
 
28
//-------------------------------------------------------------------------------------------------
 
29
 
 
30
#include <dspatch/DspSignalBus.h>
 
31
#include <dspatch/DspWireBus.h>
 
32
#include <dspatch/DspComponentThread.h>
 
33
#include <dspatch/DspParameter.h>
 
34
 
 
35
class DspCircuit;
 
36
 
 
37
//=================================================================================================
 
38
/// Abstract base class for all DSPatch components
 
39
 
 
40
/**
 
41
Classes derived from DspComponent can be added to a DspCircuit and routed to and from other
 
42
DspComponents.
 
43
 
 
44
On construction, derived classes must configure the component's IO buses by calling AddInput_() and
 
45
AddOutput_() respectively, as well as populate the component's parameter map via AddParameter_()
 
46
(see DspParameter).
 
47
 
 
48
Derived classes must also implement the virtual method: Process_(). The Process_() method is a
 
49
callback from the DSPatch engine that occurs when a new set of input signals is ready for
 
50
processing. The Process_() method has 2 arguments: the input bus, and the output bus. This
 
51
method's purpose is to pull its required inputs out of the input bus, process these inputs, and
 
52
populate the output bus with the results (see DspSignalBus).
 
53
 
 
54
Derived classes that expose parameters will also need to implement the virtual ParameterUpdating_()
 
55
method. The ParameterUpdating_() method is a callback from the DSPatch engine that occurs when an
 
56
update to a component parameter has been requested via the public SetParameter() method.
 
57
ParameterUpdating_() has 2 arguments: the parameter name, and the new parameter value to be set.
 
58
This method's purpose is to: 1. validate that the new value is legal, 2. make the necessary
 
59
internal changes associated with that parameter change, and 3. update the target parameter itself
 
60
by calling the protected SetParameter_() method. If the new parameter value is legal and the update
 
61
was successful, ParameterUpdating_() should return true, otherwise, it should return false.
 
62
 
 
63
In order for a component to do any work it must be ticked over. This is performed by repeatedly
 
64
calling the Tick() and Reset() methods. The Tick() method is responsible for acquiring the next set
 
65
of input signals from component input wires and populating the component's input bus. To insure
 
66
that these inputs are up-to-date, the dependent component first calls all of its input components'
 
67
Tick() methods -hence recursively called in all components going backward through the circuit (This
 
68
is what's classified as a "pull system"). The acquired input bus is then passed to the Process_()
 
69
method. The Reset() method then informs the component that the last circuit traversal has completed
 
70
and hence can execute the next Tick() request. A component's Tick() and Reset() methods can be
 
71
called in a loop from the main application thread, or alternatively, by calling StartAutoTick(), a
 
72
separate thread will spawn, automatically calling Tick() and Reset() methods continuously (This is
 
73
most commonly used to tick over an instance of DspCircuit).
 
74
*/
 
75
 
 
76
class DLLEXPORT DspComponent
 
77
{
 
78
public:
 
79
    enum CallbackType
 
80
    {
 
81
        InputAdded,
 
82
        InputRemoved,
 
83
        OutputAdded,
 
84
        OutputRemoved,
 
85
        ParameterAdded,
 
86
        ParameterRemoved,
 
87
        ParameterUpdated
 
88
    };
 
89
    typedef void (*Callback_t)(DspComponent* component, CallbackType const& callbackType, int index, void* userData);
 
90
 
 
91
    DspComponent();
 
92
    virtual ~DspComponent();
 
93
 
 
94
    void SetCallback(Callback_t const& callback, void* userData = NULL);
 
95
 
 
96
    void SetComponentName(std::string const& componentName);
 
97
    std::string GetComponentName() const;
 
98
 
 
99
    template <class FromOutputId, class ToInputId>
 
100
    bool ConnectInput(DspComponent* fromComponent, FromOutputId const& fromOutput, ToInputId const& toInput);
 
101
 
 
102
    template <class FromOutputId, class ToInputId>
 
103
    bool ConnectInput(DspComponent& fromComponent, FromOutputId const& fromOutput, ToInputId const& toInput);
 
104
 
 
105
    template <class FromOutputId, class ToInputId>
 
106
    void DisconnectInput(DspComponent const* fromComponent, FromOutputId const& fromOutput, ToInputId const& toInput);
 
107
 
 
108
    template <class FromOutputId, class ToInputId>
 
109
    void DisconnectInput(DspComponent const& fromComponent, FromOutputId const& fromOutput, ToInputId const& toInput);
 
110
 
 
111
    void DisconnectInput(int inputIndex);
 
112
    void DisconnectInput(std::string const& inputName);
 
113
    void DisconnectInput(DspComponent const* inputComponent);
 
114
    void DisconnectAllInputs();
 
115
 
 
116
    int GetInputCount();
 
117
    int GetOutputCount();
 
118
    int GetParameterCount();
 
119
 
 
120
    std::string GetInputName(int index);
 
121
    std::string GetOutputName(int index);
 
122
    std::string GetParameterName(int index);
 
123
 
 
124
    bool GetParameter(int index, DspParameter& param);
 
125
    DspParameter const* GetParameter(int index);
 
126
    bool SetParameter(int index, DspParameter const& param);
 
127
 
 
128
    void Tick();
 
129
    void Reset();
 
130
 
 
131
    void StartAutoTick();
 
132
    void StopAutoTick();
 
133
    void PauseAutoTick();
 
134
    void ResumeAutoTick();
 
135
 
 
136
protected:
 
137
    virtual void Process_(DspSignalBus&, DspSignalBus&);
 
138
    virtual bool ParameterUpdating_(int, DspParameter const&);
 
139
 
 
140
    bool AddInput_(std::string const& inputName = "");
 
141
    bool AddOutput_(std::string const& outputName = "");
 
142
    int AddParameter_(std::string const& paramName, DspParameter const& param);
 
143
 
 
144
    bool RemoveInput_();
 
145
    bool RemoveOutput_();
 
146
    bool RemoveParameter_();
 
147
 
 
148
    void RemoveAllInputs_();
 
149
    void RemoveAllOutputs_();
 
150
    void RemoveAllParameters_();
 
151
 
 
152
    int GetInputCount_();
 
153
    int GetOutputCount_();
 
154
    int GetParameterCount_();
 
155
 
 
156
    DspParameter const* GetParameter_(int index) const;
 
157
    bool SetParameter_(int index, DspParameter const& param);
 
158
 
 
159
private:
 
160
    virtual void _PauseAutoTick();
 
161
 
 
162
    void _SetParentCircuit(DspCircuit* parentCircuit);
 
163
    DspCircuit* _GetParentCircuit();
 
164
 
 
165
    bool _FindInput(std::string const& signalName, int& returnIndex) const;
 
166
    bool _FindInput(int signalIndex, int& returnIndex) const;
 
167
    bool _FindOutput(std::string const& signalName, int& returnIndex) const;
 
168
    bool _FindOutput(int signalIndex, int& returnIndex) const;
 
169
 
 
170
    void _SetBufferCount(int bufferCount);
 
171
    int _GetBufferCount() const;
 
172
 
 
173
    void _ThreadTick(int threadNo);
 
174
    void _ThreadReset(int threadNo);
 
175
 
 
176
    bool _SetInputSignal(int inputIndex, DspSignal const* newSignal);
 
177
    bool _SetInputSignal(int inputIndex, int threadIndex, DspSignal const* newSignal);
 
178
    DspSignal* _GetOutputSignal(int outputIndex);
 
179
    DspSignal* _GetOutputSignal(int outputIndex, int threadIndex);
 
180
 
 
181
    void _WaitForRelease(int threadNo);
 
182
    void _ReleaseThread(int threadNo);
 
183
 
 
184
private:
 
185
    friend class DspCircuit;
 
186
    friend class DspCircuitThread;
 
187
 
 
188
    DspCircuit* _parentCircuit;
 
189
 
 
190
    int _bufferCount;
 
191
 
 
192
    DspSignalBus _inputBus;
 
193
    DspSignalBus _outputBus;
 
194
 
 
195
    std::vector<DspSignalBus> _inputBuses;
 
196
    std::vector<DspSignalBus> _outputBuses;
 
197
 
 
198
    std::vector< std::pair<std::string, DspParameter> > _parameters;
 
199
 
 
200
    std::string _componentName;
 
201
    bool _isAutoTickRunning;
 
202
    bool _isAutoTickPaused;
 
203
    int _pauseCount;
 
204
 
 
205
    DspWireBus _inputWires;
 
206
 
 
207
    bool _hasTicked;
 
208
 
 
209
    DspComponentThread _componentThread;
 
210
 
 
211
    std::vector<bool*> _hasTickeds;  // bool pointers ensure that parallel threads will only read from this vector
 
212
    std::vector<bool> _gotReleases;  // bool pointers not used here as only 1 thread writes to this vector at a time
 
213
    std::vector<DspMutex> _releaseMutexes;
 
214
    std::vector<DspWaitCondition> _releaseCondts;
 
215
 
 
216
    Callback_t _callback;
 
217
    void* _userData;
 
218
};
 
219
 
 
220
//=================================================================================================
 
221
 
 
222
template <class FromOutputId, class ToInputId>
 
223
bool DspComponent::ConnectInput(DspComponent* fromComponent, FromOutputId const& fromOutput, ToInputId const& toInput)
 
224
{
 
225
    int fromOutputIndex;
 
226
    int toInputIndex;
 
227
 
 
228
    if (!fromComponent->_outputBus.FindSignal(fromOutput, fromOutputIndex) ||
 
229
        !_inputBus.FindSignal(toInput, toInputIndex))
 
230
    {
 
231
        return false;
 
232
    }
 
233
 
 
234
    PauseAutoTick();
 
235
    _inputWires.AddWire(fromComponent, fromOutputIndex, toInputIndex);
 
236
    ResumeAutoTick();
 
237
 
 
238
    return true;
 
239
}
 
240
 
 
241
//-------------------------------------------------------------------------------------------------
 
242
 
 
243
template <class FromOutputId, class ToInputId>
 
244
bool DspComponent::ConnectInput(DspComponent& fromComponent, FromOutputId const& fromOutput, ToInputId const& toInput)
 
245
{
 
246
    return ConnectInput(&fromComponent, fromOutput, toInput);
 
247
}
 
248
 
 
249
//-------------------------------------------------------------------------------------------------
 
250
 
 
251
template <class FromOutputId, class ToInputId>
 
252
void DspComponent::DisconnectInput(DspComponent const* fromComponent,
 
253
                                   FromOutputId const& fromOutput,
 
254
                                   ToInputId const& toInput)
 
255
{
 
256
    int fromOutputIndex;
 
257
    int toInputIndex;
 
258
 
 
259
    if (!fromComponent->_outputBus.FindSignal(fromOutput, fromOutputIndex) ||
 
260
        !_inputBus.FindSignal(toInput, toInputIndex))
 
261
    {
 
262
        return;
 
263
    }
 
264
 
 
265
    PauseAutoTick();
 
266
    _inputWires.RemoveWire(fromComponent, fromOutputIndex, toInputIndex);
 
267
    ResumeAutoTick();
 
268
}
 
269
 
 
270
//-------------------------------------------------------------------------------------------------
 
271
 
 
272
template <class FromOutputId, class ToInputId>
 
273
void DspComponent::DisconnectInput(DspComponent const& fromComponent,
 
274
                                   FromOutputId const& fromOutput,
 
275
                                   ToInputId const& toInput)
 
276
{
 
277
    DisconnectInput(&fromComponent, fromOutput, toInput);
 
278
}
 
279
 
 
280
//=================================================================================================
 
281
 
 
282
#endif  // DSPCOMPONENT_H