]> git.sesse.net Git - vlc/blob - modules/gui/qt4/extensions_manager.cpp
37888edaa37097c36df85f436c4439e75a1cd70c
[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, inputChanged( input_thread_t* ),
51              this, inputChanged( input_thread_t* ) );
52     b_unloading = false;
53     b_failed = false;
54 }
55
56 ExtensionsManager::~ExtensionsManager()
57 {
58     msg_Dbg( p_intf, "Killing extension dialog provider" );
59     ExtensionsDialogProvider::killInstance();
60     if( p_extensions_manager )
61     {
62         module_unneed( p_extensions_manager, p_extensions_manager->p_module );
63         vlc_object_release( p_extensions_manager );
64     }
65 }
66
67 bool ExtensionsManager::loadExtensions()
68 {
69     if( !p_extensions_manager )
70     {
71         p_extensions_manager = ( extensions_manager_t* )
72                     vlc_object_create( p_intf, sizeof( extensions_manager_t ) );
73         if( !p_extensions_manager )
74         {
75             b_failed = true;
76             emit extensionsUpdated();
77             return false;
78         }
79         vlc_object_attach( p_extensions_manager, p_intf );
80
81         p_extensions_manager->p_module =
82                 module_need( p_extensions_manager, "extension", NULL, false );
83
84         if( !p_extensions_manager->p_module )
85         {
86             msg_Err( p_intf, "Unable to load extensions module" );
87             vlc_object_release( p_extensions_manager );
88             p_extensions_manager = NULL;
89             b_failed = true;
90             emit extensionsUpdated();
91             return false;
92         }
93
94         /* Initialize dialog provider */
95         p_edp = ExtensionsDialogProvider::getInstance( p_intf,
96                                                        p_extensions_manager );
97         if( !p_edp )
98         {
99             msg_Err( p_intf, "Unable to create dialogs provider for extensions" );
100             module_unneed( p_extensions_manager,
101                            p_extensions_manager->p_module );
102             vlc_object_release( p_extensions_manager );
103             p_extensions_manager = NULL;
104             b_failed = true;
105             emit extensionsUpdated();
106             return false;
107         }
108         b_unloading = false;
109     }
110     b_failed = false;
111     emit extensionsUpdated();
112     return true;
113 }
114
115 void ExtensionsManager::unloadExtensions()
116 {
117     if( !p_extensions_manager )
118         return;
119     b_unloading = true;
120     module_unneed( p_extensions_manager, p_extensions_manager->p_module );
121     vlc_object_release( p_extensions_manager );
122     p_extensions_manager = NULL;
123     emit extensionsUpdated();
124     ExtensionsDialogProvider::killInstance();
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 ) );
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                 }
174                 if( !i_num )
175                 {
176                     action = submenu->addAction( qtr( "Empty" ) );
177                     action->setEnabled( false );
178                 }
179             }
180             else
181             {
182                 msg_Warn( p_intf, "Could not get menu for extension '%s'",
183                           p_ext->psz_title );
184                 action = submenu->addAction( qtr( "Empty" ) );
185                 action->setEnabled( false );
186             }
187
188             submenu->addSeparator();
189             action = submenu->addAction( QIcon( ":/menu/quit" ),
190                                          qtr( "Deactivate" ) );
191             menuMapper->setMapping( action, MENU_MAP( 0, i_ext ) );
192             CONNECT( action, triggered(), menuMapper, map() );
193         }
194         else
195         {
196             action = current->addAction( qfu( p_ext->psz_title ) );
197             menuMapper->setMapping( action, MENU_MAP( 0, i_ext ) );
198             CONNECT( action, triggered(), menuMapper, map() );
199
200             if( !extension_TriggerOnly( p_extensions_manager, p_ext ) )
201             {
202                 action->setCheckable( true );
203                 action->setChecked( b_Active );
204             }
205         }
206         i_ext++;
207     }
208     FOREACH_END()
209
210     vlc_mutex_unlock( &p_extensions_manager->lock );
211 }
212
213 void ExtensionsManager::triggerMenu( int id )
214 {
215     uint16_t i_ext = MENU_GET_EXTENSION( id );
216     uint16_t i_action = MENU_GET_ACTION( id );
217
218     vlc_mutex_lock( &p_extensions_manager->lock );
219
220     if( (int) i_ext > p_extensions_manager->extensions.i_size )
221     {
222         msg_Dbg( p_intf, "can't trigger extension with wrong id %d",
223                  (int) i_ext );
224         return;
225     }
226
227     extension_t *p_ext = ARRAY_VAL( p_extensions_manager->extensions, i_ext );
228     assert( p_ext != NULL);
229
230     vlc_mutex_unlock( &p_extensions_manager->lock );
231
232     if( i_action == 0 )
233     {
234         msg_Dbg( p_intf, "activating or triggering extension '%s'",
235                  p_ext->psz_title );
236
237         if( extension_TriggerOnly( p_extensions_manager, p_ext ) )
238         {
239             extension_Trigger( p_extensions_manager, p_ext );
240         }
241         else
242         {
243             if( !extension_IsActivated( p_extensions_manager, p_ext ) )
244                 extension_Activate( p_extensions_manager, p_ext );
245             else
246                 extension_Deactivate( p_extensions_manager, p_ext );
247         }
248     }
249     else
250     {
251         msg_Dbg( p_intf, "triggering extension '%s', on menu with id = 0x%x",
252                  p_ext->psz_title, i_action );
253
254         extension_TriggerMenu( p_extensions_manager, p_ext, i_action );
255     }
256 }
257
258 void ExtensionsManager::inputChanged( input_thread_t* p_input )
259 {
260     vlc_mutex_lock( &p_extensions_manager->lock );
261
262     extension_t *p_ext;
263     FOREACH_ARRAY( p_ext, p_extensions_manager->extensions )
264     {
265         if( extension_IsActivated( p_extensions_manager, p_ext ) )
266         {
267             extension_SetInput( p_extensions_manager, p_ext, p_input );
268         }
269     }
270     FOREACH_END()
271
272     vlc_mutex_unlock( &p_extensions_manager->lock );
273 }