/** * Copyright (c) 2007 洪任諭 (PCMan) * * 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; either version 2 of the License, or * (at your option) any later version. * * 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, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include #include #include #include #include #include #include #include "eggtrayicon.h" #define LIBDIR PREFIX"/lib/gtkhirad" static const char* current = NULL; static GPid pid = 0; static void kill_player() { int status; kill ( pid, SIGTERM ); waitpid( pid, &status, 0 ); pid = 0; } static void play_radio( const char* url ) { char cmd[1024]; char* argv[3] = { LIBDIR"/play.pl", NULL, NULL }; GError* err = NULL; argv[1] = url; if( pid ) kill_player(); g_spawn_async( NULL, argv, NULL, G_SPAWN_SEARCH_PATH/*|G_SPAWN_STDOUT_TO_DEV_NULL|G_SPAWN_STDERR_TO_DEV_NULL*/, NULL, NULL, &pid, &err ); if( err ) { GtkWidget* msg; msg = gtk_message_dialog_new(NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, err->message ); g_error_free( err ); } } static void on_update_menu( GtkWidget* item, gpointer user_data ) { GtkWidget* dlg; g_spawn_command_line_sync( LIBDIR"/update_menu.pl", NULL, NULL, NULL, NULL ); dlg = gtk_message_dialog_new( NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_INFO, GTK_BUTTONS_OK, "電台清單更新完成!" ); gtk_dialog_run( dlg ); gtk_widget_destroy( dlg ); } static void on_menu( GtkWidget* item, gpointer user_data ) { int i; char cmd[1024]; char* url = g_object_get_data(item, "url"); if( ! GTK_CHECK_MENU_ITEM(item)->active ) return; g_free( current ); current = g_strdup( url ); play_radio( url ); } void on_stop( GtkCheckMenuItem* item, gpointer user_data ) { if( item->active ) { kill_player(); current = NULL; } } void on_tray_icon_button_press_event( GtkWidget* widget, GdkEventButton* evt, gpointer user_data ) { GtkMenu* menu = gtk_menu_new(); GtkMenuItem* menu_item; int i; FILE* fi; GSList* group = NULL; char buf[1024], *name, *url; gchar* dir=g_build_filename( g_get_home_dir(), ".gtkhirad", NULL ); g_chdir( dir ); g_free( dir ); if( !(fi=fopen("menu", "r")) ) return; menu_item = gtk_radio_menu_item_new_with_label( group, "停止播放" ); group = gtk_radio_menu_item_get_group( menu_item ); gtk_menu_shell_append( menu, menu_item ); g_signal_connect( menu_item, "toggled", on_stop, NULL ); menu_item = gtk_image_menu_item_new_with_label( "線上更新電台清單" ); gtk_menu_shell_append( menu, menu_item ); g_signal_connect( menu_item, "activate", on_update_menu, NULL ); gtk_menu_shell_append( menu, gtk_separator_menu_item_new() ); GtkWidget* category = NULL; while( fgets( buf, sizeof(buf), fi ) ) { name = strtok( buf, "\r\n"); name = strtok( name, "\t" ); if( name ) url=strtok( NULL, "\r\n"); else url = NULL; // g_debug( "name=%s", name ); if( ! url ) { if( name && isdigit( *name ) ) { char imgf[32]; GtkWidget* img; GdkPixbuf* pix; menu_item = gtk_menu_item_new(); g_snprintf( imgf, sizeof(imgf)/sizeof(char), "%s.gif", buf ); pix = gdk_pixbuf_new_from_file_at_scale( imgf, -1, 24, TRUE, NULL ); //g_debug( "imgf=%s, pix=%p, %s", imgf, pix, err ? err->message : "" ); img = gtk_image_new_from_pixbuf( pix ); g_object_unref( pix ); gtk_container_add( menu_item, img ); gtk_widget_show( img ); category = gtk_menu_new(); gtk_menu_item_set_submenu( menu_item, category ); gtk_menu_shell_append( menu, menu_item ); } } else if( name ) { if( !category ) continue; menu_item = gtk_radio_menu_item_new_with_label( group, name ); group = gtk_radio_menu_item_get_group( menu_item ); g_object_set_data_full( menu_item, "url", g_strdup(url), g_free ); if( current && 0 == strcmp( url, current ) ) gtk_check_menu_item_set_active( menu_item, TRUE ); g_signal_connect( menu_item, "toggled", on_menu, NULL ); gtk_menu_shell_append( category, menu_item ); } else { category = NULL; } } fclose( fi ); gtk_menu_shell_append( menu, gtk_separator_menu_item_new() ); menu_item = gtk_image_menu_item_new_from_stock( GTK_STOCK_QUIT, NULL ); gtk_menu_shell_append( menu, menu_item ); g_signal_connect( menu_item, "activate", gtk_main_quit, NULL ); g_signal_connect( menu, "selection-done", gtk_widget_destroy, NULL ); gtk_widget_show_all( menu ); gtk_menu_popup( menu, NULL, NULL, NULL, NULL, evt->button, evt->time ); } static void check_menu() { char* menu = g_build_filename( g_get_home_dir(), ".gtkhirad/menu", NULL ); if( !g_file_test(menu, G_FILE_TEST_EXISTS) ) { g_spawn_command_line_sync( LIBDIR"/update_menu.pl", NULL, NULL, NULL, NULL ); } } int main( int argc, char** argv ) { GtkWidget *icon; GtkWidget *evt_box; GtkTooltips *tooltips; EggTrayIcon *tray_icon; gtk_init( &argc, &argv ); check_menu(); tooltips = gtk_tooltips_new (); tray_icon = egg_tray_icon_new ("GtkHiRad 電台點播器"); evt_box = gtk_event_box_new (); gtk_container_add (GTK_CONTAINER (tray_icon), evt_box); g_signal_connect (G_OBJECT (evt_box), "button-press-event", G_CALLBACK (on_tray_icon_button_press_event), NULL); gtk_tooltips_set_tip (GTK_TOOLTIPS(tooltips), evt_box, "GtkHiRad 電台點播器", NULL); icon = gtk_image_new_from_icon_name( "gtkhirad", GTK_ICON_SIZE_MENU ); gtk_container_add (GTK_CONTAINER (evt_box), icon); gtk_widget_show_all (GTK_WIDGET (tray_icon)); gtk_main(); if( pid > 0 ) kill_player(); return 0; }