diff options
-rw-r--r-- | Makefile.am | 3 | ||||
-rw-r--r-- | parser.c | 107 | ||||
-rw-r--r-- | parser.h | 39 | ||||
-rw-r--r-- | streamer.c | 108 |
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 @@ -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; } |