aboutsummaryrefslogtreecommitdiffstats
path: root/src/input/cdda_input_plugin.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/input/cdda_input_plugin.c69
1 files changed, 59 insertions, 10 deletions
diff --git a/src/input/cdda_input_plugin.c b/src/input/cdda_input_plugin.c
index b2b86abc3..df54ed47d 100644
--- a/src/input/cdda_input_plugin.c
+++ b/src/input/cdda_input_plugin.c
@@ -82,6 +82,58 @@ input_cdda_close(struct input_stream *is)
g_free(i);
}
+struct cdda_uri {
+ char device[64];
+ int track;
+};
+
+static bool
+parse_cdda_uri(struct cdda_uri *dest, const char *src, GError **error_r)
+{
+ if (!g_str_has_prefix(src, "cdda://"))
+ return false;
+
+ src += 7;
+
+ if (*src == 0) {
+ /* play the whole CD in the default drive */
+ dest->device[0] = 0;
+ dest->track = -1;
+ return true;
+ }
+
+ const char *slash = strrchr(src, '/');
+ if (slash == NULL) {
+ /* play the whole CD in the specified drive */
+ g_strlcpy(dest->device, src, sizeof(dest->device));
+ dest->track = -1;
+ return true;
+ }
+
+ size_t device_length = slash - src;
+ if (device_length >= sizeof(dest->device))
+ device_length = sizeof(dest->device) - 1;
+
+ memcpy(dest->device, src, device_length);
+ dest->device[device_length] = 0;
+
+ const char *track = slash + 1;
+
+ char *endptr;
+ dest->track = strtoul(track, &endptr, 10);
+ if (*endptr != 0) {
+ g_set_error(error_r, cdda_quark(), 0,
+ "Malformed track number");
+ return false;
+ }
+
+ if (endptr == track)
+ /* play the whole CD */
+ dest->track = -1;
+
+ return true;
+}
+
static char *
cdda_detect_device(void)
{
@@ -100,7 +152,8 @@ input_cdda_open(const char *uri, GError **error_r)
{
struct input_cdda *i;
- if (!g_str_has_prefix(uri, "cdda://"))
+ struct cdda_uri parsed_uri;
+ if (!parse_cdda_uri(&parsed_uri, uri, error_r))
return NULL;
i = g_new(struct input_cdda, 1);
@@ -110,17 +163,13 @@ input_cdda_open(const char *uri, GError **error_r)
i->drv = NULL;
i->cdio = NULL;
i->para = NULL;
+ i->trackno = parsed_uri.track;
pcm_buffer_init(&i->conv_buffer);
- if (parse_cdda_uri(uri, &drive, &trackno) == -1) {
- g_set_error(error_r, cdda_quark(), 0,
- "Unable parse URI\n");
- input_cdda_close(&i->base);
- return NULL;
- }
-
/* get list of CD's supporting CD-DA */
- char *device = cdda_detect_device();
+ char *device = parsed_uri.device[0] != 0
+ ? g_strdup(parsed_uri.device)
+ : cdda_detect_device();
if (device == NULL) {
g_set_error(error_r, cdda_quark(), 0,
"Unable find or access a CD-ROM drive with an audio CD in it.");
@@ -164,7 +213,7 @@ input_cdda_open(const char *uri, GError **error_r)
default:
g_set_error(error_r, cdda_quark(), 0,
"Drive returns unknown data type %d", i->endian);
- input_cdda_close(i)
+ input_cdda_close(&i->base);
return NULL;
}