Support for input plugins with multiple tracks per file
Olivier Galibert <[email protected]>
| Newsgroups | gmane.comp.multimedia.xmms.devel |
|---|---|
| Message-ID | <[email protected]> |
Everything is in the subject. Single-track-per-channel plugins are source and binary compatible with the post-patch version. For multi-track plugins the InputPlugin structure has 3 more optional fields placed at the end: int (*count_tracks) (char *filename); /* Return the number of tracks available in a given file */ void (*play_track) (char *filename, int track); /* Play a given track from a file */ void (*get_track_info) (char *filename, int track, char **title, int *length); /* Function to grab the title string */ play_track replaces play_file (which MUST be null, that's how the type is recognized) and get_track_info replaces get_song_info. Playlists are compatible both ways, the only difference is when the track is non-zero the "filename" line in .m3u files is changed into "trackno filename" with a space for separator. I attach the patch to xmms-cvs and also a patch to xmms-sidplay-0.40 as an example of use. OG. _______________________________________________ xmms-devel mailing list [email protected] http://lists.xmms.org/mailman/listinfo/xmms-devel
multitrack.diff
(text/plain, 11.2 KB)
Index: xmms/input.c
===================================================================
RCS file: /cvs/xmms/xmms/input.c,v
retrieving revision 1.18
diff -u -r1.18 input.c
--- xmms/input.c 13 Jul 2003 22:16:39 -0000 1.18
+++ xmms/input.c 17 Nov 2003 01:28:31 -0000
@@ -224,7 +224,7 @@
pthread_mutex_unlock(&vis_mutex);
}
-gboolean input_check_file(gchar * filename)
+guint input_check_file(gchar * filename)
{
GList *node;
InputPlugin *ip;
@@ -235,13 +235,20 @@
ip = (InputPlugin *) node->data;
if (ip && !g_list_find(disabled_iplugins, ip) &&
ip->is_our_file(filename))
- return TRUE;
+ {
+ /* Single-track plugin */
+ if (ip->play_file)
+ return 1;
+ /* Multi-track */
+ else
+ return ip->count_tracks(filename);
+ }
node = node->next;
}
- return FALSE;
+ return 0;
}
-void input_play(char *filename)
+void input_play(char *filename, guint track)
{
GList *node;
InputPlugin *ip;
@@ -263,7 +270,10 @@
{
set_current_input_plugin(ip);
ip->output = get_current_output_plugin();
- ip->play_file(filename);
+ if (ip->play_file)
+ ip->play_file(filename);
+ else
+ ip->play_track(filename, track);
ip_data->playing = TRUE;
return;
@@ -339,11 +349,13 @@
get_current_input_plugin()->set_eq(on, preamp, bands);
}
-void input_get_song_info(gchar * filename, gchar ** title, gint * length)
+void input_get_song_info(gchar * filename, guint track, gchar ** title, gint * length)
{
GList *node;
InputPlugin *ip = NULL;
+ fprintf(stderr, "GSI %s:%d\n", filename, track);
+
node = get_input_list();
while (node)
{
@@ -353,8 +365,13 @@
break;
node = node->next;
}
- if (ip && node && ip->get_song_info)
- ip->get_song_info(filename, title, length);
+ if (ip && node && (ip->play_file ? ip->get_song_info != 0 : ip->get_track_info != 0))
+ {
+ if (ip->play_file)
+ ip->get_song_info(filename, title, length);
+ else
+ ip->get_track_info(filename, track, title, length);
+ }
else
{
gchar *temp, *ext;
Index: xmms/input.h
===================================================================
RCS file: /cvs/xmms/xmms/input.h,v
retrieving revision 1.4
diff -u -r1.4 input.h
--- xmms/input.h 16 Feb 2000 21:05:57 -0000 1.4
+++ xmms/input.h 17 Nov 2003 01:28:31 -0000
@@ -31,14 +31,14 @@
InputPlugin *get_current_input_plugin(void);
void set_current_input_plugin(InputPlugin * ip);
InputVisType input_get_vis_type();
-gboolean input_check_file(gchar * filename);
-void input_play(char *filename);
+guint input_check_file(gchar * filename);
+void input_play(char *filename, guint track);
void input_stop(void);
void input_pause(void);
int input_get_time(void);
void input_set_eq(int on, float preamp, float *bands);
void input_seek(int time);
-void input_get_song_info(gchar * filename, gchar ** title, gint * length);
+void input_get_song_info(gchar * filename, guint track, gchar ** title, gint * length);
gboolean get_input_playing(void);
gboolean get_input_paused(void);
guchar *input_get_vis(gint time);
Index: xmms/playlist.c
===================================================================
RCS file: /cvs/xmms/xmms/playlist.c,v
retrieving revision 1.78
diff -u -r1.78 playlist.c
--- xmms/playlist.c 6 Nov 2003 23:36:35 -0000 1.78
+++ xmms/playlist.c 17 Nov 2003 01:28:32 -0000
@@ -254,12 +254,13 @@
}
}
-static void __playlist_ins_with_info(char *filename, long pos, char* title, int len)
+static void __playlist_ins_with_info(char *filename, long pos, guint track, char* title, int len)
{
PlaylistEntry *entry;
entry = g_malloc0(sizeof (PlaylistEntry));
entry->filename = g_strdup(filename);
+ entry->track = track;
if (title)
entry->title = g_strdup(title);
entry->length = len;
@@ -271,9 +272,11 @@
playlist_get_info_scan_active = TRUE;
}
-static void __playlist_ins(char * filename, long pos)
+static void __playlist_ins(char * filename, long pos, guint count)
{
- __playlist_ins_with_info(filename, pos, NULL, -1);
+ guint i;
+ for (i=0; i<count; i++)
+ __playlist_ins_with_info(filename, pos, i, NULL, -1);
}
static gboolean is_playlist_name(char *pathname)
@@ -288,13 +291,16 @@
}
-void playlist_ins(gchar * filename, glong pos)
+guint playlist_ins(gchar * filename, glong pos)
{
gboolean ispl = FALSE;
+ guint count = 0;
ispl = is_playlist_name (filename);
+ if (!ispl)
+ count = input_check_file(filename);
- if (!ispl && !input_check_file(filename))
+ if (!ispl && !count)
{
/*
* Some files (typically produced by some cgi-scripts)
@@ -333,14 +339,16 @@
}
if (ispl)
- playlist_load_ins(filename, pos);
+ return playlist_load_ins(filename, pos);
else
- if (input_check_file(filename))
+ if (count)
{
- __playlist_ins(filename, pos);
+ __playlist_ins(filename, pos, count);
playlist_generate_shuffle_list();
playlistwin_update_list();
- }
+ return count;
+ } else
+ return 0;
}
static guint devino_hash(gconstpointer key)
@@ -361,6 +369,12 @@
return TRUE;
}
+struct __playlist_file_entry
+{
+ char *filename;
+ guint track_count;
+};
+
static GList* playlist_dir_find_files(char *path, gboolean background, GHashTable *htab)
{
DIR *dir;
@@ -399,8 +413,10 @@
node = ilist;
while (node)
{
- char *name = g_strconcat(temp, node->data, NULL);
- list = g_list_prepend(list, name);
+ struct __playlist_file_entry *e = g_malloc (sizeof (*e));
+ e->filename = g_strconcat(temp, node->data, NULL);
+ e->track_count = 1;
+ list = g_list_prepend(list, e);
g_free(node->data);
node = g_list_next(node);
}
@@ -438,10 +454,19 @@
g_free(filename);
list = g_list_concat(list, sub);
}
- else if (input_check_file(filename))
- list = g_list_prepend(list, filename);
else
- g_free(filename);
+ {
+ guint track_count = input_check_file(filename);
+ if (track_count)
+ {
+ struct __playlist_file_entry *e = g_malloc (sizeof (*e));
+ e->filename = filename;
+ e->track_count = track_count;
+ list = g_list_prepend(list, e);
+ }
+ else
+ g_free(filename);
+ }
while (background && gtk_events_pending())
gtk_main_iteration();
@@ -468,11 +493,13 @@
node = list;
while (node)
{
- __playlist_ins(node->data, pos);
- entries++;
+ struct __playlist_file_entry *e = node->data;
+ __playlist_ins(e->filename, pos, e->track_count);
+ entries += e->track_count;
if (pos >= 0)
- pos++;
- g_free(node->data);
+ pos += e->track_count;
+ g_free(e->filename);
+ g_free(e);
node = g_list_next(node);
}
g_list_free(list);
@@ -510,10 +537,7 @@
if (is_playlist_name (string))
i = playlist_load_ins(string, pos);
else
- {
- playlist_ins(string, pos);
- i = 1;
- }
+ i = playlist_ins(string, pos);
}
entries += i;
if (pos >= 0)
@@ -531,6 +555,7 @@
void playlist_play(void)
{
char *filename = NULL;
+ guint track = 0;
if (get_playlist_length() == 0)
return;
@@ -580,13 +605,14 @@
playlist_position = playlist->data;
}
filename = playlist_position->filename;
+ track = playlist_position->track;
}
PL_UNLOCK();
if (!filename)
return;
- input_play(filename);
+ input_play(filename, track);
if (input_get_time() != -1)
{
@@ -1041,7 +1067,10 @@
fprintf(file, "#EXTINF:%d,%s\n",
seconds, entry->title);
}
- fprintf(file, "%s\n", entry->filename);
+ if (entry->track)
+ fprintf(file, "%d %s\n", entry->track, entry->filename);
+ else
+ fprintf(file, "%s\n", entry->filename);
}
node = g_list_next(node);
}
@@ -1056,10 +1085,21 @@
static void playlist_load_ins_file(char *filename, char *playlist_name, long pos, char *title, int len)
{
- char *temp, *path;
+ char *temp, *path, *p;
+ guint track = 0;
filename = g_strstrip(filename);
+ p = filename;
+ while (*p && (*p >= '0' && *p <= '9'))
+ p++;
+
+ if(*p == ' ' && p != filename)
+ {
+ track = strtol(filename, 0, 10);
+ filename = p + 1;
+ }
+
if (cfg.use_backslash_as_dir_delimiter)
{
while ((temp = strchr(filename, '\\')) != NULL)
@@ -1074,16 +1114,16 @@
*temp = '\0';
else
{
- __playlist_ins_with_info(filename, pos, title, len);
+ __playlist_ins_with_info(filename, pos, track, title, len);
return;
}
temp = g_strdup_printf("%s/%s", path, filename);
- __playlist_ins_with_info(temp, pos, title, len);
+ __playlist_ins_with_info(temp, pos, track, title, len);
g_free(temp);
g_free(path);
}
else
- __playlist_ins_with_info(filename, pos, title, len);
+ __playlist_ins_with_info(filename, pos, track, title, len);
}
static void parse_extm3u_info(char *info, char **title, int *length)
@@ -1739,14 +1779,16 @@
*/
char *temp_filename, *temp_title;
int temp_length;
+ guint temp_track;
temp_filename = g_strdup(entry->filename);
+ temp_track = entry->track;
temp_title = NULL;
temp_length = -1;
/* We don't want to lock the playlist while reading info */
PL_UNLOCK();
- input_get_song_info(temp_filename, &temp_title, &temp_length);
+ input_get_song_info(temp_filename, temp_track, &temp_title, &temp_length);
PL_LOCK();
g_free(temp_filename);
Index: xmms/playlist.h
===================================================================
RCS file: /cvs/xmms/xmms/playlist.h,v
retrieving revision 1.19
diff -u -r1.19 playlist.h
--- xmms/playlist.h 8 Jun 2003 21:52:02 -0000 1.19
+++ xmms/playlist.h 17 Nov 2003 01:28:32 -0000
@@ -23,6 +23,7 @@
typedef struct
{
gchar *filename;
+ guint track;
gchar *title;
gint length;
gboolean selected;
@@ -33,7 +34,7 @@
void playlist_delete(gboolean crop);
/* void playlist_add(gchar * filename); */
#define playlist_add(filename) playlist_ins(filename, -1)
-void playlist_ins(gchar * filename, glong pos);
+guint playlist_ins(gchar * filename, glong pos);
/* void playlist_add_dir(gchar * dir); */
#define playlist_add_dir(directory) playlist_ins_dir(directory, -1, TRUE)
guint playlist_ins_dir(char *dir, long pos, gboolean background);
Index: xmms/plugin.h
===================================================================
RCS file: /cvs/xmms/xmms/plugin.h,v
retrieving revision 1.6
diff -u -r1.6 plugin.h
--- xmms/plugin.h 5 Jul 2001 22:35:01 -0000 1.6
+++ xmms/plugin.h 17 Nov 2003 01:28:33 -0000
@@ -92,7 +92,7 @@
int (*is_our_file) (char *filename); /* Return 1 if the plugin can handle the file */
GList *(*scan_dir) (char *dirname); /* Look in Input/cdaudio/cdaudio.c to see how */
/* to use this */
- void (*play_file) (char *filename); /* Guess what... */
+ void (*play_file) (char *filename); /* Play file for single-track per file plugins only */
void (*stop) (void); /* Tricky one */
void (*pause) (short paused); /* Pause or unpause */
void (*seek) (int time); /* Seek to the specified time */
@@ -112,6 +112,12 @@
void (*get_song_info) (char *filename, char **title, int *length); /* Function to grab the title string */
void (*file_info_box) (char *filename); /* Bring up an info window for the filename passed in */
OutputPlugin *output; /* Handle to the current output plugin. Filled in by xmms */
+
+ /* Starting from here the fields are for multi-track plugins */
+
+ int (*count_tracks) (char *filename); /* Return the number of tracks available in a given file */
+ void (*play_track) (char *filename, int track); /* Play a given track from a file */
+ void (*get_track_info) (char *filename, int track, char **title, int *length); /* Function to grab the title string */
}
InputPlugin;
sidplay.diff
(text/plain, 4.1 KB)
--- xmms-sidplay-0.40.orig/sid.cc 2001-06-10 22:27:25.000000000 +0200
+++ xmms-sidplay-0.40/sid.cc 2003-11-17 02:27:08.706675677 +0100
@@ -17,12 +17,12 @@
static void sid_about(void);
static void sid_configure(void);
static int sid_is_our_file(char *filename);
-static void sid_play_file(char *filename);
+static int sid_count_tracks(char *filename);
+static void sid_play_track(char *filename, int track);
static void sid_stop(void);
static void sid_pause(short paused);
-static void sid_seek(int time);
static int sid_get_time(void);
-static void sid_get_song_info(char *filename,char **title,int *length);
+static void sid_get_track_info(char *filename,int track,char **title,int *length);
static void sid_file_info_box(char *filename);
InputPlugin sid_ip = {
@@ -34,10 +34,10 @@
sid_configure,
sid_is_our_file,
NULL,
- sid_play_file,
+ NULL,
sid_stop,
sid_pause,
- sid_seek,
+ NULL,
NULL,
sid_get_time,
NULL,
@@ -47,9 +47,12 @@
NULL,
NULL,
NULL,
- sid_get_song_info,
+ NULL,
sid_file_info_box,
- NULL
+ NULL,
+ sid_count_tracks,
+ sid_play_track,
+ sid_get_track_info
};
emuConfig config = {
@@ -139,14 +142,14 @@
if (info.songs == 0)
return 0;
- sid_ip.set_info(g_strdup_printf("%s (%i/%i)", info.nameString, currentSong, info.songs),
- 100000,
+ sid_ip.set_info(g_strdup_printf("%s (%i/%i)", info.nameString, currentSong+1, info.songs),
+ -1,
config.channels * (config.bitsPerSample / 8) * config.frequency,
config.frequency, config.channels);
if (infolabel) {
gtk_label_set_text(GTK_LABEL(infolabel),
- g_strdup_printf("%i/%i", currentSong, info.songs));
+ g_strdup_printf("%i/%i", currentSong+1, info.songs));
}
if(!sid_ip.output->
@@ -752,8 +755,20 @@
gtk_widget_destroy(dialog);
}
+static int
+sid_count_tracks(char *filename)
+{
+ sidTuneInfo info;
+
+ if(!tune->open(filename))
+ return 0;
+
+ tune->getInfo(info);
+ return info.songs;
+}
+
static void
-sid_play_file(char *filename)
+sid_play_track(char *filename, int track)
{
sidTuneInfo info;
@@ -768,7 +783,7 @@
sid_file_info_box(filename);
tune->getInfo(info);
- change_current_song(info.startSong);
+ change_current_song(track);
}
static void
@@ -787,20 +802,6 @@
sid_ip.output->pause(paused);
}
-static void
-sid_seek(int time)
-{
- sidTuneInfo info;
- tune->getInfo(info);
-
- if (time == 0 && currentSong > 1) {
- change_current_song(currentSong - 1);
- }
- else if (time == 100 && currentSong < info.songs) {
- change_current_song(currentSong + 1);
- }
-}
-
static int
sid_get_time(void)
{
@@ -811,21 +812,15 @@
}
static void
-sid_get_song_info(char *filename,char **title,int *length)
+sid_get_track_info(char *filename,int track,char **title,int *length)
{
sidTune ttune(filename);
sidTuneInfo info;
ttune.getInfo(info);
- *title = g_strdup_printf("%s (%i/%i)", info.nameString, info.startSong, info.songs);
-
- *length = 0;
-}
+ *title = g_strdup_printf("%s (%i/%i)", info.nameString, track+1, info.songs);
-static void
-tune_changed_cb(GtkWidget *widget, gpointer data)
-{
- change_current_song((int)GTK_ADJUSTMENT(widget)->value);
+ *length = -1;
}
static void
@@ -877,17 +872,9 @@
label = gtk_label_new(text);
gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, TRUE, 2);
- infolabel = gtk_label_new(g_strdup_printf("%i/%i", currentSong, info.songs));
+ infolabel = gtk_label_new(g_strdup_printf("%i/%i", currentSong+1, info.songs));
gtk_box_pack_start(GTK_BOX(vbox), infolabel, FALSE, TRUE, 2);
- adjustment = gtk_adjustment_new(currentSong, 1.0, info.songs + 1,
- 1.0, 1.0, 1.0);
- currentSongBar = gtk_hscrollbar_new(GTK_ADJUSTMENT(adjustment));
- gtk_range_set_update_policy(GTK_RANGE(currentSongBar), GTK_UPDATE_CONTINUOUS);
- gtk_signal_connect(GTK_OBJECT(adjustment), "value_changed",
- GTK_SIGNAL_FUNC(tune_changed_cb), NULL);
- gtk_box_pack_start(GTK_BOX(vbox), currentSongBar, TRUE, FALSE, 2);
-
button = gtk_button_new_with_label("Ok");
gtk_box_pack_start(GTK_BOX(GTK_DIALOG(infodialog)->action_area), button,
TRUE, TRUE, 5);