]> sjero.net Git - linphone/blob - linphone/mediastreamer2/src/aqsnd.c
0c7f06bd860a8fab9e56a2b9bab1e2a56acd121f
[linphone] / linphone / mediastreamer2 / src / aqsnd.c
1 /*
2 mediastreamer2 library - modular sound and video processing and streaming
3 Copyright (C) 2006  Simon MORLAT (simon.morlat@linphone.org)
4
5 This program is free software; you can redistribute it and/or
6 modify it under the terms of the GNU General Public License
7 as published by the Free Software Foundation; either version 2
8 of the License, or (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18 */
19
20 /* this file is specifically distributed under a BSD license */
21
22 /**
23 * Copyright (C) 2008  Hiroki Mori (himori@users.sourceforge.net)
24 * All rights reserved.
25
26 * Redistribution and use in source and binary forms, with or without
27 * modification, are permitted provided that the following conditions are met:
28 *     * Redistributions of source code must retain the above copyright
29 *       notice, this list of conditions and the following disclaimer.
30 *     * Redistributions in binary form must reproduce the above copyright
31 *       notice, this list of conditions and the following disclaimer in the
32 *       documentation and/or other materials provided with the distribution.
33 *     * Neither the name of the <organization> nor the
34 *       names of its contributors may be used to endorse or promote products
35 *       derived from this software without specific prior written permission.
36 *
37 * THIS SOFTWARE IS PROVIDED BY <copyright holder> ``AS IS'' AND ANY
38 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
39 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
40 * DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY
41 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
42 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
43 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
44 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
45 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
46 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
47 **/
48
49 /*
50  This is MacOS X Audio Queue Service support code for mediastreamer2.
51  Audio Queue Support MacOS X 10.5 or later.
52  http://developer.apple.com/documentation/MusicAudio/Conceptual/AudioQueueProgrammingGuide/
53  */
54
55 #include <AudioToolbox/AudioToolbox.h>
56 #if (!defined(__AudioHardware_h__) & !defined(__IPHONE_3_0))
57 #include "AudioHardware.h"
58 #endif
59
60 #include "mediastreamer2/mssndcard.h"
61 #include "mediastreamer2/msfilter.h"
62
63 MSFilter *ms_aq_read_new(MSSndCard * card);
64 MSFilter *ms_aq_write_new(MSSndCard * card);
65
66 #define kSecondsPerBuffer               0.02    /*0.04 */
67 #define kNumberAudioOutDataBuffers      4
68 #define kNumberAudioInDataBuffers       4
69
70 float gain_volume_in=1.0;
71 float gain_volume_out=1.0;
72 bool gain_changed_in = true;
73 bool gain_changed_out = true;
74
75 typedef struct AQData {
76         CFStringRef uidname;
77         AudioStreamBasicDescription devicereadFormat;
78         AudioStreamBasicDescription devicewriteFormat;
79
80         int rate;
81         int bits;
82         bool_t stereo;
83
84         ms_mutex_t mutex;
85         queue_t rq;
86         bool_t read_started;
87         bool_t write_started;
88
89         AudioConverterRef readAudioConverter;
90         AudioQueueRef readQueue;
91         AudioStreamBasicDescription readAudioFormat;
92         UInt32 readBufferByteSize;
93
94         AudioConverterRef writeAudioConverter;
95         AudioQueueRef writeQueue;
96         AudioStreamBasicDescription writeAudioFormat;
97         UInt32 writeBufferByteSize;
98         AudioQueueBufferRef writeBuffers[kNumberAudioOutDataBuffers];
99         int curWriteBuffer;
100         MSBufferizer *bufferizer;
101 } AQData;
102
103
104
105 /*
106  mediastreamer2 function
107  */
108
109 typedef struct AqSndDsCard {
110         CFStringRef uidname;
111         AudioStreamBasicDescription devicereadFormat;
112         AudioStreamBasicDescription devicewriteFormat;
113         int removed;
114 } AqSndDsCard;
115
116 static void aqcard_set_level(MSSndCard * card, MSSndCardMixerElem e,
117                                                          int percent)
118 {
119         switch(e){
120                 case MS_SND_CARD_PLAYBACK:
121                 case MS_SND_CARD_MASTER:
122                         gain_volume_out =((float)percent)/100.0f;
123                         gain_changed_out = true;
124                         return;
125                 case MS_SND_CARD_CAPTURE:
126                         gain_volume_in =((float)percent)/100.0f;
127                         gain_changed_in = true;
128                         return;
129                 default:
130                         ms_warning("aqcard_set_level: unsupported command.");
131         }
132 }
133
134 static int aqcard_get_level(MSSndCard * card, MSSndCardMixerElem e)
135 {
136         switch(e){
137                 case MS_SND_CARD_PLAYBACK:
138                 case MS_SND_CARD_MASTER:
139                         {
140                         }
141                   return (int)(gain_volume_out*100.0f);
142                 case MS_SND_CARD_CAPTURE:
143                   return (int)(gain_volume_in*100.0f);
144                 default:
145                         ms_warning("aqcard_get_level: unsupported command.");
146         }
147         return -1;
148 }
149
150 static void aqcard_set_source(MSSndCard * card, MSSndCardCapture source)
151 {
152 }
153
154 static void aqcard_init(MSSndCard * card)
155 {
156         AqSndDsCard *c = (AqSndDsCard *) ms_new(AqSndDsCard, 1);
157         c->removed = 0;
158         card->data = c;
159 }
160
161 static void aqcard_uninit(MSSndCard * card)
162 {
163         AqSndDsCard *d = (AqSndDsCard *) card->data;
164         if (d->uidname != NULL)
165                 CFRelease(d->uidname);
166         ms_free(d);
167 }
168
169 static void aqcard_detect(MSSndCardManager * m);
170 static MSSndCard *aqcard_duplicate(MSSndCard * obj);
171
172 MSSndCardDesc aq_card_desc = {
173         .driver_type = "AQ",
174         .detect = aqcard_detect,
175         .init = aqcard_init,
176         .set_level = aqcard_set_level,
177         .get_level = aqcard_get_level,
178         .set_capture = aqcard_set_source,
179         .set_control = NULL,
180         .get_control = NULL,
181         .create_reader = ms_aq_read_new,
182         .create_writer = ms_aq_write_new,
183         .uninit = aqcard_uninit,
184         .duplicate = aqcard_duplicate
185 };
186
187 static MSSndCard *aqcard_duplicate(MSSndCard * obj)
188 {
189         MSSndCard *card = ms_snd_card_new(&aq_card_desc);
190         card->name = ms_strdup(obj->name);
191         card->data = ms_new(AqSndDsCard, 1);
192         memcpy(card->data, obj->data, sizeof(AqSndDsCard));
193         return card;
194 }
195
196 static MSSndCard *aq_card_new(const char *name, CFStringRef uidname,
197                                                           AudioStreamBasicDescription *
198                                                           devicereadFormat,
199                                                           AudioStreamBasicDescription *
200                                                           devicewriteFormat, unsigned cap)
201 {
202         MSSndCard *card = ms_snd_card_new(&aq_card_desc);
203         AqSndDsCard *d = (AqSndDsCard *) card->data;
204         d->uidname = uidname;
205         memcpy(&d->devicereadFormat, devicereadFormat,
206                    sizeof(AudioStreamBasicDescription));
207         memcpy(&d->devicewriteFormat, devicewriteFormat,
208                    sizeof(AudioStreamBasicDescription));
209         card->name = ms_strdup(name);
210         card->capabilities = cap;
211         return card;
212 }
213
214 static void show_format(char *name,
215                                                 AudioStreamBasicDescription * deviceFormat)
216 {
217         ms_debug("Format for %s", name);
218         ms_debug("mSampleRate = %g", deviceFormat->mSampleRate);
219         char *the4CCString = (char *) &deviceFormat->mFormatID;
220         char outName[5];
221         outName[0] = the4CCString[0];
222         outName[1] = the4CCString[1];
223         outName[2] = the4CCString[2];
224         outName[3] = the4CCString[3];
225         outName[4] = 0;
226         ms_debug("mFormatID = %s", outName);
227         ms_debug("mFormatFlags = %08lX", deviceFormat->mFormatFlags);
228         ms_debug("mBytesPerPacket = %ld", deviceFormat->mBytesPerPacket);
229         ms_debug("mFramesPerPacket = %ld", deviceFormat->mFramesPerPacket);
230         ms_debug("mChannelsPerFrame = %ld", deviceFormat->mChannelsPerFrame);
231         ms_debug("mBytesPerFrame = %ld", deviceFormat->mBytesPerFrame);
232         ms_debug("mBitsPerChannel = %ld", deviceFormat->mBitsPerChannel);
233 }
234
235 static void aqcard_detect(MSSndCardManager * m)
236 {
237         OSStatus err;
238         UInt32 slen;
239         int count;
240         Boolean writable;
241         int i;
242         writable = 0;
243         slen = 0;
244         err =
245                 AudioHardwareGetPropertyInfo(kAudioHardwarePropertyDevices, &slen,
246                                                                          &writable);
247         if (err != kAudioHardwareNoError) {
248                 ms_error("get kAudioHardwarePropertyDevices error %ld", err);
249                 return;
250         }
251         AudioDeviceID V[slen / sizeof(AudioDeviceID)];
252         err =
253                 AudioHardwareGetProperty(kAudioHardwarePropertyDevices, &slen, V);
254         if (err != kAudioHardwareNoError) {
255                 ms_error("get kAudioHardwarePropertyDevices error %ld", err);
256                 return;
257         }
258         count = slen / sizeof(AudioDeviceID);
259         for (i = 0; i < count; i++) {
260                 char devname[256];
261                 char uidname[256];
262                 int cap = 0;
263                 slen = 256;
264                 err =
265                         AudioDeviceGetProperty(V[i], 0, FALSE,
266                                                                    kAudioDevicePropertyDeviceName, &slen,
267                                                                    devname);
268                 if (err != kAudioHardwareNoError) {
269                         ms_error("get kAudioDevicePropertyDeviceName error %ld", err);
270                         continue;
271                 }
272                 slen = strlen(devname);
273                 /* trim whitespace */
274                 while ((slen > 0) && (devname[slen - 1] == ' ')) {
275                         slen--;
276                 }
277                 devname[slen] = '\0';
278
279                 err =
280                         AudioDeviceGetPropertyInfo(V[i], 0, FALSE,
281                                                                            kAudioDevicePropertyStreamConfiguration,
282                                                                            &slen, &writable);
283                 if (err != kAudioHardwareNoError) {
284                         ms_error("get kAudioDevicePropertyDeviceName error %ld", err);
285                         continue;
286                 }
287                 AudioBufferList *buflist = ms_new(slen, 1);
288                 if (buflist == NULL) {
289                         ms_error("alloc AudioBufferList %ld", err);
290                         continue;
291                 }
292
293                 err =
294                         AudioDeviceGetProperty(V[i], 0, FALSE,
295                                                                    kAudioDevicePropertyStreamConfiguration,
296                                                                    &slen, buflist);
297                 if (err != kAudioHardwareNoError) {
298                         ms_error("get kAudioDevicePropertyDeviceName error %ld", err);
299                         ms_free(buflist);
300                         continue;
301                 }
302
303                 UInt32 j;
304                 for (j = 0; j < buflist->mNumberBuffers; j++) {
305                         if (buflist->mBuffers[j].mNumberChannels > 0) {
306                                 cap = MS_SND_CARD_CAP_PLAYBACK;
307                                 break;
308                         }
309                 }
310
311                 ms_free(buflist);
312
313                 err =
314                         AudioDeviceGetPropertyInfo(V[i], 0, TRUE,
315                                                                            kAudioDevicePropertyStreamConfiguration,
316                                                                            &slen, &writable);
317                 if (err != kAudioHardwareNoError) {
318                         ms_error("get kAudioDevicePropertyDeviceName error %ld", err);
319                         continue;
320                 }
321                 buflist = ms_new(slen, 1);
322                 if (buflist == NULL) {
323                         ms_error("alloc error %ld", err);
324                         continue;
325                 }
326
327                 err =
328                         AudioDeviceGetProperty(V[i], 0, TRUE,
329                                                                    kAudioDevicePropertyStreamConfiguration,
330                                                                    &slen, buflist);
331                 if (err != kAudioHardwareNoError) {
332                         ms_error("get kAudioDevicePropertyDeviceName error %ld", err);
333                         ms_free(buflist);
334                         continue;
335                 }
336
337                 for (j = 0; j < buflist->mNumberBuffers; j++) {
338                         if (buflist->mBuffers[j].mNumberChannels > 0) {
339                                 cap |= MS_SND_CARD_CAP_CAPTURE;
340                                 break;
341                         }
342                 }
343
344                 ms_free(buflist);
345
346                 CFStringRef dUID;
347                 dUID = NULL;
348                 slen = sizeof(CFStringRef);
349                 err =
350                         AudioDeviceGetProperty(V[i], 0, false,
351                                                                    kAudioDevicePropertyDeviceUID, &slen,
352                                                                    &dUID);
353                 if (err != kAudioHardwareNoError) {
354                         ms_error("get kAudioHardwarePropertyDevices error %ld", err);
355                         continue;
356                 }
357                 CFStringGetCString(dUID, uidname, 256,
358                                                    CFStringGetSystemEncoding());
359                 ms_message("AQ: devname:%s uidname:%s", devname, uidname);
360
361                 AudioStreamBasicDescription devicereadFormat;
362                 AudioStreamBasicDescription devicewriteFormat;
363                 slen = sizeof(devicewriteFormat);
364                 err = AudioDeviceGetProperty(V[i], 0, false,
365                                                                          kAudioDevicePropertyStreamFormat,
366                                                                          &slen, &devicewriteFormat);
367                 if (err == kAudioHardwareNoError) {
368                         show_format("output device", &devicewriteFormat);
369                 }
370                 slen = sizeof(devicereadFormat);
371                 err = AudioDeviceGetProperty(V[i], 0, true,
372                                                                          kAudioDevicePropertyStreamFormat,
373                                                                          &slen, &devicereadFormat);
374                 if (err == kAudioHardwareNoError) {
375                         show_format("input device", &devicereadFormat);
376                 }
377
378                 MSSndCard *card = aq_card_new(devname, dUID, &devicereadFormat,
379                                                                           &devicewriteFormat, cap);
380                 ms_snd_card_manager_add_card(m, card);
381         }
382 }
383
384
385 /*
386  Audio Queue recode callback
387  */
388
389 static void readCallback(void *aqData,
390                                                  AudioQueueRef inAQ,
391                                                  AudioQueueBufferRef inBuffer,
392                                                  const AudioTimeStamp * inStartTime,
393                                                  UInt32 inNumPackets,
394                                                  const AudioStreamPacketDescription * inPacketDesc)
395 {
396         AQData *d = (AQData *) aqData;
397         OSStatus err;
398         mblk_t *rm = NULL;
399
400         UInt32 len =
401                 (inBuffer->mAudioDataByteSize * d->readAudioFormat.mSampleRate /
402                  1) / d->devicereadFormat.mSampleRate /
403                 d->devicereadFormat.mChannelsPerFrame;
404
405         ms_mutex_lock(&d->mutex);
406         if (d->read_started == FALSE) {
407                 ms_mutex_unlock(&d->mutex);
408                 return;
409         }
410
411         rm = allocb(len, 0);
412
413         err = AudioConverterConvertBuffer(d->readAudioConverter,
414                                                                           inBuffer->mAudioDataByteSize,
415                                                                           inBuffer->mAudioData,
416                                                                           &len, rm->b_wptr);
417         if (err != noErr) {
418                 ms_error("readCallback: AudioConverterConvertBuffer %d", err);
419                 ms_warning("readCallback: inBuffer->mAudioDataByteSize = %d",
420                                    inBuffer->mAudioDataByteSize);
421                 ms_warning("readCallback: outlen = %d", len);
422                 ms_warning("readCallback: origlen = %i",
423                                    (inBuffer->mAudioDataByteSize *
424                                         d->readAudioFormat.mSampleRate / 1) /
425                                    d->devicereadFormat.mSampleRate /
426                                    d->devicereadFormat.mChannelsPerFrame);
427                 freeb(rm);
428         } else {
429
430           rm->b_wptr += len;
431           if (gain_volume_in != 1.0f)
432             {
433               int16_t *ptr=(int16_t *)rm->b_rptr;
434               for (;ptr<(int16_t *)rm->b_wptr;ptr++)
435                 {
436                   *ptr=(int16_t)(((float)(*ptr))*gain_volume_in);
437                 }
438             }
439           putq(&d->rq, rm);
440         }
441
442         err = AudioQueueEnqueueBuffer(d->readQueue, inBuffer, 0, NULL);
443         if (err != noErr) {
444                 ms_error("readCallback:AudioQueueEnqueueBuffer %d", err);
445         }
446         ms_mutex_unlock(&d->mutex);
447 }
448
449 /*
450  Audio Queue play callback
451  */
452
453 static void writeCallback(void *aqData,
454                                                   AudioQueueRef inAQ, AudioQueueBufferRef inBuffer)
455 {
456         AQData *d = (AQData *) aqData;
457         OSStatus err;
458
459         int len =
460                 (d->writeBufferByteSize * d->writeAudioFormat.mSampleRate / 1) /
461                 d->devicewriteFormat.mSampleRate /
462                 d->devicewriteFormat.mChannelsPerFrame;
463
464         ms_mutex_lock(&d->mutex);
465         if (d->write_started == FALSE) {
466                 ms_mutex_unlock(&d->mutex);
467                 return;
468         }
469         if (d->bufferizer->size >= len) {
470                 UInt32 bsize = d->writeBufferByteSize;
471                 uint8_t *pData = ms_malloc(len);
472
473                 ms_bufferizer_read(d->bufferizer, pData, len);
474                 err = AudioConverterConvertBuffer(d->writeAudioConverter,
475                                                                                   len,
476                                                                                   pData,
477                                                                                   &bsize, inBuffer->mAudioData);
478                 if (err != noErr) {
479                         ms_error("writeCallback: AudioConverterConvertBuffer %d", err);
480                 }
481                 ms_free(pData);
482
483                 if (bsize != d->writeBufferByteSize)
484                         ms_warning("d->writeBufferByteSize = %i len = %i bsize = %i",
485                                            d->writeBufferByteSize, len, bsize);
486         } else {
487                 memset(inBuffer->mAudioData, 0, d->writeBufferByteSize);
488         }
489         inBuffer->mAudioDataByteSize = d->writeBufferByteSize;
490
491         if (gain_changed_out == true)
492           {
493             AudioQueueSetParameter (d->writeQueue,
494                                     kAudioQueueParam_Volume,
495                                     gain_volume_out);
496             gain_changed_out = false;
497           }
498
499         err = AudioQueueEnqueueBuffer(d->writeQueue, inBuffer, 0, NULL);
500         if (err != noErr) {
501                 ms_error("AudioQueueEnqueueBuffer %d", err);
502         }
503         ms_mutex_unlock(&d->mutex);
504 }
505
506 void putWriteAQ(void *aqData, int queuenum)
507 {
508         AQData *d = (AQData *) aqData;
509         OSStatus err;
510         err = AudioQueueEnqueueBuffer(d->writeQueue,
511                                                                   d->writeBuffers[queuenum], 0, NULL);
512         if (err != noErr) {
513                 ms_error("AudioQueueEnqueueBuffer %d", err);
514         }
515 }
516
517 /*
518  play buffer setup function
519  */
520
521 void setupWrite(MSFilter * f)
522 {
523         AQData *d = (AQData *) f->data;
524         OSStatus err;
525
526         int bufferIndex;
527
528         for (bufferIndex = 0; bufferIndex < kNumberAudioOutDataBuffers;
529                  ++bufferIndex) {
530
531                 err = AudioQueueAllocateBuffer(d->writeQueue,
532                                                                            d->writeBufferByteSize,
533                                                                            &d->writeBuffers[bufferIndex]
534                         );
535                 if (err != noErr) {
536                         ms_error("setupWrite:AudioQueueAllocateBuffer %d", err);
537                 }
538         }
539 }
540
541 /*
542  recode buffer setup function
543  */
544
545 void setupRead(MSFilter * f)
546 {
547         AQData *d = (AQData *) f->data;
548         OSStatus err;
549
550         // allocate and enqueue buffers
551         int bufferIndex;
552
553         for (bufferIndex = 0; bufferIndex < kNumberAudioInDataBuffers;
554                  ++bufferIndex) {
555
556                 AudioQueueBufferRef buffer;
557
558                 err = AudioQueueAllocateBuffer(d->readQueue,
559                                                                            d->readBufferByteSize, &buffer);
560                 if (err != noErr) {
561                         ms_error("setupRead:AudioQueueAllocateBuffer %d", err);
562                 }
563
564                 err = AudioQueueEnqueueBuffer(d->readQueue, buffer, 0, NULL);
565                 if (err != noErr) {
566                         ms_error("AudioQueueEnqueueBuffer %d", err);
567                 }
568         }
569 }
570
571
572 static void aq_start_r(MSFilter * f)
573 {
574         AQData *d = (AQData *) f->data;
575         if (d->read_started == FALSE) {
576                 OSStatus aqresult;
577
578                 d->readAudioFormat.mSampleRate = d->rate;
579                 d->readAudioFormat.mFormatID = kAudioFormatLinearPCM;
580                 d->readAudioFormat.mFormatFlags =
581                         kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked;
582                 d->readAudioFormat.mFramesPerPacket = 1;
583                 d->readAudioFormat.mChannelsPerFrame = 1;
584                 d->readAudioFormat.mBitsPerChannel = d->bits;
585                 d->readAudioFormat.mBytesPerPacket = d->bits / 8;
586                 d->readAudioFormat.mBytesPerFrame = d->bits / 8;
587
588                 //show_format("input device", &d->devicereadFormat);
589                 //show_format("data from input filter", &d->readAudioFormat);
590
591                 memcpy(&d->devicereadFormat, &d->readAudioFormat,
592                            sizeof(d->readAudioFormat));
593                 d->readBufferByteSize =
594                         kSecondsPerBuffer * d->devicereadFormat.mSampleRate *
595                         (d->devicereadFormat.mBitsPerChannel / 8) *
596                         d->devicereadFormat.mChannelsPerFrame;
597
598                 aqresult = AudioConverterNew(&d->devicereadFormat,
599                                                                          &d->readAudioFormat,
600                                                                          &d->readAudioConverter);
601                 if (aqresult != noErr) {
602                         ms_error("d->readAudioConverter = %d", aqresult);
603                         d->readAudioConverter = NULL;
604                 }
605
606                 aqresult = AudioQueueNewInput(&d->devicereadFormat, readCallback, d,    // userData
607                                                                           NULL, // run loop
608                                                                           NULL, // run loop mode
609                                                                           0,    // flags
610                                                                           &d->readQueue);
611                 if (aqresult != noErr) {
612                         ms_error("AudioQueueNewInput = %d", aqresult);
613                 }
614
615                 char uidname[256];
616                 CFStringGetCString(d->uidname, uidname, 256,
617                                                    CFStringGetSystemEncoding());
618                 ms_message("AQ: using uidname:%s", uidname);
619                 aqresult =
620                         AudioQueueSetProperty(d->readQueue,
621                                                                   kAudioQueueProperty_CurrentDevice,
622                                                                   &d->uidname, sizeof(CFStringRef));
623                 if (aqresult != noErr) {
624                         ms_error
625                                 ("AudioQueueSetProperty on kAudioQueueProperty_CurrentDevice %d",
626                                  aqresult);
627                 }
628
629                 setupRead(f);
630                 AudioQueueStart(d->readQueue, NULL      // start time. NULL means ASAP.
631                         );
632                 if (aqresult != noErr) {
633                         ms_error("AudioQueueStart %d", aqresult);
634                 }
635                 d->read_started = TRUE;
636         }
637 }
638
639 static void aq_stop_r(MSFilter * f)
640 {
641         AQData *d = (AQData *) f->data;
642
643         if (d->read_started == TRUE) {
644                 ms_mutex_lock(&d->mutex);
645                 d->read_started = FALSE;        /* avoid a deadlock related to buffer conversion in callback  */
646                 ms_mutex_unlock(&d->mutex);
647                 AudioConverterDispose(d->readAudioConverter);
648                 AudioQueueStop(d->readQueue, true);
649                 AudioQueueDispose(d->readQueue, true);
650         }
651 }
652
653 static void aq_start_w(MSFilter * f)
654 {
655         AQData *d = (AQData *) f->data;
656         if (d->write_started == FALSE) {
657                 OSStatus aqresult;
658
659                 d->writeAudioFormat.mSampleRate = d->rate;
660                 d->writeAudioFormat.mFormatID = kAudioFormatLinearPCM;
661                 d->writeAudioFormat.mFormatFlags =
662                         kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked;
663                 d->writeAudioFormat.mFramesPerPacket = 1;
664                 d->writeAudioFormat.mChannelsPerFrame = 1;
665                 d->writeAudioFormat.mBitsPerChannel = d->bits;
666                 d->writeAudioFormat.mBytesPerPacket = d->bits / 8;
667                 d->writeAudioFormat.mBytesPerFrame = d->bits / 8;
668
669                 //show_format("data provided to output filter", &d->writeAudioFormat);
670                 //show_format("output device", &d->devicewriteFormat);
671
672                 memcpy(&d->devicewriteFormat, &d->writeAudioFormat,
673                            sizeof(d->writeAudioFormat));
674                 d->writeBufferByteSize =
675                         kSecondsPerBuffer * d->devicewriteFormat.mSampleRate *
676                         (d->devicewriteFormat.mBitsPerChannel / 8) *
677                         d->devicewriteFormat.mChannelsPerFrame;
678
679                 aqresult = AudioConverterNew(&d->writeAudioFormat,
680                                                                          &d->devicewriteFormat,
681                                                                          &d->writeAudioConverter);
682                 if (aqresult != noErr) {
683                         ms_error("d->writeAudioConverter = %d", aqresult);
684                         d->writeAudioConverter = NULL;
685                 }
686                 // create the playback audio queue object
687                 aqresult = AudioQueueNewOutput(&d->devicewriteFormat, writeCallback, d, NULL,   /*CFRunLoopGetCurrent () */
688                                                                            NULL,        /*kCFRunLoopCommonModes */
689                                                                            0,   // run loop flags
690                                                                            &d->writeQueue);
691                 if (aqresult != noErr) {
692                         ms_error("AudioQueueNewOutput = %d", aqresult);
693                 }
694
695                 AudioQueueSetParameter (d->writeQueue,
696                                         kAudioQueueParam_Volume,
697                                         gain_volume_out);
698
699                 char uidname[256];
700                 CFStringGetCString(d->uidname, uidname, 256,
701                                                    CFStringGetSystemEncoding());
702                 ms_message("AQ: using uidname:%s", uidname);
703                 aqresult =
704                         AudioQueueSetProperty(d->writeQueue,
705                                                                   kAudioQueueProperty_CurrentDevice,
706                                                                   &d->uidname, sizeof(CFStringRef));
707                 if (aqresult != noErr) {
708                         ms_error
709                                 ("AudioQueueSetProperty on kAudioQueueProperty_CurrentDevice %d",
710                                  aqresult);
711                 }
712                 setupWrite(f);
713                 d->curWriteBuffer = 0;
714         }
715 }
716
717 static void aq_stop_w(MSFilter * f)
718 {
719         AQData *d = (AQData *) f->data;
720         if (d->write_started == TRUE) {
721                 ms_mutex_lock(&d->mutex);
722                 d->write_started = FALSE;       /* avoid a deadlock related to buffer conversion in callback */
723                 ms_mutex_unlock(&d->mutex);
724                 AudioConverterDispose(d->writeAudioConverter);
725                 AudioQueueStop(d->writeQueue, true);
726
727                 AudioQueueDispose(d->writeQueue, true);
728         }
729 }
730
731 static mblk_t *aq_get(MSFilter * f)
732 {
733         AQData *d = (AQData *) f->data;
734         mblk_t *m;
735         ms_mutex_lock(&d->mutex);
736         m = getq(&d->rq);
737         ms_mutex_unlock(&d->mutex);
738         return m;
739 }
740
741 static void aq_put(MSFilter * f, mblk_t * m)
742 {
743         AQData *d = (AQData *) f->data;
744         ms_mutex_lock(&d->mutex);
745         ms_bufferizer_put(d->bufferizer, m);
746         ms_mutex_unlock(&d->mutex);
747
748         int len =
749                 (d->writeBufferByteSize * d->writeAudioFormat.mSampleRate / 1) /
750                 d->devicewriteFormat.mSampleRate /
751                 d->devicewriteFormat.mChannelsPerFrame;
752         if (d->write_started == FALSE && d->bufferizer->size >= len) {
753                 AudioQueueBufferRef curbuf = d->writeBuffers[d->curWriteBuffer];
754                 OSStatus err;
755                 UInt32 bsize = d->writeBufferByteSize;
756                 uint8_t *pData = ms_malloc(len);
757
758                 ms_bufferizer_read(d->bufferizer, pData, len);
759                 err = AudioConverterConvertBuffer(d->writeAudioConverter,
760                                                                                   len,
761                                                                                   pData,
762                                                                                   &bsize, curbuf->mAudioData);
763                 if (err != noErr) {
764                         ms_error("writeCallback: AudioConverterConvertBuffer %d", err);
765                 }
766                 ms_free(pData);
767
768                 if (bsize != d->writeBufferByteSize)
769                         ms_warning("d->writeBufferByteSize = %i len = %i bsize = %i",
770                                            d->writeBufferByteSize, len, bsize);
771
772                 curbuf->mAudioDataByteSize = d->writeBufferByteSize;
773                 putWriteAQ(d, d->curWriteBuffer);
774                 ++d->curWriteBuffer;
775         }
776         if (d->write_started == FALSE
777                 && d->curWriteBuffer == kNumberAudioOutDataBuffers - 1) {
778                 OSStatus err;
779                 err = AudioQueueStart(d->writeQueue, NULL       // start time. NULL means ASAP.
780                         );
781                 if (err != noErr) {
782                         ms_error("AudioQueueStart %d", err);
783                 }
784                 d->write_started = TRUE;
785         }
786 }
787
788 static void aq_init(MSFilter * f)
789 {
790         AQData *d = ms_new(AQData, 1);
791         d->bits = 16;
792         d->rate = 8000;
793         d->stereo = FALSE;
794
795         d->read_started = FALSE;
796         d->write_started = FALSE;
797         qinit(&d->rq);
798         d->bufferizer = ms_bufferizer_new();
799         ms_mutex_init(&d->mutex, NULL);
800         f->data = d;
801 }
802
803 static void aq_uninit(MSFilter * f)
804 {
805         AQData *d = (AQData *) f->data;
806         flushq(&d->rq, 0);
807         ms_bufferizer_destroy(d->bufferizer);
808         ms_mutex_destroy(&d->mutex);
809         if (d->uidname != NULL)
810                 CFRelease(d->uidname);
811         ms_free(d);
812 }
813
814 static void aq_read_preprocess(MSFilter * f)
815 {
816         aq_start_r(f);
817 }
818
819 static void aq_read_postprocess(MSFilter * f)
820 {
821         aq_stop_r(f);
822 }
823
824 static void aq_read_process(MSFilter * f)
825 {
826         mblk_t *m;
827         while ((m = aq_get(f)) != NULL) {
828                 ms_queue_put(f->outputs[0], m);
829         }
830 }
831
832 static void aq_write_preprocess(MSFilter * f)
833 {
834         aq_start_w(f);
835 }
836
837 static void aq_write_postprocess(MSFilter * f)
838 {
839         aq_stop_w(f);
840 }
841
842 static void aq_write_process(MSFilter * f)
843 {
844         mblk_t *m;
845         while ((m = ms_queue_get(f->inputs[0])) != NULL) {
846                 aq_put(f, m);
847         }
848 }
849
850 static int set_rate(MSFilter * f, void *arg)
851 {
852         AQData *d = (AQData *) f->data;
853         d->rate = *((int *) arg);
854         return 0;
855 }
856
857 static int read_get_rate(MSFilter * f, void *arg)
858 {
859         AQData *d = (AQData *) f->data;
860         *((int *) arg) = d->rate;
861         return 0;
862 }
863
864 static int write_get_rate(MSFilter * f, void *arg)
865 {
866         AQData *d = (AQData *) f->data;
867         *((int *) arg) = d->rate;
868         return 0;
869 }
870
871 /*
872 static int set_nchannels(MSFilter *f, void *arg){
873         AQData *d=(AQData*)f->data;
874         d->stereo=(*((int*)arg)==2);
875         return 0;
876 }
877 */
878
879 static MSFilterMethod aq_read_methods[] = {
880         {MS_FILTER_SET_SAMPLE_RATE, set_rate},
881         {MS_FILTER_GET_SAMPLE_RATE, read_get_rate},
882 /* not support yet
883         {       MS_FILTER_SET_NCHANNELS         , set_nchannels },
884 */
885         {0, NULL}
886 };
887
888 MSFilterDesc aq_read_desc = {
889         .id = MS_AQ_READ_ID,
890         .name = "MSAQRead",
891         .text = N_("Sound capture filter for MacOS X Audio Queue Service"),
892         .category = MS_FILTER_OTHER,
893         .ninputs = 0,
894         .noutputs = 1,
895         .init = aq_init,
896         .preprocess = aq_read_preprocess,
897         .process = aq_read_process,
898         .postprocess = aq_read_postprocess,
899         .uninit = aq_uninit,
900         .methods = aq_read_methods
901 };
902
903 static MSFilterMethod aq_write_methods[] = {
904         {MS_FILTER_SET_SAMPLE_RATE, set_rate},
905         {MS_FILTER_GET_SAMPLE_RATE, write_get_rate},
906 /* not support yet
907         {       MS_FILTER_SET_NCHANNELS         , set_nchannels },
908 */
909         {0, NULL}
910 };
911
912 MSFilterDesc aq_write_desc = {
913         .id = MS_AQ_WRITE_ID,
914         .name = "MSAQWrite",
915         .text = N_("Sound playback filter for MacOS X Audio Queue Service"),
916         .category = MS_FILTER_OTHER,
917         .ninputs = 1,
918         .noutputs = 0,
919         .init = aq_init,
920         .preprocess = aq_write_preprocess,
921         .process = aq_write_process,
922         .postprocess = aq_write_postprocess,
923         .uninit = aq_uninit,
924         .methods = aq_write_methods
925 };
926
927 MSFilter *ms_aq_read_new(MSSndCard * card)
928 {
929         MSFilter *f = ms_filter_new_from_desc(&aq_read_desc);
930         AqSndDsCard *wc = (AqSndDsCard *) card->data;
931         AQData *d = (AQData *) f->data;
932         d->uidname = CFStringCreateCopy(NULL, wc->uidname);
933         memcpy(&d->devicereadFormat, &wc->devicereadFormat,
934                    sizeof(AudioStreamBasicDescription));
935         memcpy(&d->devicewriteFormat, &wc->devicewriteFormat,
936                    sizeof(AudioStreamBasicDescription));
937         return f;
938 }
939
940
941 MSFilter *ms_aq_write_new(MSSndCard * card)
942 {
943         MSFilter *f = ms_filter_new_from_desc(&aq_write_desc);
944         AqSndDsCard *wc = (AqSndDsCard *) card->data;
945         AQData *d = (AQData *) f->data;
946         d->uidname = CFStringCreateCopy(NULL, wc->uidname);
947         memcpy(&d->devicereadFormat, &wc->devicereadFormat,
948                    sizeof(AudioStreamBasicDescription));
949         memcpy(&d->devicewriteFormat, &wc->devicewriteFormat,
950                    sizeof(AudioStreamBasicDescription));
951         return f;
952 }
953
954 MS_FILTER_DESC_EXPORT(aq_read_desc)
955 MS_FILTER_DESC_EXPORT(aq_write_desc)