Jamoma API  0.6.0.a19
TTOutput.cpp
Go to the documentation of this file.
1 /** @file
2  *
3  * @ingroup modularLibrary
4  *
5  * @brief Handles any signal output
6  *
7  * @details
8  *
9  * @authors Théo de la Hogue
10  *
11  * @copyright © 2010, Théo de la Hogue @n
12  * This code is licensed under the terms of the "New BSD License" @n
13  * http://creativecommons.org/licenses/BSD/
14  */
15 
16 
17 #include "TTOutput.h"
18 
19 #define thisTTClass TTOutput
20 #define thisTTClassName "Output"
21 #define thisTTClassTags "output"
22 
23 TT_MODULAR_CONSTRUCTOR,
24 mType(kTTSymEmpty),
25 mInputAddress(kTTAdrsEmpty),
26 mMute(NO),
27 mMix(100.),
28 mGain(100.),
29 mFreeze(NO),
30 mSignalAttr(NULL)
31 {
32  if (arguments.size() > 0)
33  mReturnSignalCallback = arguments[0];
34 
36 
37  addAttributeWithSetter(InputAddress, kTypeSymbol);
38  addAttributeProperty(InputAddress, hidden, YES);
39 
43  addAttribute(Freeze, kTypeBoolean);
44 
46  addAttributeProperty(Signal, hidden, YES);
47  addAttributeProperty(Signal, readOnly, YES);
48 
50  addMessageProperty(Send, hidden, YES);
51 
52  addMessageWithArguments(SendBypassed);
53  addMessageProperty(SendBypassed, hidden, YES);
54 
56  addMessageProperty(Link, hidden, YES);
57 
58  addMessage(Unlink);
59  addMessageProperty(Unlink, hidden, YES);
60 
61  // only needed because, for Max, the configuration file tells to convert 'mix' into 'Mix')
63  addMessageProperty(Mix, hidden, YES);
64 
65  mLast.clear();
66 
67  this->findAttribute(TTSymbol("signal"), &mSignalAttr);
68 }
69 
70 TTOutput::~TTOutput()
71 {
72  if (mInputAddress != kTTSymEmpty)
73  accessApplicationLocalDirectory->removeObserverForNotifications(mInputAddress, mAddressObserver);
74 }
75 
76 TTErr TTOutput::Send(const TTValue& inputValue, TTValue& outputValue)
77 {
78  TTErr err;
79  TTValue none;
80 
81  if (!mReturnSignalCallback.valid())
82  return kTTErrGeneric;
83 
84  if (mMute)
85  err = kTTErrNone;
86 
87  else if (mFreeze) {
88 
89  err = mReturnSignalCallback.send("notify", mLast);
90 
91  notifySignalObserver(mLast);
92  }
93  else {
94 
95  err = mReturnSignalCallback.send("notify", inputValue);
96 
97  notifySignalObserver(inputValue);
98  }
99 
100  // copy
101  if (!mFreeze)
102  mLast = inputValue;
103 
104  return err;
105 }
106 
107 TTErr TTOutput::SendBypassed(const TTValue& inputValue, TTValue& outputValue)
108 {
109  TTValue dummy;
110  return Send(inputValue, dummy);
111 }
112 
113 TTErr TTOutput::Link(const TTValue& inputValue, TTValue& outputValue)
114 {
115  TTValue none;
116 
117  mInputObject = inputValue[0];
118  return kTTErrNone;
119 }
120 
121 TTErr TTOutput::Unlink()
122 {
123  TTValue none;
124 
125  mInputObject = TTObject();
126  return kTTErrNone;
127 }
128 
129 TTErr TTOutput::setInputAddress(const TTValue& value)
130 {
131  TTValue args;
132  TTAddress newAddress;
133  TTNodePtr aNode;
134  TTObject o;
135  TTValue none, n = value; // use new value to protect the attribute
136 
137  newAddress = value[0];
138 
139  if (newAddress == kTTAdrsEmpty) {
140 
141  mAddressObserver.set(kTTSym_address, kTTAdrsEmpty);
142  mAddressObserver = TTObject();
143  return kTTErrGeneric;
144  }
145 
146  if (!accessApplicationLocalDirectory->getTTNode(newAddress, &aNode)) {
147 
148  o = aNode->getObject();
149  if (o.valid())
150  if (o.name() == kTTSym_Input|| o.name() == kTTSym_InputAudio)
151  Link(o, none);
152  }
153 
154  // create receiver if needed
155  if (!mAddressObserver.valid()) {
156 
157  // prepare arguments
158  mAddressObserver = TTObject("callback");
159 
160  mAddressObserver.set(kTTSym_baton, TTPtr(this)); // théo -- we have to register our self as a #TTPtr to not reference this instance otherwhise the destructor will never be called
161  mAddressObserver.set(kTTSym_function, TTPtr(&TTOutputDirectoryCallback));
162  }
163 
164  // update directory observation
165  if (mInputAddress != kTTAdrsEmpty)
166  accessApplicationLocalDirectory->removeObserverForNotifications(mInputAddress, mAddressObserver);
167 
168  accessApplicationLocalDirectory->addObserverForNotifications(newAddress, mAddressObserver, 0); // ask for notification only for equal addresses
169 
170  mInputAddress = newAddress;
171 
172  return kTTErrNone;
173 }
174 
175 TTErr TTOutput::setMute(const TTValue& value)
176 {
177  mMute = value;
178 
179  if (mGainUnit.valid()) {
180 
181  if (mMute)
182  return mGainUnit.set("linearGain", 0.0);
183  else
184  return mGainUnit.set("midiGain", mGain);
185  }
186  else
187  return kTTErrGeneric;
188 }
189 
190 TTErr TTOutput::setMix(const TTValue& value)
191 {
192  mMix = value;
193 
194  return mMixUnit.set("position", mMix * 0.01);
195 }
196 
197 TTErr TTOutput::Mix(const TTValue& inputValue, TTValue& outputValue)
198 {
199  return setMix(inputValue);
200 }
201 
202 TTErr TTOutput::setGain(const TTValue& value)
203 {
204  mGain = value;
205 
206  if (mGainUnit.valid())
207  return mGainUnit.set("midiGain", mGain);
208  else
209  return kTTErrGeneric;
210 }
211 
212 TTErr TTOutput::notifySignalObserver(const TTValue& value)
213 {
214  mSignal = value;
215 
216  mSignalAttr->sendNotification(kTTSym_notify, mSignal); // we use kTTSym_notify because we know that observers are TTCallback
217 
218  return kTTErrNone;
219 }
220 
221 #if 0
222 #pragma mark -
223 #pragma mark Some Methods
224 #endif
225 
226 TTErr TTOutputDirectoryCallback(const TTValue& baton, const TTValue& data)
227 {
228  TTObject o;
229  TTOutputPtr anOutput;
230  TTSymbol anAddress;
231  TTNodePtr aNode;
232  TTUInt8 flag;
233  TTValue none;
234 
235  // unpack baton (a #TTOutputPtr)
236  anOutput = TTOutputPtr((TTPtr)baton[0]); // théo -- we have to register our self as a #TTPtr to not reference this instance otherwhise the destructor will never be called
237 
238  // Unpack data (anAddress, aNode, flag, anObserver)
239  anAddress = data[0];
240  aNode = TTNodePtr((TTPtr)data[1]);
241  flag = data[2];
242 
243  o = aNode->getObject();
244  if (o.valid()) {
245  if (o.name() == kTTSym_Input || o.name() == kTTSym_InputAudio) {
246 
247  switch (flag) {
248 
249  case kAddressCreated :
250  {
251  anOutput->Link(o, none);
252  break;
253  }
254 
255  case kAddressDestroyed :
256  {
257  anOutput->Unlink();
258  break;
259  }
260 
261  default:
262  break;
263  }
264  }
265  }
266 
267  return kTTErrNone;
268 }
this flag means that a TTNode have been destroyed in the tree structure
Definition: TTAddressBase.h:56
#define addAttribute(name, type)
A convenience macro to be used by subclasses for registering attributes with a custom getter...
Definition: TTAttribute.h:29
We build a directory of TTNodes, and you can request a pointer for any TTNode, or add an observer to ...
Definition: TTNode.h:59
The TTAddress class is used to represent a string and efficiently pass and compare that string...
Definition: TTAddress.h:29
Create and use Jamoma object instances.
Definition: TTObject.h:29
TTObject & getObject()
Get the object binded by this node.
Definition: TTNode.cpp:468
Symbol type.
Definition: TTBase.h:282
This is a special type used by TTAttribute to indicate that a value is a TTValue and is locally maint...
Definition: TTBase.h:286
void * TTPtr
A generic pointer.
Definition: TTBase.h:248
64-bit floating point
Definition: TTBase.h:272
TTSymbol name() const
Return the name of this class.
Definition: TTObject.cpp:129
#define addAttributeProperty(attributeName, propertyName, initialValue)
A convenience macro to be used for registering properties of attributes.
Definition: TTAttribute.h:68
The TTSymbol class is used to represent a string and efficiently pass and compare that string...
Definition: TTSymbol.h:26
Boolean (1/0) or (true/false) flag.
Definition: TTBase.h:281
#define addMessageWithArguments(name)
A convenience macro to be used by subclasses for registering messages.
Definition: TTMessage.h:27
void set(const TTUInt16 index, const T &anElementValue)
DEPRECATED.
Definition: TTValue.h:569
Something went wrong, but what exactly is not known. Typically used for context-specific problems...
Definition: TTBase.h:344
TTErr
Jamoma Error Codes Enumeration of error codes that might be returned by any of the TTBlue functions a...
Definition: TTBase.h:342
this flag means that a TTNode have been created in the tree structure
Definition: TTAddressBase.h:57
#define addAttributeWithSetter(name, type)
A convenience macro to be used by subclasses for registering attributes with a custom setter...
Definition: TTAttribute.h:47
#define addMessage(name)
A convenience macro to be used by subclasses for registering messages.
Definition: TTMessage.h:19
Handles any signal output.
No Error.
Definition: TTBase.h:343
TTErr TTOutputDirectoryCallback(const TTValue &baton, const TTValue &data)
Definition: TTOutput.cpp:226
TTBoolean valid() const
Determine if the object contained by this TTObject is truly ready for use.
Definition: TTObject.cpp:179
#define accessApplicationLocalDirectory
Access to the local application directory.
[doxygenAppendixC_copyExample]
Definition: TTValue.h:34
unsigned char TTUInt8
8 bit unsigned integer (char)
Definition: TTBase.h:174
#define addMessageProperty(messageName, propertyName, initialValue)
A convenience macro to be used for registering properties of messages.
Definition: TTMessage.h:37