gtk.c
上传用户:riyaled888
上传日期:2009-03-27
资源大小:7338k
文件大小:20k
源码类别:

多媒体

开发平台:

MultiPlatform

  1. /*****************************************************************************
  2.  * gtk.c : Gtk+ plugin for vlc
  3.  *****************************************************************************
  4.  * Copyright (C) 2000-2001 VideoLAN
  5.  * $Id: gtk.c 7932 2004-06-07 18:26:27Z fenrir $
  6.  *
  7.  * Authors: Samuel Hocevar <sam@zoy.org>
  8.  *
  9.  * This program is free software; you can redistribute it and/or modify
  10.  * it under the terms of the GNU General Public License as published by
  11.  * the Free Software Foundation; either version 2 of the License, or
  12.  * (at your option) any later version.
  13.  *
  14.  * This program is distributed in the hope that it will be useful,
  15.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17.  * GNU General Public License for more details.
  18.  *
  19.  * You should have received a copy of the GNU General Public License
  20.  * along with this program; if not, write to the Free Software
  21.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
  22.  *****************************************************************************/
  23. /*****************************************************************************
  24.  * Preamble
  25.  *****************************************************************************/
  26. #include <stdlib.h>                                      /* malloc(), free() */
  27. #include <errno.h>                                                 /* ENOMEM */
  28. #include <string.h>                                            /* strerror() */
  29. #include <stdio.h>
  30. #include <vlc/vlc.h>
  31. #include <vlc/intf.h>
  32. #include <gtk/gtk.h>
  33. #include "gtk_callbacks.h"
  34. #include "gtk_interface.h"
  35. #include "gtk_support.h"
  36. #include "menu.h"
  37. #include "display.h"
  38. #include "common.h"
  39. /*****************************************************************************
  40.  * Local prototypes.
  41.  *****************************************************************************/
  42. static int  Open         ( vlc_object_t * );
  43. static void Close        ( vlc_object_t * );
  44. static void Run          ( intf_thread_t * );
  45. static int  Manage       ( intf_thread_t * );
  46. /*****************************************************************************
  47.  * Module descriptor
  48.  *****************************************************************************/
  49. #define TOOLTIPS_TEXT N_("Show tooltips")
  50. #define TOOLTIPS_LONGTEXT N_("Show tooltips for configuration options.")
  51. #define PREFS_MAXH_TEXT N_("Maximum height for the configuration windows")
  52. #define PREFS_MAXH_LONGTEXT N_( 
  53.     "You can set the maximum height that the configuration windows in the " 
  54.     "preferences menu will occupy.")
  55. #define PATH_TEXT N_("Interface default search path")
  56. #define PATH_LONGTEXT N_( 
  57.     "This option allows you to set the default path that the interface will " 
  58.     "open when looking for a file.")
  59. vlc_module_begin();
  60. #ifdef WIN32
  61.     int i = 90;
  62. #else
  63.     int i = getenv( "DISPLAY" ) == NULL ? 10 : 90;
  64. #endif
  65.     set_description( _("Gtk+ interface") );
  66.     add_bool( "gtk-tooltips", 1, E_(GtkHideTooltips),
  67.               TOOLTIPS_TEXT, TOOLTIPS_LONGTEXT, VLC_FALSE );
  68.     add_integer( "gtk-prefs-maxh", 480, NULL,
  69.                  PREFS_MAXH_TEXT, PREFS_MAXH_LONGTEXT, VLC_TRUE );
  70.     add_directory( "gtk-search-path", NULL, NULL, PATH_TEXT,
  71.                    PATH_LONGTEXT, VLC_TRUE );
  72.     set_capability( "interface", i );
  73.     set_callbacks( Open, Close );
  74.     add_shortcut( "gtk" );
  75.     set_program( "gvlc" );
  76. vlc_module_end();
  77. /*****************************************************************************
  78.  * Open: initialize and create window
  79.  *****************************************************************************/
  80. static int Open( vlc_object_t *p_this )
  81. {
  82.     intf_thread_t *p_intf = (intf_thread_t *)p_this;
  83.     /* Allocate instance and initialize some members */
  84.     p_intf->p_sys = malloc( sizeof( intf_sys_t ) );
  85.     if( p_intf->p_sys == NULL )
  86.     {
  87.         msg_Err( p_intf, "out of memory" );
  88.         return VLC_ENOMEM;
  89.     }
  90. #ifdef NEED_GTK_MAIN
  91.     p_intf->p_sys->p_gtk_main =
  92.         module_Need( p_this, "gui-helper", "gtk", VLC_TRUE );
  93.     if( p_intf->p_sys->p_gtk_main == NULL )
  94.     {
  95.         free( p_intf->p_sys );
  96.         return VLC_ENOMOD;
  97.     }
  98. #endif
  99.     p_intf->pf_run = Run;
  100.     p_intf->p_sys->p_sub = msg_Subscribe( p_intf );
  101.     /* Initialize Gtk+ thread */
  102.     p_intf->p_sys->b_playing = VLC_FALSE;
  103.     p_intf->p_sys->b_deinterlace_update = VLC_FALSE;
  104.     p_intf->p_sys->b_aout_update = VLC_FALSE;
  105.     p_intf->p_sys->b_vout_update = VLC_FALSE;
  106.     p_intf->p_sys->b_popup_changed = VLC_FALSE;
  107.     p_intf->p_sys->b_window_changed = VLC_FALSE;
  108.     p_intf->p_sys->b_playlist_changed = VLC_FALSE;
  109.     p_intf->p_sys->b_program_update = VLC_FALSE;
  110.     p_intf->p_sys->b_title_update = VLC_FALSE;
  111.     p_intf->p_sys->b_chapter_update = VLC_FALSE;
  112.     p_intf->p_sys->b_spu_update = VLC_FALSE;
  113.     p_intf->p_sys->b_audio_update = VLC_FALSE;
  114.     p_intf->p_sys->p_input = NULL;
  115.     p_intf->p_sys->i_playing = -1;
  116.     p_intf->p_sys->b_slider_free = VLC_TRUE;
  117.     p_intf->p_sys->i_part = 0;
  118.     p_intf->p_sys->b_mute = VLC_FALSE;
  119.     return VLC_SUCCESS;
  120. }
  121. /*****************************************************************************
  122.  * Close: destroy interface window
  123.  *****************************************************************************/
  124. static void Close( vlc_object_t *p_this )
  125. {
  126.     intf_thread_t *p_intf = (intf_thread_t *)p_this;
  127.     if( p_intf->p_sys->p_input )
  128.     {
  129.         vlc_object_release( p_intf->p_sys->p_input );
  130.     }
  131.     msg_Unsubscribe( p_intf, p_intf->p_sys->p_sub );
  132. #ifdef NEED_GTK_MAIN
  133.     module_Unneed( p_intf, p_intf->p_sys->p_gtk_main );
  134. #endif
  135.     /* Destroy structure */
  136.     free( p_intf->p_sys );
  137. }
  138. /*****************************************************************************
  139.  * Run: Gtk+ thread
  140.  *****************************************************************************
  141.  * this part of the interface is in a separate thread so that we can call
  142.  * gtk_main() from within it without annoying the rest of the program.
  143.  *****************************************************************************/
  144. static void Run( intf_thread_t *p_intf )
  145. {
  146.     /* The data types we are allowed to receive */
  147.     static GtkTargetEntry target_table[] =
  148.     {
  149.         { "STRING", 0, DROP_ACCEPT_STRING },
  150.         { "text/uri-list", 0, DROP_ACCEPT_TEXT_URI_LIST },
  151.         { "text/plain", 0, DROP_ACCEPT_TEXT_PLAIN }
  152.     };
  153.     char *psz_sout;
  154.     GString *       p_target;
  155. #ifdef NEED_GTK_MAIN
  156.     gdk_threads_enter();
  157. #else
  158.     /* gtk_init needs to know the command line. We don't care, so we
  159.      * give it an empty one */
  160.     char  *p_args[] = { "", NULL };
  161.     char **pp_args  = p_args;
  162.     int    i_args   = 1;
  163.     int    i_dummy;
  164.     gtk_init( &i_args, &pp_args );
  165. #endif
  166.     /* Create some useful widgets that will certainly be used */
  167.     p_intf->p_sys->p_window = create_intf_window();
  168.     p_intf->p_sys->p_popup = create_intf_popup();
  169.     p_intf->p_sys->p_playwin = create_intf_playlist();
  170.     p_intf->p_sys->p_messages = create_intf_messages();
  171.     p_intf->p_sys->p_tooltips = gtk_tooltips_new();
  172.     p_intf->p_sys->p_sout = create_intf_sout();
  173.     /* Set the title of the main window */
  174.     gtk_window_set_title( GTK_WINDOW(p_intf->p_sys->p_window),
  175.                           VOUT_TITLE " (Gtk+ interface)");
  176.     /* Accept file drops on the main window */
  177.     gtk_drag_dest_set( GTK_WIDGET( p_intf->p_sys->p_window ),
  178.                        GTK_DEST_DEFAULT_ALL, target_table,
  179.                        DROP_ACCEPT_END, GDK_ACTION_COPY );
  180.     /* Accept file drops on the playlist window */
  181.     gtk_drag_dest_set( GTK_WIDGET( lookup_widget( p_intf->p_sys->p_playwin,
  182.                                    "playlist_clist") ),
  183.                        GTK_DEST_DEFAULT_ALL, target_table,
  184.                        DROP_ACCEPT_END, GDK_ACTION_COPY );
  185.     /* Get the slider object */
  186.     p_intf->p_sys->p_slider_frame = GTK_FRAME( gtk_object_get_data(
  187.         GTK_OBJECT( p_intf->p_sys->p_window ), "slider_frame" ) );
  188.     /* Configure the log window */
  189.     p_intf->p_sys->p_messages_text = GTK_TEXT( gtk_object_get_data(
  190.         GTK_OBJECT(p_intf->p_sys->p_messages ), "messages_textbox" ) );
  191.     gtk_text_set_line_wrap( p_intf->p_sys->p_messages_text, TRUE);
  192.     gtk_text_set_word_wrap( p_intf->p_sys->p_messages_text, FALSE);
  193.     /* Get the interface labels */
  194. #define P_LABEL( name ) GTK_LABEL( gtk_object_get_data( 
  195.                          GTK_OBJECT( p_intf->p_sys->p_window ), name ) )
  196.     p_intf->p_sys->p_label_title = P_LABEL( "title_label" );
  197.     p_intf->p_sys->p_label_chapter = P_LABEL( "chapter_label" );
  198. #undef P_LABEL
  199.     /* Connect the date display to the slider */
  200. #define P_SLIDER GTK_RANGE( gtk_object_get_data( 
  201.                          GTK_OBJECT( p_intf->p_sys->p_window ), "slider" ) )
  202.     p_intf->p_sys->p_adj = gtk_range_get_adjustment( P_SLIDER );
  203.     gtk_signal_connect ( GTK_OBJECT( p_intf->p_sys->p_adj ), "value_changed",
  204.                          GTK_SIGNAL_FUNC( E_(GtkDisplayDate) ), NULL );
  205.     p_intf->p_sys->f_adj_oldvalue = 0;
  206. #undef P_SLIDER
  207.     /* We don't create these ones yet because we perhaps won't need them */
  208.     p_intf->p_sys->p_about = NULL;
  209.     p_intf->p_sys->p_modules = NULL;
  210.     p_intf->p_sys->p_open = NULL;
  211.     p_intf->p_sys->p_jump = NULL;
  212.     /* Hide tooltips if the option is set */
  213.     if( !config_GetInt( p_intf, "gtk-tooltips" ) )
  214.     {
  215.         gtk_tooltips_disable( p_intf->p_sys->p_tooltips );
  216.     }
  217.     /* Store p_intf to keep an eye on it */
  218.     gtk_object_set_data( GTK_OBJECT(p_intf->p_sys->p_window),
  219.                          "p_intf", p_intf );
  220.     gtk_object_set_data( GTK_OBJECT(p_intf->p_sys->p_popup),
  221.                          "p_intf", p_intf );
  222.     gtk_object_set_data( GTK_OBJECT( gtk_object_get_data(
  223.                              GTK_OBJECT(p_intf->p_sys->p_popup),
  224.                              "popup_audio" ) ), "p_intf", p_intf );
  225.     gtk_object_set_data( GTK_OBJECT( gtk_object_get_data(
  226.                              GTK_OBJECT(p_intf->p_sys->p_popup),
  227.                              "popup_video" ) ), "p_intf", p_intf );
  228.     gtk_object_set_data( GTK_OBJECT( p_intf->p_sys->p_playwin ),
  229.                          "p_intf", p_intf );
  230.     gtk_object_set_data( GTK_OBJECT( p_intf->p_sys->p_messages ),
  231.                          "p_intf", p_intf );
  232.     gtk_object_set_data( GTK_OBJECT(p_intf->p_sys->p_adj),
  233.                          "p_intf", p_intf );
  234.     gtk_object_set_data( GTK_OBJECT( p_intf->p_sys->p_sout ),
  235.                          "p_intf", p_intf );
  236.     psz_sout = config_GetPsz( p_intf, "sout" );
  237.     p_target = g_string_new( psz_sout ? psz_sout : "" );
  238.     if( psz_sout ) free( psz_sout );
  239.     gtk_entry_set_text( gtk_object_get_data( GTK_OBJECT( p_intf->p_sys->p_sout ), "sout_entry_target" ), p_target->str );
  240.     g_string_free( p_target, TRUE );
  241.     /* FIXME it's to be sure that only file entry is selected */
  242.     gtk_toggle_button_set_active(  gtk_object_get_data( GTK_OBJECT( p_intf->p_sys->p_sout ),
  243.                                    "sout_access_udp" ), TRUE );
  244.     gtk_toggle_button_set_active(  gtk_object_get_data( GTK_OBJECT( p_intf->p_sys->p_sout ),
  245.                                    "sout_access_file" ), TRUE );
  246.     /* Show the control window */
  247.     gtk_widget_show( p_intf->p_sys->p_window );
  248. #ifdef NEED_GTK_MAIN
  249.     while( !p_intf->b_die )
  250.     {
  251.         Manage( p_intf );
  252.         /* Sleep to avoid using all CPU - since some interfaces need to
  253.          * access keyboard events, a 100ms delay is a good compromise */
  254.         gdk_threads_leave();
  255.         msleep( INTF_IDLE_SLEEP );
  256.         gdk_threads_enter();
  257.     }
  258. #else
  259.     /* Sleep to avoid using all CPU - since some interfaces needs to access
  260.      * keyboard events, a 100ms delay is a good compromise */
  261.     i_dummy = gtk_timeout_add( INTF_IDLE_SLEEP / 1000, (GtkFunction)Manage,
  262.                                p_intf );
  263.     /* Enter Gtk mode */
  264.     gtk_main();
  265.     /* Remove the timeout */
  266.     gtk_timeout_remove( i_dummy );
  267. #endif
  268.     /* Destroy the Tooltips structure */
  269.     gtk_object_destroy( GTK_OBJECT(p_intf->p_sys->p_tooltips) );
  270.     gtk_object_destroy( GTK_OBJECT(p_intf->p_sys->p_messages) );
  271.     gtk_object_destroy( GTK_OBJECT(p_intf->p_sys->p_playwin) );
  272.     gtk_object_destroy( GTK_OBJECT(p_intf->p_sys->p_popup) );
  273.     gtk_object_destroy( GTK_OBJECT(p_intf->p_sys->p_window) );
  274. #ifdef NEED_GTK_MAIN
  275.     gdk_threads_leave();
  276. #endif
  277. }
  278. /* following functions are local */
  279. /*****************************************************************************
  280.  * Manage: manage main thread messages
  281.  *****************************************************************************
  282.  * In this function, called approx. 10 times a second, we check what the
  283.  * main program wanted to tell us.
  284.  *****************************************************************************/
  285. static int Manage( intf_thread_t *p_intf )
  286. {
  287.     int i_start, i_stop;
  288.     vlc_mutex_lock( &p_intf->change_lock );
  289.     /* If the "display popup" flag has changed */
  290.     if( p_intf->b_menu_change )
  291.     {
  292.         if( !GTK_IS_WIDGET( p_intf->p_sys->p_popup ) )
  293.         {
  294.             p_intf->p_sys->p_popup = create_intf_popup();
  295.             gtk_object_set_data( GTK_OBJECT( p_intf->p_sys->p_popup ),
  296.                                  "p_intf", p_intf );
  297.         }
  298.         gtk_menu_popup( GTK_MENU( p_intf->p_sys->p_popup ),
  299.                         NULL, NULL, NULL, NULL, 0, GDK_CURRENT_TIME );
  300.         p_intf->b_menu_change = 0;
  301.     }
  302.     /* Update the log window */
  303.     vlc_mutex_lock( p_intf->p_sys->p_sub->p_lock );
  304.     i_stop = *p_intf->p_sys->p_sub->pi_stop;
  305.     vlc_mutex_unlock( p_intf->p_sys->p_sub->p_lock );
  306.     if( p_intf->p_sys->p_sub->i_start != i_stop )
  307.     {
  308.         static GdkColor white  = { 0, 0xffff, 0xffff, 0xffff };
  309.         static GdkColor gray   = { 0, 0xaaaa, 0xaaaa, 0xaaaa };
  310.         static GdkColor yellow = { 0, 0xffff, 0xffff, 0x6666 };
  311.         static GdkColor red    = { 0, 0xffff, 0x6666, 0x6666 };
  312.         static const char * ppsz_type[4] = { ": ", " error: ", " warning: ",
  313.                                              " debug: " };
  314.         static GdkColor *   pp_color[4] = { &white, &red, &yellow, &gray };
  315.         for( i_start = p_intf->p_sys->p_sub->i_start;
  316.              i_start != i_stop;
  317.              i_start = (i_start+1) % VLC_MSG_QSIZE )
  318.         {
  319.             /* Append all messages to log window */
  320.             gtk_text_insert( p_intf->p_sys->p_messages_text, NULL, &gray,
  321.              NULL, p_intf->p_sys->p_sub->p_msg[i_start].psz_module, -1 );
  322.             gtk_text_insert( p_intf->p_sys->p_messages_text, NULL, &gray,
  323.                 NULL, ppsz_type[p_intf->p_sys->p_sub->p_msg[i_start].i_type],
  324.                 -1 );
  325.             gtk_text_insert( p_intf->p_sys->p_messages_text, NULL,
  326.                 pp_color[p_intf->p_sys->p_sub->p_msg[i_start].i_type], NULL,
  327.                 p_intf->p_sys->p_sub->p_msg[i_start].psz_msg, -1 );
  328.             gtk_text_insert( p_intf->p_sys->p_messages_text, NULL, &gray,
  329.                 NULL, "n", -1 );
  330.         }
  331.         vlc_mutex_lock( p_intf->p_sys->p_sub->p_lock );
  332.         p_intf->p_sys->p_sub->i_start = i_start;
  333.         vlc_mutex_unlock( p_intf->p_sys->p_sub->p_lock );
  334.         /* If the messages list becomes too big, just clean half of it. */
  335.         if( gtk_text_get_length( p_intf->p_sys->p_messages_text ) >
  336.             VLC_MSG_QSIZE * 1000 )
  337.         {
  338.             gtk_text_set_point( p_intf->p_sys->p_messages_text, 0 );
  339.             gtk_text_forward_delete( p_intf->p_sys->p_messages_text,
  340.                 gtk_text_get_length( p_intf->p_sys->p_messages_text ) / 2 );
  341.         }
  342.         gtk_text_set_point( p_intf->p_sys->p_messages_text,
  343.                     gtk_text_get_length( p_intf->p_sys->p_messages_text ) );
  344.     }
  345.     /* Update the playlist */
  346.     GtkPlayListManage( p_intf );
  347.     /* Update the input */
  348.     if( p_intf->p_sys->p_input == NULL )
  349.     {
  350.         p_intf->p_sys->p_input = vlc_object_find( p_intf, VLC_OBJECT_INPUT,
  351.                                                           FIND_ANYWHERE );
  352.     }
  353.     else if( p_intf->p_sys->p_input->b_dead )
  354.     {
  355.         vlc_object_release( p_intf->p_sys->p_input );
  356.         p_intf->p_sys->p_input = NULL;
  357.     }
  358.     if( p_intf->p_sys->p_input )
  359.     {
  360.         input_thread_t  *p_input = p_intf->p_sys->p_input;
  361.         aout_instance_t *p_aout  = NULL;
  362.         vout_thread_t   *p_vout  = NULL;
  363.         vlc_bool_t      b_need_menus = VLC_FALSE;
  364.         vlc_mutex_lock( &p_input->stream.stream_lock );
  365.         if( !p_input->b_die )
  366.         {
  367.             /* New input or stream map change */
  368.             if( p_input->stream.b_changed )
  369.             {
  370.                 E_(GtkModeManage)( p_intf );
  371.                 GtkSetupMenus( p_intf );
  372.                 p_intf->p_sys->b_playing = 1;
  373.             }
  374.             /* Manage the slider */
  375.             if( p_input->stream.b_seekable && p_intf->p_sys->b_playing )
  376.             {
  377.                 float newvalue = p_intf->p_sys->p_adj->value;
  378. #define p_area p_input->stream.p_selected_area
  379.                 /* If the user hasn't touched the slider since the last time,
  380.                  * then the input can safely change it */
  381.                 if( newvalue == p_intf->p_sys->f_adj_oldvalue )
  382.                 {
  383.                     /* Update the value */
  384.                     p_intf->p_sys->p_adj->value =
  385.                     p_intf->p_sys->f_adj_oldvalue =
  386.                         ( 100. * p_area->i_tell ) / p_area->i_size;
  387.                     gtk_signal_emit_by_name( GTK_OBJECT( p_intf->p_sys->p_adj ),
  388.                                              "value_changed" );
  389.                 }
  390.                 /* Otherwise, send message to the input if the user has
  391.                  * finished dragging the slider.
  392.                  * Beware, the hack below is needed by the dvdplay plugin! */
  393.                 else if( p_intf->p_sys->b_slider_free
  394.                 /* hack -> */ && (p_intf->p_sys->f_adj_oldvalue < 100.) )
  395.                 {
  396.                     if( newvalue >= 0. && newvalue < 100. )
  397.                     {
  398.                         double f_fpos = (double)newvalue / 100.0;
  399.                         /* release the lock to be able to seek */
  400.                         vlc_mutex_unlock( &p_input->stream.stream_lock );
  401.                         var_SetFloat( p_input, "position", f_fpos );
  402.                         vlc_mutex_lock( &p_input->stream.stream_lock );
  403.                     }
  404.                     /* Update the old value */
  405.                     p_intf->p_sys->f_adj_oldvalue = newvalue;
  406.                 }
  407. #undef p_area
  408.             }
  409.             if( p_intf->p_sys->i_part !=
  410.                 p_input->stream.p_selected_area->i_part )
  411.             {
  412.                 p_intf->p_sys->b_chapter_update = 1;
  413.                 b_need_menus = VLC_TRUE;
  414.             }
  415.             /* Does the audio output require to update the menus ? */
  416.             p_aout = (aout_instance_t *)vlc_object_find( p_intf, VLC_OBJECT_AOUT,
  417.                                                          FIND_ANYWHERE );
  418.             if( p_aout != NULL )
  419.             {
  420.                 vlc_value_t val;
  421.                 if( var_Get( (vlc_object_t *)p_aout, "intf-change", &val ) >= 0
  422.                     && val.b_bool )
  423.                 {
  424.                     p_intf->p_sys->b_aout_update = 1;
  425.                     b_need_menus = 1;
  426.                 }
  427.                 vlc_object_release( (vlc_object_t *)p_aout );
  428.             }
  429.             /* Does the video output require to update the menus ? */
  430.             p_vout = (vout_thread_t *)vlc_object_find( p_intf, VLC_OBJECT_VOUT,
  431.                                                        FIND_ANYWHERE );
  432.             if( p_vout != NULL ) 
  433.             {
  434.                 vlc_value_t val;
  435.                 if( var_Get( (vlc_object_t *)p_vout, "intf-change", &val ) >= 0
  436.                     && val.b_bool )
  437.                 {
  438.                     p_intf->p_sys->b_vout_update = 1;
  439.                     b_need_menus = 1;
  440.                 }
  441.                 vlc_object_release( (vlc_object_t *)p_vout );
  442.             }
  443.             if( b_need_menus )
  444.             {
  445.                 GtkSetupMenus( p_intf );
  446.             }
  447.         }
  448.         vlc_mutex_unlock( &p_input->stream.stream_lock );
  449.     }
  450.     else if( p_intf->p_sys->b_playing && !p_intf->b_die )
  451.     {
  452.         E_(GtkModeManage)( p_intf );
  453.         p_intf->p_sys->b_playing = 0;
  454.     }
  455. #ifndef NEED_GTK_MAIN
  456.     if( p_intf->b_die )
  457.     {
  458.         vlc_mutex_unlock( &p_intf->change_lock );
  459.         /* Prepare to die, young Skywalker */
  460.         gtk_main_quit();
  461.         return FALSE;
  462.     }
  463. #endif
  464.     vlc_mutex_unlock( &p_intf->change_lock );
  465.     return TRUE;
  466. }