aboutsummaryrefslogtreecommitdiffstats
path: root/src/audio_parser.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/audio_parser.c')
-rw-r--r--src/audio_parser.c166
1 files changed, 133 insertions, 33 deletions
diff --git a/src/audio_parser.c b/src/audio_parser.c
index 906b0f819..139cf1c04 100644
--- a/src/audio_parser.c
+++ b/src/audio_parser.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2009 The Music Player Daemon Project
+ * Copyright (C) 2003-2010 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -22,9 +22,13 @@
*
*/
+#include "config.h"
#include "audio_parser.h"
#include "audio_format.h"
+#include "audio_check.h"
+#include <assert.h>
+#include <string.h>
#include <stdlib.h>
/**
@@ -36,64 +40,160 @@ audio_parser_quark(void)
return g_quark_from_static_string("audio_parser");
}
-bool
-audio_format_parse(struct audio_format *dest, const char *src, GError **error)
+static bool
+parse_sample_rate(const char *src, bool mask, uint32_t *sample_rate_r,
+ const char **endptr_r, GError **error_r)
{
- char *endptr;
unsigned long value;
+ char *endptr;
- audio_format_clear(dest);
-
- /* parse sample rate */
+ 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, audio_parser_quark(), 0,
- "Sample rate missing");
+ g_set_error(error_r, audio_parser_quark(), 0,
+ "Failed to parse the sample rate");
return false;
- } else if (*endptr != ':') {
- g_set_error(error, audio_parser_quark(), 0,
- "Sample format missing");
+ } else if (!audio_check_sample_rate(value, error_r))
+ return false;
+
+ *sample_rate_r = value;
+ *endptr_r = endptr;
+ return true;
+}
+
+static bool
+parse_sample_format(const char *src, bool mask,
+ enum sample_format *sample_format_r,
+ const char **endptr_r, GError **error_r)
+{
+ unsigned long value;
+ char *endptr;
+ enum sample_format sample_format;
+
+ if (mask && *src == '*') {
+ *sample_format_r = SAMPLE_FORMAT_UNDEFINED;
+ *endptr_r = src + 1;
+ return true;
+ }
+
+ value = strtoul(src, &endptr, 10);
+ if (endptr == src) {
+ g_set_error(error_r, audio_parser_quark(), 0,
+ "Failed to parse the sample format");
return false;
- } else if (!audio_valid_sample_rate(value)) {
- g_set_error(error, audio_parser_quark(), 0,
- "Invalid sample rate: %lu", value);
+ }
+
+ switch (value) {
+ case 8:
+ sample_format = SAMPLE_FORMAT_S8;
+ break;
+
+ case 16:
+ sample_format = SAMPLE_FORMAT_S16;
+ break;
+
+ case 24:
+ if (memcmp(endptr, "_3", 2) == 0) {
+ sample_format = SAMPLE_FORMAT_S24;
+ endptr += 2;
+ } else
+ sample_format = SAMPLE_FORMAT_S24_P32;
+ break;
+
+ case 32:
+ sample_format = SAMPLE_FORMAT_S32;
+ break;
+
+ default:
+ g_set_error(error_r, audio_parser_quark(), 0,
+ "Invalid sample format: %lu", value);
return false;
}
- dest->sample_rate = value;
+ assert(audio_valid_sample_format(sample_format));
- /* parse sample format */
+ *sample_format_r = sample_format;
+ *endptr_r = endptr;
+ return true;
+}
+
+static bool
+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;
+ }
- src = endptr + 1;
value = strtoul(src, &endptr, 10);
if (endptr == src) {
- g_set_error(error, audio_parser_quark(), 0,
- "Sample format missing");
+ g_set_error(error_r, audio_parser_quark(), 0,
+ "Failed to parse the channel count");
return false;
- } else if (*endptr != ':') {
- g_set_error(error, audio_parser_quark(), 0,
- "Channel count missing");
+ } else if (!audio_check_channel_count(value, error_r))
return false;
- } else if (!audio_valid_sample_format(value)) {
- g_set_error(error, audio_parser_quark(), 0,
- "Invalid sample format: %lu", value);
+
+ *channels_r = value;
+ *endptr_r = endptr;
+ return true;
+}
+
+bool
+audio_format_parse(struct audio_format *dest, const char *src,
+ bool mask, GError **error_r)
+{
+ uint32_t rate;
+ enum sample_format sample_format;
+ uint8_t channels;
+
+ audio_format_clear(dest);
+
+ /* parse sample rate */
+
+ if (!parse_sample_rate(src, mask, &rate, &src, error_r))
+ return false;
+
+ if (*src++ != ':') {
+ g_set_error(error_r, audio_parser_quark(), 0,
+ "Sample format missing");
return false;
}
- dest->bits = value;
+ /* parse sample format */
+
+ if (!parse_sample_format(src, mask, &sample_format, &src, error_r))
+ return false;
+
+ if (*src++ != ':') {
+ g_set_error(error_r, audio_parser_quark(), 0,
+ "Channel count missing");
+ return false;
+ }
/* parse channel count */
- src = endptr + 1;
- value = strtoul(src, &endptr, 10);
- if (*endptr != 0 || !audio_valid_channel_count(value)) {
- g_set_error(error, audio_parser_quark(), 0,
- "Invalid channel count: %s", src);
+ if (!parse_channel_count(src, mask, &channels, &src, error_r))
+ return false;
+
+ if (*src != 0) {
+ g_set_error(error_r, audio_parser_quark(), 0,
+ "Extra data after channel count: %s", src);
return false;
}
- dest->channels = value;
+ audio_format_init(dest, rate, sample_format, channels);
+ assert(mask ? audio_format_mask_valid(dest)
+ : audio_format_valid(dest));
return true;
}