aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/audio.c8
-rw-r--r--src/audioOutput.c108
-rw-r--r--src/audioOutput.h3
-rw-r--r--src/audioOutputs/audioOutput_alsa.c24
-rw-r--r--src/audioOutputs/audioOutput_ao.c2
-rw-r--r--src/audioOutputs/audioOutput_oss.c44
-rw-r--r--src/audioOutputs/audioOutput_shout.c2
-rw-r--r--src/log.c3
-rw-r--r--src/main.c2
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
};
diff --git a/src/log.c b/src/log.c
index 964b8aa66..e50b14f9b 100644
--- a/src/log.c
+++ b/src/log.c
@@ -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 */
{