# HG changeset patch # User mf0102 <0102@gmx.at> # Date 1215635190 -7200 # Node ID f3e242d1855bf52a987e7edced0c8645a3ffdcef # Parent 14a58e80ecfe48688a8f74b80835ae43b9aee7a1# Parent f9c6a9cb442e9a4414489ef761d02af982c036a1 merge diff -r 14a58e80ecfe -r f3e242d1855b src/skins/Makefile --- 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 \ diff -r 14a58e80ecfe -r f3e242d1855b src/skins/ui_playlist.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 diff -r 14a58e80ecfe -r f3e242d1855b src/skins/ui_playlist_manager.c --- /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 . + * + * 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 +#include "ui_main.h" + +#include +#include +#include +#include + + +#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 */ +} diff -r 14a58e80ecfe -r f3e242d1855b src/skins/ui_playlist_manager.h --- /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 . + * + * 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 */ diff -r 14a58e80ecfe -r f3e242d1855b src/streambrowser/Makefile --- 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 diff -r 14a58e80ecfe -r f3e242d1855b src/streambrowser/gui/streambrowser_win.c --- 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, "%s", 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, }; diff -r 14a58e80ecfe -r f3e242d1855b src/streambrowser/gui/streambrowser_win.h --- 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 diff -r 14a58e80ecfe -r f3e242d1855b src/streambrowser/images/streambrowser-16x16.png Binary file src/streambrowser/images/streambrowser-16x16.png has changed diff -r 14a58e80ecfe -r f3e242d1855b src/streambrowser/images/streambrowser-64x64.png Binary file src/streambrowser/images/streambrowser-64x64.png has changed diff -r 14a58e80ecfe -r f3e242d1855b src/streambrowser/images/streambrowser.svg --- /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 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff -r 14a58e80ecfe -r f3e242d1855b src/streambrowser/shoutcast.h --- 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 diff -r 14a58e80ecfe -r f3e242d1855b src/streambrowser/streambrowser.c --- 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); diff -r 14a58e80ecfe -r f3e242d1855b src/streambrowser/streambrowser.h --- 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 #include -#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 { diff -r 14a58e80ecfe -r f3e242d1855b src/streambrowser/streamdir.h --- 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 #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);