]> git.sesse.net Git - vlc/blob - modules/gui/skins2/src/skin_main.cpp
vlc_plugin: fix non-LGPL plugins meta infos
[vlc] / modules / gui / skins2 / src / skin_main.cpp
1 /*****************************************************************************
2  * skin_main.cpp
3  *****************************************************************************
4  * Copyright (C) 2003 the VideoLAN team
5  * $Id$
6  *
7  * Authors: Cyril Deguet     <asmax@via.ecp.fr>
8  *          Olivier Teulière <ipkiss@via.ecp.fr>
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23  *****************************************************************************/
24
25 #ifdef HAVE_CONFIG_H
26 # include "config.h"
27 #endif
28
29 #define VLC_MODULE_LICENSE VLC_LICENSE_GPL_2_PLUS
30 #include <vlc_common.h>
31 #include <vlc_plugin.h>
32 #include <vlc_input.h>
33 #include <vlc_playlist.h>
34 #include <vlc_threads.h>
35 #include <vlc_vout_window.h>
36 #include <vlc_vout_display.h>
37
38 #include "dialogs.hpp"
39 #include "os_factory.hpp"
40 #include "os_loop.hpp"
41 #include "var_manager.hpp"
42 #include "vlcproc.hpp"
43 #include "theme_loader.hpp"
44 #include "theme.hpp"
45 #include "theme_repository.hpp"
46 #include "vout_window.hpp"
47 #include "vout_manager.hpp"
48 #include "art_manager.hpp"
49 #include "../parser/interpreter.hpp"
50 #include "../commands/async_queue.hpp"
51 #include "../commands/cmd_quit.hpp"
52 #include "../commands/cmd_dialogs.hpp"
53 #include "../commands/cmd_minimize.hpp"
54 #include "../commands/cmd_playlist.hpp"
55 #include "../commands/cmd_callbacks.hpp"
56 #include "../commands/cmd_show_window.hpp"
57 #include "../commands/cmd_resize.hpp"
58 #include "../commands/cmd_on_top.hpp"
59
60 //---------------------------------------------------------------------------
61 // Local prototypes
62 //---------------------------------------------------------------------------
63 static int  Open  ( vlc_object_t * );
64 static void Close ( vlc_object_t * );
65 static void *Run  ( void * );
66
67 static struct
68 {
69     intf_thread_t *intf;
70     vlc_mutex_t mutex;
71 } skin_load = { NULL, VLC_STATIC_MUTEX };
72
73 //---------------------------------------------------------------------------
74 // Open: initialize interface
75 //---------------------------------------------------------------------------
76 static int Open( vlc_object_t *p_this )
77 {
78     intf_thread_t *p_intf = (intf_thread_t *)p_this;
79
80     // Allocate instance and initialize some members
81     p_intf->p_sys = (intf_sys_t *) calloc( 1, sizeof( intf_sys_t ) );
82     if( p_intf->p_sys == NULL )
83         return VLC_ENOMEM;
84
85     p_intf->p_sys->p_input = NULL;
86     p_intf->p_sys->p_playlist = pl_Get( p_intf );
87
88     // Initialize "singleton" objects
89     p_intf->p_sys->p_logger = NULL;
90     p_intf->p_sys->p_queue = NULL;
91     p_intf->p_sys->p_dialogs = NULL;
92     p_intf->p_sys->p_interpreter = NULL;
93     p_intf->p_sys->p_osFactory = NULL;
94     p_intf->p_sys->p_osLoop = NULL;
95     p_intf->p_sys->p_varManager = NULL;
96     p_intf->p_sys->p_voutManager = NULL;
97     p_intf->p_sys->p_vlcProc = NULL;
98     p_intf->p_sys->p_repository = NULL;
99
100     // No theme yet
101     p_intf->p_sys->p_theme = NULL;
102
103     vlc_mutex_init( &p_intf->p_sys->init_lock );
104     vlc_cond_init( &p_intf->p_sys->init_wait );
105
106     vlc_mutex_lock( &p_intf->p_sys->init_lock );
107     p_intf->p_sys->b_error = false;
108     p_intf->p_sys->b_ready = false;
109
110     if( vlc_clone( &p_intf->p_sys->thread, Run, p_intf,
111                                VLC_THREAD_PRIORITY_LOW ) )
112     {
113         vlc_mutex_unlock( &p_intf->p_sys->init_lock );
114
115         vlc_cond_destroy( &p_intf->p_sys->init_wait );
116         vlc_mutex_destroy( &p_intf->p_sys->init_lock );
117         free( p_intf->p_sys );
118         return VLC_EGENERIC;
119     }
120
121     while( !p_intf->p_sys->b_ready )
122         vlc_cond_wait( &p_intf->p_sys->init_wait, &p_intf->p_sys->init_lock );
123     vlc_mutex_unlock( &p_intf->p_sys->init_lock );
124
125     if( p_intf->p_sys->b_error )
126     {
127         vlc_join( p_intf->p_sys->thread, NULL );
128
129         vlc_mutex_destroy( &p_intf->p_sys->init_lock );
130         vlc_cond_destroy( &p_intf->p_sys->init_wait );
131
132         free( p_intf->p_sys );
133         return VLC_EGENERIC;
134     }
135
136     vlc_mutex_lock( &skin_load.mutex );
137     skin_load.intf = p_intf;
138     vlc_mutex_unlock( &skin_load.mutex );
139
140     return VLC_SUCCESS;
141 }
142
143 //---------------------------------------------------------------------------
144 // Close: destroy interface
145 //---------------------------------------------------------------------------
146 static void Close( vlc_object_t *p_this )
147 {
148     intf_thread_t *p_intf = (intf_thread_t *)p_this;
149
150     msg_Dbg( p_intf, "closing skins2 module" );
151
152     /* Terminate input to ensure that our window provider is released. */
153     playlist_Deactivate( p_intf->p_sys->p_playlist );
154
155     vlc_mutex_lock( &skin_load.mutex );
156     skin_load.intf = NULL;
157     vlc_mutex_unlock( &skin_load.mutex);
158
159     AsyncQueue *pQueue = p_intf->p_sys->p_queue;
160     if( pQueue )
161     {
162         CmdGeneric *pCmd = new CmdExitLoop( p_intf );
163         if( pCmd )
164             pQueue->push( CmdGenericPtr( pCmd ) );
165     }
166     else
167     {
168         msg_Err( p_intf, "thread found already stopped (weird!)" );
169     }
170
171     vlc_join( p_intf->p_sys->thread, NULL );
172
173     vlc_mutex_destroy( &p_intf->p_sys->init_lock );
174     vlc_cond_destroy( &p_intf->p_sys->init_wait );
175
176     // Destroy structure
177     free( p_intf->p_sys );
178 }
179
180
181 //---------------------------------------------------------------------------
182 // Run: main loop
183 //---------------------------------------------------------------------------
184 static void *Run( void * p_obj )
185 {
186     int canc = vlc_savecancel();
187
188     intf_thread_t *p_intf = (intf_thread_t *)p_obj;
189
190     bool b_error = false;
191     char *skin_last = NULL;
192     ThemeLoader *pLoader = NULL;
193     OSLoop *loop = NULL;
194
195     vlc_mutex_lock( &p_intf->p_sys->init_lock );
196
197     // Initialize singletons
198     if( OSFactory::instance( p_intf ) == NULL )
199     {
200         msg_Err( p_intf, "cannot initialize OSFactory" );
201         b_error = true;
202         goto end;
203     }
204     if( AsyncQueue::instance( p_intf ) == NULL )
205     {
206         msg_Err( p_intf, "cannot initialize AsyncQueue" );
207         b_error = true;
208         goto end;
209     }
210     if( Interpreter::instance( p_intf ) == NULL )
211     {
212         msg_Err( p_intf, "cannot instantiate Interpreter" );
213         b_error = true;
214         goto end;
215     }
216     if( VarManager::instance( p_intf ) == NULL )
217     {
218         msg_Err( p_intf, "cannot instantiate VarManager" );
219         b_error = true;
220         goto end;
221     }
222     if( VlcProc::instance( p_intf ) == NULL )
223     {
224         msg_Err( p_intf, "cannot initialize VLCProc" );
225         b_error = true;
226         goto end;
227     }
228     if( VoutManager::instance( p_intf ) == NULL )
229     {
230         msg_Err( p_intf, "cannot instantiate VoutManager" );
231         b_error = true;
232         goto end;
233     }
234     if( ArtManager::instance( p_intf ) == NULL )
235     {
236         msg_Err( p_intf, "cannot instantiate ArtManager" );
237         b_error = true;
238         goto end;
239     }
240     if( ThemeRepository::instance( p_intf ) == NULL )
241     {
242         msg_Err( p_intf, "cannot instantiate ThemeRepository" );
243         b_error = true;
244         goto end;
245     }
246     if( Dialogs::instance( p_intf ) == NULL )
247     {
248         msg_Err( p_intf, "cannot instantiate qt4 dialogs provider" );
249         b_error = true;
250         goto end;
251     }
252
253     // Load a theme
254     skin_last = config_GetPsz( p_intf, "skins2-last" );
255     pLoader = new ThemeLoader( p_intf );
256
257     if( !skin_last || !pLoader->load( skin_last ) )
258     {
259         // No skins (not even the default one). let's quit
260         CmdQuit *pCmd = new CmdQuit( p_intf );
261         AsyncQueue *pQueue = AsyncQueue::instance( p_intf );
262         pQueue->push( CmdGenericPtr( pCmd ) );
263         msg_Err( p_intf, "no skins found : exiting");
264     }
265
266     delete pLoader;
267     free( skin_last );
268
269     // Get the instance of OSLoop
270     loop = OSFactory::instance( p_intf )->getOSLoop();
271
272     // Signal the main thread this thread is now ready
273     p_intf->p_sys->b_error = false;
274     p_intf->p_sys->b_ready = true;
275     vlc_cond_signal( &p_intf->p_sys->init_wait );
276     vlc_mutex_unlock( &p_intf->p_sys->init_lock );
277
278     // Enter the main event loop
279     loop->run();
280
281     // Destroy OSLoop
282     OSFactory::instance( p_intf )->destroyOSLoop();
283
284     // save and delete the theme
285     if( p_intf->p_sys->p_theme )
286     {
287         p_intf->p_sys->p_theme->saveConfig();
288
289         delete p_intf->p_sys->p_theme;
290         p_intf->p_sys->p_theme = NULL;
291
292         msg_Dbg( p_intf, "current theme deleted" );
293     }
294
295     // save config file
296     config_SaveConfigFile( p_intf );
297
298 end:
299     // Destroy "singleton" objects
300     Dialogs::destroy( p_intf );
301     ThemeRepository::destroy( p_intf );
302     ArtManager::destroy( p_intf );
303     VoutManager::destroy( p_intf );
304     VlcProc::destroy( p_intf );
305     VarManager::destroy( p_intf );
306     Interpreter::destroy( p_intf );
307     AsyncQueue::destroy( p_intf );
308     OSFactory::destroy( p_intf );
309
310     if( b_error )
311     {
312         p_intf->p_sys->b_error = true;
313         p_intf->p_sys->b_ready = true;
314         vlc_cond_signal( &p_intf->p_sys->init_wait );
315         vlc_mutex_unlock( &p_intf->p_sys->init_lock );
316     }
317
318     vlc_restorecancel(canc);
319     return NULL;
320 }
321
322 static int  WindowOpen( vout_window_t *, const vout_window_cfg_t * );
323 static void WindowClose( vout_window_t * );
324 static int  WindowControl( vout_window_t *, int, va_list );
325
326 struct vout_window_sys_t
327 {
328     intf_thread_t*     pIntf;
329     vout_window_cfg_t  cfg;
330 };
331
332 static void WindowOpenLocal( intf_thread_t* pIntf, vlc_object_t *pObj )
333 {
334     vout_window_t* pWnd = (vout_window_t*)pObj;
335     int width = (int)pWnd->sys->cfg.width;
336     int height = (int)pWnd->sys->cfg.height;
337     VoutManager::instance( pIntf )->acceptWnd( pWnd, width, height );
338 }
339
340 static void WindowCloseLocal( intf_thread_t* pIntf, vlc_object_t *pObj )
341 {
342     vout_window_t* pWnd = (vout_window_t*)pObj;
343     VoutManager::instance( pIntf )->releaseWnd( pWnd );
344 }
345
346 static int WindowOpen( vout_window_t *pWnd, const vout_window_cfg_t *cfg )
347 {
348     if( cfg->type != VOUT_WINDOW_TYPE_INVALID )
349     {
350 #ifdef X11_SKINS
351         if( cfg->type != VOUT_WINDOW_TYPE_XID )
352 #else
353         if( cfg->type != VOUT_WINDOW_TYPE_HWND )
354 #endif
355             return VLC_EGENERIC;
356     }
357
358     vout_window_sys_t* sys;
359
360     vlc_mutex_lock( &skin_load.mutex );
361     intf_thread_t *pIntf = skin_load.intf;
362     if( pIntf )
363         vlc_object_hold( pIntf );
364     vlc_mutex_unlock( &skin_load.mutex );
365
366     if( pIntf == NULL )
367         return VLC_EGENERIC;
368
369     if( !var_InheritBool( pIntf, "skinned-video") ||
370         cfg->is_standalone )
371     {
372         vlc_object_release( pIntf );
373         return VLC_EGENERIC;
374     }
375
376     sys = (vout_window_sys_t*)calloc( 1, sizeof( *sys ) );
377     if( !sys )
378     {
379         vlc_object_release( pIntf );
380         return VLC_ENOMEM;
381     }
382
383     pWnd->sys = sys;
384     pWnd->sys->cfg = *cfg;
385     pWnd->sys->pIntf = pIntf;
386 #ifdef X11_SKINS
387     pWnd->type = VOUT_WINDOW_TYPE_XID;
388 #else
389     pWnd->type = VOUT_WINDOW_TYPE_HWND;
390 #endif
391     pWnd->control = WindowControl;
392
393     // force execution in the skins2 thread context
394     CmdExecuteBlock* cmd = new CmdExecuteBlock( pIntf, VLC_OBJECT( pWnd ),
395                                                 WindowOpenLocal );
396     CmdExecuteBlock::executeWait( CmdGenericPtr( cmd ) );
397
398 #ifdef X11_SKINS
399     pWnd->display.x11 = NULL;
400
401     if( !pWnd->handle.xid )
402 #else
403     if( !pWnd->handle.hwnd )
404 #endif
405     {
406         free( sys );
407         vlc_object_release( pIntf );
408         return VLC_EGENERIC;
409     }
410
411     return VLC_SUCCESS;
412 }
413
414 static void WindowClose( vout_window_t *pWnd )
415 {
416     vout_window_sys_t* sys = pWnd->sys;
417     intf_thread_t *pIntf = sys->pIntf;
418
419     // force execution in the skins2 thread context
420     CmdExecuteBlock* cmd = new CmdExecuteBlock( pIntf, VLC_OBJECT( pWnd ),
421                                                 WindowCloseLocal );
422     CmdExecuteBlock::executeWait( CmdGenericPtr( cmd ) );
423
424     vlc_object_release( sys->pIntf );
425     free( sys );
426 }
427
428 static int WindowControl( vout_window_t *pWnd, int query, va_list args )
429 {
430     vout_window_sys_t* sys = pWnd->sys;
431     intf_thread_t *pIntf = sys->pIntf;
432     AsyncQueue *pQueue = AsyncQueue::instance( pIntf );
433
434     switch( query )
435     {
436         case VOUT_WINDOW_SET_SIZE:
437         {
438             unsigned int i_width  = va_arg( args, unsigned int );
439             unsigned int i_height = va_arg( args, unsigned int );
440
441             if( i_width && i_height )
442             {
443                 // Post a vout resize command
444                 CmdResizeVout *pCmd =
445                     new CmdResizeVout( pIntf, pWnd,
446                                        (int)i_width, (int)i_height );
447                 pQueue->push( CmdGenericPtr( pCmd ) );
448             }
449             return VLC_EGENERIC;
450         }
451
452         case VOUT_WINDOW_SET_FULLSCREEN:
453         {
454             bool b_fullscreen = va_arg( args, int );
455
456             // Post a set fullscreen command
457             CmdSetFullscreen* pCmd =
458                 new CmdSetFullscreen( pIntf, pWnd, b_fullscreen );
459             pQueue->push( CmdGenericPtr( pCmd ) );
460             return VLC_SUCCESS;
461         }
462
463         case VOUT_WINDOW_SET_STATE:
464         {
465             unsigned i_arg = va_arg( args, unsigned );
466             unsigned on_top = i_arg & VOUT_WINDOW_STATE_ABOVE;
467
468             // Post a SetOnTop command
469             CmdSetOnTop* pCmd =
470                 new CmdSetOnTop( pIntf, on_top );
471             pQueue->push( CmdGenericPtr( pCmd ) );
472             return VLC_SUCCESS;
473         }
474
475         default:
476             msg_Dbg( pIntf, "control query not supported" );
477             return VLC_EGENERIC;
478     }
479 }
480
481 //---------------------------------------------------------------------------
482 // Module descriptor
483 //---------------------------------------------------------------------------
484 #define SKINS2_LAST      N_("Skin to use")
485 #define SKINS2_LAST_LONG N_("Path to the skin to use.")
486 #define SKINS2_CONFIG      N_("Config of last used skin")
487 #define SKINS2_CONFIG_LONG N_("Windows configuration of the last skin used. " \
488         "This option is updated automatically, do not touch it." )
489 #define SKINS2_SYSTRAY      N_("Systray icon")
490 #define SKINS2_SYSTRAY_LONG N_("Show a systray icon for VLC")
491 #define SKINS2_TASKBAR      N_("Show VLC on the taskbar")
492 #define SKINS2_TASKBAR_LONG N_("Show VLC on the taskbar")
493 #define SKINS2_TRANSPARENCY      N_("Enable transparency effects")
494 #define SKINS2_TRANSPARENCY_LONG N_("You can disable all transparency effects"\
495     " if you want. This is mainly useful when moving windows does not behave" \
496     " correctly.")
497 #define SKINS2_PLAYLIST N_("Use a skinned playlist")
498 #define SKINS2_PLAYLIST_LONG N_("Use a skinned playlist")
499 #define SKINS2_VIDEO N_("Display video in a skinned window if any")
500 #define SKINS2_VIDEO_LONG N_( \
501     "When set to 'no', this parameter is intended to give old skins a chance" \
502     " to play back video even though no video tag is implemented")
503
504 vlc_module_begin ()
505     set_category( CAT_INTERFACE )
506     set_subcategory( SUBCAT_INTERFACE_MAIN )
507     add_loadfile( "skins2-last", "", SKINS2_LAST, SKINS2_LAST_LONG,
508                   true )
509     add_string( "skins2-config", "", SKINS2_CONFIG, SKINS2_CONFIG_LONG,
510                 true )
511         change_private ()
512 #ifdef _WIN32
513     add_bool( "skins2-systray", true, SKINS2_SYSTRAY,
514               SKINS2_SYSTRAY_LONG, false );
515     add_bool( "skins2-taskbar", true, SKINS2_TASKBAR,
516               SKINS2_TASKBAR_LONG, false );
517 #endif
518     add_bool( "skins2-transparency", false, SKINS2_TRANSPARENCY,
519               SKINS2_TRANSPARENCY_LONG, false );
520
521     add_bool( "skinned-playlist", true, SKINS2_PLAYLIST,
522               SKINS2_PLAYLIST_LONG, false );
523     add_bool( "skinned-video", true, SKINS2_VIDEO,
524               SKINS2_VIDEO_LONG, false );
525     set_shortname( N_("Skins"))
526     set_description( N_("Skinnable Interface") )
527     set_capability( "interface", 30 )
528     set_callbacks( Open, Close )
529     add_shortcut( "skins" )
530
531     add_submodule ()
532         set_capability( "vout window", 51 )
533         set_callbacks( WindowOpen, WindowClose )
534
535 vlc_module_end ()