summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile.am3
-rw-r--r--parser.c107
-rw-r--r--parser.h39
-rw-r--r--streamer.c108
4 files changed, 237 insertions, 20 deletions
diff --git a/Makefile.am b/Makefile.am
index 0ad76ecb..8640bcc7 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -38,7 +38,8 @@ deadbeef_SOURCES =\
dsppreset.c dsppreset.h\
replaygain.c replaygain.h\
fft.c fft.h\
- handler.c handler.h
+ handler.c handler.h\
+ parser.c parser.h
# ConvertUTF/ConvertUTF.c ConvertUTF/ConvertUTF.h
diff --git a/parser.c b/parser.c
new file mode 100644
index 00000000..c49eeb72
--- /dev/null
+++ b/parser.c
@@ -0,0 +1,107 @@
+/*
+ DeaDBeeF - ultimate music player for GNU/Linux systems with X11
+ Copyright (C) 2009-2012 Alexey Yakovenko <waker@users.sourceforge.net>
+
+ 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, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <stdlib.h>
+#include <assert.h>
+#include <string.h>
+#include <stdio.h>
+#include "parser.h"
+
+// very basic parser, ripped from psynth, optimized, and extended to support
+// quoted strings and extra special chars
+int parser_line;
+
+void
+parser_init (void) {
+ parser_line = 1;
+}
+
+const char *
+skipws (const char *p) {
+ while (*p <= ' ' && *p) {
+ if (*p == '\n') {
+ parser_line++;
+ }
+ p++;
+ }
+ if (!*p) {
+ return NULL;
+ }
+ return p;
+}
+
+const char *
+gettoken (const char *p, char *tok) {
+ const char *c;
+ assert (p);
+ assert (tok);
+ int n = MAX_TOKEN-1;
+ char specialchars[] = "{}();";
+ if (!(p = skipws (p))) {
+ return NULL;
+ }
+ if (*p == '"') {
+ p++;
+ c = p;
+ while (n > 0 && *c && *c != '"') {
+ if (*c == '\n') {
+ parser_line++;
+ }
+ *tok++ = *c++;
+ n--;
+ }
+ if (*c) {
+ c++;
+ }
+ *tok = 0;
+ return c;
+ }
+ if (strchr (specialchars, *p)) {
+ *tok = *p;
+ tok[1] = 0;
+ return p+1;
+ }
+ c = p;
+ while (n > 0 && *c > ' ' && !strchr (specialchars, *c)) {
+ *tok++ = *c++;
+ n--;
+ }
+ *tok = 0;
+ return c;
+}
+
+const char *
+gettoken_warn_eof (const char *p, char *tok) {
+ p = gettoken (p, tok);
+ if (!p) {
+ fprintf (stderr, "parser: unexpected eof at line %d", parser_line);
+ }
+ return p;
+}
+
+const char *
+gettoken_err_eof (const char *p, char *tok) {
+ p = gettoken (p, tok);
+ if (!p) {
+ fprintf (stderr, "parser: unexpected eof at line %d", parser_line);
+ exit (-1);
+ }
+ return p;
+}
+
+
diff --git a/parser.h b/parser.h
new file mode 100644
index 00000000..b0f95169
--- /dev/null
+++ b/parser.h
@@ -0,0 +1,39 @@
+/*
+ DeaDBeeF - ultimate music player for GNU/Linux systems with X11
+ Copyright (C) 2009-2012 Alexey Yakovenko <waker@users.sourceforge.net>
+
+ 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, see <http://www.gnu.org/licenses/>.
+*/
+#ifndef __PARSER_H
+#define __PARSER_H
+
+#define MAX_TOKEN 256
+extern int parser_line;
+
+void
+parser_init (void);
+
+const char *
+skipws (const char *p);
+
+const char *
+gettoken (const char *p, char *tok);
+
+const char *
+gettoken_warn_eof (const char *p, char *tok);
+
+const char *
+gettoken_err_eof (const char *p, char *tok);
+
+#endif
diff --git a/streamer.c b/streamer.c
index ada406bb..57acce7d 100644
--- a/streamer.c
+++ b/streamer.c
@@ -49,6 +49,7 @@
#include "replaygain.h"
#include "fft.h"
#include "handler.h"
+#include "parser.h"
//#define trace(...) { fprintf(stderr, __VA_ARGS__); }
#define trace(fmt,...)
@@ -682,16 +683,81 @@ streamer_song_removed_notify (playItem_t *it) {
}
}
-// map of some popular content types to decoders
-// FIXME: must be in config and in GUI settings
-const char * decmap_audio_mpeg[] = { "audio/mpeg", "stdmpg", "ffmpeg", NULL };
-const char * decmap_audio_x_mpeg[] = { "audio/x-mpeg", "stdmpg", "ffmpeg", NULL };
-const char * decmap_application_ogg[] = { "application/ogg", "stdogg", "ffmpeg", NULL };
-const char * decmap_audio_ogg[] = { "audio/ogg", "stdogg", "ffmpeg", NULL };
-const char * decmap_audio_aac[] = { "audio/aac", "aac", "ffmpeg", NULL };
-const char * decmap_audio_aacp[] = { "audio/aacp", "aac", "ffmpeg", NULL };
-const char * decmap_audio_wma[] = { "audio/wma", "wma", "ffmpeg", NULL };
-const char ** decmap[] = { decmap_audio_mpeg, decmap_audio_x_mpeg, decmap_application_ogg, decmap_audio_ogg, decmap_audio_aac, decmap_audio_aacp, decmap_audio_wma, NULL };
+#define CTMAP_MAX_PLUGINS 5
+
+typedef struct ctmap_s {
+ char *ct;
+ char *plugins[CTMAP_MAX_PLUGINS];
+ struct ctmap_s *next;
+} ctmap_t;
+
+ctmap_t *streamer_ctmap;
+
+static void
+ctmap_free (void) {
+ while (streamer_ctmap) {
+ ctmap_t *ct = streamer_ctmap;
+ free (ct->ct);
+ for (int i = 0; ct->plugins[i]; i++) {
+ free (ct->plugins[i]);
+ }
+ streamer_ctmap = ct->next;
+ free (ct);
+ }
+}
+
+static void
+ctmap_init (void) {
+ ctmap_free ();
+ char mapstr[2048];
+ deadbeef->conf_get_str ("network.ctmapping", DDB_DEFAULT_CTMAPPING, mapstr, sizeof (mapstr));
+
+ const char *p = mapstr;
+ char t[MAX_TOKEN];
+ char ct[MAX_TOKEN];
+ char plugins[MAX_TOKEN*5];
+
+ ctmap_t *tail = NULL;
+
+ for (;;) {
+ p = gettoken (p, t);
+
+ if (!p) {
+ break;
+ }
+
+ ctmap_t *ctmap = malloc (sizeof (ctmap_t));
+ memset (ctmap, 0, sizeof (ctmap_t));
+ ctmap->ct = strdup (t);
+
+ int n = 0;
+
+ p = gettoken (p, t);
+ if (!p || strcmp (t, "{")) {
+ free (ctmap->ct);
+ free (ctmap);
+ break;
+ }
+
+ plugins[0] = 0;
+ for (;;) {
+ p = gettoken (p, t);
+ if (!p || !strcmp (t, "}") || n >= CTMAP_MAX_PLUGINS-1) {
+ break;
+ }
+
+ ctmap->plugins[n++] = strdup (t);
+ }
+ ctmap->plugins[n] = NULL;
+ if (tail) {
+ tail->next = ctmap;
+ }
+ tail = ctmap;
+ if (!streamer_ctmap) {
+ streamer_ctmap = ctmap;
+ }
+ }
+}
// that must be called after last sample from str_playing_song was done reading
static int
@@ -748,7 +814,7 @@ streamer_set_current (playItem_t *it) {
strncpy (filetype, ft, sizeof (filetype));
}
pl_unlock ();
- const char **plugs = NULL;
+ ctmap_t *ctmap = NULL;
if (!decoder_id[0] && (!strcmp (filetype, "content") || !filetype[0])) {
// try to get content-type
mutex_lock (decodemutex);
@@ -777,14 +843,15 @@ streamer_set_current (playItem_t *it) {
*sc = 0;
}
- for (int map = 0; decmap[map]; map++) {
- if (!strcmp (cct, decmap[map][0])) {
- plugs = decmap[map];
+ ctmap = streamer_ctmap;
+ while (ctmap) {
+ if (!strcmp (cct, ctmap->ct)) {
break;
}
+ ctmap = ctmap->next;
}
- if (!plugs && (!strcmp (cct, "audio/x-mpegurl") || !strncmp (cct, "text/html", 9) || !strncmp (cct, "audio/x-scpls", 13) || !strncmp (cct, "application/octet-stream", 9))) {
+ if (!ctmap && (!strcmp (cct, "audio/x-mpegurl") || !strncmp (cct, "text/html", 9) || !strncmp (cct, "audio/x-scpls", 13) || !strncmp (cct, "application/octet-stream", 9))) {
// download playlist into temp file
trace ("downloading playlist into temp file...\n");
char *buf = NULL;
@@ -907,9 +974,9 @@ m3u_error:
}
playlist_track = it;
- int plug_idx = 1;
+ int plug_idx = 0;
for (;;) {
- if (!decoder_id[0] && plugs && !plugs[plug_idx]) {
+ if (!decoder_id[0] && ctmap && !ctmap->plugins[plug_idx]) {
it->played = 1;
trace ("decoder->init returned %p\n", new_fileinfo);
streamer_buffering = 0;
@@ -952,9 +1019,9 @@ m3u_error:
pl_unlock ();
}
}
- else if (plugs) {
+ else if (ctmap) {
// match by decoder
- dec = plug_get_decoder_for_id (plugs[plug_idx]);
+ dec = plug_get_decoder_for_id (ctmap->plugins[plug_idx]);
if (dec) {
pl_replace_meta (it, "!DECODER", dec->plugin.id);
}
@@ -1783,6 +1850,9 @@ streamer_init (void) {
streamer_dsp_init ();
replaygain_set (conf_get_int ("replaygain_mode", 0), conf_get_int ("replaygain_scale", 1), conf_get_float ("replaygain_preamp", 0), conf_get_float ("global_preamp", 0));
+
+ ctmap_init ();
+
streamer_tid = thread_start (streamer_thread, NULL);
return 0;
}