# HG changeset patch # User Calin Crisan ccrisan@gmail.com # Date 1217277840 -10800 # Node ID 3ba1579e37a50eeee3921764af86334b80ca642f # Parent 671cdfc2d62d33c8ee65aec55f807a30f00e8bdb# Parent fbb32674bfd2805fadf8749de328e455556c5daa Automated merge with ssh://hg.atheme-project.org//hg//audacious-plugins diff -r 671cdfc2d62d -r 3ba1579e37a5 src/streambrowser/gui/streambrowser_win.c --- a/src/streambrowser/gui/streambrowser_win.c Mon Jul 28 21:48:39 2008 +0300 +++ b/src/streambrowser/gui/streambrowser_win.c Mon Jul 28 23:44:00 2008 +0300 @@ -19,7 +19,7 @@ } streamdir_gui_t; -void (* update_function) (streamdir_t *streamdir, category_t *category, streaminfo_t *streaminfo); +void (* update_function) (streamdir_t *streamdir, category_t *category, streaminfo_t *streaminfo, gboolean add_to_playlist); static GtkWidget* gtk_label_new_with_icon(gchar *icon_filename, gchar *label_text); static GtkWidget* gtk_streamdir_tree_view_new(); @@ -33,7 +33,7 @@ static gboolean on_tree_view_button_pressed(GtkWidget *widget, GdkEventButton *event, gpointer data); static streamdir_gui_t* find_streamdir_gui_by_name(gchar *name); -static streamdir_gui_t* find_streamdir_gui_by_tree_view(GtkTreeView *tree_view); +//static streamdir_gui_t* find_streamdir_gui_by_tree_view(GtkTreeView *tree_view); todo: remove this static streamdir_gui_t* find_streamdir_gui_by_table(GtkTable *table); static streamdir_gui_t* find_streamdir_gui_by_streamdir(streamdir_t *streamdir); static gboolean tree_view_search_equal_func(GtkTreeModel *model, gint column, const gchar *key, GtkTreeIter *iter, gpointer data); @@ -46,6 +46,9 @@ static GtkCellRenderer* cell_renderer_pixbuf; static GtkCellRenderer* cell_renderer_text; +static gboolean tree_view_button_pressed = FALSE; + + void streambrowser_win_init() { @@ -186,13 +189,37 @@ streaminfo = streaminfo_get_by_index(category, i); gtk_tree_store_append(store, &new_iter, &iter); - gtk_tree_store_set(store, &new_iter, 0, "gtk-directory", 1, streaminfo->name, 2, streaminfo->current_track, -1); + gtk_tree_store_set(store, &new_iter, 0, "gtk-media-play", 1, streaminfo->name, 2, streaminfo->current_track, -1); } gtk_tree_path_free(path); } -void streambrowser_win_set_update_function(void (*function) (streamdir_t *streamdir, category_t *category, streaminfo_t *streaminfo)) +void streambrowser_win_set_streaminfo(streamdir_t *streamdir, category_t *category, streaminfo_t *streaminfo) +{ + streamdir_gui_t *streamdir_gui = find_streamdir_gui_by_name(streamdir->name); + if (streamdir_gui == NULL) { + failure("gui: streambrowser_win_set_category() called with non-existent streamdir\n"); + return; + } + + GtkTreeView *tree_view = GTK_TREE_VIEW(streamdir_gui->tree_view); + GtkTreeStore *store = GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(tree_view))); + GtkTreePath *path; + GtkTreeIter iter, new_iter; + + /* find the corresponding streaminfo tree iter */ + path = gtk_tree_path_new_from_indices(category_get_index(streamdir, category), streaminfo_get_index(category, streaminfo), -1); + if (!gtk_tree_model_get_iter(GTK_TREE_MODEL(store), &iter, path)) + return; + + /* update the streaminfo*/ + gtk_tree_store_set(store, &new_iter, 0, "gtk-media-play", 1, streaminfo->name, 2, streaminfo->current_track, -1); + + gtk_tree_path_free(path); +} + +void streambrowser_win_set_update_function(void (*function) (streamdir_t *streamdir, category_t *category, streaminfo_t *streaminfo, gboolean add_to_playlist)) { update_function = function; } @@ -240,7 +267,7 @@ gtk_tree_store_set(store, &iter, 0, "gtk-refresh", 1, temp, 2, streaminfo->current_track, -1); } else { - gtk_tree_store_set(store, &iter, 0, "gtk-directory", 1, streaminfo->name, 2, streaminfo->current_track, -1); + gtk_tree_store_set(store, &iter, 0, "gtk-media-play", 1, streaminfo->name, 2, streaminfo->current_track, -1); } } @@ -330,53 +357,72 @@ return TRUE; } + static gboolean on_tree_view_cursor_changed(GtkTreeView *tree_view, gpointer data) { + /* only do the refresh if this cursor change occured due to a mouse click */ + if (!tree_view_button_pressed) + return FALSE; + + tree_view_button_pressed = FALSE; + GtkTreePath *path; - GtkTreeIter iter; - GtkTreeModel *model; + GtkTreeViewColumn *focus_column; + + /* get the currently selected tree view */ + GtkWidget *table = gtk_notebook_get_nth_page(GTK_NOTEBOOK(notebook), gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook))); + streamdir_gui_t *streamdir_gui = find_streamdir_gui_by_table(GTK_TABLE(table)); + if (streamdir_gui == NULL) + return FALSE; + + /* get the currently selected path in the tree */ + gtk_tree_view_get_cursor(tree_view, &path, &focus_column); + + if (path == NULL || gtk_tree_path_get_depth(path) == 0) + return FALSE; - /* obtain the current category */ - gtk_tree_view_get_cursor(tree_view, &path, NULL); - - if (path == NULL) - return TRUE; - gint *indices = gtk_tree_path_get_indices(path); - if (gtk_tree_path_get_depth(path) != 1) { + int category_index = indices[0]; + streamdir_t *streamdir = streamdir_gui->streamdir; + category_t *category = category_get_by_index(streamdir_gui->streamdir, category_index); + + /* if the selected item is a category */ + if (gtk_tree_path_get_depth(path) == 1) { + if (!gtk_tree_view_row_expanded(tree_view, path)) { + gtk_entry_set_text(GTK_ENTRY(search_entry), ""); + update_function(streamdir, category, NULL, FALSE); + } + gtk_tree_path_free(path); - return TRUE; + } + /* if the selected item is a streaminfo */ + else { + int streaminfo_index = indices[1]; + + gtk_tree_path_free(path); + + /* get the currently selected stream (info) */ + streaminfo_t *streaminfo = streaminfo_get_by_index(category, streaminfo_index); + + gtk_entry_set_text(GTK_ENTRY(search_entry), ""); + update_function(streamdir, category, streaminfo, FALSE); } - model = gtk_tree_view_get_model(tree_view); - gtk_tree_model_get_iter(model, &iter, path); - - /* don't fetch a category that has been already fetched */ - if (gtk_tree_model_iter_has_child(model, &iter)) { - gtk_tree_path_free(path); - return TRUE; - } - - int category_index = indices[0]; - - gtk_tree_path_free(path); - - streamdir_gui_t *streamdir_gui = find_streamdir_gui_by_tree_view(tree_view); - if (streamdir_gui == NULL) - return TRUE; - - /* issue an update on the current category */ - update_function(streamdir_gui->streamdir, category_get_by_index(streamdir_gui->streamdir, category_index), NULL); - - return TRUE; + return FALSE; } static gboolean on_tree_view_button_pressed(GtkWidget *widget, GdkEventButton *event, gpointer data) { /* double click adds the currently selected stream to the playlist */ if (event->type == GDK_2BUTTON_PRESS) { + tree_view_button_pressed = FALSE; on_add_button_clicked(NULL, NULL); } + /* single click triggers a refresh of the selected item */ + else { + tree_view_button_pressed = TRUE; + } + return FALSE; } @@ -386,6 +432,7 @@ GtkTreePath *path; GtkTreeViewColumn *focus_column; + /* get the currently selected tree view */ GtkWidget *table = gtk_notebook_get_nth_page(GTK_NOTEBOOK(notebook), gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook))); streamdir_gui_t *streamdir_gui = find_streamdir_gui_by_table(GTK_TABLE(table)); if (streamdir_gui == NULL) @@ -393,6 +440,7 @@ GtkTreeView *tree_view = GTK_TREE_VIEW(streamdir_gui->tree_view); + /* get the currently selected path in the tree */ gtk_tree_view_get_cursor(tree_view, &path, &focus_column); if (path == NULL) @@ -414,12 +462,13 @@ gtk_tree_path_free(path); + /* get the currently selected stream (info) */ streamdir_t *streamdir = streamdir_gui->streamdir; category_t *category = category_get_by_index(streamdir_gui->streamdir, category_index); streaminfo_t *streaminfo = streaminfo_get_by_index(category, streaminfo_index); gtk_entry_set_text(GTK_ENTRY(search_entry), ""); - update_function(streamdir, category, streaminfo); + update_function(streamdir, category, streaminfo, TRUE); return TRUE; } @@ -470,6 +519,7 @@ return NULL; } +/* todo: remove this static streamdir_gui_t *find_streamdir_gui_by_tree_view(GtkTreeView *tree_view) { GList *iterator; @@ -484,6 +534,7 @@ return NULL; } +*/ static streamdir_gui_t *find_streamdir_gui_by_table(GtkTable *table) { diff -r 671cdfc2d62d -r 3ba1579e37a5 src/streambrowser/gui/streambrowser_win.h --- a/src/streambrowser/gui/streambrowser_win.h Mon Jul 28 21:48:39 2008 +0300 +++ b/src/streambrowser/gui/streambrowser_win.h Mon Jul 28 23:44:00 2008 +0300 @@ -12,7 +12,9 @@ void streambrowser_win_set_streamdir(streamdir_t *streamdir, gchar *icon_filename); void streambrowser_win_set_category(streamdir_t *streamdir, category_t *category); -void streambrowser_win_set_update_function(void (* update_function) (streamdir_t *streamdir, category_t *category, streaminfo_t *streaminfo)); +void streambrowser_win_set_streaminfo(streamdir_t *streamdir, category_t *category, streaminfo_t *streaminfo); + +void streambrowser_win_set_update_function(void (* update_function) (streamdir_t *streamdir, category_t *category, streaminfo_t *streaminfo, gboolean add_to_playlist)); void streambrowser_win_set_category_state(streamdir_t *streamdir, category_t *category, gboolean fetching); void streambrowser_win_set_streaminfo_state(streamdir_t *streamdir, category_t *category, streaminfo_t *streaminfo, gboolean fetching); diff -r 671cdfc2d62d -r 3ba1579e37a5 src/streambrowser/shoutcast.c --- a/src/streambrowser/shoutcast.c Mon Jul 28 21:48:39 2008 +0300 +++ b/src/streambrowser/shoutcast.c Mon Jul 28 23:44:00 2008 +0300 @@ -27,6 +27,78 @@ #include "shoutcast.h" +gboolean shoutcast_streaminfo_fetch(category_t *category, streaminfo_t *streaminfo) +{ + gchar url[DEF_STRING_LEN]; + g_snprintf(url, DEF_STRING_LEN, SHOUTCAST_CATEGORY_URL, category->name); + + /* generate a valid, temporary filename */ + char *temp_filename = tempnam(NULL, "aud_sb"); + if (temp_filename == NULL) { + failure("shoutcast: failed to create a temporary file\n"); + return FALSE; + } + + char temp_pathname[DEF_STRING_LEN]; + sprintf(temp_pathname, "file://%s", temp_filename); + + debug("shoutcast: fetching category file '%s'\n", url); + if (!fetch_remote_to_local_file(url, temp_pathname)) { + failure("shoutcast: category file '%s' could not be downloaded to '%s'\n", url, temp_pathname); + free(temp_filename); + return FALSE; + } + debug("shoutcast: category file '%s' successfuly downloaded to '%s'\n", url, temp_pathname); + + xmlDoc *doc = xmlReadFile(temp_pathname, NULL, 0); + if (doc == NULL) { + failure("shoutcast: failed to read '%s' category file\n", category->name); + free(temp_filename); + return FALSE; + } + + xmlNode *root_node = xmlDocGetRootElement(doc); + xmlNode *node; + + root_node = root_node->children; + + for (node = root_node; node != NULL; node = node->next) { + if (node->type == XML_ELEMENT_NODE && !strcmp((char *) node->name, "station")) { + gchar *streaminfo_name = (gchar*) xmlGetProp(node, (xmlChar *) "name"); + gchar *streaminfo_id = (gchar*) xmlGetProp(node, (xmlChar *) "id"); + gchar streaminfo_playlist_url[DEF_STRING_LEN]; + gchar *streaminfo_current_track = (gchar*) xmlGetProp(node, (xmlChar *) "ct"); + + g_snprintf(streaminfo_playlist_url, DEF_STRING_LEN, SHOUTCAST_STREAMINFO_URL, streaminfo_id); + + if (strncmp(streaminfo_playlist_url, streaminfo->playlist_url, DEF_STRING_LEN) == 0) { + debug("shoutcast: updating stream info for '%s/%d' from '%s'\n", streaminfo_name, streaminfo_id, url); + + strcpy(streaminfo->name, streaminfo_name); + strcpy(streaminfo->playlist_url, streaminfo_playlist_url); + strcpy(streaminfo->current_track, streaminfo_current_track); + + xmlFree(streaminfo_name); + xmlFree(streaminfo_id); + xmlFree(streaminfo_current_track); + + debug("shoutcast: stream info added\n"); + + break; + } + } + } + + xmlFreeDoc(doc); + + if (remove(temp_filename) != 0) { + failure("shoutcast: cannot remove the temporary file: %s\n", strerror(errno)); + } + free(temp_filename); + + return TRUE; +} + gboolean shoutcast_category_fetch(category_t *category) { gchar url[DEF_STRING_LEN]; @@ -75,7 +147,7 @@ g_snprintf(streaminfo_playlist_url, DEF_STRING_LEN, SHOUTCAST_STREAMINFO_URL, streaminfo_id); - debug("shoutcast: fetching stream info for '%s/%d' from '%s'\n", streaminfo_name, streaminfo_id, url); + debug("shoutcast: adding stream info for '%s/%d' from '%s'\n", streaminfo_name, streaminfo_id, url); streaminfo_t *streaminfo = streaminfo_new(streaminfo_name, streaminfo_playlist_url, "", streaminfo_current_track); streaminfo_add(category, streaminfo); diff -r 671cdfc2d62d -r 3ba1579e37a5 src/streambrowser/shoutcast.h --- a/src/streambrowser/shoutcast.h Mon Jul 28 21:48:39 2008 +0300 +++ b/src/streambrowser/shoutcast.h Mon Jul 28 23:44:00 2008 +0300 @@ -30,6 +30,7 @@ #define SHOUTCAST_STREAMINFO_URL "http://www.shoutcast.com/sbin/shoutcast-playlist.pls?rn=%s&file=filename.pls" +gboolean shoutcast_streaminfo_fetch(category_t *category, streaminfo_t *streaminfo); gboolean shoutcast_category_fetch(category_t *category); streamdir_t* shoutcast_streamdir_fetch(); diff -r 671cdfc2d62d -r 3ba1579e37a5 src/streambrowser/streambrowser.c --- a/src/streambrowser/streambrowser.c Mon Jul 28 21:48:39 2008 +0300 +++ b/src/streambrowser/streambrowser.c Mon Jul 28 23:44:00 2008 +0300 @@ -34,6 +34,7 @@ streamdir_t *streamdir; category_t *category; streaminfo_t *streaminfo; + gboolean add_to_playlist; } update_thread_data_t; @@ -47,7 +48,7 @@ static void config_load(); static void config_save(); -static void streamdir_update(streamdir_t *streamdir, category_t *category, streaminfo_t *streaminfo); +static void streamdir_update(streamdir_t *streamdir, category_t *category, streaminfo_t *streaminfo, gboolean add_to_playlist); static gpointer update_thread_core(gpointer user_data); static void streaminfo_add_to_playlist(streaminfo_t *streaminfo); static void on_plugin_services_menu_item_click(); @@ -271,12 +272,13 @@ debug("configuration saved\n"); } -static void streamdir_update(streamdir_t *streamdir, category_t *category, streaminfo_t *streaminfo) +static void streamdir_update(streamdir_t *streamdir, category_t *category, streaminfo_t *streaminfo, gboolean add_to_playlist) { - debug("requested streamdir update (streamdir = '%s', category = '%s', streaminfo = '%s')\n", + debug("requested streamdir update (streamdir = '%s', category = '%s', streaminfo = '%s', add_to_playlist = %d)\n", streamdir == NULL ? "" : streamdir->name, category == NULL ? "" : category->name, - streaminfo == NULL ? "" : streaminfo->name); + streaminfo == NULL ? "" : streaminfo->name, + add_to_playlist); if (g_queue_get_length(update_thread_data_queue) >= MAX_UPDATE_THREADS) { debug("another %d streamdir updates are pending, this request will be dropped\n", g_queue_get_length(update_thread_data_queue)); @@ -295,7 +297,8 @@ update_thread_data = g_queue_peek_nth(update_thread_data_queue, i); if (update_thread_data->streamdir == streamdir && update_thread_data->category == category && - update_thread_data->streaminfo == streaminfo) { + update_thread_data->streaminfo == streaminfo && + update_thread_data->add_to_playlist == add_to_playlist) { exists = TRUE; break; } @@ -310,6 +313,7 @@ update_thread_data->streamdir = streamdir; update_thread_data->category = category; update_thread_data->streaminfo = streaminfo; + update_thread_data->add_to_playlist = add_to_playlist; g_queue_push_tail(update_thread_data_queue, update_thread_data); } @@ -326,6 +330,7 @@ data->streamdir = streamdir; data->category = category; data->streaminfo = streaminfo; + data->add_to_playlist = add_to_playlist; g_queue_push_tail(update_thread_data_queue, data); @@ -350,46 +355,51 @@ /* repetitively process the queue elements, until queue is empty */ while (data != NULL && g_queue_get_length(update_thread_data_queue) > 0) { - /* update a streaminfo - that is - add this streaminfo to playlist */ + /* update a streaminfo */ if (data->streaminfo != NULL) { gdk_threads_enter(); streambrowser_win_set_streaminfo_state(data->streamdir, data->category, data->streaminfo, TRUE); gdk_threads_leave(); - streaminfo_add_to_playlist(data->streaminfo); + if (data->add_to_playlist) + streaminfo_add_to_playlist(data->streaminfo); + else { + /* shoutcast */ + if (strncmp(data->streamdir->name, SHOUTCAST_NAME, strlen(SHOUTCAST_NAME)) == 0) { + printf("DAAAA!\n"); + shoutcast_streaminfo_fetch(data->category, data->streaminfo); + } + /* xiph */ + else if (strncmp(data->streamdir->name, XIPH_NAME, strlen(XIPH_NAME)) == 0) { + //xiph_category_fetch(data->category); + } + } gdk_threads_enter(); + if (!data->add_to_playlist) + streambrowser_win_set_streaminfo(data->streamdir, data->category, data->streaminfo); streambrowser_win_set_streaminfo_state(data->streamdir, data->category, data->streaminfo, FALSE); gdk_threads_leave(); } /* update a category */ else if (data->category != NULL) { + gdk_threads_enter(); + streambrowser_win_set_category_state(data->streamdir, data->category, TRUE); + gdk_threads_leave(); + /* shoutcast */ if (strncmp(data->streamdir->name, SHOUTCAST_NAME, strlen(SHOUTCAST_NAME)) == 0) { - gdk_threads_enter(); - streambrowser_win_set_category_state(data->streamdir, data->category, TRUE); - gdk_threads_leave(); - shoutcast_category_fetch(data->category); - - gdk_threads_enter(); - streambrowser_win_set_category(data->streamdir, data->category); - streambrowser_win_set_category_state(data->streamdir, data->category, FALSE); - gdk_threads_leave(); } /* xiph */ else if (strncmp(data->streamdir->name, XIPH_NAME, strlen(XIPH_NAME)) == 0) { - gdk_threads_enter(); - streambrowser_win_set_category_state(data->streamdir, data->category, TRUE); - gdk_threads_leave(); - xiph_category_fetch(data->category); + } - gdk_threads_enter(); - streambrowser_win_set_category(data->streamdir, data->category); - streambrowser_win_set_category_state(data->streamdir, data->category, FALSE); - gdk_threads_leave(); - } + gdk_threads_enter(); + streambrowser_win_set_category(data->streamdir, data->category); + streambrowser_win_set_category_state(data->streamdir, data->category, FALSE); + gdk_threads_leave(); } /* update a streamdir */ else if (data->streamdir != NULL) { @@ -476,6 +486,6 @@ debug("on_plugin_services_menu_item_click()\n"); streambrowser_win_show(); - streamdir_update(NULL, NULL, NULL); + streamdir_update(NULL, NULL, NULL, FALSE); }