]> git.sesse.net Git - vlc/blob - modules/gui/qt4/extensions_manager.cpp
35589c84c7cfd6d35d0cad42461e44d9ec7b28f7
[vlc] / modules / gui / qt4 / extensions_manager.cpp
1 /*****************************************************************************
2  * extensions_manager.cpp: Extensions manager for Qt
3  ****************************************************************************
4  * Copyright (C) 2009-2010 VideoLAN and authors
5  * $Id$
6  *
7  * Authors: Jean-Philippe AndrĂ© < jpeg # videolan.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 #include "extensions_manager.hpp"
25 #include "input_manager.hpp"
26 #include "dialogs/extensions.hpp"
27
28 #include "assert.h"
29
30 #include <QMenu>
31 #include <QAction>
32 #include <QSignalMapper>
33 #include <QIcon>
34
35 #define MENU_MAP(a,e) ((uint32_t)( (((uint16_t)a) << 16) | ((uint16_t)e) ))
36 #define MENU_GET_ACTION(a) ( (uint16_t)( ((uint32_t)a) >> 16 ) )
37 #define MENU_GET_EXTENSION(a) ( (uint16_t)( ((uint32_t)a) & 0xFFFF ) )
38
39 ExtensionsManager* ExtensionsManager::instance = NULL;
40
41 ExtensionsManager::ExtensionsManager( intf_thread_t *_p_intf, QObject *parent )
42         : QObject( parent ), p_intf( _p_intf ), p_extensions_manager( NULL )
43         , p_edp( NULL )
44 {
45     assert( ExtensionsManager::instance == NULL );
46     instance = this;
47
48     menuMapper = new QSignalMapper( this );
49     CONNECT( menuMapper, mapped( int ), this, triggerMenu( int ) );
50     CONNECT( THEMIM->getIM(), statusChanged( int ), this, playingChanged( int ) );
51     DCONNECT( THEMIM, inputChanged( input_thread_t* ),
52               this, inputChanged( input_thread_t* ) );
53     b_unloading = false;
54     b_failed = false;
55 }
56
57 ExtensionsManager::~ExtensionsManager()
58 {
59     msg_Dbg( p_intf, "Killing extension dialog provider" );
60     ExtensionsDialogProvider::killInstance();
61     if( p_extensions_manager )
62     {
63         module_unneed( p_extensions_manager, p_extensions_manager->p_module );
64         vlc_object_release( p_extensions_manager );
65     }
66 }
67
68 bool ExtensionsManager::loadExtensions()
69 {
70     if( !p_extensions_manager )
71     {
72         p_extensions_manager = ( extensions_manager_t* )
73                     vlc_object_create( p_intf, sizeof( extensions_manager_t ) );
74         if( !p_extensions_manager )
75         {
76             b_failed = true;
77             emit extensionsUpdated();
78             return false;
79         }
80         vlc_object_attach( p_extensions_manager, p_intf );
81
82         p_extensions_manager->p_module =
83                 module_need( p_extensions_manager, "extension", NULL, false );
84
85         if( !p_extensions_manager->p_module )
86         {
87             msg_Err( p_intf, "Unable to load extensions module" );
88             vlc_object_release( p_extensions_manager );
89             p_extensions_manager = NULL;
90             b_failed = true;
91             emit extensionsUpdated();
92             return false;
93         }
94
95         /* Initialize dialog provider */
96         p_edp = ExtensionsDialogProvider::getInstance( p_intf,
97                                                        p_extensions_manager );
98         if( !p_edp )
99         {
100             msg_Err( p_intf, "Unable to create dialogs provider for extensions" );
101             module_unneed( p_extensions_manager,
102                            p_extensions_manager->p_module );
103             vlc_object_release( p_extensions_manager );
104             p_extensions_manager = NULL;
105             b_failed = true;
106             emit extensionsUpdated();
107             return false;
108         }
109         b_unloading = false;
110     }
111     b_failed = false;
112     emit extensionsUpdated();
113     return true;
114 }
115
116 void ExtensionsManager::unloadExtensions()
117 {
118     if( !p_extensions_manager )
119         return;
120     b_unloading = true;
121     ExtensionsDialogProvider::killInstance();
122     module_unneed( p_extensions_manager, p_extensions_manager->p_module );
123     vlc_object_release( p_extensions_manager );
124     p_extensions_manager = NULL;
125 }
126
127 void ExtensionsManager::reloadExtensions()
128 {
129     unloadExtensions();
130     loadExtensions();
131     emit extensionsUpdated();
132 }
133
134 void ExtensionsManager::menu( QMenu *current )
135 {
136     assert( current != NULL );
137     if( !isLoaded() )
138     {
139         // This case can happen: do nothing
140         return;
141     }
142
143     vlc_mutex_lock( &p_extensions_manager->lock );
144
145     QAction *action;
146     extension_t *p_ext = NULL;
147     int i_ext = 0;
148     FOREACH_ARRAY( p_ext, p_extensions_manager->extensions )
149     {
150         bool b_Active = extension_IsActivated( p_extensions_manager, p_ext );
151
152         if( b_Active && extension_HasMenu( p_extensions_manager, p_ext ) )
153         {
154             QMenu *submenu = new QMenu( qfu( p_ext->psz_title ), current );
155             char **ppsz_titles = NULL;
156             uint16_t *pi_ids = NULL;
157             size_t i_num = 0;
158             action = current->addMenu( submenu );
159
160             action->setCheckable( true );
161             action->setChecked( true );
162
163             if( extension_GetMenu( p_extensions_manager, p_ext,
164                                    &ppsz_titles, &pi_ids ) == VLC_SUCCESS )
165             {
166                 for( int i = 0; ppsz_titles[i] != NULL; ++i )
167                 {
168                     ++i_num;
169                     action = submenu->addAction( qfu( ppsz_titles[i] ) );
170                     menuMapper->setMapping( action,
171                                             MENU_MAP( pi_ids[i], i_ext ) );
172                     CONNECT( action, triggered(), menuMapper, map() );
173                     free( ppsz_titles[i] );
174                 }
175                 if( !i_num )
176                 {
177                     action = submenu->addAction( qtr( "Empty" ) );
178                     action->setEnabled( false );
179                 }
180                 free( ppsz_titles );
181                 free( pi_ids );
182             }
183             else
184             {
185                 msg_Warn( p_intf, "Could not get menu for extension '%s'",
186                           p_ext->psz_title );
187                 action = submenu->addAction( qtr( "Empty" ) );
188                 action->setEnabled( false );
189             }
190
191             submenu->addSeparator();
192             action = submenu->addAction( QIcon( ":/menu/quit" ),
193                                          qtr( "Deactivate" ) );
194             menuMapper->setMapping( action, MENU_MAP( 0, i_ext ) );
195             CONNECT( action, triggered(), menuMapper, map() );
196         }
197         else
198         {
199             action = current->addAction( qfu( p_ext->psz_title ) );
200             menuMapper->setMapping( action, MENU_MAP( 0, i_ext ) );
201             CONNECT( action, triggered(), menuMapper, map() );
202
203             if( !extension_TriggerOnly( p_extensions_manager, p_ext ) )
204             {
205                 action->setCheckable( true );
206                 action->setChecked( b_Active );
207             }
208         }
209         i_ext++;
210     }
211     FOREACH_END()
212
213     vlc_mutex_unlock( &p_extensions_manager->lock );
214 }
215
216 void ExtensionsManager::triggerMenu( int id )
217 {
218     uint16_t i_ext = MENU_GET_EXTENSION( id );
219     uint16_t i_action = MENU_GET_ACTION( id );
220
221     vlc_mutex_lock( &p_extensions_manager->lock );
222
223     if( (int) i_ext > p_extensions_manager->extensions.i_size )
224     {
225         msg_Dbg( p_intf, "can't trigger extension with wrong id %d",
226                  (int) i_ext );
227         return;
228     }
229
230     extension_t *p_ext = ARRAY_VAL( p_extensions_manager->extensions, i_ext );
231     assert( p_ext != NULL);
232
233     vlc_mutex_unlock( &p_extensions_manager->lock );
234
235     if( i_action == 0 )
236     {
237         msg_Dbg( p_intf, "activating or triggering extension '%s'",
238                  p_ext->psz_title );
239
240         if( extension_TriggerOnly( p_extensions_manager, p_ext ) )
241         {
242             extension_Trigger( p_extensions_manager, p_ext );
243         }
244         else
245         {
246             if( !extension_IsActivated( p_extensions_manager, p_ext ) )
247                 extension_Activate( p_extensions_manager, p_ext );
248             else
249                 extension_Deactivate( p_extensions_manager, p_ext );
250         }
251     }
252     else
253     {
254         msg_Dbg( p_intf, "triggering extension '%s', on menu with id = 0x%x",
255                  p_ext->psz_title, i_action );
256
257         extension_TriggerMenu( p_extensions_manager, p_ext, i_action );
258     }
259 }
260
261 void ExtensionsManager::inputChanged( input_thread_t* p_input )
262 {
263     //This is unlikely, but can happen if no extension modules can be loaded.
264     if ( p_extensions_manager == NULL )
265         return ;
266     vlc_mutex_lock( &p_extensions_manager->lock );
267
268     extension_t *p_ext;
269     FOREACH_ARRAY( p_ext, p_extensions_manager->extensions )
270     {
271         if( extension_IsActivated( p_extensions_manager, p_ext ) )
272         {
273             extension_SetInput( p_extensions_manager, p_ext, p_input );
274         }
275     }
276     FOREACH_END()
277
278     vlc_mutex_unlock( &p_extensions_manager->lock );
279 }
280
281 void ExtensionsManager::playingChanged( int state )
282 {
283     //This is unlikely, but can happen if no extension modules can be loaded.
284     if ( p_extensions_manager == NULL )
285         return ;
286     vlc_mutex_lock( &p_extensions_manager->lock );
287
288     extension_t *p_ext;
289     FOREACH_ARRAY( p_ext, p_extensions_manager->extensions )
290     {
291         if( extension_IsActivated( p_extensions_manager, p_ext ) )
292         {
293             extension_PlayingChanged( p_extensions_manager, p_ext, state );
294         }
295     }
296     FOREACH_END()
297
298     vlc_mutex_unlock( &p_extensions_manager->lock );
299 }