audio: output selection functionality

This commit is contained in:
James Laird
2013-04-01 21:43:24 +11:00
parent 86e94064c0
commit 9b33878c59
8 changed files with 84 additions and 20 deletions
+2 -2
View File
@@ -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
+40
View File
@@ -0,0 +1,40 @@
#include <stdio.h>
#include <string.h>
#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)" : "");
}
+6 -3
View File
@@ -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
+11 -1
View File
@@ -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=<id>\n"
" -n name shorthand for -o dev=<name> -o dsp=<name>\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,
+17 -11
View File
@@ -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
};
+2 -1
View File
@@ -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;
+1
View File
@@ -0,0 +1 @@
#define CONFIG_AO
+5 -2
View File
@@ -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.