diff options
-rw-r--r-- | Makefile.am | 6 | ||||
-rw-r--r-- | callbacks.c | 61 | ||||
-rw-r--r-- | cmp3.c | 137 | ||||
-rw-r--r-- | cmp3.h | 2 | ||||
-rw-r--r-- | codec.h | 4 | ||||
-rw-r--r-- | deadbeef.h | 38 | ||||
-rw-r--r-- | main.c | 10 | ||||
-rw-r--r-- | playlist.c | 88 | ||||
-rw-r--r-- | playlist.h | 4 | ||||
-rw-r--r-- | plugins.c | 22 | ||||
-rw-r--r-- | plugins.h | 3 | ||||
-rw-r--r-- | plugins/lastfm/lastfm.c | 5 | ||||
-rw-r--r-- | streamer.c | 28 |
13 files changed, 238 insertions, 170 deletions
diff --git a/Makefile.am b/Makefile.am index f444040d..54f21ecd 100644 --- a/Makefile.am +++ b/Makefile.am @@ -20,15 +20,17 @@ deadbeef_SOURCES =\ messagepump.c messagepump.h messages.h\ conf.c conf.h\ search.c search.h\ - csid.cpp cdumb.c cmp3.c cvorbis.c cflac.c cgme.c \ + cmp3.c\ palsa.c palsa.h playback.h\ threading_pthread.c threading.h\ md5/md5.c md5/md5.h md5/md5_loc.h\ - csid.h cdumb.h cmp3.h cvorbis.h cflac.h cgme.h\ volume.c volume.h\ drawing.h gdkdrawing.c\ session.h session.c gtksession.c +# csid.cpp cdumb.c cmp3.c cvorbis.c cflac.c cgme.c +# csid.h cdumb.h cmp3.h cvorbis.h cflac.h cgme.h + sdkdir = $(pkgincludedir) sdk_HEADERS = deadbeef.h diff --git a/callbacks.c b/callbacks.c index 070add31..8119ac5b 100644 --- a/callbacks.c +++ b/callbacks.c @@ -45,12 +45,14 @@ #include "volume.h" #include "session.h" -#include "cvorbis.h" -#include "cdumb.h" -#include "cmp3.h" -#include "cgme.h" -#include "cflac.h" -#include "csid.h" +#include "plugins.h" + +//#include "cmp3.h" +//#include "cvorbis.h" +//#include "cdumb.h" +//#include "cgme.h" +//#include "cflac.h" +//#include "csid.h" extern GtkWidget *mainwin; extern gtkplaylist_t main_playlist; @@ -174,12 +176,11 @@ on_open_activate (GtkMenuItem *menuitem, flt = gtk_file_filter_new (); gtk_file_filter_set_name (flt, "Supported music files"); - codec_t *codecs[] = { - &cdumb, &cvorbis, &cflac, &cgme, &cmp3, &csid, NULL - }; + DB_decoder_t **codecs = plug_get_decoder_list (); + for (int i = 0; codecs[i]; i++) { - if (codecs[i]->getexts && codecs[i]->insert) { - const char **exts = codecs[i]->getexts (); + if (codecs[i]->exts && codecs[i]->insert) { + const char **exts = codecs[i]->exts; if (exts) { for (int e = 0; exts[e]; e++) { char filter[20]; @@ -236,12 +237,10 @@ on_add_files_activate (GtkMenuItem *menuitem, flt = gtk_file_filter_new (); gtk_file_filter_set_name (flt, "Supported music files"); - codec_t *codecs[] = { - &cdumb, &cvorbis, &cflac, &cgme, &cmp3, &csid, NULL - }; + DB_decoder_t **codecs = plug_get_decoder_list (); for (int i = 0; codecs[i]; i++) { - if (codecs[i]->getexts && codecs[i]->insert) { - const char **exts = codecs[i]->getexts (); + if (codecs[i]->exts && codecs[i]->insert) { + const char **exts = codecs[i]->exts; if (exts) { for (int e = 0; exts[e]; e++) { char filter[20]; @@ -298,12 +297,10 @@ on_add_folder1_activate (GtkMenuItem *menuitem, flt = gtk_file_filter_new (); gtk_file_filter_set_name (flt, "Supported music files"); - codec_t *codecs[] = { - &cdumb, &cvorbis, &cflac, &cgme, &cmp3, &csid, NULL - }; + DB_decoder_t **codecs = plug_get_decoder_list (); for (int i = 0; codecs[i]; i++) { - if (codecs[i]->getexts && codecs[i]->insert) { - const char **exts = codecs[i]->getexts (); + if (codecs[i]->exts && codecs[i]->insert) { + const char **exts = codecs[i]->exts; if (exts) { for (int e = 0; exts[e]; e++) { char filter[20]; @@ -635,8 +632,8 @@ on_voice1_clicked (GtkButton *button, gpointer user_data) { codec_lock (); - if (playlist_current.codec && playlist_current.codec->mutevoice) { - playlist_current.codec->mutevoice (0, gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button)) ? 0 : 1); + if (playlist_current.decoder && playlist_current.decoder->mutevoice) { + playlist_current.decoder->mutevoice (0, gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button)) ? 0 : 1); } codec_unlock (); } @@ -647,8 +644,8 @@ on_voice2_clicked (GtkButton *button, gpointer user_data) { codec_lock (); - if (playlist_current.codec && playlist_current.codec->mutevoice) { - playlist_current.codec->mutevoice (1, gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button)) ? 0 : 1); + if (playlist_current.decoder && playlist_current.decoder->mutevoice) { + playlist_current.decoder->mutevoice (1, gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button)) ? 0 : 1); } codec_unlock (); } @@ -659,8 +656,8 @@ on_voice3_clicked (GtkButton *button, gpointer user_data) { codec_lock (); - if (playlist_current.codec && playlist_current.codec->mutevoice) { - playlist_current.codec->mutevoice (2, gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button)) ? 0 : 1); + if (playlist_current.decoder && playlist_current.decoder->mutevoice) { + playlist_current.decoder->mutevoice (2, gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button)) ? 0 : 1); } codec_unlock (); } @@ -671,8 +668,8 @@ on_voice4_clicked (GtkButton *button, gpointer user_data) { codec_lock (); - if (playlist_current.codec && playlist_current.codec->mutevoice) { - playlist_current.codec->mutevoice (3, gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button)) ? 0 : 1); + if (playlist_current.decoder && playlist_current.decoder->mutevoice) { + playlist_current.decoder->mutevoice (3, gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button)) ? 0 : 1); } codec_unlock (); } @@ -683,8 +680,8 @@ on_voice5_clicked (GtkButton *button, gpointer user_data) { codec_lock (); - if (playlist_current.codec && playlist_current.codec->mutevoice) { - playlist_current.codec->mutevoice (4, gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button)) ? 0 : 1); + if (playlist_current.decoder && playlist_current.decoder->mutevoice) { + playlist_current.decoder->mutevoice (4, gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button)) ? 0 : 1); } codec_unlock (); } @@ -929,7 +926,7 @@ seekbar_draw (GtkWidget *widget) { pos = x; } else { - if (playlist_current.codec && playlist_current.duration > 0) { + if (playlist_current.decoder && playlist_current.duration > 0) { pos = streamer_get_playpos () / playlist_current.duration; pos *= widget->allocation.width; } @@ -22,10 +22,16 @@ #include <stdlib.h> #include <iconv.h> //#include <sys/mman.h> -#include "codec.h" -#include "cmp3.h" -#include "playlist.h" -#include "common.h" +//#include "plugin.h" +//#include "playlist.h" +//#include "common.h" +#include "deadbeef.h" + +#define min(x,y) ((x)<(y)?(x):(y)) +#define max(x,y) ((x)>(y)?(x):(y)) + +static DB_decoder_t plugin; +static DB_functions_t *deadbeef; #define READBUFFER 5*8192 @@ -104,7 +110,7 @@ static int cmp3_scan_stream (buffer_t *buffer, float position); int -cmp3_init (struct playItem_s *it) { +cmp3_init (DB_playItem_t *it) { memset (&buffer, 0, sizeof (buffer)); buffer.file = fopen (it->fname, "rb"); if (!buffer.file) { @@ -116,7 +122,7 @@ cmp3_init (struct playItem_s *it) { buffer.output = NULL; buffer.readsize = 0; buffer.cachefill = 0; - cmp3.info.readposition = 0; + plugin.info.readpos = 0; mad_timer_reset(&buffer.timer); // fseek (buffer.file, buffer.startoffset, SEEK_SET); @@ -138,9 +144,9 @@ cmp3_init (struct playItem_s *it) { fclose (buffer.file); return -1; } - cmp3.info.bitsPerSample = buffer.bitspersample; - cmp3.info.samplesPerSecond = buffer.samplerate; - cmp3.info.channels = buffer.channels; + plugin.info.bps = buffer.bitspersample; + plugin.info.samplerate = buffer.samplerate; + plugin.info.channels = buffer.channels; mad_stream_init(&stream); mad_frame_init(&frame); @@ -531,8 +537,8 @@ cmp3_decode (void) { } } - cmp3.info.samplesPerSecond = frame.header.samplerate; - cmp3.info.channels = MAD_NCHANNELS(&frame.header); + plugin.info.samplerate = frame.header.samplerate; + plugin.info.channels = MAD_NCHANNELS(&frame.header); mad_timer_add(&buffer.timer,frame.header.duration); @@ -599,7 +605,7 @@ int cmp3_read (char *bytes, int size) { int result; int ret = 0; - if (cmp3.info.readposition >= (buffer.timeend - buffer.timestart)) { + if (plugin.info.readpos >= (buffer.timeend - buffer.timestart)) { return 0; } if (buffer.cachefill > 0) { @@ -620,9 +626,9 @@ cmp3_read (char *bytes, int size) { buffer.output = bytes; buffer.readsize = size; ret += cmp3_decode (); - cmp3.info.readposition = (float)buffer.timer.seconds + (float)buffer.timer.fraction / MAD_TIMER_RESOLUTION; + plugin.info.readpos = (float)buffer.timer.seconds + (float)buffer.timer.fraction / MAD_TIMER_RESOLUTION; } - if (cmp3.info.readposition >= (buffer.timeend - buffer.timestart)) { + if (plugin.info.readpos >= (buffer.timeend - buffer.timestart)) { return 0; } return ret; @@ -645,19 +651,19 @@ cmp3_seek (float time) { mad_timer_reset(&buffer.timer); if (time == 0) { - cmp3.info.readposition = 0; + plugin.info.readpos = 0; return 0; } if (cmp3_scan_stream (&buffer, time) == -1) { - cmp3.info.readposition = 0; + plugin.info.readpos = 0; return -1; } // fixup timer - cmp3.info.readposition = (float)buffer.timer.seconds + (float)buffer.timer.fraction / MAD_TIMER_RESOLUTION; - cmp3.info.readposition -= buffer.timestart; - buffer.timer.seconds = (int)cmp3.info.readposition; - buffer.timer.fraction = (cmp3.info.readposition - buffer.timer.seconds) * MAD_TIMER_RESOLUTION; + plugin.info.readpos = (float)buffer.timer.seconds + (float)buffer.timer.fraction / MAD_TIMER_RESOLUTION; + plugin.info.readpos -= buffer.timestart; + buffer.timer.seconds = (int)plugin.info.readpos; + buffer.timer.fraction = (plugin.info.readpos - buffer.timer.seconds) * MAD_TIMER_RESOLUTION; return 0; } @@ -998,7 +1004,7 @@ str_trim_right (uint8_t *str, int len) { // should read both id3v1 and id3v1.1 int -cmp3_read_id3v1 (playItem_t *it, FILE *fp) { +cmp3_read_id3v1 (DB_playItem_t *it, FILE *fp) { if (!it || !fp) { printf ("bad call to cmp3_read_id3v1!\n"); return -1; @@ -1053,16 +1059,16 @@ cmp3_read_id3v1 (playItem_t *it, FILE *fp) { // add meta // printf ("%s - %s - %s - %s - %s - %s\n", title, artist, album, year, comment, genre); - pl_add_meta (it, "title", convstr_id3v1 (title, strlen (title))); - pl_add_meta (it, "artist", convstr_id3v1 (artist, strlen (artist))); - pl_add_meta (it, "album", convstr_id3v1 (album, strlen (album))); - pl_add_meta (it, "year", year); - pl_add_meta (it, "comment", convstr_id3v1 (comment, strlen (comment))); - pl_add_meta (it, "genre", convstr_id3v1 (genre, strlen (genre))); + deadbeef->pl_add_meta (it, "title", convstr_id3v1 (title, strlen (title))); + deadbeef->pl_add_meta (it, "artist", convstr_id3v1 (artist, strlen (artist))); + deadbeef->pl_add_meta (it, "album", convstr_id3v1 (album, strlen (album))); + deadbeef->pl_add_meta (it, "year", year); + deadbeef->pl_add_meta (it, "comment", convstr_id3v1 (comment, strlen (comment))); + deadbeef->pl_add_meta (it, "genre", convstr_id3v1 (genre, strlen (genre))); if (tracknum != 0xff) { char s[4]; snprintf (s, 4, "%d", tracknum); - pl_add_meta (it, "track", s); + deadbeef->pl_add_meta (it, "track", s); } if (it->endoffset < 128) { @@ -1073,7 +1079,7 @@ cmp3_read_id3v1 (playItem_t *it, FILE *fp) { } int -cmp3_read_ape (playItem_t *it, FILE *fp) { +cmp3_read_ape (DB_playItem_t *it, FILE *fp) { // printf ("trying to read ape tag\n"); // try to read footer, position must be already at the EOF right before // id3v1 (if present) @@ -1140,16 +1146,16 @@ cmp3_read_ape (playItem_t *it, FILE *fp) { int valuetype = ((itemflags & (0x3<<1)) >> 1); if (valuetype == 0) { if (!strcasecmp (key, "artist")) { - pl_add_meta (it, "artist", value); + deadbeef->pl_add_meta (it, "artist", value); } else if (!strcasecmp (key, "title")) { - pl_add_meta (it, "title", value); + deadbeef->pl_add_meta (it, "title", value); } else if (!strcasecmp (key, "album")) { - pl_add_meta (it, "album", value); + deadbeef->pl_add_meta (it, "album", value); } else if (!strcasecmp (key, "track")) { - pl_add_meta (it, "track", value); + deadbeef->pl_add_meta (it, "track", value); } } } @@ -1182,7 +1188,7 @@ id3v2_string_read (int version, uint8_t *out, int sz, int unsync, uint8_t **prea } int -cmp3_read_id3v2 (playItem_t *it, FILE *fp) { +cmp3_read_id3v2 (DB_playItem_t *it, FILE *fp) { int title_added = 0; if (!it || !fp) { printf ("bad call to cmp3_read_id3v2!\n"); @@ -1403,31 +1409,31 @@ cmp3_read_id3v2 (playItem_t *it, FILE *fp) { } if (!err) { if (artist) { - pl_add_meta (it, "artist", artist); + deadbeef->pl_add_meta (it, "artist", artist); free (artist); } if (album) { - pl_add_meta (it, "album", album); + deadbeef->pl_add_meta (it, "album", album); free (album); } if (band) { - pl_add_meta (it, "band", band); + deadbeef->pl_add_meta (it, "band", band); free (band); } if (track) { - pl_add_meta (it, "track", track); + deadbeef->pl_add_meta (it, "track", track); free (track); } if (title) { - pl_add_meta (it, "title", title); + deadbeef->pl_add_meta (it, "title", title); free (title); } if (vendor) { - pl_add_meta (it, "vendor", vendor); + deadbeef->pl_add_meta (it, "vendor", vendor); free (vendor); } if (!title) { - pl_add_meta (it, "title", NULL); + deadbeef->pl_add_meta (it, "title", NULL); } return 0; } @@ -1445,7 +1451,7 @@ cmp3_read_id3v2 (playItem_t *it, FILE *fp) { #define FRAMES_AND_BYTES (FRAMES_FLAG | BYTES_FLAG) int -cmp3_read_info_tag (buffer_t *buffer, playItem_t *it, FILE *fp) { +cmp3_read_info_tag (buffer_t *buffer, DB_playItem_t *it, FILE *fp) { rewind (fp); int h_id, h_mode, h_sr_index, h_ly_index; static int sr_table[4] = { 44100, 48000, 32000, -1 }; @@ -1574,15 +1580,14 @@ cmp3_read_info_tag (buffer_t *buffer, playItem_t *it, FILE *fp) { #endif // }}} -playItem_t * -cmp3_insert (playItem_t *after, const char *fname) { +DB_playItem_t * +cmp3_insert (DB_playItem_t *after, const char *fname) { FILE *fp = fopen (fname, "rb"); if (!fp) { return NULL; } - playItem_t *it = malloc (sizeof (playItem_t)); - memset (it, 0, sizeof (playItem_t)); - it->codec = &cmp3; + DB_playItem_t *it = deadbeef->pl_item_alloc (); + it->decoder = &plugin; it->fname = strdup (fname); buffer_t buffer; @@ -1605,14 +1610,14 @@ cmp3_insert (playItem_t *after, const char *fname) { fseek (fp, 0, SEEK_END); } int apeerr = cmp3_read_ape (it, fp); - pl_add_meta (it, "title", NULL); + deadbeef->pl_add_meta (it, "title", NULL); buffer.startoffset = it->startoffset; fseek (fp, buffer.startoffset, SEEK_SET); // calc approx. mp3 duration int res = cmp3_scan_stream (&buffer, 0); if (res < 0) { - pl_item_free (it); + deadbeef->pl_item_free (it); return NULL; } it->startoffset = buffer.startoffset; @@ -1629,38 +1634,54 @@ cmp3_insert (playItem_t *after, const char *fname) { break; } - playItem_t *cue_after = pl_insert_cue (after, fname, &cmp3, it->filetype); + DB_playItem_t *cue_after = deadbeef->pl_insert_cue (after, fname, &plugin, it->filetype); if (cue_after) { cue_after->timeend = buffer.duration; cue_after->duration = cue_after->timeend - cue_after->timestart; - pl_item_free (it); + deadbeef->pl_item_free (it); fclose (fp); return cue_after; } - after = pl_insert_item (after, it); + after = deadbeef->pl_insert_item (after, it); fclose (fp); return after; } -static const char * exts[]= -{ +static const char *exts[] = { "mp1", "mp2", "mp3", NULL }; +static const char *filetypes[] = { + "MP1", "MP2", "MP3", NULL +}; + const char **cmp3_getexts (void) { return exts; } -codec_t cmp3 = { +// define plugin interface +static DB_decoder_t plugin = { + .plugin.version_major = 0, + .plugin.version_minor = 1, + .plugin.type = DB_PLUGIN_DECODER, + .plugin.name = "MPEG 1/2/3 decoder", + .plugin.descr = "based on libmad", + .plugin.author = "Alexey Yakovenko", + .plugin.email = "waker@users.sourceforge.net", + .plugin.website = "http://deadbeef.sf.net", .init = cmp3_init, .free = cmp3_free, .read = cmp3_read, .seek = cmp3_seek, .insert = cmp3_insert, - .getexts = cmp3_getexts, + .exts = exts, .id = "stdmp3", - .filetypes = { "MP1", "MP2", "MP3", NULL } + .filetypes = filetypes }; - +DB_plugin_t * +mpegmad_load (DB_functions_t *api) { + deadbeef = api; + return DB_PLUGIN (&plugin); +} @@ -18,6 +18,6 @@ #ifndef __CMP3_H #define __CMP3_H -extern codec_t cmp3; +//extern struct DB_decoder_s cmp3; #endif // __CMP3_H @@ -21,6 +21,7 @@ #include <stdint.h> //#include "playlist.h" +#if 0 typedef struct { int bitsPerSample; int channels; @@ -45,8 +46,9 @@ typedef struct codec_s { const char *filetypes[20]; // NULL terminated array of const strings, representing supported file types (can be NULL) fileinfo_t info; } codec_t; +#endif -codec_t *get_codec_for_file (const char *fname); +//codec_t *get_codec_for_file (const char *fname); void codec_init_locking (void); @@ -48,7 +48,7 @@ extern "C" { // there are "public" fields, available to plugins typedef struct { char *fname; // full pathname - struct codec_s *codec; // codec to use with this file + struct DB_decoder_s *decoder; // codec to use with this file int tracknum; // used for stuff like sid, nsf, cue (will be ignored by most codecs) float timestart; // start time of cue track, or -1 float timeend; // end time of cue track, or -1 @@ -138,7 +138,12 @@ typedef struct { DB_playItem_t * (*pl_item_alloc) (void); void (*pl_item_free) (DB_playItem_t *it); void (*pl_item_copy) (DB_playItem_t *out, DB_playItem_t *in); + DB_playItem_t *(*pl_insert_item) (DB_playItem_t *after, DB_playItem_t *it); + // metainfo + void (*pl_add_meta) (DB_playItem_t *it, const char *key, const char *value); const char *(*pl_find_meta) (DB_playItem_t *song, const char *meta); + // cuesheet support + DB_playItem_t * (*pl_insert_cue) (DB_playItem_t *after, const char *cuename, struct DB_decoder_s *decoder, const char *ftype); // volume control void (*volume_set_db) (float dB); float (*volume_get_db) (void); @@ -173,9 +178,17 @@ typedef struct DB_plugin_s { int (*exec_cmdline) (const char *cmdline, int cmdline_size); } DB_plugin_t; -// decoder plugin typedef struct { + int bps; + int channels; + int samplerate; + float readpos; +} DB_fileinfo_t; + +// decoder plugin +typedef struct DB_decoder_s { DB_plugin_t plugin; + DB_fileinfo_t info; // init is called to prepare song to be started int (*init) (DB_playItem_t *it); @@ -184,22 +197,37 @@ typedef struct { // read is called by streamer to decode specified number of bytes // must return number of bytes that were successfully decoded (sample aligned) - // output format is always single precision float + + // dummy function ptr int (*read) (char *buffer, int size); + + // read_int16 must always output 16 bit signed integer samples + int (*read_int16) (char *buffer, int size); + + // read_float32 must always output 32 bit floating point samples + int (*read_float32) (char *buffer, int size); + + int (*seek) (float seconds); // perform seeking in samples (if possible) // return -1 if failed, or 0 on success // if -1 is returned, that will mean that streamer must skip that song - int (*seek) (int64_t samples); + int (*seek_sample) (int64_t samples); // 'insert' is called to insert new item to playlist // decoder is responsible to calculate duration, split it into subsongs, load cuesheet, etc // after==NULL means "prepend before 1st item in playlist" - struct playItem_s * (*insert) (DB_playItem_t *after, const char *fname); + DB_playItem_t * (*insert) (DB_playItem_t *after, const char *fname); + + int (*numvoices) (void); + void (*mutevoice) (int voice, int mute); // NULL terminated array of all supported extensions const char **exts; + // NULL terminated array of all file type names + const char **filetypes; + // codec id used for playlist serialization const char *id; } DB_decoder_t; @@ -95,17 +95,17 @@ update_songinfo (void) { else if (p_isstopped ()) { strcpy (sbtext_new, "Stopped"); } - else if (playlist_current.codec) { + else if (playlist_current.decoder) { codec_lock (); - codec_t *c = playlist_current.codec; + DB_decoder_t *c = playlist_current.decoder; float playpos = streamer_get_playpos (); int minpos = playpos / 60; int secpos = playpos - minpos * 60; int mindur = playlist_current.duration / 60; int secdur = playlist_current.duration - mindur * 60; const char *mode = c->info.channels == 1 ? "Mono" : "Stereo"; - int samplerate = c->info.samplesPerSecond; - int bitspersample = c->info.bitsPerSample; + int samplerate = c->info.samplerate; + int bitspersample = c->info.bps; songpos = playpos; codec_unlock (); @@ -575,9 +575,9 @@ main (int argc, char *argv[]) { server_start (); conf_load (); + plug_load_all (); pl_load (defpl); session_load (sessfile); - plug_load_all (); messagepump_init (); codec_init_locking (); streamer_init (); @@ -34,16 +34,12 @@ #include "playback.h" #include "plugins.h" -#include "cvorbis.h" -#include "cdumb.h" -#include "cmp3.h" -#include "cgme.h" -#include "cflac.h" -#include "csid.h" - -codec_t *codecs[] = { - &cdumb, &cvorbis, &cflac, &cgme, &cmp3, &csid, NULL -}; +//#include "cvorbis.h" +//#include "cdumb.h" +//#include "cmp3.h" +//#include "cgme.h" +//#include "cflac.h" +//#include "csid.h" #define SKIP_BLANK_CUE_TRACKS 1 @@ -138,7 +134,7 @@ pl_cue_parse_time (const char *p) { } playItem_t * -pl_insert_cue (playItem_t *after, const char *fname, codec_t *codec, const char *ftype) { +pl_insert_cue (playItem_t *after, const char *fname, struct DB_decoder_s *decoder, const char *ftype) { int len = strlen (fname); char cuename[len+5]; strcpy (cuename, fname); @@ -246,11 +242,11 @@ pl_insert_cue (playItem_t *after, const char *fname, codec_t *codec, const char // printf ("adding %s\n", str); playItem_t *it = malloc (sizeof (playItem_t)); memset (it, 0, sizeof (playItem_t)); - it->codec = codec; + it->decoder = decoder; it->fname = strdup (file); it->tracknum = atoi (track); it->timestart = tstart; - it->timeend = -1; // will be filled by next read, or by codec + it->timeend = -1; // will be filled by next read, or by decoder it->filetype = ftype; after = pl_insert_item (after, it); pl_add_meta (it, "artist", performer); @@ -273,23 +269,24 @@ pl_insert_file (playItem_t *after, const char *fname, int *pabort, int (*cb)(pla if (!fname) { return NULL; } - // detect codec - codec_t *codec = NULL; + // detect decoder +// DB_decoder_t *decoder = NULL; const char *eol = fname + strlen (fname) - 1; while (eol > fname && *eol != '.') { eol--; } eol++; - // match by codec - for (int i = 0; codecs[i]; i++) { - if (codecs[i]->getexts && codecs[i]->insert) { - const char **exts = codecs[i]->getexts (); + DB_decoder_t **decoders = plug_get_decoder_list (); + // match by decoder + for (int i = 0; decoders[i]; i++) { + if (decoders[i]->exts && decoders[i]->insert) { + const char **exts = decoders[i]->exts; if (exts) { for (int e = 0; exts[e]; e++) { if (!strcasecmp (exts[e], eol)) { playItem_t *inserted = NULL; - if ((inserted = codecs[i]->insert (after, fname)) != NULL) { + if ((inserted = (playItem_t *)decoders[i]->insert (DB_PLAYITEM (after), fname)) != NULL) { if (cb) { if (cb (inserted, user_data) < 0) { *pabort = 1; @@ -528,7 +525,7 @@ pl_insert_item (playItem_t *after, playItem_t *it) { void pl_item_copy (playItem_t *out, playItem_t *it) { out->fname = strdup (it->fname); - out->codec = it->codec; + out->decoder = it->decoder; out->tracknum = it->tracknum; out->timestart = it->timestart; out->timeend = it->timeend; @@ -588,23 +585,23 @@ pl_set_current (playItem_t *it) { int ret = 0; int from = pl_get_idx_of (playlist_current_ptr); int to = it ? pl_get_idx_of (it) : -1; - if (playlist_current.codec) { + if (playlist_current.decoder) { plug_trigger_event (DB_EV_SONGFINISHED); } codec_lock (); - if (playlist_current.codec) { - playlist_current.codec->free (); + if (playlist_current.decoder) { + playlist_current.decoder->free (); } pl_item_free (&playlist_current); playlist_current_ptr = it; - if (it && it->codec) { + if (it && it->decoder) { // don't do anything on fail, streamer will take care - ret = it->codec->init (it); + ret = it->decoder->init (DB_PLAYITEM (it)); if (ret < 0) { // pl_item_free (&playlist_current); // playlist_current_ptr = NULL; // return ret; -//// it->codec->info.samplesPerSecond = -1; +//// it->decoder->info.samplesPerSecond = -1; } } if (playlist_current_ptr) { @@ -810,10 +807,10 @@ void pl_start_current (void) { codec_lock (); playItem_t *it = playlist_current_ptr; - if (it && it->codec) { + if (it && it->decoder) { // don't do anything on fail, streamer will take care - it->codec->free (); - it->codec->init (it); + it->decoder->free (); + it->decoder->init (DB_PLAYITEM (it)); } codec_unlock (); } @@ -995,11 +992,11 @@ pl_save (const char *fname) { if (fwrite (it->fname, 1, l, fp) != l) { goto save_fail; } - ll = strlen (it->codec->id); + ll = strlen (it->decoder->id); if (fwrite (&ll, 1, 1, fp) != 1) { goto save_fail; } - if (fwrite (it->codec->id, 1, ll, fp) != ll) { + if (fwrite (it->decoder->id, 1, ll, fp) != ll) { goto save_fail; } l = it->tracknum; @@ -1064,6 +1061,7 @@ save_fail: int pl_load (const char *fname) { pl_free (); + DB_decoder_t **decoders = plug_get_decoder_list (); uint8_t majorver = 1; uint8_t minorver = 0; FILE *fp = fopen (fname, "rb"); @@ -1110,7 +1108,7 @@ pl_load (const char *fname) { goto load_fail; } it->fname[l] = 0; - // codec + // decoder uint8_t ll; if (fread (&ll, 1, 1, fp) != 1) { goto load_fail; @@ -1118,17 +1116,17 @@ pl_load (const char *fname) { if (ll >= 20) { goto load_fail; } - char codec[20]; - if (fread (codec, 1, ll, fp) != ll) { + char decoder[20]; + if (fread (decoder, 1, ll, fp) != ll) { goto load_fail; } - codec[ll] = 0; - for (int c = 0; codecs[c]; c++) { - if (!strcmp (codec, codecs[c]->id)) { - it->codec = codecs[c]; + decoder[ll] = 0; + for (int c = 0; decoders[c]; c++) { + if (!strcmp (decoder, decoders[c]->id)) { + it->decoder = decoders[c]; } } - if (!it->codec) { + if (!it->decoder) { goto load_fail; } // tracknum @@ -1148,7 +1146,7 @@ pl_load (const char *fname) { if (fread (&it->duration, 1, 4, fp) != 4) { goto load_fail; } - // get const filetype string from codec + // get const filetype string from decoder uint8_t ft; if (fread (&ft, 1, 1, fp) != 1) { goto load_fail; @@ -1159,10 +1157,10 @@ pl_load (const char *fname) { goto load_fail; } ftype[ft] = 0; - if (it->codec && it->codec->filetypes) { - for (int i = 0; it->codec->filetypes[i]; i++) { - if (!strcasecmp (it->codec->filetypes[i], ftype)) { - it->filetype = it->codec->filetypes[i]; + if (it->decoder && it->decoder->filetypes) { + for (int i = 0; it->decoder->filetypes[i]; i++) { + if (!strcasecmp (it->decoder->filetypes[i], ftype)) { + it->filetype = it->decoder->filetypes[i]; break; } } @@ -30,7 +30,7 @@ typedef struct metaInfo_s { typedef struct playItem_s { char *fname; // full pathname - struct codec_s *codec; // codec to use with this file + struct DB_decoder_s *decoder; // codec to use with this file int tracknum; // used for stuff like sid, nsf, cue (will be ignored by most codecs) float timestart; // start time of cue track, or -1 float timeend; // end time of cue track, or -1 @@ -100,7 +100,7 @@ int pl_get_idx_of (playItem_t *it); playItem_t * -pl_insert_cue (playItem_t *after, const char *cuename, struct codec_s *codec, const char *ftype); +pl_insert_cue (playItem_t *after, const char *cuename, struct DB_decoder_s *decoder, const char *ftype); int pl_set_current (playItem_t *it); @@ -52,7 +52,12 @@ DB_functions_t deadbeef_api = { .pl_item_alloc = (DB_playItem_t* (*)(void))pl_item_alloc, .pl_item_free = (void (*)(DB_playItem_t *))pl_item_free, .pl_item_copy = (void (*)(DB_playItem_t *, DB_playItem_t *))pl_item_copy, - .pl_find_meta = (const char *(*) (DB_playItem_t *song, const char *meta))pl_find_meta, + .pl_insert_item = (DB_playItem_t *(*) (DB_playItem_t *after, DB_playItem_t *it))pl_insert_item, + // metainfo + .pl_add_meta = (void (*) (DB_playItem_t *, const char *, const char *))pl_add_meta, + .pl_find_meta = (const char *(*) (DB_playItem_t *, const char *))pl_find_meta, + // cuesheet support + .pl_insert_cue = (DB_playItem_t *(*)(DB_playItem_t *, const char *, struct DB_decoder_s *, const char *))pl_insert_cue, // volume control .volume_set_db = volume_set_db, .volume_get_db = volume_get_db, @@ -60,6 +65,10 @@ DB_functions_t deadbeef_api = { .volume_get_amp = volume_get_amp, }; +// hack: mp3 decoder module +DB_plugin_t *cmp3; +DB_decoder_t *g_decoders[2]; + void plug_md5 (uint8_t sig[16], const char *in, int len) { md5_buffer (in, len, sig); @@ -263,6 +272,11 @@ plug_load_all (void) { } free (namelist); } + // hack: init mp3 decoder module, and store pointer + extern DB_plugin_t *mpegmad_load (DB_functions_t *api); + cmp3 = mpegmad_load (&deadbeef_api); + g_decoders[0] = (DB_decoder_t*)cmp3; + g_decoders[1] = NULL; } void @@ -276,3 +290,9 @@ plug_unload_all (void) { plugins = next; } } + +struct DB_decoder_s ** +plug_get_decoder_list (void) { + return g_decoders; +} + @@ -50,4 +50,7 @@ plug_playback_get_pos (void); void plug_playback_set_pos (float pos); +struct DB_decoder_s ** +plug_get_decoder_list (void); + #endif // __PLUGINS_H diff --git a/plugins/lastfm/lastfm.c b/plugins/lastfm/lastfm.c index 4a276916..d637b61b 100644 --- a/plugins/lastfm/lastfm.c +++ b/plugins/lastfm/lastfm.c @@ -119,11 +119,6 @@ curl_req_cleanup (void) { static int auth (void) { - static int count = 5; - if (count > 0) { - count--; - return -1; - } if (lfm_sess[0]) { return 0; } @@ -33,6 +33,7 @@ #include "conf.h" #include "plugins.h" +static int streamer_tid; static SRC_STATE *src; static SRC_DATA srcdata; static int codecleft; @@ -135,9 +136,9 @@ streamer_thread (uintptr_t ctx) { if (seekpos >= 0) { float pos = seekpos; seekpos = -1; - if (playlist_current.codec && playlist_current.codec->seek (pos) >= 0) { + if (playlist_current.decoder && playlist_current.decoder->seek (pos) >= 0) { streamer_lock (); - playpos = playlist_current.codec->info.readposition; + playpos = playlist_current.decoder->info.readpos; streambuffer_fill = 0; streamer_unlock (); codec_lock (); @@ -179,13 +180,14 @@ streamer_init (void) { if (!src) { return -1; } - thread_start (streamer_thread, 0); + streamer_tid = thread_start (streamer_thread, 0); return 0; } void streamer_free (void) { streaming_terminate = 1; + thread_join (streamer_tid); mutex_free (mutex); } @@ -205,23 +207,23 @@ streamer_read_async (char *bytes, int size) { for (;;) { int bytesread = 0; codec_lock (); - codec_t *codec = playlist_current.codec; - if (!codec) { + DB_decoder_t *decoder = playlist_current.decoder; + if (!decoder) { codec_unlock (); break; } - if (codec->info.samplesPerSecond != -1) { - int nchannels = codec->info.channels; - int samplerate = codec->info.samplesPerSecond; + if (decoder->info.samplerate != -1) { + int nchannels = decoder->info.channels; + int samplerate = decoder->info.samplerate; // read and do SRC - if (codec->info.samplesPerSecond == p_get_rate ()) { + if (decoder->info.samplerate == p_get_rate ()) { int i; - if (codec->info.channels == 2) { - bytesread = codec->read (bytes, size); + if (decoder->info.channels == 2) { + bytesread = decoder->read (bytes, size); codec_unlock (); } else { - bytesread = codec->read (g_readbuffer, size/2); + bytesread = decoder->read (g_readbuffer, size/2); codec_unlock (); for (i = 0; i < size/4; i++) { int16_t sample = (int16_t)(((int32_t)(((int16_t*)g_readbuffer)[i]))); @@ -249,7 +251,7 @@ streamer_read_async (char *bytes, int size) { // printf ("FATAL: nbytes=%d, nsamples=%d, codecleft=%d, nchannels=%d, ratio=%f\n", nbytes, nsamples, codecleft, nchannels, (float)p_get_rate ()/samplerate); // assert ((nbytes & 3) == 0); // } - bytesread = codec->read (g_readbuffer, nbytes); + bytesread = decoder->read (g_readbuffer, nbytes); } codec_unlock (); // recalculate nsamples according to how many bytes we've got |