1 /*****************************************************************************
2 * extensions_manager.cpp: Extensions manager for Cocoa
3 ****************************************************************************
4 * Copyright (C) 2009-2012 VideoLAN and authors
7 * Authors: Brendon Justin <brendonjustin@gmail.com>,
8 * Jean-Philippe André < jpeg # videolan.org >
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.
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.
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 *****************************************************************************/
25 #import "ExtensionsManager.h"
27 #import "ExtensionsDialogProvider.h"
29 #import <vlc_modules.h>
32 #define MENU_MAP(a,e) ((uint32_t)( (((uint16_t)a) << 16) | ((uint16_t)e) ))
33 #define MENU_GET_ACTION(a) ( (uint16_t)( ((uint32_t)a) >> 16 ) )
34 #define MENU_GET_EXTENSION(a) ( (uint16_t)( ((uint32_t)a) & 0xFFFF ) )
36 @implementation ExtensionsManager
38 static ExtensionsManager* instance = nil;
40 @synthesize isUnloading = b_unloading;
42 + (ExtensionsManager *)getInstance:( intf_thread_t *)_p_intf
45 instance = [[[ExtensionsManager alloc] initWithIntf:_p_intf] autorelease];
49 - (id)initWithIntf:(intf_thread_t *)_p_intf
51 if ((self = [super init]))
54 p_extensions_manager = NULL;
57 p_extDict = [[NSMutableDictionary alloc] init];
68 /** Get the extensions_manager_t if it is loaded and hold the object */
69 - (extensions_manager_t *)getManager
71 if( !p_extensions_manager )
74 vlc_object_hold( p_extensions_manager );
75 return p_extensions_manager;
78 - (void)buildMenu:(NSMenu *)extMenu
80 assert( extMenu != nil );
81 if( ![self isLoaded] )
83 // This case can happen: do nothing
87 vlc_mutex_lock( &p_extensions_manager->lock );
89 extension_t *p_ext = NULL;
91 FOREACH_ARRAY( p_ext, p_extensions_manager->extensions )
93 bool b_Active = extension_IsActivated( p_extensions_manager, p_ext );
95 NSString *titleString = [NSString stringWithCString:p_ext->psz_title
96 encoding:NSUTF8StringEncoding];
98 if( b_Active && extension_HasMenu( p_extensions_manager, p_ext ) )
100 NSMenu *submenu = [[NSMenu alloc] initWithTitle:titleString];
101 NSMenuItem *submenuItem = [extMenu addItemWithTitle:titleString
105 [extMenu setSubmenu:submenu forItem:submenuItem];
108 char **ppsz_titles = NULL;
109 uint16_t *pi_ids = NULL;
112 if( extension_GetMenu( p_extensions_manager, p_ext,
113 &ppsz_titles, &pi_ids ) == VLC_SUCCESS )
115 for( int i = 0; ppsz_titles[i] != NULL; ++i )
118 titleString = [NSString stringWithCString:ppsz_titles[i]
119 encoding:NSUTF8StringEncoding];
120 NSMenuItem *menuItem = [submenu addItemWithTitle:titleString
121 action:@selector(triggerMenu:)
123 [menuItem setTarget:self];
124 menuItem.tag = MENU_MAP(pi_ids[i], i_ext);
126 free( ppsz_titles[i] );
130 NSMenuItem *menuItem = [submenu addItemWithTitle:@"Empty"
131 action:@selector(triggerMenu:)
133 [menuItem setEnabled:NO];
140 msg_Warn( p_intf, "Could not get menu for extension '%s'",
142 NSMenuItem *menuItem = [submenu addItemWithTitle:@"Empty"
143 action:@selector(triggerMenu:)
145 [menuItem setEnabled:NO];
148 [submenu addItem:[NSMenuItem separatorItem]];
150 NSMenuItem *deactivateItem = [submenu addItemWithTitle:@"Deactivate"
151 action:@selector(triggerMenu:)
153 [deactivateItem setTarget:self];
154 deactivateItem.tag = MENU_MAP(0, i_ext);
158 NSMenuItem *menuItem = [extMenu addItemWithTitle:titleString
159 action:@selector(triggerMenu:)
161 [menuItem setTarget:self];
163 if( !extension_TriggerOnly( p_extensions_manager, p_ext ) )
166 [menuItem setState:NSOnState];
168 menuItem.tag = MENU_MAP(0, i_ext);
174 vlc_mutex_unlock( &p_extensions_manager->lock );
177 - (BOOL)loadExtensions
179 if( !p_extensions_manager )
181 p_extensions_manager = ( extensions_manager_t* )
182 vlc_object_create( p_intf, sizeof( extensions_manager_t ) );
183 if( !p_extensions_manager )
186 [delegate extensionsUpdated];
190 p_extensions_manager->p_module =
191 module_need( p_extensions_manager, "extension", NULL, false );
193 if( !p_extensions_manager->p_module )
195 msg_Err( p_intf, "Unable to load extensions module" );
196 vlc_object_release( p_extensions_manager );
197 p_extensions_manager = NULL;
199 [delegate extensionsUpdated];
203 /* Initialize dialog provider */
204 p_edp = [ExtensionsDialogProvider sharedInstance:p_intf];
209 msg_Err( p_intf, "Unable to create dialogs provider for extensions" );
210 module_unneed( p_extensions_manager,
211 p_extensions_manager->p_module );
212 vlc_object_release( p_extensions_manager );
213 p_extensions_manager = NULL;
215 [delegate extensionsUpdated];
221 [delegate extensionsUpdated];
225 - (void)unloadExtensions
227 if( !p_extensions_manager )
231 module_unneed( p_extensions_manager, p_extensions_manager->p_module );
232 vlc_object_release( p_extensions_manager );
233 p_extensions_manager = NULL;
236 - (void)reloadExtensions
238 [self unloadExtensions];
239 [self loadExtensions];
242 [delegate extensionsUpdated];
245 - (void)triggerMenu:(id)sender
247 uint32_t identifier = [(NSMenuItem *)sender tag];
249 uint16_t i_ext = MENU_GET_EXTENSION( identifier );
250 uint16_t i_action = MENU_GET_ACTION( identifier );
252 vlc_mutex_lock( &p_extensions_manager->lock );
254 if( (int) i_ext > p_extensions_manager->extensions.i_size )
256 msg_Dbg( p_intf, "can't trigger extension with wrong id %d",
261 extension_t *p_ext = ARRAY_VAL( p_extensions_manager->extensions, i_ext );
262 assert( p_ext != NULL);
264 vlc_mutex_unlock( &p_extensions_manager->lock );
268 msg_Dbg( p_intf, "activating or triggering extension '%s', id %d",
269 p_ext->psz_title, i_ext );
271 if( extension_TriggerOnly( p_extensions_manager, p_ext ) )
273 extension_Trigger( p_extensions_manager, p_ext );
277 if( !extension_IsActivated( p_extensions_manager, p_ext ) )
278 extension_Activate( p_extensions_manager, p_ext );
280 extension_Deactivate( p_extensions_manager, p_ext );
285 msg_Dbg( p_intf, "triggering extension '%s', on menu with id = 0x%x",
286 p_ext->psz_title, i_action );
288 extension_TriggerMenu( p_extensions_manager, p_ext, i_action );
292 - (void)inputChanged:(input_thread_t *)p_input
294 //This is unlikely, but can happen if no extension modules can be loaded.
295 if ( p_extensions_manager == NULL )
297 vlc_mutex_lock( &p_extensions_manager->lock );
300 FOREACH_ARRAY( p_ext, p_extensions_manager->extensions )
302 if( extension_IsActivated( p_extensions_manager, p_ext ) )
304 extension_SetInput( p_extensions_manager, p_ext, p_input );
309 vlc_mutex_unlock( &p_extensions_manager->lock );
312 - (void)playingChanged:(int)state
314 //This is unlikely, but can happen if no extension modules can be loaded.
315 if ( p_extensions_manager == NULL )
317 vlc_mutex_lock( &p_extensions_manager->lock );
320 FOREACH_ARRAY( p_ext, p_extensions_manager->extensions )
322 if( extension_IsActivated( p_extensions_manager, p_ext ) )
324 extension_PlayingChanged( p_extensions_manager, p_ext, state );
329 vlc_mutex_unlock( &p_extensions_manager->lock );
332 - (void)metaChanged:(input_item_t *)p_input
334 //This is unlikely, but can happen if no extension modules can be loaded.
335 if ( p_extensions_manager == NULL )
337 vlc_mutex_lock( &p_extensions_manager->lock );
339 FOREACH_ARRAY( p_ext, p_extensions_manager->extensions )
341 if( extension_IsActivated( p_extensions_manager, p_ext ) )
343 extension_MetaChanged( p_extensions_manager, p_ext );
347 vlc_mutex_unlock( &p_extensions_manager->lock );
352 msg_Dbg( p_intf, "Killing extension dialog provider" );
353 [ExtensionsDialogProvider killInstance];
355 if( p_extensions_manager )
356 vlc_object_release( p_extensions_manager );
365 return p_extensions_manager != NULL;
370 return b_unloading || b_failed;