Use static mutexes
[vlc.git] / modules / misc / gtk_main.c
1 /*****************************************************************************
2  * gtk_main.c : Gtk+ wrapper for gtk_main
3  *****************************************************************************
4  * Copyright (C) 2002 the VideoLAN team
5  * $Id$
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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22  *****************************************************************************/
23
24 /*****************************************************************************
25  * Preamble
26  *****************************************************************************/
27 #ifdef HAVE_CONFIG_H
28 # include "config.h"
29 #endif
30
31 #include <vlc_common.h>
32 #include <vlc_plugin.h>
33
34
35 #include <gtk/gtk.h>
36
37 #if defined(MODULE_NAME_IS_gtk2_main)
38 #   include <glib.h>
39 #endif
40
41 #if defined(MODULE_NAME_IS_gnome_main) || defined(MODULE_NAME_IS_gnome2_main)
42 #   include <gnome.h>
43 #endif
44
45 /*****************************************************************************
46  * Local prototypes.
47  *****************************************************************************/
48 static int  Open    ( vlc_object_t * );
49 static void Close   ( vlc_object_t * );
50
51 static void* GtkMain ( vlc_object_t * );
52
53 /*****************************************************************************
54  * Local variables (mutex-protected).
55  *****************************************************************************/
56 static int            i_refcount = 0;
57 static vlc_object_t * p_gtk_main = NULL;
58
59 /*****************************************************************************
60  * Module descriptor
61  *****************************************************************************/
62 vlc_module_begin();
63     int i_cap;
64     set_description( N_("Gtk+ GUI helper") );
65 #if defined(MODULE_NAME_IS_gtk_main)
66     i_cap = 90;
67     add_shortcut( "gtk" );
68 #elif defined(MODULE_NAME_IS_gnome_main)
69     i_cap = 100;
70     add_shortcut( "gtk" );
71     add_shortcut( "gnome" );
72 #elif defined(MODULE_NAME_IS_gtk2_main)
73     i_cap = 95;
74     add_shortcut( "gtk2" );
75 #elif defined(MODULE_NAME_IS_gnome2_main)
76     i_cap = 105;
77     add_shortcut( "gtk2" );
78     add_shortcut( "gnome2" );
79 #endif
80     set_capability( "gui-helper", i_cap );
81     set_callbacks( Open, Close );
82     linked_with_a_crap_library_which_uses_atexit();
83 vlc_module_end();
84
85 static vlc_mutex_t gtk_lock = VLC_STATIC_MUTEX;
86
87 /*****************************************************************************
88  * Open: initialize and create window
89  *****************************************************************************/
90 static int Open( vlc_object_t *p_this )
91 {
92     vlc_mutex_lock( &gtk_lock );
93
94     if( i_refcount > 0 )
95     {
96         i_refcount++;
97         vlc_mutex_unlock( lock );
98
99         return VLC_SUCCESS;
100     }
101
102     p_gtk_main = vlc_object_create( p_this, sizeof( vlc_object_t ) );
103
104     /* Only initialize gthreads if it's the first time we do it */
105     if( !g_thread_supported() )
106     {
107         g_thread_init( NULL );
108     }
109
110     /* Launch the gtk_main() thread. It will not return until it has
111      * called gdk_threads_enter(), which ensures us thread safety. */
112     if( vlc_thread_create( p_gtk_main, "gtk_main", GtkMain,
113                            VLC_THREAD_PRIORITY_LOW, true ) )
114     {
115         vlc_object_release( p_gtk_main );
116         i_refcount--;
117         vlc_mutex_unlock( lock );
118         return VLC_ETHREAD;
119     }
120
121     i_refcount++;
122     vlc_mutex_unlock( &gtk_lock );
123
124     return VLC_SUCCESS;
125 }
126
127 /*****************************************************************************
128  * Close: destroy interface window
129  *****************************************************************************/
130 static void Close( vlc_object_t *p_this )
131 {
132     vlc_mutex_lock( &gtk_lock );
133
134     i_refcount--;
135
136     if( --i_refcount == 0 )
137     {
138         gtk_main_quit();
139         vlc_thread_join( p_gtk_main );
140
141         vlc_object_release( p_gtk_main );
142         p_gtk_main = NULL;
143     }
144     vlc_mutex_unlock( &gtk_lock );
145 }
146
147 static gint foo( gpointer bar ) { return TRUE; }
148
149 /*****************************************************************************
150  * GtkMain: Gtk+ thread
151  *****************************************************************************
152  * this part of the interface is in a separate thread so that we can call
153  * gtk_main() from within it without annoying the rest of the program.
154  *****************************************************************************/
155 static void* GtkMain( vlc_object_t *p_this )
156 {
157     /* gtk_init needs to know the command line. We don't care, so we
158      * give it an empty one */
159     static char  *p_args[] = { "", NULL };
160 #if defined(MODULE_NAME_IS_gtk_main) || defined(MODULE_NAME_IS_gtk2_main)
161     static char **pp_args  = p_args;
162 #endif
163     static int    i_args   = 1;
164     int canc = vlc_savecancel ();
165
166     /* FIXME: deprecated ? */
167 #if defined(MODULE_NAME_IS_gtk2_main) || defined(MODULE_NAME_IS_gnome2_main)
168     gdk_threads_init();
169 #endif
170
171 #if defined(MODULE_NAME_IS_gnome_main)
172     gnome_init( p_this->p_libvlc->psz_object_name, VERSION, i_args, p_args );
173 #elif defined(MODULE_NAME_IS_gnome2_main)
174     gnome_program_init( PACKAGE, VERSION, LIBGNOMEUI_MODULE,
175                         i_args, p_args,
176                         GNOME_PARAM_APP_DATADIR, "",//PACKAGE_DATA_DIR,
177                         NULL );
178 #else
179     gtk_set_locale();
180     gtk_init( &i_args, &pp_args );
181 #endif
182
183     gdk_threads_enter();
184
185     vlc_thread_ready( p_this );
186
187     /* If we don't add this simple timeout, gtk_main remains stuck if
188      * we try to close the window without having sent any gtk event. */
189     gtk_timeout_add( INTF_IDLE_SLEEP / 1000, foo, p_this );
190
191     /* Enter Gtk mode */
192     gtk_main();
193
194     gdk_threads_leave();
195     vlc_restorecancel (canc);
196     return NULL;
197 }