summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar waker <wakeroid@gmail.com>2009-08-29 21:36:19 +0200
committerGravatar waker <wakeroid@gmail.com>2009-08-29 21:36:19 +0200
commitf4d508b243888a9dbe79b5916e497254d370e35a (patch)
tree48846519dfc51a3d44991b3b4b18a2efda5083f0
parent003a54afeba00597fd2f50e38ccd35c7cd5e4e39 (diff)
mp3 decoder porting as plugin WIP
-rw-r--r--Makefile.am6
-rw-r--r--callbacks.c61
-rw-r--r--cmp3.c137
-rw-r--r--cmp3.h2
-rw-r--r--codec.h4
-rw-r--r--deadbeef.h38
-rw-r--r--main.c10
-rw-r--r--playlist.c88
-rw-r--r--playlist.h4
-rw-r--r--plugins.c22
-rw-r--r--plugins.h3
-rw-r--r--plugins/lastfm/lastfm.c5
-rw-r--r--streamer.c28
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;
}
diff --git a/cmp3.c b/cmp3.c
index fdf19029..d0db147f 100644
--- a/cmp3.c
+++ b/cmp3.c
@@ -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);
+}
diff --git a/cmp3.h b/cmp3.h
index 5cdf1795..80b59468 100644
--- a/cmp3.h
+++ b/cmp3.h
@@ -18,6 +18,6 @@
#ifndef __CMP3_H
#define __CMP3_H
-extern codec_t cmp3;
+//extern struct DB_decoder_s cmp3;
#endif // __CMP3_H
diff --git a/codec.h b/codec.h
index 82d95491..8c76bff4 100644
--- a/codec.h
+++ b/codec.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);
diff --git a/deadbeef.h b/deadbeef.h
index 452717bc..537ad014 100644
--- a/deadbeef.h
+++ b/deadbeef.h
@@ -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;
diff --git a/main.c b/main.c
index 885eaa9c..d724dc13 100644
--- a/main.c
+++ b/main.c
@@ -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 ();
diff --git a/playlist.c b/playlist.c
index 14be6429..ed391de3 100644
--- a/playlist.c
+++ b/playlist.c
@@ -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;
}
}
diff --git a/playlist.h b/playlist.h
index a84a19ec..1d007aa2 100644
--- a/playlist.h
+++ b/playlist.h
@@ -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);
diff --git a/plugins.c b/plugins.c
index f1f0c4f0..60c36a8e 100644
--- a/plugins.c
+++ b/plugins.c
@@ -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;
+}
+
diff --git a/plugins.h b/plugins.h
index d155f54a..a82a2eb7 100644
--- a/plugins.h
+++ b/plugins.h
@@ -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;
}
diff --git a/streamer.c b/streamer.c
index 9df1b633..b5dafebc 100644
--- a/streamer.c
+++ b/streamer.c
@@ -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