1
/************************************************************************
2
DSPatch - Cross-Platform, Object-Oriented, Flow-Based Programming Library
3
Copyright (c) 2012-2015 Marcus Tomlinson
5
This file is part of DSPatch.
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.
16
Alternatively, this file may be used in accordance with the terms and
17
conditions contained in a signed written agreement between you and
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
************************************************************************/
25
#ifndef DSPCOMPONENT_H
26
#define DSPCOMPONENT_H
28
//-------------------------------------------------------------------------------------------------
30
#include <dspatch/DspSignalBus.h>
31
#include <dspatch/DspWireBus.h>
32
#include <dspatch/DspComponentThread.h>
33
#include <dspatch/DspParameter.h>
37
//=================================================================================================
38
/// Abstract base class for all DSPatch components
41
Classes derived from DspComponent can be added to a DspCircuit and routed to and from other
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_()
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).
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.
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).
76
class DLLEXPORT DspComponent
89
typedef void (*Callback_t)(DspComponent* component, CallbackType const& callbackType, int index, void* userData);
92
virtual ~DspComponent();
94
void SetCallback(Callback_t const& callback, void* userData = NULL);
96
void SetComponentName(std::string const& componentName);
97
std::string GetComponentName() const;
99
template <class FromOutputId, class ToInputId>
100
bool ConnectInput(DspComponent* fromComponent, FromOutputId const& fromOutput, ToInputId const& toInput);
102
template <class FromOutputId, class ToInputId>
103
bool ConnectInput(DspComponent& fromComponent, FromOutputId const& fromOutput, ToInputId const& toInput);
105
template <class FromOutputId, class ToInputId>
106
void DisconnectInput(DspComponent const* fromComponent, FromOutputId const& fromOutput, ToInputId const& toInput);
108
template <class FromOutputId, class ToInputId>
109
void DisconnectInput(DspComponent const& fromComponent, FromOutputId const& fromOutput, ToInputId const& toInput);
111
void DisconnectInput(int inputIndex);
112
void DisconnectInput(std::string const& inputName);
113
void DisconnectInput(DspComponent const* inputComponent);
114
void DisconnectAllInputs();
117
int GetOutputCount();
118
int GetParameterCount();
120
std::string GetInputName(int index);
121
std::string GetOutputName(int index);
122
std::string GetParameterName(int index);
124
bool GetParameter(int index, DspParameter& param);
125
DspParameter const* GetParameter(int index);
126
bool SetParameter(int index, DspParameter const& param);
131
void StartAutoTick();
133
void PauseAutoTick();
134
void ResumeAutoTick();
137
virtual void Process_(DspSignalBus&, DspSignalBus&);
138
virtual bool ParameterUpdating_(int, DspParameter const&);
140
bool AddInput_(std::string const& inputName = "");
141
bool AddOutput_(std::string const& outputName = "");
142
int AddParameter_(std::string const& paramName, DspParameter const& param);
145
bool RemoveOutput_();
146
bool RemoveParameter_();
148
void RemoveAllInputs_();
149
void RemoveAllOutputs_();
150
void RemoveAllParameters_();
152
int GetInputCount_();
153
int GetOutputCount_();
154
int GetParameterCount_();
156
DspParameter const* GetParameter_(int index) const;
157
bool SetParameter_(int index, DspParameter const& param);
160
virtual void _PauseAutoTick();
162
void _SetParentCircuit(DspCircuit* parentCircuit);
163
DspCircuit* _GetParentCircuit();
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;
170
void _SetBufferCount(int bufferCount);
171
int _GetBufferCount() const;
173
void _ThreadTick(int threadNo);
174
void _ThreadReset(int threadNo);
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);
181
void _WaitForRelease(int threadNo);
182
void _ReleaseThread(int threadNo);
185
friend class DspCircuit;
186
friend class DspCircuitThread;
188
DspCircuit* _parentCircuit;
192
DspSignalBus _inputBus;
193
DspSignalBus _outputBus;
195
std::vector<DspSignalBus> _inputBuses;
196
std::vector<DspSignalBus> _outputBuses;
198
std::vector< std::pair<std::string, DspParameter> > _parameters;
200
std::string _componentName;
201
bool _isAutoTickRunning;
202
bool _isAutoTickPaused;
205
DspWireBus _inputWires;
209
DspComponentThread _componentThread;
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;
216
Callback_t _callback;
220
//=================================================================================================
222
template <class FromOutputId, class ToInputId>
223
bool DspComponent::ConnectInput(DspComponent* fromComponent, FromOutputId const& fromOutput, ToInputId const& toInput)
228
if (!fromComponent->_outputBus.FindSignal(fromOutput, fromOutputIndex) ||
229
!_inputBus.FindSignal(toInput, toInputIndex))
235
_inputWires.AddWire(fromComponent, fromOutputIndex, toInputIndex);
241
//-------------------------------------------------------------------------------------------------
243
template <class FromOutputId, class ToInputId>
244
bool DspComponent::ConnectInput(DspComponent& fromComponent, FromOutputId const& fromOutput, ToInputId const& toInput)
246
return ConnectInput(&fromComponent, fromOutput, toInput);
249
//-------------------------------------------------------------------------------------------------
251
template <class FromOutputId, class ToInputId>
252
void DspComponent::DisconnectInput(DspComponent const* fromComponent,
253
FromOutputId const& fromOutput,
254
ToInputId const& toInput)
259
if (!fromComponent->_outputBus.FindSignal(fromOutput, fromOutputIndex) ||
260
!_inputBus.FindSignal(toInput, toInputIndex))
266
_inputWires.RemoveWire(fromComponent, fromOutputIndex, toInputIndex);
270
//-------------------------------------------------------------------------------------------------
272
template <class FromOutputId, class ToInputId>
273
void DspComponent::DisconnectInput(DspComponent const& fromComponent,
274
FromOutputId const& fromOutput,
275
ToInputId const& toInput)
277
DisconnectInput(&fromComponent, fromOutput, toInput);
280
//=================================================================================================
282
#endif // DSPCOMPONENT_H