]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
apply portaudio patches from jira and add some fixes for linux
authorAnthony Minessale <anthony.minessale@gmail.com>
Thu, 15 Jan 2009 18:39:51 +0000 (18:39 +0000)
committerAnthony Minessale <anthony.minessale@gmail.com>
Thu, 15 Jan 2009 18:39:51 +0000 (18:39 +0000)
git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@11227 d0543943-73ff-0310-b7d9-9358b9ac24b2

src/mod/endpoints/mod_portaudio/mod_portaudio.c
src/mod/endpoints/mod_portaudio/pablio.c
src/mod/endpoints/mod_portaudio/pablio.h

index 88bc0dd69829ca1036bb8b93d614cd457bfeda19..710d4dd38389056f98e4b2311b2724f7c40bda1c 100644 (file)
@@ -157,7 +157,7 @@ static void deactivate_ring_device(void);
 static int dump_info(int verbose);
 static switch_status_t load_config(void);
 static int get_dev_by_name(char *name, int in);
-static int get_dev_by_number(int number, int in);
+static int get_dev_by_number(char *numstr, int in);
 SWITCH_STANDARD_API(pa_cmd);
 
 /* 
@@ -263,6 +263,7 @@ static switch_status_t channel_on_init(switch_core_session_t *session)
                                        unsigned int pos = 0;
                                        switch_core_file_seek(&fh, &pos, 0, SEEK_SET);
                                }
+
                                if (globals.ring_stream) {
                                        WriteAudioStream(globals.ring_stream, abuf, (long) olen, &globals.timer);
                                }
@@ -784,6 +785,10 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_portaudio_load)
        switch_console_set_complete("add pa indev");
        switch_console_set_complete("add pa outdev");
        switch_console_set_complete("add pa ringdev");
+       switch_console_set_complete("add pa play");
+       switch_console_set_complete("add pa ringtest");
+       switch_console_set_complete("add pa looptest");
+
        /* indicate that the module should continue to be loaded */
        return SWITCH_STATUS_SUCCESS;
 }
@@ -836,19 +841,19 @@ static switch_status_t load_config(void)
                                set_global_cid_num(val);
                        } else if (!strcmp(var, "indev")) {
                                if (*val == '#') {
-                                       globals.indev = get_dev_by_number(atoi(val + 1), 1);
+                                       globals.indev = get_dev_by_number(val + 1, 1);
                                } else {
                                        globals.indev = get_dev_by_name(val, 1);
                                }
                        } else if (!strcmp(var, "outdev")) {
                                if (*val == '#') {
-                                       globals.outdev = get_dev_by_number(atoi(val + 1), 0);
+                                       globals.outdev = get_dev_by_number(val + 1, 0);
                                } else {
                                        globals.outdev = get_dev_by_name(val, 0);
                                }
                        } else if (!strcmp(var, "ringdev")) {
                                if (*val == '#') {
-                                       globals.ringdev = get_dev_by_number(atoi(val + 1), 0);
+                                       globals.ringdev = get_dev_by_number(val + 1, 0);
                                } else {
                                        globals.ringdev = get_dev_by_name(val, 0);
                                }
@@ -910,6 +915,8 @@ static switch_status_t load_config(void)
 
 SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_portaudio_shutdown)
 {
+       
+
        if (globals.read_codec.implementation) {
                switch_core_codec_destroy(&globals.read_codec);
        }
@@ -918,19 +925,30 @@ SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_portaudio_shutdown)
                switch_core_codec_destroy(&globals.write_codec);
        }
 
+
        switch_core_timer_destroy(&globals.timer);
        switch_core_timer_destroy(&globals.hold_timer);
        Pa_Terminate();
        switch_core_hash_destroy(&globals.call_hash);
 
+       switch_event_free_subclass(MY_EVENT_RINGING);
+
        return SWITCH_STATUS_SUCCESS;
 }
 
 
-static int get_dev_by_number(int number, int in)
+static int get_dev_by_number(char *numstr, int in)
 {
        int numDevices = Pa_GetDeviceCount();
        const PaDeviceInfo *pdi;
+       char *end_ptr;
+       int number;
+
+       number = (int) strtol(numstr, &end_ptr, 10);
+
+       if (end_ptr == numstr || number < 0) {
+               return -1;
+       }
 
        if (number > -1 && number < numDevices && (pdi = Pa_GetDeviceInfo(number))) {
                if (in && pdi->maxInputChannels) {
@@ -974,11 +992,7 @@ static int get_dev_by_name(char *name, int in)
                }
        }
 
-       if (switch_strlen_zero(name)) {
-               return -1;
-       }
-
-       return get_dev_by_name(NULL, in);
+       return -1;
 }
 
 
