The JUCE cross-platform C++ framework, with DISTRHO/KXStudio specific changes
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

774 lines
21KB

  1. /*!
  2. @file AudioUnitSDK/AUPlugInDispatch.cpp
  3. @copyright © 2000-2021 Apple Inc. All rights reserved.
  4. */
  5. #include <AudioUnitSDK/AUBase.h>
  6. #include <AudioUnitSDK/AUPlugInDispatch.h>
  7. #include <AudioUnitSDK/AUUtility.h>
  8. #include <AudioUnitSDK/ComponentBase.h>
  9. #include <cmath>
  10. #include <cstddef>
  11. #define CATCH_EXCEPTIONS_IN_RENDER_METHODS TARGET_OS_OSX // NOLINT
  12. #define HAVE_MUSICDEVICE_PREPARE_RELEASE TARGET_OS_OSX // NOLINT
  13. namespace ausdk {
  14. // ------------------------------------------------------------------------------------------------
  15. static auto AUInstance(void* self)
  16. {
  17. return reinterpret_cast<AUBase*>( // NOLINT reinterpret_cast
  18. &(static_cast<AudioComponentPlugInInstance*>(self)->mInstanceStorage));
  19. }
  20. // ------------------------------------------------------------------------------------------------
  21. class AUInstanceGuard {
  22. public:
  23. explicit AUInstanceGuard(void* self) : mGuard(AUInstance(self)->GetMutex()) {}
  24. private:
  25. const AUEntryGuard mGuard;
  26. };
  27. // ------------------------------------------------------------------------------------------------
  28. static bool IsValidParameterValue(AudioUnitParameterValue value) { return std::isfinite(value); }
  29. static bool AreValidParameterEvents(const AudioUnitParameterEvent* events, UInt32 numEvents)
  30. {
  31. if (events == nullptr) {
  32. return true;
  33. }
  34. for (UInt32 i = 0; i < numEvents; ++i) {
  35. const auto& event = events[i]; // NOLINT
  36. switch (event.eventType) {
  37. case kParameterEvent_Immediate: {
  38. if (!IsValidParameterValue(event.eventValues.immediate.value)) { // NOLINT
  39. return false;
  40. }
  41. break;
  42. }
  43. case kParameterEvent_Ramped: {
  44. if (!IsValidParameterValue(event.eventValues.ramp.startValue) || // NOLINT
  45. !IsValidParameterValue(event.eventValues.ramp.endValue)) { // NOLINT
  46. return false;
  47. }
  48. break;
  49. }
  50. default:
  51. break;
  52. }
  53. }
  54. return true;
  55. }
  56. // ------------------------------------------------------------------------------------------------
  57. static OSStatus AUMethodInitialize(void* self)
  58. {
  59. OSStatus result = noErr;
  60. try {
  61. const AUInstanceGuard guard(self);
  62. result = AUInstance(self)->DoInitialize();
  63. }
  64. AUSDK_Catch(result)
  65. return result;
  66. }
  67. static OSStatus AUMethodUninitialize(void* self)
  68. {
  69. OSStatus result = noErr;
  70. try {
  71. const AUInstanceGuard guard(self);
  72. AUInstance(self)->DoCleanup();
  73. }
  74. AUSDK_Catch(result)
  75. return result;
  76. }
  77. static OSStatus AUMethodGetPropertyInfo(void* self, AudioUnitPropertyID prop, AudioUnitScope scope,
  78. AudioUnitElement elem, UInt32* outDataSize, Boolean* outWritable)
  79. {
  80. OSStatus result = noErr;
  81. try {
  82. UInt32 dataSize = 0; // 13517289 GetPropetyInfo was returning an uninitialized value when
  83. // there is an error. This is a problem for auval.
  84. bool writable = false;
  85. const AUInstanceGuard guard(self);
  86. result = AUInstance(self)->DispatchGetPropertyInfo(prop, scope, elem, dataSize, writable);
  87. if (outDataSize != nullptr) {
  88. *outDataSize = dataSize;
  89. }
  90. if (outWritable != nullptr) {
  91. *outWritable = static_cast<Boolean>(writable);
  92. }
  93. }
  94. AUSDK_Catch(result)
  95. return result;
  96. }
  97. static OSStatus AUMethodGetProperty(void* self, AudioUnitPropertyID inID, AudioUnitScope inScope,
  98. AudioUnitElement inElement, void* outData, UInt32* ioDataSize)
  99. {
  100. OSStatus result = noErr;
  101. try {
  102. bool writable = false;
  103. const AUInstanceGuard guard(self);
  104. if (ioDataSize == nullptr) {
  105. AUSDK_LogError("AudioUnitGetProperty: null size pointer");
  106. return kAudio_ParamError;
  107. }
  108. if (outData == nullptr) {
  109. UInt32 dataSize = 0;
  110. result = AUInstance(self)->DispatchGetPropertyInfo(
  111. inID, inScope, inElement, dataSize, writable);
  112. *ioDataSize = dataSize;
  113. return result;
  114. }
  115. const auto clientBufferSize = *ioDataSize;
  116. if (clientBufferSize == 0) {
  117. AUSDK_LogError("AudioUnitGetProperty: *ioDataSize == 0 on entry");
  118. return kAudio_ParamError;
  119. }
  120. UInt32 actualPropertySize = 0;
  121. result = AUInstance(self)->DispatchGetPropertyInfo(
  122. inID, inScope, inElement, actualPropertySize, writable);
  123. if (result != noErr) {
  124. return result;
  125. }
  126. std::vector<std::byte> tempBuffer;
  127. void* destBuffer = nullptr;
  128. if (clientBufferSize < actualPropertySize) {
  129. tempBuffer.resize(actualPropertySize);
  130. destBuffer = tempBuffer.data();
  131. } else {
  132. destBuffer = outData;
  133. }
  134. result = AUInstance(self)->DispatchGetProperty(inID, inScope, inElement, destBuffer);
  135. if (result == noErr) {
  136. if (clientBufferSize < actualPropertySize && !tempBuffer.empty()) {
  137. memcpy(outData, tempBuffer.data(), clientBufferSize);
  138. // ioDataSize remains correct, the number of bytes we wrote
  139. } else {
  140. *ioDataSize = actualPropertySize;
  141. }
  142. } else {
  143. *ioDataSize = 0;
  144. }
  145. }
  146. AUSDK_Catch(result)
  147. return result;
  148. }
  149. static OSStatus AUMethodSetProperty(void* self, AudioUnitPropertyID inID, AudioUnitScope inScope,
  150. AudioUnitElement inElement, const void* inData, UInt32 inDataSize)
  151. {
  152. OSStatus result = noErr;
  153. try {
  154. const AUInstanceGuard guard(self);
  155. if ((inData != nullptr) && (inDataSize != 0u)) {
  156. result =
  157. AUInstance(self)->DispatchSetProperty(inID, inScope, inElement, inData, inDataSize);
  158. } else {
  159. if (inData == nullptr && inDataSize == 0) {
  160. result = AUInstance(self)->DispatchRemovePropertyValue(inID, inScope, inElement);
  161. } else {
  162. if (inData == nullptr) {
  163. AUSDK_LogError("AudioUnitSetProperty: inData == NULL");
  164. return kAudio_ParamError;
  165. }
  166. if (inDataSize == 0) {
  167. AUSDK_LogError("AudioUnitSetProperty: inDataSize == 0");
  168. return kAudio_ParamError;
  169. }
  170. }
  171. }
  172. }
  173. AUSDK_Catch(result)
  174. return result;
  175. }
  176. static OSStatus AUMethodAddPropertyListener(
  177. void* self, AudioUnitPropertyID prop, AudioUnitPropertyListenerProc proc, void* userData)
  178. {
  179. OSStatus result = noErr;
  180. try {
  181. const AUInstanceGuard guard(self);
  182. result = AUInstance(self)->AddPropertyListener(prop, proc, userData);
  183. }
  184. AUSDK_Catch(result)
  185. return result;
  186. }
  187. static OSStatus AUMethodRemovePropertyListener(
  188. void* self, AudioUnitPropertyID prop, AudioUnitPropertyListenerProc proc)
  189. {
  190. OSStatus result = noErr;
  191. try {
  192. const AUInstanceGuard guard(self);
  193. result = AUInstance(self)->RemovePropertyListener(prop, proc, nullptr, false);
  194. }
  195. AUSDK_Catch(result)
  196. return result;
  197. }
  198. static OSStatus AUMethodRemovePropertyListenerWithUserData(
  199. void* self, AudioUnitPropertyID prop, AudioUnitPropertyListenerProc proc, void* userData)
  200. {
  201. OSStatus result = noErr;
  202. try {
  203. const AUInstanceGuard guard(self);
  204. result = AUInstance(self)->RemovePropertyListener(prop, proc, userData, true);
  205. }
  206. AUSDK_Catch(result)
  207. return result;
  208. }
  209. static OSStatus AUMethodAddRenderNotify(void* self, AURenderCallback proc, void* userData)
  210. {
  211. OSStatus result = noErr;
  212. try {
  213. const AUInstanceGuard guard(self);
  214. result = AUInstance(self)->SetRenderNotification(proc, userData);
  215. }
  216. AUSDK_Catch(result)
  217. return result;
  218. }
  219. static OSStatus AUMethodRemoveRenderNotify(void* self, AURenderCallback proc, void* userData)
  220. {
  221. OSStatus result = noErr;
  222. try {
  223. const AUInstanceGuard guard(self);
  224. result = AUInstance(self)->RemoveRenderNotification(proc, userData);
  225. }
  226. AUSDK_Catch(result)
  227. return result;
  228. }
  229. static OSStatus AUMethodGetParameter(void* self, AudioUnitParameterID param, AudioUnitScope scope,
  230. AudioUnitElement elem, AudioUnitParameterValue* value)
  231. {
  232. OSStatus result = noErr;
  233. try {
  234. const AUInstanceGuard guard(self);
  235. result = (value == nullptr ? kAudio_ParamError
  236. : AUInstance(self)->GetParameter(param, scope, elem, *value));
  237. }
  238. AUSDK_Catch(result)
  239. return result;
  240. }
  241. static OSStatus AUMethodSetParameter(void* self, AudioUnitParameterID param, AudioUnitScope scope,
  242. AudioUnitElement elem, AudioUnitParameterValue value, UInt32 bufferOffset)
  243. {
  244. if (!IsValidParameterValue(value)) {
  245. return kAudioUnitErr_InvalidParameterValue;
  246. }
  247. OSStatus result = noErr;
  248. try {
  249. // this is a (potentially) realtime method; no lock
  250. result = AUInstance(self)->SetParameter(param, scope, elem, value, bufferOffset);
  251. }
  252. AUSDK_Catch(result)
  253. return result;
  254. }
  255. static OSStatus AUMethodScheduleParameters(
  256. void* self, const AudioUnitParameterEvent* events, UInt32 numEvents)
  257. {
  258. if (!AreValidParameterEvents(events, numEvents)) {
  259. return kAudioUnitErr_InvalidParameterValue;
  260. }
  261. OSStatus result = noErr;
  262. try {
  263. // this is a (potentially) realtime method; no lock
  264. result = AUInstance(self)->ScheduleParameter(events, numEvents);
  265. }
  266. AUSDK_Catch(result)
  267. return result;
  268. }
  269. static OSStatus AUMethodRender(void* self, AudioUnitRenderActionFlags* ioActionFlags,
  270. const AudioTimeStamp* inTimeStamp, UInt32 inOutputBusNumber, UInt32 inNumberFrames,
  271. AudioBufferList* ioData)
  272. {
  273. OSStatus result = noErr;
  274. #if CATCH_EXCEPTIONS_IN_RENDER_METHODS
  275. try {
  276. #endif
  277. // this is a processing method; no lock
  278. AudioUnitRenderActionFlags tempFlags{};
  279. if (inTimeStamp == nullptr || ioData == nullptr) {
  280. result = kAudio_ParamError;
  281. } else {
  282. if (ioActionFlags == nullptr) {
  283. tempFlags = 0;
  284. ioActionFlags = &tempFlags;
  285. }
  286. result = AUInstance(self)->DoRender(
  287. *ioActionFlags, *inTimeStamp, inOutputBusNumber, inNumberFrames, *ioData);
  288. }
  289. #if CATCH_EXCEPTIONS_IN_RENDER_METHODS
  290. }
  291. AUSDK_Catch(result)
  292. #endif
  293. return result;
  294. }
  295. static OSStatus AUMethodComplexRender(void* self, AudioUnitRenderActionFlags* ioActionFlags,
  296. const AudioTimeStamp* inTimeStamp, UInt32 inOutputBusNumber, UInt32 inNumberOfPackets,
  297. UInt32* outNumberOfPackets, AudioStreamPacketDescription* outPacketDescriptions,
  298. AudioBufferList* ioData, void* outMetadata, UInt32* outMetadataByteSize)
  299. {
  300. OSStatus result = noErr;
  301. #if CATCH_EXCEPTIONS_IN_RENDER_METHODS
  302. try {
  303. #endif
  304. // this is a processing method; no lock
  305. AudioUnitRenderActionFlags tempFlags{};
  306. if (inTimeStamp == nullptr || ioData == nullptr) {
  307. result = kAudio_ParamError;
  308. } else {
  309. if (ioActionFlags == nullptr) {
  310. tempFlags = 0;
  311. ioActionFlags = &tempFlags;
  312. }
  313. result = AUInstance(self)->ComplexRender(*ioActionFlags, *inTimeStamp,
  314. inOutputBusNumber, inNumberOfPackets, outNumberOfPackets, outPacketDescriptions,
  315. *ioData, outMetadata, outMetadataByteSize);
  316. }
  317. #if CATCH_EXCEPTIONS_IN_RENDER_METHODS
  318. }
  319. AUSDK_Catch(result)
  320. #endif
  321. return result;
  322. }
  323. static OSStatus AUMethodReset(void* self, AudioUnitScope scope, AudioUnitElement elem)
  324. {
  325. OSStatus result = noErr;
  326. try {
  327. const AUInstanceGuard guard(self);
  328. result = AUInstance(self)->Reset(scope, elem);
  329. }
  330. AUSDK_Catch(result)
  331. return result;
  332. }
  333. static OSStatus AUMethodProcess(void* self, AudioUnitRenderActionFlags* ioActionFlags,
  334. const AudioTimeStamp* inTimeStamp, UInt32 inNumberFrames, AudioBufferList* ioData)
  335. {
  336. OSStatus result = noErr;
  337. #if CATCH_EXCEPTIONS_IN_RENDER_METHODS
  338. try {
  339. #endif
  340. // this is a processing method; no lock
  341. bool doParamCheck = true;
  342. AudioUnitRenderActionFlags tempFlags{};
  343. if (ioActionFlags == nullptr) {
  344. tempFlags = 0;
  345. ioActionFlags = &tempFlags;
  346. } else {
  347. if ((*ioActionFlags & kAudioUnitRenderAction_DoNotCheckRenderArgs) != 0u) {
  348. doParamCheck = false;
  349. }
  350. }
  351. if (doParamCheck && (inTimeStamp == nullptr || ioData == nullptr)) {
  352. result = kAudio_ParamError;
  353. } else {
  354. result =
  355. AUInstance(self)->DoProcess(*ioActionFlags, *inTimeStamp, inNumberFrames, *ioData);
  356. }
  357. #if CATCH_EXCEPTIONS_IN_RENDER_METHODS
  358. }
  359. AUSDK_Catch(result)
  360. #endif
  361. return result;
  362. }
  363. static OSStatus AUMethodProcessMultiple(void* self, AudioUnitRenderActionFlags* ioActionFlags,
  364. const AudioTimeStamp* inTimeStamp, UInt32 inNumberFrames, UInt32 inNumberInputBufferLists,
  365. const AudioBufferList** inInputBufferLists, UInt32 inNumberOutputBufferLists,
  366. AudioBufferList** ioOutputBufferLists)
  367. {
  368. OSStatus result = noErr;
  369. #if CATCH_EXCEPTIONS_IN_RENDER_METHODS
  370. try {
  371. #endif
  372. // this is a processing method; no lock
  373. bool doParamCheck = true;
  374. AudioUnitRenderActionFlags tempFlags{};
  375. if (ioActionFlags == nullptr) {
  376. tempFlags = 0;
  377. ioActionFlags = &tempFlags;
  378. } else {
  379. if ((*ioActionFlags & kAudioUnitRenderAction_DoNotCheckRenderArgs) != 0u) {
  380. doParamCheck = false;
  381. }
  382. }
  383. if (doParamCheck && (inTimeStamp == nullptr || inInputBufferLists == nullptr ||
  384. ioOutputBufferLists == nullptr)) {
  385. result = kAudio_ParamError;
  386. } else {
  387. result = AUInstance(self)->DoProcessMultiple(*ioActionFlags, *inTimeStamp,
  388. inNumberFrames, inNumberInputBufferLists, inInputBufferLists,
  389. inNumberOutputBufferLists, ioOutputBufferLists);
  390. }
  391. #if CATCH_EXCEPTIONS_IN_RENDER_METHODS
  392. }
  393. AUSDK_Catch(result)
  394. #endif
  395. return result;
  396. }
  397. // ------------------------------------------------------------------------------------------------
  398. static OSStatus AUMethodStart(void* self)
  399. {
  400. OSStatus result = noErr;
  401. try {
  402. const AUInstanceGuard guard(self);
  403. result = AUInstance(self)->Start();
  404. }
  405. AUSDK_Catch(result)
  406. return result;
  407. }
  408. static OSStatus AUMethodStop(void* self)
  409. {
  410. OSStatus result = noErr;
  411. try {
  412. const AUInstanceGuard guard(self);
  413. result = AUInstance(self)->Stop();
  414. }
  415. AUSDK_Catch(result)
  416. return result;
  417. }
  418. // ------------------------------------------------------------------------------------------------
  419. // I don't know what I'm doing here; conflicts with the multiple inheritence in MusicDeviceBase.
  420. static OSStatus AUMethodMIDIEvent(
  421. void* self, UInt32 inStatus, UInt32 inData1, UInt32 inData2, UInt32 inOffsetSampleFrame)
  422. {
  423. OSStatus result = noErr;
  424. try {
  425. // this is a potential render-time method; no lock
  426. result = AUInstance(self)->MIDIEvent(inStatus, inData1, inData2, inOffsetSampleFrame);
  427. }
  428. AUSDK_Catch(result)
  429. return result;
  430. }
  431. static OSStatus AUMethodSysEx(void* self, const UInt8* inData, UInt32 inLength)
  432. {
  433. OSStatus result = noErr;
  434. try {
  435. // this is a potential render-time method; no lock
  436. result = AUInstance(self)->SysEx(inData, inLength);
  437. }
  438. AUSDK_Catch(result)
  439. return result;
  440. }
  441. #if AUSDK_MIDI2_AVAILABLE
  442. static OSStatus AUMethodMIDIEventList(
  443. void* self, UInt32 inOffsetSampleFrame, const struct MIDIEventList* eventList)
  444. {
  445. if (eventList == nullptr) {
  446. return kAudio_ParamError;
  447. }
  448. OSStatus result = noErr;
  449. try {
  450. // this is a potential render-time method; no lock
  451. // Note that a MIDIEventList is variably-sized and can be backed by less memory than
  452. // required, so it is Undefined Behavior to form a reference to it; we must only use
  453. // pointers.
  454. result = AUInstance(self)->MIDIEventList(inOffsetSampleFrame, eventList);
  455. }
  456. AUSDK_Catch(result)
  457. return result;
  458. }
  459. #endif
  460. static OSStatus AUMethodStartNote(void* self, MusicDeviceInstrumentID inInstrument,
  461. MusicDeviceGroupID inGroupID, NoteInstanceID* outNoteInstanceID, UInt32 inOffsetSampleFrame,
  462. const MusicDeviceNoteParams* inParams)
  463. {
  464. OSStatus result = noErr;
  465. try {
  466. // this is a potential render-time method; no lock
  467. if (inParams == nullptr) {
  468. result = kAudio_ParamError;
  469. } else {
  470. result = AUInstance(self)->StartNote(
  471. inInstrument, inGroupID, outNoteInstanceID, inOffsetSampleFrame, *inParams);
  472. }
  473. }
  474. AUSDK_Catch(result)
  475. return result;
  476. }
  477. static OSStatus AUMethodStopNote(void* self, MusicDeviceGroupID inGroupID,
  478. NoteInstanceID inNoteInstanceID, UInt32 inOffsetSampleFrame)
  479. {
  480. OSStatus result = noErr;
  481. try {
  482. // this is a potential render-time method; no lock
  483. result = AUInstance(self)->StopNote(inGroupID, inNoteInstanceID, inOffsetSampleFrame);
  484. }
  485. AUSDK_Catch(result)
  486. return result;
  487. }
  488. #if HAVE_MUSICDEVICE_PREPARE_RELEASE
  489. static OSStatus AUMethodPrepareInstrument(void* self, MusicDeviceInstrumentID inInstrument)
  490. {
  491. OSStatus result = noErr;
  492. try {
  493. // this is a potential render-time method; no lock
  494. result = AUInstance(self)->PrepareInstrument(inInstrument); // NOLINT static via instance
  495. }
  496. AUSDK_Catch(result)
  497. return result;
  498. }
  499. static OSStatus AUMethodReleaseInstrument(void* self, MusicDeviceInstrumentID inInstrument)
  500. {
  501. OSStatus result = noErr;
  502. try {
  503. // this is a potential render-time method; no lock
  504. result = AUInstance(self)->ReleaseInstrument(inInstrument); // NOLINT static via instance
  505. }
  506. AUSDK_Catch(result)
  507. return result;
  508. }
  509. #endif // HAVE_MUSICDEVICE_PREPARE_RELEASE
  510. //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  511. #pragma mark -
  512. #pragma mark Lookup Methods
  513. AudioComponentMethod AUBaseLookup::Lookup(SInt16 selector)
  514. {
  515. switch (selector) {
  516. case kAudioUnitInitializeSelect:
  517. return (AudioComponentMethod)AUMethodInitialize; // NOLINT cast
  518. case kAudioUnitUninitializeSelect:
  519. return (AudioComponentMethod)AUMethodUninitialize; // NOLINT cast
  520. case kAudioUnitGetPropertyInfoSelect:
  521. return (AudioComponentMethod)AUMethodGetPropertyInfo; // NOLINT cast
  522. case kAudioUnitGetPropertySelect:
  523. return (AudioComponentMethod)AUMethodGetProperty; // NOLINT cast
  524. case kAudioUnitSetPropertySelect:
  525. return (AudioComponentMethod)AUMethodSetProperty; // NOLINT cast
  526. case kAudioUnitAddPropertyListenerSelect:
  527. return (AudioComponentMethod)AUMethodAddPropertyListener; // NOLINT cast
  528. case kAudioUnitRemovePropertyListenerSelect:
  529. return (AudioComponentMethod)AUMethodRemovePropertyListener; // NOLINT cast
  530. case kAudioUnitRemovePropertyListenerWithUserDataSelect:
  531. return (AudioComponentMethod)AUMethodRemovePropertyListenerWithUserData; // NOLINT cast
  532. case kAudioUnitAddRenderNotifySelect:
  533. return (AudioComponentMethod)AUMethodAddRenderNotify; // NOLINT cast
  534. case kAudioUnitRemoveRenderNotifySelect:
  535. return (AudioComponentMethod)AUMethodRemoveRenderNotify; // NOLINT cast
  536. case kAudioUnitGetParameterSelect:
  537. return (AudioComponentMethod)AUMethodGetParameter; // NOLINT cast
  538. case kAudioUnitSetParameterSelect:
  539. return (AudioComponentMethod)AUMethodSetParameter; // NOLINT cast
  540. case kAudioUnitScheduleParametersSelect:
  541. return (AudioComponentMethod)AUMethodScheduleParameters; // NOLINT cast
  542. case kAudioUnitRenderSelect:
  543. return (AudioComponentMethod)AUMethodRender; // NOLINT cast
  544. case kAudioUnitResetSelect:
  545. return (AudioComponentMethod)AUMethodReset; // NOLINT cast
  546. default:
  547. break;
  548. }
  549. return nullptr;
  550. }
  551. AudioComponentMethod AUOutputLookup::Lookup(SInt16 selector)
  552. {
  553. const AudioComponentMethod method = AUBaseLookup::Lookup(selector);
  554. if (method != nullptr) {
  555. return method;
  556. }
  557. switch (selector) {
  558. case kAudioOutputUnitStartSelect:
  559. return (AudioComponentMethod)AUMethodStart; // NOLINT cast
  560. case kAudioOutputUnitStopSelect:
  561. return (AudioComponentMethod)AUMethodStop; // NOLINT cast
  562. default:
  563. break;
  564. }
  565. return nullptr;
  566. }
  567. AudioComponentMethod AUComplexOutputLookup::Lookup(SInt16 selector)
  568. {
  569. AudioComponentMethod method = AUBaseLookup::Lookup(selector);
  570. if (method != nullptr) {
  571. return method;
  572. }
  573. method = AUOutputLookup::Lookup(selector);
  574. if (method != nullptr) {
  575. return method;
  576. }
  577. if (selector == kAudioUnitComplexRenderSelect) {
  578. return (AudioComponentMethod)AUMethodComplexRender; // NOLINT cast
  579. }
  580. return nullptr;
  581. }
  582. AudioComponentMethod AUBaseProcessLookup::Lookup(SInt16 selector)
  583. {
  584. const AudioComponentMethod method = AUBaseLookup::Lookup(selector);
  585. if (method != nullptr) {
  586. return method;
  587. }
  588. if (selector == kAudioUnitProcessSelect) {
  589. return (AudioComponentMethod)AUMethodProcess; // NOLINT cast
  590. }
  591. return nullptr;
  592. }
  593. AudioComponentMethod AUBaseProcessMultipleLookup::Lookup(SInt16 selector)
  594. {
  595. const AudioComponentMethod method = AUBaseLookup::Lookup(selector);
  596. if (method != nullptr) {
  597. return method;
  598. }
  599. if (selector == kAudioUnitProcessMultipleSelect) {
  600. return (AudioComponentMethod)AUMethodProcessMultiple; // NOLINT cast
  601. }
  602. return nullptr;
  603. }
  604. AudioComponentMethod AUBaseProcessAndMultipleLookup::Lookup(SInt16 selector)
  605. {
  606. AudioComponentMethod method = AUBaseLookup::Lookup(selector);
  607. if (method != nullptr) {
  608. return method;
  609. }
  610. method = AUBaseProcessMultipleLookup::Lookup(selector);
  611. if (method != nullptr) {
  612. return method;
  613. }
  614. method = AUBaseProcessLookup::Lookup(selector);
  615. if (method != nullptr) {
  616. return method;
  617. }
  618. return nullptr;
  619. }
  620. inline AudioComponentMethod MIDI_Lookup(SInt16 selector)
  621. {
  622. switch (selector) {
  623. case kMusicDeviceMIDIEventSelect:
  624. return (AudioComponentMethod)AUMethodMIDIEvent; // NOLINT cast
  625. case kMusicDeviceSysExSelect:
  626. return (AudioComponentMethod)AUMethodSysEx; // NOLINT cast
  627. #if AUSDK_MIDI2_AVAILABLE
  628. case kMusicDeviceMIDIEventListSelect:
  629. return (AudioComponentMethod)AUMethodMIDIEventList; // NOLINT cast
  630. #endif
  631. default:
  632. break;
  633. }
  634. return nullptr;
  635. }
  636. AudioComponentMethod AUMIDILookup::Lookup(SInt16 selector)
  637. {
  638. const AudioComponentMethod method = AUBaseLookup::Lookup(selector);
  639. if (method != nullptr) {
  640. return method;
  641. }
  642. return MIDI_Lookup(selector);
  643. }
  644. AudioComponentMethod AUMIDIProcessLookup::Lookup(SInt16 selector)
  645. {
  646. const AudioComponentMethod method = AUBaseProcessLookup::Lookup(selector);
  647. if (method != nullptr) {
  648. return method;
  649. }
  650. return MIDI_Lookup(selector);
  651. }
  652. AudioComponentMethod AUMusicLookup::Lookup(SInt16 selector)
  653. {
  654. const AudioComponentMethod method = AUBaseLookup::Lookup(selector);
  655. if (method != nullptr) {
  656. return method;
  657. }
  658. switch (selector) {
  659. case kMusicDeviceStartNoteSelect:
  660. return (AudioComponentMethod)AUMethodStartNote; // NOLINT cast
  661. case kMusicDeviceStopNoteSelect:
  662. return (AudioComponentMethod)AUMethodStopNote; // NOLINT cast
  663. #if HAVE_MUSICDEVICE_PREPARE_RELEASE
  664. case kMusicDevicePrepareInstrumentSelect:
  665. return (AudioComponentMethod)AUMethodPrepareInstrument; // NOLINT cast
  666. case kMusicDeviceReleaseInstrumentSelect:
  667. return (AudioComponentMethod)AUMethodReleaseInstrument; // NOLINT cast
  668. #endif
  669. default:
  670. break;
  671. }
  672. return MIDI_Lookup(selector);
  673. }
  674. } // namespace ausdk