Mercurial > audlegacy-plugins
changeset 2794:f3e242d1855b
merge
author | mf0102 <0102@gmx.at> |
---|---|
date | Wed, 09 Jul 2008 22:26:30 +0200 |
parents | 14a58e80ecfe (current diff) f9c6a9cb442e (diff) |
children | 2ce16807a088 |
files | src/skins/ui_playlist.c |
diffstat | 14 files changed, 849 insertions(+), 29 deletions(-) [+] |
line wrap: on
line diff
--- a/src/skins/Makefile Wed Jul 09 22:25:31 2008 +0200 +++ b/src/skins/Makefile Wed Jul 09 22:26:30 2008 +0200 @@ -24,6 +24,7 @@ ui_main.c \ ui_equalizer.c \ ui_playlist.c \ + ui_playlist_manager.c \ ui_main_evlisteners.c \ ui_playlist_evlisteners.c \ ui_manager.c \
--- a/src/skins/ui_playlist.c Wed Jul 09 22:25:31 2008 +0200 +++ b/src/skins/ui_playlist.c Wed Jul 09 22:26:30 2008 +0200 @@ -54,9 +54,7 @@ #include "ui_main.h" #include "ui_manager.h" #include "ui_playlist_evlisteners.h" -#if 0 #include "ui_playlist_manager.h" -#endif #include "util.h" #include "ui_skinned_window.h" @@ -1869,9 +1867,7 @@ void action_open_list_manager(void) { -#if 0 playlist_manager_ui_show(); -#endif } void
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/skins/ui_playlist_manager.c Wed Jul 09 22:26:30 2008 +0200 @@ -0,0 +1,498 @@ +/* Audacious - Cross-platform multimedia player + * Copyright (C) 2005-2007 Audacious development team. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; under version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses>. + * + * The Audacious team does not consider modular code linking to + * Audacious or using our public API to be a derived work. + */ + +#include "ui_playlist_manager.h" +#include "ui_playlist.h" +#include <audacious/plugin.h> +#include "ui_main.h" + +#include <glib.h> +#include <glib/gi18n.h> +#include <gtk/gtk.h> +#include <gdk/gdkkeysyms.h> + + +#define DISABLE_MANAGER_UPDATE() g_object_set_data(G_OBJECT(listview),"opt1",GINT_TO_POINTER(1)) +#define ENABLE_MANAGER_UPDATE() g_object_set_data(G_OBJECT(listview),"opt1",GINT_TO_POINTER(0)) + + +static GtkWidget *playman_win = NULL; + + +/* in this enum, place the columns according to visualization order + (information not displayed in columns should be placed right before PLLIST_NUMCOLS) */ +enum +{ + PLLIST_COL_NAME = 0, + PLLIST_COL_ENTRIESNUM, + PLLIST_PLPOINTER, + PLLIST_TEXT_WEIGHT, + PLLIST_NUMCOLS +}; + + +static GtkTreeIter +playlist_manager_populate ( GtkListStore * store ) +{ + GList *playlists = NULL; + Playlist *active, *iter_playlist, *next_playlist; + GtkTreeIter iter, insert, next, active_iter; + gboolean valid, have_active_iter; + + active = aud_playlist_get_active(); + playlists = aud_playlist_get_playlists(); + valid = gtk_tree_model_get_iter_first( GTK_TREE_MODEL(store) , &iter ); + have_active_iter = FALSE; + while ( playlists != NULL ) + { + GList *entries = NULL; + gint entriesnum = 0; + gchar *pl_name = NULL; + Playlist *playlist = (Playlist*)playlists->data; + + if(playlist != active) //XXX the active playlist has been locked in playlist_new_from_selected() + PLAYLIST_LOCK(playlist); + + /* for each playlist, pick name and number of entries */ + pl_name = (gchar*)aud_playlist_get_current_name( playlist ); + for (entries = playlist->entries; entries; entries = g_list_next(entries)) + entriesnum++; + + if(playlist != active) + PLAYLIST_UNLOCK(playlist); + + /* update the tree model conservatively */ + + if ( !valid ) + { + /* append */ + gtk_list_store_append( store , &insert ); + goto store_set; + } + + gtk_tree_model_get( GTK_TREE_MODEL(store) , &iter , + PLLIST_PLPOINTER , &iter_playlist , -1 ); + + if ( playlist == iter_playlist ) + { + /* already have - just update */ + insert = iter; + valid = gtk_tree_model_iter_next( GTK_TREE_MODEL(store) , &iter ); + goto store_set; + } + + /* handle movement/deletion/insertion of single elements */ + if ( gtk_tree_model_iter_next( GTK_TREE_MODEL(store) , &next ) ) + { + gtk_tree_model_get( GTK_TREE_MODEL(store) , &next , + PLLIST_PLPOINTER , &next_playlist , -1 ); + if ( playlist == next_playlist ) + { + /* remove */ + gtk_list_store_remove( store , &iter ); + iter = next; + valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(store), &iter); + goto next_playlist; + } + } + + /* insert */ + gtk_list_store_insert_before( store , &insert , &iter ); + +store_set: + gtk_list_store_set( store, &insert, + PLLIST_COL_NAME , pl_name , + PLLIST_COL_ENTRIESNUM , entriesnum , + PLLIST_PLPOINTER , playlist , + PLLIST_TEXT_WEIGHT , playlist == active ? + PANGO_WEIGHT_BOLD : PANGO_WEIGHT_NORMAL , + -1 ); + if ( !have_active_iter && playlist == active ) + { + active_iter = insert; + have_active_iter = TRUE; + } + +next_playlist: + playlists = g_list_next(playlists); + } + + while (valid) + { + /* remove any other elements */ + next = iter; + valid = gtk_tree_model_iter_next( GTK_TREE_MODEL(store) , &next ); + gtk_list_store_remove( store , &iter ); + iter = next; + } + + if ( !have_active_iter ) + gtk_tree_model_get_iter_first( GTK_TREE_MODEL(store) , &active_iter ); + + return active_iter; +} + + +static void +playlist_manager_cb_new ( gpointer listview ) +{ + GList *playlists = NULL; + Playlist *newpl = NULL; + GtkTreeIter iter; + GtkListStore *store; + gchar *pl_name = NULL; + + /* this ensures that playlist_manager_update() will + not perform update, since we're already doing it here */ + DISABLE_MANAGER_UPDATE(); + + newpl = aud_playlist_new(); + pl_name = (gchar*)aud_playlist_get_current_name( newpl ); + playlists = aud_playlist_get_playlists(); + aud_playlist_add_playlist( newpl ); + + store = (GtkListStore*)gtk_tree_view_get_model( GTK_TREE_VIEW(listview) ); + gtk_list_store_append( store , &iter ); + gtk_list_store_set( store, &iter, + PLLIST_COL_NAME , pl_name , + PLLIST_COL_ENTRIESNUM , 0 , + PLLIST_PLPOINTER , newpl , + PLLIST_TEXT_WEIGHT , PANGO_WEIGHT_NORMAL , + -1 ); + + ENABLE_MANAGER_UPDATE(); + + return; +} + + +static void +playlist_manager_cb_del ( gpointer listview ) +{ + GtkTreeSelection *listsel = gtk_tree_view_get_selection( GTK_TREE_VIEW(listview) ); + GtkTreeModel *store; + GtkTreeIter iter; + Playlist *active; + gboolean was_active; + + if ( gtk_tree_selection_get_selected( listsel , &store , &iter ) == TRUE ) + { + Playlist *playlist = NULL; + gtk_tree_model_get( store, &iter, PLLIST_PLPOINTER , &playlist , -1 ); + + active = aud_playlist_get_active(); + was_active = ( playlist == active ); + + if ( gtk_tree_model_iter_n_children( store , NULL ) < 2 ) + { + /* let playlist_manager_update() handle the deletion of the last playlist */ + aud_playlist_remove_playlist( playlist ); + } + else + { + gtk_list_store_remove( (GtkListStore*)store , &iter ); + /* this ensures that playlist_manager_update() will + not perform update, since we're already doing it here */ + DISABLE_MANAGER_UPDATE(); + aud_playlist_remove_playlist( playlist ); + ENABLE_MANAGER_UPDATE(); + } + + if ( was_active && gtk_tree_model_get_iter_first( store , &iter ) ) + { + /* update bolded playlist */ + active = aud_playlist_get_active(); + do { + gtk_tree_model_get( store , &iter , + PLLIST_PLPOINTER , &playlist , -1 ); + gtk_list_store_set( GTK_LIST_STORE(store) , &iter , + PLLIST_TEXT_WEIGHT , playlist == active ? + PANGO_WEIGHT_BOLD : PANGO_WEIGHT_NORMAL , + -1 ); + } while ( gtk_tree_model_iter_next( store , &iter ) ); + } + } + + return; +} + + +static void +playlist_manager_cb_lv_dclick ( GtkTreeView * listview , GtkTreePath * path , + GtkTreeViewColumn * col , gpointer userdata ) +{ + GtkTreeModel *store; + GtkTreeIter iter; + Playlist *playlist = NULL, *active; + + store = gtk_tree_view_get_model( GTK_TREE_VIEW(listview) ); + if ( gtk_tree_model_get_iter( store , &iter , path ) == TRUE ) + { + gtk_tree_model_get( store , &iter , PLLIST_PLPOINTER , &playlist , -1 ); + DISABLE_MANAGER_UPDATE(); + aud_playlist_select_playlist( playlist ); + ENABLE_MANAGER_UPDATE(); + } + + if ( gtk_tree_model_get_iter_first( store , &iter ) ) + { + /* update bolded playlist */ + active = aud_playlist_get_active(); + do { + gtk_tree_model_get( store , &iter , + PLLIST_PLPOINTER , &playlist , -1 ); + gtk_list_store_set( GTK_LIST_STORE(store) , &iter , + PLLIST_TEXT_WEIGHT , playlist == active ? + PANGO_WEIGHT_BOLD : PANGO_WEIGHT_NORMAL , + -1 ); + } while ( gtk_tree_model_iter_next( store , &iter ) ); + } + + return; +} + + +static void +playlist_manager_cb_lv_pmenu_rename ( GtkMenuItem *menuitem , gpointer lv ) +{ + GtkTreeSelection *listsel = gtk_tree_view_get_selection( GTK_TREE_VIEW(lv) ); + GtkTreeModel *store; + GtkTreeIter iter; + + if ( gtk_tree_selection_get_selected( listsel , &store , &iter ) == TRUE ) + { + GtkTreePath *path = gtk_tree_model_get_path( GTK_TREE_MODEL(store) , &iter ); + GtkCellRenderer *rndrname = g_object_get_data( G_OBJECT(lv) , "rn" ); + /* set the name renderer to editable and start editing */ + g_object_set( G_OBJECT(rndrname) , "editable" , TRUE , NULL ); + gtk_tree_view_set_cursor_on_cell( GTK_TREE_VIEW(lv) , path , + gtk_tree_view_get_column( GTK_TREE_VIEW(lv) , PLLIST_COL_NAME ) , rndrname , TRUE ); + gtk_tree_path_free( path ); + } +} + +static void +playlist_manager_cb_lv_name_edited ( GtkCellRendererText *cell , gchar *path_string , + gchar *new_text , gpointer listview ) +{ + /* this is currently used to change playlist names */ + GtkTreeModel *store = gtk_tree_view_get_model( GTK_TREE_VIEW(listview) ); + GtkTreeIter iter; + + if ( gtk_tree_model_get_iter_from_string( store , &iter , path_string ) == TRUE ) + { + Playlist *playlist = NULL; + gtk_tree_model_get( GTK_TREE_MODEL(store), &iter, PLLIST_PLPOINTER , &playlist , -1 ); + DISABLE_MANAGER_UPDATE(); + aud_playlist_set_current_name( playlist , new_text ); + ENABLE_MANAGER_UPDATE(); + gtk_list_store_set( GTK_LIST_STORE(store), &iter, PLLIST_COL_NAME , new_text , -1 ); + } + /* set the renderer uneditable again */ + g_object_set( G_OBJECT(cell) , "editable" , FALSE , NULL ); +} + + +static gboolean +playlist_manager_cb_lv_btpress ( GtkWidget *lv , GdkEventButton *event ) +{ + if (( event->type == GDK_BUTTON_PRESS ) && ( event->button == 3 )) + { + GtkWidget *pmenu = (GtkWidget*)g_object_get_data( G_OBJECT(lv) , "menu" ); + gtk_menu_popup( GTK_MENU(pmenu) , NULL , NULL , NULL , NULL , + (event != NULL) ? event->button : 0, + event->time); + return TRUE; + } + + return FALSE; +} + + +static gboolean +playlist_manager_cb_keypress ( GtkWidget *win , GdkEventKey *event ) +{ + switch (event->keyval) + { + case GDK_Escape: + gtk_widget_destroy( playman_win ); + return TRUE; + default: + return FALSE; + } +} + + +void +playlist_manager_ui_show ( void ) +{ + GtkWidget *playman_vbox; + GtkWidget *playman_pl_lv, *playman_pl_lv_frame, *playman_pl_lv_sw; + GtkCellRenderer *playman_pl_lv_textrndr_name, *playman_pl_lv_textrndr_entriesnum; + GtkTreeViewColumn *playman_pl_lv_col_name, *playman_pl_lv_col_entriesnum; + GtkListStore *pl_store; + GtkWidget *playman_pl_lv_pmenu, *playman_pl_lv_pmenu_rename; + GtkWidget *playman_bbar_hbbox; + GtkWidget *playman_bbar_bt_new, *playman_bbar_bt_del, *playman_bbar_bt_close; + GdkGeometry playman_win_hints; + GtkTreeIter active_iter; + GtkTreePath *active_path; + + if ( playman_win != NULL ) + { + gtk_window_present( GTK_WINDOW(playman_win) ); + return; + } + + playman_win = gtk_window_new( GTK_WINDOW_TOPLEVEL ); + gtk_window_set_type_hint( GTK_WINDOW(playman_win), GDK_WINDOW_TYPE_HINT_DIALOG ); + gtk_window_set_transient_for( GTK_WINDOW(playman_win) , GTK_WINDOW(mainwin) ); + gtk_window_set_position( GTK_WINDOW(playman_win), GTK_WIN_POS_CENTER ); + gtk_window_set_title( GTK_WINDOW(playman_win), _("Playlist Manager") ); + gtk_container_set_border_width( GTK_CONTAINER(playman_win), 10 ); + g_signal_connect( G_OBJECT(playman_win) , "destroy" , + G_CALLBACK(gtk_widget_destroyed) , &playman_win ); + g_signal_connect( G_OBJECT(playman_win) , "key-press-event" , + G_CALLBACK(playlist_manager_cb_keypress) , NULL ); + playman_win_hints.min_width = 400; + playman_win_hints.min_height = 250; + gtk_window_set_geometry_hints( GTK_WINDOW(playman_win) , GTK_WIDGET(playman_win) , + &playman_win_hints , GDK_HINT_MIN_SIZE ); + + playman_vbox = gtk_vbox_new( FALSE , 10 ); + gtk_container_add( GTK_CONTAINER(playman_win) , playman_vbox ); + + /* current liststore model + ---------------------------------------------- + G_TYPE_STRING -> playlist name + G_TYPE_UINT -> number of entries in playlist + G_TYPE_POINTER -> playlist pointer (Playlist*) + PANGO_TYPE_WEIGHT -> font weight + ---------------------------------------------- + */ + pl_store = gtk_list_store_new( PLLIST_NUMCOLS , + G_TYPE_STRING , G_TYPE_UINT , G_TYPE_POINTER , PANGO_TYPE_WEIGHT ); + active_iter = playlist_manager_populate( pl_store ); + + playman_pl_lv_frame = gtk_frame_new( NULL ); + playman_pl_lv = gtk_tree_view_new_with_model( GTK_TREE_MODEL(pl_store) ); + + g_object_set_data( G_OBJECT(playman_win) , "lv" , playman_pl_lv ); + g_object_set_data( G_OBJECT(playman_pl_lv) , "opt1" , GINT_TO_POINTER(0) ); + playman_pl_lv_textrndr_entriesnum = gtk_cell_renderer_text_new(); /* uneditable */ + playman_pl_lv_textrndr_name = gtk_cell_renderer_text_new(); /* can become editable */ + g_object_set( G_OBJECT(playman_pl_lv_textrndr_entriesnum) , "weight-set" , TRUE , NULL ); + g_object_set( G_OBJECT(playman_pl_lv_textrndr_name) , "weight-set" , TRUE , NULL ); + g_signal_connect( G_OBJECT(playman_pl_lv_textrndr_name) , "edited" , + G_CALLBACK(playlist_manager_cb_lv_name_edited) , playman_pl_lv ); + g_object_set_data( G_OBJECT(playman_pl_lv) , "rn" , playman_pl_lv_textrndr_name ); + playman_pl_lv_col_name = gtk_tree_view_column_new_with_attributes( + _("Playlist") , playman_pl_lv_textrndr_name , + "text" , PLLIST_COL_NAME , + "weight", PLLIST_TEXT_WEIGHT , + NULL ); + gtk_tree_view_column_set_expand( GTK_TREE_VIEW_COLUMN(playman_pl_lv_col_name) , TRUE ); + gtk_tree_view_append_column( GTK_TREE_VIEW(playman_pl_lv), playman_pl_lv_col_name ); + playman_pl_lv_col_entriesnum = gtk_tree_view_column_new_with_attributes( + _("Entries") , playman_pl_lv_textrndr_entriesnum , + "text" , PLLIST_COL_ENTRIESNUM , + "weight", PLLIST_TEXT_WEIGHT , + NULL ); + gtk_tree_view_column_set_expand( GTK_TREE_VIEW_COLUMN(playman_pl_lv_col_entriesnum) , FALSE ); + gtk_tree_view_append_column( GTK_TREE_VIEW(playman_pl_lv), playman_pl_lv_col_entriesnum ); + playman_pl_lv_sw = gtk_scrolled_window_new( NULL , NULL ); + gtk_scrolled_window_set_policy( GTK_SCROLLED_WINDOW(playman_pl_lv_sw) , + GTK_POLICY_NEVER , GTK_POLICY_ALWAYS ); + gtk_container_add( GTK_CONTAINER(playman_pl_lv_sw) , playman_pl_lv ); + gtk_container_add( GTK_CONTAINER(playman_pl_lv_frame) , playman_pl_lv_sw ); + gtk_box_pack_start( GTK_BOX(playman_vbox) , playman_pl_lv_frame , TRUE , TRUE , 0 ); + + /* listview popup menu */ + playman_pl_lv_pmenu = gtk_menu_new(); + playman_pl_lv_pmenu_rename = gtk_menu_item_new_with_mnemonic( _( "_Rename" ) ); + g_signal_connect( G_OBJECT(playman_pl_lv_pmenu_rename) , "activate" , + G_CALLBACK(playlist_manager_cb_lv_pmenu_rename) , playman_pl_lv ); + gtk_menu_shell_append( GTK_MENU_SHELL(playman_pl_lv_pmenu) , playman_pl_lv_pmenu_rename ); + gtk_widget_show_all( playman_pl_lv_pmenu ); + g_object_set_data( G_OBJECT(playman_pl_lv) , "menu" , playman_pl_lv_pmenu ); + g_signal_connect_swapped( G_OBJECT(playman_win) , "destroy" , + G_CALLBACK(gtk_widget_destroy) , playman_pl_lv_pmenu ); + + /* button bar */ + playman_bbar_hbbox = gtk_hbutton_box_new(); + gtk_button_box_set_layout( GTK_BUTTON_BOX(playman_bbar_hbbox) , GTK_BUTTONBOX_END ); + gtk_button_box_set_spacing(GTK_BUTTON_BOX(playman_bbar_hbbox), 5); + playman_bbar_bt_close = gtk_button_new_from_stock( GTK_STOCK_CLOSE ); + playman_bbar_bt_del = gtk_button_new_from_stock( GTK_STOCK_DELETE ); + playman_bbar_bt_new = gtk_button_new_from_stock( GTK_STOCK_NEW ); + gtk_container_add( GTK_CONTAINER(playman_bbar_hbbox) , playman_bbar_bt_close ); + gtk_container_add( GTK_CONTAINER(playman_bbar_hbbox) , playman_bbar_bt_del ); + gtk_container_add( GTK_CONTAINER(playman_bbar_hbbox) , playman_bbar_bt_new ); + gtk_button_box_set_child_secondary( GTK_BUTTON_BOX(playman_bbar_hbbox) , + playman_bbar_bt_close , TRUE ); + gtk_box_pack_start( GTK_BOX(playman_vbox) , playman_bbar_hbbox , FALSE , FALSE , 0 ); + + g_signal_connect( G_OBJECT(playman_pl_lv) , "button-press-event" , + G_CALLBACK(playlist_manager_cb_lv_btpress) , NULL ); + g_signal_connect( G_OBJECT(playman_pl_lv) , "row-activated" , + G_CALLBACK(playlist_manager_cb_lv_dclick) , NULL ); + g_signal_connect_swapped( G_OBJECT(playman_bbar_bt_new) , "clicked" , + G_CALLBACK(playlist_manager_cb_new) , playman_pl_lv ); + g_signal_connect_swapped( G_OBJECT(playman_bbar_bt_del) , "clicked" , + G_CALLBACK(playlist_manager_cb_del) , playman_pl_lv ); + g_signal_connect_swapped( G_OBJECT(playman_bbar_bt_close) , "clicked" , + G_CALLBACK(gtk_widget_destroy) , playman_win ); + + /* have active playlist selected and scrolled to */ + active_path = gtk_tree_model_get_path( GTK_TREE_MODEL(pl_store) , + &active_iter ); + gtk_tree_view_set_cursor( GTK_TREE_VIEW(playman_pl_lv) , + active_path , NULL , FALSE ); + gtk_tree_view_scroll_to_cell( GTK_TREE_VIEW(playman_pl_lv) , + active_path , NULL , TRUE , 0.5 , 0.0 ); + gtk_tree_path_free( active_path ); + + g_object_unref( pl_store ); + + gtk_widget_show_all( playman_win ); +} + + +void +playlist_manager_update ( void ) +{ + /* this function is called whenever there is a change in playlist, such as + playlist created/deleted or entry added/deleted in a playlist; if the playlist + manager is active, it should be updated to keep consistency of information */ + + /* CAREFUL! this currently locks/unlocks all the playlists */ + + if ( playman_win != NULL ) + { + GtkWidget *lv = (GtkWidget*)g_object_get_data( G_OBJECT(playman_win) , "lv" ); + if ( GPOINTER_TO_INT(g_object_get_data(G_OBJECT(lv),"opt1")) == 0 ) + { + GtkListStore *store = (GtkListStore*)gtk_tree_view_get_model( GTK_TREE_VIEW(lv) ); + playlist_manager_populate( store ); + } + return; + } + else + return; /* if the playlist manager is not active, simply return */ +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/skins/ui_playlist_manager.h Wed Jul 09 22:26:30 2008 +0200 @@ -0,0 +1,26 @@ +/* Audacious - Cross-platform multimedia player + * Copyright (C) 2005-2007 Audacious development team. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; under version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses>. + * + * The Audacious team does not consider modular code linking to + * Audacious or using our public API to be a derived work. + */ + +#ifndef AUDACIOUS_UI_PLAYLIST_MANAGER_H +#define AUDACIOUS_UI_PLAYLIST_MANAGER_H + +void playlist_manager_update ( void ); +void playlist_manager_ui_show ( void ); + +#endif /* AUDACIOUS_UI_PLAYLIST_MANAGER_H */
--- a/src/streambrowser/Makefile Wed Jul 09 22:25:31 2008 +0200 +++ b/src/streambrowser/Makefile Wed Jul 09 22:26:30 2008 +0200 @@ -6,7 +6,9 @@ gui/about_win.c \ gui/streambrowser_win.c -DATA = images/shoutcast.png +DATA = images/shoutcast.png \ + images/streambrowser-16x16.png \ + images/streambrowser-64x64.png include ../../buildsys.mk include ../../extra.mk
--- a/src/streambrowser/gui/streambrowser_win.c Wed Jul 09 22:25:31 2008 +0200 +++ b/src/streambrowser/gui/streambrowser_win.c Wed Jul 09 22:26:30 2008 +0200 @@ -32,6 +32,7 @@ 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_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); @@ -80,12 +81,12 @@ gtk_window_set_title(GTK_WINDOW(streambrowser_window), _("Stream browser")); gtk_window_set_position(GTK_WINDOW(streambrowser_window), GTK_WIN_POS_CENTER); gtk_window_set_default_size(GTK_WINDOW(streambrowser_window), 700, 400); + gtk_window_set_icon_from_file(GTK_WINDOW(streambrowser_window), STREAMBROWSER_ICON, NULL); g_signal_connect(G_OBJECT(streambrowser_window), "delete-event", G_CALLBACK(gtk_widget_hide_on_delete), streambrowser_window); gtk_container_add(GTK_CONTAINER(streambrowser_window), vbox1); /* others */ cell_renderer_pixbuf = gtk_cell_renderer_pixbuf_new(); - g_object_set(G_OBJECT(cell_renderer_pixbuf), "stock-id", "gtk-directory", NULL); cell_renderer_text = gtk_cell_renderer_text_new(); } @@ -147,7 +148,7 @@ category = category_get_by_index(streamdir, i); gtk_tree_store_append(store, &iter, NULL); - gtk_tree_store_set(store, &iter, 0, NULL, 1, category->name, 2, "", -1); + gtk_tree_store_set(store, &iter, 0, "gtk-directory", 1, category->name, 2, "", -1); } } @@ -183,7 +184,7 @@ streaminfo = streaminfo_get_by_index(category, i); gtk_tree_store_append(store, &new_iter, &iter); - gtk_tree_store_set(store, &new_iter, 0, NULL, 1, streaminfo->name, 2, streaminfo->current_track, -1); + gtk_tree_store_set(store, &new_iter, 0, "gtk-directory", 1, streaminfo->name, 2, streaminfo->current_track, -1); } } @@ -192,6 +193,29 @@ update_function = function; } +void streambrowser_win_set_category_state(streamdir_t *streamdir, category_t *category, gboolean fetching) +{ + streamdir_gui_t *streamdir_gui = find_streamdir_gui_by_streamdir(streamdir); + GtkTreeView *tree_view = GTK_TREE_VIEW(streamdir_gui->tree_view); + GtkTreeStore *store = GTK_TREE_STORE(gtk_tree_view_get_model(tree_view)); + GtkTreePath *path; + GtkTreeIter iter; + + /* find the corresponding category tree iter */ + path = gtk_tree_path_new_from_indices(category_get_index(streamdir, category), -1); + if (!gtk_tree_model_get_iter(GTK_TREE_MODEL(store), &iter, path)) + return; + + if (fetching) { + gchar temp[DEF_STRING_LEN]; + sprintf(temp, "<span style='italic' weight='heavy'>%s</span>", category->name); + gtk_tree_store_set(store, &iter, 0, "gtk-refresh", 1, temp, 2, "", -1); + } + else { + gtk_tree_store_set(store, &iter, 0, "gtk-directory", 1, category->name, 2, "", -1); + } +} + static GtkWidget* gtk_label_new_with_icon(gchar *icon_filename, gchar *label_text) { GtkWidget *hbox = gtk_hbox_new(FALSE, 1); @@ -208,7 +232,7 @@ { GtkWidget *tree_view = gtk_tree_view_new(); - GtkTreeStore *store = gtk_tree_store_new(3, GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_STRING); + GtkTreeStore *store = gtk_tree_store_new(3, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING); gtk_tree_view_set_model(GTK_TREE_VIEW(tree_view), GTK_TREE_MODEL(store)); gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(tree_view), TRUE); @@ -218,13 +242,13 @@ GtkTreeViewColumn *column = gtk_tree_view_column_new(); gtk_tree_view_column_pack_start(column, cell_renderer_pixbuf, TRUE); - gtk_tree_view_column_add_attribute(column, cell_renderer_pixbuf, "pixbuf", 0); + gtk_tree_view_column_add_attribute(column, cell_renderer_pixbuf, "stock-id", 0); gtk_tree_view_column_set_resizable(column, TRUE); gtk_tree_view_append_column(GTK_TREE_VIEW(tree_view), column); column = gtk_tree_view_column_new(); gtk_tree_view_column_pack_start(column, cell_renderer_text, TRUE); - gtk_tree_view_column_add_attribute(column, cell_renderer_text, "text", 1); + gtk_tree_view_column_add_attribute(column, cell_renderer_text, "markup", 1); gtk_tree_view_column_set_resizable(column, TRUE); gtk_tree_view_column_set_title(column, _("Stream name")); gtk_tree_view_append_column(GTK_TREE_VIEW(tree_view), column); @@ -438,6 +462,21 @@ return NULL; } +static streamdir_gui_t* find_streamdir_gui_by_streamdir(streamdir_t *streamdir) +{ + GList *iterator; + streamdir_gui_t *streamdir_gui; + + for (iterator = g_list_first(streamdir_gui_list); iterator != NULL; iterator = g_list_next(iterator)) { + streamdir_gui = iterator->data; + + if ((void *) streamdir_gui->streamdir == (void *) streamdir) + return streamdir_gui; + } + + return NULL; +} + static gboolean tree_view_search_equal_func(GtkTreeModel *model, gint column, const gchar *key, GtkTreeIter *iter, gpointer data) { GValue value = {0, };
--- a/src/streambrowser/gui/streambrowser_win.h Wed Jul 09 22:25:31 2008 +0200 +++ b/src/streambrowser/gui/streambrowser_win.h Wed Jul 09 22:26:30 2008 +0200 @@ -13,6 +13,7 @@ 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_category_state(streamdir_t *streamdir, category_t *category, gboolean fetching); #endif // STREAMBROWSER_WIN_H
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/streambrowser/images/streambrowser.svg Wed Jul 09 22:26:30 2008 +0200 @@ -0,0 +1,251 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + version="1.1" + width="128px" + height="128px" + id="RSSicon" + viewBox="0 0 256 256" + sodipodi:version="0.32" + inkscape:version="0.46" + sodipodi:docname="Feed-icon.svg" + inkscape:output_extension="org.inkscape.output.svg.inkscape"> + <metadata + id="metadata33"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + </cc:Work> + </rdf:RDF> + </metadata> + <sodipodi:namedview + inkscape:window-height="967" + inkscape:window-width="1225" + inkscape:pageshadow="2" + inkscape:pageopacity="0.0" + guidetolerance="10.0" + gridtolerance="10.0" + objecttolerance="10.0" + borderopacity="1.0" + bordercolor="#666666" + pagecolor="#ffffff" + id="base" + showgrid="false" + inkscape:zoom="1.9296875" + inkscape:cx="153.86031" + inkscape:cy="-44.300212" + inkscape:window-x="455" + inkscape:window-y="57" + inkscape:current-layer="RSSicon" /> + <defs + id="defs3"> + <linearGradient + id="linearGradient3744"> + <stop + style="stop-color:#3c5aa0;stop-opacity:1;" + offset="0" + id="stop3746" /> + <stop + id="stop3752" + offset="0.2962963" + style="stop-color:#5979c1;stop-opacity:1;" /> + <stop + style="stop-color:#243660;stop-opacity:1;" + offset="1" + id="stop3748" /> + </linearGradient> + <linearGradient + id="linearGradient3210"> + <stop + style="stop-color:#ff7326;stop-opacity:1;" + offset="0" + id="stop3212" /> + <stop + id="stop3218" + offset="1" + style="stop-color:#ff7426;stop-opacity:1;" /> + </linearGradient> + <inkscape:perspective + sodipodi:type="inkscape:persp3d" + inkscape:vp_x="0 : 64 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_z="128 : 64 : 1" + inkscape:persp3d-origin="64 : 42.666667 : 1" + id="perspective35" /> + <linearGradient + x1="0.085000001" + y1="0.085000001" + x2="0.91500002" + y2="0.91500002" + id="RSSg" + xlink:href="#linearGradient3210"> + <stop + offset="0" + stop-color="#DE642B" + id="stop16" + style="stop-color:#768bc7;stop-opacity:1;" /> + <stop + offset="1" + stop-color="#D95B29" + id="stop18" + style="stop-color:#3c5aa0;stop-opacity:1;" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3210" + id="linearGradient3216" + x1="44" + y1="125.5" + x2="219" + y2="125.5" + gradientUnits="userSpaceOnUse" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3210" + id="linearGradient3226" + x1="44" + y1="155" + x2="160" + y2="155" + gradientUnits="userSpaceOnUse" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3210" + id="linearGradient3234" + x1="44" + y1="189" + x2="92" + y2="189" + gradientUnits="userSpaceOnUse" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3210" + id="linearGradient3275" + gradientUnits="userSpaceOnUse" + x1="44" + y1="189" + x2="92" + y2="189" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3210" + id="linearGradient3277" + gradientUnits="userSpaceOnUse" + x1="44" + y1="155" + x2="160" + y2="155" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3210" + id="linearGradient3279" + gradientUnits="userSpaceOnUse" + x1="44" + y1="125.5" + x2="219" + y2="125.5" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3744" + id="linearGradient3750" + x1="23.191692" + y1="29.795177" + x2="234.27405" + y2="226.20482" + gradientUnits="userSpaceOnUse" /> + <filter + inkscape:collect="always" + id="filter3758"> + <feGaussianBlur + inkscape:collect="always" + stdDeviation="4.1217132" + id="feGaussianBlur3760" /> + </filter> + </defs> + <rect + width="256" + height="256" + rx="55" + ry="55" + x="0" + y="0" + id="rect20" + style="fill:#2f477d;fill-opacity:1" + fill="#CC5D15" /> + <rect + width="246" + height="246" + rx="50" + ry="50" + x="5" + y="5" + id="rect22" + style="fill:#6180c6;fill-opacity:1" + fill="#F49C52" /> + <rect + width="236" + height="236" + rx="47" + ry="47" + x="10" + y="10" + id="rect24" + style="fill-opacity:1.0;fill:url(#linearGradient3750)" + fill="url(#RSSg)" /> + <g + id="g3289" + style="fill:#000000;fill-opacity:1;stroke:none;stroke-opacity:1;filter:url(#filter3758)" + transform="matrix(-0.5614008,-0.5989944,-0.5948616,0.565301,279.23409,118.24669)"> + <circle + style="fill:#000000;fill-opacity:1;stroke:none;stroke-opacity:1" + id="circle3291" + r="24" + cy="189" + cx="68" + sodipodi:cx="68" + sodipodi:cy="189" + sodipodi:rx="24" + sodipodi:ry="24" /> + <path + style="fill:#000000;fill-opacity:1;stroke:none;stroke-opacity:1" + id="path3293" + d="M 160,213 L 126,213 C 126,167.71265 89.287349,131 44,131 L 44,97 C 108.06503,97 160,148.93497 160,213 z" /> + <path + style="opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-opacity:1" + id="path3295" + d="M 184,213 C 184,135.68014 121.31986,73 44,73 L 44,38 C 140.64983,38 219,116.35017 219,213 L 184,213 z" /> + </g> + <g + id="g3236" + style="stroke:#000000;stroke-opacity:1" + transform="matrix(-0.5614008,-0.5989945,-0.5948617,0.565301,277.11073,108.90355)"> + <circle + style="fill:url(#linearGradient3275);fill-opacity:1;stroke:#000000;stroke-opacity:1" + id="circle26" + r="24" + cy="189" + cx="68" + sodipodi:cx="68" + sodipodi:cy="189" + sodipodi:rx="24" + sodipodi:ry="24" /> + <path + style="fill:url(#linearGradient3277);fill-opacity:1;stroke:#000000;stroke-opacity:1" + id="path28" + d="M 160,213 L 126,213 C 126,167.71265 89.287349,131 44,131 L 44,97 C 108.06503,97 160,148.93497 160,213 z" /> + <path + style="opacity:1;fill:url(#linearGradient3279);fill-opacity:1.0;stroke:#000000;stroke-opacity:1" + id="path30" + d="M 184,213 C 184,135.68014 121.31986,73 44,73 L 44,38 C 140.64983,38 219,116.35017 219,213 L 184,213 z" /> + </g> +</svg>
--- a/src/streambrowser/shoutcast.h Wed Jul 09 22:25:31 2008 +0200 +++ b/src/streambrowser/shoutcast.h Wed Jul 09 22:26:30 2008 +0200 @@ -5,16 +5,16 @@ #include "streambrowser.h" #include "streamdir.h" -#define SHOUTCAST_NAME "Shoutcast" -#define SHOUTCAST_ICON DATA_DIR G_DIR_SEPARATOR_S "images" G_DIR_SEPARATOR_S "shoutcast.png" +#define SHOUTCAST_NAME "Shoutcast" +#define SHOUTCAST_ICON DATA_DIR G_DIR_SEPARATOR_S "images" G_DIR_SEPARATOR_S "shoutcast.png" #define SHOUTCAST_STREAMDIR_URL "http://www.shoutcast.com/sbin/newxml.phtml" #define SHOUTCAST_CATEGORY_URL "http://www.shoutcast.com/sbin/newxml.phtml?genre=%s" #define SHOUTCAST_STREAMINFO_URL "http://www.shoutcast.com/sbin/shoutcast-playlist.pls?rn=%s&file=filename.pls" #define SHOUTCAST_BUFFER_SIZE 256 -gboolean shoutcast_category_fetch(category_t *category); -streamdir_t* shoutcast_streamdir_fetch(); +gboolean shoutcast_category_fetch(category_t *category); +streamdir_t* shoutcast_streamdir_fetch(); #endif // SHOUTCAST_H
--- a/src/streambrowser/streambrowser.c Wed Jul 09 22:25:31 2008 +0200 +++ b/src/streambrowser/streambrowser.c Wed Jul 09 22:26:30 2008 +0200 @@ -154,14 +154,14 @@ static void gui_init() { /* the plugin services menu */ - playlist_menu_item = gtk_image_menu_item_new_with_label("Streambrowser"); - gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(playlist_menu_item), gtk_image_new_from_stock(GTK_STOCK_CDROM, GTK_ICON_SIZE_MENU)); + playlist_menu_item = gtk_image_menu_item_new_with_label(_("Streambrowser")); + gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(playlist_menu_item), gtk_image_new_from_file(STREAMBROWSER_ICON_SMALL)); gtk_widget_show(playlist_menu_item); g_signal_connect(G_OBJECT(playlist_menu_item), "activate", G_CALLBACK(on_plugin_services_menu_item_click), NULL); audacious_menu_plugin_item_add(AUDACIOUS_MENU_PLAYLIST_RCLICK, playlist_menu_item); - main_menu_item = gtk_image_menu_item_new_with_label("Streambrowser"); - gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(main_menu_item), gtk_image_new_from_stock(GTK_STOCK_CDROM, GTK_ICON_SIZE_MENU)); + main_menu_item = gtk_image_menu_item_new_with_label(_("Streambrowser")); + gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(main_menu_item), gtk_image_new_from_file(STREAMBROWSER_ICON_SMALL)); gtk_widget_show(main_menu_item); g_signal_connect(G_OBJECT(main_menu_item), "activate", G_CALLBACK(on_plugin_services_menu_item_click), NULL); audacious_menu_plugin_item_add(AUDACIOUS_MENU_MAIN, main_menu_item); @@ -304,10 +304,15 @@ else if (data->category != NULL) { /* 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(); } } @@ -336,7 +341,7 @@ g_free(data); - /* check to see if there are pending update requests */ + /* check to see if there are queued update requests */ data = NULL; g_mutex_lock(update_thread_mutex);
--- a/src/streambrowser/streambrowser.h Wed Jul 09 22:25:31 2008 +0200 +++ b/src/streambrowser/streambrowser.h Wed Jul 09 22:26:30 2008 +0200 @@ -7,10 +7,12 @@ #include <config.h> #include <audacious/i18n.h> -#define DEF_STRING_LEN 1024 -#define DEF_BUFFER_SIZE 512 -#define MAX_UPDATE_THREADS 4 -#define PLAYLIST_TEMP_FILE "file:///tmp/playlist.pls" +#define DEF_STRING_LEN 1024 +#define DEF_BUFFER_SIZE 512 +#define MAX_UPDATE_THREADS 4 +#define PLAYLIST_TEMP_FILE "file:///tmp/playlist.pls" +#define STREAMBROWSER_ICON_SMALL DATA_DIR G_DIR_SEPARATOR_S "images" G_DIR_SEPARATOR_S "streambrowser-16x16.png" +#define STREAMBROWSER_ICON DATA_DIR G_DIR_SEPARATOR_S "images" G_DIR_SEPARATOR_S "streambrowser-64x64.png" typedef struct {
--- a/src/streambrowser/streamdir.h Wed Jul 09 22:25:31 2008 +0200 +++ b/src/streambrowser/streamdir.h Wed Jul 09 22:26:30 2008 +0200 @@ -2,7 +2,6 @@ #ifndef STREAMDIR_H #define STREAMDIR_H - #include <glib.h> #include "streambrowser.h" @@ -31,7 +30,7 @@ } streamdir_t; -streamdir_t* streamdir_new(gchar *name); +streamdir_t* streamdir_new(gchar *name); void streamdir_delete(streamdir_t *streamdir); category_t* category_new(gchar *name); @@ -43,13 +42,13 @@ gint category_get_count(streamdir_t *streamdir); gint category_get_index(streamdir_t *streamdir, category_t *category); -streaminfo_t* streaminfo_new(gchar *name, gchar *playlist_url, gchar *current_track); +streaminfo_t* streaminfo_new(gchar *name, gchar *playlist_url, gchar *current_track); void streaminfo_delete(streaminfo_t *streaminfo); void streaminfo_free(streaminfo_t *streaminfo); void streaminfo_add(category_t *category, streaminfo_t *streaminfo); void streaminfo_remove(category_t *category, streaminfo_t *streaminfo); -streaminfo_t* streaminfo_get_by_index(category_t *category, gint index); -streaminfo_t* streaminfo_get_by_name(category_t *category, gchar *name); +streaminfo_t* streaminfo_get_by_index(category_t *category, gint index); +streaminfo_t* streaminfo_get_by_name(category_t *category, gchar *name); gint streaminfo_get_count(category_t *category); gint streaminfo_get_index(category_t *category, streaminfo_t *streaminfo);