source: mediastreamer2/src/aqsnd.c @ 1086:8d3b60579ec2

Last change on this file since 1086:8d3b60579ec2 was 1086:8d3b60579ec2, checked in by laurent, 2 years ago

bug fix : set/get audio/video device

File size: 28.6 KB
Line 
1/*
2mediastreamer2 library - modular sound and video processing and streaming
3Copyright (C) 2006  Simon MORLAT (simon.morlat@linphone.org)
4
5This program is free software; you can redistribute it and/or
6modify it under the terms of the GNU General Public License
7as published by the Free Software Foundation; either version 2
8of the License, or (at your option) any later version.
9
10This program is distributed in the hope that it will be useful,
11but WITHOUT ANY WARRANTY; without even the implied warranty of
12MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13GNU General Public License for more details.
14
15You should have received a copy of the GNU General Public License
16along with this program; if not, write to the Free Software
17Foundation, 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#ifdef __APPLE__
56#include "TargetConditionals.h"
57#endif
58
59#include <AudioToolbox/AudioToolbox.h>
60#ifndef TARGET_OS_IPHONE
61#include <CoreAudio/AudioHardware.h>
62#endif
63
64#include "mediastreamer2/mssndcard.h"
65#include "mediastreamer2/msfilter.h"
66
67MSFilter *ms_aq_read_new(MSSndCard * card);
68MSFilter *ms_aq_write_new(MSSndCard * card);
69
70#define kSecondsPerBuffer               0.02    /*0.04 */
71#define kNumberAudioOutDataBuffers      4
72#define kNumberAudioInDataBuffers       4
73
74static float gain_volume_in=1.0;
75static float gain_volume_out=1.0;
76static bool gain_changed_in = true;
77static bool gain_changed_out = true;
78
79#ifdef TARGET_OS_IPHONE
80#define CFStringRef void *
81#define CFRelease(A) {}
82#define CFStringGetCString(A, B, LEN, encoding)  {}
83#define CFStringCreateCopy(A, B) NULL
84#endif
85
86typedef struct AQData {
87        CFStringRef uidname;
88        AudioStreamBasicDescription devicereadFormat;
89        AudioStreamBasicDescription devicewriteFormat;
90
91        int rate;
92        int bits;
93        bool_t stereo;
94
95        ms_mutex_t mutex;
96        queue_t rq;
97        bool_t read_started;
98        bool_t write_started;
99#if 0
100        AudioConverterRef readAudioConverter;
101#endif
102        AudioQueueRef readQueue;
103        AudioStreamBasicDescription readAudioFormat;
104        UInt32 readBufferByteSize;
105
106#if 0
107        AudioConverterRef writeAudioConverter;
108#endif
109        AudioQueueRef writeQueue;
110        AudioStreamBasicDescription writeAudioFormat;
111        UInt32 writeBufferByteSize;
112        AudioQueueBufferRef writeBuffers[kNumberAudioOutDataBuffers];
113        int curWriteBuffer;
114        MSBufferizer *bufferizer;
115} AQData;
116
117
118
119/*
120 mediastreamer2 function
121 */
122
123typedef struct AqSndDsCard {
124        CFStringRef uidname;
125        AudioStreamBasicDescription devicereadFormat;
126        AudioStreamBasicDescription devicewriteFormat;
127        int removed;
128} AqSndDsCard;
129
130static void aqcard_set_level(MSSndCard * card, MSSndCardMixerElem e,
131                                                         int percent)
132{
133        switch(e){
134                case MS_SND_CARD_PLAYBACK:
135                case MS_SND_CARD_MASTER:
136                        gain_volume_out =((float)percent)/100.0f;
137                        gain_changed_out = true;
138                        return;
139                case MS_SND_CARD_CAPTURE:
140                        gain_volume_in =((float)percent)/100.0f;
141                        gain_changed_in = true;
142                        return;
143                default:
144                        ms_warning("aqcard_set_level: unsupported command.");
145        }
146}
147
148static int aqcard_get_level(MSSndCard * card, MSSndCardMixerElem e)
149{
150        switch(e){
151                case MS_SND_CARD_PLAYBACK:
152                case MS_SND_CARD_MASTER:
153                  return (int)(gain_volume_out*100.0f);
154                case MS_SND_CARD_CAPTURE:
155                  return (int)(gain_volume_in*100.0f);
156                default:
157                        ms_warning("aqcard_get_level: unsupported command.");
158        }
159        return -1;
160}
161
162static void aqcard_set_source(MSSndCard * card, MSSndCardCapture source)
163{
164}
165
166static void aqcard_init(MSSndCard * card)
167{
168        AqSndDsCard *c = (AqSndDsCard *) ms_new0(AqSndDsCard, 1);
169        c->removed = 0;
170        card->data = c;
171}
172
173static void aqcard_uninit(MSSndCard * card)
174{
175        AqSndDsCard *d = (AqSndDsCard *) card->data;
176        if (d->uidname != NULL)
177                CFRelease(d->uidname);
178        ms_free(d);
179}
180
181static void aqcard_detect(MSSndCardManager * m);
182static MSSndCard *aqcard_duplicate(MSSndCard * obj);
183
184MSSndCardDesc aq_card_desc = {
185        .driver_type = "AQ",
186        .detect = aqcard_detect,
187        .init = aqcard_init,
188        .set_level = aqcard_set_level,
189        .get_level = aqcard_get_level,
190        .set_capture = aqcard_set_source,
191        .set_control = NULL,
192        .get_control = NULL,
193        .create_reader = ms_aq_read_new,
194        .create_writer = ms_aq_write_new,
195        .uninit = aqcard_uninit,
196        .duplicate = aqcard_duplicate
197};
198
199static MSSndCard *aqcard_duplicate(MSSndCard * obj)
200{
201        AqSndDsCard *ca;
202        AqSndDsCard *cadup;
203        MSSndCard *card = ms_snd_card_new(&aq_card_desc);
204        card->name = ms_strdup(obj->name);
205        card->data = ms_new0(AqSndDsCard, 1);
206        memcpy(card->data, obj->data, sizeof(AqSndDsCard));
207        ca = obj->data;
208        cadup = card->data;
209        cadup->uidname = CFStringCreateCopy(NULL, ca->uidname);
210        return card;
211}
212
213static MSSndCard *aq_card_new(const char *name, CFStringRef uidname,
214                                                          AudioStreamBasicDescription *
215                                                          devicereadFormat,
216                                                          AudioStreamBasicDescription *
217                                                          devicewriteFormat, unsigned cap)
218{
219        MSSndCard *card = ms_snd_card_new(&aq_card_desc);
220        AqSndDsCard *d = (AqSndDsCard *) card->data;
221        d->uidname = uidname;
222        if (devicereadFormat!=NULL)
223          memcpy(&d->devicereadFormat, devicereadFormat,
224                 sizeof(AudioStreamBasicDescription));
225        if (devicewriteFormat!=NULL)
226          memcpy(&d->devicewriteFormat, devicewriteFormat,
227                 sizeof(AudioStreamBasicDescription));
228        card->name = ms_strdup(name);
229        card->capabilities = cap;
230        return card;
231}
232
233static void show_format(char *name,
234                                                AudioStreamBasicDescription * deviceFormat)
235{
236        ms_message("Format for %s", name);
237        ms_message("mSampleRate = %g", deviceFormat->mSampleRate);
238        char *the4CCString = (char *) &deviceFormat->mFormatID;
239        char outName[5];
240        outName[0] = the4CCString[0];
241        outName[1] = the4CCString[1];
242        outName[2] = the4CCString[2];
243        outName[3] = the4CCString[3];
244        outName[4] = 0;
245        ms_message("mFormatID = %s", outName);
246        ms_message("mFormatFlags = %08lX", deviceFormat->mFormatFlags);
247        ms_message("mBytesPerPacket = %ld", deviceFormat->mBytesPerPacket);
248        ms_message("mFramesPerPacket = %ld", deviceFormat->mFramesPerPacket);
249        ms_message("mChannelsPerFrame = %ld", deviceFormat->mChannelsPerFrame);
250        ms_message("mBytesPerFrame = %ld", deviceFormat->mBytesPerFrame);
251        ms_message("mBitsPerChannel = %ld", deviceFormat->mBitsPerChannel);
252}
253
254static void aqcard_detect(MSSndCardManager * m)
255{
256#if TARGET_OS_IPHONE
257
258        AudioStreamBasicDescription deviceFormat;
259        memset(&deviceFormat, 0, sizeof(AudioStreamBasicDescription));
260       
261        MSSndCard *card = aq_card_new("Audio Queue Device", NULL, &deviceFormat,
262                                                                  &deviceFormat, MS_SND_CARD_CAP_PLAYBACK|MS_SND_CARD_CAP_CAPTURE);
263        ms_snd_card_manager_add_card(m, card);
264#else
265
266        OSStatus err;
267        UInt32 slen;
268        int count;
269        Boolean writable;
270        int i;
271        writable = 0;
272        slen = 0;
273        err =
274                AudioHardwareGetPropertyInfo(kAudioHardwarePropertyDevices, &slen,
275                                                                         &writable);
276        if (err != kAudioHardwareNoError) {
277                ms_error("get kAudioHardwarePropertyDevices error %ld", err);
278                return;
279        }
280        AudioDeviceID V[slen / sizeof(AudioDeviceID)];
281        err =
282                AudioHardwareGetProperty(kAudioHardwarePropertyDevices, &slen, V);
283        if (err != kAudioHardwareNoError) {
284                ms_error("get kAudioHardwarePropertyDevices error %ld", err);
285                return;
286        }
287        count = slen / sizeof(AudioDeviceID);
288        for (i = 0; i < count; i++) {
289                char devname_in[256];
290                char uidname_in[256];
291                char devname_out[256];
292                char uidname_out[256];
293                int cap = 0;
294
295                /* OUTPUT CARDS */
296                slen = 256;
297                err =
298                        AudioDeviceGetProperty(V[i], 0, FALSE,
299                                                                   kAudioDevicePropertyDeviceName, &slen,
300                                                                   devname_out);
301                if (err != kAudioHardwareNoError) {
302                        ms_error("get kAudioDevicePropertyDeviceName error %ld", err);
303                        continue;
304                }
305                slen = strlen(devname_out);
306                /* trim whitespace */
307                while ((slen > 0) && (devname_out[slen - 1] == ' ')) {
308                        slen--;
309                }
310                devname_out[slen] = '\0';
311
312                err =
313                        AudioDeviceGetPropertyInfo(V[i], 0, FALSE,
314                                                                           kAudioDevicePropertyStreamConfiguration,
315                                                                           &slen, &writable);
316                if (err != kAudioHardwareNoError) {
317                        ms_error("get kAudioDevicePropertyDeviceName error %ld", err);
318                        continue;
319                }
320
321                AudioBufferList *buflist = ms_malloc(slen);
322                if (buflist == NULL) {
323                        ms_error("alloc AudioBufferList %ld", err);
324                        continue;
325                }
326
327                err =
328                        AudioDeviceGetProperty(V[i], 0, FALSE,
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                UInt32 j;
338                for (j = 0; j < buflist->mNumberBuffers; j++) {
339                        if (buflist->mBuffers[j].mNumberChannels > 0) {
340                                cap = MS_SND_CARD_CAP_PLAYBACK;
341                                break;
342                        }
343                }
344
345                ms_free(buflist);
346
347                /* INPUT CARDS */
348                slen = 256;
349                err =
350                        AudioDeviceGetProperty(V[i], 0, TRUE,
351                                                                   kAudioDevicePropertyDeviceName, &slen,
352                                                                   devname_in);
353                if (err != kAudioHardwareNoError) {
354                        ms_error("get kAudioDevicePropertyDeviceName error %ld", err);
355                        continue;
356                }
357                slen = strlen(devname_in);
358                /* trim whitespace */
359                while ((slen > 0) && (devname_in[slen - 1] == ' ')) {
360                        slen--;
361                }
362                devname_in[slen] = '\0';
363
364                err =
365                        AudioDeviceGetPropertyInfo(V[i], 0, TRUE,
366                                                                           kAudioDevicePropertyStreamConfiguration,
367                                                                           &slen, &writable);
368                if (err != kAudioHardwareNoError) {
369                        ms_error("get kAudioDevicePropertyDeviceName error %ld", err);
370                        continue;
371                }
372
373
374                err =
375                        AudioDeviceGetPropertyInfo(V[i], 0, TRUE,
376                                                                           kAudioDevicePropertyStreamConfiguration,
377                                                                           &slen, &writable);
378                if (err != kAudioHardwareNoError) {
379                        ms_error("get kAudioDevicePropertyDeviceName error %ld", err);
380                        continue;
381                }
382                buflist = ms_malloc(slen);
383                if (buflist == NULL) {
384                        ms_error("alloc error %ld", err);
385                        continue;
386                }
387
388                err =
389                        AudioDeviceGetProperty(V[i], 0, TRUE,
390                                                                   kAudioDevicePropertyStreamConfiguration,
391                                                                   &slen, buflist);
392                if (err != kAudioHardwareNoError) {
393                        ms_error("get kAudioDevicePropertyDeviceName error %ld", err);
394                        ms_free(buflist);
395                        continue;
396                }
397
398                for (j = 0; j < buflist->mNumberBuffers; j++) {
399                        if (buflist->mBuffers[j].mNumberChannels > 0) {
400                                cap |= MS_SND_CARD_CAP_CAPTURE;
401                                break;
402                        }
403                }
404
405                ms_free(buflist);
406
407                if (cap & MS_SND_CARD_CAP_PLAYBACK) {
408                  CFStringRef dUID_out;
409                  dUID_out = NULL;
410                  slen = sizeof(CFStringRef);
411                  err =
412                    AudioDeviceGetProperty(V[i], 0, false,
413                                           kAudioDevicePropertyDeviceUID, &slen,
414                                           &dUID_out);
415                  if (err != kAudioHardwareNoError) {
416                    ms_error("get kAudioHardwarePropertyDevices error %ld", err);
417                    continue;
418                  }
419                  CFStringGetCString(dUID_out, uidname_out, 256,
420                                     CFStringGetSystemEncoding());
421                  ms_message("AQ: devname_out:%s uidname_out:%s", devname_out, uidname_out);
422
423                  AudioStreamBasicDescription devicewriteFormat;
424                  slen = sizeof(devicewriteFormat);
425                  err = AudioDeviceGetProperty(V[i], 0, false,
426                                               kAudioDevicePropertyStreamFormat,
427                                               &slen, &devicewriteFormat);
428                  if (err == kAudioHardwareNoError) {
429                    show_format("output device", &devicewriteFormat);
430                  }
431                  MSSndCard *card = aq_card_new(devname_out, dUID_out, NULL,
432                                                &devicewriteFormat, MS_SND_CARD_CAP_PLAYBACK);
433                  ms_snd_card_manager_add_card(m, card);
434                }
435
436                if (cap & MS_SND_CARD_CAP_CAPTURE) {
437                  CFStringRef dUID_in;
438                  dUID_in = NULL;
439                  slen = sizeof(CFStringRef);
440                  err =
441                    AudioDeviceGetProperty(V[i], 0, true,
442                                           kAudioDevicePropertyDeviceUID, &slen,
443                                           &dUID_in);
444                  if (err != kAudioHardwareNoError) {
445                    ms_error("get kAudioHardwarePropertyDevices error %ld", err);
446                    continue;
447                  }
448                  CFStringGetCString(dUID_in, uidname_in, 256,
449                                     CFStringGetSystemEncoding());
450                  ms_message("AQ: devname_in:%s uidname_in:%s", devname_in, uidname_in);
451                 
452                  AudioStreamBasicDescription devicereadFormat;
453                  slen = sizeof(devicereadFormat);
454                  err = AudioDeviceGetProperty(V[i], 0, true,
455                                               kAudioDevicePropertyStreamFormat,
456                                               &slen, &devicereadFormat);
457                  if (err == kAudioHardwareNoError) {
458                    show_format("input device", &devicereadFormat);
459                  }
460                  MSSndCard *card = aq_card_new(devname_in, dUID_in, &devicereadFormat,
461                                                NULL, MS_SND_CARD_CAP_CAPTURE);
462                  ms_snd_card_manager_add_card(m, card);
463                }
464        }
465#endif
466}
467
468
469/*
470 Audio Queue recode callback
471 */
472
473static void readCallback(void *aqData,
474                                                 AudioQueueRef inAQ,
475                                                 AudioQueueBufferRef inBuffer,
476                                                 const AudioTimeStamp * inStartTime,
477                                                 UInt32 inNumPackets,
478                                                 const AudioStreamPacketDescription * inPacketDesc)
479{
480        AQData *d = (AQData *) aqData;
481        OSStatus err;
482        mblk_t *rm = NULL;
483
484        UInt32 len =
485                (inBuffer->mAudioDataByteSize * d->readAudioFormat.mSampleRate /
486                 1) / d->devicereadFormat.mSampleRate /
487                d->devicereadFormat.mChannelsPerFrame;
488
489        ms_mutex_lock(&d->mutex);
490        if (d->read_started == FALSE) {
491                ms_mutex_unlock(&d->mutex);
492                return;
493        }
494
495        rm = allocb(len, 0);
496
497#if 0
498        err = AudioConverterConvertBuffer(d->readAudioConverter,
499                                                                          inBuffer->mAudioDataByteSize,
500                                                                          inBuffer->mAudioData,
501                                                                          &len, rm->b_wptr);
502        if (err != noErr) {
503                ms_error("readCallback: AudioConverterConvertBuffer %d", err);
504                ms_warning("readCallback: inBuffer->mAudioDataByteSize = %d",
505                                   inBuffer->mAudioDataByteSize);
506                ms_warning("readCallback: outlen = %d", len);
507                ms_warning("readCallback: origlen = %i",
508                                   (inBuffer->mAudioDataByteSize *
509                                        d->readAudioFormat.mSampleRate / 1) /
510                                   d->devicereadFormat.mSampleRate /
511                                   d->devicereadFormat.mChannelsPerFrame);
512                freeb(rm);
513        } else {
514
515          rm->b_wptr += len;
516          if (gain_volume_in != 1.0f)
517            {
518              int16_t *ptr=(int16_t *)rm->b_rptr;
519              for (;ptr<(int16_t *)rm->b_wptr;ptr++)
520                {
521                  *ptr=(int16_t)(((float)(*ptr))*gain_volume_in);
522                }
523            }
524          putq(&d->rq, rm);
525        }
526#else
527        memcpy(rm->b_wptr, inBuffer->mAudioData, len);
528        rm->b_wptr += len;
529        if (gain_volume_in != 1.0f)
530        {
531                int16_t *ptr=(int16_t *)rm->b_rptr;
532                for (;ptr<(int16_t *)rm->b_wptr;ptr++)
533                {
534                        *ptr=(int16_t)(((float)(*ptr))*gain_volume_in);
535                }
536        }
537        putq(&d->rq, rm);       
538#endif
539       
540        err = AudioQueueEnqueueBuffer(d->readQueue, inBuffer, 0, NULL);
541        if (err != noErr) {
542                ms_error("readCallback:AudioQueueEnqueueBuffer %d", err);
543        }
544        ms_mutex_unlock(&d->mutex);
545}
546
547/*
548 Audio Queue play callback
549 */
550
551static void writeCallback(void *aqData,
552                                                  AudioQueueRef inAQ, AudioQueueBufferRef inBuffer)
553{
554        AQData *d = (AQData *) aqData;
555        OSStatus err;
556
557        int len =
558                (d->writeBufferByteSize * d->writeAudioFormat.mSampleRate / 1) /
559                d->devicewriteFormat.mSampleRate /
560                d->devicewriteFormat.mChannelsPerFrame;
561
562        ms_mutex_lock(&d->mutex);
563        if (d->write_started == FALSE) {
564                ms_mutex_unlock(&d->mutex);
565                return;
566        }
567        if (d->bufferizer->size >= len) {
568#if 0
569                UInt32 bsize = d->writeBufferByteSize;
570                uint8_t *pData = ms_malloc(len);
571
572                ms_bufferizer_read(d->bufferizer, pData, len);
573                err = AudioConverterConvertBuffer(d->writeAudioConverter,
574                                                                                  len,
575                                                                                  pData,
576                                                                                  &bsize, inBuffer->mAudioData);
577                if (err != noErr) {
578                        ms_error("writeCallback: AudioConverterConvertBuffer %d", err);
579                }
580                ms_free(pData);
581
582                if (bsize != d->writeBufferByteSize)
583                        ms_warning("d->writeBufferByteSize = %i len = %i bsize = %i",
584                                           d->writeBufferByteSize, len, bsize);
585#else
586                ms_bufferizer_read(d->bufferizer, inBuffer->mAudioData, len);
587#endif
588        } else {
589                memset(inBuffer->mAudioData, 0, d->writeBufferByteSize);
590        }
591        inBuffer->mAudioDataByteSize = d->writeBufferByteSize;
592
593        if (gain_changed_out == true)
594          {
595            AudioQueueSetParameter (d->writeQueue,
596                                    kAudioQueueParam_Volume,
597                                    gain_volume_out);
598            gain_changed_out = false;
599          }
600
601        err = AudioQueueEnqueueBuffer(d->writeQueue, inBuffer, 0, NULL);
602        if (err != noErr) {
603                ms_error("AudioQueueEnqueueBuffer %d", err);
604        }
605        ms_mutex_unlock(&d->mutex);
606}
607
608void putWriteAQ(void *aqData, int queuenum)
609{
610        AQData *d = (AQData *) aqData;
611        OSStatus err;
612        err = AudioQueueEnqueueBuffer(d->writeQueue,
613                                                                  d->writeBuffers[queuenum], 0, NULL);
614        if (err != noErr) {
615                ms_error("AudioQueueEnqueueBuffer %d", err);
616        }
617}
618
619/*
620 play buffer setup function
621 */
622
623void setupWrite(MSFilter * f)
624{
625        AQData *d = (AQData *) f->data;
626        OSStatus err;
627
628        int bufferIndex;
629
630        for (bufferIndex = 0; bufferIndex < kNumberAudioOutDataBuffers;
631                 ++bufferIndex) {
632
633                err = AudioQueueAllocateBuffer(d->writeQueue,
634                                                                           d->writeBufferByteSize,
635                                                                           &d->writeBuffers[bufferIndex]
636                        );
637                if (err != noErr) {
638                        ms_error("setupWrite:AudioQueueAllocateBuffer %d", err);
639                }
640        }
641}
642
643/*
644 recode buffer setup function
645 */
646
647void setupRead(MSFilter * f)
648{
649        AQData *d = (AQData *) f->data;
650        OSStatus err;
651
652        // allocate and enqueue buffers
653        int bufferIndex;
654
655        for (bufferIndex = 0; bufferIndex < kNumberAudioInDataBuffers;
656                 ++bufferIndex) {
657
658                AudioQueueBufferRef buffer;
659
660                err = AudioQueueAllocateBuffer(d->readQueue,
661                                                                           d->readBufferByteSize, &buffer);
662                if (err != noErr) {
663                        ms_error("setupRead:AudioQueueAllocateBuffer %d", err);
664                }
665
666                err = AudioQueueEnqueueBuffer(d->readQueue, buffer, 0, NULL);
667                if (err != noErr) {
668                        ms_error("AudioQueueEnqueueBuffer %d", err);
669                }
670        }
671}
672
673
674static void aq_start_r(MSFilter * f)
675{
676        AQData *d = (AQData *) f->data;
677        if (d->read_started == FALSE) {
678                OSStatus aqresult;
679
680                d->readAudioFormat.mSampleRate = d->rate;
681                d->readAudioFormat.mFormatID = kAudioFormatLinearPCM;
682                d->readAudioFormat.mFormatFlags =
683                        kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked;
684                d->readAudioFormat.mFramesPerPacket = 1;
685                d->readAudioFormat.mChannelsPerFrame = 1;
686                d->readAudioFormat.mBitsPerChannel = d->bits;
687                d->readAudioFormat.mBytesPerPacket = d->bits / 8;
688                d->readAudioFormat.mBytesPerFrame = d->bits / 8;
689
690                //show_format("input device", &d->devicereadFormat);
691                //show_format("data from input filter", &d->readAudioFormat);
692
693                memcpy(&d->devicereadFormat, &d->readAudioFormat,
694                           sizeof(d->readAudioFormat));
695                d->readBufferByteSize =
696                        kSecondsPerBuffer * d->devicereadFormat.mSampleRate *
697                        (d->devicereadFormat.mBitsPerChannel / 8) *
698                        d->devicereadFormat.mChannelsPerFrame;
699
700#if 0
701                aqresult = AudioConverterNew(&d->devicereadFormat,
702                                                                         &d->readAudioFormat,
703                                                                         &d->readAudioConverter);
704                if (aqresult != noErr) {
705                        ms_error("d->readAudioConverter = %d", aqresult);
706                        d->readAudioConverter = NULL;
707                }
708#endif
709               
710                aqresult = AudioQueueNewInput(&d->devicereadFormat, readCallback, d,    // userData
711                                                                          NULL, // run loop
712                                                                          NULL, // run loop mode
713                                                                          0,    // flags
714                                                                          &d->readQueue);
715                if (aqresult != noErr) {
716                        ms_error("AudioQueueNewInput = %d", aqresult);
717                }
718
719                if (d->uidname!=NULL){
720                        char uidname[256];
721                        CFStringGetCString(d->uidname, uidname, 256,
722                                                           CFStringGetSystemEncoding());
723                        ms_message("AQ: using uidname:%s", uidname);
724                        aqresult =
725                                AudioQueueSetProperty(d->readQueue,
726                                                                  kAudioQueueProperty_CurrentDevice,
727                                                                  &d->uidname, sizeof(CFStringRef));
728                        if (aqresult != noErr) {
729                                ms_error
730                                        ("AudioQueueSetProperty on kAudioQueueProperty_CurrentDevice %d",
731                                         aqresult);
732                        }
733                }
734
735                setupRead(f);
736                aqresult = AudioQueueStart(d->readQueue, NULL); // start time. NULL means ASAP.
737                if (aqresult != noErr) {
738                        ms_error("AudioQueueStart -read- %d", aqresult);
739                }
740                d->read_started = TRUE;
741        }
742}
743
744static void aq_stop_r(MSFilter * f)
745{
746        AQData *d = (AQData *) f->data;
747
748        if (d->read_started == TRUE) {
749                ms_mutex_lock(&d->mutex);
750                d->read_started = FALSE;        /* avoid a deadlock related to buffer conversion in callback  */
751                ms_mutex_unlock(&d->mutex);
752#if 0
753                AudioConverterDispose(d->readAudioConverter);
754#endif
755                AudioQueueStop(d->readQueue, true);
756                AudioQueueDispose(d->readQueue, true);
757        }
758}
759
760static void aq_start_w(MSFilter * f)
761{
762        AQData *d = (AQData *) f->data;
763        if (d->write_started == FALSE) {
764                OSStatus aqresult;
765
766                d->writeAudioFormat.mSampleRate = d->rate;
767                d->writeAudioFormat.mFormatID = kAudioFormatLinearPCM;
768                d->writeAudioFormat.mFormatFlags =
769                        kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked;
770                d->writeAudioFormat.mFramesPerPacket = 1;
771                d->writeAudioFormat.mChannelsPerFrame = 1;
772                d->writeAudioFormat.mBitsPerChannel = d->bits;
773                d->writeAudioFormat.mBytesPerPacket = d->bits / 8;
774                d->writeAudioFormat.mBytesPerFrame = d->bits / 8;
775
776                show_format("data provided to output filter",   &d->writeAudioFormat);
777                show_format("output device", &d->devicewriteFormat);
778
779                memcpy(&d->devicewriteFormat, &d->writeAudioFormat,
780                           sizeof(d->writeAudioFormat));
781                d->writeBufferByteSize =
782                        kSecondsPerBuffer * d->devicewriteFormat.mSampleRate *
783                        (d->devicewriteFormat.mBitsPerChannel / 8) *
784                        d->devicewriteFormat.mChannelsPerFrame;
785
786#if 0
787                aqresult = AudioConverterNew(&d->writeAudioFormat,
788                                                                         &d->devicewriteFormat,
789                                                                         &d->writeAudioConverter);
790                if (aqresult != noErr) {
791                        ms_error("d->writeAudioConverter = %d", aqresult);
792                        d->writeAudioConverter = NULL;
793                }
794#endif
795               
796                // create the playback audio queue object
797                aqresult = AudioQueueNewOutput(&d->devicewriteFormat, writeCallback, d, NULL,   /*CFRunLoopGetCurrent () */
798                                                                           NULL,        /*kCFRunLoopCommonModes */
799                                                                           0,   // run loop flags
800                                                                           &d->writeQueue);
801                if (aqresult != noErr) {
802                        ms_error("AudioQueueNewOutput = %d", aqresult);
803                }
804
805                AudioQueueSetParameter (d->writeQueue,
806                                        kAudioQueueParam_Volume,
807                                        gain_volume_out);
808
809                if (d->uidname!=NULL){
810                        char uidname[256];
811                        CFStringGetCString(d->uidname, uidname, 256,
812                                                           CFStringGetSystemEncoding());
813                        ms_message("AQ: using uidname:%s", uidname);
814                        aqresult =
815                                AudioQueueSetProperty(d->writeQueue,
816                                                                          kAudioQueueProperty_CurrentDevice,
817                                                                          &d->uidname, sizeof(CFStringRef));
818                        if (aqresult != noErr) {
819                                ms_error
820                                        ("AudioQueueSetProperty on kAudioQueueProperty_CurrentDevice %d",
821                                         aqresult);
822                        }
823                }
824
825                setupWrite(f);
826                d->curWriteBuffer = 0;
827        }
828}
829
830static void aq_stop_w(MSFilter * f)
831{
832        AQData *d = (AQData *) f->data;
833        if (d->write_started == TRUE) {
834                ms_mutex_lock(&d->mutex);
835                d->write_started = FALSE;       /* avoid a deadlock related to buffer conversion in callback */
836                ms_mutex_unlock(&d->mutex);
837#if 0
838                AudioConverterDispose(d->writeAudioConverter);
839#endif
840                AudioQueueStop(d->writeQueue, true);
841
842                AudioQueueDispose(d->writeQueue, true);
843        }
844}
845
846static mblk_t *aq_get(MSFilter * f)
847{
848        AQData *d = (AQData *) f->data;
849        mblk_t *m;
850        ms_mutex_lock(&d->mutex);
851        m = getq(&d->rq);
852        ms_mutex_unlock(&d->mutex);
853        return m;
854}
855
856static void aq_put(MSFilter * f, mblk_t * m)
857{
858        AQData *d = (AQData *) f->data;
859        ms_mutex_lock(&d->mutex);
860        ms_bufferizer_put(d->bufferizer, m);
861        ms_mutex_unlock(&d->mutex);
862
863        int len =
864                (d->writeBufferByteSize * d->writeAudioFormat.mSampleRate / 1) /
865                d->devicewriteFormat.mSampleRate /
866                d->devicewriteFormat.mChannelsPerFrame;
867        if (d->write_started == FALSE && d->bufferizer->size >= len) {
868                AudioQueueBufferRef curbuf = d->writeBuffers[d->curWriteBuffer];
869#if 0
870                OSStatus err;
871                UInt32 bsize = d->writeBufferByteSize;
872                uint8_t *pData = ms_malloc(len);
873
874                ms_bufferizer_read(d->bufferizer, pData, len);
875                err = AudioConverterConvertBuffer(d->writeAudioConverter,
876                                                                                  len,
877                                                                                  pData,
878                                                                                  &bsize, curbuf->mAudioData);
879                if (err != noErr) {
880                        ms_error("writeCallback: AudioConverterConvertBuffer %d", err);
881                }
882                ms_free(pData);
883
884                if (bsize != d->writeBufferByteSize)
885                        ms_warning("d->writeBufferByteSize = %i len = %i bsize = %i",
886                                           d->writeBufferByteSize, len, bsize);
887#else
888                ms_bufferizer_read(d->bufferizer, curbuf->mAudioData, len);
889#endif
890                curbuf->mAudioDataByteSize = d->writeBufferByteSize;
891                putWriteAQ(d, d->curWriteBuffer);
892                ++d->curWriteBuffer;
893        }
894        if (d->write_started == FALSE
895                && d->curWriteBuffer == kNumberAudioOutDataBuffers - 1) {
896                OSStatus err;
897                err = AudioQueueStart(d->writeQueue, NULL       // start time. NULL means ASAP.
898                        );
899                if (err != noErr) {
900                        ms_error("AudioQueueStart -write- %d", err);
901                }
902                d->write_started = TRUE;
903
904        }
905}
906
907static void aq_init(MSFilter * f)
908{
909        AQData *d = ms_new(AQData, 1);
910        d->bits = 16;
911        d->rate = 8000;
912        d->stereo = FALSE;
913
914        d->read_started = FALSE;
915        d->write_started = FALSE;
916        qinit(&d->rq);
917        d->bufferizer = ms_bufferizer_new();
918        ms_mutex_init(&d->mutex, NULL);
919        f->data = d;
920}
921
922static void aq_uninit(MSFilter * f)
923{
924        AQData *d = (AQData *) f->data;
925        flushq(&d->rq, 0);
926        ms_bufferizer_destroy(d->bufferizer);
927        ms_mutex_destroy(&d->mutex);
928        if (d->uidname != NULL)
929                CFRelease(d->uidname);
930        ms_free(d);
931}
932
933static void aq_read_preprocess(MSFilter * f)
934{
935        aq_start_r(f);
936}
937
938static void aq_read_postprocess(MSFilter * f)
939{
940        aq_stop_r(f);
941}
942
943static void aq_read_process(MSFilter * f)
944{
945        mblk_t *m;
946        while ((m = aq_get(f)) != NULL) {
947                ms_queue_put(f->outputs[0], m);
948        }
949}
950
951static void aq_write_preprocess(MSFilter * f)
952{
953        aq_start_w(f);
954}
955
956static void aq_write_postprocess(MSFilter * f)
957{
958        aq_stop_w(f);
959}
960
961static void aq_write_process(MSFilter * f)
962{
963        mblk_t *m;
964        while ((m = ms_queue_get(f->inputs[0])) != NULL) {
965                aq_put(f, m);
966        }
967}
968
969static int set_rate(MSFilter * f, void *arg)
970{
971        AQData *d = (AQData *) f->data;
972        d->rate = *((int *) arg);
973        return 0;
974}
975
976static int read_get_rate(MSFilter * f, void *arg)
977{
978        AQData *d = (AQData *) f->data;
979        *((int *) arg) = d->rate;
980        return 0;
981}
982
983static int write_get_rate(MSFilter * f, void *arg)
984{
985        AQData *d = (AQData *) f->data;
986        *((int *) arg) = d->rate;
987        return 0;
988}
989
990/*
991static int set_nchannels(MSFilter *f, void *arg){
992        AQData *d=(AQData*)f->data;
993        d->stereo=(*((int*)arg)==2);
994        return 0;
995}
996*/
997
998static MSFilterMethod aq_read_methods[] = {
999        {MS_FILTER_SET_SAMPLE_RATE, set_rate},
1000        {MS_FILTER_GET_SAMPLE_RATE, read_get_rate},
1001/* not support yet
1002        {       MS_FILTER_SET_NCHANNELS         , set_nchannels },
1003*/
1004        {0, NULL}
1005};
1006
1007MSFilterDesc aq_read_desc = {
1008        .id = MS_AQ_READ_ID,
1009        .name = "MSAQRead",
1010        .text = N_("Sound capture filter for MacOS X Audio Queue Service"),
1011        .category = MS_FILTER_OTHER,
1012        .ninputs = 0,
1013        .noutputs = 1,
1014        .init = aq_init,
1015        .preprocess = aq_read_preprocess,
1016        .process = aq_read_process,
1017        .postprocess = aq_read_postprocess,
1018        .uninit = aq_uninit,
1019        .methods = aq_read_methods
1020};
1021
1022static MSFilterMethod aq_write_methods[] = {
1023        {MS_FILTER_SET_SAMPLE_RATE, set_rate},
1024        {MS_FILTER_GET_SAMPLE_RATE, write_get_rate},
1025/* not support yet
1026        {       MS_FILTER_SET_NCHANNELS         , set_nchannels },
1027*/
1028        {0, NULL}
1029};
1030
1031MSFilterDesc aq_write_desc = {
1032        .id = MS_AQ_WRITE_ID,
1033        .name = "MSAQWrite",
1034        .text = N_("Sound playback filter for MacOS X Audio Queue Service"),
1035        .category = MS_FILTER_OTHER,
1036        .ninputs = 1,
1037        .noutputs = 0,
1038        .init = aq_init,
1039        .preprocess = aq_write_preprocess,
1040        .process = aq_write_process,
1041        .postprocess = aq_write_postprocess,
1042        .uninit = aq_uninit,
1043        .methods = aq_write_methods
1044};
1045
1046MSFilter *ms_aq_read_new(MSSndCard * card)
1047{
1048        MSFilter *f = ms_filter_new_from_desc(&aq_read_desc);
1049        AqSndDsCard *wc = (AqSndDsCard *) card->data;
1050        AQData *d = (AQData *) f->data;
1051        d->uidname = NULL;
1052        if (wc->uidname != NULL)
1053                d->uidname = CFStringCreateCopy(NULL, wc->uidname);
1054        memcpy(&d->devicereadFormat, &wc->devicereadFormat,
1055                   sizeof(AudioStreamBasicDescription));
1056        memcpy(&d->devicewriteFormat, &wc->devicewriteFormat,
1057                   sizeof(AudioStreamBasicDescription));
1058        return f;
1059}
1060
1061
1062MSFilter *ms_aq_write_new(MSSndCard * card)
1063{
1064        MSFilter *f = ms_filter_new_from_desc(&aq_write_desc);
1065        AqSndDsCard *wc = (AqSndDsCard *) card->data;
1066        AQData *d = (AQData *) f->data;
1067        d->uidname = NULL;
1068        if (wc->uidname != NULL)
1069                d->uidname = CFStringCreateCopy(NULL, wc->uidname);
1070        memcpy(&d->devicereadFormat, &wc->devicereadFormat,
1071                   sizeof(AudioStreamBasicDescription));
1072        memcpy(&d->devicewriteFormat, &wc->devicewriteFormat,
1073                   sizeof(AudioStreamBasicDescription));
1074        return f;
1075}
1076
1077MS_FILTER_DESC_EXPORT(aq_read_desc)
1078MS_FILTER_DESC_EXPORT(aq_write_desc)
Note: See TracBrowser for help on using the repository browser.