Commit 0fee43a4 authored by Stéphane Borel's avatar Stéphane Borel

-Fall back to one-packet-once reading in dvd input since multi-block

seems to have a bug that make the vlc crash on title/audio/spu change. I
hope that this bug will be fixed soon for the performance is poorer now

-add-ons and changes in gnome interface:
        *menu subdivision is done only if there are over 20 items,
        *in DVD mode next/prev apply to title,
        *in DVD mode, added a box with button to navigate through
         chapters.
This has not been finished yet (and it is not in gtk plugin then). And I
think I will leave toolbar next/prev buttons for playlist and add
button specifically for title change like for chapters.*
parent 8ccd224c
......@@ -10,7 +10,7 @@
* -dvd_udf to find files
*****************************************************************************
* Copyright (C) 1998-2001 VideoLAN
* $Id: input_dvd.c,v 1.36 2001/04/02 23:30:41 sam Exp $
* $Id: input_dvd.c,v 1.37 2001/04/03 03:39:41 stef Exp $
*
* Author: Stphane Borel <stef@via.ecp.fr>
*
......@@ -691,7 +691,7 @@ static int DVDSetArea( input_thread_t * p_input, input_area_t * p_area )
i_spu += vts.manager_inf.i_audio_nb;
input_SelectES( p_input, p_input->stream.pp_es[i_spu] );
}
} // i_title >= 0
} /* i_title >= 0 */
else
{
p_area = p_input->stream.p_selected_area;
......@@ -747,8 +747,11 @@ static void DVDInit( input_thread_t * p_input )
p_dvd->i_fd = p_input->i_handle;
p_dvd->i_block_once = 32;
p_input->i_read_once = 128;
/* reading several block once seems to cause lock-up
* when using input_ToggleES
* who wrote thez damn buggy piece of shit ??? --stef */
p_dvd->i_block_once = 1;//32;
p_input->i_read_once = 4;//128;
i = CSSTest( p_input->i_handle );
......@@ -766,7 +769,7 @@ static void DVDInit( input_thread_t * p_input )
/* Reading structures initialisation */
p_input->p_method_data =
DVDNetlistInit( 8192, 16384, 2048, DVD_LB_SIZE, p_dvd->i_block_once );
DVDNetlistInit( 2048, 8192, 2048, DVD_LB_SIZE, p_dvd->i_block_once );
intf_WarnMsg( 2, "dvd info: netlist initialized" );
/* Ifo initialisation */
......
......@@ -2,7 +2,7 @@
* gnome_callbacks.c : Callbacks for the Gnome plugin.
*****************************************************************************
* Copyright (C) 2000, 2001 VideoLAN
* $Id: gnome_callbacks.c,v 1.19 2001/04/01 07:31:38 stef Exp $
* $Id: gnome_callbacks.c,v 1.20 2001/04/03 03:39:41 stef Exp $
*
* Authors: Samuel Hocevar <sam@zoy.org>
* Stphane Borel <stef@via.ecp.fr>
......@@ -160,6 +160,44 @@ on_intf_window_drag_data_received (GtkWidget *widget,
}
void
on_button_chapter_prev_clicked (GtkButton *button,
gpointer user_data)
{
intf_thread_t * p_intf;
input_area_t * p_area;
p_intf = GetIntf( GTK_WIDGET(button), "intf_window" );
p_area = p_intf->p_input->stream.p_selected_area;
if( p_area->i_part - 1 >= 0 )
{
p_area->i_part--;
p_intf->p_input->pf_set_area( p_intf->p_input, (input_area_t*)p_area );
input_SetStatus( p_intf->p_input, INPUT_STATUS_PLAY );
}
}
void
on_button_chapter_next_clicked (GtkButton *button,
gpointer user_data)
{
intf_thread_t * p_intf;
input_area_t * p_area;
p_intf = GetIntf( GTK_WIDGET(button), "intf_window" );
p_area = p_intf->p_input->stream.p_selected_area;
if( p_area->i_part + 1 < p_area->i_part_nb )
{
p_area->i_part++;
p_intf->p_input->pf_set_area( p_intf->p_input, (input_area_t*)p_area );
input_SetStatus( p_intf->p_input, INPUT_STATUS_PLAY );
}
}
/*****************************************************************************
* Menubar callbacks
*****************************************************************************
......@@ -505,6 +543,48 @@ on_toolbar_next_clicked (GtkButton *button,
}
void
on_toolbar_prev_title_clicked (GtkButton *button,
gpointer user_data)
{
intf_thread_t * p_intf;
input_area_t * p_area;
int i_id;
p_intf = GetIntf( GTK_WIDGET(button), "intf_window" );
i_id = p_intf->p_input->stream.p_selected_area->i_id - 1;
if( i_id >= 0 )
{
p_area = p_intf->p_input->stream.pp_areas[i_id];
p_intf->p_input->pf_set_area( p_intf->p_input, (input_area_t*)p_area );
p_intf->p_sys->b_menus_update = 1;
input_SetStatus( p_intf->p_input, INPUT_STATUS_PLAY );
}
}
void
on_toolbar_next_title_clicked (GtkButton *button,
gpointer user_data)
{
intf_thread_t * p_intf;
input_area_t * p_area;
int i_id;
p_intf = GetIntf( GTK_WIDGET(button), "intf_window" );
i_id = p_intf->p_input->stream.p_selected_area->i_id + 1;
if( i_id < p_intf->p_input->stream.i_area_nb )
{
p_area = p_intf->p_input->stream.pp_areas[i_id];
p_intf->p_input->pf_set_area( p_intf->p_input, (input_area_t*)p_area );
p_intf->p_sys->b_menus_update = 1;
input_SetStatus( p_intf->p_input, INPUT_STATUS_PLAY );
}
}
/*****************************************************************************
* Popup callbacks
*****************************************************************************
......@@ -856,6 +936,8 @@ on_disc_ok_clicked (GtkButton *button,
"disc_dvd" ) )->active )
{
psz_method = "dvd";
p_intf->p_sys->i_intf_mode = DVD_MODE;
p_intf->p_sys->b_mode_changed = 1;
}
else if( GTK_TOGGLE_BUTTON( lookup_widget( GTK_WIDGET(button),
"disc_vcd" ) )->active )
......
......@@ -2,7 +2,7 @@
* gnome_callbacks.h : Callbacks for the Gnome plugin.
*****************************************************************************
* Copyright (C) 2000, 2001 VideoLAN
* $Id: gnome_callbacks.h,v 1.12 2001/03/21 13:42:34 sam Exp $
* $Id: gnome_callbacks.h,v 1.13 2001/04/03 03:39:41 stef Exp $
*
* Authors: Samuel Hocevar <sam@zoy.org>
*
......@@ -86,6 +86,14 @@ void
on_toolbar_next_clicked (GtkButton *button,
gpointer user_data);
void
on_toolbar_prev_title_clicked (GtkButton *button,
gpointer user_data);
void
on_toolbar_next_title_clicked (GtkButton *button,
gpointer user_data);
void
on_popup_play_activate (GtkMenuItem *menuitem,
gpointer user_data);
......@@ -273,3 +281,11 @@ on_slider_button_release_event (GtkWidget *widget,
void
on_menubar_chapter_toggle (GtkCheckMenuItem *menuitem,
gpointer user_data);
void
on_button_chapter_prev_clicked (GtkButton *button,
gpointer user_data);
void
on_button_chapter_next_clicked (GtkButton *button,
gpointer user_data);
......@@ -140,7 +140,16 @@ create_intf_window (void)
GtkWidget *label_status;
GtkWidget *label_bar;
GtkWidget *slider;
GtkWidget *dvd_box;
GtkWidget *label_title;
GtkWidget *hbox6;
GtkWidget *button_chapter_prev;
GtkWidget *label_chapter;
GtkWidget *button_chapter_next;
GtkWidget *appbar;
GtkTooltips *tooltips;
tooltips = gtk_tooltips_new ();
intf_window = gnome_app_new ("VideoLAN Client", _("VideoLAN Client"));
gtk_object_set_data (GTK_OBJECT (intf_window), "intf_window", intf_window);
......@@ -462,6 +471,51 @@ create_intf_window (void)
gtk_scale_set_draw_value (GTK_SCALE (slider), FALSE);
gtk_scale_set_digits (GTK_SCALE (slider), 3);
dvd_box = gtk_hbox_new (FALSE, 0);
gtk_widget_ref (dvd_box);
gtk_object_set_data_full (GTK_OBJECT (intf_window), "dvd_box", dvd_box,
(GtkDestroyNotify) gtk_widget_unref);
gtk_box_pack_start (GTK_BOX (vbox2), dvd_box, TRUE, TRUE, 0);
label_title = gtk_label_new (_("Title:"));
gtk_widget_ref (label_title);
gtk_object_set_data_full (GTK_OBJECT (intf_window), "label_title", label_title,
(GtkDestroyNotify) gtk_widget_unref);
gtk_widget_show (label_title);
gtk_box_pack_start (GTK_BOX (dvd_box), label_title, TRUE, FALSE, 0);
hbox6 = gtk_hbox_new (FALSE, 10);
gtk_widget_ref (hbox6);
gtk_object_set_data_full (GTK_OBJECT (intf_window), "hbox6", hbox6,
(GtkDestroyNotify) gtk_widget_unref);
gtk_widget_show (hbox6);
gtk_box_pack_start (GTK_BOX (dvd_box), hbox6, TRUE, FALSE, 0);
button_chapter_prev = gnome_stock_button (GNOME_STOCK_BUTTON_PREV);
gtk_widget_ref (button_chapter_prev);
gtk_object_set_data_full (GTK_OBJECT (intf_window), "button_chapter_prev", button_chapter_prev,
(GtkDestroyNotify) gtk_widget_unref);
gtk_widget_show (button_chapter_prev);
gtk_box_pack_start (GTK_BOX (hbox6), button_chapter_prev, FALSE, FALSE, 0);
gtk_tooltips_set_tip (tooltips, button_chapter_prev, _("Select previous chapter"), NULL);
gtk_button_set_relief (GTK_BUTTON (button_chapter_prev), GTK_RELIEF_NONE);
label_chapter = gtk_label_new (_("Chapter: "));
gtk_widget_ref (label_chapter);
gtk_object_set_data_full (GTK_OBJECT (intf_window), "label_chapter", label_chapter,
(GtkDestroyNotify) gtk_widget_unref);
gtk_widget_show (label_chapter);
gtk_box_pack_start (GTK_BOX (hbox6), label_chapter, FALSE, FALSE, 0);
button_chapter_next = gnome_stock_button (GNOME_STOCK_BUTTON_NEXT);
gtk_widget_ref (button_chapter_next);
gtk_object_set_data_full (GTK_OBJECT (intf_window), "button_chapter_next", button_chapter_next,
(GtkDestroyNotify) gtk_widget_unref);
gtk_widget_show (button_chapter_next);
gtk_box_pack_start (GTK_BOX (hbox6), button_chapter_next, FALSE, FALSE, 0);
gtk_tooltips_set_tip (tooltips, button_chapter_next, _("Select next chapter"), NULL);
gtk_button_set_relief (GTK_BUTTON (button_chapter_next), GTK_RELIEF_NONE);
appbar = gnome_appbar_new (TRUE, TRUE, GNOME_PREFERENCES_NEVER);
gtk_widget_ref (appbar);
gtk_object_set_data_full (GTK_OBJECT (intf_window), "appbar", appbar,
......@@ -518,6 +572,14 @@ create_intf_window (void)
gtk_signal_connect (GTK_OBJECT (slider), "button_release_event",
GTK_SIGNAL_FUNC (on_slider_button_release_event),
NULL);
gtk_signal_connect (GTK_OBJECT (button_chapter_prev), "clicked",
GTK_SIGNAL_FUNC (on_button_chapter_prev_clicked),
NULL);
gtk_signal_connect (GTK_OBJECT (button_chapter_next), "clicked",
GTK_SIGNAL_FUNC (on_button_chapter_next_clicked),
NULL);
gtk_object_set_data (GTK_OBJECT (intf_window), "tooltips", tooltips);
return intf_window;
}
......
......@@ -2,7 +2,7 @@
* intf_gnome.c: Gnome interface
*****************************************************************************
* Copyright (C) 1999, 2000 VideoLAN
* $Id: intf_gnome.c,v 1.24 2001/04/01 07:31:38 stef Exp $
* $Id: intf_gnome.c,v 1.25 2001/04/03 03:39:41 stef Exp $
*
* Authors: Samuel Hocevar <sam@zoy.org>
* Stphane Borel <stef@via.ecp.fr>
......@@ -49,6 +49,7 @@
#include "intf_msg.h"
#include "interface.h"
#include "intf_playlist.h"
#include "gnome_callbacks.h"
#include "gnome_interface.h"
......@@ -74,6 +75,7 @@ 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 GnomeDVDModeManage( intf_thread_t * p_intf );
/*****************************************************************************
* g_atexit: kludge to avoid the Gnome thread to segfault at exit
......@@ -149,6 +151,9 @@ static int intf_Open( intf_thread_t *p_intf )
p_intf->p_sys->b_slider_free = 1;
p_intf->p_sys->b_mode_changed = 0;
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;
......@@ -198,6 +203,16 @@ static void intf_Run( intf_thread_t *p_intf )
p_intf->p_sys->p_disc = create_intf_disc( );
p_intf->p_sys->p_network = create_intf_network( );
/* Sets the interface mode according to playlist item */
if( p_main->p_playlist->p_item != NULL )
{
if( !strncmp( p_main->p_playlist->p_item->psz_name, "dvd:", 4 ) )
{
p_intf->p_sys->i_intf_mode = DVD_MODE;
p_intf->p_sys->b_mode_changed = 1;
}
}
/* Set the title of the main window */
gtk_window_set_title( GTK_WINDOW(p_intf->p_sys->p_window),
VOUT_TITLE " (Gnome interface)");
......@@ -212,6 +227,8 @@ static void intf_Run( intf_thread_t *p_intf )
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 */
......@@ -296,6 +313,20 @@ static gint GnomeManage( gpointer p_data )
p_intf->b_menu_change = 0;
}
if( p_intf->p_input != NULL && p_intf->p_sys->p_window != NULL &&
p_intf->p_sys->b_mode_changed )
{
switch( p_intf->p_sys->i_intf_mode )
{
case DVD_MODE:
GnomeDVDModeManage( p_intf );
break;
}
p_intf->p_sys->b_mode_changed = 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 )
......@@ -445,7 +476,6 @@ static gint GnomeLanguageMenus( gpointer p_data,
{
/* don't lose p_item when we append into menu */
p_item_active = p_item;
gtk_object_ref( GTK_OBJECT( p_item_active ) );
}
gtk_widget_show( p_item );
......@@ -470,7 +500,6 @@ static gint GnomeLanguageMenus( gpointer p_data,
{
gtk_check_menu_item_set_active( GTK_CHECK_MENU_ITEM( p_item_active ),
TRUE );
gtk_object_unref( GTK_OBJECT( p_item_active ) );
}
/* be sure that menu is sensitive if non empty */
......@@ -519,7 +548,7 @@ static gint GnomeChapterMenu( gpointer p_data, GtkWidget * p_chapter,
for( i_chapter = 0 ; i_chapter < i_nb ; i_chapter++ )
{
/* we group chapters in packets of ten for small screens */
if( ( i_chapter % 10 == 0 ) )// && ( i_nb > 20 ) )
if( ( i_chapter % 10 == 0 ) && ( i_nb > 20 ) )
{
if( i_chapter != 0 )
{
......@@ -545,7 +574,6 @@ static gint GnomeChapterMenu( gpointer p_data, GtkWidget * p_chapter,
== i_chapter + 1 )
{
p_item_selected = p_item;
gtk_object_ref( GTK_OBJECT( p_item_selected ) );
}
gtk_widget_show( p_item );
......@@ -556,13 +584,22 @@ static gint GnomeChapterMenu( gpointer p_data, GtkWidget * p_chapter,
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 ),
......@@ -573,7 +610,6 @@ static gint GnomeChapterMenu( gpointer p_data, GtkWidget * p_chapter,
{
gtk_check_menu_item_set_active( GTK_CHECK_MENU_ITEM( p_item_selected ),
TRUE );
gtk_object_unref( GTK_OBJECT( p_item_selected ) );
}
/* be sure that chapter menu is sensitive, if there are several items */
......@@ -611,7 +647,8 @@ static gint GnomeTitleMenu( gpointer p_data,
GSList * p_chapter_group;
gint i_title;
gint i_chapter;
gint i_nb;
gint i_title_nb;
gint i_chapter_nb;
/* cast */
p_intf = (intf_thread_t*)p_data;
......@@ -624,13 +661,13 @@ static gint GnomeTitleMenu( gpointer p_data,
p_chapter_submenu = NULL;
p_chapter_menu_item = NULL;
p_item_active = NULL;
i_nb = p_intf->p_input->stream.i_area_nb;
i_title_nb = p_intf->p_input->stream.i_area_nb;
/* loop on titles */
for( i_title = 1 ; i_title < i_nb ; i_title++ )
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_nb > 20 ) )
if( ( i_title % 10 == 1 ) && ( i_title_nb > 20 ) )
{
if( i_title != 1 )
{
......@@ -658,7 +695,6 @@ static gint GnomeTitleMenu( gpointer p_data,
p_intf->p_input->stream.p_selected_area )
{
p_item_active = p_title_item;
gtk_object_ref( GTK_OBJECT( p_item_active ) );
}
/* setup signal hanling */
......@@ -678,14 +714,13 @@ static gint GnomeTitleMenu( gpointer p_data,
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++ )
{
/* we group chapters in packets of ten for small screens */
if( ( i_chapter % 10 == 0 ) )// && ( i_nb > 20 ) )
if( ( i_chapter % 10 == 0 ) && ( i_chapter_nb > 20 ) )
{
if( i_chapter != 0 )
{
......@@ -716,7 +751,6 @@ static gint GnomeTitleMenu( gpointer p_data,
== i_chapter + 1 )
{
p_item_active = p_item;
gtk_object_ref( GTK_OBJECT( p_item_active ) );
}
/* setup signal hanling */
......@@ -725,12 +759,23 @@ static gint GnomeTitleMenu( gpointer p_data,
GTK_SIGNAL_FUNC( pf_toggle ),
(gpointer)( ( i_title * 100 ) + ( 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 );
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 ),
......@@ -744,12 +789,22 @@ static gint GnomeTitleMenu( gpointer p_data,
}
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 );
......@@ -761,7 +816,6 @@ static gint GnomeTitleMenu( gpointer p_data,
{
gtk_check_menu_item_set_active( GTK_CHECK_MENU_ITEM( p_item_active ),
TRUE );
gtk_object_unref( GTK_OBJECT( p_item_active ) );
}
......@@ -780,8 +834,6 @@ static gint GnomeSetupMenu( intf_thread_t * p_intf )
GtkWidget * p_popup_menu;
gint i;
vlc_mutex_lock( &p_intf->p_input->stream.stream_lock );
if( p_intf->p_input->stream.i_area_nb > 1 )
{
p_menubar_menu = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT(
......@@ -814,8 +866,6 @@ static gint GnomeSetupMenu( intf_thread_t * p_intf )
}
}
vlc_mutex_unlock( &p_intf->p_input->stream.stream_lock );
/* audio menus */
/* find audio root menu */
......@@ -879,3 +929,33 @@ void GnomeDisplayDate( GtkAdjustment *p_adj )
}
/*****************************************************************************
* GnomeDVDModeManage
*****************************************************************************/
static gint GnomeDVDModeManage( intf_thread_t * p_intf )
{
GtkWidget * p_dvd_box;
GtkWidget * p_toolbar_next;
GtkWidget * p_toolbar_prev;
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 ) );
p_toolbar_next = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT(
p_intf->p_sys->p_window ), "toolbar_next" ) );
gtk_signal_disconnect_by_data( GTK_OBJECT( p_toolbar_next ), NULL );
gtk_signal_connect( GTK_OBJECT( p_toolbar_next ), "clicked",
GTK_SIGNAL_FUNC( on_toolbar_next_title_clicked ),
NULL);
p_toolbar_prev = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT(
p_intf->p_sys->p_window ), "toolbar_prev" ) );
gtk_signal_disconnect_by_data( GTK_OBJECT( p_toolbar_prev ), NULL );
gtk_signal_connect( GTK_OBJECT( p_toolbar_prev ), "clicked",
GTK_SIGNAL_FUNC( on_toolbar_prev_title_clicked ),
NULL);
return TRUE;
}
......@@ -581,6 +581,103 @@
<fill>True</fill>
</child>
</widget>
<widget>
<class>GtkHBox</class>
<name>dvd_box</name>
<visible>False</visible>
<homogeneous>False</homogeneous>
<spacing>0</spacing>
<child>
<padding>0</padding>
<expand>True</expand>
<fill>True</fill>
</child>
<widget>
<class>GtkLabel</class>
<name>label_title</name>
<label>Title:</label>
<justify>GTK_JUSTIFY_CENTER</justify>
<wrap>False</wrap>
<xalign>0.5</xalign>
<yalign>0.5</yalign>
<xpad>0</xpad>
<ypad>0</ypad>
<child>
<padding>0</padding>
<expand>True</expand>
<fill>False</fill>
</child>
</widget>
<widget>
<class>GtkHBox</class>
<name>hbox6</name>
<homogeneous>False</homogeneous>
<spacing>10</spacing>
<child>
<padding>0</padding>
<expand>True</expand>
<fill>False</fill>
</child>
<widget>
<class>GtkButton</class>
<name>button_chapter_prev</name>
<tooltip>Select previous chapter</tooltip>
<can_focus>True</can_focus>
<signal>