From 7bccab7d4a27e554259637f4ed23356519433549 Mon Sep 17 00:00:00 2001 From: waker Date: Tue, 4 Aug 2009 17:49:03 +0200 Subject: playlist insertion WIP --- cdumb.c | 12 ++-- cflac.c | 27 ++++----- cgme.c | 10 ++-- cmp3.c | 12 ++-- codec.h | 5 +- common.h | 12 ---- csid.cpp | 22 +++++-- cvorbis.c | 14 ++--- playlist.c | 195 +++++++++++++++++++++++++++++++++++++++++++++++++++---------- playlist.h | 21 ++++++- psdl.c | 11 ++++ 11 files changed, 252 insertions(+), 89 deletions(-) diff --git a/cdumb.c b/cdumb.c index dc4062e9..8a6680e8 100644 --- a/cdumb.c +++ b/cdumb.c @@ -656,8 +656,8 @@ static DUH * open_module(const char *fname, const char *ext, int *start_order, i return duh; } -int -cdumb_add (const char *fname) { +playItem_t * +cdumb_insert (playItem_t *after, const char *fname) { const char *ext = fname + strlen (fname) - 1; while (*ext != '.' && ext > fname) { ext--; @@ -669,7 +669,7 @@ cdumb_add (const char *fname) { dumb_register_stdfiles (); DUH* duh = open_module(fname, ext, &start_order, &is_it, &is_dos); if (!duh) { - return -1; + return NULL; } unload_duh (duh); playItem_t *it = malloc (sizeof (playItem_t)); @@ -679,9 +679,9 @@ cdumb_add (const char *fname) { it->tracknum = 0; it->timestart = 0; it->timeend = 0; - ps_append_item (it); + after = ps_insert_item (after, it); - return 0; + return after; } const char **cdumb_getexts (void) { @@ -693,7 +693,7 @@ codec_t cdumb = { .free = cdumb_free, .read = cdumb_read, .seek = cdumb_seek, - .add = cdumb_add, + .insert = cdumb_insert, .getexts = cdumb_getexts }; diff --git a/cflac.c b/cflac.c index eb95f8ac..0c6ea3c5 100644 --- a/cflac.c +++ b/cflac.c @@ -181,22 +181,23 @@ cflac_init_metadata_callback(const FLAC__StreamDecoder *decoder, const FLAC__Str *psr = metadata->data.stream_info.sample_rate; } -int -cflac_add (const char *fname) { +playItem_t * +cflac_insert (playItem_t *after, const char *fname) { // try cue char cuename[1024]; snprintf (cuename, 1024, "%s.cue", fname); // printf ("loading %s\n", cuename); - if (!ps_add_cue (cuename)) { - return 0; + playItem_t *cue_after; + if ((cue_after = ps_insert_cue (after, cuename)) != NULL) { + return cue_after; } int n = strlen (fname) - 4; if (n > 0) { strncpy (cuename, fname, n); strcpy (cuename + n, "cue"); // printf ("loading %s\n", cuename); - if (!ps_add_cue (cuename)) { - return 0; + if ((cue_after = ps_insert_cue (after, cuename)) != NULL) { + return cue_after; } } @@ -205,22 +206,22 @@ cflac_add (const char *fname) { decoder = FLAC__stream_decoder_new(); if (!decoder) { printf ("FLAC__stream_decoder_new failed\n"); - return -1; + return NULL; } FLAC__stream_decoder_set_md5_checking(decoder, 0); int samplerate = -1; status = FLAC__stream_decoder_init_file(decoder, fname, cflac_init_write_callback, cflac_init_metadata_callback, cflac_error_callback, &samplerate); if (status != FLAC__STREAM_DECODER_INIT_STATUS_OK) { FLAC__stream_decoder_delete(decoder); - return -1; + return NULL; } if (!FLAC__stream_decoder_process_until_end_of_metadata (decoder)) { FLAC__stream_decoder_delete(decoder); - return -1; + return NULL; } if (samplerate == -1) { // not a FLAC stream FLAC__stream_decoder_delete(decoder); - return -1; + return NULL; } FLAC__stream_decoder_delete(decoder); playItem_t *it = malloc (sizeof (playItem_t)); @@ -230,8 +231,8 @@ cflac_add (const char *fname) { it->tracknum = 0; it->timestart = 0; it->timeend = 0; - ps_append_item (it); - return 0; + after = ps_insert_item (after, it); + return after; } static const char * exts[]= @@ -248,6 +249,6 @@ codec_t cflac = { .free = cflac_free, .read = cflac_read, .seek = cflac_seek, - .add = cflac_add, + .insert = cflac_insert, .getexts = cflac_getexts }; diff --git a/cgme.c b/cgme.c index 72193c29..74a7e6e2 100644 --- a/cgme.c +++ b/cgme.c @@ -89,8 +89,8 @@ cgme_seek (float time) { return 0; } -int -cgme_add (const char *fname) { +playItem_t * +cgme_insert (playItem_t *after, const char *fname) { // printf ("adding %s chiptune\n", fname); Music_Emu *emu; if (!gme_open_file (fname, &emu, gme_info_only)) { @@ -123,7 +123,7 @@ cgme_add (const char *fname) { char trk[10]; snprintf (trk, 10, "%d", i+1); ps_add_meta (it, "track", trk); - ps_append_item (it); + after = ps_insert_item (after, it); } else { printf ("gme error: %s\n", ret); @@ -136,7 +136,7 @@ cgme_add (const char *fname) { else { printf ("error adding %s\n", fname); } - return 0; + return after; } static const char * exts[]= @@ -170,7 +170,7 @@ codec_t cgme = { .free = cgme_free, .read = cgme_read, .seek = cgme_seek, - .add = cgme_add, + .insert = cgme_insert, .getexts = cgme_getexts, .numvoices = cgme_numvoices, .mutevoice = cgme_mutevoice diff --git a/cmp3.c b/cmp3.c index c7349445..9338b447 100644 --- a/cmp3.c +++ b/cmp3.c @@ -916,11 +916,11 @@ cmp3_read_id3v2 (playItem_t *it, FILE *fp) { return 0; } -int -cmp3_add (const char *fname) { +playItem_t * +cmp3_insert (playItem_t *after, const char *fname) { FILE *fp = fopen (fname, "rb"); if (!fp) { - return -1; + return NULL; } playItem_t *it = malloc (sizeof (playItem_t)); memset (it, 0, sizeof (playItem_t)); @@ -933,8 +933,8 @@ cmp3_add (const char *fname) { it->tracknum = 0; it->timestart = 0; it->timeend = 0; - ps_append_item (it); - return 0; + after = ps_insert_item (after, it); + return after; } static const char * exts[]= @@ -951,7 +951,7 @@ codec_t cmp3 = { .free = cmp3_free, .read = cmp3_read, .seek = cmp3_seek, - .add = cmp3_add, + .insert = cmp3_insert, .getexts = cmp3_getexts }; diff --git a/codec.h b/codec.h index 5e86cb78..68f29e54 100644 --- a/codec.h +++ b/codec.h @@ -2,6 +2,7 @@ #define __CODEC_H #include +//#include "playlist.h" typedef struct { int bitsPerSample; @@ -11,13 +12,15 @@ typedef struct { float position; } fileinfo_t; +struct playItem_s; + typedef struct codec_s { int (*init) (const char *fname, int track, float start, float end); void (*free) (void); // player is responsible for starting next song if -1 is returned int (*read) (char *bytes, int size); int (*seek) (float time); - int (*add) (const char *fname); + struct playItem_s * (*insert) (struct playItem_s *after, const char *fname); // after==NULL means "prepend to beginning" const char ** (*getexts) (void); int (*numvoices) (void); void (*mutevoice) (int voice, int mute); diff --git a/common.h b/common.h index 0cefcb8d..63f0f010 100644 --- a/common.h +++ b/common.h @@ -4,16 +4,4 @@ #define min(x,y) ((x)<(y)?(x):(y)) #define max(x,y) ((x)>(y)?(x):(y)) -inline void -le_int16 (int16_t in, char *out) { - char *pin = (char *)∈ -#if !BIGENDIAN - out[0] = pin[0]; - out[1] = pin[1]; -#else - out[1] = pin[0]; - out[0] = pin[1]; -#endif -} - #endif // __COMMON_H diff --git a/csid.cpp b/csid.cpp index 76394b16..e0f36605 100644 --- a/csid.cpp +++ b/csid.cpp @@ -12,6 +12,18 @@ extern "C" { #include "common.h" } +static inline void +le_int16 (int16_t in, char *out) { + char *pin = (char *)∈ +#if !BIGENDIAN + out[0] = pin[0]; + out[1] = pin[1]; +#else + out[1] = pin[0]; + out[0] = pin[1]; +#endif +} + static sidplay2 *sidplay; static ReSIDBuilder *resid; static SidTune *tune; @@ -346,8 +358,8 @@ convstr (const char* str) { return out; } -extern "C" int -csid_add (const char *fname) { +extern "C" playItem_t * +csid_insert (playItem_t *after, const char *fname) { sldb_load(sldb_fname); SidTune *tune; tune = new SidTune (fname); @@ -384,11 +396,11 @@ csid_add (const char *fname) { char trk[10]; snprintf (trk, 10, "%d", s+1); ps_add_meta (it, "track", trk); - ps_append_item (it); + after = ps_insert_item (after, it); } } delete tune; - return 0; + return after; } static const char *exts[]= @@ -428,7 +440,7 @@ codec_t csid = { csid_free, csid_read, csid_seek, - csid_add, + csid_insert, csid_getexts, csid_numvoices, csid_mutevoice diff --git a/cvorbis.c b/cvorbis.c index f45194f7..2d801113 100644 --- a/cvorbis.c +++ b/cvorbis.c @@ -97,19 +97,19 @@ cvorbis_seek (float time) { return 0; } -int -cvorbis_add (const char *fname) { +playItem_t * +cvorbis_insert (playItem_t *after, const char *fname) { // check for validity FILE *fp = fopen (fname, "rb"); if (!fp) { - return -1; + return NULL; } OggVorbis_File vorbis_file; vorbis_info *vi; ov_open (fp, &vorbis_file, NULL, 0); vi = ov_info (&vorbis_file, -1); if (!vi) { // not a vorbis stream - return -1; + return NULL; } playItem_t *it = malloc (sizeof (playItem_t)); memset (it, 0, sizeof (playItem_t)); @@ -136,8 +136,8 @@ cvorbis_add (const char *fname) { } } ov_clear (&vorbis_file); - ps_append_item (it); - return 0; + after = ps_insert_item (after, it); + return after; } static const char * exts[]= @@ -154,7 +154,7 @@ codec_t cvorbis = { .free = cvorbis_free, .read = cvorbis_read, .seek = cvorbis_seek, - .add = cvorbis_add, + .insert = cvorbis_insert, .getexts = cvorbis_getexts }; diff --git a/playlist.c b/playlist.c index 07a175d8..d91af9cf 100644 --- a/playlist.c +++ b/playlist.c @@ -110,8 +110,131 @@ ps_cue_parse_time (const char *p) { return mins * 60 + sec; } +playItem_t * +ps_insert_cue (playItem_t *after, const char *cuename) { + FILE *fp = fopen (cuename, "rt"); + if (!fp) { + return NULL; + } + char performer[1024]; + char albumtitle[1024]; + char file[1024]; + char track[1024]; + char title[1024]; + char start[1024]; + playItem_t *prev = NULL; + for (;;) { + char str[1024]; + if (!fgets (str, 1024, fp)) { + break; // eof + } + char *p = ps_cue_skipspaces (str); + if (!strncmp (p, "PERFORMER ", 10)) { + ps_get_qvalue_from_cue (p + 10, performer); +// printf ("got performer: %s\n", performer); + } + else if (!strncmp (p, "TITLE ", 6)) { + if (str[0] > ' ') { + ps_get_qvalue_from_cue (p + 6, albumtitle); +// printf ("got albumtitle: %s\n", albumtitle); + } + else { + ps_get_qvalue_from_cue (p + 6, title); +// printf ("got title: %s\n", title); + } + } + else if (!strncmp (p, "FILE ", 5)) { + ps_get_qvalue_from_cue (p + 5, file); +// printf ("got filename: %s\n", file); + // copy directory name + char fname[1024]; + int len = strlen (cuename); + memcpy (fname, cuename, len+1); + char *p = fname + len; + while (*p != '/') { + p--; + len--; + } + p++; + len++; + // add file name + int flen = strlen (file); + // ensure fullname fills in buffer + if (flen + len >= 1024) { +// printf ("cue file name is too long"); + return NULL; + } + strcpy (p, file); + // copy full name in place of relative name + strcpy (file, fname); +// printf ("ended up as: %s\n", file); + } + else if (!strncmp (p, "TRACK ", 6)) { + ps_get_value_from_cue (p + 6, track); +// printf ("got track: %s\n", track); + } +// else if (!strncmp (p, "PERFORMER ", 10)) { +// ps_get_qvalue_from_cue (p + 10, performer); +// } + else if (!strncmp (p, "INDEX 00 ", 9) || !strncmp (p, "INDEX 01 ", 9)) { + if (!track[0]) { + continue; + } +#if SKIP_BLANK_CUE_TRACKS + if (!title[0]) + continue; +#endif + ps_get_value_from_cue (p + 9, start); +// printf ("got index0: %s\n", start); + char *p = track; + while (*p && isdigit (*p)) { + p++; + } + *p = 0; + // check that indexes have valid timestamps + float tstart = ps_cue_parse_time (start); + if (tstart < 0) { +// printf ("cue file %s has bad timestamp(s)\n", cuename); + continue; + } + if (prev) { + prev->timeend = tstart; +// printf ("end time for prev track (%x): %f\n", prev, tstart); + } + // add this track + char str[1024]; + snprintf (str, 1024, "%d. %s - %s", atoi (track), performer, title[0] ? title : "?", start, tstart); +// printf ("adding %s\n", str); + playItem_t *it = malloc (sizeof (playItem_t)); + memset (it, 0, sizeof (playItem_t)); + it->codec = &cflac; + it->fname = strdup (file); + it->tracknum = atoi (track); + it->timestart = tstart; + it->timeend = -1; // will be filled by next read, or by codec + after = ps_insert_item (after, it); +// ps_append_item (it); +// printf ("added item %x\n", it); + prev = it; + track[0] = 0; + } + else { +// printf ("got unknown line:\n%s\n", p); + } + } + fclose (fp); + return after; +} + int ps_add_cue (const char *cuename) { + playItem_t *it = ps_insert_cue (playlist_tail, cuename); + if (!it) { + return -1; + } + return 0; +// {{{ hide old cue code +#if 0 FILE *fp = fopen (cuename, "rt"); if (!fp) { return -1; @@ -223,6 +346,16 @@ ps_add_cue (const char *cuename) { } fclose (fp); return 0; +#endif +// }}} +} + +playItem_t * +ps_insert_file (playItem_t *after, const char *fname) { +} + +playItem_t * +ps_insert_dir (playItem_t *after, const char *dirname) { } int @@ -242,13 +375,15 @@ ps_add_file (const char *fname) { codec_t *codecs[] = { &cdumb, &cvorbis, &cflac, &cgme, &cmp3, &csid, NULL }; + playItem_t *after = playlist_tail; for (int i = 0; codecs[i]; i++) { - if (codecs[i]->getexts && codecs[i]->add) { + if (codecs[i]->getexts && codecs[i]->insert) { const char **exts = codecs[i]->getexts (); if (exts) { for (int e = 0; exts[e]; e++) { if (!strcasecmp (exts[e], eol)) { - if (!codecs[i]->add (fname)) { + playItem_t *inserted = NULL; + if ((inserted = codecs[i]->insert (after, fname)) != NULL) { return 0; } } @@ -258,35 +393,6 @@ ps_add_file (const char *fname) { } return -1; -#if 0 - // add by extension (temporary hack) -// else if (!strcasecmp (eol, "wav")) { -// codec = &cwav; -// } - if (!strcasecmp (eol, "mp3")) { - codec = &cmp3; - } - else { - return -1; - } - // copy string - playItem_t *it = malloc (sizeof (playItem_t)); - memset (it, 0, sizeof (playItem_t)); - it->codec = codec; - it->fname = strdup (fname); - // find 1st slash from end - while (eol > fname && *eol != '/') { - eol--; - } - if (*eol=='/') { - eol++; - } - - it->timestart = -1; - it->timeend = -1; - - ps_append_item (it); -#endif } int @@ -406,6 +512,33 @@ ps_append_item (playItem_t *it) { ps_count++; } +playItem_t * +ps_insert_item (playItem_t *after, playItem_t *it) { + if (!after) { + it->next = playlist_head; + it->prev = NULL; + if (playlist_head) { + playlist_head->prev = it; + } + else { + playlist_tail = it; + } + playlist_head = it; + } + else { + it->next = after; + it->prev = after->prev; + if (after->prev) { + after->prev->next = it; + } + after->prev = it; + if (after == playlist_tail) { + playlist_tail = it; + } + } + return it; +} + void ps_item_copy (playItem_t *out, playItem_t *it) { out->fname = strdup (it->fname); diff --git a/playlist.h b/playlist.h index d649b416..681bf2bc 100644 --- a/playlist.h +++ b/playlist.h @@ -25,13 +25,22 @@ extern playItem_t *playlist_current_ptr; // pointer to a real current playlist i extern playItem_t playlist_current; // copy of playlist item being played (stays in memory even if removed from playlist) int -ps_add_file (const char *fname); +ps_add_dir (const char *dirname); int -ps_append_item (playItem_t *it); +ps_add_file (const char *fname); + +playItem_t * +ps_insert_dir (playItem_t *after, const char *dirname); + +playItem_t * +ps_insert_file (playItem_t *after, const char *fname); + +playItem_t * +ps_insert_item (playItem_t *after, playItem_t *it); int -ps_add_dir (const char *dirname); +ps_append_item (playItem_t *it); int ps_remove (playItem_t *i); @@ -57,6 +66,12 @@ ps_get_idx_of (playItem_t *it); int ps_add_cue (const char *cuename); +playItem_t * +ps_insert_cue (playItem_t *after, const char *cuename); + +playItem_t * +ps_insert_cue (playItem_t *after, const char *cuename); + int ps_set_current (playItem_t *it); diff --git a/psdl.c b/psdl.c index 1ffa21ca..72305b7e 100644 --- a/psdl.c +++ b/psdl.c @@ -9,6 +9,17 @@ static SDL_AudioSpec spec; static void psdl_callback (void *userdata, Uint8 *stream, int len); static float sdl_volume = 1; +static inline void +le_int16 (int16_t in, char *out) { + char *pin = (char *)∈ +#if !BIGENDIAN + out[0] = pin[0]; + out[1] = pin[1]; +#else + out[1] = pin[0]; + out[0] = pin[1]; +#endif +} int psdl_init (void) { SDL_AudioSpec obt; -- cgit v1.2.3