diff --git a/Makefile b/Makefile index 7f3e39b2..629c705b 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ -SRCS := shairport.c rtsp.c mdns.c common.c rtp.c player.c alac.c $(wildcard audio_*.c) +SRCS := shairport.c rtsp.c mdns.c audio.c common.c rtp.c player.c alac.c $(wildcard audio_*.c) LIBS := -lcrypto -lm -lao -lpthread shairport: $(SRCS) - gcc -ggdb -Wall $(SRCS) $(LIBS) -o shairport + gcc -ggdb -Wall -Wno-unused-value $(SRCS) $(LIBS) -o shairport diff --git a/audio.c b/audio.c new file mode 100644 index 00000000..ff29c222 --- /dev/null +++ b/audio.c @@ -0,0 +1,40 @@ +#include +#include +#include "audio.h" +#include "config.h" + +#ifdef CONFIG_AO +extern audio_output audio_ao; +#endif +extern audio_output audio_dummy; + +static audio_output *outputs[] = { +#ifdef CONFIG_AO + &audio_ao, +#endif + &audio_dummy, + NULL +}; + + +audio_output *audio_get_output(char *name) { + audio_output **out; + + // default to the first + if (!name) + return outputs[0]; + + for (out=outputs; *out; out++) + if (!strcasecmp(name, (*out)->name)) + return *out; + + return NULL; +} + +void audio_ls_outputs(void) { + audio_output **out; + + printf("Available audio outputs:\n"); + for (out=outputs; *out; out++) + printf(" %s%s\n", (*out)->name, out==outputs ? " (default)" : ""); +} diff --git a/audio.h b/audio.h index a1d65c8f..66c9c2f0 100644 --- a/audio.h +++ b/audio.h @@ -2,6 +2,9 @@ #define _AUDIO_H typedef struct { + void (*help)(void); + char *name; + // start of program int (*init)(int argc, char **argv); // at end of program @@ -14,9 +17,9 @@ typedef struct { // may be NULL, in which case soft volume is applied void (*volume)(double vol); -} audio_ops; +} audio_output; -extern audio_ops audio_dummy; -extern audio_ops audio_ao; +audio_output *audio_get_output(char *name); +void audio_ls_outputs(void); #endif //_AUDIO_H diff --git a/audio_ao.c b/audio_ao.c index 704b63b6..b762bdc0 100644 --- a/audio_ao.c +++ b/audio_ao.c @@ -7,6 +7,14 @@ ao_device *dev = NULL; +static void help(void) { + printf(" -d driver set the output driver\n" + " -o name=value set an arbitrary ao option\n" + " -i id shorthand for -o id=\n" + " -n name shorthand for -o dev= -o dsp=\n" + ); +} + static int init(int argc, char **argv) { printf("ao: init\n"); ao_initialize(); @@ -43,7 +51,9 @@ static void play(short buf[], int samples) { static void stop(void) { } -audio_ops audio_ao = { +audio_output audio_ao = { + .name = "ao", + .help = &help, .init = &init, .deinit = &deinit, .start = &start, diff --git a/audio_dummy.c b/audio_dummy.c index 7eab0544..24c05094 100644 --- a/audio_dummy.c +++ b/audio_dummy.c @@ -6,21 +6,21 @@ int Fs; long long starttime, samples_played; -static int dummy_init(int argc, char **argv) { +static int init(int argc, char **argv) { return 0; } -static void dummy_deinit(void) { +static void deinit(void) { } -static void dummy_start(int sample_rate) { +static void start(int sample_rate) { Fs = sample_rate; starttime = 0; samples_played = 0; printf("dummy audio output started at Fs=%d Hz\n", sample_rate); } -static void dummy_play(short buf[], int samples) { +static void play(short buf[], int samples) { struct timeval tv; // this is all a bit expensive but it's long-term stable. @@ -38,15 +38,21 @@ static void dummy_play(short buf[], int samples) { usleep(finishtime - nowtime); } -static void dummy_stop(void) { +static void stop(void) { printf("dummy audio stopped\n"); } -audio_ops audio_dummy = { - .init = &dummy_init, - .deinit = &dummy_deinit, - .start = &dummy_start, - .stop = &dummy_stop, - .play = &dummy_play, +static void help(void) { + printf("There are no options for dummy audio.\n"); +} + +audio_output audio_dummy = { + .name = "dummy", + .help = &help, + .init = &init, + .deinit = &deinit, + .start = &start, + .stop = &stop, + .play = &play, .volume = NULL }; diff --git a/common.h b/common.h index cf64b3e4..02d2d089 100644 --- a/common.h +++ b/common.h @@ -10,7 +10,8 @@ typedef struct { char *apname; char hw_addr[6]; int port; - audio_ops *output; + char *output_name; + audio_output *output; int buffer_start_fill; } shairport_cfg; diff --git a/config.h b/config.h new file mode 100644 index 00000000..111a93db --- /dev/null +++ b/config.h @@ -0,0 +1 @@ +#define CONFIG_AO diff --git a/shairport.c b/shairport.c index ffb113cc..32079094 100644 --- a/shairport.c +++ b/shairport.c @@ -31,8 +31,11 @@ int main(int argc, char **argv) { config.port = 9000; config.apname = "hellothere"; - config.output = &audio_dummy; - //config.output = &audio_ao; + config.output = audio_get_output(config.output_name); + if (!config.output) { + audio_ls_outputs(); + die("Invalid audio output specified!\n"); + } // mask off all signals before creating threads. // this way we control which thread gets which signals.