]> git.sesse.net Git - vlc/blob - plugins/gnome/intf_gnome.c
* removed useless includes in intf_gnome.c
[vlc] / plugins / gnome / intf_gnome.c
1 /*****************************************************************************
2  * intf_gnome.c: Gnome interface
3  *****************************************************************************
4  * Copyright (C) 1999, 2000 VideoLAN
5  * $Id: intf_gnome.c,v 1.12 2001/02/15 07:59:38 sam Exp $
6  *
7  * Authors:
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 /*****************************************************************************
25  * Preamble
26  *****************************************************************************/
27 #include "defs.h"
28
29 #include <errno.h>                                                 /* ENOMEM */
30 #include <stdlib.h>                                                /* free() */
31 #include <string.h>                                            /* strerror() */
32 #include <stdio.h>
33
34 #include <gnome.h>
35
36 #include "config.h"
37 #include "common.h"
38 #include "threads.h"
39 #include "mtime.h"
40 #include "tests.h"
41 #include "modules.h"
42
43 #include "stream_control.h"
44 #include "input_ext-intf.h"
45
46 #include "intf_msg.h"
47 #include "interface.h"
48
49 #include "gnome_sys.h"
50 #include "gnome_interface.h"
51 #include "gnome_support.h"
52
53 #include "main.h"
54
55 /*****************************************************************************
56  * Local prototypes.
57  *****************************************************************************/
58 static int  intf_Probe     ( probedata_t *p_data );
59 static int  intf_Open      ( intf_thread_t *p_intf );
60 static void intf_Close     ( intf_thread_t *p_intf );
61 static void intf_Run       ( intf_thread_t *p_intf );
62
63 static gint GnomeManage    ( gpointer p_data );
64
65 /*****************************************************************************
66  * g_atexit: kludge to avoid the Gnome thread to segfault at exit
67  *****************************************************************************
68  * gtk_init() makes several calls to g_atexit() which calls atexit() to
69  * register tidying callbacks to be called at program exit. Since the Gnome
70  * plugin is likely to be unloaded at program exit, we have to export this
71  * symbol to intercept the g_atexit() calls. Talk about crude hack.
72  *****************************************************************************/
73 void g_atexit( GVoidFunc func )
74 {
75     intf_thread_t *p_intf = p_main->p_intf;
76
77     if( p_intf->p_sys->pf_gdk_callback == NULL )
78     {
79         p_intf->p_sys->pf_gdk_callback = func;
80     }
81     else if( p_intf->p_sys->pf_gtk_callback == NULL )
82     {
83         p_intf->p_sys->pf_gtk_callback = func;
84     }
85     /* else nothing, but we could do something here */
86     return;
87 }
88
89 /*****************************************************************************
90  * Functions exported as capabilities. They are declared as static so that
91  * we don't pollute the namespace too much.
92  *****************************************************************************/
93 void intf_getfunctions( function_list_t * p_function_list )
94 {
95     p_function_list->pf_probe = intf_Probe;
96     p_function_list->functions.intf.pf_open  = intf_Open;
97     p_function_list->functions.intf.pf_close = intf_Close;
98     p_function_list->functions.intf.pf_run   = intf_Run;
99 }
100
101 /*****************************************************************************
102  * intf_Probe: probe the interface and return a score
103  *****************************************************************************
104  * This function tries to initialize Gnome and returns a score to the
105  * plugin manager so that it can select the best plugin.
106  *****************************************************************************/
107 static int intf_Probe( probedata_t *p_data )
108 {
109     if( TestMethod( INTF_METHOD_VAR, "gnome" ) )
110     {
111         return( 999 );
112     }
113
114     return( 40 );
115 }
116
117 /*****************************************************************************
118  * intf_Open: initialize and create window
119  *****************************************************************************/
120 static int intf_Open( intf_thread_t *p_intf )
121 {
122     /* Allocate instance and initialize some members */
123     p_intf->p_sys = malloc( sizeof( intf_sys_t ) );
124     if( p_intf->p_sys == NULL )
125     {
126         intf_ErrMsg("error: %s", strerror(ENOMEM));
127         return( 1 );
128     }
129
130     /* Initialize Gnome thread */
131     p_intf->p_sys->b_popup_changed = 0;
132     p_intf->p_sys->b_window_changed = 0;
133     p_intf->p_sys->b_playlist_changed = 0;
134
135     p_intf->p_sys->b_scale_isfree = 1;
136
137     p_intf->p_sys->pf_gtk_callback = NULL;
138     p_intf->p_sys->pf_gdk_callback = NULL;
139
140     return( 0 );
141 }
142
143 /*****************************************************************************
144  * intf_Close: destroy interface window
145  *****************************************************************************/
146 static void intf_Close( intf_thread_t *p_intf )
147 {
148     /* Destroy structure */
149     free( p_intf->p_sys );
150 }
151
152 /*****************************************************************************
153  * intf_Run: Gnome thread
154  *****************************************************************************
155  * this part of the interface is in a separate thread so that we can call
156  * gtk_main() from within it without annoying the rest of the program.
157  * XXX: the approach may look kludgy, and probably is, but I could not find
158  * a better way to dynamically load a Gnome interface at runtime.
159  *****************************************************************************/
160 static void intf_Run( intf_thread_t *p_intf )
161 {
162     /* gnome_init needs to know the command line. We don't care, so we
163      * give it an empty one */
164     char *p_args[] = { };
165
166     /* Initialize Gnome */
167     gnome_init( p_main->psz_arg0, VERSION, 1, p_args );
168
169     /* create some useful widgets that will certainly be used */
170     p_intf->p_sys->p_window = create_intf_window();
171     p_intf->p_sys->p_popup = create_intf_popup( );
172
173     /* we don't create these ones yet because we perhaps won't need them */
174     p_intf->p_sys->p_about = NULL;
175     p_intf->p_sys->p_playlist = NULL;
176     p_intf->p_sys->p_modules = NULL;
177     p_intf->p_sys->p_fileopen = NULL;
178
179     /* store p_sys to keep an eye on it */
180     gtk_object_set_data( GTK_OBJECT(p_intf->p_sys->p_window),
181                          "p_intf", p_intf );
182
183     gtk_object_set_data( GTK_OBJECT(p_intf->p_sys->p_popup),
184                          "p_intf", p_intf );
185
186     /* show the control window */
187     gtk_widget_show( p_intf->p_sys->p_window );
188
189     /* Sleep to avoid using all CPU - since some interfaces needs to access
190      * keyboard events, a 100ms delay is a good compromise */
191     p_intf->p_sys->i_timeout = gtk_timeout_add( INTF_IDLE_SLEEP / 1000,
192                                                 GnomeManage, p_intf );
193  
194     /* enter gnome mode */
195     gtk_main();
196
197     /* launch stored callbacks */
198     if( p_intf->p_sys->pf_gtk_callback != NULL )
199     {
200         p_intf->p_sys->pf_gtk_callback();
201
202         if( p_intf->p_sys->pf_gdk_callback != NULL )
203         {
204             p_intf->p_sys->pf_gdk_callback();
205         }
206     }
207 }
208
209 /* following functions are local */
210
211 /*****************************************************************************
212  * GnomeManage: manage main thread messages
213  *****************************************************************************
214  * In this function, called approx. 10 times a second, we check what the
215  * main program wanted to tell us.
216  *****************************************************************************/
217 static gint GnomeManage( gpointer p_data )
218 {
219     intf_thread_t *p_intf = (void *)p_data;
220
221     vlc_mutex_lock( &p_intf->p_sys->change_lock );
222
223     /* If the "display popup" flag has changed */
224     if( p_intf->b_menu_change )
225     {
226         gnome_popup_menu_do_popup( p_intf->p_sys->p_popup,
227                                    NULL, NULL, NULL, NULL );
228         p_intf->b_menu_change = 0;
229     }
230
231     /* Manage the slider */
232     if( p_intf->p_input != NULL && p_intf->p_sys->p_window != NULL
233          && p_intf->p_sys->b_scale_isfree )
234     {
235         GtkWidget *p_scale;
236         GtkAdjustment *p_adj;
237    
238         p_scale = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT(
239                                   p_intf->p_sys->p_window ), "hscale" ) );
240         p_adj = gtk_range_get_adjustment ( GTK_RANGE( p_scale ) );
241
242         /* Update the value */
243         p_adj->value = ( 100. * p_intf->p_input->stream.i_tell )
244                            / p_intf->p_input->stream.i_size;
245
246         /* Gtv does it this way. Why not. */
247         gtk_range_set_adjustment ( GTK_RANGE( p_scale ), p_adj );
248         gtk_range_slider_update ( GTK_RANGE( p_scale ) );
249         gtk_range_clear_background ( GTK_RANGE( p_scale ) );
250         gtk_range_draw_background ( GTK_RANGE( p_scale ) );
251     }
252
253     /* Manage core vlc functions through the callback */
254     p_intf->pf_manage( p_intf );
255
256     if( p_intf->b_die )
257     {
258         /* Make sure we won't be called again */
259         gtk_timeout_remove( p_intf->p_sys->i_timeout );
260
261         vlc_mutex_unlock( &p_intf->p_sys->change_lock );
262
263         /* Prepare to die, young Skywalker */
264         gtk_main_quit();
265         return( FALSE );
266     }
267
268     vlc_mutex_unlock( &p_intf->p_sys->change_lock );
269
270     return( TRUE );
271 }
272