source: mediastreamer2/src/msiounit.c @ 1294:0ada932d0ea6

Last change on this file since 1294:0ada932d0ea6 was 1294:0ada932d0ea6, checked in by smorlat <smorlat@…>, 2 years ago

fix bugs in dtmf generator, ios audio unit, and allow setting of dtmf amplitude.

File size: 19.0 KB
Line 
1/*
2 * auiosnd.c -I/O unit Media plugin for Linphone-
3 *
4 *
5 * Copyright (C) 2009  Belledonne Comunications, Grenoble, France
6 *
7 *  This program is free software; you can redistribute it and/or modify
8 *  it under the terms of the GNU General Public License as published by
9 *  the Free Software Foundation; either version 2 of the License, or
10 *  (at your option) any later version.
11 *
12 *  This program is distributed in the hope that it will be useful,
13 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 *  GNU Library General Public License for more details.
16 *
17 *  You should have received a copy of the GNU General Public License
18 *  along with this program; if not, write to the Free Software
19 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 */
21#include <AudioToolbox/AudioToolbox.h>
22#include "mediastreamer2/mssndcard.h"
23#include "mediastreamer2/msfilter.h"
24#include "mediastreamer2/msticker.h"
25
26#define PREFERRED_HW_SAMPLE_RATE 44100
27
28#if 0
29#undef ms_debug
30#define ms_debug ms_message
31#endif
32static const char* AU_CARD_RECEIVER = "Audio Unit Receiver";
33static const char* AU_CARD_SPEAKER = "Audio Unit Speaker";
34
35
36static MSFilter *ms_au_read_new(MSSndCard *card);
37static MSFilter *ms_au_write_new(MSSndCard *card);
38
39typedef struct AUData_t{
40        AudioUnit       io_unit;
41        unsigned int    rate;
42        unsigned int    bits;
43        unsigned int    nchannels;
44        ms_mutex_t      mutex;
45        queue_t         rq;
46        MSBufferizer    *bufferizer;
47        bool_t          started;
48        bool_t          read_started;
49        bool_t          write_started;
50        AudioTimeStamp readTimeStamp;
51        unsigned int n_lost_frame;
52        bool_t io_unit_must_be_started;
53        bool_t is_ringer;
54} AUData;
55
56
57/*
58 mediastreamer2 function
59 */
60
61static void au_set_level(MSSndCard *card, MSSndCardMixerElem e, int percent)
62{
63}
64
65static int au_get_level(MSSndCard *card, MSSndCardMixerElem e)
66{
67        return 0;
68}
69
70static void au_set_source(MSSndCard *card, MSSndCardCapture source)
71{
72}
73
74static void au_init(MSSndCard *card){
75        ms_debug("au_init");
76        AUData *d=ms_new(AUData,1);
77        //OSStatus auresult;
78        d->bits=16;
79        d->rate=PREFERRED_HW_SAMPLE_RATE;
80        d->nchannels=1;
81       
82        d->read_started=FALSE;
83        d->write_started=FALSE;
84        d->bufferizer=ms_bufferizer_new();
85        d->n_lost_frame=0;
86        d->started=FALSE;
87        d->io_unit_must_be_started=FALSE;
88        qinit(&d->rq);
89        d->readTimeStamp.mSampleTime=-1;
90        ms_mutex_init(&d->mutex,NULL);
91       
92        if (strcmp(card->name,AU_CARD_SPEAKER)==0) {
93                d->is_ringer=TRUE;
94        } else {
95                d->is_ringer=FALSE;
96        }
97        card->data=d;
98}
99
100static void au_uninit(MSSndCard *card){
101        AUData *d=(AUData*)card->data;
102        ms_bufferizer_destroy(d->bufferizer);
103        ms_mutex_destroy(&d->mutex);
104        ms_free(d);
105}
106
107static void au_detect(MSSndCardManager *m);
108static MSSndCard *au_duplicate(MSSndCard *obj);
109
110MSSndCardDesc au_card_desc={
111.driver_type="AU",
112.detect=au_detect,
113.init=au_init,
114.set_level=au_set_level,
115.get_level=au_get_level,
116.set_capture=au_set_source,
117.set_control=NULL,
118.get_control=NULL,
119.create_reader=ms_au_read_new,
120.create_writer=ms_au_write_new,
121.uninit=au_uninit,
122.duplicate=au_duplicate
123};
124
125static MSSndCard *au_duplicate(MSSndCard *obj){
126        MSSndCard *card=ms_snd_card_new_with_name(&au_card_desc,obj->name);
127        return card;
128}
129#define check_auresult(au,method) \
130if (au!=0) ms_error("AudioUnit error for %s: ret=%i",method,au)
131static void au_interuption_listener(void* inClientData, UInt32 inInterruptionState) {
132        if (((MSSndCard*)inClientData)->data == NULL) return;
133       
134        AUData *d=(AUData*)(((MSSndCard*)inClientData)->data);
135        if (d->started == FALSE) {
136                //nothing to do
137                return;
138        }
139        switch (inInterruptionState) {
140                case kAudioSessionBeginInterruption:
141                        ms_message ("IO unit interruption begin");
142                        AudioOutputUnitStop(d->io_unit);
143                        break;
144                case kAudioSessionEndInterruption:
145                        // make sure we are again the active session
146                        ms_message ("IO unit interruption end");
147                        OSStatus auresult = AudioSessionSetActive(true);
148                        check_auresult(auresult,"AudioSessionSetActive");
149                        d->io_unit_must_be_started=TRUE;
150                        break;
151                default:
152                        ms_warning ("unexpected interuption %i",inInterruptionState);
153        }
154}
155
156static MSSndCard *au_card_new(const char* name){
157        MSSndCard *card=ms_snd_card_new_with_name(&au_card_desc,name);
158        OSStatus auresult = AudioSessionInitialize(NULL, NULL, au_interuption_listener, card);
159        if (auresult != kAudioSessionAlreadyInitialized) {
160                check_auresult(auresult,"AudioSessionInitialize");
161        }
162        return card;
163}
164
165static void au_detect(MSSndCardManager *m){
166        ms_debug("au_detect");
167        MSSndCard *card=au_card_new(AU_CARD_RECEIVER);
168        ms_snd_card_manager_add_card(m,card);
169        card=au_card_new(AU_CARD_SPEAKER);
170        ms_snd_card_manager_add_card(m,card);   
171}
172
173static OSStatus au_read_cb (
174                                                          void                        *inRefCon,
175                                                          AudioUnitRenderActionFlags  *ioActionFlags,
176                                                          const AudioTimeStamp        *inTimeStamp,
177                                                          UInt32                      inBusNumber,
178                                                          UInt32                      inNumberFrames,
179                                                          AudioBufferList             *ioData
180)
181{
182        AUData *d=(AUData*)inRefCon;
183        if (d->readTimeStamp.mSampleTime <0) {
184                d->readTimeStamp=*inTimeStamp;
185        }
186        OSStatus err=0;
187        mblk_t * rm=NULL;
188        if (d->read_started) {
189                rm=allocb(ioData->mBuffers[0].mDataByteSize,0);
190                ioData->mBuffers[0].mData=rm->b_wptr;
191        }
192        err = AudioUnitRender(d->io_unit, ioActionFlags, &d->readTimeStamp, inBusNumber,inNumberFrames, ioData);
193        if (d->read_started){
194                if (err == 0) {
195                        rm->b_wptr += ioData->mBuffers[0].mDataByteSize;
196                        ms_mutex_lock(&d->mutex);
197                        putq(&d->rq,rm);
198                        ms_mutex_unlock(&d->mutex);
199                        d->readTimeStamp.mSampleTime+=ioData->mBuffers[0].mDataByteSize/(d->bits/2);
200                }else ms_warning("AudioUnitRender() failed: %i",err);
201        }
202        return err;
203}
204
205/********************read/write cb******************/
206
207static OSStatus au_render_cb (
208                                                          void                        *inRefCon,
209                                                          AudioUnitRenderActionFlags  *ioActionFlags,
210                                                          const AudioTimeStamp        *inTimeStamp,
211                                                          UInt32                      inBusNumber,
212                                                          UInt32                      inNumberFrames,
213                                                          AudioBufferList             *ioData
214) {
215        ms_debug("render cb");
216        AUData *d=(AUData*)inRefCon;
217       
218        if (d->write_started == TRUE) {
219                ioData->mBuffers[0].mDataByteSize=inNumberFrames*d->bits/8;
220                ioData->mNumberBuffers=1;
221               
222                ms_mutex_lock(&d->mutex);
223                if(ms_bufferizer_get_avail(d->bufferizer) >= inNumberFrames*d->bits/8) {
224                        ms_bufferizer_read(d->bufferizer, ioData->mBuffers[0].mData, inNumberFrames*d->bits/8);
225
226                        if (ms_bufferizer_get_avail(d->bufferizer) >10*inNumberFrames*d->bits/8) {
227                                ms_debug("we are late, bufferizer sise is %i bytes in framezize is %i bytes",ms_bufferizer_get_avail(d->bufferizer),inNumberFrames*d->bits/8);
228                                ms_bufferizer_flush(d->bufferizer);
229                        }
230                        ms_mutex_unlock(&d->mutex);
231                       
232                } else {
233                       
234                        ms_mutex_unlock(&d->mutex);
235                        memset(ioData->mBuffers[0].mData, 0,ioData->mBuffers[0].mDataByteSize);
236                        ms_debug("nothing to write, pushing silences, bufferizer size is %i bytes in framezize is %i bytes mDataByteSize %i"
237                                         ,ms_bufferizer_get_avail(d->bufferizer)
238                                         ,inNumberFrames*d->bits/8
239                                         ,ioData->mBuffers[0].mDataByteSize);
240                        d->n_lost_frame+=inNumberFrames;
241                }
242        }
243        if (!d->is_ringer) { // no need to read in ringer mode
244                AudioBufferList readAudioBufferList;
245                readAudioBufferList.mBuffers[0].mDataByteSize=inNumberFrames*d->bits/8; 
246                readAudioBufferList.mNumberBuffers=1;
247                readAudioBufferList.mBuffers[0].mData=NULL;
248                readAudioBufferList.mBuffers[0].mNumberChannels=d->nchannels;
249                AudioUnitElement inputBus = 1;
250                au_read_cb(d, ioActionFlags, inTimeStamp, inputBus, inNumberFrames, &readAudioBufferList);
251        }
252        return 0;
253}
254
255/****************config**************/
256
257static void au_configure(AUData *d) {
258        AudioStreamBasicDescription audioFormat;
259        AudioComponentDescription au_description;
260        AudioComponent foundComponent;
261        OSStatus auresult;
262        UInt32 doSetProperty      = 1;
263        UInt32 doNotSetProperty    = 0;
264       
265       
266       
267        auresult = AudioSessionSetActive(true);
268        check_auresult(auresult,"AudioSessionSetActive");
269       
270       
271        UInt32 audioCategory =kAudioSessionCategory_PlayAndRecord;
272        auresult =AudioSessionSetProperty(kAudioSessionProperty_AudioCategory, sizeof(audioCategory), &audioCategory);
273        check_auresult(auresult,"Configuring audio session ");
274       
275
276        if (d->is_ringer) {
277                auresult=AudioSessionSetProperty (kAudioSessionProperty_OverrideCategoryDefaultToSpeaker,sizeof (doSetProperty),&doSetProperty);
278                check_auresult(auresult,"kAudioSessionProperty_OverrideAudioRoute");
279                ms_message("Configuring audio session default route to speaker");
280        } else {
281                ms_message("Configuring audio session default route to receiver");
282        }
283        if (d->started == TRUE) {
284                //nothing else to do
285                return;
286        }
287       
288        au_description.componentType          = kAudioUnitType_Output;
289        au_description.componentSubType       = kAudioUnitSubType_VoiceProcessingIO;
290        au_description.componentManufacturer  = kAudioUnitManufacturer_Apple;
291        au_description.componentFlags         = 0;
292        au_description.componentFlagsMask     = 0;
293       
294        foundComponent = AudioComponentFindNext (NULL,&au_description);
295       
296        auresult=AudioComponentInstanceNew (foundComponent, &d->io_unit);
297       
298        check_auresult(auresult,"AudioComponentInstanceNew");
299
300        audioFormat.mSampleRate                 = d->rate;
301        audioFormat.mFormatID                   = kAudioFormatLinearPCM;
302        audioFormat.mFormatFlags                = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked;
303        audioFormat.mFramesPerPacket    = 1;
304        audioFormat.mChannelsPerFrame   = d->nchannels;
305        audioFormat.mBitsPerChannel             = d->bits;
306        audioFormat.mBytesPerPacket             = d->bits / 8;
307        audioFormat.mBytesPerFrame              = d->nchannels * d->bits / 8;
308        AudioUnitElement outputBus = 0;
309        AudioUnitElement inputBus = 1;
310        auresult=AudioUnitUninitialize (d->io_unit);
311       
312        check_auresult(auresult,"AudioUnitUninitialize");
313       
314        //read
315        auresult=AudioUnitSetProperty (
316                                                                   d->io_unit,
317                                                                   kAudioOutputUnitProperty_EnableIO,
318                                                                   kAudioUnitScope_Input ,
319                                                                   inputBus,
320                                                                   &doSetProperty,
321                                                                   sizeof (doSetProperty)
322                                                                   );
323        check_auresult(auresult,"kAudioOutputUnitProperty_EnableIO,kAudioUnitScope_Input");
324        //setup stream format
325        auresult=AudioUnitSetProperty (
326                                                                   d->io_unit,
327                                                                   kAudioUnitProperty_StreamFormat,
328                                                                   kAudioUnitScope_Input,
329                                                                   outputBus,
330                                                                   &audioFormat,
331                                                                   sizeof (audioFormat)
332                                                                   );
333       
334        //write
335        //enable output bus
336        auresult =AudioUnitSetProperty (
337                                                                        d->io_unit,
338                                                                        kAudioOutputUnitProperty_EnableIO,
339                                                                        kAudioUnitScope_Output ,
340                                                                        outputBus,
341                                                                        &doSetProperty,
342                                                                        sizeof (doSetProperty)
343                                                                        );
344        check_auresult(auresult,"kAudioOutputUnitProperty_EnableIO,kAudioUnitScope_Output");
345       
346        //setup stream format
347        auresult=AudioUnitSetProperty (
348                                                                   d->io_unit,
349                                                                   kAudioUnitProperty_StreamFormat,
350                                                                   kAudioUnitScope_Output,
351                                                                   inputBus,
352                                                                   &audioFormat,
353                                                                   sizeof (audioFormat)
354                                                                   );
355        check_auresult(auresult,"kAudioUnitProperty_StreamFormat,kAudioUnitScope_Output");
356       
357        check_auresult(auresult,"kAudioUnitProperty_StreamFormat,kAudioUnitScope_Input");
358       
359        //disable unit buffer allocation
360        auresult=AudioUnitSetProperty (
361                                                                   d->io_unit,
362                                                                   kAudioUnitProperty_ShouldAllocateBuffer,
363                                                                   kAudioUnitScope_Output,
364                                                                   outputBus,
365                                                                   &doNotSetProperty,
366                                                                   sizeof (doNotSetProperty)
367                                                                   );
368        check_auresult(auresult,"kAudioUnitProperty_ShouldAllocateBuffer,kAudioUnitScope_Output");
369       
370       
371        AURenderCallbackStruct renderCallbackStruct;           
372        renderCallbackStruct.inputProc       = au_render_cb; 
373        renderCallbackStruct.inputProcRefCon = d;         
374       
375        auresult=AudioUnitSetProperty (
376                                                                   d->io_unit,                                 
377                                                                   kAudioUnitProperty_SetRenderCallback,       
378                                                                   kAudioUnitScope_Input,                       
379                                                                   outputBus,                                   
380                                                                   &renderCallbackStruct,                             
381                                                                   sizeof (renderCallbackStruct)                       
382                                                                   );
383        check_auresult(auresult,"kAudioUnitProperty_SetRenderCallback,kAudioUnitScope_Input");
384       
385        const Float64 preferredSampleRate = d->rate;//PREFERRED_HW_SAMPLE_RATE; /*optimum to minimize delay, must put a software resampler to deal with 8khz*/
386       
387        auresult=AudioSessionSetProperty(kAudioSessionProperty_PreferredHardwareSampleRate
388                                                                         ,sizeof(preferredSampleRate)
389                                                                         , &preferredSampleRate);
390        check_auresult(auresult,"kAudioSessionProperty_PreferredHardwareSampleRate");
391       
392       
393        Float32 preferredBufferSize;
394        switch (d->rate) {
395                case 11025:
396                case 22050:
397                        preferredBufferSize= .020;
398                        break;
399                default:
400                        preferredBufferSize= .015;
401        }
402                       
403        auresult=AudioSessionSetProperty(kAudioSessionProperty_PreferredHardwareIOBufferDuration
404                                                                         ,sizeof(preferredBufferSize)
405                                                                         , &preferredBufferSize);
406       
407       
408        if (auresult != 0) ms_message("kAudioSessionProperty_PreferredHardwareIOBufferDuration returns %i ",auresult);
409       
410        Float64 delay;
411        UInt32 delaySize = sizeof(delay);
412        auresult=AudioUnitGetProperty(d->io_unit
413                                                                  ,kAudioUnitProperty_Latency
414                                                                  , kAudioUnitScope_Global
415                                                                  , 0
416                                                                  , &delay
417                                                                  , &delaySize);
418
419        UInt32 quality;
420        UInt32 qualitySize = sizeof(quality);
421        auresult=AudioUnitGetProperty(d->io_unit
422                                                                  ,kAudioUnitProperty_RenderQuality
423                                                                  , kAudioUnitScope_Global
424                                                                  , 0
425                                                                  , &quality
426                                                                  , &qualitySize);
427       
428       
429       
430        ms_message("I/O unit latency [%f], quality [%i]",delay,quality);
431        Float32 hwoutputlatency;
432        UInt32 hwoutputlatencySize=sizeof(hwoutputlatency);
433        auresult=AudioSessionGetProperty(kAudioSessionProperty_CurrentHardwareOutputLatency
434                                                                         ,&hwoutputlatencySize
435                                                                         , &hwoutputlatency);
436        Float32 hwinputlatency;
437        UInt32 hwinputlatencySize=sizeof(hwoutputlatency);
438        auresult=AudioSessionGetProperty(kAudioSessionProperty_CurrentHardwareInputLatency
439                                                                         ,&hwinputlatencySize
440                                                                         , &hwinputlatency);
441       
442        Float32 hwiobuf;
443        UInt32 hwiobufSize=sizeof(hwiobuf);
444        auresult=AudioSessionGetProperty(kAudioSessionProperty_CurrentHardwareIOBufferDuration
445                                                                         ,&hwiobufSize
446                                                                         , &hwiobuf);
447       
448        Float64 hwsamplerate;
449        UInt32 hwsamplerateSize=sizeof(hwsamplerate);
450        auresult=AudioSessionGetProperty(kAudioSessionProperty_CurrentHardwareSampleRate
451                                                                         ,&hwsamplerateSize
452                                                                         ,&hwsamplerate);
453
454        ms_message("current hw output latency [%f] input [%f] iobuf[%f] sample rate [%f]",hwoutputlatency,hwinputlatency,hwiobuf,hwsamplerate);
455        auresult=AudioOutputUnitStart(d->io_unit);
456        check_auresult(auresult,"AudioOutputUnitStart");
457        d->started=TRUE;
458        return;
459}       
460
461static void au_configure_read(AUData *d) {
462        d->read_started=TRUE;
463        au_configure(d);
464        ms_mutex_lock(&d->mutex);
465        flushq(&d->rq,0);
466        ms_mutex_unlock(&d->mutex);
467       
468}
469
470static void au_configure_write(AUData *d) {
471        d->write_started=TRUE;
472        au_configure(d);
473        ms_mutex_lock(&d->mutex);
474        ms_bufferizer_flush(d->bufferizer);
475        ms_mutex_unlock(&d->mutex);     
476}
477
478
479static void au_unconfigure(AUData *d) {
480        if (d->write_started==FALSE && d->read_started==FALSE) {
481                AudioUnitUninitialize(d->io_unit);
482                AudioOutputUnitStop(d->io_unit);
483                AudioComponentInstanceDispose (d->io_unit);
484                d->started=FALSE;
485        }
486}
487
488static void au_unconfigure_read(AUData *d){
489        if(d->read_started == TRUE) {
490                d->read_started=FALSE;
491                AudioUnitElement inputBus = 1;
492                AudioUnitReset(d->io_unit,
493                        kAudioUnitScope_Global,
494                        inputBus);
495        }
496        au_unconfigure(d);
497        ms_mutex_lock(&d->mutex);
498        flushq(&d->rq,0);
499        ms_mutex_unlock(&d->mutex);
500}
501
502static void au_unconfigure_write(AUData *d){
503        if(d->write_started == TRUE) {
504                d->write_started=FALSE;
505                AudioUnitElement outputBus = 0;
506                AudioUnitReset(d->io_unit,
507                        kAudioUnitScope_Global,
508                        outputBus);             
509        }
510        ms_message("[%i] frames of silence inserted for [%i] ms.",d->n_lost_frame,(d->n_lost_frame*1000)/d->rate);
511        au_unconfigure(d);
512        ms_mutex_lock(&d->mutex);
513        ms_bufferizer_flush(d->bufferizer);
514        ms_mutex_unlock(&d->mutex);
515}
516
517
518
519
520/***********************************read function********************/
521
522static void au_read_preprocess(MSFilter *f){
523        ms_debug("au_read_preprocess");
524        AUData *d=(AUData*)((MSSndCard*)f->data)->data;
525        au_configure_read(d);
526       
527}
528
529static void au_read_postprocess(MSFilter *f){
530        AUData *d=(AUData*)((MSSndCard*)f->data)->data;
531        au_unconfigure_read(d);
532}
533
534static void au_read_process(MSFilter *f){
535        AUData *d=(AUData*)((MSSndCard*)f->data)->data;
536        mblk_t *m;
537               
538        if (d->io_unit_must_be_started) {
539                if (f->ticker->time % 100 == 0) { /*more or less every 100ms*/
540                        if (AudioOutputUnitStart(d->io_unit) == 0) {
541                                d->io_unit_must_be_started=FALSE;
542                        };
543                }
544        }
545        do {
546                ms_mutex_lock(&d->mutex);
547                m=getq(&d->rq);
548                ms_mutex_unlock(&d->mutex);
549                if (m != NULL) ms_queue_put(f->outputs[0],m); 
550        }while(m!=NULL);
551       
552}
553
554
555
556/***********************************write function********************/
557
558static void au_write_preprocess(MSFilter *f){
559        ms_debug("au_write_preprocess");
560        AUData *d=(AUData*)((MSSndCard*)f->data)->data;
561        au_configure_write(d);
562}
563
564static void au_write_postprocess(MSFilter *f){
565        ms_debug("au_write_postprocess");
566        AUData *d=(AUData*)((MSSndCard*)f->data)->data;
567        au_unconfigure_write(d);
568}
569
570
571
572static void au_write_process(MSFilter *f){
573        ms_debug("au_write_process");
574        mblk_t *m;
575        AUData *d=(AUData*)((MSSndCard*)f->data)->data;
576       
577        while((m=ms_queue_get(f->inputs[0]))!=NULL){
578                ms_mutex_lock(&d->mutex);
579                ms_bufferizer_put(d->bufferizer,m);
580                ms_mutex_unlock(&d->mutex);
581        }
582}
583
584static int set_rate(MSFilter *f, void *arg){
585        int proposed_rate = *((int*)arg);
586        ms_debug("set_rate %d",proposed_rate);
587        /*if (proposed_rate != PREFERRED_HW_SAMPLE_RATE) {
588                return -1;//only support 1 rate
589        }*/
590        MSSndCard *card=(MSSndCard*)f->data;
591        AUData *d=(AUData*)card->data;
592        d->rate=proposed_rate;
593        return 0;
594}
595
596static int get_rate(MSFilter *f, void *data){
597        MSSndCard *card=(MSSndCard*)f->data;
598        AUData *d=(AUData*)card->data;
599        *(int*)data=d->rate;
600        return 0;
601}
602
603
604static int set_nchannels(MSFilter *f, void *arg){
605        ms_debug("set_nchannels %d", *((int*)arg));
606        MSSndCard *card=(MSSndCard*)f->data;
607        AUData *d=(AUData*)card->data;
608        d->nchannels=*(int*)arg;
609        return 0;
610}
611
612static MSFilterMethod au_methods[]={
613        {       MS_FILTER_SET_SAMPLE_RATE       , set_rate      },
614        {       MS_FILTER_GET_SAMPLE_RATE       , get_rate      },
615        {       MS_FILTER_SET_NCHANNELS         , set_nchannels },
616        {       0                               , NULL          }
617};
618
619MSFilterDesc au_read_desc={
620.id=MS_IOUNIT_READ_ID,
621.name="MSAURead",
622.text=N_("Sound capture filter for MacOS X Audio Unit Service"),
623.category=MS_FILTER_OTHER,
624.ninputs=0,
625.noutputs=1,
626.preprocess=au_read_preprocess,
627.process=au_read_process,
628.postprocess=au_read_postprocess,
629.methods=au_methods
630};
631
632
633MSFilterDesc au_write_desc={
634.id=MS_IOUNIT_WRITE_ID,
635.name="MSAUWrite",
636.text=N_("Sound playback filter for MacOS X Audio Unit Service"),
637.category=MS_FILTER_OTHER,
638.ninputs=1,
639.noutputs=0,
640.preprocess=au_write_preprocess,
641.process=au_write_process,
642.postprocess=au_write_postprocess,
643.methods=au_methods
644};
645
646static MSFilter *ms_au_read_new(MSSndCard *card){
647        ms_debug("ms_au_read_new");
648        MSFilter *f=ms_filter_new_from_desc(&au_read_desc);
649        f->data=card;
650        return f;
651}
652
653
654static MSFilter *ms_au_write_new(MSSndCard *card){
655        ms_debug("ms_au_write_new");
656        MSFilter *f=ms_filter_new_from_desc(&au_write_desc);
657        f->data=card;
658        return f;
659}
660
661MS_FILTER_DESC_EXPORT(au_read_desc)
662MS_FILTER_DESC_EXPORT(au_write_desc)
663
664void ms_au_register_card() {
665        /**
666         * register audio unit plugin should be move to linphone code
667         */
668        ms_snd_card_manager_register_desc(ms_snd_card_manager_get(),&au_card_desc);
669}       
Note: See TracBrowser for help on using the repository browser.