X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=plugins%2Fgnome%2Fintf_gnome.c;h=14a6afbd8324bb12c15dbb4bab3aa24b09618f07;hb=a70f8bb371466209770c4c3bcdb7137b94acef66;hp=9021e0635efeada030ba8cb20da033f0dcb8a463;hpb=93ca3031ee75338ae1eb922b74cbfe7ee0dc66b8;p=vlc diff --git a/plugins/gnome/intf_gnome.c b/plugins/gnome/intf_gnome.c index 9021e0635e..14a6afbd83 100644 --- a/plugins/gnome/intf_gnome.c +++ b/plugins/gnome/intf_gnome.c @@ -2,9 +2,10 @@ * intf_gnome.c: Gnome interface ***************************************************************************** * Copyright (C) 1999, 2000 VideoLAN - * $Id: intf_gnome.c,v 1.21 2001/03/15 00:37:04 stef Exp $ + * $Id: intf_gnome.c,v 1.34 2001/05/01 04:18:18 sam Exp $ * * Authors: Samuel Hocevar + * Stéphane Borel * * 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 @@ -48,11 +49,12 @@ #include "intf_msg.h" #include "interface.h" +#include "intf_playlist.h" -#include "gnome_sys.h" #include "gnome_callbacks.h" #include "gnome_interface.h" #include "gnome_support.h" +#include "intf_gnome.h" #include "main.h" @@ -69,9 +71,15 @@ static gint GnomeLanguageMenus( gpointer, GtkWidget *, es_descriptor_t *, gint, void (*pf_toggle)(GtkCheckMenuItem *, gpointer) ); static gint GnomeChapterMenu ( gpointer, GtkWidget *, void (*pf_toggle)(GtkCheckMenuItem *, gpointer) ); +static gint GnomeAngleMenu ( gpointer, GtkWidget *, + void (*pf_toggle)(GtkCheckMenuItem *, gpointer) ); static gint GnomeTitleMenu ( gpointer, GtkWidget *, void (*pf_toggle)(GtkCheckMenuItem *, gpointer) ); static gint GnomeSetupMenu ( intf_thread_t * p_intf ); +static void GnomeDisplayDate ( GtkAdjustment *p_adj ); +static gint GnomeDiscModeManage( intf_thread_t * p_intf ); +static gint GnomeFileModeManage( intf_thread_t * p_intf ); +static gint GnomeNetworkModeManage( intf_thread_t * p_intf ); /***************************************************************************** * g_atexit: kludge to avoid the Gnome thread to segfault at exit @@ -122,6 +130,11 @@ static int intf_Probe( probedata_t *p_data ) return( 999 ); } + if( TestProgram( "gnome-vlc" ) ) + { + return( 200 ); + } + return( 100 ); } @@ -142,16 +155,15 @@ static int intf_Open( intf_thread_t *p_intf ) p_intf->p_sys->b_popup_changed = 0; p_intf->p_sys->b_window_changed = 0; p_intf->p_sys->b_playlist_changed = 0; - p_intf->p_sys->b_menus_update = 1; - p_intf->p_sys->b_scale_isfree = 1; + p_intf->p_sys->b_slider_free = 1; + + p_intf->p_sys->b_mode_changed = 1; + p_intf->p_sys->i_intf_mode = FILE_MODE; p_intf->p_sys->pf_gtk_callback = NULL; p_intf->p_sys->pf_gdk_callback = NULL; - /* Initialize lock */ - vlc_mutex_init( &p_intf->p_sys->change_lock ); - return( 0 ); } @@ -160,9 +172,6 @@ static int intf_Open( intf_thread_t *p_intf ) *****************************************************************************/ static void intf_Close( intf_thread_t *p_intf ) { - /* Destroy lock */ - vlc_mutex_destroy( &p_intf->p_sys->change_lock ); - /* Destroy structure */ free( p_intf->p_sys ); } @@ -180,20 +189,26 @@ static void intf_Run( intf_thread_t *p_intf ) /* gnome_init needs to know the command line. We don't care, so we * give it an empty one */ char *p_args[] = { "" }; + int i_args = 1; /* The data types we are allowed to receive */ static GtkTargetEntry target_table[] = { { "text/uri-list", 0, DROP_ACCEPT_TEXT_URI_LIST }, - { "text/plain", 0, DROP_ACCEPT_TEXT_PLAIN } + { "text/plain", 0, DROP_ACCEPT_TEXT_PLAIN } }; + /* intf_Manage callback timeout */ + int i_timeout; + /* Initialize Gnome */ - gnome_init( p_main->psz_arg0, VERSION, 1, p_args ); + gnome_init( p_main->psz_arg0, VERSION, i_args, p_args ); /* Create some useful widgets that will certainly be used */ p_intf->p_sys->p_window = create_intf_window( ); p_intf->p_sys->p_popup = create_intf_popup( ); + p_intf->p_sys->p_disc = create_intf_disc( ); + p_intf->p_sys->p_network = create_intf_network( ); /* Set the title of the main window */ gtk_window_set_title( GTK_WINDOW(p_intf->p_sys->p_window), @@ -204,12 +219,30 @@ static void intf_Run( intf_thread_t *p_intf ) GTK_DEST_DEFAULT_ALL, target_table, 1, GDK_ACTION_COPY ); + /* Get the interface labels */ + #define P_LABEL( name ) GTK_LABEL( gtk_object_get_data( \ + GTK_OBJECT( p_intf->p_sys->p_window ), name ) ) + p_intf->p_sys->p_label_date = P_LABEL( "label_date" ); + p_intf->p_sys->p_label_status = P_LABEL( "label_status" ); + p_intf->p_sys->p_label_title = P_LABEL( "label_title" ); + p_intf->p_sys->p_label_chapter = P_LABEL( "label_chapter" ); + #undef P_LABEL + + /* Connect the date display to the slider */ + #define P_SLIDER GTK_RANGE( gtk_object_get_data( \ + GTK_OBJECT( p_intf->p_sys->p_window ), "slider" ) ) + p_intf->p_sys->p_adj = gtk_range_get_adjustment( P_SLIDER ); + + gtk_signal_connect ( GTK_OBJECT( p_intf->p_sys->p_adj ), "value_changed", + GTK_SIGNAL_FUNC( GnomeDisplayDate ), NULL ); + p_intf->p_sys->f_adj_oldvalue = 0; + #undef P_SLIDER + /* We don't create these ones yet because we perhaps won't need them */ p_intf->p_sys->p_about = NULL; p_intf->p_sys->p_playlist = NULL; p_intf->p_sys->p_modules = NULL; p_intf->p_sys->p_fileopen = NULL; - p_intf->p_sys->p_disc = NULL; /* Store p_intf to keep an eye on it */ gtk_object_set_data( GTK_OBJECT(p_intf->p_sys->p_window), @@ -218,27 +251,40 @@ static void intf_Run( intf_thread_t *p_intf ) gtk_object_set_data( GTK_OBJECT(p_intf->p_sys->p_popup), "p_intf", p_intf ); + gtk_object_set_data( GTK_OBJECT(p_intf->p_sys->p_disc), + "p_intf", p_intf ); + + gtk_object_set_data( GTK_OBJECT(p_intf->p_sys->p_network), + "p_intf", p_intf ); + + gtk_object_set_data( GTK_OBJECT(p_intf->p_sys->p_adj), + "p_intf", p_intf ); + /* Show the control window */ gtk_widget_show( p_intf->p_sys->p_window ); /* Sleep to avoid using all CPU - since some interfaces needs to access * keyboard events, a 100ms delay is a good compromise */ - p_intf->p_sys->i_timeout = gtk_timeout_add( INTF_IDLE_SLEEP / 1000, - GnomeManage, p_intf ); - + i_timeout = gtk_timeout_add( INTF_IDLE_SLEEP / 1000, GnomeManage, p_intf ); /* Enter gnome mode */ gtk_main(); - /* launch stored callbacks */ + /* Remove the timeout */ + gtk_timeout_remove( i_timeout ); + + /* Get rid of stored callbacks so we can unload the plugin */ if( p_intf->p_sys->pf_gtk_callback != NULL ) { - p_intf->p_sys->pf_gtk_callback(); + p_intf->p_sys->pf_gtk_callback( ); + p_intf->p_sys->pf_gtk_callback = NULL; - if( p_intf->p_sys->pf_gdk_callback != NULL ) - { - p_intf->p_sys->pf_gdk_callback(); - } + } + + if( p_intf->p_sys->pf_gdk_callback != NULL ) + { + p_intf->p_sys->pf_gdk_callback( ); + p_intf->p_sys->pf_gdk_callback = NULL; } } @@ -252,9 +298,9 @@ static void intf_Run( intf_thread_t *p_intf ) *****************************************************************************/ static gint GnomeManage( gpointer p_data ) { - intf_thread_t *p_intf = (void *)p_data; +#define p_intf ((intf_thread_t *)p_data) - vlc_mutex_lock( &p_intf->p_sys->change_lock ); + vlc_mutex_lock( &p_intf->change_lock ); /* If the "display popup" flag has changed */ if( p_intf->b_menu_change ) @@ -264,34 +310,96 @@ static gint GnomeManage( gpointer p_data ) p_intf->b_menu_change = 0; } - /* Update language/chapter menus after user request */ - if( p_intf->p_input != NULL && p_intf->p_sys->p_window != NULL && - p_intf->p_sys->b_menus_update ) + if( p_intf->p_input != NULL ) { + GtkWidget * p_slider; + float newvalue; + +// vlc_mutex_lock( &p_intf->p_input->stream.stream_lock ); + /* New input or stream map change */ + if( p_intf->p_input->stream.b_changed || p_intf->p_sys->b_mode_changed ) + { + switch( p_intf->p_input->stream.i_method & 0xf0 ) + { + case INPUT_METHOD_FILE: + GnomeFileModeManage( p_intf ); + break; + case INPUT_METHOD_DISC: + GnomeDiscModeManage( p_intf ); + break; + case INPUT_METHOD_NETWORK: + GnomeNetworkModeManage( p_intf ); + break; + default: + intf_ErrMsg( "intf error: can't determine input method" ); + break; + } + p_slider = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT( + p_intf->p_sys->p_window ), "slider" ) ); + + if( p_intf->p_input->stream.b_seekable ) + { + gtk_widget_show( GTK_WIDGET( p_slider ) ); + } + else + { + gtk_widget_hide( GTK_WIDGET( p_slider ) ); + } + + /* get ready for menu regeneration */ + p_intf->p_sys->b_title_update = 1; + p_intf->p_sys->b_chapter_update = 1; + p_intf->p_sys->b_angle_update = 1; + p_intf->p_sys->b_audio_update = 1; + p_intf->p_sys->b_spu_update = 1; + p_intf->p_sys->i_part = 0; + + p_intf->p_input->stream.b_changed = 0; + p_intf->p_sys->b_mode_changed = 0; + intf_WarnMsg( 2, + "intf info: menus refreshed as stream has changed" ); + + } + +// vlc_mutex_unlock( &p_intf->p_input->stream.stream_lock ); + + /* Update language/chapter menus after user request */ GnomeSetupMenu( p_intf ); - } - /* Manage the slider */ - if( p_intf->p_input != NULL && p_intf->p_sys->p_window != NULL - && p_intf->p_sys->b_scale_isfree ) - { - GtkWidget *p_scale; - GtkAdjustment *p_adj; - - p_scale = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT( - p_intf->p_sys->p_window ), "hscale" ) ); - p_adj = gtk_range_get_adjustment ( GTK_RANGE( p_scale ) ); - - /* Update the value */ - p_adj->value = ( 100. * - p_intf->p_input->stream.p_selected_area->i_tell ) / - p_intf->p_input->stream.p_selected_area->i_size; - - /* Gtv does it this way. Why not. */ - gtk_range_set_adjustment ( GTK_RANGE( p_scale ), p_adj ); - gtk_range_slider_update ( GTK_RANGE( p_scale ) ); - gtk_range_clear_background ( GTK_RANGE( p_scale ) ); - gtk_range_draw_background ( GTK_RANGE( p_scale ) ); +#define p_area p_intf->p_input->stream.p_selected_area + /* Update menus when chapter changes */ + p_intf->p_sys->b_chapter_update = + ( p_intf->p_sys->i_part != p_area->i_part ); + + if( p_intf->p_input->stream.b_seekable ) + { + /* Manage the slider */ + newvalue = p_intf->p_sys->p_adj->value; + + /* If the user hasn't touched the slider since the last time, + * then the input can safely change it */ + if( newvalue == p_intf->p_sys->f_adj_oldvalue ) + { + /* Update the value */ + p_intf->p_sys->p_adj->value = p_intf->p_sys->f_adj_oldvalue = + ( 100. * p_area->i_tell ) / p_area->i_size; + + gtk_signal_emit_by_name( GTK_OBJECT( p_intf->p_sys->p_adj ), + "value_changed" ); + } + /* Otherwise, send message to the input if the user has + * finished dragging the slider */ + else if( p_intf->p_sys->b_slider_free ) + { + off_t i_seek = ( newvalue * p_area->i_size ) / 100; + + input_Seek( p_intf->p_input, i_seek ); + + /* Update the old value */ + p_intf->p_sys->f_adj_oldvalue = newvalue; + } + } +#undef p_area } /* Manage core vlc functions through the callback */ @@ -299,19 +407,20 @@ static gint GnomeManage( gpointer p_data ) if( p_intf->b_die ) { - /* Make sure we won't be called again */ - gtk_timeout_remove( p_intf->p_sys->i_timeout ); - - vlc_mutex_unlock( &p_intf->p_sys->change_lock ); + vlc_mutex_unlock( &p_intf->change_lock ); /* Prepare to die, young Skywalker */ gtk_main_quit(); + + /* Just in case */ return( FALSE ); } - vlc_mutex_unlock( &p_intf->p_sys->change_lock ); + vlc_mutex_unlock( &p_intf->change_lock ); return( TRUE ); + +#undef p_intf } /***************************************************************************** @@ -326,19 +435,18 @@ static gint GnomeManage( gpointer p_data ) static gint GnomeLanguageMenus( gpointer p_data, GtkWidget * p_root, es_descriptor_t * p_es, - gint i_type, + gint i_cat, void(*pf_toggle )( GtkCheckMenuItem *, gpointer ) ) { +#define GNOME_LANGUAGE_MENU_SIZE 64 intf_thread_t * p_intf; GtkWidget * p_menu; GtkWidget * p_separator; GtkWidget * p_item; - GtkWidget * p_item_off; + GtkWidget * p_item_active; GSList * p_group; - char * psz_name; - gint b_active; - gint b_audio; - gint b_spu; + char psz_name[ GNOME_LANGUAGE_MENU_SIZE ]; + gint i_item; gint i; @@ -346,52 +454,63 @@ static gint GnomeLanguageMenus( gpointer p_data, /* cast */ p_intf = (intf_thread_t *)p_data; - vlc_mutex_lock( &p_intf->p_input->stream.stream_lock ); - /* removes previous menu */ gtk_menu_item_remove_submenu( GTK_MENU_ITEM( p_root ) ); + gtk_widget_set_sensitive( p_root, FALSE ); - b_audio = ( i_type == 1 ); p_group = NULL; /* menu container */ p_menu = gtk_menu_new(); /* special case for "off" item */ - b_active = ( p_es == NULL ) ? TRUE : FALSE; - psz_name = "Off"; + snprintf( psz_name, GNOME_LANGUAGE_MENU_SIZE, "Off" ); + psz_name[ GNOME_LANGUAGE_MENU_SIZE - 1 ] = '\0'; - p_item_off = gtk_radio_menu_item_new_with_label( p_group, psz_name ); - p_group = gtk_radio_menu_item_group( GTK_RADIO_MENU_ITEM( p_item_off ) ); - gtk_widget_show( p_item_off ); - gtk_check_menu_item_set_active( GTK_CHECK_MENU_ITEM( p_item_off ), - b_active ); - gtk_menu_append( GTK_MENU( p_menu ), p_item_off ); + p_item = gtk_radio_menu_item_new_with_label( p_group, psz_name ); + p_group = gtk_radio_menu_item_group( GTK_RADIO_MENU_ITEM( p_item ) ); + + gtk_widget_show( p_item ); + + /* signal hanling for off */ + gtk_signal_connect( GTK_OBJECT( p_item ), "toggled", + GTK_SIGNAL_FUNC ( pf_toggle ), NULL ); + + gtk_menu_append( GTK_MENU( p_menu ), p_item ); p_separator = gtk_menu_item_new(); + gtk_widget_set_sensitive( p_separator, FALSE ); gtk_widget_show( p_separator ); gtk_menu_append( GTK_MENU( p_menu ), p_separator ); - gtk_widget_set_sensitive( p_separator, FALSE ); + + vlc_mutex_lock( &p_intf->p_input->stream.stream_lock ); + p_item_active = NULL; + i_item = 0; /* create a set of language buttons and append them to the container */ for( i = 0 ; i < p_intf->p_input->stream.i_es_number ; i++ ) { - - b_audio = ( i_type == 1 ) && p_intf->p_input->stream.pp_es[i]->b_audio; - b_spu = ( i_type == 2 ) && p_intf->p_input->stream.pp_es[i]->b_spu; - - if( b_audio || b_spu ) + if( p_intf->p_input->stream.pp_es[i]->i_cat == i_cat ) { - b_active = ( p_es == p_intf->p_input->stream.pp_es[i] ) ? TRUE : - FALSE; - psz_name = p_intf->p_input->stream.pp_es[i]->psz_desc; + i_item++; + strcpy( psz_name, p_intf->p_input->stream.pp_es[i]->psz_desc ); + if( psz_name[0] == '\0' ) + { + snprintf( psz_name, GNOME_LANGUAGE_MENU_SIZE, + "Language %d", i_item ); + psz_name[ GNOME_LANGUAGE_MENU_SIZE - 1 ] = '\0'; + } p_item = gtk_radio_menu_item_new_with_label( p_group, psz_name ); p_group = gtk_radio_menu_item_group( GTK_RADIO_MENU_ITEM( p_item ) ); - gtk_check_menu_item_set_active( GTK_CHECK_MENU_ITEM( p_item ), - b_active ); - gtk_menu_append( GTK_MENU( p_menu ), p_item ); + + if( p_es == p_intf->p_input->stream.pp_es[i] ) + { + /* don't lose p_item when we append into menu */ + p_item_active = p_item; + } + gtk_widget_show( p_item ); /* setup signal hanling */ @@ -399,21 +518,101 @@ static gint GnomeLanguageMenus( gpointer p_data, GTK_SIGNAL_FUNC( pf_toggle ), (gpointer)( p_intf->p_input->stream.pp_es[i] ) ); + gtk_menu_append( GTK_MENU( p_menu ), p_item ); } } - /* signal hanling for off - dunno why this does not work - * if it is before the loop */ - gtk_signal_connect( GTK_OBJECT( p_item_off ), "toggled", - GTK_SIGNAL_FUNC ( pf_toggle ), NULL ); + vlc_mutex_unlock( &p_intf->p_input->stream.stream_lock ); /* link the new menu to the menubar item */ gtk_menu_item_set_submenu( GTK_MENU_ITEM( p_root ), p_menu ); - /* be sure that menu is sensitive */ - gtk_widget_set_sensitive( p_root, TRUE ); + /* acitvation will call signals so we can only do it + * when submenu is attached to menu - to get intf_window */ + if( p_item_active != NULL ) + { + gtk_check_menu_item_set_active( GTK_CHECK_MENU_ITEM( p_item_active ), + TRUE ); + } - vlc_mutex_unlock( &p_intf->p_input->stream.stream_lock ); + /* be sure that menu is sensitive if non empty */ + if( i_item > 0 ) + { + gtk_widget_set_sensitive( p_root, TRUE ); + } + + return TRUE; +} + +/***************************************************************************** + * GnomeAngleMenu: generate angle menu for current title + *****************************************************************************/ +static gint GnomeAngleMenu( gpointer p_data, GtkWidget * p_angle, + void(*pf_toggle)( GtkCheckMenuItem *, gpointer ) ) +{ +#define GNOME_ANGLE_MENU_SIZE 64 + intf_thread_t * p_intf; + char psz_name[ GNOME_ANGLE_MENU_SIZE ]; + GtkWidget * p_angle_menu; + GSList * p_angle_group; + GtkWidget * p_item; + GtkWidget * p_item_active; + gint i_angle; + + /* cast */ + p_intf = (intf_thread_t*)p_data; + + /* removes previous menu */ + gtk_menu_item_remove_submenu( GTK_MENU_ITEM( p_angle ) ); + gtk_widget_set_sensitive( p_angle, FALSE ); + + p_angle_menu = gtk_menu_new();; + p_angle_group = NULL; + p_item = NULL; + p_item_active = NULL; + + for( i_angle = 0 ; + i_angle < p_intf->p_input->stream.p_selected_area->i_angle_nb ; + i_angle++ ) + { + snprintf( psz_name, GNOME_ANGLE_MENU_SIZE, "Angle %d", i_angle + 1 ); + psz_name[ GNOME_ANGLE_MENU_SIZE - 1 ] = '\0'; + + p_item = gtk_radio_menu_item_new_with_label( p_angle_group, + psz_name ); + p_angle_group = + gtk_radio_menu_item_group( GTK_RADIO_MENU_ITEM( p_item ) ); + + if( p_intf->p_input->stream.p_selected_area->i_angle == + ( i_angle + 1 ) ) + { + p_item_active = p_item; + } + + gtk_widget_show( p_item ); + + /* setup signal hanling */ + gtk_signal_connect( GTK_OBJECT( p_item ), + "toggled", + GTK_SIGNAL_FUNC( pf_toggle ), + (gpointer)(i_angle + 1) ); + + gtk_menu_append( GTK_MENU( p_angle_menu ), p_item ); + } + + gtk_menu_item_set_submenu( GTK_MENU_ITEM( p_angle ), p_angle_menu ); + + if( p_item_active != NULL ) + { + gtk_check_menu_item_set_active( GTK_CHECK_MENU_ITEM( p_item_active ), + TRUE ); + } + + /* be sure that menu is sensitive if non empty */ + if( p_intf->p_input->stream.p_selected_area->i_angle_nb > 1 ) + { + gtk_widget_set_sensitive( p_angle, TRUE ); + } return TRUE; } @@ -425,56 +624,109 @@ static gint GnomeChapterMenu( gpointer p_data, GtkWidget * p_chapter, void(*pf_toggle )( GtkCheckMenuItem *, gpointer ) ) { intf_thread_t * p_intf; - char psz_name[10]; + char psz_name[12]; GtkWidget * p_chapter_menu; + GtkWidget * p_chapter_submenu; + GtkWidget * p_menu_item; GtkWidget * p_item; + GtkWidget * p_item_selected; GSList * p_chapter_group; gint i_title; gint i_chapter; - gint b_active; + gint i_nb; /* cast */ p_intf = (intf_thread_t*)p_data; /* removes previous menu */ gtk_menu_item_remove_submenu( GTK_MENU_ITEM( p_chapter ) ); + gtk_widget_set_sensitive( p_chapter, FALSE ); + p_chapter_submenu = NULL; p_chapter_group = NULL; + p_item_selected = NULL; + p_menu_item = NULL; i_title = p_intf->p_input->stream.p_selected_area->i_id; p_chapter_menu = gtk_menu_new(); + i_nb = p_intf->p_input->stream.pp_areas[i_title]->i_part_nb; - for( i_chapter = 0; - i_chapter < p_intf->p_input->stream.pp_areas[i_title]->i_part_nb ; - i_chapter++ ) + for( i_chapter = 0 ; i_chapter < i_nb ; i_chapter++ ) { - b_active = ( p_intf->p_input->stream.pp_areas[i_title]->i_part - == i_chapter + 1 ) ? 1 : 0; - - sprintf( psz_name, "Chapter %d", i_chapter + 1 ); + /* we group chapters in packets of ten for small screens */ + if( ( i_chapter % 10 == 0 ) && ( i_nb > 20 ) ) + { + if( i_chapter != 0 ) + { + gtk_menu_item_set_submenu( GTK_MENU_ITEM( p_menu_item ), + p_chapter_submenu ); + gtk_menu_append( GTK_MENU( p_chapter_menu ), p_menu_item ); + } + + snprintf( psz_name, GNOME_ANGLE_MENU_SIZE, + "%d - %d", i_chapter + 1, i_chapter + 10); + psz_name[ GNOME_ANGLE_MENU_SIZE - 1 ] = '\0'; + p_menu_item = gtk_menu_item_new_with_label( psz_name ); + gtk_widget_show( p_menu_item ); + p_chapter_submenu = gtk_menu_new(); + } + + snprintf( psz_name, GNOME_ANGLE_MENU_SIZE, + "Chapter %d", i_chapter + 1 ); + psz_name[ GNOME_ANGLE_MENU_SIZE - 1 ] = '\0'; p_item = gtk_radio_menu_item_new_with_label( p_chapter_group, psz_name ); p_chapter_group = gtk_radio_menu_item_group( GTK_RADIO_MENU_ITEM( p_item ) ); - gtk_menu_append( GTK_MENU( p_chapter_menu ), p_item ); + + if( p_intf->p_input->stream.pp_areas[i_title]->i_part + == i_chapter + 1 ) + { + p_item_selected = p_item; + } + gtk_widget_show( p_item ); - gtk_check_menu_item_set_active( GTK_CHECK_MENU_ITEM( p_item ), - b_active ); /* setup signal hanling */ gtk_signal_connect( GTK_OBJECT( p_item ), "toggled", GTK_SIGNAL_FUNC( pf_toggle ), (gpointer)(i_chapter + 1) ); + + if( i_nb > 20 ) + { + gtk_menu_append( GTK_MENU( p_chapter_submenu ), p_item ); + } + else + { + gtk_menu_append( GTK_MENU( p_chapter_menu ), p_item ); + } + } + + if( i_nb > 20 ) + { + gtk_menu_item_set_submenu( GTK_MENU_ITEM( p_menu_item ), + p_chapter_submenu ); + gtk_menu_append( GTK_MENU( p_chapter_menu ), p_menu_item ); } /* link the new menu to the title menu item */ gtk_menu_item_set_submenu( GTK_MENU_ITEM( p_chapter ), p_chapter_menu ); - /* be sure that chapter menu is sensitive */ - gtk_widget_set_sensitive( p_chapter, TRUE ); + /* toggle currently selected chapter */ + if( p_item_selected != NULL ) + { + gtk_check_menu_item_set_active( GTK_CHECK_MENU_ITEM( p_item_selected ), + TRUE ); + } + + /* be sure that chapter menu is sensitive, if there are several items */ + if( p_intf->p_input->stream.pp_areas[i_title]->i_part_nb > 1 ) + { + gtk_widget_set_sensitive( p_chapter, TRUE ); + } return TRUE; } @@ -490,100 +742,205 @@ static gint GnomeTitleMenu( gpointer p_data, GtkWidget * p_navigation, void(*pf_toggle )( GtkCheckMenuItem *, gpointer ) ) { +#define GNOME_TITLE_MENU_SIZE 64 intf_thread_t * p_intf; - char psz_name[10]; + char psz_name[ GNOME_TITLE_MENU_SIZE ]; GtkWidget * p_title_menu; + GtkWidget * p_title_submenu; GtkWidget * p_title_item; + GtkWidget * p_item_active; GtkWidget * p_chapter_menu; + GtkWidget * p_chapter_submenu; + GtkWidget * p_title_menu_item; + GtkWidget * p_chapter_menu_item; GtkWidget * p_item; GSList * p_title_group; GSList * p_chapter_group; gint i_title; gint i_chapter; - gint b_active; + gint i_title_nb; + gint i_chapter_nb; /* cast */ p_intf = (intf_thread_t*)p_data; + /* removes previous menu */ + gtk_menu_item_remove_submenu( GTK_MENU_ITEM( p_navigation ) ); + gtk_widget_set_sensitive( p_navigation, FALSE ); + p_title_menu = gtk_menu_new(); p_title_group = NULL; + p_title_submenu = NULL; + p_title_menu_item = NULL; p_chapter_group = NULL; + p_chapter_submenu = NULL; + p_chapter_menu_item = NULL; + p_item_active = NULL; + i_title_nb = p_intf->p_input->stream.i_area_nb; /* loop on titles */ - for( i_title = 1 ; - i_title < p_intf->p_input->stream.i_area_nb ; - i_title++ ) + for( i_title = 1 ; i_title < i_title_nb ; i_title++ ) { - b_active = ( p_intf->p_input->stream.pp_areas[i_title] == - p_intf->p_input->stream.p_selected_area ) ? 1 : 0; - sprintf( psz_name, "Title %d", i_title ); - - p_title_item = gtk_radio_menu_item_new_with_label( p_title_group, - psz_name ); - p_title_group = - gtk_radio_menu_item_group( GTK_RADIO_MENU_ITEM( p_title_item ) ); - gtk_menu_append( GTK_MENU( p_title_menu ), p_title_item ); - gtk_widget_show( p_title_item ); + /* we group titles in packets of ten for small screens */ + if( ( i_title % 10 == 1 ) && ( i_title_nb > 20 ) ) + { + if( i_title != 1 ) + { + gtk_menu_item_set_submenu( GTK_MENU_ITEM( p_title_menu_item ), + p_title_submenu ); + gtk_menu_append( GTK_MENU( p_title_menu ), p_title_menu_item ); + } + + snprintf( psz_name, GNOME_TITLE_MENU_SIZE, + "%d - %d", i_title, i_title + 9 ); + psz_name[ GNOME_TITLE_MENU_SIZE - 1 ] = '\0'; + p_title_menu_item = gtk_menu_item_new_with_label( psz_name ); + gtk_widget_show( p_title_menu_item ); + p_title_submenu = gtk_menu_new(); + } - + snprintf( psz_name, GNOME_TITLE_MENU_SIZE, "Title %d (%d)", i_title, + p_intf->p_input->stream.pp_areas[i_title]->i_part_nb ); + psz_name[ GNOME_TITLE_MENU_SIZE - 1 ] = '\0'; if( pf_toggle == on_menubar_title_toggle ) { + p_title_item = gtk_radio_menu_item_new_with_label( p_title_group, + psz_name ); + p_title_group = + gtk_radio_menu_item_group( GTK_RADIO_MENU_ITEM( p_title_item ) ); + + if( p_intf->p_input->stream.pp_areas[i_title] == + p_intf->p_input->stream.p_selected_area ) + { + p_item_active = p_title_item; + } - gtk_check_menu_item_set_active( GTK_CHECK_MENU_ITEM( p_title_item ), - b_active ); /* setup signal hanling */ gtk_signal_connect( GTK_OBJECT( p_title_item ), "toggled", GTK_SIGNAL_FUNC( pf_toggle ), (gpointer)(p_intf->p_input->stream.pp_areas[i_title]) ); + + if( p_intf->p_input->stream.i_area_nb > 1 ) + { + /* be sure that menu is sensitive */ + gtk_widget_set_sensitive( p_navigation, TRUE ); + } } else { + + p_title_item = gtk_menu_item_new_with_label( psz_name ); p_chapter_menu = gtk_menu_new(); + i_chapter_nb = + p_intf->p_input->stream.pp_areas[i_title]->i_part_nb; - for( i_chapter = 0; - i_chapter < - p_intf->p_input->stream.pp_areas[i_title]->i_part_nb ; - i_chapter++ ) + for( i_chapter = 0 ; i_chapter < i_chapter_nb ; i_chapter++ ) { - b_active = ( p_intf->p_input->stream.pp_areas[i_title]->i_part - == i_chapter + 1 ) ? 1 : 0; - - sprintf( psz_name, "Chapter %d", i_chapter + 1 ); + /* we group chapters in packets of ten for small screens */ + if( ( i_chapter % 10 == 0 ) && ( i_chapter_nb > 20 ) ) + { + if( i_chapter != 0 ) + { + gtk_menu_item_set_submenu( + GTK_MENU_ITEM( p_chapter_menu_item ), + p_chapter_submenu ); + gtk_menu_append( GTK_MENU( p_chapter_menu ), + p_chapter_menu_item ); + } + + snprintf( psz_name, GNOME_TITLE_MENU_SIZE, + "%d - %d", i_chapter + 1, i_chapter + 10 ); + psz_name[ GNOME_TITLE_MENU_SIZE - 1 ] = '\0'; + p_chapter_menu_item = + gtk_menu_item_new_with_label( psz_name ); + gtk_widget_show( p_chapter_menu_item ); + p_chapter_submenu = gtk_menu_new(); + } + + snprintf( psz_name, GNOME_TITLE_MENU_SIZE, + "Chapter %d", i_chapter + 1 ); + psz_name[ GNOME_TITLE_MENU_SIZE - 1 ] = '\0'; p_item = gtk_radio_menu_item_new_with_label( p_chapter_group, psz_name ); p_chapter_group = gtk_radio_menu_item_group( GTK_RADIO_MENU_ITEM( p_item ) ); - gtk_menu_append( GTK_MENU( p_chapter_menu ), p_item ); gtk_widget_show( p_item ); - gtk_check_menu_item_set_active( - GTK_CHECK_MENU_ITEM( p_item ), b_active ); + +#define p_area p_intf->p_input->stream.pp_areas[i_title] + if( ( p_area == p_intf->p_input->stream.p_selected_area ) && + ( p_area->i_part == i_chapter + 1 ) ) + { + p_item_active = p_item; + } +#undef p_area /* setup signal hanling */ gtk_signal_connect( GTK_OBJECT( p_item ), "toggled", GTK_SIGNAL_FUNC( pf_toggle ), (gpointer)( ( i_title * 100 ) + ( i_chapter + 1) ) ); - } - /* link the new menu to the title menu item */ - gtk_menu_item_set_submenu( GTK_MENU_ITEM( p_title_item ), - p_chapter_menu ); + if( i_chapter_nb > 20 ) + { + gtk_menu_append( GTK_MENU( p_chapter_submenu ), p_item ); + } + else + { + gtk_menu_append( GTK_MENU( p_chapter_menu ), p_item ); + } + } + + if( i_chapter_nb > 20 ) + { + gtk_menu_item_set_submenu( GTK_MENU_ITEM( p_chapter_menu_item ), + p_chapter_submenu ); + gtk_menu_append( GTK_MENU( p_chapter_menu ), + p_chapter_menu_item ); + } + + /* link the new menu to the title menu item */ + gtk_menu_item_set_submenu( GTK_MENU_ITEM( p_title_item ), + p_chapter_menu ); + + if( p_intf->p_input->stream.pp_areas[i_title]->i_part_nb > 1 ) + { + /* be sure that menu is sensitive */ + gtk_widget_set_sensitive( p_navigation, TRUE ); + } } + gtk_widget_show( p_title_item ); - /* be sure that chapter menu is sensitive */ - gtk_widget_set_sensitive( p_title_menu, TRUE ); + if( i_title_nb > 20 ) + { + gtk_menu_append( GTK_MENU( p_title_submenu ), p_title_item ); + } + else + { + gtk_menu_append( GTK_MENU( p_title_menu ), p_title_item ); + } + } + if( i_title_nb > 20 ) + { + gtk_menu_item_set_submenu( GTK_MENU_ITEM( p_title_menu_item ), + p_title_submenu ); + gtk_menu_append( GTK_MENU( p_title_menu ), p_title_menu_item ); } + /* be sure that menu is sensitive */ + gtk_widget_set_sensitive( p_title_menu, TRUE ); + /* link the new menu to the menubar item */ gtk_menu_item_set_submenu( GTK_MENU_ITEM( p_navigation ), p_title_menu ); - /* be sure that menu is sensitive */ - gtk_widget_set_sensitive( p_navigation, TRUE ); - + if( p_item_active != NULL ) + { + gtk_check_menu_item_set_active( GTK_CHECK_MENU_ITEM( p_item_active ), + TRUE ); + } return TRUE; } @@ -600,68 +957,237 @@ static gint GnomeSetupMenu( intf_thread_t * p_intf ) GtkWidget * p_popup_menu; gint i; - p_menubar_menu = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT( - p_intf->p_sys->p_window ), "menubar_title" ) ); + p_intf->p_sys->b_chapter_update |= p_intf->p_sys->b_title_update; + p_intf->p_sys->b_angle_update |= p_intf->p_sys->b_title_update; + p_intf->p_sys->b_audio_update |= p_intf->p_sys->b_title_update; + p_intf->p_sys->b_spu_update |= p_intf->p_sys->b_title_update; + + if( p_intf->p_sys->b_title_update ) + { + char psz_title[5]; + + p_menubar_menu = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT( + p_intf->p_sys->p_window ), "menubar_title" ) ); + GnomeTitleMenu( p_intf, p_menubar_menu, on_menubar_title_toggle ); + + snprintf( psz_title, 5, "%d", + p_intf->p_input->stream.p_selected_area->i_id ); + psz_title[ 4 ] = '\0'; + gtk_label_set_text( p_intf->p_sys->p_label_title, psz_title ); + + p_intf->p_sys->b_title_update = 0; + } + + if( p_intf->p_sys->b_chapter_update ) + { + char psz_chapter[5]; + + p_popup_menu = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT( + p_intf->p_sys->p_popup ), "popup_navigation" ) ); + GnomeTitleMenu( p_intf, p_popup_menu, on_popup_navigation_toggle ); + + p_menubar_menu = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT( + p_intf->p_sys->p_window ), "menubar_chapter" ) ); + GnomeChapterMenu( p_intf, p_menubar_menu, on_menubar_chapter_toggle ); - GnomeTitleMenu( p_intf, p_menubar_menu, on_menubar_title_toggle ); + snprintf( psz_chapter, 5, "%d", + p_intf->p_input->stream.p_selected_area->i_part ); + psz_chapter[ 4 ] = '\0'; + gtk_label_set_text( p_intf->p_sys->p_label_chapter, psz_chapter ); - p_menubar_menu = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT( - p_intf->p_sys->p_window ), "menubar_chapter" ) ); + p_intf->p_sys->i_part = + p_intf->p_input->stream.p_selected_area->i_part; - GnomeChapterMenu( p_intf, p_menubar_menu, on_menubar_chapter_toggle ); + p_intf->p_sys->b_chapter_update = 0; + } - p_popup_menu = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT( - p_intf->p_sys->p_popup ), "popup_navigation" ) ); + if( p_intf->p_sys->b_angle_update ) + { + p_menubar_menu = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT( + p_intf->p_sys->p_window ), "menubar_angle" ) ); + GnomeAngleMenu( p_intf, p_menubar_menu, on_menubar_angle_toggle ); - GnomeTitleMenu( p_intf, p_popup_menu, on_popup_navigation_toggle ); + p_popup_menu = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT( + p_intf->p_sys->p_popup ), "popup_angle" ) ); + GnomeAngleMenu( p_intf, p_popup_menu, on_popup_angle_toggle ); + p_intf->p_sys->b_angle_update = 0; + } + /* look for selected ES */ p_audio_es = NULL; p_spu_es = NULL; for( i = 0 ; i < p_intf->p_input->stream.i_selected_es_number ; i++ ) { - if( p_intf->p_input->stream.pp_es[i]->b_audio ) + if( p_intf->p_input->stream.pp_selected_es[i]->i_cat == AUDIO_ES ) { - p_audio_es = p_intf->p_input->stream.pp_es[i]; + p_audio_es = p_intf->p_input->stream.pp_selected_es[i]; } - if( p_intf->p_input->stream.pp_es[i]->b_spu ) + if( p_intf->p_input->stream.pp_selected_es[i]->i_cat == SPU_ES ) { - p_spu_es = p_intf->p_input->stream.pp_es[i]; + p_spu_es = p_intf->p_input->stream.pp_selected_es[i]; } } /* audio menus */ + if( p_intf->p_sys->b_audio_update ) + { + /* find audio root menu */ + p_menubar_menu = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT( + p_intf->p_sys->p_window ), "menubar_audio" ) ); + + p_popup_menu = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT( + p_intf->p_sys->p_popup ), "popup_audio" ) ); + + GnomeLanguageMenus( p_intf, p_menubar_menu, p_audio_es, AUDIO_ES, + on_menubar_audio_toggle ); + GnomeLanguageMenus( p_intf, p_popup_menu, p_audio_es, AUDIO_ES, + on_popup_audio_toggle ); - /* find audio root menu */ - p_menubar_menu = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT( - p_intf->p_sys->p_window ), "menubar_audio" ) ); + p_intf->p_sys->b_audio_update = 0; + } + + /* sub picture menus */ + if( p_intf->p_sys->b_spu_update ) + { + /* find spu root menu */ + p_menubar_menu = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT( + p_intf->p_sys->p_window ), "menubar_subtitle" ) ); + + p_popup_menu = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT( + p_intf->p_sys->p_popup ), "popup_subtitle" ) ); + + GnomeLanguageMenus( p_intf, p_menubar_menu, p_spu_es, SPU_ES, + on_menubar_subtitle_toggle ); + GnomeLanguageMenus( p_intf, p_popup_menu, p_spu_es, SPU_ES, + on_popup_subtitle_toggle ); - p_popup_menu = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT( - p_intf->p_sys->p_popup ), "popup_audio" ) ); + p_intf->p_sys->b_spu_update = 0; + } - GnomeLanguageMenus( p_intf, p_menubar_menu, p_audio_es, 1, - on_menubar_audio_toggle ); - GnomeLanguageMenus( p_intf, p_popup_menu, p_audio_es, 1, - on_popup_audio_toggle ); + return TRUE; +} - /* sub picture menus */ +/***************************************************************************** + * GnomeDisplayDate: display stream date + ***************************************************************************** + * This function displays the current date related to the position in + * the stream. It is called whenever the slider changes its value. + *****************************************************************************/ +void GnomeDisplayDate( GtkAdjustment *p_adj ) +{ + intf_thread_t *p_intf; + + p_intf = gtk_object_get_data( GTK_OBJECT( p_adj ), "p_intf" ); + + if( p_intf->p_input != NULL ) + { +#define p_area p_intf->p_input->stream.p_selected_area + char psz_time[ OFFSETTOTIME_MAX_SIZE ]; + + vlc_mutex_lock( &p_intf->p_input->stream.stream_lock ); + + gtk_label_set_text( p_intf->p_sys->p_label_date, + input_OffsetToTime( p_intf->p_input, psz_time, + ( p_area->i_size * p_adj->value ) / 100 ) ); + + vlc_mutex_unlock( &p_intf->p_input->stream.stream_lock ); +#undef p_area + } +} + + +/***************************************************************************** + * GnomeDiscModeManage + *****************************************************************************/ +static gint GnomeDiscModeManage( intf_thread_t * p_intf ) +{ + GtkWidget * p_dvd_box; + GtkWidget * p_file_box; + GtkWidget * p_network_box; + + p_file_box = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT( + p_intf->p_sys->p_window ), "file_box" ) ); + gtk_widget_hide( GTK_WIDGET( p_file_box ) ); + + p_network_box = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT( + p_intf->p_sys->p_window ), "network_box" ) ); + gtk_widget_hide( GTK_WIDGET( p_network_box ) ); + + p_dvd_box = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT( + p_intf->p_sys->p_window ), "dvd_box" ) ); + gtk_widget_show( GTK_WIDGET( p_dvd_box ) ); + + gtk_label_set_text( p_intf->p_sys->p_label_status, + "Status: playing DVD" ); + + return TRUE; +} + +/***************************************************************************** + * GnomeFileModeManage + *****************************************************************************/ +static gint GnomeFileModeManage( intf_thread_t * p_intf ) +{ + GtkWidget * p_dvd_box; + GtkWidget * p_file_box; + GtkWidget * p_network_box; + char * psz_name; + + p_network_box = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT( + p_intf->p_sys->p_window ), "network_box" ) ); + gtk_widget_hide( GTK_WIDGET( p_network_box ) ); + + p_dvd_box = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT( + p_intf->p_sys->p_window ), "dvd_box" ) ); + gtk_widget_hide( GTK_WIDGET( p_dvd_box ) ); + + p_file_box = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT( + p_intf->p_sys->p_window ), "file_box" ) ); + gtk_widget_show( GTK_WIDGET( p_file_box ) ); + +#if 1 +// psz_name = malloc( 16 + strlen( p_intf->p_input->p_source ) ); +// sprintf( psz_name, "Status: playing %s", p_intf->p_input->p_source ); + + psz_name = strdup( p_intf->p_input->p_source ); + + gtk_label_set_text( p_intf->p_sys->p_label_status, psz_name ); + + free( psz_name ); +#else + gtk_label_set_text( p_intf->p_sys->p_label_status, + "Status: foo" ); +#endif + + return TRUE; +} + +/***************************************************************************** + * GnomeNetworkModeManage + *****************************************************************************/ +static gint GnomeNetworkModeManage( intf_thread_t * p_intf ) +{ + GtkWidget * p_dvd_box; + GtkWidget * p_file_box; + GtkWidget * p_network_box; - /* find spu root menu */ - p_menubar_menu = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT( - p_intf->p_sys->p_window ), "menubar_subtitle" ) ); + p_dvd_box = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT( + p_intf->p_sys->p_window ), "dvd_box" ) ); + gtk_widget_hide( GTK_WIDGET( p_dvd_box ) ); - p_popup_menu = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT( - p_intf->p_sys->p_popup ), "popup_subtitle" ) ); + p_file_box = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT( + p_intf->p_sys->p_window ), "file_box" ) ); + gtk_widget_hide( GTK_WIDGET( p_file_box ) ); - GnomeLanguageMenus( p_intf, p_menubar_menu, p_spu_es, 2, - on_menubar_subtitle_toggle ); - GnomeLanguageMenus( p_intf, p_popup_menu, p_spu_es, 2, - on_popup_subtitle_toggle ); + p_network_box = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT( + p_intf->p_sys->p_window ), "network_box" ) ); + gtk_widget_show( GTK_WIDGET( p_network_box ) ); - /* everything is ready */ - p_intf->p_sys->b_menus_update = 0; + gtk_label_set_text( p_intf->p_sys->p_label_status, + "Status: waiting for stream" ); return TRUE; }