diff options
author | Max Kellermann <max@duempel.org> | 2009-02-10 18:51:49 +0100 |
---|---|---|
committer | Max Kellermann <max@duempel.org> | 2009-02-10 18:51:49 +0100 |
commit | a3a6eefcfe6f8b8129ac36a70243ca90e651a7fc (patch) | |
tree | 8f30130c658f5f819da2ec4f659159654b741aba /src | |
parent | e7505381eb4fa708afa7de6fd50f29736ccf3d5e (diff) | |
download | mpd-a3a6eefcfe6f8b8129ac36a70243ca90e651a7fc.tar.gz mpd-a3a6eefcfe6f8b8129ac36a70243ca90e651a7fc.tar.xz mpd-a3a6eefcfe6f8b8129ac36a70243ca90e651a7fc.zip |
audio: moved code to output_all.c
Moved code which deals with all audio outputs at once into a separate
library.
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile.am | 2 | ||||
-rw-r--r-- | src/audio.c | 275 | ||||
-rw-r--r-- | src/audio.h | 40 | ||||
-rw-r--r-- | src/main.c | 1 | ||||
-rw-r--r-- | src/output_all.c | 270 | ||||
-rw-r--r-- | src/output_all.h | 69 | ||||
-rw-r--r-- | src/output_print.c | 2 | ||||
-rw-r--r-- | src/output_state.c | 2 | ||||
-rw-r--r-- | src/player_thread.c | 2 | ||||
-rw-r--r-- | src/volume.c | 1 |
10 files changed, 366 insertions, 298 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index 140c0f436..98fe8bea7 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -39,6 +39,7 @@ mpd_headers = \ output_internal.h \ output_api.h \ output_list.h \ + output_all.h \ output_thread.h \ output_control.h \ output_state.h \ @@ -138,6 +139,7 @@ mpd_SOURCES = \ audioOutput.c \ output_api.c \ output_list.c \ + output_all.c \ output_thread.c \ output_control.c \ output_state.c \ diff --git a/src/audio.c b/src/audio.c index 56aa70921..d3e66fdb2 100644 --- a/src/audio.c +++ b/src/audio.c @@ -21,6 +21,7 @@ #include "output_api.h" #include "output_control.h" #include "output_internal.h" +#include "output_all.h" #include "path.h" #include "idle.h" #include "mixer_api.h" @@ -31,94 +32,6 @@ #include <stdlib.h> static struct audio_format configured_audio_format; -static struct audio_format input_audio_format; - -static struct audio_output *audioOutputArray; -static unsigned int audioOutputArraySize; - -unsigned int audio_output_count(void) -{ - return audioOutputArraySize; -} - -struct audio_output * -audio_output_get(unsigned i) -{ - assert(i < audioOutputArraySize); - - return &audioOutputArray[i]; -} - -struct audio_output * -audio_output_find(const char *name) -{ - for (unsigned i = 0; i < audioOutputArraySize; ++i) { - struct audio_output *ao = audio_output_get(i); - - if (strcmp(ao->name, name) == 0) - return ao; - } - - /* name not found */ - return NULL; -} - -static unsigned -audio_output_config_count(void) -{ - unsigned int nr = 0; - const struct config_param *param = NULL; - - while ((param = config_get_next_param(CONF_AUDIO_OUTPUT, param))) - nr++; - if (!nr) - nr = 1; /* we'll always have at least one device */ - return nr; -} - -/* make sure initPlayerData is called before this function!! */ -void initAudioDriver(void) -{ - const struct config_param *param = NULL; - unsigned int i; - - notify_init(&audio_output_client_notify); - - audioOutputArraySize = audio_output_config_count(); - audioOutputArray = g_new(struct audio_output, audioOutputArraySize); - - for (i = 0; i < audioOutputArraySize; i++) - { - struct audio_output *output = &audioOutputArray[i]; - unsigned int j; - - param = config_get_next_param(CONF_AUDIO_OUTPUT, param); - - /* only allow param to be NULL if there just one audioOutput */ - assert(param || (audioOutputArraySize == 1)); - - if (!audio_output_init(output, param)) { - if (param) - { - g_error("problems configuring output device " - "defined at line %i\n", param->line); - } - else - { - g_error("No audio_output specified and unable to " - "detect a default audio output device\n"); - } - } - - /* require output names to be unique: */ - for (j = 0; j < i; j++) { - if (!strcmp(output->name, audioOutputArray[j].name)) { - g_error("output devices with identical " - "names: %s\n", output->name); - } - } - } -} void getOutputAudioFormat(const struct audio_format *inAudioFormat, struct audio_format *outAudioFormat) @@ -199,171 +112,17 @@ void finishAudioConfig(void) audio_format_clear(&configured_audio_format); } -void finishAudioDriver(void) -{ - unsigned int i; - - for (i = 0; i < audioOutputArraySize; i++) { - audio_output_finish(&audioOutputArray[i]); - } - - g_free(audioOutputArray); - audioOutputArray = NULL; - audioOutputArraySize = 0; - - notify_deinit(&audio_output_client_notify); -} - -static void audio_output_wait_all(void) -{ - unsigned i; - - while (1) { - int finished = 1; - - for (i = 0; i < audioOutputArraySize; ++i) - if (audio_output_is_open(&audioOutputArray[i]) && - !audio_output_command_is_finished(&audioOutputArray[i])) - finished = 0; - - if (finished) - break; - - notify_wait(&audio_output_client_notify); - }; -} - -static void syncAudioDeviceStates(void) -{ - unsigned int i; - - if (!audio_format_defined(&input_audio_format)) - return; - - for (i = 0; i < audioOutputArraySize; ++i) - audio_output_update(&audioOutputArray[i], &input_audio_format); -} - -bool playAudio(const char *buffer, size_t length) -{ - bool ret = false; - unsigned int i; - - assert(length > 0); - /* no partial frames allowed */ - assert((length % audio_format_frame_size(&input_audio_format)) == 0); - - syncAudioDeviceStates(); - - for (i = 0; i < audioOutputArraySize; ++i) - if (audio_output_is_open(&audioOutputArray[i])) - audio_output_play(&audioOutputArray[i], - buffer, length); - - while (true) { - bool finished = true; - - for (i = 0; i < audioOutputArraySize; ++i) { - struct audio_output *ao = &audioOutputArray[i]; - - if (!audio_output_is_open(ao)) - continue; - - if (audio_output_command_is_finished(ao)) - ret = true; - else { - finished = false; - audio_output_signal(ao); - } - } - - if (finished) - break; - - notify_wait(&audio_output_client_notify); - }; - - return ret; -} - -bool openAudioDevice(const struct audio_format *audioFormat) -{ - bool ret = false; - unsigned int i; - - if (!audioOutputArray) - return false; - - if (audioFormat != NULL) - input_audio_format = *audioFormat; - - syncAudioDeviceStates(); - - for (i = 0; i < audioOutputArraySize; ++i) { - if (audioOutputArray[i].open) - ret = true; - } - - if (!ret) - /* close all devices if there was an error */ - closeAudioDevice(); - - return ret; -} - -void audio_output_pause_all(void) -{ - unsigned int i; - - syncAudioDeviceStates(); - - for (i = 0; i < audioOutputArraySize; ++i) - if (audio_output_is_open(&audioOutputArray[i])) - audio_output_pause(&audioOutputArray[i]); - - audio_output_wait_all(); -} - -void dropBufferedAudio(void) -{ - unsigned int i; - - syncAudioDeviceStates(); - - for (i = 0; i < audioOutputArraySize; ++i) { - if (audio_output_is_open(&audioOutputArray[i])) - audio_output_cancel(&audioOutputArray[i]); - } - - audio_output_wait_all(); -} - -void closeAudioDevice(void) -{ - unsigned int i; - - for (i = 0; i < audioOutputArraySize; ++i) - audio_output_close(&audioOutputArray[i]); -} - -void sendMetadataToAudioDevice(const struct tag *tag) -{ - unsigned int i; - - for (i = 0; i < audioOutputArraySize; ++i) - if (audio_output_is_open(&audioOutputArray[i])) - audio_output_send_tag(&audioOutputArray[i], tag); - - audio_output_wait_all(); -} - int enableAudioDevice(unsigned int device) { - if (device >= audioOutputArraySize) + struct audio_output *ao; + + if (device >= audio_output_count()) return -1; - audioOutputArray[device].reopen_after = 0; - audioOutputArray[device].enabled = true; + ao = audio_output_get(device); + + ao->reopen_after = 0; + ao->enabled = true; idle_add(IDLE_OUTPUT); return 0; @@ -371,10 +130,14 @@ int enableAudioDevice(unsigned int device) int disableAudioDevice(unsigned int device) { - if (device >= audioOutputArraySize) + struct audio_output *ao; + + if (device >= audio_output_count()) return -1; - audioOutputArray[device].enabled = false; + ao = audio_output_get(device); + + ao->enabled = false; idle_add(IDLE_OUTPUT); return 0; @@ -383,10 +146,11 @@ int disableAudioDevice(unsigned int device) bool mixer_control_setvol(unsigned int device, int volume, int rel) { struct audio_output *output; - if (device >= audioOutputArraySize) + + if (device >= audio_output_count()) return false; - output = &audioOutputArray[device]; + output = audio_output_get(device); if (output->plugin && output->plugin->control) { if (rel) { int cur_volume; @@ -408,10 +172,11 @@ bool mixer_control_setvol(unsigned int device, int volume, int rel) bool mixer_control_getvol(unsigned int device, int *volume) { struct audio_output *output; - if (device >= audioOutputArraySize) + + if (device >= audio_output_count()) return false; - output = &audioOutputArray[device]; + output = audio_output_get(device); if (output->plugin && output->plugin->control) { return output->plugin->control(output->data, AC_MIXER_GETVOL, volume); } diff --git a/src/audio.h b/src/audio.h index 2ccebc358..865890485 100644 --- a/src/audio.h +++ b/src/audio.h @@ -20,32 +20,8 @@ #define MPD_AUDIO_H #include <stdbool.h> -#include <stddef.h> - -#define AUDIO_AO_DRIVER_DEFAULT "default" struct audio_format; -struct tag; -struct config_param; - -/** - * Returns the total number of audio output devices, including those - * who are disabled right now. - */ -unsigned int audio_output_count(void); - -/** - * Returns the "i"th audio output device. - */ -struct audio_output * -audio_output_get(unsigned i); - -/** - * Returns the audio output device with the specified name. Returns - * NULL if the name does not exist. - */ -struct audio_output * -audio_output_find(const char *name); void getOutputAudioFormat(const struct audio_format *inFormat, struct audio_format *outFormat); @@ -57,22 +33,6 @@ void initAudioConfig(void); void finishAudioConfig(void); -void initAudioDriver(void); - -void finishAudioDriver(void); - -bool openAudioDevice(const struct audio_format *audioFormat); - -bool playAudio(const char *playChunk, size_t size); - -void audio_output_pause_all(void); - -void dropBufferedAudio(void); - -void closeAudioDevice(void); - -void sendMetadataToAudioDevice(const struct tag *tag); - /* these functions are called in the main parent process while the child process is busy playing to the audio */ int enableAudioDevice(unsigned int device); diff --git a/src/main.c b/src/main.c index 7df773146..5dc07975e 100644 --- a/src/main.c +++ b/src/main.c @@ -37,6 +37,7 @@ #include "stats.h" #include "sig_handlers.h" #include "audio.h" +#include "output_all.h" #include "volume.h" #include "log.h" #include "permission.h" diff --git a/src/output_all.c b/src/output_all.c new file mode 100644 index 000000000..dff84e04a --- /dev/null +++ b/src/output_all.c @@ -0,0 +1,270 @@ +/* + * Copyright (C) 2003-2009 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "output_all.h" +#include "output_internal.h" +#include "output_control.h" + +#include <assert.h> + +static struct audio_format input_audio_format; + +static struct audio_output *audioOutputArray; +static unsigned int audioOutputArraySize; + +unsigned int audio_output_count(void) +{ + return audioOutputArraySize; +} + +struct audio_output * +audio_output_get(unsigned i) +{ + assert(i < audioOutputArraySize); + + return &audioOutputArray[i]; +} + +struct audio_output * +audio_output_find(const char *name) +{ + for (unsigned i = 0; i < audioOutputArraySize; ++i) { + struct audio_output *ao = audio_output_get(i); + + if (strcmp(ao->name, name) == 0) + return ao; + } + + /* name not found */ + return NULL; +} + +static unsigned +audio_output_config_count(void) +{ + unsigned int nr = 0; + const struct config_param *param = NULL; + + while ((param = config_get_next_param(CONF_AUDIO_OUTPUT, param))) + nr++; + if (!nr) + nr = 1; /* we'll always have at least one device */ + return nr; +} + +/* make sure initPlayerData is called before this function!! */ +void initAudioDriver(void) +{ + const struct config_param *param = NULL; + unsigned int i; + + notify_init(&audio_output_client_notify); + + audioOutputArraySize = audio_output_config_count(); + audioOutputArray = g_new(struct audio_output, audioOutputArraySize); + + for (i = 0; i < audioOutputArraySize; i++) + { + struct audio_output *output = &audioOutputArray[i]; + unsigned int j; + + param = config_get_next_param(CONF_AUDIO_OUTPUT, param); + + /* only allow param to be NULL if there just one audioOutput */ + assert(param || (audioOutputArraySize == 1)); + + if (!audio_output_init(output, param)) { + if (param) + { + g_error("problems configuring output device " + "defined at line %i\n", param->line); + } + else + { + g_error("No audio_output specified and unable to " + "detect a default audio output device\n"); + } + } + + /* require output names to be unique: */ + for (j = 0; j < i; j++) { + if (!strcmp(output->name, audioOutputArray[j].name)) { + g_error("output devices with identical " + "names: %s\n", output->name); + } + } + } +} + +void finishAudioDriver(void) +{ + unsigned int i; + + for (i = 0; i < audioOutputArraySize; i++) { + audio_output_finish(&audioOutputArray[i]); + } + + g_free(audioOutputArray); + audioOutputArray = NULL; + audioOutputArraySize = 0; + + notify_deinit(&audio_output_client_notify); +} + +static void audio_output_wait_all(void) +{ + unsigned i; + + while (1) { + int finished = 1; + + for (i = 0; i < audioOutputArraySize; ++i) + if (audio_output_is_open(&audioOutputArray[i]) && + !audio_output_command_is_finished(&audioOutputArray[i])) + finished = 0; + + if (finished) + break; + + notify_wait(&audio_output_client_notify); + }; +} + +static void syncAudioDeviceStates(void) +{ + unsigned int i; + + if (!audio_format_defined(&input_audio_format)) + return; + + for (i = 0; i < audioOutputArraySize; ++i) + audio_output_update(&audioOutputArray[i], &input_audio_format); +} + +bool playAudio(const char *buffer, size_t length) +{ + bool ret = false; + unsigned int i; + + assert(length > 0); + /* no partial frames allowed */ + assert((length % audio_format_frame_size(&input_audio_format)) == 0); + + syncAudioDeviceStates(); + + for (i = 0; i < audioOutputArraySize; ++i) + if (audio_output_is_open(&audioOutputArray[i])) + audio_output_play(&audioOutputArray[i], + buffer, length); + + while (true) { + bool finished = true; + + for (i = 0; i < audioOutputArraySize; ++i) { + struct audio_output *ao = &audioOutputArray[i]; + + if (!audio_output_is_open(ao)) + continue; + + if (audio_output_command_is_finished(ao)) + ret = true; + else { + finished = false; + audio_output_signal(ao); + } + } + + if (finished) + break; + + notify_wait(&audio_output_client_notify); + }; + + return ret; +} + +bool openAudioDevice(const struct audio_format *audioFormat) +{ + bool ret = false; + unsigned int i; + + if (!audioOutputArray) + return false; + + if (audioFormat != NULL) + input_audio_format = *audioFormat; + + syncAudioDeviceStates(); + + for (i = 0; i < audioOutputArraySize; ++i) { + if (audioOutputArray[i].open) + ret = true; + } + + if (!ret) + /* close all devices if there was an error */ + closeAudioDevice(); + + return ret; +} + +void audio_output_pause_all(void) +{ + unsigned int i; + + syncAudioDeviceStates(); + + for (i = 0; i < audioOutputArraySize; ++i) + if (audio_output_is_open(&audioOutputArray[i])) + audio_output_pause(&audioOutputArray[i]); + + audio_output_wait_all(); +} + +void dropBufferedAudio(void) +{ + unsigned int i; + + syncAudioDeviceStates(); + + for (i = 0; i < audioOutputArraySize; ++i) { + if (audio_output_is_open(&audioOutputArray[i])) + audio_output_cancel(&audioOutputArray[i]); + } + + audio_output_wait_all(); +} + +void closeAudioDevice(void) +{ + unsigned int i; + + for (i = 0; i < audioOutputArraySize; ++i) + audio_output_close(&audioOutputArray[i]); +} + +void sendMetadataToAudioDevice(const struct tag *tag) +{ + unsigned int i; + + for (i = 0; i < audioOutputArraySize; ++i) + if (audio_output_is_open(&audioOutputArray[i])) + audio_output_send_tag(&audioOutputArray[i], tag); + + audio_output_wait_all(); +} diff --git a/src/output_all.h b/src/output_all.h new file mode 100644 index 000000000..15a1dce7d --- /dev/null +++ b/src/output_all.h @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2003-2009 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * Functions for dealing with all configured (enabled) audion outputs + * at once. + * + */ + +#ifndef OUTPUT_ALL_H +#define OUTPUT_ALL_H + +#include <stdbool.h> +#include <stddef.h> + +struct audio_format; +struct tag; + +/** + * Returns the total number of audio output devices, including those + * who are disabled right now. + */ +unsigned int audio_output_count(void); + +/** + * Returns the "i"th audio output device. + */ +struct audio_output * +audio_output_get(unsigned i); + +/** + * Returns the audio output device with the specified name. Returns + * NULL if the name does not exist. + */ +struct audio_output * +audio_output_find(const char *name); + +void initAudioDriver(void); + +void finishAudioDriver(void); + +bool openAudioDevice(const struct audio_format *audioFormat); + +bool playAudio(const char *playChunk, size_t size); + +void audio_output_pause_all(void); + +void dropBufferedAudio(void); + +void closeAudioDevice(void); + +void sendMetadataToAudioDevice(const struct tag *tag); + +#endif diff --git a/src/output_print.c b/src/output_print.c index 6b2ab1b31..ac188639a 100644 --- a/src/output_print.c +++ b/src/output_print.c @@ -23,7 +23,7 @@ #include "output_print.h" #include "output_internal.h" -#include "audio.h" +#include "output_all.h" #include "client.h" void diff --git a/src/output_state.c b/src/output_state.c index d0a2baeff..c28fc3915 100644 --- a/src/output_state.c +++ b/src/output_state.c @@ -23,7 +23,7 @@ #include "output_state.h" #include "output_internal.h" -#include "audio.h" +#include "output_all.h" #include <glib.h> diff --git a/src/player_thread.c b/src/player_thread.c index 239fbab2d..a8f89197b 100644 --- a/src/player_thread.c +++ b/src/player_thread.c @@ -20,7 +20,7 @@ #include "player_control.h" #include "decoder_control.h" #include "decoder_thread.h" -#include "audio.h" +#include "output_all.h" #include "pcm_volume.h" #include "path.h" #include "event_pipe.h" diff --git a/src/volume.c b/src/volume.c index 6f7c922c0..501791016 100644 --- a/src/volume.c +++ b/src/volume.c @@ -23,6 +23,7 @@ #include "pcm_volume.h" #include "config.h" #include "audio.h" +#include "output_all.h" #include <glib.h> |