audio: output selection functionality
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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)" : "");
|
||||
}
|
||||
@@ -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
@@ -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
@@ -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
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
+5
-2
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user