@@ -1110,13 +1124,13 @@ static int dump_info(int verbose)
                inputParameters.device = i;
                inputParameters.channelCount = deviceInfo->maxInputChannels;
                inputParameters.sampleFormat = paInt16;
-               inputParameters.suggestedLatency = 0;   /* ignored by Pa_IsFormatSupported() */
+               inputParameters.suggestedLatency = deviceInfo->defaultLowOutputLatency; /* ignored by Pa_IsFormatSupported() */
                inputParameters.hostApiSpecificStreamInfo = NULL;
-
+               
                outputParameters.device = i;
                outputParameters.channelCount = deviceInfo->maxOutputChannels;
                outputParameters.sampleFormat = paInt16;
-               outputParameters.suggestedLatency = 0;  /* ignored by Pa_IsFormatSupported() */
+               outputParameters.suggestedLatency = deviceInfo->defaultLowOutputLatency;        /* ignored by Pa_IsFormatSupported() */
                outputParameters.hostApiSpecificStreamInfo = NULL;
 
                if (inputParameters.channelCount > 0) {
@@ -1131,7 +1145,7 @@ static int dump_info(int verbose)
                }
 
                if (inputParameters.channelCount > 0 && outputParameters.channelCount > 0) {
-
+                       
                        switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_INFO,
                                                          "full-duplex 16 bit %d channel input, %d channel output rates:", inputParameters.channelCount,
                                                          outputParameters.channelCount);
@@ -1226,6 +1240,9 @@ static switch_status_t engage_device(int sample_rate, int codec_ms)
                outputParameters.sampleFormat = SAMPLE_TYPE;
                outputParameters.suggestedLatency = Pa_GetDeviceInfo(outputParameters.device)->defaultLowOutputLatency;
                outputParameters.hostApiSpecificStreamInfo = NULL;
+               //err = OpenAudioStream(&globals.audio_stream, NULL/*&inputParameters*/, &outputParameters, sample_rate, paClipOff,
+               //globals.read_codec.implementation->samples_per_packet);
+
                err = OpenAudioStream(&globals.audio_stream, &inputParameters, &outputParameters, sample_rate, paClipOff,
                                                          globals.read_codec.implementation->samples_per_packet);
                /* UNLOCKED ************************************************************************************************* */
@@ -1630,7 +1647,10 @@ SWITCH_STANDARD_API(pa_cmd)
                "pa devlist\n"
                "pa indev #<num>|<partial name>\n"
                "pa outdev #<num>|<partial name>\n"
