You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
940 lines
34 KiB
940 lines
34 KiB
/*****************************************************************************
|
|
* gtk_menu.c : functions to handle menu items.
|
|
*****************************************************************************
|
|
* Copyright (C) 2000, 2001 VideoLAN
|
|
* $Id: gtk_menu.c,v 1.9 2001/06/02 01:09:03 sam Exp $
|
|
*
|
|
* Authors: Samuel Hocevar <sam@zoy.org>
|
|
* Stéphane Borel <stef@via.ecp.fr>
|
|
*
|
|
* 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., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
|
|
*****************************************************************************/
|
|
|
|
/*****************************************************************************
|
|
* Preamble
|
|
*****************************************************************************/
|
|
#include "defs.h"
|
|
#include <sys/types.h> /* off_t */
|
|
#include <stdlib.h>
|
|
|
|
#include <gtk/gtk.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include "config.h"
|
|
#include "common.h"
|
|
#include "threads.h"
|
|
#include "mtime.h"
|
|
|
|
#include "stream_control.h"
|
|
#include "input_ext-intf.h"
|
|
|
|
#include "interface.h"
|
|
#include "intf_playlist.h"
|
|
#include "intf_msg.h"
|
|
|
|
#include "video.h"
|
|
#include "video_output.h"
|
|
#include "audio_output.h"
|
|
|
|
#include "gtk_callbacks.h"
|
|
#include "gtk_interface.h"
|
|
#include "gtk_support.h"
|
|
#include "gtk_playlist.h"
|
|
#include "intf_gtk.h"
|
|
|
|
#include "main.h"
|
|
|
|
#include "modules_export.h"
|
|
|
|
#ifdef WIN32
|
|
#ifndef snprintf
|
|
#define snprintf _snprintf
|
|
#endif
|
|
#endif
|
|
|
|
/*
|
|
* Local Prototypes
|
|
*/
|
|
static gint GtkLanguageMenus( gpointer , GtkWidget *, es_descriptor_t *, gint,
|
|
void(*pf_toggle )( GtkCheckMenuItem *, gpointer ) );
|
|
|
|
void GtkMenubarAudioToggle ( GtkCheckMenuItem *, gpointer );
|
|
void GtkPopupAudioToggle ( GtkCheckMenuItem *, gpointer );
|
|
void GtkMenubarSubtitleToggle( GtkCheckMenuItem *, gpointer );
|
|
void GtkPopupSubtitleToggle ( GtkCheckMenuItem *, gpointer );
|
|
static gint GtkTitleMenu( gpointer, GtkWidget *,
|
|
void(*pf_toggle )( GtkCheckMenuItem *, gpointer ) );
|
|
static gint GtkRadioMenu( intf_thread_t *, GtkWidget *, GSList *,
|
|
char *, int, int,
|
|
void( *pf_toggle )( GtkCheckMenuItem *, gpointer ) );
|
|
void GtkMenubarAngleToggle( GtkCheckMenuItem *, gpointer );
|
|
void GtkPopupAngleToggle( GtkCheckMenuItem *, gpointer );
|
|
|
|
gint GtkSetupMenus( intf_thread_t * p_intf );
|
|
|
|
/****************************************************************************
|
|
* Gtk*Toggle: callbacks to toggle the value of a checkmenuitem
|
|
****************************************************************************
|
|
* We need separate functions for menubar and popup here since we can't use
|
|
* user_data to transmit intf_* and we need to refresh the other menu.
|
|
****************************************************************************/
|
|
|
|
#define GtkLangToggle( intf, window, menu, type, callback, b_update ) \
|
|
intf_thread_t * p_intf; \
|
|
GtkWidget * p_menu; \
|
|
es_descriptor_t * p_es; \
|
|
\
|
|
p_intf = GetIntf( GTK_WIDGET(menuitem), (intf) ); \
|
|
\
|
|
if( !p_intf->p_sys->b_update ) \
|
|
{ \
|
|
p_menu = GTK_WIDGET( gtk_object_get_data( \
|
|
GTK_OBJECT( p_intf->p_sys->window ), (menu) ) ); \
|
|
p_es = (es_descriptor_t*)user_data; \
|
|
\
|
|
input_ToggleES( p_intf->p_input, p_es, menuitem->active ); \
|
|
\
|
|
p_intf->p_sys->b_update = menuitem->active; \
|
|
\
|
|
if( p_intf->p_sys->b_update ) \
|
|
{ \
|
|
GtkLanguageMenus( p_intf, p_menu, p_es, type, callback ); \
|
|
} \
|
|
\
|
|
p_intf->p_sys->b_update = 0; \
|
|
}
|
|
|
|
/*
|
|
* Audio
|
|
*/
|
|
|
|
void GtkMenubarAudioToggle( GtkCheckMenuItem * menuitem, gpointer user_data )
|
|
{
|
|
GtkLangToggle( "intf_window", p_popup, "popup_audio", AUDIO_ES,
|
|
GtkPopupAudioToggle, b_audio_update );
|
|
}
|
|
|
|
void GtkPopupAudioToggle( GtkCheckMenuItem * menuitem, gpointer user_data )
|
|
{
|
|
GtkLangToggle( "intf_popup", p_window, "menubar_audio", AUDIO_ES,
|
|
GtkMenubarAudioToggle, b_audio_update );
|
|
}
|
|
|
|
/*
|
|
* Subtitles
|
|
*/
|
|
|
|
void GtkMenubarSubtitleToggle( GtkCheckMenuItem * menuitem, gpointer user_data )
|
|
{
|
|
GtkLangToggle( "intf_window", p_popup, "popup_subpictures", SPU_ES,
|
|
GtkPopupSubtitleToggle, b_spu_update );
|
|
}
|
|
|
|
void GtkPopupSubtitleToggle( GtkCheckMenuItem * menuitem, gpointer user_data )
|
|
{
|
|
GtkLangToggle( "intf_popup", p_window, "menubar_subpictures", SPU_ES,
|
|
GtkMenubarSubtitleToggle, b_spu_update );
|
|
}
|
|
|
|
#undef GtkLangToggle
|
|
|
|
/*
|
|
* Navigation
|
|
*/
|
|
|
|
void GtkPopupNavigationToggle( GtkCheckMenuItem * menuitem,
|
|
gpointer user_data )
|
|
{
|
|
intf_thread_t * p_intf = GetIntf( GTK_WIDGET(menuitem), "intf_popup" );
|
|
|
|
if( menuitem->active &&
|
|
!p_intf->p_sys->b_title_update &&
|
|
!p_intf->p_sys->b_chapter_update )
|
|
{
|
|
input_area_t *p_area;
|
|
|
|
gint i_title = DATA2TITLE( user_data );
|
|
gint i_chapter = DATA2CHAPTER( user_data );
|
|
|
|
p_area = p_intf->p_input->stream.p_selected_area;
|
|
|
|
if( p_area != p_intf->p_input->stream.pp_areas[i_title] )
|
|
{
|
|
p_area = p_intf->p_input->stream.pp_areas[i_title];
|
|
p_intf->p_sys->b_title_update = 1;
|
|
}
|
|
|
|
p_area->i_part = i_chapter;
|
|
|
|
input_ChangeArea( p_intf->p_input, (input_area_t*)p_area );
|
|
|
|
p_intf->p_sys->b_chapter_update = 1;
|
|
vlc_mutex_lock( &p_intf->p_input->stream.stream_lock );
|
|
GtkSetupMenus( p_intf );
|
|
vlc_mutex_unlock( &p_intf->p_input->stream.stream_lock );
|
|
|
|
input_SetStatus( p_intf->p_input, INPUT_STATUS_PLAY );
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Title
|
|
*/
|
|
|
|
void GtkMenubarTitleToggle( GtkCheckMenuItem * menuitem, gpointer user_data )
|
|
{
|
|
intf_thread_t * p_intf = GetIntf( GTK_WIDGET(menuitem), "intf_window" );
|
|
|
|
if( menuitem->active && !p_intf->p_sys->b_title_update )
|
|
{
|
|
gint i_title = (gint)user_data;
|
|
input_ChangeArea( p_intf->p_input,
|
|
p_intf->p_input->stream.pp_areas[i_title] );
|
|
|
|
p_intf->p_sys->b_title_update = 1;
|
|
vlc_mutex_lock( &p_intf->p_input->stream.stream_lock );
|
|
GtkSetupMenus( p_intf );
|
|
vlc_mutex_unlock( &p_intf->p_input->stream.stream_lock );
|
|
p_intf->p_sys->b_title_update = 0;
|
|
|
|
input_SetStatus( p_intf->p_input, INPUT_STATUS_PLAY );
|
|
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Chapter
|
|
*/
|
|
|
|
void GtkMenubarChapterToggle( GtkCheckMenuItem * menuitem, gpointer user_data )
|
|
{
|
|
intf_thread_t * p_intf;
|
|
input_area_t * p_area;
|
|
gint i_chapter;
|
|
char psz_chapter[5];
|
|
GtkWidget * p_popup_menu;
|
|
|
|
p_intf = GetIntf( GTK_WIDGET(menuitem), "intf_window" );
|
|
p_area = p_intf->p_input->stream.p_selected_area;
|
|
i_chapter = (gint)user_data;
|
|
|
|
if( menuitem->active && !p_intf->p_sys->b_chapter_update )
|
|
{
|
|
p_area->i_part = i_chapter;
|
|
input_ChangeArea( p_intf->p_input, (input_area_t*)p_area );
|
|
|
|
snprintf( psz_chapter, 4, "%02d", p_area->i_part );
|
|
psz_chapter[ 4 ] = '\0';
|
|
gtk_label_set_text( p_intf->p_sys->p_label_chapter, psz_chapter );
|
|
|
|
p_intf->p_sys->b_chapter_update = 1;
|
|
p_popup_menu = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT(
|
|
p_intf->p_sys->p_popup ), "popup_navigation" ) );
|
|
|
|
vlc_mutex_lock( &p_intf->p_input->stream.stream_lock );
|
|
GtkTitleMenu( p_intf, p_popup_menu, GtkPopupNavigationToggle );
|
|
vlc_mutex_unlock( &p_intf->p_input->stream.stream_lock );
|
|
|
|
p_intf->p_sys->b_chapter_update = 0;
|
|
|
|
input_SetStatus( p_intf->p_input, INPUT_STATUS_PLAY );
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
* Angle
|
|
*/
|
|
|
|
#define GtkAngleToggle( intf, window, menu, callback ) \
|
|
intf_thread_t * p_intf; \
|
|
GtkWidget * p_menu; \
|
|
input_area_t * p_area; \
|
|
\
|
|
p_intf = GetIntf( GTK_WIDGET(menuitem), (intf) ); \
|
|
\
|
|
if( menuitem->active && !p_intf->p_sys->b_angle_update ) \
|
|
{ \
|
|
p_menu = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT( \
|
|
p_intf->p_sys->window ), (menu) ) ); \
|
|
p_area = p_intf->p_input->stream.p_selected_area; \
|
|
p_area->i_angle = (gint)user_data; \
|
|
\
|
|
input_ChangeArea( p_intf->p_input, (input_area_t*)p_area ); \
|
|
\
|
|
p_intf->p_sys->b_angle_update = 1; \
|
|
vlc_mutex_lock( &p_intf->p_input->stream.stream_lock ); \
|
|
GtkRadioMenu( p_intf, p_menu, NULL, "Angle", \
|
|
p_area->i_angle_nb, p_area->i_angle, (callback) ); \
|
|
vlc_mutex_unlock( &p_intf->p_input->stream.stream_lock ); \
|
|
p_intf->p_sys->b_angle_update = 0; \
|
|
}
|
|
|
|
void GtkMenubarAngleToggle( GtkCheckMenuItem * menuitem, gpointer user_data )
|
|
{
|
|
GtkAngleToggle( "intf_window", p_popup, "popup_angle",
|
|
GtkPopupAngleToggle );
|
|
}
|
|
|
|
void GtkPopupAngleToggle( GtkCheckMenuItem * menuitem, gpointer user_data )
|
|
{
|
|
GtkAngleToggle( "intf_popup", p_window, "menubar_angle",
|
|
GtkMenubarAngleToggle );
|
|
}
|
|
|
|
#undef GtkAngleToggle
|
|
|
|
/****************************************************************************
|
|
* Functions to generate menus
|
|
****************************************************************************/
|
|
|
|
/*****************************************************************************
|
|
* GtkRadioMenu: update interactive menus of the interface
|
|
*****************************************************************************
|
|
* Sets up menus with information from input
|
|
* Warning: since this function is designed to be called by management
|
|
* function, the interface lock has to be taken
|
|
*****************************************************************************/
|
|
static gint GtkRadioMenu( intf_thread_t * p_intf,
|
|
GtkWidget * p_root, GSList * p_menu_group,
|
|
char * psz_item_name,
|
|
int i_nb, int i_selected,
|
|
void( *pf_toggle )( GtkCheckMenuItem *, gpointer ) )
|
|
{
|
|
char psz_name[ GTK_MENU_LABEL_SIZE ];
|
|
GtkWidget * p_menu;
|
|
GtkWidget * p_submenu;
|
|
GtkWidget * p_item_group;
|
|
GtkWidget * p_item;
|
|
GtkWidget * p_item_selected;
|
|
GSList * p_group;
|
|
gint i_item;
|
|
|
|
/* temporary hack to avoid blank menu when an open menu is removed */
|
|
if( GTK_MENU_ITEM(p_root)->submenu != NULL )
|
|
{
|
|
gtk_menu_popdown( GTK_MENU( GTK_MENU_ITEM(p_root)->submenu ) );
|
|
}
|
|
/* removes previous menu */
|
|
gtk_menu_item_remove_submenu( GTK_MENU_ITEM( p_root ) );
|
|
gtk_widget_set_sensitive( p_root, FALSE );
|
|
|
|
p_item_group = NULL;
|
|
p_submenu = NULL;
|
|
p_item_selected = NULL;
|
|
p_group = p_menu_group;
|
|
|
|
p_menu = gtk_menu_new();
|
|
|
|
for( i_item = 0 ; i_item < i_nb ; i_item++ )
|
|
{
|
|
/* we group chapters in packets of ten for small screens */
|
|
if( ( i_item % 10 == 0 ) && ( i_nb > 20 ) )
|
|
{
|
|
if( i_item != 0 )
|
|
{
|
|
gtk_menu_item_set_submenu( GTK_MENU_ITEM( p_item_group ),
|
|
p_submenu );
|
|
gtk_menu_append( GTK_MENU( p_menu ), p_item_group );
|
|
}
|
|
|
|
snprintf( psz_name, GTK_MENU_LABEL_SIZE,
|
|
"%ss %d to %d", psz_item_name, i_item + 1, i_item + 10);
|
|
psz_name[ GTK_MENU_LABEL_SIZE - 1 ] = '\0';
|
|
p_item_group = gtk_menu_item_new_with_label( psz_name );
|
|
gtk_widget_show( p_item_group );
|
|
p_submenu = gtk_menu_new();
|
|
}
|
|
|
|
snprintf( psz_name, GTK_MENU_LABEL_SIZE, "%s %d",
|
|
psz_item_name, i_item + 1 );
|
|
psz_name[ GTK_MENU_LABEL_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 ) );
|
|
|
|
if( i_selected == i_item + 1 )
|
|
{
|
|
p_item_selected = 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_item + 1) );
|
|
|
|
if( i_nb > 20 )
|
|
{
|
|
gtk_menu_append( GTK_MENU( p_submenu ), p_item );
|
|
}
|
|
else
|
|
{
|
|
gtk_menu_append( GTK_MENU( p_menu ), p_item );
|
|
}
|
|
}
|
|
|
|
if( i_nb > 20 )
|
|
{
|
|
gtk_menu_item_set_submenu( GTK_MENU_ITEM( p_item_group ), p_submenu );
|
|
gtk_menu_append( GTK_MENU( p_menu ), p_item_group );
|
|
}
|
|
|
|
/* link the new menu to the title menu item */
|
|
gtk_menu_item_set_submenu( GTK_MENU_ITEM( p_root ), p_menu );
|
|
|
|
/* toggle currently selected chapter
|
|
* We have to release the lock since input_ToggleES needs it */
|
|
if( p_item_selected != NULL )
|
|
{
|
|
vlc_mutex_unlock( &p_intf->p_input->stream.stream_lock );
|
|
gtk_check_menu_item_set_active( GTK_CHECK_MENU_ITEM( p_item_selected ),
|
|
TRUE );
|
|
vlc_mutex_lock( &p_intf->p_input->stream.stream_lock );
|
|
}
|
|
|
|
/* be sure that menu is sensitive, if there are several items */
|
|
if( i_nb > 1 )
|
|
{
|
|
gtk_widget_set_sensitive( p_root, TRUE );
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* GtkLanguageMenus: update interactive menus of the interface
|
|
*****************************************************************************
|
|
* Sets up menus with information from input:
|
|
* -languages
|
|
* -sub-pictures
|
|
* Warning: since this function is designed to be called by management
|
|
* function, the interface lock has to be taken
|
|
*****************************************************************************/
|
|
static gint GtkLanguageMenus( gpointer p_data,
|
|
GtkWidget * p_root,
|
|
es_descriptor_t * p_es,
|
|
gint i_cat,
|
|
void(*pf_toggle )( GtkCheckMenuItem *, gpointer ) )
|
|
{
|
|
intf_thread_t * p_intf;
|
|
GtkWidget * p_menu;
|
|
GtkWidget * p_separator;
|
|
GtkWidget * p_item;
|
|
GtkWidget * p_item_active;
|
|
GSList * p_group;
|
|
char psz_name[ GTK_MENU_LABEL_SIZE ];
|
|
gint i_item;
|
|
gint i;
|
|
|
|
|
|
|
|
/* cast */
|
|
p_intf = (intf_thread_t *)p_data;
|
|
|
|
/* temporary hack to avoid blank menu when an open menu is removed */
|
|
if( GTK_MENU_ITEM(p_root)->submenu != NULL )
|
|
{
|
|
gtk_menu_popdown( GTK_MENU( GTK_MENU_ITEM(p_root)->submenu ) );
|
|
}
|
|
/* removes previous menu */
|
|
gtk_menu_item_remove_submenu( GTK_MENU_ITEM( p_root ) );
|
|
gtk_widget_set_sensitive( p_root, FALSE );
|
|
|
|
p_group = NULL;
|
|
|
|
/* menu container */
|
|
p_menu = gtk_menu_new();
|
|
|
|
/* special case for "off" item */
|
|
snprintf( psz_name, GTK_MENU_LABEL_SIZE, "None" );
|
|
psz_name[ GTK_MENU_LABEL_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_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 );
|
|
|
|
p_item_active = NULL;
|
|
i_item = 0;
|
|
|
|
vlc_mutex_lock( &p_intf->p_input->stream.stream_lock );
|
|
|
|
/* 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++ )
|
|
{
|
|
if( p_intf->p_input->stream.pp_es[i]->i_cat == i_cat )
|
|
{
|
|
i_item++;
|
|
strcpy( psz_name, p_intf->p_input->stream.pp_es[i]->psz_desc );
|
|
if( psz_name[0] == '\0' )
|
|
{
|
|
snprintf( psz_name, GTK_MENU_LABEL_SIZE,
|
|
"Language %d", i_item );
|
|
psz_name[ GTK_MENU_LABEL_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 ) );
|
|
|
|
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 */
|
|
gtk_signal_connect( GTK_OBJECT( p_item ), "toggled",
|
|
GTK_SIGNAL_FUNC( pf_toggle ),
|
|
(gpointer)( p_intf->p_input->stream.pp_es[i] ) );
|
|
|
|
gtk_menu_append( GTK_MENU( p_menu ), p_item );
|
|
}
|
|
}
|
|
|
|
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 );
|
|
|
|
/* acitvation will call signals so we can only do it
|
|
* when submenu is attached to menu - to get intf_window
|
|
* We have to release the lock since input_ToggleES needs it */
|
|
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( i_item > 0 )
|
|
{
|
|
gtk_widget_set_sensitive( p_root, TRUE );
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* GtkTitleMenu: sets menus for titles and chapters selection
|
|
*****************************************************************************
|
|
* Generates two types of menus:
|
|
* -simple list of titles
|
|
* -cascaded lists of chapters for each title
|
|
*****************************************************************************/
|
|
static gint GtkTitleMenu( gpointer p_data,
|
|
GtkWidget * p_navigation,
|
|
void(*pf_toggle )( GtkCheckMenuItem *, gpointer ) )
|
|
{
|
|
intf_thread_t * p_intf;
|
|
char psz_name[ GTK_MENU_LABEL_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 i_title_nb;
|
|
gint i_chapter_nb;
|
|
|
|
/* cast */
|
|
p_intf = (intf_thread_t*)p_data;
|
|
|
|
/* temporary hack to avoid blank menu when an open menu is removed */
|
|
if( GTK_MENU_ITEM(p_navigation)->submenu != NULL )
|
|
{
|
|
gtk_menu_popdown( GTK_MENU( GTK_MENU_ITEM(p_navigation)->submenu ) );
|
|
}
|
|
/* 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 < i_title_nb ; i_title++ )
|
|
{
|
|
/* 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, GTK_MENU_LABEL_SIZE,
|
|
"%d - %d", i_title, i_title + 9 );
|
|
psz_name[ GTK_MENU_LABEL_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, GTK_MENU_LABEL_SIZE, "Title %d (%d)", i_title,
|
|
p_intf->p_input->stream.pp_areas[i_title]->i_part_nb );
|
|
psz_name[ GTK_MENU_LABEL_SIZE - 1 ] = '\0';
|
|
#if 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;
|
|
}
|
|
|
|
/* 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
|
|
#endif
|
|
{
|
|
p_title_item = gtk_menu_item_new_with_label( psz_name );
|
|
|
|
#if 1
|
|
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 < i_chapter_nb ; i_chapter++ )
|
|
{
|
|
/* 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, GTK_MENU_LABEL_SIZE,
|
|
"%d - %d", i_chapter + 1, i_chapter + 10 );
|
|
psz_name[ GTK_MENU_LABEL_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, GTK_MENU_LABEL_SIZE,
|
|
"Chapter %d", i_chapter + 1 );
|
|
psz_name[ GTK_MENU_LABEL_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_widget_show( p_item );
|
|
|
|
#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)POS2DATA( i_title, i_chapter + 1) );
|
|
|
|
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 );
|
|
}
|
|
#else
|
|
GtkRadioMenu( p_intf, p_title_item, p_chapter_group, "Chapter",
|
|
p_intf->p_input->stream.pp_areas[i_title]->i_part_nb,
|
|
i_title * 100,
|
|
p_intf->p_input->stream.p_selected_area->i_part +
|
|
p_intf->p_input->stream.p_selected_area->i_id *100,
|
|
pf_toggle );
|
|
|
|
#endif
|
|
}
|
|
gtk_widget_show( p_title_item );
|
|
|
|
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 );
|
|
|
|
/* Default selected chapter
|
|
* We have to release the lock since input_ToggleES needs it */
|
|
if( p_item_active != NULL )
|
|
{
|
|
vlc_mutex_unlock( &p_intf->p_input->stream.stream_lock );
|
|
gtk_check_menu_item_set_active( GTK_CHECK_MENU_ITEM( p_item_active ),
|
|
TRUE );
|
|
vlc_mutex_lock( &p_intf->p_input->stream.stream_lock );
|
|
}
|
|
#if 0
|
|
if( p_intf->p_input->stream.i_area_nb > 1 )
|
|
{
|
|
/* be sure that menu is sensitive */
|
|
gtk_widget_set_sensitive( p_navigation, TRUE );
|
|
}
|
|
#endif
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* GtkSetupMenus: function that generates title/chapter/audio/subpic
|
|
* menus with help from preceding functions
|
|
*****************************************************************************/
|
|
gint GtkSetupMenus( intf_thread_t * p_intf )
|
|
{
|
|
es_descriptor_t * p_audio_es;
|
|
es_descriptor_t * p_spu_es;
|
|
GtkWidget * p_menubar_menu;
|
|
GtkWidget * p_popup_menu;
|
|
gint i;
|
|
|
|
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;
|
|
|
|
// vlc_mutex_lock( &p_intf->p_input->stream.stream_lock );
|
|
|
|
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" ) );
|
|
GtkRadioMenu( p_intf, p_menubar_menu, NULL, "Title",
|
|
p_intf->p_input->stream.i_area_nb - 1,
|
|
p_intf->p_input->stream.p_selected_area->i_id,
|
|
GtkMenubarTitleToggle );
|
|
|
|
snprintf( psz_title, 4, "%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" ) );
|
|
GtkTitleMenu( p_intf, p_popup_menu, GtkPopupNavigationToggle );
|
|
#if 0
|
|
GtkRadioMenu( p_intf, p_menubar_menu, NULL, "Title",
|
|
p_intf->p_input->stream.i_area_nb - 1,
|
|
p_intf->p_input->stream.p_selected_area->i_id,
|
|
on_menubar_chapter_toggle );
|
|
#endif
|
|
|
|
p_menubar_menu = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT(
|
|
p_intf->p_sys->p_window ), "menubar_chapter" ) );
|
|
GtkRadioMenu( p_intf, p_menubar_menu, NULL, "Chapter",
|
|
p_intf->p_input->stream.p_selected_area->i_part_nb,
|
|
p_intf->p_input->stream.p_selected_area->i_part,
|
|
GtkMenubarChapterToggle );
|
|
|
|
|
|
snprintf( psz_chapter, 4, "%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_intf->p_sys->i_part =
|
|
p_intf->p_input->stream.p_selected_area->i_part;
|
|
|
|
p_intf->p_sys->b_chapter_update = 0;
|
|
}
|
|
|
|
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" ) );
|
|
GtkRadioMenu( p_intf, p_menubar_menu, NULL, "Angle",
|
|
p_intf->p_input->stream.p_selected_area->i_angle_nb,
|
|
p_intf->p_input->stream.p_selected_area->i_angle,
|
|
GtkMenubarAngleToggle );
|
|
|
|
p_popup_menu = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT(
|
|
p_intf->p_sys->p_popup ), "popup_angle" ) );
|
|
GtkRadioMenu( p_intf, p_popup_menu, NULL, "Angle",
|
|
p_intf->p_input->stream.p_selected_area->i_angle_nb,
|
|
p_intf->p_input->stream.p_selected_area->i_angle,
|
|
GtkPopupAngleToggle );
|
|
|
|
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_selected_es[i]->i_cat == AUDIO_ES )
|
|
{
|
|
p_audio_es = p_intf->p_input->stream.pp_selected_es[i];
|
|
}
|
|
|
|
if( p_intf->p_input->stream.pp_selected_es[i]->i_cat == SPU_ES )
|
|
{
|
|
p_spu_es = p_intf->p_input->stream.pp_selected_es[i];
|
|
}
|
|
}
|
|
|
|
vlc_mutex_unlock( &p_intf->p_input->stream.stream_lock );
|
|
|
|
/* 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" ) );
|
|
|
|
p_intf->p_sys->b_audio_update = 1;
|
|
GtkLanguageMenus( p_intf, p_menubar_menu, p_audio_es, AUDIO_ES,
|
|
GtkMenubarAudioToggle );
|
|
p_intf->p_sys->b_audio_update = 1;
|
|
GtkLanguageMenus( p_intf, p_popup_menu, p_audio_es, AUDIO_ES,
|
|
GtkPopupAudioToggle );
|
|
|
|
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_subpictures" ) );
|
|
|
|
p_popup_menu = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT(
|
|
p_intf->p_sys->p_popup ), "popup_subpictures" ) );
|
|
|
|
p_intf->p_sys->b_spu_update = 1;
|
|
GtkLanguageMenus( p_intf, p_menubar_menu, p_spu_es, SPU_ES,
|
|
GtkMenubarSubtitleToggle );
|
|
p_intf->p_sys->b_spu_update = 1;
|
|
GtkLanguageMenus( p_intf, p_popup_menu, p_spu_es, SPU_ES,
|
|
GtkPopupSubtitleToggle );
|
|
|
|
p_intf->p_sys->b_spu_update = 0;
|
|
}
|
|
|
|
vlc_mutex_lock( &p_intf->p_input->stream.stream_lock );
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|