diff options
Diffstat (limited to '')
-rw-r--r-- | src/audio.c | 8 | ||||
-rw-r--r-- | src/audioOutput.c | 108 | ||||
-rw-r--r-- | src/audioOutput.h | 3 | ||||
-rw-r--r-- | src/audioOutputs/audioOutput_alsa.c | 24 | ||||
-rw-r--r-- | src/audioOutputs/audioOutput_ao.c | 2 | ||||
-rw-r--r-- | src/audioOutputs/audioOutput_oss.c | 44 | ||||
-rw-r--r-- | src/audioOutputs/audioOutput_shout.c | 2 | ||||
-rw-r--r-- | src/log.c | 3 | ||||
-rw-r--r-- | src/main.c | 2 |
9 files changed, 149 insertions, 47 deletions
diff --git a/src/audio.c b/src/audio.c index 728f93718..c3b87fa5b 100644 --- a/src/audio.c +++ b/src/audio.c @@ -79,7 +79,9 @@ void initAudioDriver() { myAudioDevicesEnabled[i] = 1; } - while((param = getNextConfigParam(CONF_AUDIO_OUTPUT, param))) { + param = getNextConfigParam(CONF_AUDIO_OUTPUT, param); + + do { if(audioOutputArraySize == AUDIO_MAX_DEVICES) { ERROR("only up to 255 audio output devices are " "supported"); @@ -93,12 +95,12 @@ void initAudioDriver() { audioOutputArray[i] = newAudioOutput(param); - if(!audioOutputArray[i]) { + if(!audioOutputArray[i] && param) { ERROR("problems configuring output device defined at " "line %i\n", param->line); exit(EXIT_FAILURE); } - } + } while((param = getNextConfigParam(CONF_AUDIO_OUTPUT, param))); } void getOutputAudioFormat(AudioFormat * inAudioFormat, diff --git a/src/audioOutput.c b/src/audioOutput.c index 1186dbe0d..632d1b8dc 100644 --- a/src/audioOutput.c +++ b/src/audioOutput.c @@ -48,55 +48,87 @@ AudioOutput * newAudioOutput(ConfigParam * param) { char * name = NULL; char * format = NULL; char * type = NULL; - BlockParam * bp; - - getBlockParam(AUDIO_OUTPUT_NAME, name, 1); - getBlockParam(AUDIO_OUTPUT_TYPE, type, 1); - - if(findInList(audioOutputPluginList, type, &data)) { - AudioOutputPlugin * plugin = (AudioOutputPlugin *) data; - ret = malloc(sizeof(AudioOutput)); - ret->name = strdup(name); - ret->type = strdup(type); - ret->finishDriverFunc = plugin->finishDriverFunc; - ret->openDeviceFunc = plugin->openDeviceFunc; - ret->playFunc = plugin->playFunc; - ret->dropBufferedAudioFunc = plugin->dropBufferedAudioFunc; - ret->closeDeviceFunc = plugin->closeDeviceFunc; - ret->sendMetdataFunc = plugin->sendMetdataFunc; - ret->open = 0; - - ret->convertAudioFormat = 0; - ret->sameInAndOutFormats = 0; - ret->convBuffer = NULL; - ret->convBufferLen = 0; - - memset(&ret->inAudioFormat, 0, sizeof(AudioFormat)); - memset(&ret->outAudioFormat, 0, sizeof(AudioFormat)); - memset(&ret->reqAudioFormat, 0, sizeof(AudioFormat)); - - getBlockParam(AUDIO_OUTPUT_FORMAT, format, 0); + BlockParam * bp = NULL; + AudioOutputPlugin * plugin = NULL; + + if(param) { + getBlockParam(AUDIO_OUTPUT_NAME, name, 1); + getBlockParam(AUDIO_OUTPUT_TYPE, type, 1); + + if(!findInList(audioOutputPluginList, type, &data)) { + ERROR("couldn't find audio output plugin for type " + "\"%s\" at line %i\n", type, + param->line); + exit(EXIT_FAILURE); + } + plugin = (AudioOutputPlugin *) data; + if(format) { ret->convertAudioFormat = 1; if(0 != parseAudioConfig(&ret->reqAudioFormat, format)) { - ERROR("error parsing format at line %i\n", + ERROR("error parsing format at line %i\n", bp->line); - exit(EXIT_FAILURE); - } + exit(EXIT_FAILURE); + } + } + } + else { + ListNode * node = audioOutputPluginList->firstNode; + + WARNING("No \"%s\" defined in config file\n", + CONF_AUDIO_OUTPUT); + WARNING("Attempt to detect audio output device\n"); + + while(node) { + plugin = (AudioOutputPlugin *) node->data; + if(plugin->testDefaultDeviceFunc) { + WARNING("Attempting to detect a %s audio " + "device\n", plugin->name); + if(plugin->testDefaultDeviceFunc() == 0) { + WARNING("Successfully detected a %s " + "audio device\n", + plugin->name); + break; + } + } + node = node->nextNode; } - if(plugin->initDriverFunc(ret, param) != 0) { - free(ret); - ret = NULL; + if(!node) { + WARNING("Unable to detect an audio device\n"); + return NULL; } + + name = "default detected output"; + type = plugin->name; } - else { - ERROR("couldn't find audio output plugin for type \"%s\" at " - "line %i\n", type, param->line); - exit(EXIT_FAILURE); + + ret = malloc(sizeof(AudioOutput)); + ret->name = strdup(name); + ret->type = strdup(type); + ret->finishDriverFunc = plugin->finishDriverFunc; + ret->openDeviceFunc = plugin->openDeviceFunc; + ret->playFunc = plugin->playFunc; + ret->dropBufferedAudioFunc = plugin->dropBufferedAudioFunc; + ret->closeDeviceFunc = plugin->closeDeviceFunc; + ret->sendMetdataFunc = plugin->sendMetdataFunc; + ret->open = 0; + + ret->convertAudioFormat = 0; + ret->sameInAndOutFormats = 0; + ret->convBuffer = NULL; + ret->convBufferLen = 0; + + memset(&ret->inAudioFormat, 0, sizeof(AudioFormat)); + memset(&ret->outAudioFormat, 0, sizeof(AudioFormat)); + memset(&ret->reqAudioFormat, 0, sizeof(AudioFormat)); + + if(plugin->initDriverFunc(ret, param) != 0) { + free(ret); + ret = NULL; } return ret; diff --git a/src/audioOutput.h b/src/audioOutput.h index 85868eaeb..b0ae4810d 100644 --- a/src/audioOutput.h +++ b/src/audioOutput.h @@ -28,6 +28,8 @@ typedef struct _AudioOutput AudioOutput; +typedef int (* AudioOutputTestDefaultDeviceFunc) (); + typedef int (* AudioOutputInitDriverFunc) (AudioOutput * audioOutput, ConfigParam * param); @@ -71,6 +73,7 @@ struct _AudioOutput { typedef struct _AudioOutputPlugin { char * name; + AudioOutputTestDefaultDeviceFunc testDefaultDeviceFunc; AudioOutputInitDriverFunc initDriverFunc; AudioOutputFinishDriverFunc finishDriverFunc; AudioOutputOpenDeviceFunc openDeviceFunc; diff --git a/src/audioOutputs/audioOutput_alsa.c b/src/audioOutputs/audioOutput_alsa.c index d804720b0..9cc15c842 100644 --- a/src/audioOutputs/audioOutput_alsa.c +++ b/src/audioOutputs/audioOutput_alsa.c @@ -69,7 +69,10 @@ static void freeAlsaData(AlsaData * ad) { } static int alsa_initDriver(AudioOutput * audioOutput, ConfigParam * param) { - BlockParam * bp = getBlockParam(param, "device"); + BlockParam * bp = NULL; + + if(param) bp = getBlockParam(param, "device"); + AlsaData * ad = newAlsaData(); audioOutput->data = ad; @@ -85,6 +88,23 @@ static void alsa_finishDriver(AudioOutput * audioOutput) { freeAlsaData(ad); } +static int alsa_testDefault() +{ + snd_pcm_t * handle; + + int ret = snd_pcm_open(&handle, "default", SND_PCM_STREAM_PLAYBACK, + SND_PCM_NONBLOCK); + + if(ret) { + WARNING("Error opening default alsa device: %s\n", + snd_strerror(-ret)); + return -1; + } + else snd_pcm_close(handle); + + return 0; +} + static int alsa_openDevice(AudioOutput * audioOutput) { AlsaData * ad = audioOutput->data; @@ -313,6 +333,7 @@ static int alsa_playAudio(AudioOutput * audioOutput, char * playChunk, AudioOutputPlugin alsaPlugin = { "alsa", + alsa_testDefault, alsa_initDriver, alsa_finishDriver, alsa_openDevice, @@ -332,6 +353,7 @@ AudioOutputPlugin alsaPlugin = NULL, NULL, NULL, + NULL, NULL /* sendMetadataFunc */ }; diff --git a/src/audioOutputs/audioOutput_ao.c b/src/audioOutputs/audioOutput_ao.c index 380e6e9d5..25dd3ff10 100644 --- a/src/audioOutputs/audioOutput_ao.c +++ b/src/audioOutputs/audioOutput_ao.c @@ -237,6 +237,7 @@ static int audioOutputAo_play(AudioOutput * audioOutput, char * playChunk, AudioOutputPlugin aoPlugin = { "ao", + NULL, audioOutputAo_initDriver, audioOutputAo_finishDriver, audioOutputAo_openDevice, @@ -259,6 +260,7 @@ AudioOutputPlugin aoPlugin = NULL, NULL, NULL, + NULL, NULL }; diff --git a/src/audioOutputs/audioOutput_oss.c b/src/audioOutputs/audioOutput_oss.c index b3ad9bff4..fc703bd90 100644 --- a/src/audioOutputs/audioOutput_oss.c +++ b/src/audioOutputs/audioOutput_oss.c @@ -291,10 +291,38 @@ static int oss_statDevice(char * device, int * stErrno) { return 0; } +static int oss_testDefault() { + int fd; + + fd = open("/dev/sound/dsp", O_WRONLY); + + if(fd) { + close(fd); + return 0; + } + + WARNING("Error opening OSS device \"/dev/sound/dsp\": %s\n", + strerror(errno)); + + fd = open("/dev/dsp", O_WRONLY); + + if(fd) { + close(fd); + return 0; + } + + WARNING("Error opening OSS device \"/dev/dsp\": %s\n", + strerror(errno)); + + return -1; +} + static int oss_initDriver(AudioOutput * audioOutput, ConfigParam * param) { - BlockParam * bp = getBlockParam(param, "device"); + BlockParam * bp = NULL; + + if(param) bp = getBlockParam(param, "device"); + OssData * od = newOssData(); - audioOutput->data = od; if(!bp) { @@ -307,8 +335,14 @@ static int oss_initDriver(AudioOutput * audioOutput, ConfigParam * param) { if(ret[0] == 0) od->device = strdup("/dev/sound/dsp"); else if(ret[1] == 0) od->device = strdup("/dev/dsp"); else { - ERROR("Error trying to open default OSS device " - "specified at line %i\n", param->line); + if(param) { + ERROR("Error trying to open default OSS device " + "specified at line %i\n", param->line); + } + else { + ERROR("Error trying to open default OSS " + "device\n"); + } if(ret[0] == ret[1] == OSS_STAT_DOESN_T_EXIST) { ERROR("Neither /dev/dsp nor /dev/sound/dsp " @@ -501,6 +535,7 @@ static int oss_playAudio(AudioOutput * audioOutput, char * playChunk, AudioOutputPlugin ossPlugin = { "oss", + oss_testDefault, oss_initDriver, oss_finishDriver, oss_openDevice, @@ -521,6 +556,7 @@ AudioOutputPlugin ossPlugin = NULL, NULL, NULL, + NULL, NULL /* sendMetadataFunc */ }; diff --git a/src/audioOutputs/audioOutput_shout.c b/src/audioOutputs/audioOutput_shout.c index 9a54eb8a9..322f7e325 100644 --- a/src/audioOutputs/audioOutput_shout.c +++ b/src/audioOutputs/audioOutput_shout.c @@ -597,6 +597,7 @@ static void myShout_setTag(AudioOutput * audioOutput, MpdTag * tag) { AudioOutputPlugin shoutPlugin = { "shout", + NULL, myShout_initDriver, myShout_finishDriver, myShout_openDevice, @@ -617,6 +618,7 @@ AudioOutputPlugin shoutPlugin = NULL, NULL, NULL, + NULL, NULL }; @@ -68,9 +68,12 @@ void bufferWarning(char * format, ... ) { va_end(arglist); } + void flushWarningLog() { char * s; + DEBUG("flushing warning messages\n"); + if(warningBuffer == NULL) return; s = strtok(warningBuffer, "\n"); diff --git a/src/main.c b/src/main.c index 11ad00efd..8cce240d3 100644 --- a/src/main.c +++ b/src/main.c @@ -357,8 +357,8 @@ void setupLogOutput(Options * options, FILE * out, FILE * err) { } myfprintfStdLogMode(out, err); - flushWarningLog(); } + flushWarningLog(); /* lets redirect stdin to dev null as a work around for libao bug */ { |