diff options
Diffstat (limited to '')
-rw-r--r-- | src/Makefile.am | 3 | ||||
-rw-r--r-- | src/audioOutput.c | 22 | ||||
-rw-r--r-- | src/audioOutput.h | 16 | ||||
-rw-r--r-- | src/audioOutput_ao.c | 181 |
4 files changed, 89 insertions, 133 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index bac83b8e4..c1ece1d97 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -14,6 +14,7 @@ mpd_inputPlugins = \ mpd_headers = \ ack.h \ audio.h \ + audioOutput.h \ buffer2array.h \ charConv.h \ command.h \ @@ -55,6 +56,8 @@ mpd_SOURCES = \ $(mpd_headers) \ $(mpd_inputPlugins) \ audio.c \ + audioOutput.c \ + audioOutput_ao.c \ buffer2array.c \ charConv.c \ command.c \ diff --git a/src/audioOutput.c b/src/audioOutput.c index aedfda59f..ff0c614a2 100644 --- a/src/audioOutput.c +++ b/src/audioOutput.c @@ -28,16 +28,30 @@ AudioOutput * newAudioOutput(char * name) { if(findInList(audioOutputPluginList, name, &data)) { AudioOutputPlugin * plugin = (AudioOutputPlugin *) data; ret = malloc(sizeof(AudioOutput)); - ret->initConfigFunc = plugin->initConfigFunc; - ret->finishConfigFunc = plugin->finishConfigFunc; - ret->initDriverFunc = plugin->initDriverFunc; ret->finishDriverFunc = plugin->initDriverFunc; ret->openDeviceFunc = plugin->openDeviceFunc; ret->playFunc = plugin->playFunc; ret->closeDeviceFunc = plugin->closeDeviceFunc; + + plugin->initDriverFunc(ret); } return ret; } -void closeAudioOutput(AudioOutput * audioOutput); +int openAudioOutput(AudioOutput * audioOutput, AudioFormat * audioFormat) { + return audioOutput->openDeviceFunc(audioOutput, audioFormat); +} + +int playAudioOutput(AudioOutput * audioOutput, char * playChunk, int size) { + return audioOutput->playFunc(audioOutput, playChunk, size); +} + +void closeAudioOutput(AudioOutput * audioOutput) { + audioOutput->closeDeviceFunc(audioOutput); +} + +void finishAudioOutput(AudioOutput * audioOutput) { + audioOutput->finishDriverFunc(audioOutput); + free(audioOutput); +} diff --git a/src/audioOutput.h b/src/audioOutput.h index 1a01263b8..fd76e4772 100644 --- a/src/audioOutput.h +++ b/src/audioOutput.h @@ -28,10 +28,6 @@ typedef struct _AudioOutput AudioOutput; -typedef void (* AudioOutputInitConfigFunc) (AudioOutput * audioOutput); - -typedef void (* AudioOutputFinishConfigFunc) (AudioOutput * audioOutput); - typedef void (* AudioOutputInitDriverFunc) (AudioOutput * audioOutput); typedef void (* AudioOutputFinishDriverFunc) (AudioOutput * audioOutput); @@ -47,32 +43,30 @@ typedef void (* AudioOutputCloseDeviceFunc) (AudioOutput * audioOutput); struct _AudioOutput { int error; - AudioOutputInitConfigFunc initConfigFunc; - AudioOutputFinishConfigFunc finishConfigFunc; - AudioOutputInitDriverFunc initDriverFunc; AudioOutputFinishDriverFunc finishDriverFunc; AudioOutputOpenDeviceFunc openDeviceFunc; AudioOutputPlayFunc playFunc; - AudioOutputCloseDevicFunc closeDeviceFunc; + AudioOutputCloseDeviceFunc closeDeviceFunc; void * data; }; typedef struct _AudioOutputPlugin { char * name; - AudioOutputInitConfigFunc initConfigFunc; - AudioOutputFinishConfigFunc finishConfigFunc; AudioOutputInitDriverFunc initDriverFunc; AudioOutputFinishDriverFunc finishDriverFunc; AudioOutputOpenDeviceFunc openDeviceFunc; AudioOutputPlayFunc playFunc; - AudioOutputCloseDevicFunc closeDeviceFunc; + AudioOutputCloseDeviceFunc closeDeviceFunc; } AudioOutputPlugin; void loadAudioOutputPlugin(AudioOutputPlugin * audioOutputPlugin); void unloadAudioOutputPlugin(AudioOutputPlugin * audioOutputPlugin); AudioOutput * newAudioOutput(char * name); +int openAudioOutput(AudioOutput * audioOutput, AudioFormat * audioFormat); +int audioOutputPlay(AudioOutput * audioOutput, char * playChunk, int size); void closeAudioOutput(AudioOutput * audioOutput); +void finishAudioOutput(AudioOutput * audioOutput); #endif diff --git a/src/audioOutput_ao.c b/src/audioOutput_ao.c index 385efe2ff..023b7f4a9 100644 --- a/src/audioOutput_ao.c +++ b/src/audioOutput_ao.c @@ -27,14 +27,24 @@ #include <ao/ao.h> -static int audioOutputAo_write_size; +static int driverInitCount = 0; -static int audioOutputAo_driver_id; -static ao_option * audioOutputAo_options; +typedef struct _AoData { + int writeSize; + int driverId; + ao_option * options; + ao_device * device; +} AoData; -static ao_device * audioOutputAo_device = NULL; +static AoData * newAoData() { + AoData * ret = malloc(sizeof(AoData)); + ret->device = NULL; + ret->options = NULL; -void audioOutputAo_initDriver() { + return ret; +} + +static void audioOutputAo_initDriver(AudioOutput * audioOutput) { ao_info * ai; char * dup; char * stk1; @@ -43,28 +53,33 @@ void audioOutputAo_initDriver() { char * key; char * value; char * test; + AoData * ad = newAoData(); - audio_write_size = strtol((getConf())[CONF_AUDIO_WRITE_SIZE],&test,10); + audioOutput->data = ad; + + ad->writeSize = strtol((getConf())[CONF_AUDIO_WRITE_SIZE],&test,10); if (*test!='\0') { ERROR("\"%s\" is not a valid write size", (getConf())[CONF_AUDIO_WRITE_SIZE]); exit(EXIT_FAILURE); } - audio_ao_options = NULL; - - ao_initialize(); + if(driverInitCount == 0) { + ao_initialize(); + } + driverInitCount++; + if(strcmp(AUDIO_AO_DRIVER_DEFAULT,(getConf())[CONF_AO_DRIVER])==0) { - audio_ao_driver_id = ao_default_driver_id(); + ad->driverId = ao_default_driver_id(); } - else if((audio_ao_driver_id = + else if((ad->driverId = ao_driver_id((getConf())[CONF_AO_DRIVER]))<0) { ERROR("\"%s\" is not a valid ao driver\n", (getConf())[CONF_AO_DRIVER]); exit(EXIT_FAILURE); } - if((ai = ao_driver_info(audio_ao_driver_id))==NULL) { + if((ai = ao_driver_info(ad->driverId))==NULL) { ERROR("problems getting ao_driver_info\n"); ERROR("you may not have permission to the audio device\n"); exit(EXIT_FAILURE); @@ -101,135 +116,76 @@ void audioOutputAo_initDriver() { "ao_driver_options \"%s\"\n", n1); exit(EXIT_FAILURE); } - ao_append_option(&audio_ao_options,key,value); + ao_append_option(&ad->options,key,value); n1 = strtok_r(NULL,";",&stk1); } } free(dup); } -void audioOutputAo_initConfig() { - char * conf = getConf()[CONF_AUDIO_OUTPUT_FORMAT]; - char * test; - - if(NULL == conf) return; - - audio_configFormat = malloc(sizeof(AudioFormat)); +static void audioOutputAo_finishDriver(AudioOutput * audioOutput) { + AoData * ad = (AoData *)audioOutput->data; + ao_free_options(ad->options); - memset(audio_configFormat,0,sizeof(AudioFormat)); - - audio_configFormat->sampleRate = strtol(conf,&test,10); - - if(*test!=':') { - ERROR("error parsing audio output format: %s\n",conf); - exit(EXIT_FAILURE); - } - - /*switch(audio_configFormat->sampleRate) { - case 48000: - case 44100: - case 32000: - case 16000: - break; - default: - ERROR("sample rate %i can not be used for audio output\n", - (int)audio_configFormat->sampleRate); - exit(EXIT_FAILURE); - }*/ - - if(audio_configFormat->sampleRate <= 0) { - ERROR("sample rate %i is not >= 0\n", - (int)audio_configFormat->sampleRate); - exit(EXIT_FAILURE); - } - - audio_configFormat->bits = strtol(test+1,&test,10); - - if(*test!=':') { - ERROR("error parsing audio output format: %s\n",conf); - exit(EXIT_FAILURE); - } - - switch(audio_configFormat->bits) { - case 16: - break; - default: - ERROR("bits %i can not be used for audio output\n", - (int)audio_configFormat->bits); - exit(EXIT_FAILURE); - } - - audio_configFormat->channels = strtol(test+1,&test,10); - - if(*test!='\0') { - ERROR("error parsing audio output format: %s\n",conf); - exit(EXIT_FAILURE); - } - - switch(audio_configFormat->channels) { - case 2: - break; - default: - ERROR("channels %i can not be used for audio output\n", - (int)audio_configFormat->channels); - exit(EXIT_FAILURE); - } -} + driverInitCount--; -void audioOutputAo_finishConfig() { - if(audio_configFormat) free(audio_configFormat); + if(driverInitCount == 0) ao_shutdown(); } -void audioOutputAo_finishDriver() { - ao_free_options(audio_ao_options); +static void audioOutputAo_closeDevice(AudioOutput * audioOutput) { + AoData * ad = (AoData *) audioOutput->data; - ao_shutdown(); + if(ad->device) { + blockSignals(); + ao_close(ad->device); + ad->device = NULL; + unblockSignals(); + } } -int audioOutputAo_openDevice(AudioFormat * audioFormat) { +static int audioOutputAo_openDevice(AudioOutput * audioOutput, + AudioFormat * audioFormat) +{ ao_sample_format format; + AoData * ad = (AoData *)audioOutput->data; - if(audio_device && !isCurrentAudioFormat(audioFormat)) { - closeAudioDevice(); + if(ad->device) { + audioOutputAo_closeDevice(audioOutput); } - if(!audio_device) { - if(audioFormat) { - copyAudioFormat(&audio_format,audioFormat); - } + format.bits = audioFormat->bits; + format.rate = audioFormat->sampleRate; + format.byte_format = AO_FMT_NATIVE; + format.channels = audioFormat->channels; - format.bits = audio_format.bits; - format.rate = audio_format.sampleRate; - format.byte_format = AO_FMT_NATIVE; - format.channels = audio_format.channels; + blockSignals(); + ad->device = ao_open_live(ad->driverId, &format, ad->options); + unblockSignals(); - blockSignals(); - audio_device = ao_open_live(audio_ao_driver_id, &format, - audio_ao_options); - unblockSignals(); - - if(audio_device==NULL) return -1; - } + if(ad->device==NULL) return -1; return 0; } -int audioOutputAo_playAudio(char * playChunk, int size) { +static int audioOutputAo_play(AudioOutput * audioOutput, char * playChunk, + int size) +{ int send; + AoData * ad = (AoData *)audioOutput->data; - if(audio_device==NULL) { + if(ad->device==NULL) { ERROR("trying to play w/o the audio device being open!\n"); return -1; } while(size>0) { - send = audio_write_size>size?size:audio_write_size; + send = ad->writeSize > size ? size : ad->writeSize; - if(ao_play(audio_device,playChunk,send)==0) { + if(ao_play(ad->device, playChunk, send)==0) { audioError(); ERROR("closing audio device due to write error\n"); - closeAudioDevice(); + audioOutputAo_closeDevice(audioOutput); return -1; } @@ -240,20 +196,9 @@ int audioOutputAo_playAudio(char * playChunk, int size) { return 0; } -void audioOutputAo_closeAudioDevice() { - if(audio_device) { - blockSignals(); - ao_close(audio_device); - audio_device = NULL; - unblockSignals(); - } -} - AudioOutputPlugin aoPlugin = { "ao", - audioOutputAo_initConfig, - audioOutputAo_finishConfig, audioOutputAo_initDriver, audioOutputAo_finishDriver, audioOutputAo_openDevice, |