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

多媒体

开发平台:

MultiPlatform

  1. /*****************************************************************************
  2.  * gnome.c : Gnome plugin for vlc
  3.  *****************************************************************************
  4.  * Copyright (C) 2000 VideoLAN
  5.  * $Id: gnome.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 <gnome.h>
  33. #include "gnome_callbacks.h"
  34. #include "gnome_interface.h"
  35. #include "gnome_support.h"
  36. #include "display.h"
  37. #include "common.h"
  38. /*****************************************************************************
  39.  * Local prototypes.
  40.  *****************************************************************************/
  41. static int  Open         ( vlc_object_t * );
  42. static void Close        ( vlc_object_t * );
  43. static void Run          ( intf_thread_t * );
  44. static void Manage       ( intf_thread_t * );
  45. /*****************************************************************************
  46.  * Module descriptor
  47.  *****************************************************************************/
  48. #define TOOLTIPS_TEXT N_("Show tooltips")
  49. #define TOOLTIPS_LONGTEXT N_("Show tooltips for configuration options.")
  50. #define TOOLBAR_TEXT N_("Show text on toolbar buttons")
  51. #define TOOLBAR_LONGTEXT N_("Show the text below icons on the toolbar.")
  52. #define PREFS_MAXH_TEXT N_("Maximum height for the configuration windows")
  53. #define PREFS_MAXH_LONGTEXT N_( 
  54.     "You can set the maximum height that the configuration windows in the " 
  55.     "preferences menu will occupy.")
  56. #define PATH_TEXT N_("Interface default search path")
  57. #define PATH_LONGTEXT N_( 
  58.     "This option allows you to set the default path that the interface will " 
  59.     "open when looking for a file.")
  60. vlc_module_begin();
  61. #ifdef WIN32
  62.     int i = 90;
  63. #else
  64.     int i = getenv( "DISPLAY" ) == NULL ? 15 : 100;
  65. #endif
  66.     set_description( _("GNOME interface") );
  67.     add_bool( "gnome-tooltips", 1, E_(GtkHideTooltips),
  68.               TOOLTIPS_TEXT, TOOLTIPS_LONGTEXT, VLC_FALSE );
  69.     add_bool( "gnome-toolbartext", 1, GtkHideToolbarText, TOOLBAR_TEXT,
  70.               TOOLBAR_LONGTEXT, VLC_FALSE );
  71.     add_integer( "gnome-prefs-maxh", 480, NULL,
  72.                  PREFS_MAXH_TEXT, PREFS_MAXH_LONGTEXT, VLC_TRUE );
  73.     add_directory( "gnome-search-path", NULL, NULL, PATH_TEXT,
  74.                    PATH_LONGTEXT, VLC_TRUE );
  75.     set_capability( "interface", i );
  76.     set_callbacks( Open, Close );
  77.     set_program( "gnome-vlc" );
  78. vlc_module_end();
  79. /*****************************************************************************
  80.  * Open: initialize and create window
  81.  *****************************************************************************/
  82. static int Open( vlc_object_t *p_this )
  83. {
  84.     intf_thread_t *p_intf = (intf_thread_t *)p_this;
  85.     /* Allocate instance and initialize some members */
  86.     p_intf->p_sys = malloc( sizeof( intf_sys_t ) );
  87.     if( p_intf->p_sys == NULL )
  88.     {
  89.         msg_Err( p_intf, "out of memory" );
  90.         return VLC_ENOMEM;
  91.     }
  92.     p_intf->p_sys->p_gtk_main =
  93.         module_Need( p_this, "gui-helper", "gnome", VLC_TRUE );
  94.     if( p_intf->p_sys->p_gtk_main == NULL )
  95.     {
  96.         free( p_intf->p_sys );
  97.         return VLC_ENOMOD;
  98.     }
  99.     p_intf->pf_run = Run;
  100.     p_intf->p_sys->p_sub = msg_Subscribe( p_intf );
  101.     /* Initialize Gnome 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.     module_Unneed( p_intf, p_intf->p_sys->p_gtk_main );
  133.     /* Destroy structure */
  134.     free( p_intf->p_sys );
  135. }
  136. /*****************************************************************************
  137.  * Run: Gnome thread
  138.  *****************************************************************************
  139.  * this part of the interface is in a separate thread so that we can call
  140.  * gtk_main() from within it without annoying the rest of the program.
  141.  * XXX: the approach may look kludgy, and probably is, but I could not find
  142.  * a better way to dynamically load a Gnome interface at runtime.
  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.     gdk_threads_enter();
  156.     /* Create some useful widgets that will certainly be used */
  157.     p_intf->p_sys->p_window = create_intf_window( );
  158.     p_intf->p_sys->p_popup = create_intf_popup( );
  159.     p_intf->p_sys->p_playwin = create_intf_playlist();
  160.     p_intf->p_sys->p_messages = create_intf_messages();
  161.     p_intf->p_sys->p_tooltips = gtk_tooltips_new();
  162.     p_intf->p_sys->p_sout = create_intf_sout();
  163.     /* Set the title of the main window */
  164.     gtk_window_set_title( GTK_WINDOW(p_intf->p_sys->p_window),
  165.                           VOUT_TITLE " (Gnome interface)");
  166.     /* Accept file drops on the main window */
  167.     gtk_drag_dest_set( GTK_WIDGET( p_intf->p_sys->p_window ),
  168.                        GTK_DEST_DEFAULT_ALL, target_table,
  169.                        DROP_ACCEPT_END, GDK_ACTION_COPY );
  170.     /* Accept file drops on the playlist window */
  171.     gtk_drag_dest_set( GTK_WIDGET( gtk_object_get_data( GTK_OBJECT(
  172.                             p_intf->p_sys->p_playwin ), "playlist_clist") ),
  173.                        GTK_DEST_DEFAULT_ALL, target_table,
  174.                        DROP_ACCEPT_END, GDK_ACTION_COPY );
  175.     /* Get the slider object */
  176.     p_intf->p_sys->p_slider_frame = gtk_object_get_data(
  177.                       GTK_OBJECT( p_intf->p_sys->p_window ), "slider_frame" );
  178.     /* Configure the log window */
  179.     p_intf->p_sys->p_messages_text = GTK_TEXT( gtk_object_get_data(
  180.         GTK_OBJECT(p_intf->p_sys->p_messages ), "messages_textbox" ) );
  181.     gtk_text_set_line_wrap( p_intf->p_sys->p_messages_text, TRUE);
  182.     gtk_text_set_word_wrap( p_intf->p_sys->p_messages_text, FALSE);
  183.     /* Get the interface labels */
  184.     #define P_LABEL( name ) GTK_LABEL( gtk_object_get_data( 
  185.                          GTK_OBJECT( p_intf->p_sys->p_window ), name ) )
  186.     p_intf->p_sys->p_label_title = P_LABEL( "title_label" );
  187.     p_intf->p_sys->p_label_chapter = P_LABEL( "chapter_label" );
  188.     #undef P_LABEL
  189.     /* Connect the date display to the slider */
  190.     #define P_SLIDER GTK_RANGE( gtk_object_get_data( 
  191.                          GTK_OBJECT( p_intf->p_sys->p_window ), "slider" ) )
  192.     p_intf->p_sys->p_adj = gtk_range_get_adjustment( P_SLIDER );
  193.     gtk_signal_connect ( GTK_OBJECT( p_intf->p_sys->p_adj ), "value_changed",
  194.                          GTK_SIGNAL_FUNC( E_(GtkDisplayDate) ), NULL );
  195.     p_intf->p_sys->f_adj_oldvalue = 0;
  196.     #undef P_SLIDER
  197.     /* We don't create these ones yet because we perhaps won't need them */
  198.     p_intf->p_sys->p_about = NULL;
  199.     p_intf->p_sys->p_modules = NULL;
  200.     p_intf->p_sys->p_open = NULL;
  201.     p_intf->p_sys->p_jump = NULL;
  202.     /* Hide tooltips if the option is set */
  203.     if( !config_GetInt( p_intf, "gnome-tooltips" ) )
  204.     {
  205.         gtk_tooltips_disable( p_intf->p_sys->p_tooltips );
  206.     }
  207.     /* Hide toolbar text of the option is set */
  208.     if( !config_GetInt( p_intf, "gnome-toolbartext" ) )
  209.     {
  210.         gtk_toolbar_set_style(
  211.             GTK_TOOLBAR(lookup_widget( p_intf->p_sys->p_window, "toolbar" )),
  212.             GTK_TOOLBAR_ICONS );
  213.     }
  214.     /* Store p_intf to keep an eye on it */
  215.     gtk_object_set_data( GTK_OBJECT(p_intf->p_sys->p_window),
  216.                          "p_intf", p_intf );
  217.     gtk_object_set_data( GTK_OBJECT(p_intf->p_sys->p_popup),
  218.                          "p_intf", p_intf );
  219.     gtk_object_set_data( GTK_OBJECT( gtk_object_get_data(
  220.                              GTK_OBJECT(p_intf->p_sys->p_popup),
  221.                              "popup_audio" ) ), "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_video" ) ), "p_intf", p_intf );
  225.     gtk_object_set_data( GTK_OBJECT( p_intf->p_sys->p_playwin ),
  226.                          "p_intf", p_intf );
  227.     gtk_object_set_data( GTK_OBJECT( p_intf->p_sys->p_messages ),
  228.                          "p_intf", p_intf );
  229.     gtk_object_set_data( GTK_OBJECT(p_intf->p_sys->p_adj),
  230.                          "p_intf", p_intf );
  231.     gtk_object_set_data( GTK_OBJECT( p_intf->p_sys->p_sout ),
  232.                                      "p_intf", p_intf );
  233.     psz_sout = config_GetPsz( p_intf, "sout" );
  234.     p_target = g_string_new( psz_sout ? psz_sout : "" );
  235.     if( psz_sout ) free( psz_sout );
  236.     gtk_entry_set_text( gtk_object_get_data( GTK_OBJECT( p_intf->p_sys->p_sout ), "sout_entry_target" ), p_target->str );
  237.     g_string_free( p_target, TRUE );
  238.     /* FIXME it's to be sure that only file entry is selected */
  239.     gtk_toggle_button_set_active(  gtk_object_get_data( GTK_OBJECT( p_intf->p_sys->p_sout ),
  240.                                    "sout_access_udp" ), TRUE );
  241.     gtk_toggle_button_set_active(  gtk_object_get_data( GTK_OBJECT( p_intf->p_sys->p_sout ),
  242.                                    "sout_access_file" ), TRUE );
  243.     /* Show the control window */
  244.     gtk_widget_show( p_intf->p_sys->p_window );
  245.     while( !p_intf->b_die )
  246.     {
  247.         Manage( p_intf );
  248.         /* Sleep to avoid using all CPU - since some interfaces need to
  249.          * access keyboard events, a 100ms delay is a good compromise */
  250.         gdk_threads_leave();
  251.         msleep( INTF_IDLE_SLEEP );
  252.         gdk_threads_enter();
  253.     }
  254.     /* Destroy the Tooltips structure */
  255.     gtk_object_destroy( GTK_OBJECT(p_intf->p_sys->p_tooltips) );
  256.     gtk_object_destroy( GTK_OBJECT(p_intf->p_sys->p_messages) );
  257.     gtk_object_destroy( GTK_OBJECT(p_intf->p_sys->p_playwin) );
  258.     gtk_object_destroy( GTK_OBJECT(p_intf->p_sys->p_popup) );
  259.     gtk_object_destroy( GTK_OBJECT(p_intf->p_sys->p_window) );
  260.     gdk_threads_leave();
  261. }
  262. /* following functions are local */
  263. /*****************************************************************************
  264.  * Manage: manage main thread messages
  265.  *****************************************************************************
  266.  * In this function, called approx. 10 times a second, we check what the
  267.  * main program wanted to tell us.
  268.  *****************************************************************************/
  269. static void Manage( intf_thread_t *p_intf )
  270. {
  271.     int i_start, i_stop;
  272.     vlc_mutex_lock( &p_intf->change_lock );
  273.     /* If the "display popup" flag has changed */
  274.     if( p_intf->b_menu_change )
  275.     {
  276.         if( !GTK_IS_WIDGET( p_intf->p_sys->p_popup ) )
  277.         {
  278.             p_intf->p_sys->p_popup = create_intf_popup();
  279.             gtk_object_set_data( GTK_OBJECT( p_intf->p_sys->p_popup ),
  280.                                  "p_popup", p_intf );
  281.         }
  282.         gnome_popup_menu_do_popup( p_intf->p_sys->p_popup,
  283.                                    NULL, NULL, NULL, NULL );
  284.         p_intf->b_menu_change = 0;
  285.     }
  286.     /* Update the log window */
  287.     vlc_mutex_lock( p_intf->p_sys->p_sub->p_lock );
  288.     i_stop = *p_intf->p_sys->p_sub->pi_stop;
  289.     vlc_mutex_unlock( p_intf->p_sys->p_sub->p_lock );
  290.     if( p_intf->p_sys->p_sub->i_start != i_stop )
  291.     {
  292.         static GdkColor white  = { 0, 0xffff, 0xffff, 0xffff };
  293.         static GdkColor gray   = { 0, 0xaaaa, 0xaaaa, 0xaaaa };
  294.         static GdkColor yellow = { 0, 0xffff, 0xffff, 0x6666 };
  295.         static GdkColor red    = { 0, 0xffff, 0x6666, 0x6666 };
  296.         static const char * ppsz_type[4] = { ": ", " error: ", " warning: ",
  297.                                              " debug: " };
  298.         static GdkColor *   pp_color[4] = { &white, &red, &yellow, &gray };
  299.         for( i_start = p_intf->p_sys->p_sub->i_start;
  300.              i_start != i_stop;
  301.              i_start = (i_start+1) % VLC_MSG_QSIZE )
  302.         {
  303.             /* Append all messages to log window */
  304.             gtk_text_insert( p_intf->p_sys->p_messages_text, NULL, &gray,
  305.              NULL, p_intf->p_sys->p_sub->p_msg[i_start].psz_module, -1 );
  306.             gtk_text_insert( p_intf->p_sys->p_messages_text, NULL, &gray,
  307.                 NULL, ppsz_type[p_intf->p_sys->p_sub->p_msg[i_start].i_type],
  308.                 -1 );
  309.             gtk_text_insert( p_intf->p_sys->p_messages_text, NULL,
  310.                 pp_color[p_intf->p_sys->p_sub->p_msg[i_start].i_type], NULL,
  311.                 p_intf->p_sys->p_sub->p_msg[i_start].psz_msg, -1 );
  312.             gtk_text_insert( p_intf->p_sys->p_messages_text, NULL, &gray,
  313.                 NULL, "n", -1 );
  314.         }
  315.         vlc_mutex_lock( p_intf->p_sys->p_sub->p_lock );
  316.         p_intf->p_sys->p_sub->i_start = i_start;
  317.         vlc_mutex_unlock( p_intf->p_sys->p_sub->p_lock );
  318.         /* If the messages list becomes too big, just clean half of it. */
  319.         if( gtk_text_get_length( p_intf->p_sys->p_messages_text ) >
  320.             VLC_MSG_QSIZE * 1000 )
  321.         {
  322.             gtk_text_set_point( p_intf->p_sys->p_messages_text, 0 );
  323.             gtk_text_forward_delete( p_intf->p_sys->p_messages_text,
  324.                 gtk_text_get_length( p_intf->p_sys->p_messages_text ) / 2 );
  325.         }
  326.         gtk_text_set_point( p_intf->p_sys->p_messages_text,
  327.                     gtk_text_get_length( p_intf->p_sys->p_messages_text ) );
  328.     }
  329.     /* Update the playlist */
  330.     GtkPlayListManage( p_intf );
  331.     /* Update the input */
  332.     if( p_intf->p_sys->p_input != NULL )
  333.     {
  334.         if( p_intf->p_sys->p_input->b_dead )
  335.         {
  336.             vlc_object_release( p_intf->p_sys->p_input );
  337.             p_intf->p_sys->p_input = NULL;
  338.         }
  339.     }
  340.     if( p_intf->p_sys->p_input == NULL )
  341.     {
  342.         p_intf->p_sys->p_input = vlc_object_find( p_intf, VLC_OBJECT_INPUT,
  343.                                                           FIND_ANYWHERE );
  344.     }
  345.     if( p_intf->p_sys->p_input )
  346.     {
  347.         input_thread_t *p_input = p_intf->p_sys->p_input;
  348.         aout_instance_t *p_aout  = NULL;
  349.         vout_thread_t   *p_vout  = NULL;
  350.         vlc_bool_t      b_need_menus = VLC_FALSE;
  351.         vlc_mutex_lock( &p_input->stream.stream_lock );
  352.         if( !p_input->b_die )
  353.         {
  354.             /* New input or stream map change */
  355.             if( p_input->stream.b_changed )
  356.             {
  357.                 E_(GtkModeManage)( p_intf );
  358.                 GtkSetupMenus( p_intf );
  359.                 p_intf->p_sys->b_playing = 1;
  360.             }
  361.             /* Manage the slider */
  362.             if( p_input->stream.b_seekable && p_intf->p_sys->b_playing )
  363.             {
  364.                 float newvalue = p_intf->p_sys->p_adj->value;
  365. #define p_area p_input->stream.p_selected_area
  366.                 /* If the user hasn't touched the slider since the last time,
  367.                  * then the input can safely change it */
  368.                 if( newvalue == p_intf->p_sys->f_adj_oldvalue )
  369.                 {
  370.                     /* Update the value */
  371.                     p_intf->p_sys->p_adj->value =
  372.                     p_intf->p_sys->f_adj_oldvalue =
  373.                         ( 100. * p_area->i_tell ) / p_area->i_size;
  374.                     gtk_signal_emit_by_name( GTK_OBJECT( p_intf->p_sys->p_adj ),
  375.                                              "value_changed" );
  376.                 }
  377.                 /* Otherwise, send message to the input if the user has
  378.                  * finished dragging the slider.
  379.                  * Beware, the hack below is needed by the dvdplay plugin! */
  380.                 else if( p_intf->p_sys->b_slider_free
  381.                 /* hack -> */ && (p_intf->p_sys->f_adj_oldvalue < 100.) )
  382.                 {
  383.                     if( newvalue >= 0. && newvalue < 100. )
  384.                     {
  385.                         double f_fpos = (double)newvalue / 100.0;
  386.                         /* release the lock to be able to seek */
  387.                         vlc_mutex_unlock( &p_input->stream.stream_lock );
  388.                         var_SetFloat( p_input, "position", f_fpos );
  389.                         vlc_mutex_lock( &p_input->stream.stream_lock );
  390.                     }
  391.                     /* Update the old value */
  392.                     p_intf->p_sys->f_adj_oldvalue = newvalue;
  393.                 }
  394. #undef p_area
  395.             }
  396.             if( p_intf->p_sys->i_part !=
  397.                 p_input->stream.p_selected_area->i_part )
  398.             {
  399.                 p_intf->p_sys->b_chapter_update = 1;
  400.                 b_need_menus = VLC_TRUE;
  401.             }
  402.             /* Does the audio output require to update the menus ? */
  403.             p_aout = (aout_instance_t *)vlc_object_find( p_intf, VLC_OBJECT_AOUT,
  404.                                                          FIND_ANYWHERE );
  405.             if( p_aout != NULL )
  406.             {
  407.                 vlc_value_t val;
  408.                 if( var_Get( (vlc_object_t *)p_aout, "intf-change", &val ) >= 0
  409.                     && val.b_bool )
  410.                 {
  411.                     p_intf->p_sys->b_aout_update = 1;
  412.                     b_need_menus = 1;
  413.                 }
  414.                 vlc_object_release( (vlc_object_t *)p_aout );
  415.             }
  416.             /* Does the video output require to update the menus ? */
  417.             p_vout = (vout_thread_t *)vlc_object_find( p_intf, VLC_OBJECT_VOUT,
  418.                                                        FIND_ANYWHERE );
  419.             if( p_vout != NULL ) 
  420.             {
  421.                 vlc_value_t val;
  422.                 if( var_Get( (vlc_object_t *)p_vout, "intf-change", &val ) >= 0
  423.                     && val.b_bool )
  424.                 {
  425.                     p_intf->p_sys->b_vout_update = 1;
  426.                     b_need_menus = 1;
  427.                 }
  428.                 vlc_object_release( (vlc_object_t *)p_vout );
  429.             }
  430.             if( b_need_menus )
  431.             {
  432.                 GtkSetupMenus( p_intf );
  433.             }
  434.         }
  435.         vlc_mutex_unlock( &p_input->stream.stream_lock );
  436.     }
  437.     else if( p_intf->p_sys->b_playing && !p_intf->b_die )
  438.     {
  439.         E_(GtkModeManage)( p_intf );
  440.         p_intf->p_sys->b_playing = 0;
  441.     }
  442.     vlc_mutex_unlock( &p_intf->change_lock );
  443.     return;
  444. }