aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMax Kellermann <max@duempel.org>2009-10-21 23:01:04 +0200
committerMax Kellermann <max@duempel.org>2009-10-21 23:01:04 +0200
commit9526fdbe730edb4b095a1e12aade0e16f1da2292 (patch)
tree4544e77bf35e08a12d2b019e0bf3942754b85b96 /src
parenta5c4566fa1551953b84882a1fa53400c7bd6551c (diff)
downloadmpd-9526fdbe730edb4b095a1e12aade0e16f1da2292.tar.gz
mpd-9526fdbe730edb4b095a1e12aade0e16f1da2292.tar.xz
mpd-9526fdbe730edb4b095a1e12aade0e16f1da2292.zip
audio_format: wildcards allowed in audio_format configuration
An asterisk means that this attribute should not be enforced, and stays whatever it used to be. This way, some configuration values work like masks.
Diffstat (limited to 'src')
-rw-r--r--src/audio.c7
-rw-r--r--src/audio_format.h47
-rw-r--r--src/audio_parser.c32
-rw-r--r--src/audio_parser.h3
-rw-r--r--src/output/shout_plugin.c9
-rw-r--r--src/output_init.c5
-rw-r--r--src/output_thread.c11
7 files changed, 92 insertions, 22 deletions
diff --git a/src/audio.c b/src/audio.c
index fb4712728..13f128eeb 100644
--- a/src/audio.c
+++ b/src/audio.c
@@ -35,9 +35,8 @@ static struct audio_format configured_audio_format;
void getOutputAudioFormat(const struct audio_format *inAudioFormat,
struct audio_format *outAudioFormat)
{
- *outAudioFormat = audio_format_defined(&configured_audio_format)
- ? configured_audio_format
- : *inAudioFormat;
+ *outAudioFormat = *inAudioFormat;
+ audio_format_mask_apply(outAudioFormat, &configured_audio_format);
}
void initAudioConfig(void)
@@ -50,7 +49,7 @@ void initAudioConfig(void)
return;
ret = audio_format_parse(&configured_audio_format, param->value,
- &error);
+ true, &error);
if (!ret)
g_error("error parsing \"%s\" at line %i: %s",
CONF_AUDIO_OUTPUT_FORMAT, param->line, error->message);
diff --git a/src/audio_format.h b/src/audio_format.h
index a88fc3a4c..a4f5ba2e0 100644
--- a/src/audio_format.h
+++ b/src/audio_format.h
@@ -91,6 +91,27 @@ static inline bool audio_format_defined(const struct audio_format *af)
}
/**
+ * Checks whether the specified #audio_format object is full, i.e. all
+ * attributes are defined. This is more complete than
+ * audio_format_defined(), but slower.
+ */
+static inline bool
+audio_format_fully_defined(const struct audio_format *af)
+{
+ return af->sample_rate != 0 && af->bits != 0 && af->channels != 0;
+}
+
+/**
+ * Checks whether the specified #audio_format object has at least one
+ * defined value.
+ */
+static inline bool
+audio_format_mask_defined(const struct audio_format *af)
+{
+ return af->sample_rate != 0 || af->bits != 0 || af->channels != 0;
+}
+
+/**
* Checks whether the sample rate is valid.
*
* @param sample_rate the sample rate in Hz
@@ -132,6 +153,18 @@ static inline bool audio_format_valid(const struct audio_format *af)
audio_valid_channel_count(af->channels);
}
+/**
+ * Returns false if the format mask is not valid for playback with
+ * MPD. This function performs some basic validity checks.
+ */
+static inline bool audio_format_mask_valid(const struct audio_format *af)
+{
+ return (af->sample_rate == 0 ||
+ audio_valid_sample_rate(af->sample_rate)) &&
+ (af->bits == 0 || audio_valid_sample_format(af->bits)) &&
+ (af->channels == 0 || audio_valid_channel_count(af->channels));
+}
+
static inline bool audio_format_equals(const struct audio_format *a,
const struct audio_format *b)
{
@@ -141,6 +174,20 @@ static inline bool audio_format_equals(const struct audio_format *a,
a->reverse_endian == b->reverse_endian;
}
+static inline void
+audio_format_mask_apply(struct audio_format *af,
+ const struct audio_format *mask)
+{
+ if (mask->sample_rate != 0)
+ af->sample_rate = mask->sample_rate;
+
+ if (mask->bits != 0)
+ af->bits = mask->bits;
+
+ if (mask->channels != 0)
+ af->channels = mask->channels;
+}
+
/**
* Returns the size of each (mono) sample in bytes.
*/
diff --git a/src/audio_parser.c b/src/audio_parser.c
index 0b3474ab3..7c0d45ddc 100644
--- a/src/audio_parser.c
+++ b/src/audio_parser.c
@@ -37,12 +37,18 @@ audio_parser_quark(void)
}
static bool
-parse_sample_rate(const char *src, uint32_t *sample_rate_r,
+parse_sample_rate(const char *src, bool mask, uint32_t *sample_rate_r,
const char **endptr_r, GError **error_r)
{
unsigned long value;
char *endptr;
+ if (mask && *src == '*') {
+ *sample_rate_r = 0;
+ *endptr_r = src + 1;
+ return true;
+ }
+
value = strtoul(src, &endptr, 10);
if (endptr == src) {
g_set_error(error_r, audio_parser_quark(), 0,
@@ -60,12 +66,18 @@ parse_sample_rate(const char *src, uint32_t *sample_rate_r,
}
static bool
-parse_sample_format(const char *src, uint8_t *bits_r,
+parse_sample_format(const char *src, bool mask, uint8_t *bits_r,
const char **endptr_r, GError **error_r)
{
unsigned long value;
char *endptr;
+ if (mask && *src == '*') {
+ *bits_r = 0;
+ *endptr_r = src + 1;
+ return true;
+ }
+
value = strtoul(src, &endptr, 10);
if (endptr == src) {
g_set_error(error_r, audio_parser_quark(), 0,
@@ -83,12 +95,18 @@ parse_sample_format(const char *src, uint8_t *bits_r,
}
static bool
-parse_channel_count(const char *src, uint8_t *channels_r,
+parse_channel_count(const char *src, bool mask, uint8_t *channels_r,
const char **endptr_r, GError **error_r)
{
unsigned long value;
char *endptr;
+ if (mask && *src == '*') {
+ *channels_r = 0;
+ *endptr_r = src + 1;
+ return true;
+ }
+
value = strtoul(src, &endptr, 10);
if (endptr == src) {
g_set_error(error_r, audio_parser_quark(), 0,
@@ -107,7 +125,7 @@ parse_channel_count(const char *src, uint8_t *channels_r,
bool
audio_format_parse(struct audio_format *dest, const char *src,
- GError **error_r)
+ bool mask, GError **error_r)
{
uint32_t rate;
uint8_t bits, channels;
@@ -116,7 +134,7 @@ audio_format_parse(struct audio_format *dest, const char *src,
/* parse sample rate */
- if (!parse_sample_rate(src, &rate, &src, error_r))
+ if (!parse_sample_rate(src, mask, &rate, &src, error_r))
return false;
if (*src++ != ':') {
@@ -127,7 +145,7 @@ audio_format_parse(struct audio_format *dest, const char *src,
/* parse sample format */
- if (!parse_sample_format(src, &bits, &src, error_r))
+ if (!parse_sample_format(src, mask, &bits, &src, error_r))
return false;
if (*src++ != ':') {
@@ -138,7 +156,7 @@ audio_format_parse(struct audio_format *dest, const char *src,
/* parse channel count */
- if (!parse_channel_count(src, &channels, &src, error_r))
+ if (!parse_channel_count(src, mask, &channels, &src, error_r))
return false;
if (*src != 0) {
diff --git a/src/audio_parser.h b/src/audio_parser.h
index 1d821eaf5..d50c17489 100644
--- a/src/audio_parser.h
+++ b/src/audio_parser.h
@@ -37,12 +37,13 @@ struct audio_format;
*
* @param dest the destination #audio_format struct
* @param src the input string
+ * @param mask if true, then "*" is allowed for any number of items
* @param error_r location to store the error occuring, or NULL to
* ignore errors
* @return true on success
*/
bool
audio_format_parse(struct audio_format *dest, const char *src,
- GError **error_r);
+ bool mask, GError **error_r);
#endif
diff --git a/src/output/shout_plugin.c b/src/output/shout_plugin.c
index f1b21bb36..da90efd2d 100644
--- a/src/output/shout_plugin.c
+++ b/src/output/shout_plugin.c
@@ -126,6 +126,13 @@ my_shout_init_driver(const struct audio_format *audio_format,
struct block_param *block_param;
int public;
+ if (audio_format == NULL ||
+ !audio_format_fully_defined(audio_format)) {
+ g_set_error(error, shout_output_quark(), 0,
+ "Need full audio format specification");
+ return NULL;
+ }
+
sd = new_shout_data();
if (shout_init_count == 0)
@@ -191,8 +198,6 @@ my_shout_init_driver(const struct audio_format *audio_format,
}
}
- check_block_param("format");
-
encoding = config_get_block_string(param, "encoding", "ogg");
encoder_plugin = shout_encoder_plugin_get(encoding);
if (encoder_plugin == NULL) {
diff --git a/src/output_init.c b/src/output_init.c
index f097f2c2d..745b63e30 100644
--- a/src/output_init.c
+++ b/src/output_init.c
@@ -157,7 +157,7 @@ audio_output_init(struct audio_output *ao, const struct config_param *param,
if (p != NULL) {
bool success =
audio_format_parse(&ao->config_audio_format,
- p, error_r);
+ p, true, error_r);
if (!success)
return false;
} else
@@ -195,8 +195,7 @@ audio_output_init(struct audio_output *ao, const struct config_param *param,
ao->mutex = g_mutex_new();
ao->data = ao_plugin_init(plugin,
- audio_format_defined(&ao->config_audio_format)
- ? &ao->config_audio_format : NULL,
+ &ao->config_audio_format,
param, error_r);
if (ao->data == NULL)
return false;
diff --git a/src/output_thread.c b/src/output_thread.c
index dd97d88b0..9eb2478b0 100644
--- a/src/output_thread.c
+++ b/src/output_thread.c
@@ -67,10 +67,9 @@ ao_open(struct audio_output *ao)
return;
}
- if (audio_format_defined(&ao->config_audio_format))
- ao->out_audio_format = ao->config_audio_format;
- else
- ao->out_audio_format = *filter_audio_format;
+ ao->out_audio_format = *filter_audio_format;
+ audio_format_mask_apply(&ao->out_audio_format,
+ &ao->config_audio_format);
success = ao_plugin_open(ao->plugin, ao->data,
&ao->out_audio_format,
@@ -166,7 +165,7 @@ ao_reopen_filter(struct audio_output *ao)
static void
ao_reopen(struct audio_output *ao)
{
- if (!audio_format_defined(&ao->config_audio_format)) {
+ if (!audio_format_fully_defined(&ao->config_audio_format)) {
if (ao->open) {
const struct music_pipe *mp = ao->pipe;
ao_close(ao);
@@ -177,6 +176,8 @@ ao_reopen(struct audio_output *ao)
the output's open() method determine the effective
out_audio_format */
ao->out_audio_format = ao->in_audio_format;
+ audio_format_mask_apply(&ao->out_audio_format,
+ &ao->config_audio_format);
}
if (ao->open)