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])) {
53 p_extensions_manager = NULL;
56 p_extDict = [[NSMutableDictionary alloc] init];
67 - (void)buildMenu:(NSMenu *)extMenu
69 assert(extMenu != nil);
71 // This case can happen: do nothing
74 vlc_mutex_lock(&p_extensions_manager->lock);
76 extension_t *p_ext = NULL;
78 FOREACH_ARRAY(p_ext, p_extensions_manager->extensions) {
79 bool b_Active = extension_IsActivated(p_extensions_manager, p_ext);
81 NSString *titleString = [NSString stringWithCString:p_ext->psz_title
82 encoding:NSUTF8StringEncoding];
84 if (b_Active && extension_HasMenu(p_extensions_manager, p_ext)) {
85 NSMenu *submenu = [[NSMenu alloc] initWithTitle:titleString];
86 NSMenuItem *submenuItem = [extMenu addItemWithTitle:titleString
90 [extMenu setSubmenu:submenu forItem:submenuItem];
93 char **ppsz_titles = NULL;
94 uint16_t *pi_ids = NULL;
97 if (extension_GetMenu(p_extensions_manager, p_ext,
98 &ppsz_titles, &pi_ids) == VLC_SUCCESS) {
99 for (int i = 0; ppsz_titles[i] != NULL; ++i) {
101 titleString = [NSString stringWithCString:ppsz_titles[i]
102 encoding:NSUTF8StringEncoding];
103 NSMenuItem *menuItem = [submenu addItemWithTitle:titleString
104 action:@selector(triggerMenu:)
106 [menuItem setTarget:self];
107 menuItem.tag = MENU_MAP(pi_ids[i], i_ext);
109 free(ppsz_titles[i]);
112 NSMenuItem *menuItem = [submenu addItemWithTitle:@"Empty"
113 action:@selector(triggerMenu:)
115 [menuItem setEnabled:NO];
120 msg_Warn(p_intf, "Could not get menu for extension '%s'",
122 NSMenuItem *menuItem = [submenu addItemWithTitle:@"Empty"
123 action:@selector(triggerMenu:)
125 [menuItem setEnabled:NO];
128 [submenu addItem:[NSMenuItem separatorItem]];
130 NSMenuItem *deactivateItem = [submenu addItemWithTitle:@"Deactivate"
131 action:@selector(triggerMenu:)
133 [deactivateItem setTarget:self];
134 deactivateItem.tag = MENU_MAP(0, i_ext);
138 NSMenuItem *menuItem = [extMenu addItemWithTitle:titleString
139 action:@selector(triggerMenu:)
141 [menuItem setTarget:self];
143 if (!extension_TriggerOnly(p_extensions_manager, p_ext)) {
145 [menuItem setState:NSOnState];
147 menuItem.tag = MENU_MAP(0, i_ext);
153 vlc_mutex_unlock(&p_extensions_manager->lock);
156 - (BOOL)loadExtensions
158 if (!p_extensions_manager) {
159 p_extensions_manager = (extensions_manager_t*)
160 vlc_object_create(p_intf, sizeof(extensions_manager_t));
161 if (!p_extensions_manager) {
163 [delegate extensionsUpdated];
167 p_extensions_manager->p_module =
168 module_need(p_extensions_manager, "extension", NULL, false);
170 if (!p_extensions_manager->p_module) {
171 msg_Err(p_intf, "Unable to load extensions module");
172 vlc_object_release(p_extensions_manager);
173 p_extensions_manager = NULL;
175 [delegate extensionsUpdated];
179 /* Initialize dialog provider */
180 p_edp = [ExtensionsDialogProvider sharedInstance:p_intf];
184 msg_Err(p_intf, "Unable to create dialogs provider for extensions");
185 module_unneed(p_extensions_manager,
186 p_extensions_manager->p_module);
187 vlc_object_release(p_extensions_manager);
188 p_extensions_manager = NULL;
190 [delegate extensionsUpdated];
196 [delegate extensionsUpdated];
200 - (void)unloadExtensions
202 if (!p_extensions_manager)
206 module_unneed(p_extensions_manager, p_extensions_manager->p_module);
207 vlc_object_release(p_extensions_manager);
208 p_extensions_manager = NULL;
211 - (void)reloadExtensions
213 [self unloadExtensions];
214 [self loadExtensions];
217 [delegate extensionsUpdated];
220 - (void)triggerMenu:(id)sender
222 uint32_t identifier = [(NSMenuItem *)sender tag];
224 uint16_t i_ext = MENU_GET_EXTENSION(identifier);
225 uint16_t i_action = MENU_GET_ACTION(identifier);
227 vlc_mutex_lock(&p_extensions_manager->lock);
229 if ((int) i_ext > p_extensions_manager->extensions.i_size) {
230 msg_Dbg(p_intf, "can't trigger extension with wrong id %d",
235 extension_t *p_ext = ARRAY_VAL(p_extensions_manager->extensions, i_ext);
236 assert(p_ext != NULL);
238 vlc_mutex_unlock(&p_extensions_manager->lock);
241 msg_Dbg(p_intf, "activating or triggering extension '%s', id %d",
242 p_ext->psz_title, i_ext);
244 if (extension_TriggerOnly(p_extensions_manager, p_ext)) {
245 extension_Trigger(p_extensions_manager, p_ext);
247 if (!extension_IsActivated(p_extensions_manager, p_ext))
248 extension_Activate(p_extensions_manager, p_ext);
250 extension_Deactivate(p_extensions_manager, p_ext);
255 msg_Dbg(p_intf, "triggering extension '%s', on menu with id = 0x%x",
256 p_ext->psz_title, i_action);
258 extension_TriggerMenu(p_extensions_manager, p_ext, i_action);
262 - (void)inputChanged:(input_thread_t *)p_input
264 //This is unlikely, but can happen if no extension modules can be loaded.
265 if (p_extensions_manager == NULL)
267 vlc_mutex_lock(&p_extensions_manager->lock);
270 FOREACH_ARRAY(p_ext, p_extensions_manager->extensions) {
271 if (extension_IsActivated(p_extensions_manager, p_ext))
272 extension_SetInput(p_extensions_manager, p_ext, p_input);
276 vlc_mutex_unlock(&p_extensions_manager->lock);
279 - (void)playingChanged:(int)state
281 //This is unlikely, but can happen if no extension modules can be loaded.
282 if (p_extensions_manager == NULL)
284 vlc_mutex_lock(&p_extensions_manager->lock);
287 FOREACH_ARRAY(p_ext, p_extensions_manager->extensions) {
288 if (extension_IsActivated(p_extensions_manager, p_ext))
289 extension_PlayingChanged(p_extensions_manager, p_ext, state);
293 vlc_mutex_unlock(&p_extensions_manager->lock);
296 - (void)metaChanged:(input_item_t *)p_input
298 //This is unlikely, but can happen if no extension modules can be loaded.
299 if (p_extensions_manager == NULL)
301 vlc_mutex_lock(&p_extensions_manager->lock);
303 FOREACH_ARRAY(p_ext, p_extensions_manager->extensions) {
304 if (extension_IsActivated(p_extensions_manager, p_ext))
305 extension_MetaChanged(p_extensions_manager, p_ext);
308 vlc_mutex_unlock(&p_extensions_manager->lock);
313 msg_Dbg(p_intf, "Killing extension dialog provider");
314 [ExtensionsDialogProvider killInstance];
316 if (p_extensions_manager)
317 vlc_object_release(p_extensions_manager);
326 return p_extensions_manager != NULL;
331 return b_unloading || b_failed;