commit 85dc7f90e72265ea93c8a1a4222e64758310a98e Author: phantomjinx <p.g.richard...@phantomjinx.co.uk> Date: Sun Jan 31 22:32:35 2010 +0000
Restoring funtionality to actions - libgtkpod/*file.* Adds back these file format support files to the library - gtkpod_app_iface.* Turn signal names into #defines for uniformity Differentiation between tracks displayed and tracks selected - misc_playlist.c Restores functionality of new playlist actions back to toolbar libgtkpod/Makefile.am | 7 +- libgtkpod/flacfile.c | 1 + libgtkpod/flacfile.h | 1 + libgtkpod/gtkpod_app_iface.c | 40 ++- libgtkpod/gtkpod_app_iface.h | 18 +- libgtkpod/mp3file.c | 1 + libgtkpod/mp3file.h | 1 + libgtkpod/mp4file.c | 1 + libgtkpod/mp4file.h | 1 + libgtkpod/oggfile.c | 1 + libgtkpod/oggfile.h | 1 + libgtkpod/wavfile.c | 1 + libgtkpod/wavfile.h | 1 + plugins/playlist_display/plugin.c | 6 +- plugins/sorttab_display/display_sorttabs.h | 1 + plugins/sorttab_display/plugin.c | 2 +- plugins/sorttab_display/sorttab_display_actions.c | 1 + plugins/track_display/plugin.c | 6 +- src/display_sorttabs.c | 7 +- src/display_tracks.c | 4 +- src/file.c | 408 ++++++++++----------- src/flacfile.c | 9 +- src/misc_playlist.c | 9 +- src/mp3file.h | 3 +- src/mp4file.c | 65 ++-- src/oggfile.c | 15 +- src/wavfile.c | 3 +- 27 files changed, 328 insertions(+), 286 deletions(-) --- diff --git a/libgtkpod/Makefile.am b/libgtkpod/Makefile.am index 5623fb3..376bd4f 100644 --- a/libgtkpod/Makefile.am +++ b/libgtkpod/Makefile.am @@ -22,7 +22,12 @@ libgtkpod_la_SOURCES = gtkpod_app_iface.h gtkpod_app_iface.c \ stock_icons.c stock_icons.h \ gtkpod_app-marshallers.c gtkpod_app-marshallers.h \ tool_menu_action.c tool_menu_action.h \ - gp_spl.c gp_spl.h + gp_spl.c gp_spl.h \ + flacfile.c flacfile.h \ + mp3file.c mp3file.h \ + mp4file.c mp4file.h \ + oggfile.c oggfile.h \ + wavfile.c wavfile.h # Include paths AM_CFLAGS = \ diff --git a/libgtkpod/flacfile.c b/libgtkpod/flacfile.c new file mode 120000 index 0000000..901315b --- /dev/null +++ b/libgtkpod/flacfile.c @@ -0,0 +1 @@ +../src/flacfile.c \ No newline at end of file diff --git a/libgtkpod/flacfile.h b/libgtkpod/flacfile.h new file mode 120000 index 0000000..d5cc4be --- /dev/null +++ b/libgtkpod/flacfile.h @@ -0,0 +1 @@ +../src/flacfile.h \ No newline at end of file diff --git a/libgtkpod/gtkpod_app_iface.c b/libgtkpod/gtkpod_app_iface.c index f708d9c..1689ca2 100644 --- a/libgtkpod/gtkpod_app_iface.c +++ b/libgtkpod/gtkpod_app_iface.c @@ -43,19 +43,22 @@ static void gtkpod_app_base_init(GtkPodAppInterface* klass) { klass->sort_enablement = TRUE; gtkpod_app_signals[ITDB_UPDATED] - = g_signal_new("itdb_updated", G_OBJECT_CLASS_TYPE (klass), G_SIGNAL_RUN_LAST, 0, NULL, NULL, _gtkpod_app_marshal_VOID__POINTER_POINTER, G_TYPE_NONE, 2, G_TYPE_POINTER, G_TYPE_POINTER); + = g_signal_new(SIGNAL_ITDB_UPDATED, G_OBJECT_CLASS_TYPE (klass), G_SIGNAL_RUN_LAST, 0, NULL, NULL, _gtkpod_app_marshal_VOID__POINTER_POINTER, G_TYPE_NONE, 2, G_TYPE_POINTER, G_TYPE_POINTER); gtkpod_app_signals[PLAYLIST_SELECTED] - = g_signal_new("playlist_selected", G_OBJECT_CLASS_TYPE (klass), G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1, G_TYPE_POINTER); + = g_signal_new(SIGNAL_PLAYLIST_SELECTED, G_OBJECT_CLASS_TYPE (klass), G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1, G_TYPE_POINTER); + + gtkpod_app_signals[TRACKS_DISPLAYED] + = g_signal_new(SIGNAL_TRACKS_DISPLAYED, G_OBJECT_CLASS_TYPE (klass), G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1, G_TYPE_POINTER); gtkpod_app_signals[TRACKS_SELECTED] - = g_signal_new("tracks_selected", G_OBJECT_CLASS_TYPE (klass), G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1, G_TYPE_POINTER); + = g_signal_new(SIGNAL_TRACKS_SELECTED, G_OBJECT_CLASS_TYPE (klass), G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1, G_TYPE_POINTER); gtkpod_app_signals[SORT_ENABLEMENT] - = g_signal_new("sort_enablement", G_OBJECT_CLASS_TYPE (klass), G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__BOOLEAN, G_TYPE_NONE, 1, G_TYPE_BOOLEAN); + = g_signal_new(SIGNAL_SORT_ENABLEMENT, G_OBJECT_CLASS_TYPE (klass), G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__BOOLEAN, G_TYPE_NONE, 1, G_TYPE_BOOLEAN); gtkpod_app_signals[PLAYLIST_ADDED] - = g_signal_new("playlist_added", G_OBJECT_CLASS_TYPE (klass), G_SIGNAL_RUN_LAST, 0, NULL, NULL, _gtkpod_app_marshal_VOID__POINTER_INT, G_TYPE_NONE, 2, G_TYPE_POINTER, G_TYPE_INT); + = g_signal_new(SIGNAL_PLAYLIST_ADDED, G_OBJECT_CLASS_TYPE (klass), G_SIGNAL_RUN_LAST, 0, NULL, NULL, _gtkpod_app_marshal_VOID__POINTER_INT, G_TYPE_NONE, 2, G_TYPE_POINTER, G_TYPE_INT); initialized = TRUE; } @@ -185,15 +188,15 @@ void gtkpod_set_current_playlist(Playlist* playlist) { GTKPOD_APP_GET_INTERFACE (gtkpod_app)->current_playlist = playlist; if (playlist) {// if playlist not null then set its itdb as current gtkpod_set_current_itdb(playlist->itdb); - gtkpod_set_current_tracks(playlist->members); + gtkpod_set_displayed_tracks(playlist->members); } g_signal_emit(gtkpod_app, gtkpod_app_signals[PLAYLIST_SELECTED], 0, playlist); } -GList *gtkpod_get_current_tracks() { +GList *gtkpod_get_displayed_tracks() { g_return_val_if_fail (GTKPOD_IS_APP(gtkpod_app), NULL); - GList *current_tracks = GTKPOD_APP_GET_INTERFACE (gtkpod_app)->current_tracks; + GList *current_tracks = GTKPOD_APP_GET_INTERFACE (gtkpod_app)->displayed_tracks; if (current_tracks && g_list_length(current_tracks) > 0) { return g_list_copy(current_tracks); } @@ -207,9 +210,26 @@ GList *gtkpod_get_current_tracks() { return NULL; } -void gtkpod_set_current_tracks(GList *tracks) { +void gtkpod_set_displayed_tracks(GList *tracks) { + g_return_if_fail (GTKPOD_IS_APP(gtkpod_app)); + GTKPOD_APP_GET_INTERFACE (gtkpod_app)->displayed_tracks = tracks; + + g_signal_emit(gtkpod_app, gtkpod_app_signals[TRACKS_DISPLAYED], 0, tracks); +} + +GList *gtkpod_get_selected_tracks() { + g_return_val_if_fail (GTKPOD_IS_APP(gtkpod_app), NULL); + GList *selected_tracks = GTKPOD_APP_GET_INTERFACE (gtkpod_app)->selected_tracks; + if (selected_tracks && g_list_length(selected_tracks) > 0) { + return g_list_copy(selected_tracks); + } + + return gtkpod_get_displayed_tracks(); +} + +void gtkpod_set_selected_tracks(GList *tracks) { g_return_if_fail (GTKPOD_IS_APP(gtkpod_app)); - GTKPOD_APP_GET_INTERFACE (gtkpod_app)->current_tracks = tracks; + GTKPOD_APP_GET_INTERFACE (gtkpod_app)->selected_tracks = tracks; g_signal_emit(gtkpod_app, gtkpod_app_signals[TRACKS_SELECTED], 0, tracks); } diff --git a/libgtkpod/gtkpod_app_iface.h b/libgtkpod/gtkpod_app_iface.h index f18512b..7a352d6 100644 --- a/libgtkpod/gtkpod_app_iface.h +++ b/libgtkpod/gtkpod_app_iface.h @@ -42,6 +42,13 @@ #define GTKPOD_IS_APP(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTKPOD_APP_TYPE)) #define GTKPOD_APP_GET_INTERFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE ((inst), GTKPOD_APP_TYPE, GtkPodAppInterface)) +#define SIGNAL_TRACKS_DISPLAYED "signal_tracks_displayed" +#define SIGNAL_TRACKS_SELECTED "signal_tracks_selected" +#define SIGNAL_PLAYLIST_SELECTED "signal_playlist_selected" +#define SIGNAL_PLAYLIST_ADDED "signal_playlist_added" +#define SIGNAL_ITDB_UPDATED "signal_itdb_updated" +#define SIGNAL_SORT_ENABLEMENT "signal_sort_enablement" + typedef void (*ConfHandler)(gpointer user_data1, gpointer user_data2); /* states for gtkpod_confirmation options */ @@ -66,6 +73,7 @@ void CONF_NULL_HANDLER (gpointer d1, gpointer d2); enum { + TRACKS_DISPLAYED, TRACKS_SELECTED, PLAYLIST_SELECTED, PLAYLIST_ADDED, @@ -84,7 +92,9 @@ struct _GtkPodAppInterface { /* pointer to the currently selected playlist */ Playlist *current_playlist; /* pointer to the currently displayed set of tracks */ - GList *current_tracks; + GList *displayed_tracks; + /* pointer to the currently selected set of tracks */ + GList *selected_tracks; /* flag indicating whether sorting is enabled/disabled */ gboolean sort_enablement; /* xml filename */ @@ -122,8 +132,10 @@ iTunesDB* gtkpod_get_current_itdb(); void gtkpod_set_current_itdb(iTunesDB* itdb); Playlist* gtkpod_get_current_playlist(); void gtkpod_set_current_playlist(Playlist* playlist); -GList *gtkpod_get_current_tracks(); -void gtkpod_set_current_tracks(GList *tracks); +GList *gtkpod_get_displayed_tracks(); +void gtkpod_set_displayed_tracks(GList *tracks); +GList *gtkpod_get_selected_tracks(); +void gtkpod_set_selected_tracks(GList *tracks); void gtkpod_set_sort_enablement(gboolean enable); gboolean gtkpod_get_sort_enablement(); void gtkpod_playlist_added(iTunesDB *itdb, Playlist *playlist, gint32 pos); diff --git a/libgtkpod/mp3file.c b/libgtkpod/mp3file.c new file mode 120000 index 0000000..9be8c60 --- /dev/null +++ b/libgtkpod/mp3file.c @@ -0,0 +1 @@ +../src/mp3file.c \ No newline at end of file diff --git a/libgtkpod/mp3file.h b/libgtkpod/mp3file.h new file mode 120000 index 0000000..e483310 --- /dev/null +++ b/libgtkpod/mp3file.h @@ -0,0 +1 @@ +../src/mp3file.h \ No newline at end of file diff --git a/libgtkpod/mp4file.c b/libgtkpod/mp4file.c new file mode 120000 index 0000000..67811ee --- /dev/null +++ b/libgtkpod/mp4file.c @@ -0,0 +1 @@ +../src/mp4file.c \ No newline at end of file diff --git a/libgtkpod/mp4file.h b/libgtkpod/mp4file.h new file mode 120000 index 0000000..656eea8 --- /dev/null +++ b/libgtkpod/mp4file.h @@ -0,0 +1 @@ +../src/mp4file.h \ No newline at end of file diff --git a/libgtkpod/oggfile.c b/libgtkpod/oggfile.c new file mode 120000 index 0000000..d893f09 --- /dev/null +++ b/libgtkpod/oggfile.c @@ -0,0 +1 @@ +../src/oggfile.c \ No newline at end of file diff --git a/libgtkpod/oggfile.h b/libgtkpod/oggfile.h new file mode 120000 index 0000000..ec6b6dd --- /dev/null +++ b/libgtkpod/oggfile.h @@ -0,0 +1 @@ +../src/oggfile.h \ No newline at end of file diff --git a/libgtkpod/wavfile.c b/libgtkpod/wavfile.c new file mode 120000 index 0000000..7aeaccf --- /dev/null +++ b/libgtkpod/wavfile.c @@ -0,0 +1 @@ +../src/wavfile.c \ No newline at end of file diff --git a/libgtkpod/wavfile.h b/libgtkpod/wavfile.h new file mode 120000 index 0000000..d41914b --- /dev/null +++ b/libgtkpod/wavfile.h @@ -0,0 +1 @@ +../src/wavfile.h \ No newline at end of file diff --git a/plugins/playlist_display/plugin.c b/plugins/playlist_display/plugin.c index f4edc08..58be619 100644 --- a/plugins/playlist_display/plugin.c +++ b/plugins/playlist_display/plugin.c @@ -264,9 +264,9 @@ static gboolean activate_plugin(AnjutaPlugin *plugin) { playlist_display_plugin->playlist_view = pm_create_treeview(); - g_signal_connect (gtkpod_app, "playlist_selected", G_CALLBACK (playlist_display_select_playlist_cb), NULL); - g_signal_connect (gtkpod_app, "itdb_updated", G_CALLBACK (playlist_display_update_itdb_cb), NULL); - g_signal_connect (gtkpod_app, "playlist_added", G_CALLBACK (playlist_display_playlist_added_cb), NULL); + g_signal_connect (gtkpod_app, SIGNAL_PLAYLIST_SELECTED, G_CALLBACK (playlist_display_select_playlist_cb), NULL); + g_signal_connect (gtkpod_app, SIGNAL_ITDB_UPDATED, G_CALLBACK (playlist_display_update_itdb_cb), NULL); + g_signal_connect (gtkpod_app, SIGNAL_PLAYLIST_ADDED, G_CALLBACK (playlist_display_playlist_added_cb), NULL); gtk_container_add(GTK_CONTAINER (playlist_display_plugin->pl_window), GTK_WIDGET (playlist_display_plugin->playlist_view)); gtk_widget_show_all(playlist_display_plugin->pl_window); diff --git a/plugins/sorttab_display/display_sorttabs.h b/plugins/sorttab_display/display_sorttabs.h index 0071ce8..a109540 100644 --- a/plugins/sorttab_display/display_sorttabs.h +++ b/plugins/sorttab_display/display_sorttabs.h @@ -130,6 +130,7 @@ void st_track_changed(Track *track, gboolean removed, guint32 inst); void st_redisplay(guint32 inst); GList *st_get_selected_members(guint32 inst); void st_update_paned_position(); +void st_show_visible(void); void cal_open_calendar(gint inst, T_item item); diff --git a/plugins/sorttab_display/plugin.c b/plugins/sorttab_display/plugin.c index 69e8916..f7d3ab6 100644 --- a/plugins/sorttab_display/plugin.c +++ b/plugins/sorttab_display/plugin.c @@ -83,7 +83,7 @@ static gboolean activate_sorttab_display_plugin(AnjutaPlugin *plugin) { st_create_tabs(GTK_PANED(sorttab_display_plugin->st_paned)); gtk_widget_show(sorttab_display_plugin->st_paned); - g_signal_connect (gtkpod_app, "playlist_selected", G_CALLBACK (sorttab_display_select_playlist_cb), NULL); + g_signal_connect (gtkpod_app, SIGNAL_PLAYLIST_SELECTED, G_CALLBACK (sorttab_display_select_playlist_cb), NULL); anjuta_shell_add_widget(plugin->shell, sorttab_display_plugin->st_paned, "SorttabDisplayPlugin", "Track Filter", NULL, ANJUTA_SHELL_PLACEMENT_CENTER, NULL); return TRUE; /* FALSE if activation failed */ diff --git a/plugins/sorttab_display/sorttab_display_actions.c b/plugins/sorttab_display/sorttab_display_actions.c index 8d3cfe1..76bb06e 100644 --- a/plugins/sorttab_display/sorttab_display_actions.c +++ b/plugins/sorttab_display/sorttab_display_actions.c @@ -31,6 +31,7 @@ # include <config.h> #endif +#include "libgtkpod/prefs.h" #include "sorttab_display_actions.h" #include "display_sorttabs.h" diff --git a/plugins/track_display/plugin.c b/plugins/track_display/plugin.c index 6813f5b..703fc49 100644 --- a/plugins/track_display/plugin.c +++ b/plugins/track_display/plugin.c @@ -66,9 +66,9 @@ static gboolean activate_track_display_plugin(AnjutaPlugin *plugin) { gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW (track_display_plugin->track_window), GTK_SHADOW_IN); tm_create_track_display (track_display_plugin->track_window); - g_signal_connect (gtkpod_app, "tracks_selected", G_CALLBACK (track_display_set_tracks_cb), NULL); - g_signal_connect (gtkpod_app, "playlist_selected", G_CALLBACK (track_display_set_playlist_cb), NULL); - g_signal_connect (gtkpod_app, "sort_enablement", G_CALLBACK (track_display_set_sort_enablement), NULL); + g_signal_connect (gtkpod_app, SIGNAL_TRACKS_DISPLAYED, G_CALLBACK (track_display_set_tracks_cb), NULL); + g_signal_connect (gtkpod_app, SIGNAL_PLAYLIST_SELECTED, G_CALLBACK (track_display_set_playlist_cb), NULL); + g_signal_connect (gtkpod_app, SIGNAL_SORT_ENABLEMENT, G_CALLBACK (track_display_set_sort_enablement), NULL); gtk_widget_show_all(track_display_plugin->track_window); anjuta_shell_add_widget(plugin->shell, track_display_plugin->track_window, "TrackDisplayPlugin", "Playlist Tracks", NULL, ANJUTA_SHELL_PLACEMENT_TOP, NULL); diff --git a/src/display_sorttabs.c b/src/display_sorttabs.c index 1dc5cad..303aca4 100644 --- a/src/display_sorttabs.c +++ b/src/display_sorttabs.c @@ -613,7 +613,7 @@ static void sp_go_cb(gpointer user_data1, gpointer user_data2) { st_add_track(track, FALSE, TRUE, inst + 1); } } - gtkpod_set_current_tracks(st->sp_members); + gtkpod_set_displayed_tracks(st->sp_members); st_enable_disable_view_sort(inst + 1, TRUE); st_add_track(NULL, TRUE, st->final, inst + 1); } @@ -1197,7 +1197,6 @@ static TabEntry *st_get_entry_by_name(const gchar *name, guint32 inst) { if (name == NULL) return NULL; /* check if we need to return the master entry */ - g_warning("entry name: %p %s", name, name); if ((strlen(name) == 1) && (*name == -1)) { entry = (TabEntry *) g_list_nth_data(entries, 0); } @@ -1614,7 +1613,7 @@ void st_remove_track(Track *track, guint32 inst) { select "All" in accordance to the prefs settings. */ void st_init(ST_CAT_item new_category, guint32 inst) { if (inst == prefs_get_int("sort_tab_num")) { - gtkpod_set_current_tracks(NULL); + gtkpod_set_displayed_tracks(NULL); gtkpod_tracks_statusbar_update(); return; } @@ -1939,7 +1938,7 @@ static gboolean st_selection_changed_cb(gpointer data) { st_add_track(track, FALSE, TRUE, inst + 1); } /* Advertise that a new set of tracks has been selected */ - gtkpod_set_current_tracks(new_entry->members); + gtkpod_set_displayed_tracks(new_entry->members); st_enable_disable_view_sort(inst + 1, TRUE); st_add_track(NULL, TRUE, st->final, inst + 1); diff --git a/src/display_tracks.c b/src/display_tracks.c index 4e09f7e..f445010 100644 --- a/src/display_tracks.c +++ b/src/display_tracks.c @@ -1758,7 +1758,7 @@ void tm_adopt_order_in_sorttab(void) { the last sort tab or from the selected playlist if no sort tabs are being used */ tm_remove_all_tracks(); - tracks = gtkpod_get_current_tracks(); + tracks = gtkpod_get_displayed_tracks(); for (gl = tracks; gl; gl = gl->next) tm_add_track_to_track_model((Track *) gl->data, NULL); } @@ -2268,6 +2268,8 @@ static gboolean tm_selection_changed_cb(gpointer data) { // coverart_select_cover(track); // } + gtkpod_set_selected_tracks(tm_get_selected_tracks()); + return FALSE; } diff --git a/src/file.c b/src/file.c index 86208f2..b03107a 100644 --- a/src/file.c +++ b/src/file.c @@ -50,6 +50,11 @@ #include "misc_track.h" #include "prefs.h" #include "misc_conversion.h" +#include "flacfile.h" +#include "mp3file.h" +#include "mp4file.h" +#include "oggfile.h" +#include "wavfile.h" /* The uppercase version of these extensions is tried as well. */ static const gchar *imageext[] = { ".jpg", ".jpeg", ".png", ".pbm", ".pgm", ".ppm", ".tif", ".tiff", ".gif", NULL}; @@ -1166,215 +1171,199 @@ static void add_coverart(Track *tr) { * exists. time_added is not modified if already set. */ /* Returns NULL on error, a pointer to the Track otherwise */ static Track *get_track_info_from_file(gchar *name, Track *orig_track) { - g_warning("TODO Should query a plugin for the type of track and info"); Track *track = NULL; - // Track *nti = NULL; - // FileType filetype; - // gint len; - // gchar *name_utf8 = NULL; - // - // g_return_val_if_fail (name, NULL); - // - // if (g_file_test (name, G_FILE_TEST_IS_DIR)) return NULL; - // - // name_utf8 = charset_to_utf8 (name); - // - // if (!g_file_test (name, G_FILE_TEST_EXISTS)) - // { - // gtkpod_warning (_("The following track could not be processed (file does not exist): '%s'\n"), name_utf8); - // g_free (name_utf8); - // return NULL; - // } - // - // /* reset the auto detection charset (see explanation in charset.c) */ - // charset_reset_auto (); - // - // /* check for filetype */ - // len = strlen (name); - // if (len < 4) return NULL; - // - // filetype = determine_file_type(name); - // switch (filetype) - // { - // case FILE_TYPE_MP3: - // nti = mp3_get_file_info (name); - // /* Set mediatype to audio */ - // if (nti) nti->mediatype = ITDB_MEDIATYPE_AUDIO; - // break; - // case FILE_TYPE_M4A: - // case FILE_TYPE_M4P: - // nti = mp4_get_file_info (name); - // /* Set mediatype to audio */ - // if (nti) - // { - // nti->mediatype = ITDB_MEDIATYPE_AUDIO; - // } - // break; - // case FILE_TYPE_M4B: - // nti = mp4_get_file_info (name); - // /* Set mediatype to audiobook */ - // if (nti) - // { - // nti->mediatype = ITDB_MEDIATYPE_AUDIOBOOK; - // } - // break; - // case FILE_TYPE_WAV: - // nti = wav_get_file_info (name); - // /* Set mediatype to audio */ - // if (nti) - // { - // nti->mediatype = ITDB_MEDIATYPE_AUDIO; - // } - // break; - // case FILE_TYPE_OGG: - // nti = ogg_get_file_info (name); - // /* Set mediatype to audio */ - // if (nti) - // { - // nti->mediatype = ITDB_MEDIATYPE_AUDIO; - // } - // break; - // case FILE_TYPE_FLAC: - // nti = flac_get_file_info (name); - // /* Set mediatype to audio */ - // if (nti) - // { - // nti->mediatype = ITDB_MEDIATYPE_AUDIO; - // } - // break; - // case FILE_TYPE_M4V: - // case FILE_TYPE_MP4: - // /* I don't know if .m4v and .mp4 can simply be handled like - // this. Let's see if someone complains. */ - // nti = mp4_get_file_info (name); - // if (!nti) video_get_file_info (name); - // /* Set mediatype to video */ - // if (nti) - // { - // nti->mediatype = ITDB_MEDIATYPE_MOVIE; - // nti->movie_flag = 0x01; - // } - // break; - // case FILE_TYPE_MOV: - // case FILE_TYPE_MPG: - // /* for now treat all the same */ - // nti = video_get_file_info (name); - // /* Set mediatype to video */ - // if (nti) - // { - // nti->mediatype = ITDB_MEDIATYPE_MOVIE; - // nti->movie_flag = 0x01; - // } - // break; - // case FILE_TYPE_UNKNOWN: - // gtkpod_warning (_("The following track could not be processed (filetype unknown): '%s'\n"), name_utf8); - // g_free (name_utf8); - // return NULL; - // case FILE_TYPE_IMAGE: - // case FILE_TYPE_DIRECTORY: - // case FILE_TYPE_M3U: - // case FILE_TYPE_PLS: - // break; - // } - // - // if (nti) - // { - // ExtraTrackData *enti=nti->userdata; - // struct stat filestat; - // - // g_return_val_if_fail (enti, NULL); - // - // if (enti->charset == NULL) - // { /* Fill in currently used charset. Try if auto_charset is - // * set first. If not, use the currently set charset. */ - // enti->charset = charset_get_auto (); - // if (enti->charset == NULL) - // update_charset_info (nti); - // } - // /* set path file information */ - // enti->pc_path_utf8 = charset_to_utf8 (name); - // enti->pc_path_locale = g_strdup (name); - // enti->lyrics=NULL; - // /* set length of file */ - // stat (name, &filestat); - // nti->size = filestat.st_size; /* get the filesize in bytes */ - // enti->mtime = filestat.st_mtime; /* get the modification date */ - // if (nti->bitrate == 0) - // { /* estimate bitrate */ - // if (nti->tracklen) - // nti->bitrate = nti->size * 8 / nti->tracklen; - // } - // /* Set unset strings (album...) from filename */ - // set_unset_entries_from_filename (nti); - // - // /* Set coverart */ - // if (prefs_get_int("coverart_file")) - // { - // /* APIC data takes precedence */ - // if (! itdb_track_has_thumbnails (nti)) - // add_coverart (nti); - // } - // - // /* Set modification date to the files modified date */ - // nti->time_modified = enti->mtime; - // /* Set added date to *now* (unless orig_track is present) */ - // if (orig_track) - // { - // nti->time_added = orig_track->time_added; - // } - // else - // { - // nti->time_added = time (NULL); - // } - // - // /* Make sure all strings are initialized -- that way we don't - // have to worry about it when we are handling the - // strings. Also, validate_entries() will fill in the utf16 - // strings if that hasn't already been done. */ - // /* exception: sha1_hash, charset and hostname: these may be - // * NULL. */ - // - // gp_track_validate_entries (nti); - // - // if (orig_track) - // { /* we need to copy all information over to the original - // * track */ - // ExtraTrackData *eorigtr=orig_track->userdata; - // - // g_return_val_if_fail (eorigtr, NULL); - // - // eorigtr->tchanged = copy_new_info (nti, orig_track); - // - // track = orig_track; - // itdb_track_free (nti); - // nti = NULL; - // } - // else - // { /* just use nti */ - // track = nti; - // nti = NULL; - // } - // - // update_mserv_data_from_file (name, track); - // } - // else - // { - // switch (filetype) - // { - // case FILE_TYPE_IMAGE: - // case FILE_TYPE_M3U: - // case FILE_TYPE_PLS: - // break; - // default: - // gtkpod_warning (_("The following track could not be processed (filetype is known but analysis failed): '%s'\n"), name_utf8); - // break; - // } - // } - // - // while (widgets_blocked && gtk_events_pending ()) - // gtk_main_iteration (); - // - // g_free (name_utf8); + Track *nti = NULL; + FileType filetype; + gint len; + gchar *name_utf8 = NULL; + + g_return_val_if_fail (name, NULL); + + if (g_file_test(name, G_FILE_TEST_IS_DIR)) + return NULL; + + name_utf8 = charset_to_utf8(name); + + if (!g_file_test(name, G_FILE_TEST_EXISTS)) { + gtkpod_warning(_("The following track could not be processed (file does not exist): '%s'\n"), name_utf8); + g_free(name_utf8); + return NULL; + } + + /* reset the auto detection charset (see explanation in charset.c) */ + charset_reset_auto(); + + /* check for filetype */ + len = strlen(name); + if (len < 4) + return NULL; + + filetype = determine_file_type(name); + switch (filetype) { + case FILE_TYPE_MP3: + nti = mp3_get_file_info(name); + /* Set mediatype to audio */ + if (nti) + nti->mediatype = ITDB_MEDIATYPE_AUDIO; + break; + case FILE_TYPE_M4A: + case FILE_TYPE_M4P: + nti = mp4_get_file_info(name); + /* Set mediatype to audio */ + if (nti) { + nti->mediatype = ITDB_MEDIATYPE_AUDIO; + } + break; + case FILE_TYPE_M4B: + nti = mp4_get_file_info(name); + /* Set mediatype to audiobook */ + if (nti) { + nti->mediatype = ITDB_MEDIATYPE_AUDIOBOOK; + } + break; + case FILE_TYPE_WAV: + nti = wav_get_file_info(name); + /* Set mediatype to audio */ + if (nti) { + nti->mediatype = ITDB_MEDIATYPE_AUDIO; + } + break; + case FILE_TYPE_OGG: + nti = ogg_get_file_info(name); + /* Set mediatype to audio */ + if (nti) { + nti->mediatype = ITDB_MEDIATYPE_AUDIO; + } + break; + case FILE_TYPE_FLAC: + nti = flac_get_file_info(name); + /* Set mediatype to audio */ + if (nti) { + nti->mediatype = ITDB_MEDIATYPE_AUDIO; + } + break; + case FILE_TYPE_M4V: + case FILE_TYPE_MP4: + /* I don't know if .m4v and .mp4 can simply be handled like + this. Let's see if someone complains. */ + nti = mp4_get_file_info(name); + if (!nti) + video_get_file_info(name); + /* Set mediatype to video */ + if (nti) { + nti->mediatype = ITDB_MEDIATYPE_MOVIE; + nti->movie_flag = 0x01; + } + break; + case FILE_TYPE_MOV: + case FILE_TYPE_MPG: + /* for now treat all the same */ + nti = video_get_file_info(name); + /* Set mediatype to video */ + if (nti) { + nti->mediatype = ITDB_MEDIATYPE_MOVIE; + nti->movie_flag = 0x01; + } + break; + case FILE_TYPE_UNKNOWN: + gtkpod_warning(_("The following track could not be processed (filetype unknown): '%s'\n"), name_utf8); + g_free(name_utf8); + return NULL; + case FILE_TYPE_IMAGE: + case FILE_TYPE_DIRECTORY: + case FILE_TYPE_M3U: + case FILE_TYPE_PLS: + break; + } + + if (nti) { + ExtraTrackData *enti = nti->userdata; + struct stat filestat; + + g_return_val_if_fail (enti, NULL); + + if (enti->charset == NULL) { /* Fill in currently used charset. Try if auto_charset is + * set first. If not, use the currently set charset. */ + enti->charset = charset_get_auto(); + if (enti->charset == NULL) + update_charset_info(nti); + } + /* set path file information */ + enti->pc_path_utf8 = charset_to_utf8(name); + enti->pc_path_locale = g_strdup(name); + enti->lyrics = NULL; + /* set length of file */ + stat(name, &filestat); + nti->size = filestat.st_size; /* get the filesize in bytes */ + enti->mtime = filestat.st_mtime; /* get the modification date */ + if (nti->bitrate == 0) { /* estimate bitrate */ + if (nti->tracklen) + nti->bitrate = nti->size * 8 / nti->tracklen; + } + /* Set unset strings (album...) from filename */ + set_unset_entries_from_filename(nti); + + /* Set coverart */ + if (prefs_get_int("coverart_file")) { + /* APIC data takes precedence */ + if (!itdb_track_has_thumbnails(nti)) + add_coverart(nti); + } + + /* Set modification date to the files modified date */ + nti->time_modified = enti->mtime; + /* Set added date to *now* (unless orig_track is present) */ + if (orig_track) { + nti->time_added = orig_track->time_added; + } + else { + nti->time_added = time(NULL); + } + + /* Make sure all strings are initialized -- that way we don't + have to worry about it when we are handling the + strings. Also, validate_entries() will fill in the utf16 + strings if that hasn't already been done. */ + /* exception: sha1_hash, charset and hostname: these may be + * NULL. */ + + gp_track_validate_entries(nti); + + if (orig_track) { /* we need to copy all information over to the original + * track */ + ExtraTrackData *eorigtr = orig_track->userdata; + + g_return_val_if_fail (eorigtr, NULL); + + eorigtr->tchanged = copy_new_info(nti, orig_track); + + track = orig_track; + itdb_track_free(nti); + nti = NULL; + } + else { /* just use nti */ + track = nti; + nti = NULL; + } + + update_mserv_data_from_file(name, track); + } + else { + switch (filetype) { + case FILE_TYPE_IMAGE: + case FILE_TYPE_M3U: + case FILE_TYPE_PLS: + break; + default: + gtkpod_warning(_("The following track could not be processed (filetype is known but analysis failed): '%s'\n"), name_utf8); + break; + } + } + + while (widgets_blocked && gtk_events_pending()) + gtk_main_iteration(); + + g_free(name_utf8); return track; } @@ -1884,8 +1873,7 @@ gboolean add_track_by_filename(iTunesDB *itdb, gchar *fname, Playlist *plitem, g basename = g_path_get_basename(fname); if (basename) { gchar *bn_utf8 = charset_to_utf8(basename); - g_warning("TODO file:add_track_from_file - status needed\n"); - // gtkpod_statusbar_message (_("Processing '%s'..."), bn_utf8); + gtkpod_statusbar_message (_("Processing '%s'..."), bn_utf8); while (widgets_blocked && gtk_events_pending()) gtk_main_iteration(); g_free(bn_utf8); diff --git a/src/flacfile.c b/src/flacfile.c index 5b7c215..3407536 100644 --- a/src/flacfile.c +++ b/src/flacfile.c @@ -35,6 +35,7 @@ #include "misc.h" #include "flacfile.h" #include "mp3file.h" +#include "gtkpod_app_iface.h" /* Info on how to implement new file formats: see mp3file.c for more info */ @@ -69,9 +70,9 @@ Track *flac_get_file_info (gchar *flacFileName) track = gp_track_new (); - if (prefs_get_int("readtags")) + if (prefs_get_int("readtags")) { - if (!FLAC__metadata_get_tags (flacFileName, &tags)) + if (!FLAC__metadata_get_tags (flacFileName, &tags)) { gchar *filename = NULL; filename = charset_to_utf8 (flacFileName); @@ -88,7 +89,7 @@ Track *flac_get_file_info (gchar *flacFileName) flac_metadata_ok = TRUE; } - for (i = 0 ; i < tags->data.vorbis_comment.num_comments ; i++) + for (i = 0 ; i < tags->data.vorbis_comment.num_comments ; i++) { gchar *tag = (gchar*)tags->data.vorbis_comment.comments[i].entry; @@ -153,7 +154,7 @@ Track *flac_get_file_info (gchar *flacFileName) if (g_ascii_strncasecmp("CDS=", tag, 4) == 0) { track->cds = atoi (tag + 4); } - /* I'm not sure if "BPM=" is correct */ + /* I'm not sure if "BPM=" is correct */ if (g_ascii_strncasecmp("BPM=", tag, 4) == 0) { track->BPM = atoi (tag + 4); } diff --git a/src/misc_playlist.c b/src/misc_playlist.c index ce49c57..9223c96 100644 --- a/src/misc_playlist.c +++ b/src/misc_playlist.c @@ -40,6 +40,7 @@ #include "prefs.h" #include "file_convert.h" #include "gtkpod_app_iface.h" +#include "gp_spl.h" #define DEBUG_MISC 0 @@ -194,7 +195,7 @@ void generate_category_playlists(iTunesDB *itdb, T_item cat) { /* Generate a new playlist containing all the tracks currently displayed */ Playlist *generate_displayed_playlist(void) { - GList *tracks = gtkpod_get_current_tracks(); + GList *tracks = gtkpod_get_displayed_tracks(); Playlist *result = NULL; if (tracks) { @@ -207,9 +208,7 @@ Playlist *generate_displayed_playlist(void) { /* Generate a new playlist containing all the tracks currently selected */ Playlist *generate_selected_playlist(void) { - GList *tracks = NULL; - g_warning("TODO generate_selected_playlist - need to get selected tracks\n"); - // tm_get_selected_tracks (); + GList *tracks = gtkpod_get_selected_tracks(); Playlist *result = NULL; if (tracks) { @@ -227,7 +226,7 @@ Playlist *generate_random_playlist(iTunesDB *itdb) { Playlist *new_pl = NULL; gchar *pl_name, *pl_name1; GList *rtracks = NULL; - GList *tracks = gtkpod_get_current_tracks(); + GList *tracks = gtkpod_get_displayed_tracks(); gint tracks_max = prefs_get_int("misc_track_nr"); gint tracks_nr = 0; diff --git a/src/mp3file.h b/src/mp3file.h index 5c3fe4a..d499dea 100644 --- a/src/mp3file.h +++ b/src/mp3file.h @@ -2,7 +2,7 @@ | | Copyright (C) 2002-2005 Jorg Schuler <jcsjcs at users sourceforge net> | Part of the gtkpod project. -| +| | URL: http://www.gtkpod.org/ | URL: http://gtkpod.sourceforge.net/ | @@ -31,6 +31,7 @@ #define MP3FILEH_INCLUDED 1 #include "itdb.h" +#include <glib/gi18n-lib.h> gboolean mp3_write_file_info (const gchar *filename, Track *track); Track *mp3_get_file_info (const gchar *name); diff --git a/src/mp4file.c b/src/mp4file.c index b2c30af..08fbbc3 100644 --- a/src/mp4file.c +++ b/src/mp4file.c @@ -2,7 +2,7 @@ | | Copyright (C) 2002-2005 Jorg Schuler <jcsjcs at users sourceforge net> | Part of the gtkpod project. -| +| | URL: http://www.gtkpod.org/ | URL: http://gtkpod.sourceforge.net/ | @@ -31,6 +31,7 @@ # include <config.h> #endif +#include <glib/gi18n-lib.h> #include "charset.h" #include "itdb.h" #include "misc.h" @@ -111,7 +112,7 @@ Finally, you may want to provide a function that can - read and set the soundcheck field: + read and set the soundcheck field: gboolean xxx_read_soundcheck (gchar *filename, Track *track) @@ -161,76 +162,76 @@ typedef u_int64_t MP4Duration; #define MP4_MSECS_TIME_SCALE MP4_MILLISECONDS_TIME_SCALE typedef MP4FileHandle (*MP4Read_t)( - const char* fileName, + const char* fileName, u_int32_t verbosity DEFAULT(0)); typedef u_int32_t (*MP4GetNumberOfTracks_t)( - MP4FileHandle hFile, + MP4FileHandle hFile, const char* type DEFAULT(NULL), u_int8_t subType DEFAULT(0)); typedef MP4TrackId (*MP4FindTrackId_t)( - MP4FileHandle hFile, - u_int16_t index, + MP4FileHandle hFile, + u_int16_t index, const char* type DEFAULT(NULL), u_int8_t subType DEFAULT(0)); typedef const char* (*MP4GetTrackType_t)( - MP4FileHandle hFile, + MP4FileHandle hFile, MP4TrackId trackId); - + typedef void (*MP4Close_t)( MP4FileHandle hFile); typedef bool (*MP4ReadSample_t)( /* input parameters */ MP4FileHandle hFile, - MP4TrackId trackId, + MP4TrackId trackId, MP4SampleId sampleId, /* input/output parameters */ - u_int8_t** ppBytes, - u_int32_t* pNumBytes, + u_int8_t** ppBytes, + u_int32_t* pNumBytes, /* output parameters */ - MP4Timestamp* pStartTime DEFAULT(NULL), + MP4Timestamp* pStartTime DEFAULT(NULL), MP4Duration* pDuration DEFAULT(NULL), - MP4Duration* pRenderingOffset DEFAULT(NULL), + MP4Duration* pRenderingOffset DEFAULT(NULL), bool* pIsSyncSample DEFAULT(NULL)); typedef u_int64_t (*MP4ConvertFromTrackTimestamp_t)( MP4FileHandle hFile, - MP4TrackId trackId, + MP4TrackId trackId, MP4Timestamp timeStamp, u_int32_t timeScale); typedef u_int64_t (*MP4ConvertFromTrackDuration_t)( MP4FileHandle hFile, - MP4TrackId trackId, + MP4TrackId trackId, MP4Duration duration, u_int32_t timeScale); typedef u_int32_t (*MP4GetTrackBitRate_t)( - MP4FileHandle hFile, + MP4FileHandle hFile, MP4TrackId trackId); typedef u_int32_t (*MP4GetTrackTimeScale_t)( - MP4FileHandle hFile, + MP4FileHandle hFile, MP4TrackId trackId); typedef u_int32_t (*MP4GetTrackMaxSampleSize_t)( MP4FileHandle hFile, - MP4TrackId trackId); + MP4TrackId trackId); typedef MP4SampleId (*MP4GetTrackNumberOfSamples_t)( - MP4FileHandle hFile, + MP4FileHandle hFile, MP4TrackId trackId); typedef MP4Timestamp (*MP4GetSampleTime_t)( MP4FileHandle hFile, - MP4TrackId trackId, + MP4TrackId trackId, MP4SampleId sampleId); typedef MP4Duration (*MP4GetTrackDuration_t)( - MP4FileHandle hFile, + MP4FileHandle hFile, MP4TrackId trackId); typedef bool (*MP4GetMetadataName_t)(MP4FileHandle hFile, char** value); @@ -255,7 +256,7 @@ typedef bool (*MP4GetMetadataTool_t)(MP4FileHandle hFile, char** value); typedef bool (*MP4GetMetadataFreeForm_t)(MP4FileHandle hFile, const char *name, u_int8_t** pValue, u_int32_t* valueSize, const char *owner DEFAULT(NULL)); -typedef bool (*MP4HaveAtom_t)(MP4FileHandle hFile, +typedef bool (*MP4HaveAtom_t)(MP4FileHandle hFile, const char *atomName); typedef bool (*MP4SetMetadataName_t)(MP4FileHandle hFile, const char* value); @@ -278,7 +279,7 @@ typedef bool (*MP4SetMetadataCoverArt_t)(MP4FileHandle hFile, u_int8_t *coverArt, u_int32_t size); typedef MP4FileHandle (*MP4Modify_t)( - const char* fileName, + const char* fileName, u_int32_t verbosity DEFAULT(0), u_int32_t flags DEFAULT(0)); @@ -336,7 +337,7 @@ static MP4MetadataDelete_t MP4MetadataDelete = NULL; /* end mp4v2 dynamic load declarations */ /* mp4v2 initialization code */ - + void mp4_init() { mp4v2_handle = dlopen("libmp4v2.so.0", RTLD_LAZY); @@ -344,7 +345,7 @@ void mp4_init() if (!mp4v2_handle) { mp4v2_handle = dlopen("libmp4v2.so.1", RTLD_LAZY); - + if (!mp4v2_handle) { return; @@ -401,7 +402,7 @@ void mp4_init() MP4MetadataDelete = (MP4MetadataDelete_t) dlsym(mp4v2_handle, "MP4MetadataDelete"); /* alternate names for HAVE_LIBMP4V2_2 */ - + if(!MP4GetMetadataWriter) { MP4GetMetadataWriter = (MP4GetMetadataWriter_t) dlsym(mp4v2_handle, "MP4GetMetadataComposer"); @@ -432,7 +433,7 @@ void mp4_init() MP4SetMetadataTempo = (MP4SetMetadataTempo_t) dlsym(mp4v2_handle, "MP4SetMetadataYear"); } } - + void mp4_close() { if (mp4v2_handle) @@ -499,7 +500,7 @@ gboolean mp4_read_soundcheck (gchar *mp4FileName, Track *track) gtkpod_warning (_("m4a/m4p/m4b soundcheck update for '%s' failed: m4a/m4p/m4b not supported without the mp4v2 library. You must install the mp4v2 library.\n"), mp4FileName); return FALSE; } - + gboolean success = FALSE; MP4FileHandle mp4File; @@ -641,15 +642,15 @@ Track *mp4_get_file_info (gchar *mp4FileName) gchar *value; guint16 numvalue, numvalue2; MP4Duration trackDuration = MP4GetTrackDuration(mp4File, trackId); - double msDuration = + double msDuration = (double)MP4ConvertFromTrackDuration(mp4File, trackId, trackDuration, MP4_MSECS_TIME_SCALE); guint32 avgBitRate = MP4GetTrackBitRate(mp4File, trackId); guint32 samplerate = MP4GetTrackTimeScale(mp4File, trackId); - + track = gp_track_new (); - + track->tracklen = msDuration; track->bitrate = avgBitRate/1000; track->samplerate = samplerate; @@ -873,7 +874,7 @@ gboolean mp4_write_file_info (gchar *mp4FileName, Track *track) MP4SetMetadataAlbumArtist (mp4File, value); g_free (value); } - + value = charset_from_utf8 (track->composer); #if HAVE_LIBMP4V2_2 MP4SetMetadataComposer (mp4File, value); diff --git a/src/oggfile.c b/src/oggfile.c index 847241f..068d5e3 100644 --- a/src/oggfile.c +++ b/src/oggfile.c @@ -2,7 +2,7 @@ | | Copyright (C) 2007 Marc d[r]eadlock <m.dreadlock at gmail com> | Part of the gtkpod project. -| +| | URL: http://www.gtkpod.org/ | URL: http://gtkpod.sourceforge.net/ | @@ -35,6 +35,7 @@ #include "itdb.h" #include "misc.h" #include "oggfile.h" +#include <glib/gi18n-lib.h> /* Info on how to implement new file formats: see mp3file.c for more info */ @@ -54,7 +55,7 @@ Track *ogg_get_file_info (gchar *oggFileName) FILE *file= NULL; file=fopen(oggFileName, "rb"); - + if (file == NULL) { gchar *filename = charset_to_utf8 (oggFileName); @@ -122,26 +123,26 @@ Track *ogg_get_file_info (gchar *oggFileName) if ((str=vorbis_comment_query(vc,"cds",0))!=NULL){ track->cds = atoi(str); } - /* I'm not sure if "bpm" is correct */ + /* I'm not sure if "bpm" is correct */ if ((str=vorbis_comment_query(vc,"bpm",0))!=NULL){ track->BPM = atoi(str); } } - + } ov_clear(&oggFile); /* performs the fclose(file); */ /* TODO: immediate conversion if thread ? */ } } - + return track; } gboolean ogg_write_file_info (gchar *oggFileName, Track *track) { gboolean result=FALSE; - /*FIXME: seems to be not easy with common API. all other projects - * are using vcedit.ch from vorbis-tools (vorbiscomment). Maybe + /*FIXME: seems to be not easy with common API. all other projects + * are using vcedit.ch from vorbis-tools (vorbiscomment). Maybe * using a library could help. LibTag looks good... */ printf("Not supported yet\n"); return result; diff --git a/src/wavfile.c b/src/wavfile.c index 96d7699..157f582 100644 --- a/src/wavfile.c +++ b/src/wavfile.c @@ -2,7 +2,7 @@ | | Copyright (C) 2002-2005 Jorg Schuler <jcsjcs at users sourceforge net> | Part of the gtkpod project. -| +| | URL: http://www.gtkpod.org/ | URL: http://gtkpod.sourceforge.net/ | @@ -35,6 +35,7 @@ #include "itdb.h" #include "misc.h" #include "wavfile.h" +#include <glib/gi18n-lib.h> #include <string.h> ------------------------------------------------------------------------------ The Planet: dedicated and managed hosting, cloud storage, colocation Stay online with enterprise data centers and the best network in the business Choose flexible plans and management services without long-term contracts Personal 24x7 support from experience hosting pros just a phone call away. http://p.sf.net/sfu/theplanet-com _______________________________________________ gtkpod-cvs2 mailing list gtkpod-cvs2@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/gtkpod-cvs2