Jamoma API  0.6.0.a19
AUDebugDispatcher.cpp
1 /* Copyright © 2007 Apple Inc. All Rights Reserved.
2 
3  Disclaimer: IMPORTANT: This Apple software is supplied to you by
4  Apple Inc. ("Apple") in consideration of your agreement to the
5  following terms, and your use, installation, modification or
6  redistribution of this Apple software constitutes acceptance of these
7  terms. If you do not agree with these terms, please do not use,
8  install, modify or redistribute this Apple software.
9 
10  In consideration of your agreement to abide by the following terms, and
11  subject to these terms, Apple grants you a personal, non-exclusive
12  license, under Apple's copyrights in this original Apple software (the
13  "Apple Software"), to use, reproduce, modify and redistribute the Apple
14  Software, with or without modifications, in source and/or binary forms;
15  provided that if you redistribute the Apple Software in its entirety and
16  without modifications, you must retain this notice and the following
17  text and disclaimers in all such redistributions of the Apple Software.
18  Neither the name, trademarks, service marks or logos of Apple Inc.
19  may be used to endorse or promote products derived from the Apple
20  Software without specific prior written permission from Apple. Except
21  as expressly stated in this notice, no other rights or licenses, express
22  or implied, are granted by Apple herein, including but not limited to
23  any patent rights that may be infringed by your derivative works or by
24  other works in which the Apple Software may be incorporated.
25 
26  The Apple Software is provided by Apple on an "AS IS" basis. APPLE
27  MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
28  THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
29  FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
30  OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
31 
32  IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
33  OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
34  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
35  INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
36  MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
37  AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
38  STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
39  POSSIBILITY OF SUCH DAMAGE.
40 */
41 /*=============================================================================
42  * AUDebugDispatcher.h
43  * CAServices
44 
45 =============================================================================*/
46 
47 #if AU_DEBUG_DISPATCHER
48 
49 #warning "This should * * NOT * * be seen on a Release Version"
50 
51 
52 #include "AUDebugDispatcher.h"
53 
54 static char* AUErrorStr (OSStatus result);
55 
56 class AUDD_Locker {
57 public:
58  AUDD_Locker (CAMutex &guard) :mGuard (guard) { didLock = mGuard.Lock(); }
59  ~AUDD_Locker () { if (didLock) mGuard.Unlock(); }
60 
61 private:
62  bool didLock;
63  CAMutex &mGuard;
64 };
65 
66 AUDebugDispatcher::AUDebugDispatcher (AUBase *au, FILE* file)
67  : mAUBase (au),
68  mFile (file),
69  mHaveDoneProperty (false),
70  mPrintMutex ("AU Debug Dispatcher Printer"),
71  mHostCB1_Result (0),
72  mHostCB2_Result (0),
73  mHostCB3_Result (0),
74  mHostCB_WhenToPrint (0),
75  mHostCB_WasPlaying (0)
76 {
77  // lets gather some info about this instance...
78  AudioComponentDescription desc = mAUBase->GetComponentDescription();
79  fprintf (mFile, "\nAUBase=0x%X, Type=%4.4s, SubType=%4.4s, Manu=%4.4s\n\n", AU(),
80  (char*)&desc.componentType,
81  (char*)&desc.componentSubType,
82  (char*)&desc.componentManufacturer);
83  mFirstTime = CAHostTimeBase::GetCurrentTime();
84 }
85 
86 
87 AUDebugDispatcher::~AUDebugDispatcher()
88 {
89  PrintHeaderString (CAHostTimeBase::GetCurrentTime(), (unsigned int)pthread_self(), "Close");
90  fprintf (mFile, "\n");
91 }
92 
93 void AUDebugDispatcher::PrintHeaderString (UInt64 inNowTime, unsigned int inThread, const char* inMethod)
94 {
95  double secsSinceStart = SecsSinceStart(inNowTime);
96  fprintf (mFile, "[AUDisp:AUBase = 0x%X, Time = %.6lf secs, Thread = 0x%X, IsInitialized = '%c'] %s()\n",
97  AU(), secsSinceStart, inThread, (mAUBase->IsInitialized() ? 'T' : 'F'), inMethod);
98 }
99 
100 unsigned int AUDebugDispatcher::RecordDispatch (UInt64 inStartTime, OSStatus result, const char* inMethod)
101 {
102  UInt64 nowTime = CAHostTimeBase::GetCurrentTime();
103 
104  unsigned int theThread = (unsigned int)pthread_self();
105 
106  PrintHeaderString (nowTime, theThread, inMethod);
107 
108  UInt64 nanos = CAHostTimeBase::ConvertToNanos(nowTime - inStartTime);
109 
110  fprintf (mFile, "\t[Time To execute = %.6lf secs", (nanos * 1.0e-9));
111 
112  if (result)
113  fprintf (mFile, ", * * * result = %ld, %s * * * ", result, AUErrorStr(result));
114 
115  fprintf (mFile, "]\n");
116 
117  return theThread;
118 }
119 
120 #pragma mark -
121 #pragma mark __AU Dispatch
122 #pragma mark -
123 
124 void AUDebugDispatcher::Initialize (UInt64 nowTime, OSStatus result)
125 {
126  AUDD_Locker lock (mPrintMutex);
127  RecordDispatch (nowTime, result, "Initialize");
128 }
129 
130 void AUDebugDispatcher::Uninitialize (UInt64 nowTime, OSStatus result)
131 {
132  AUDD_Locker lock (mPrintMutex);
133  RecordDispatch (nowTime, result, "Uninitialize");
134 }
135 
136 void AUDebugDispatcher::GetPropertyInfo (UInt64 nowTime,
137  OSStatus result,
138  AudioUnitPropertyID inID,
139  AudioUnitScope inScope,
140  AudioUnitElement inElement,
141  UInt32 *outDataSize,
142  Boolean *outWritable)
143 {
144  AUDD_Locker lock (mPrintMutex);
145  RecordDispatch (nowTime, result, "GetPropertyInfo");
146  PrintProperty (inID, inScope, inElement);
147 }
148 
149 void AUDebugDispatcher::GetProperty (UInt64 nowTime,
150  OSStatus result,
151  AudioUnitPropertyID inID,
152  AudioUnitScope inScope,
153  AudioUnitElement inElement,
154  UInt32 *ioDataSize,
155  void *outData)
156 {
157  //err -> ioDataSize == NULL or 0
158  //outData == NULL -> Dispatches to GetPropertyInfo
159 
160  // still should log these as calls to GetProperty...
161  AUDD_Locker lock (mPrintMutex);
162  const char *dispStr = outData != NULL ? "GetProperty" : "GetProperty - Info";
163  RecordDispatch (nowTime, result, dispStr);
164  PrintProperty (inID, inScope, inElement);
165 }
166 
167 void AUDebugDispatcher::SetProperty (UInt64 nowTime,
168  OSStatus result,
169  AudioUnitPropertyID inID,
170  AudioUnitScope inScope,
171  AudioUnitElement inElement,
172  const void * inData,
173  UInt32 inDataSize)
174 {
175  // inData could be NULL to remove property value...
176  AUDD_Locker lock (mPrintMutex);
177  RecordDispatch (nowTime, result, "SetProperty");
178  PrintProperty (inID, inScope, inElement);
179 }
180 
181 void AUDebugDispatcher::Render ( UInt64 nowTime,
182  OSStatus result,
183  AudioUnitRenderActionFlags * inRenderFlags,
184  const AudioTimeStamp * inTimeStamp,
185  UInt32 inOutputBusNumber,
186  UInt32 inNumFrames,
187  AudioBufferList * inIOData)
188 {
189  if (mHaveDoneProperty) {
190  AUDD_Locker lock (mPrintMutex);
191  RecordDispatch (nowTime, result, "Render");
192  fprintf (mFile, "\t\t[Sample Time = %.0lf, NumFrames = %ld]\n", inTimeStamp->mSampleTime, inNumFrames);
193  mHaveDoneProperty = false;
194  }
195  RenderActions_HostCallbacks ();
196 }
197 
198 #define kBeginLine " "
199 
200 void AUDebugDispatcher::RenderActions_HostCallbacks ()
201 {
202  bool doPrint = !(mHostCB_WhenToPrint++ % 5000);
203 
204 // (3) Host Transport State callback
205 // - this is printed below, but we use the transStateChange to see if we have something to print
206  Boolean isPlaying, transStateChange, isCycling;
207  Float64 currentSample, cycleStartBeat, cycleEndBeat;
208  OSStatus result = mAUBase->CallHostTransportState (&isPlaying, &transStateChange, &currentSample,
209  &isCycling, &cycleStartBeat, &cycleEndBeat);
210  bool newCB3Result = false;
211  if (result != mHostCB3_Result) {
212  mHostCB3_Result = result;
213  newCB3Result = true;
214  }
215 
216  if (transStateChange) mHostCB_WhenToPrint = 1;
217 
218 // Code to test the Host Callbacks
219  Float64 currentBeat, currentTempo;
220 
221 // (1) Beat and Tempo callback
222  result = mAUBase->CallHostBeatAndTempo (&currentBeat, &currentTempo);
223 
224  if (result) {
225  if (result != mHostCB1_Result) {
226  printf ("_HCback_ Error Calling HostBeatAndTempo:%ld\n", result);
227  mHostCB1_Result = result;
228  }
229  } else {
230  if (doPrint || currentBeat < 0 || transStateChange)
231  printf ("_HCback_ Beat and Tempo: Current Beat:%f, Current Tempo:%f\n", currentBeat, currentTempo);
232  }
233 
234 // (2) Musical Time callback
235  UInt32 deltaSampleOffset, timeSig_Denom;
236  Float32 timeSig_Num;
237  Float64 currentMeasureDownBeat;
238  result = mAUBase->CallHostMusicalTimeLocation (&deltaSampleOffset, &timeSig_Num, &timeSig_Denom, &currentMeasureDownBeat);
239 
240  if (result) {
241  if (result != mHostCB2_Result) {
242  printf ("%sError Calling CallHostMusicalTimeLocation:%ld\n", kBeginLine, result);
243  mHostCB2_Result = result;
244  }
245  } else {
246  if (doPrint || currentMeasureDownBeat < 0 || deltaSampleOffset < 0 || transStateChange) {
247  printf ("%sMusical Time: Delta Sample Offset:%ld, Time Sig:Num:%.1f, Time Sig:Denom:%ld, DownBeat:%f\n",
248  kBeginLine, deltaSampleOffset, timeSig_Num, timeSig_Denom, currentMeasureDownBeat);
249  }
250  }
251 
252  if (mHostCB3_Result) {
253  if (newCB3Result) {
254  printf ("%sError Calling CallHostTransportState:%ld\n", kBeginLine, mHostCB3_Result);
255  }
256  } else {
257  if (doPrint || (mHostCB_WasPlaying != isPlaying) || transStateChange || currentSample < 0)
258  {
259  printf ("%sTransport State: Was Playing:%d, ", kBeginLine, mHostCB_WasPlaying);
260  mHostCB_WasPlaying = isPlaying;
261  printf ("Is Playing:%d, Transport State Changed:%d", isPlaying, transStateChange);
262  if (isPlaying) {
263  printf (", Current Sample:%.1f", currentSample);
264  if (isCycling)
265  printf (", Is Cycling [Start Beat:%.2f, End Beat:%.2f]", cycleStartBeat, cycleEndBeat);
266  }
267  printf ("\n");
268  }
269  }
270 }
271 
272 #pragma mark -
273 #pragma mark __Utilities
274 #pragma mark -
275 
276 static char* AUScopeStr (AudioUnitScope inScope)
277 {
278  switch (inScope) {
279  case kAudioUnitScope_Global: return "Global";
280  case kAudioUnitScope_Output: return "Output";
281  case kAudioUnitScope_Input: return "Input";
282  case kAudioUnitScope_Group: return "Group";
283  }
284  return NULL;
285 }
286 
287 static char* AUErrorStr (OSStatus result)
288 {
289  switch (result) {
290  case kAudioUnitErr_InvalidProperty: return "Invalid Property";
291  case kAudioUnitErr_InvalidParameter: return "Invalid Parameter";
292  case kAudioUnitErr_InvalidElement: return "Invalid Element";
293  case kAudioUnitErr_NoConnection: return "Invalid Connection";
294  case kAudioUnitErr_FailedInitialization: return "Failed Initialization";
295  case kAudioUnitErr_TooManyFramesToProcess: return "Too Many Frames";
296  case kAudioUnitErr_IllegalInstrument: return "Illegal Instrument";
297  case kAudioUnitErr_InstrumentTypeNotFound: return "Instrument Type Not Found";
298  case kAudioUnitErr_InvalidFile: return "Invalid File";
299  case kAudioUnitErr_UnknownFileType: return "Unknown File Type";
300  case kAudioUnitErr_FileNotSpecified: return "File Not Specified";
301  case kAudioUnitErr_FormatNotSupported: return "Format Not Supported";
302  case kAudioUnitErr_Uninitialized: return "Un Initialized";
303  case kAudioUnitErr_InvalidScope: return "Invalid Scope";
304  case kAudioUnitErr_PropertyNotWritable: return "Property Not Writable";
305  case kAudioUnitErr_InvalidPropertyValue: return "Invalid Property Value";
306  case kAudioUnitErr_PropertyNotInUse: return "Property Not In Use";
307  case kAudioUnitErr_Initialized: return "Initialized";
308 
309  // some common system errors
310  case badComponentSelector: return "Bad Component Selector";
311  case paramErr: return "Parameter Error";
312  case badComponentInstance: return "Bad Component Instance";
313  }
314  return "Unknown Error";
315 }
316 
317 static char* AUPropertyStr (AudioUnitPropertyID inID)
318 {
319  switch (inID) {
320  case kAudioUnitProperty_ClassInfo: return "Class Info";
321  case kAudioUnitProperty_MakeConnection: return "Connection";
322  case kAudioUnitProperty_SampleRate: return "Sample Rate";
323  case kAudioUnitProperty_ParameterList: return "Parameter List";
324  case kAudioUnitProperty_ParameterInfo: return "Parameter Info";
325  case kAudioUnitProperty_FastDispatch: return "Fast Dispatch";
326  case kAudioUnitProperty_CPULoad: return "CPU Load";
327  case kAudioUnitProperty_StreamFormat: return "Format";
328  case kAudioUnitProperty_ReverbRoomType: return "Reverb Room Type";
329  case kAudioUnitProperty_ElementCount: return "Element Count";
330  case kAudioUnitProperty_Latency: return "Latency";
331  case kAudioUnitProperty_SupportedNumChannels: return "Supported Num Channels";
332  case kAudioUnitProperty_MaximumFramesPerSlice: return "Max Frames Per Slice";
333  case kAudioUnitProperty_SetExternalBuffer: return "Set External Buffer";
334  case kAudioUnitProperty_ParameterValueStrings: return "Parameter Value Strings";
335  case kAudioUnitProperty_GetUIComponentList: return "Carbon UI";
336  case kAudioUnitProperty_AudioChannelLayout: return "Audio Channel Layout";
337  case kAudioUnitProperty_TailTime: return "Tail Time";
338  case kAudioUnitProperty_BypassEffect: return "Bypass Effect";
339  case kAudioUnitProperty_LastRenderError: return "Last Render Error";
340  case kAudioUnitProperty_SetRenderCallback: return "Render Callback";
341  case kAudioUnitProperty_FactoryPresets: return "Factory Preset";
342  case kAudioUnitProperty_ContextName: return "Context Name";
343  case kAudioUnitProperty_RenderQuality: return "Render Quality";
344  case kAudioUnitProperty_HostCallbacks: return "Host Callbacks";
345  case kAudioUnitProperty_InPlaceProcessing: return "In Place Processing";
346  case kAudioUnitProperty_ElementName: return "Element Name";
347  case kAudioUnitProperty_CocoaUI: return "Cocoa UI";
348  case kAudioUnitProperty_SupportedChannelLayoutTags: return "Supported Channel Layout Tags";
349  case kAudioUnitProperty_ParameterStringFromValue: return "Parameter Value Name";
350  case kAudioUnitProperty_UsesInternalReverb: return "Use Internal Reverb";
351  case kAudioUnitProperty_ParameterIDName: return "Parameter ID Name";
352  case kAudioUnitProperty_ParameterClumpName: return "Clump Name";
353  case kAudioUnitProperty_PresentPreset: return "Present Preset";
354 
355 
356  case kMusicDeviceProperty_InstrumentCount: return "Instrument Count";
357  case kMusicDeviceProperty_InstrumentName: return "Instrument Name";
358  case kMusicDeviceProperty_SoundBankFSRef: return "Sound Bank - File";
359  case kMusicDeviceProperty_InstrumentNumber: return "Instrument Number";
360  case kMusicDeviceProperty_MIDIXMLNames: return "MIDI XML Names";
361  case kMusicDeviceProperty_BankName: return "Bank Name";
362  case kMusicDeviceProperty_SoundBankData: return "Sound Bank - Data";
363 
364 
365  case kAudioOutputUnitProperty_CurrentDevice: return "Current AudioDevice";
366  case kAudioOutputUnitProperty_IsRunning: return "Is Running";
367  case kAudioOutputUnitProperty_ChannelMap: return "Channel Map";
368  case kAudioOutputUnitProperty_EnableIO: return "Enable I/O";
369  case kAudioOutputUnitProperty_StartTime: return "Start Time";
370  case kAudioOutputUnitProperty_SetInputCallback: return "I/O Input Callback";
371  }
372  return "Unknown";
373 }
374 
375 
376 void AUDebugDispatcher::PrintProperty ( AudioUnitPropertyID inID,
377  AudioUnitScope inScope,
378  AudioUnitElement inElement)
379 {
380  char* scopeStr = AUScopeStr(inScope);
381  char* propStr = AUPropertyStr (inID);
382 
383  if (scopeStr != NULL)
384  fprintf (mFile, "\t\t[ID = %ld, %s, Scope = %s, El = %ld]\n", inID, propStr, scopeStr, inElement);
385  else
386  fprintf (mFile, "\t\t[ID = %ld, %s, Scope = %ld, El = %ld]\n", inID, propStr, inScope , inElement);
387 
388  bool iscback = false;
389  bool isInput = false;
390  switch (inID)
391  {
392  case kAudioUnitProperty_SetRenderCallback:
393  iscback = true;
394  case kAudioUnitProperty_MakeConnection:
395  {
396  AUInputElement *el = mAUBase->GetInput (inElement);
397  if (el) {
398  bool hasInput = false;
399  if (iscback)
400  hasInput = el->IsCallback();
401  else
402  hasInput = el->HasConnection();
403  fprintf (mFile, "\t\tHas Input=%c, ", (hasInput ? 'T' : 'F'));
404  isInput = true;
405  }
406  }
407  case kAudioUnitProperty_SampleRate:
408  case kAudioUnitProperty_StreamFormat:
409  {
410  CAStreamBasicDescription desc = mAUBase->GetStreamFormat (inScope, inElement);
411  if (!isInput)
412  fprintf (mFile, "\t\t");
413  desc.Print (mFile);
414  break;
415  }
416  default:
417  break;
418  }
419 
420  mHaveDoneProperty = true;
421 }
422 
423 #endif //AU_DEBUG_DISPATCHER