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