@@ -166,6 +166,11 @@ void _sendMessage (MessageID messageID, MessageEncoder * encoder) override
166166 : AudioUnitMessageChannel { this },
167167 _audioUnitChannel { audioUnitChannel }
168168 {
169+ // \todo there's also QOS_CLASS_USER_INTERACTIVE which seems more appropriate but is undocumented...
170+ if (_instanceCount == 0 )
171+ _readAudioQueue = dispatch_queue_create (" ARA read audio samples" , dispatch_queue_attr_make_with_qos_class (DISPATCH_QUEUE_SERIAL, QOS_CLASS_USER_INITIATED, -1 ));
172+ ++_instanceCount;
173+
169174#if !__has_feature(objc_arc)
170175 [_audioUnitChannel retain ];
171176#endif
@@ -180,6 +185,27 @@ void _sendMessage (MessageID messageID, MessageEncoder * encoder) override
180185 ~ProxyPlugInMessageChannel () override
181186 {
182187 _audioUnitChannel.callHostBlock = nil ;
188+
189+ --_instanceCount;
190+ if (_instanceCount == 0 )
191+ dispatch_release (_readAudioQueue);
192+ }
193+
194+ DispatchTarget getDispatchTargetForIncomingTransaction (MessageID messageID) override
195+ {
196+ // AUMessageChannel cannot be called back from the same thread it receives the message,
197+ // so we dispatch to the main queue for playback requests and to a dedicated read samples queue for audio requests
198+ // \todo maybe we should make this configurable, so hosts can set these queues if they already have appropriate ones?
199+ if (messageID == ARA_IPC_HOST_METHOD_ID (ARAAudioAccessControllerInterface, readAudioSamples).getMessageID ())
200+ {
201+ return _readAudioQueue;
202+ }
203+ else
204+ {
205+ ARA_INTERNAL_ASSERT ((ARA_IPC_HOST_METHOD_ID (ARAPlaybackControllerInterface, requestStartPlayback).getMessageID () <= messageID) &&
206+ (messageID <= ARA_IPC_HOST_METHOD_ID (ARAPlaybackControllerInterface, requestEnableCycle).getMessageID ()));
207+ return dispatch_get_main_queue ();
208+ }
183209 }
184210
185211protected:
@@ -191,8 +217,13 @@ void _sendMessage (MessageID messageID, MessageEncoder * encoder) override
191217
192218private:
193219 NSObject <AUMessageChannel> * __strong _Nonnull _audioUnitChannel;
220+ static dispatch_queue_t _readAudioQueue;
221+ static int _instanceCount;
194222};
195223
224+ dispatch_queue_t ProxyPlugInMessageChannel::_readAudioQueue { nullptr };
225+ int ProxyPlugInMessageChannel::_instanceCount { 0 };
226+
196227
197228// host side: proxy plug-in message channel further specialization for plug-in extension messages
198229class ProxyPlugInExtensionMessageChannel : public ProxyPlugInMessageChannel
0 commit comments