macOS: Remove NSLog logging in VLCExtensionsManager
[vlc.git] / modules / gui / macosx / VLCExtensionsManager.m
1 /*****************************************************************************
2  * VLCExtensionsManager.m: Extensions manager for Cocoa
3  ****************************************************************************
4  * Copyright (C) 2009-2012 VideoLAN and authors
5  * $Id$
6  *
7  * Authors: Brendon Justin <brendonjustin@gmail.com>,
8  *          Jean-Philippe AndrĂ© < jpeg # videolan.org >
9  *
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.
14  *
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.
19  *
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  *****************************************************************************/
24
25 #import "VLCExtensionsManager.h"
26
27 #import "VLCExtensionsDialogProvider.h"
28
29 #import <vlc_modules.h>
30 #import "assert.h"
31
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))
35
36 @interface VLCExtensionsManager()
37 {
38     extensions_manager_t *p_extensions_manager;
39     VLCExtensionsDialogProvider *_extensionDialogProvider;
40
41     NSMutableDictionary *p_extDict;
42
43     BOOL b_failed; ///< Flag set to true if we could not load the module
44 }
45 @end
46
47 @implementation VLCExtensionsManager
48
49 - (id)init
50 {
51     self = [super init];
52
53     if (self) {
54         p_extensions_manager = NULL;
55         _extensionDialogProvider = [[VLCExtensionsDialogProvider alloc] init];
56
57         p_extDict = [[NSMutableDictionary alloc] init];
58
59         _isUnloading = false;
60         b_failed = false;
61     }
62
63     return self;
64 }
65
66 - (void)buildMenu:(NSMenu *)extMenu
67 {
68     assert(extMenu != nil);
69
70     /* check if stuff was loaded, which can fail */
71     if (![self isLoaded]) {
72         BOOL b_ret = [self loadExtensions];
73         if (b_ret == NO)
74             return;
75     }
76     intf_thread_t *p_intf = getIntf();
77
78     vlc_mutex_lock(&p_extensions_manager->lock);
79
80     extension_t *p_ext = NULL;
81     int i_ext = 0;
82
83     FOREACH_ARRAY(p_ext, p_extensions_manager->extensions) {
84         bool b_Active = extension_IsActivated(p_extensions_manager, p_ext);
85
86         NSString *titleString = toNSStr(p_ext->psz_title);
87
88         if (b_Active && extension_HasMenu(p_extensions_manager, p_ext)) {
89             NSMenu *submenu = [[NSMenu alloc] initWithTitle:titleString];
90             NSMenuItem *submenuItem = [extMenu addItemWithTitle:titleString
91                                                          action:nil
92                                                   keyEquivalent:@""];
93
94             [extMenu setSubmenu:submenu forItem:submenuItem];
95
96             char **ppsz_titles = NULL;
97             uint16_t *pi_ids = NULL;
98             size_t i_num = 0;
99
100             if (extension_GetMenu(p_extensions_manager, p_ext, &ppsz_titles, &pi_ids) == VLC_SUCCESS) {
101                 for (int i = 0; ppsz_titles[i] != NULL; ++i) {
102                     ++i_num;
103                     titleString = toNSStr(ppsz_titles[i]);
104                     NSMenuItem *menuItem = [submenu addItemWithTitle:titleString
105                                                               action:@selector(triggerMenu:)
106                                                        keyEquivalent:@""];
107                     [menuItem setTarget:self];
108                     menuItem.tag = MENU_MAP(pi_ids[i], i_ext);
109
110                     free(ppsz_titles[i]);
111                 }
112                 if (!i_num) {
113                     NSMenuItem *menuItem = [submenu addItemWithTitle:@"Empty"
114                                                               action:@selector(triggerMenu:)
115                                                        keyEquivalent:@""];
116                     [menuItem setEnabled:NO];
117                 }
118                 free(ppsz_titles);
119                 free(pi_ids);
120             } else {
121                 msg_Warn(p_intf, "Could not get menu for extension '%s'",
122                           p_ext->psz_title);
123                 NSMenuItem *menuItem = [submenu addItemWithTitle:@"Empty"
124                                                           action:@selector(triggerMenu:)
125                                                    keyEquivalent:@""];
126                 [menuItem setEnabled:NO];
127             }
128
129             [submenu addItem:[NSMenuItem separatorItem]];
130
131             NSMenuItem *deactivateItem = [submenu addItemWithTitle:@"Deactivate"
132                                                             action:@selector(triggerMenu:)
133                                                      keyEquivalent:@""];
134             [deactivateItem setTarget:self];
135             deactivateItem.tag = MENU_MAP(0, i_ext);
136         }
137         else
138         {
139             NSMenuItem *menuItem = [extMenu addItemWithTitle:titleString
140                                                      action:@selector(triggerMenu:)
141                                               keyEquivalent:@""];
142             [menuItem setTarget:self];
143
144             if (!extension_TriggerOnly(p_extensions_manager, p_ext)) {
145                 if (b_Active)
146                     [menuItem setState:NSOnState];
147             }
148             menuItem.tag = MENU_MAP(0, i_ext);
149         }
150         i_ext++;
151     }
152     FOREACH_END()
153
154     vlc_mutex_unlock(&p_extensions_manager->lock);
155 }
156
157 - (BOOL)loadExtensions
158 {
159     intf_thread_t *p_intf = getIntf();
160     if (!p_extensions_manager) {
161         p_extensions_manager = (extensions_manager_t*)vlc_object_create(p_intf, sizeof(extensions_manager_t));
162         if (!p_extensions_manager) {
163             b_failed = true;
164             return false;
165         }
166
167         p_extensions_manager->p_module = module_need(p_extensions_manager, "extension", NULL, false);
168
169         if (!p_extensions_manager->p_module) {
170             msg_Err(p_intf, "Unable to load extensions module");
171             vlc_object_release(p_extensions_manager);
172             p_extensions_manager = NULL;
173             b_failed = true;
174             return false;
175         }
176
177         _isUnloading = false;
178     }
179     b_failed = false;
180     return true;
181 }
182
183 - (void)unloadExtensions
184 {
185     if (!p_extensions_manager)
186         return;
187     _isUnloading = true;
188
189     module_unneed(p_extensions_manager, p_extensions_manager->p_module);
190     vlc_object_release(p_extensions_manager);
191     p_extensions_manager = NULL;
192 }
193
194 - (void)reloadExtensions
195 {
196     [self unloadExtensions];
197     [self loadExtensions];
198 }
199
200 - (void)triggerMenu:(id)sender
201 {
202     intf_thread_t *p_intf = getIntf();
203     uint32_t identifier = [(NSMenuItem *)sender tag];
204
205     uint16_t i_ext = MENU_GET_EXTENSION(identifier);
206     uint16_t i_action = MENU_GET_ACTION(identifier);
207
208     vlc_mutex_lock(&p_extensions_manager->lock);
209
210     if ((int) i_ext > p_extensions_manager->extensions.i_size) {
211         msg_Dbg(p_intf, "can't trigger extension with wrong id %d",
212                  (int) i_ext);
213         return;
214     }
215
216     extension_t *p_ext = ARRAY_VAL(p_extensions_manager->extensions, i_ext);
217     assert(p_ext != NULL);
218
219     vlc_mutex_unlock(&p_extensions_manager->lock);
220
221     if (i_action == 0) {
222         msg_Dbg(p_intf, "activating or triggering extension '%s', id %d",
223                  p_ext->psz_title, i_ext);
224
225         if (extension_TriggerOnly(p_extensions_manager, p_ext)) {
226             extension_Trigger(p_extensions_manager, p_ext);
227         } else {
228             if (!extension_IsActivated(p_extensions_manager, p_ext))
229                 extension_Activate(p_extensions_manager, p_ext);
230             else
231                 extension_Deactivate(p_extensions_manager, p_ext);
232         }
233     }
234     else
235     {
236         msg_Dbg(p_intf, "triggering extension '%s', on menu with id = 0x%x",
237                  p_ext->psz_title, i_action);
238
239         extension_TriggerMenu(p_extensions_manager, p_ext, i_action);
240     }
241 }
242
243 - (void)inputChanged:(input_thread_t *)p_input
244 {
245     //This is unlikely, but can happen if no extension modules can be loaded.
246     if (p_extensions_manager == NULL)
247         return;
248     vlc_mutex_lock(&p_extensions_manager->lock);
249
250     extension_t *p_ext;
251     FOREACH_ARRAY(p_ext, p_extensions_manager->extensions) {
252         if (extension_IsActivated(p_extensions_manager, p_ext))
253             extension_SetInput(p_extensions_manager, p_ext, p_input);
254     }
255     FOREACH_END()
256
257     vlc_mutex_unlock(&p_extensions_manager->lock);
258 }
259
260 - (void)playingChanged:(int)state
261 {
262     //This is unlikely, but can happen if no extension modules can be loaded.
263     if (p_extensions_manager == NULL)
264         return;
265     vlc_mutex_lock(&p_extensions_manager->lock);
266
267     extension_t *p_ext;
268     FOREACH_ARRAY(p_ext, p_extensions_manager->extensions) {
269         if (extension_IsActivated(p_extensions_manager, p_ext))
270             extension_PlayingChanged(p_extensions_manager, p_ext, state);
271     }
272     FOREACH_END()
273
274     vlc_mutex_unlock(&p_extensions_manager->lock);
275 }
276
277 - (void)metaChanged:(input_item_t *)p_input
278 {
279     //This is unlikely, but can happen if no extension modules can be loaded.
280     if (p_extensions_manager == NULL)
281         return;
282     vlc_mutex_lock(&p_extensions_manager->lock);
283     extension_t *p_ext;
284     FOREACH_ARRAY(p_ext, p_extensions_manager->extensions) {
285         if (extension_IsActivated(p_extensions_manager, p_ext))
286             extension_MetaChanged(p_extensions_manager, p_ext);
287     }
288     FOREACH_END()
289     vlc_mutex_unlock(&p_extensions_manager->lock);
290 }
291
292 - (void)dealloc
293 {
294     intf_thread_t *p_intf = getIntf();
295     msg_Dbg(p_intf, "Deinitializing extensions manager");
296
297     _extensionDialogProvider = nil;
298     if (p_extensions_manager)
299         vlc_object_release(p_extensions_manager);
300 }
301
302 - (BOOL)isLoaded
303 {
304     return p_extensions_manager != NULL;
305 }
306
307 - (BOOL)cannotLoad
308 {
309     return self.isUnloading || b_failed;
310 }
311
312 @end