]> git.sesse.net Git - vlc/blob - modules/gui/qt4/extensions_manager.cpp
Qt: Call Lua status callbacks on playing status changes
[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     CONNECT( 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     module_unneed( p_extensions_manager, p_extensions_manager->p_module );
122     vlc_object_release( p_extensions_manager );
123     p_extensions_manager = NULL;
124     emit extensionsUpdated();
125     ExtensionsDialogProvider::killInstance();
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 ) );
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                 }
175                 if( !i_num )
176                 {
177                     action = submenu->addAction( qtr( "Empty" ) );
178                     action->setEnabled( false );
179                 }
180             }
181             else
182             {
183                 msg_Warn( p_intf, "Could not get menu for extension '%s'",
184                           p_ext->psz_title );
185                 action = submenu->addAction( qtr( "Empty" ) );
186                 action->setEnabled( false );
187             }
188
189             submenu->addSeparator();
190             action = submenu->addAction( QIcon( ":/menu/quit" ),
191                                          qtr( "Deactivate" ) );
192             menuMapper->setMapping( action, MENU_MAP( 0, i_ext ) );
193             CONNECT( action, triggered(), menuMapper, map() );
194         }
195         else
196         {
197             action = current->addAction( qfu( p_ext->psz_title ) );
198             menuMapper->setMapping( action, MENU_MAP( 0, i_ext ) );
199             CONNECT( action, triggered(), menuMapper, map() );
200
201             if( !extension_TriggerOnly( p_extensions_manager, p_ext ) )
202             {
203                 action->setCheckable( true );
204                 action->setChecked( b_Active );
205             }
206         }
207         i_ext++;
208     }
209     FOREACH_END()
210
211     vlc_mutex_unlock( &p_extensions_manager->lock );
212 }
213
214 void ExtensionsManager::triggerMenu( int id )
215 {
216     uint16_t i_ext = MENU_GET_EXTENSION( id );
217     uint16_t i_action = MENU_GET_ACTION( id );
218
219     vlc_mutex_lock( &p_extensions_manager->lock );
220
221     if( (int) i_ext > p_extensions_manager->extensions.i_size )
222     {
223         msg_Dbg( p_intf, "can't trigger extension with wrong id %d",
224                  (int) i_ext );
225         return;
226     }
227
228     extension_t *p_ext = ARRAY_VAL( p_extensions_manager->extensions, i_ext );
229     assert( p_ext != NULL);
230
231     vlc_mutex_unlock( &p_extensions_manager->lock );
232
233     if( i_action == 0 )
234     {
235         msg_Dbg( p_intf, "activating or triggering extension '%s'",
236                  p_ext->psz_title );
237
238         if( extension_TriggerOnly( p_extensions_manager, p_ext ) )
239         {
240             extension_Trigger( p_extensions_manager, p_ext );
241         }
242         else
243         {
244             if( !extension_IsActivated( p_extensions_manager, p_ext ) )
245                 extension_Activate( p_extensions_manager, p_ext );
246             else
247                 extension_Deactivate( p_extensions_manager, p_ext );
248         }
249     }
250     else
251     {
252         msg_Dbg( p_intf, "triggering extension '%s', on menu with id = 0x%x",
253                  p_ext->psz_title, i_action );
254
255         extension_TriggerMenu( p_extensions_manager, p_ext, i_action );
256     }
257 }
258
259 void ExtensionsManager::inputChanged( input_thread_t* p_input )
260 {
261     vlc_mutex_lock( &p_extensions_manager->lock );
262
263     extension_t *p_ext;
264     FOREACH_ARRAY( p_ext, p_extensions_manager->extensions )
265     {
266         if( extension_IsActivated( p_extensions_manager, p_ext ) )
267         {
268             extension_SetInput( p_extensions_manager, p_ext, p_input );
269         }
270     }
271     FOREACH_END()
272
273     vlc_mutex_unlock( &p_extensions_manager->lock );
274 }
275
276 void ExtensionsManager::playingChanged( int state )
277 {
278     vlc_mutex_lock( &p_extensions_manager->lock );
279
280     extension_t *p_ext;
281     FOREACH_ARRAY( p_ext, p_extensions_manager->extensions )
282     {
283         if( extension_IsActivated( p_extensions_manager, p_ext ) )
284         {
285             extension_PlayingChanged( p_extensions_manager, p_ext, state );
286         }
287     }
288     FOREACH_END()
289
290     vlc_mutex_unlock( &p_extensions_manager->lock );
291 }