1 /*****************************************************************************
2 * gtk_callbacks.c : Callbacks for the Gtk+ plugin.
3 *****************************************************************************
4 * Copyright (C) 2000, 2001 VideoLAN
5 * $Id: gtk_callbacks.c,v 1.35 2002/04/03 02:43:14 sam Exp $
7 * Authors: Samuel Hocevar <sam@zoy.org>
8 * Stéphane Borel <stef@via.ecp.fr>
9 * Julien BLACHE <jb@technologeek.org>
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
24 *****************************************************************************/
26 /*****************************************************************************
28 *****************************************************************************/
29 #include <sys/types.h> /* off_t */
32 #include <videolan/vlc.h>
40 #include "stream_control.h"
41 #include "input_ext-intf.h"
43 #include "interface.h"
44 #include "intf_playlist.h"
45 #include "intf_eject.h"
48 #include "video_output.h"
50 #include "gtk_callbacks.h"
51 #include "gtk_interface.h"
52 #include "gtk_support.h"
53 #include "gtk_common.h"
57 /*****************************************************************************
59 *****************************************************************************/
62 * Main interface callbacks
65 gboolean GtkExit( GtkWidget *widget,
66 GdkEventButton *event,
69 intf_thread_t *p_intf = GetIntf( GTK_WIDGET(widget), (char*)user_data );
71 vlc_mutex_lock( &p_intf->change_lock );
73 vlc_mutex_unlock( &p_intf->change_lock );
78 gboolean GtkWindowDelete( GtkWidget *widget,
82 GtkExit( GTK_WIDGET( widget ), NULL, user_data );
88 gboolean GtkWindowToggle( GtkWidget *widget,
89 GdkEventButton *event,
92 intf_thread_t *p_intf = GetIntf( GTK_WIDGET(widget), (char*)user_data );
94 if( GTK_WIDGET_VISIBLE(p_intf->p_sys->p_window) )
96 gtk_widget_hide( p_intf->p_sys->p_window);
101 gtk_widget_show( p_intf->p_sys->p_window );
107 gboolean GtkFullscreen( GtkWidget *widget,
108 GdkEventButton *event,
111 if( p_vout_bank->i_count )
113 vlc_mutex_lock( &p_vout_bank->pp_vout[0]->change_lock );
115 p_vout_bank->pp_vout[0]->i_changes |= VOUT_FULLSCREEN_CHANGE;
117 vlc_mutex_unlock( &p_vout_bank->pp_vout[0]->change_lock );
127 void GtkWindowDrag( GtkWidget *widget,
128 GdkDragContext *drag_context,
131 GtkSelectionData *data,
136 intf_thread_t * p_intf = GetIntf( GTK_WIDGET(widget), "intf_window" );
137 int end = p_main->p_playlist->i_size;
138 GtkDropDataReceived( p_intf, data, info, PLAYLIST_END );
140 if( p_input_bank->pp_input[0] != NULL )
142 /* FIXME: temporary hack */
143 p_input_bank->pp_input[0]->b_eof = 1;
146 intf_PlaylistJumpto( p_main->p_playlist, end-1 );
150 /****************************************************************************
152 ****************************************************************************/
154 gboolean GtkSliderRelease( GtkWidget *widget,
155 GdkEventButton *event,
158 intf_thread_t *p_intf = GetIntf( GTK_WIDGET(widget), "intf_window" );
160 vlc_mutex_lock( &p_intf->change_lock );
161 p_intf->p_sys->b_slider_free = 1;
162 vlc_mutex_unlock( &p_intf->change_lock );
168 gboolean GtkSliderPress( GtkWidget *widget,
169 GdkEventButton *event,
172 intf_thread_t *p_intf = GetIntf( GTK_WIDGET(widget), "intf_window" );
174 vlc_mutex_lock( &p_intf->change_lock );
175 p_intf->p_sys->b_slider_free = 0;
176 vlc_mutex_unlock( &p_intf->change_lock );
182 /****************************************************************************
184 ****************************************************************************/
186 void GtkTitlePrev( GtkButton * button, gpointer user_data )
188 intf_thread_t * p_intf;
189 input_area_t * p_area;
192 p_intf = GetIntf( GTK_WIDGET(button), (char*)user_data );
193 i_id = p_input_bank->pp_input[0]->stream.p_selected_area->i_id - 1;
195 /* Disallow area 0 since it is used for video_ts.vob */
198 p_area = p_input_bank->pp_input[0]->stream.pp_areas[i_id];
199 input_ChangeArea( p_input_bank->pp_input[0], (input_area_t*)p_area );
201 input_SetStatus( p_input_bank->pp_input[0], INPUT_STATUS_PLAY );
203 p_intf->p_sys->b_title_update = 1;
204 vlc_mutex_lock( &p_input_bank->pp_input[0]->stream.stream_lock );
205 GtkSetupMenus( p_intf );
206 vlc_mutex_unlock( &p_input_bank->pp_input[0]->stream.stream_lock );
211 void GtkTitleNext( GtkButton * button, gpointer user_data )
213 intf_thread_t * p_intf;
214 input_area_t * p_area;
217 p_intf = GetIntf( GTK_WIDGET(button), (char*)user_data );
218 i_id = p_input_bank->pp_input[0]->stream.p_selected_area->i_id + 1;
220 if( i_id < p_input_bank->pp_input[0]->stream.i_area_nb )
222 p_area = p_input_bank->pp_input[0]->stream.pp_areas[i_id];
223 input_ChangeArea( p_input_bank->pp_input[0], (input_area_t*)p_area );
225 input_SetStatus( p_input_bank->pp_input[0], INPUT_STATUS_PLAY );
227 p_intf->p_sys->b_title_update = 1;
228 vlc_mutex_lock( &p_input_bank->pp_input[0]->stream.stream_lock );
229 GtkSetupMenus( p_intf );
230 vlc_mutex_unlock( &p_input_bank->pp_input[0]->stream.stream_lock );
236 void GtkChapterPrev( GtkButton * button, gpointer user_data )
238 intf_thread_t * p_intf;
239 input_area_t * p_area;
241 p_intf = GetIntf( GTK_WIDGET(button), (char*)user_data );
242 p_area = p_input_bank->pp_input[0]->stream.p_selected_area;
244 if( p_area->i_part > 0 )
247 input_ChangeArea( p_input_bank->pp_input[0], (input_area_t*)p_area );
249 input_SetStatus( p_input_bank->pp_input[0], INPUT_STATUS_PLAY );
251 p_intf->p_sys->b_chapter_update = 1;
252 vlc_mutex_lock( &p_input_bank->pp_input[0]->stream.stream_lock );
253 GtkSetupMenus( p_intf );
254 vlc_mutex_unlock( &p_input_bank->pp_input[0]->stream.stream_lock );
259 void GtkChapterNext( GtkButton * button, gpointer user_data )
261 intf_thread_t * p_intf;
262 input_area_t * p_area;
264 p_intf = GetIntf( GTK_WIDGET(button), (char*)user_data );
265 p_area = p_input_bank->pp_input[0]->stream.p_selected_area;
267 if( p_area->i_part < p_area->i_part_nb )
270 input_ChangeArea( p_input_bank->pp_input[0], (input_area_t*)p_area );
272 input_SetStatus( p_input_bank->pp_input[0], INPUT_STATUS_PLAY );
274 p_intf->p_sys->b_chapter_update = 1;
275 vlc_mutex_lock( &p_input_bank->pp_input[0]->stream.stream_lock );
276 GtkSetupMenus( p_intf );
277 vlc_mutex_unlock( &p_input_bank->pp_input[0]->stream.stream_lock );
281 /****************************************************************************
282 * Network specific items
283 ****************************************************************************/
284 void GtkNetworkJoin( GtkEditable * editable, gpointer user_data )
288 i_channel = gtk_spin_button_get_value_as_int( GTK_SPIN_BUTTON( editable ) );
289 // intf_WarnMsg( 3, "intf info: joining channel %d", i_channel );
291 // network_ChannelJoin( i_channel );
294 void GtkChannelGo( GtkButton * button, gpointer user_data )
300 intf_thread_t *p_intf = GetIntf( GTK_WIDGET(button), (char*)user_data );
302 window = gtk_widget_get_toplevel( GTK_WIDGET (button) );
303 spin = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT( window ),
304 "network_channel_spinbutton" ) );
306 i_channel = gtk_spin_button_get_value_as_int( GTK_SPIN_BUTTON( spin ) );
307 intf_WarnMsg( 3, "intf info: joining channel %d", i_channel );
309 vlc_mutex_lock( &p_intf->change_lock );
310 if( p_input_bank->pp_input[0] != NULL )
312 /* end playing item */
313 p_input_bank->pp_input[0]->b_eof = 1;
315 /* update playlist */
316 vlc_mutex_lock( &p_main->p_playlist->change_lock );
318 p_main->p_playlist->i_index--;
319 p_main->p_playlist->b_stopped = 1;
321 vlc_mutex_unlock( &p_main->p_playlist->change_lock );
323 /* FIXME: ugly hack to close input and outputs */
324 p_intf->pf_manage( p_intf );
327 network_ChannelJoin( i_channel );
330 p_main->p_playlist->b_stopped = 0;
331 p_intf->pf_manage( p_intf );
333 vlc_mutex_unlock( &p_intf->change_lock );
335 // input_SetStatus( p_input_bank->pp_input[0], INPUT_STATUS_PLAY );
339 /****************************************************************************
341 ****************************************************************************/
343 gboolean GtkAboutShow( GtkWidget *widget,
344 GdkEventButton *event,
347 intf_thread_t *p_intf = GetIntf( GTK_WIDGET(widget), (char*)user_data );
349 if( !GTK_IS_WIDGET( p_intf->p_sys->p_about ) )
351 p_intf->p_sys->p_about = create_intf_about();
352 gtk_object_set_data( GTK_OBJECT( p_intf->p_sys->p_about ),
355 gtk_widget_show( p_intf->p_sys->p_about );
356 gdk_window_raise( p_intf->p_sys->p_about->window );
361 void GtkAboutOk( GtkButton * button, gpointer user_data)
363 intf_thread_t *p_intf = GetIntf( GTK_WIDGET(button), (char*)user_data );
365 gtk_widget_hide( p_intf->p_sys->p_about );
369 /****************************************************************************
371 ****************************************************************************/
373 gboolean GtkJumpShow( GtkWidget *widget,
374 GdkEventButton *event,
377 intf_thread_t *p_intf = GetIntf( GTK_WIDGET(widget), (char*)user_data );
379 if( !GTK_IS_WIDGET( p_intf->p_sys->p_jump ) )
381 p_intf->p_sys->p_jump = create_intf_jump();
382 gtk_object_set_data( GTK_OBJECT( p_intf->p_sys->p_jump ),
386 gtk_widget_show( p_intf->p_sys->p_jump );
387 gdk_window_raise( p_intf->p_sys->p_jump->window );
393 void GtkJumpOk( GtkButton *button,
396 intf_thread_t * p_intf;
403 p_intf = GetIntf( GTK_WIDGET( button ), (char*)user_data );
405 #define GET_VALUE( name ) \
406 gtk_spin_button_get_value_as_int( GTK_SPIN_BUTTON( gtk_object_get_data( \
407 GTK_OBJECT( p_intf->p_sys->p_jump ), name ) ) )
409 i_hours = GET_VALUE( "jump_hour_spinbutton" );
410 i_minutes = GET_VALUE( "jump_minute_spinbutton" );
411 i_seconds = GET_VALUE( "jump_second_spinbutton" );
415 i_seconds += 60 *i_minutes + 3600* i_hours;
417 vlc_mutex_lock( &p_input_bank->pp_input[0]->stream.stream_lock );
418 i_seek = i_seconds * 50 * p_input_bank->pp_input[0]->stream.i_mux_rate;
419 i_size = p_input_bank->pp_input[0]->stream.p_selected_area->i_size;
420 vlc_mutex_unlock( &p_input_bank->pp_input[0]->stream.stream_lock );
422 if( i_seek < i_size )
424 input_Seek( p_input_bank->pp_input[0], i_seek );
426 p_main->p_playlist->b_stopped = 0;
427 gtk_widget_hide( gtk_widget_get_toplevel( GTK_WIDGET (button) ) );
431 void GtkJumpCancel( GtkButton *button,
434 gtk_widget_hide( gtk_widget_get_toplevel( GTK_WIDGET (button) ) );
438 /****************************************************************************
439 * Callbacks for menuitems
440 ****************************************************************************/
441 void GtkExitActivate( GtkMenuItem * menuitem, gpointer user_data )
443 GtkExit( GTK_WIDGET( menuitem ), NULL, user_data );
447 void GtkFullscreenActivate( GtkMenuItem * menuitem, gpointer user_data )
449 GtkFullscreen( GTK_WIDGET( menuitem ), NULL, user_data );
453 void GtkWindowToggleActivate( GtkMenuItem * menuitem, gpointer user_data )
455 GtkWindowToggle( GTK_WIDGET( menuitem ), NULL, user_data );
459 void GtkAboutActivate( GtkMenuItem * menuitem, gpointer user_data )
461 GtkAboutShow( GTK_WIDGET( menuitem ), NULL, user_data );
465 void GtkJumpActivate( GtkMenuItem * menuitem, gpointer user_data )
467 GtkJumpShow( GTK_WIDGET( menuitem ), NULL, user_data );
471 void GtkMessagesActivate( GtkMenuItem * menuitem, gpointer user_data )
473 GtkMessagesShow( GTK_WIDGET( menuitem ), NULL, user_data );
477 /****************************************************************************
478 * Callbacks for disc ejection
479 ****************************************************************************/
480 gboolean GtkDiscEject ( GtkWidget *widget, GdkEventButton *event,
483 char *psz_device = NULL;
486 * Get the active input
487 * Determine whether we can eject a media, ie it's a VCD or DVD
488 * If it's neither a VCD nor a DVD, then return
492 * Don't really know if I must lock the stuff here, we're using it read-only
495 if (p_main->p_playlist->current.psz_name != NULL)
497 if( !strncmp(p_main->p_playlist->current.psz_name, "dvd:", 4) )
499 switch( p_main->p_playlist->current.psz_name[4] )
503 psz_device = strdup( DVD_DEVICE );
506 /* Omit the first 4 characters */
507 psz_device = strdup( p_main->p_playlist->current.psz_name + 4 );
511 else if( !strncmp(p_main->p_playlist->current.psz_name, "vcd:", 4) )
513 switch( p_main->p_playlist->current.psz_name[4] )
517 psz_device = strdup( VCD_DEVICE );
520 /* Omit the first 4 characters */
521 psz_device = strdup( p_main->p_playlist->current.psz_name + 4 );
527 psz_device = strdup( p_main->p_playlist->current.psz_name );
531 if( psz_device == NULL )
536 /* If there's a stream playing, we aren't allowed to eject ! */
537 if( p_input_bank->pp_input[0] == NULL )
539 intf_WarnMsg( 4, "intf: ejecting %s", psz_device );
541 intf_Eject( psz_device );
548 void GtkEjectDiscActivate ( GtkMenuItem *menuitem, gpointer user_data )
550 GtkDiscEject( GTK_WIDGET( menuitem ), NULL, user_data );
553 /****************************************************************************
555 ****************************************************************************/
557 gboolean GtkMessagesShow( GtkWidget *widget,
558 GdkEventButton *event,
561 static GdkColor black = { 0, 0x0000, 0x0000, 0x0000 };
562 static GdkColormap *colormap;
563 intf_thread_t *p_intf = GetIntf( GTK_WIDGET(widget), (char*)user_data );
565 gtk_widget_show( p_intf->p_sys->p_messages );
566 colormap = gdk_colormap_get_system ();
567 gdk_color_alloc( colormap, &black );
568 gdk_window_set_background( p_intf->p_sys->p_messages_text->text_area,
571 gdk_window_raise( p_intf->p_sys->p_messages->window );
573 gtk_text_set_point( p_intf->p_sys->p_messages_text,
574 gtk_text_get_length( p_intf->p_sys->p_messages_text ) );
581 GtkMessagesOk (GtkButton *button,
584 intf_thread_t *p_intf = GetIntf( GTK_WIDGET(button), (char*)user_data );
585 gtk_widget_hide( p_intf->p_sys->p_messages );
590 GtkMessagesDelete (GtkWidget *widget,
594 intf_thread_t *p_intf = GetIntf( GTK_WIDGET(widget), (char*)user_data );
595 gtk_widget_hide( p_intf->p_sys->p_messages );