-               "pa ringdev #<num>|<partial name>\n" "--------------------------------------------------------------------------------\n";
+               "pa ringdev #<num>|<partial name>\n"
+               "pa play <filename>\n"
+               "pa ringtest\n"
+               "pa looptest\n" "--------------------------------------------------------------------------------\n";
 
 
        if (stream->param_event) {
@@ -1719,34 +1739,98 @@ SWITCH_STANDARD_API(pa_cmd)
                func = dtmf_call;
        } else if (argv[1] && !strcmp(argv[0], "indev")) {
                if (*argv[1] == '#') {
-                       devval = get_dev_by_number(atoi(argv[1] + 1), 1);
+                       devval = get_dev_by_number(argv[1] + 1, 1);
                } else {
                        devval = get_dev_by_name(argv[1], 1);
                }
                devname = "indev";
-               if (devval > 0) {
+               if (devval > -1) {
                        globals.indev = devval;
                }
        } else if (argv[1] && !strcmp(argv[0], "outdev")) {
                if (*argv[1] == '#') {
-                       devval = get_dev_by_number(atoi(argv[1] + 1), 0);
+                       devval = get_dev_by_number(argv[1] + 1, 0);
                } else {
                        devval = get_dev_by_name(argv[1], 0);
                }
                devname = "outdev";
-               if (devval > 0) {
+               if (devval > -1) {
                        globals.outdev = devval;
                }
        } else if (argv[1] && !strcmp(argv[0], "ringdev")) {
                if (*argv[1] == '#') {
-                       devval = get_dev_by_number(atoi(argv[1] + 1), 0);
+                       devval = get_dev_by_number(argv[1] + 1, 0);
                } else {
                        devval = get_dev_by_name(argv[1], 0);
                }
                devname = "ringdev";
-               if (devval > 0) {
+               if (devval > -1) {
                        globals.ringdev = devval;
                }
+       } else if ((argv[1] && !strcasecmp(argv[0], "play")) || !strcasecmp(argv[0], "ringtest")) {
+               if (globals.audio_stream) {
+                       switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_INFO, "ERROR: Cannot use this command this while a call is in progress\n");
+                       goto done;
+               }
+
+               switch_file_handle_t fh = { 0 };
+               char *playfile = NULL;
+
+               if (!strcasecmp(argv[0], "ringtest")) {
+                       playfile = globals.ring_file;
+               } else {
+                       playfile = argv[1];
+               }
+
+               if (engage_device(globals.sample_rate, globals.codec_ms) == SWITCH_STATUS_SUCCESS) {
+                       if (switch_core_file_open(&fh,
+                                               playfile,
+                                               globals.read_codec.implementation->number_of_channels,
+                                               globals.read_codec.implementation->actual_samples_per_second,
+                                               SWITCH_FILE_FLAG_READ | SWITCH_FILE_DATA_SHORT, NULL) == SWITCH_STATUS_SUCCESS) {
+                               switch_size_t olen = globals.timer.samples;
+                               int16_t abuf[2048];
+                               
+                               while (switch_core_file_read(&fh, abuf, &olen) == SWITCH_STATUS_SUCCESS) {
+                                       WriteAudioStream(globals.audio_stream, abuf, (long) olen, &globals.timer);
+                                       switch_core_timer_next(&globals.timer);
+                                       olen = globals.timer.samples;
+                               } 
+
+                               switch_core_file_close(&fh);
+                       } else {
+                               stream->write_function(stream, "Cannot play requested file %s\n", argv[1]);
+                       }
+                       deactivate_audio_device();
+               } else {
+                       stream->write_function(stream, "Failed to engage audio device\n");
+               }
+               goto done;
+       } else if (!strcasecmp(argv[0], "looptest")) {
+               if (globals.audio_stream) {
+                       switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_INFO, "ERROR: Cannot use this command this while a call is in progress\n");
+                       goto done;
+               }
+
+               if (engage_device(globals.sample_rate, globals.codec_ms) == SWITCH_STATUS_SUCCESS) {
+                       int samples = 0;
+                       int success = 0;
+                       for(int i = 0; i < 400; i++) {
+                               if ((samples = ReadAudioStream(globals.audio_stream, globals.read_frame.data,
+                                               globals.read_codec.implementation->samples_per_packet, &globals.timer))) {
+                                       WriteAudioStream(globals.audio_stream, globals.read_frame.data, (long) samples, &globals.timer);
+                                       success = 1;
+                               }
+                               switch_yield(10000);
+                       }
+                       deactivate_audio_device();
+                       if (!success) {
+                               stream->write_function(stream, "Failed to read any bytes from indev\n");
+                       }
+               } else {
+                       stream->write_function(stream, "Failed to engage audio device\n");
+               }
+               goto done;
        }
 
        if (func) {
@@ -1763,7 +1847,7 @@ SWITCH_STANDARD_API(pa_cmd)
                }
        } else {
                if (devname) {
-                       if (devval > 0) {
+                       if (devval > -1) {
                                stream->write_function(stream, "%s set to %d\n", devname, devval);
                        } else {
                                stream->write_function(stream, "%s not set (invalid value)\n", devname);
index 739cc3875226f814c808e01a49f3b921d7b74fef..586ebdd38710fc3ac4253faf921c7d61275cb405 100644 (file)
@@ -55,7 +55,9 @@
 /******** Prototypes ****************************************************/
 /************************************************************************/
 
-static int blockingIOCallback(const void *inputBuffer, void *outputBuffer,
+static int iblockingIOCallback(const void *inputBuffer, void *outputBuffer,
+                                                         unsigned long framesPerBuffer, const PaStreamCallbackTimeInfo * timeInfo, PaStreamCallbackFlags statusFlags, void *userData);
+static int oblockingIOCallback(const void *inputBuffer, void *outputBuffer,
                                                          unsigned long framesPerBuffer, const PaStreamCallbackTimeInfo * timeInfo, PaStreamCallbackFlags statusFlags, void *userData);
 static PaError PABLIO_InitFIFO(PaUtilRingBuffer * rbuf, long numFrames, long bytesPerFrame);
 static PaError PABLIO_TermFIFO(PaUtilRingBuffer * rbuf);
@@ -67,7 +69,7 @@ static PaError PABLIO_TermFIFO(PaUtilRingBuffer * rbuf);
 /* Called from PortAudio.
  * Read and write data 
  */
-static int blockingIOCallback(const void *inputBuffer, void *outputBuffer,
+static int iblockingIOCallback(const void *inputBuffer, void *outputBuffer,
                                                          unsigned long framesPerBuffer, const PaStreamCallbackTimeInfo * timeInfo, PaStreamCallbackFlags statusFlags, void *userData)
 {
        PABLIO_Stream *data = (PABLIO_Stream *) userData;
@@ -80,6 +82,16 @@ static int blockingIOCallback(const void *inputBuffer, void *outputBuffer,
                        PaUtil_WriteRingBuffer(&data->inFIFO, inputBuffer, numBytes);
                }
        }
+
+       return 0;
+}
+
+static int oblockingIOCallback(const void *inputBuffer, void *outputBuffer,
+                                                         unsigned long framesPerBuffer, const PaStreamCallbackTimeInfo * timeInfo, PaStreamCallbackFlags statusFlags, void *userData)
+{
+       PABLIO_Stream *data = (PABLIO_Stream *) userData;
+       long numBytes = data->bytesPerFrame * framesPerBuffer;
+
        if (outputBuffer != NULL) {
                int i;
                int numRead = PaUtil_ReadRingBuffer(&data->outFIFO, outputBuffer, numBytes);
@@ -268,12 +280,15 @@ PaError OpenAudioStream(PABLIO_Stream ** rwblPtr,
 
        /* Open a PortAudio stream that we will use to communicate with the underlying
         * audio drivers. */
-       err = Pa_OpenStream(&aStream->stream, inputParameters, outputParameters, sampleRate, samples_per_packet, streamFlags, blockingIOCallback, aStream);
+       err = Pa_OpenStream(&aStream->istream, inputParameters, NULL, sampleRate, samples_per_packet, streamFlags, iblockingIOCallback, aStream);
+       err = Pa_OpenStream(&aStream->ostream, NULL, outputParameters, sampleRate, samples_per_packet, streamFlags, oblockingIOCallback, aStream);
 
        if (err != paNoError)
                goto error;
 
-       err = Pa_StartStream(aStream->stream);
+       err = Pa_StartStream(aStream->istream);
+       err = Pa_StartStream(aStream->ostream);
+
        if (err != paNoError)
                goto error;
        *rwblPtr = aStream;
@@ -288,7 +303,6 @@ PaError OpenAudioStream(PABLIO_Stream ** rwblPtr,
 /************************************************************/
 PaError CloseAudioStream(PABLIO_Stream * aStream)
 {
-       PaError err;
        int bytesEmpty;
        int byteSize = aStream->outFIFO.bufferSize;
 
@@ -301,17 +315,20 @@ PaError CloseAudioStream(PABLIO_Stream * aStream)
                }
        }
 
-       err = Pa_StopStream(aStream->stream);
-       if (err != paNoError)
-               goto error;
-       err = Pa_CloseStream(aStream->stream);
-       if (err != paNoError)
-               goto error;
-       Pa_Terminate();
+       if (Pa_IsStreamActive(aStream->istream)) {
+               Pa_StopStream(aStream->istream);
+               Pa_CloseStream(aStream->istream);
+       }
+
+       if (Pa_IsStreamActive(aStream->ostream)) {
+               Pa_StopStream(aStream->ostream);
+               Pa_CloseStream(aStream->ostream);
+       }
 
-  error:
        PABLIO_TermFIFO(&aStream->inFIFO);
        PABLIO_TermFIFO(&aStream->outFIFO);
        free(aStream);
-       return err;
+
+       return paNoError;
 }
+
index b3cbcfbce0817fbf363ad17adfdd22b5c8c85794..1949ff8b0c881a3eb30346d1872d90cf375c0771 100644 (file)
@@ -59,7 +59,8 @@ extern "C" {
        typedef struct {
                PaUtilRingBuffer inFIFO;
                PaUtilRingBuffer outFIFO;
-               PaStream *stream;
+               PaStream *istream;
+               PaStream *ostream;
                int bytesPerFrame;
        } PABLIO_Stream;