]> git.sesse.net Git - vlc/blob - modules/gui/macosx/AddonManager.m
macosx/addons: add missing l10n and ignore skins
[vlc] / modules / gui / macosx / AddonManager.m
1 /*****************************************************************************
2  * AddonManager.m: Addons manager for the Mac
3  ****************************************************************************
4  * Copyright (C) 2014 VideoLAN and authors
5  * Author:       Felix Paul Kühne <fkuehne # videolan.org>
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
20  *****************************************************************************/
21
22 #import "AddonManager.h"
23
24 #import <vlc_common.h>
25 #import <vlc_events.h>
26 #import <vlc_addons.h>
27 #import "intf.h"
28
29 @interface VLCAddonManager ()
30 {
31     addons_manager_t *_manager;
32     NSMutableArray *_addons;
33     NSArray *_displayedAddons;
34 }
35
36 - (void)addAddon:(addon_entry_t *)data;
37 - (void)discoveryEnded;
38 - (void)addonChanged:(addon_entry_t *)data;
39 @end
40
41 static void addonsEventsCallback( const vlc_event_t *, void * );
42
43 static void addonsEventsCallback( const vlc_event_t *event, void *data )
44 {
45     if (event->type == vlc_AddonFound)
46         [[VLCAddonManager sharedInstance] addAddon:event->u.addon_generic_event.p_entry];
47     else if (event->type == vlc_AddonsDiscoveryEnded)
48         [[VLCAddonManager sharedInstance] discoveryEnded];
49     else if (event->type == vlc_AddonChanged)
50         [[VLCAddonManager sharedInstance] addonChanged:event->u.addon_generic_event.p_entry];
51 }
52
53 @implementation VLCAddonManager
54
55 static VLCAddonManager *_o_sharedInstance = nil;
56
57 + (VLCAddonManager *)sharedInstance
58 {
59     return _o_sharedInstance ? _o_sharedInstance : [[self alloc] init];
60 }
61
62 #pragma mark - object handling
63
64 - (id)init
65 {
66     if (_o_sharedInstance)
67         [self dealloc];
68     else {
69         _o_sharedInstance = [super init];
70         _addons = [[NSMutableArray alloc] init];
71     }
72
73     return _o_sharedInstance;
74 }
75
76 - (void)dealloc
77 {
78     [_addons release];
79     [_displayedAddons release];
80     if ( _manager )
81         addons_manager_Delete(_manager);
82     [super dealloc];
83 }
84
85 #pragma mark - UI handling
86
87 - (void)awakeFromNib
88 {
89     [_typeSwitcher removeAllItems];
90     [_typeSwitcher addItemWithTitle:_NS("All")];
91     [[_typeSwitcher lastItem] setTag: -1];
92     /* no skins on OS X so far
93     [_typeSwitcher addItemWithTitle:_NS("Skins")];
94     [[_typeSwitcher lastItem] setTag:ADDON_SKIN2]; */
95     [_typeSwitcher addItemWithTitle:_NS("Playlist parsers")];
96     [[_typeSwitcher lastItem] setTag:ADDON_PLAYLIST_PARSER];
97     [_typeSwitcher addItemWithTitle:_NS("Service discovery")];
98     [[_typeSwitcher lastItem] setTag:ADDON_SERVICE_DISCOVERY];
99     [_typeSwitcher addItemWithTitle:_NS("Extensions")];
100     [[_typeSwitcher lastItem] setTag:ADDON_EXTENSION];
101
102     [_localAddonsOnlyCheckbox setTitle:_NS("Show Installed Only")];
103     [_localAddonsOnlyCheckbox setState:NSOffState];
104     [_spinner setUsesThreadedAnimation:YES];
105
106     [_window setTitle:_NS("Addon Manager")];
107
108     [[[_addonsTable tableColumnWithIdentifier:@"installed"] headerCell] setStringValue:_NS("Installed")];
109     [[[_addonsTable tableColumnWithIdentifier:@"name"] headerCell] setStringValue:_NS("Name")];
110     [[[_addonsTable tableColumnWithIdentifier:@"author"] headerCell] setStringValue:_NS("Author")];
111     [[[_addonsTable tableColumnWithIdentifier:@"type"] headerCell] setStringValue:_NS("Type")];
112
113     _manager = addons_manager_New((vlc_object_t *)VLCIntf);
114     if (!_manager)
115         return;
116
117     vlc_event_manager_t *p_em = _manager->p_event_manager;
118     vlc_event_attach(p_em, vlc_AddonFound, addonsEventsCallback, self);
119     vlc_event_attach(p_em, vlc_AddonsDiscoveryEnded, addonsEventsCallback, self);
120     vlc_event_attach(p_em, vlc_AddonChanged, addonsEventsCallback, self);
121 }
122
123 - (void)showWindow
124 {
125     [self _findNewAddons];
126     [_spinner startAnimation:nil];
127     [_window makeKeyAndOrderFront:nil];
128 }
129
130 - (IBAction)switchType:(id)sender
131 {
132     [self _refactorDataModel];
133 }
134
135 - (IBAction)toggleLocalCheckbox:(id)sender
136 {
137     [self _refactorDataModel];
138 }
139
140 - (IBAction)tableAction:(id)sender
141 {
142     NSInteger clickedRow = [_addonsTable clickedRow];
143     if (clickedRow > _displayedAddons.count - 1 || clickedRow < 0)
144         return;
145
146     NSDictionary *currentItem = _displayedAddons[clickedRow];
147
148     if ([[currentItem objectForKey:@"state"] intValue] == ADDON_INSTALLED)
149         [self _removeAddonWithID:[[currentItem objectForKey:@"uuid"] pointerValue]];
150     else
151         [self _installAddonWithID:[[currentItem objectForKey:@"uuid"] pointerValue]];
152 }
153
154 - (NSInteger)numberOfRowsInTableView:(NSTableView *)aTableView
155 {
156     return [_displayedAddons count];
157 }
158
159 - (id)tableView:(NSTableView *)aTableView objectValueForTableColumn:(NSTableColumn *)aTableColumn row:(NSInteger)rowIndex
160 {
161     NSString *identifier = [aTableColumn identifier];
162     if ([identifier isEqualToString:@"installed"]) {
163         if ([[_displayedAddons[rowIndex] objectForKey:@"state"] intValue] == ADDON_INSTALLED)
164             return @"✔";
165         return @"✘";
166     } else if([identifier isEqualToString:@"type"])
167         return [self _getAddonType:[[_displayedAddons[rowIndex] objectForKey:@"type"] intValue]];
168
169     return [_displayedAddons[rowIndex] objectForKey:identifier];
170 }
171
172 #pragma mark - data handling
173
174 - (void)addAddon:(addon_entry_t *)p_entry
175 {
176     @autoreleasepool {
177         NSString *name = [NSString stringWithUTF8String:p_entry->psz_name ? p_entry->psz_name : ""];
178         if (p_entry->e_state == ADDON_INSTALLED)
179             name = [name stringByAppendingFormat: @" (%@)", _NS("installed")];
180
181         NSDictionary *addonProperties = [NSDictionary dictionaryWithObjectsAndKeys:
182                                          name, @"name",
183                                          [NSString stringWithUTF8String:p_entry->psz_description ? p_entry->psz_description : ""], @"description",
184                                          [NSString stringWithUTF8String:p_entry->psz_author ? p_entry->psz_author : ""], @"author",
185                                          [NSString stringWithUTF8String:p_entry->psz_source_uri ? p_entry->psz_source_uri : ""], @"uri",
186                                          [NSString stringWithUTF8String:p_entry->psz_version ? p_entry->psz_version : ""], @"version",
187                                          [NSString stringWithUTF8String:p_entry->psz_image_uri ? p_entry->psz_image_uri : ""], @"imageuri",
188                                          [NSNumber numberWithInt:p_entry->e_state], @"state",
189                                          [NSNumber numberWithInt:p_entry->e_type], @"type",
190                                          [NSValue valueWithPointer:&p_entry->uuid], @"uuid",
191                                          nil];
192
193         /* no skin support on OS X so far */
194         if ([[addonProperties objectForKey:@"type"] intValue] != ADDON_SKIN2)
195             [_addons addObject:addonProperties];
196     }
197 }
198
199 - (void)discoveryEnded
200 {
201     [self _refactorDataModel];
202     [_spinner stopAnimation:nil];
203 }
204
205 - (void)addonChanged:(addon_entry_t *)data
206 {
207     [self _refactorDataModel];
208 }
209
210 #pragma mark - helpers
211
212 - (void)_refactorDataModel
213 {
214     BOOL installedOnly = _localAddonsOnlyCheckbox.state == NSOnState;
215     int type = [[_typeSwitcher selectedItem] tag];
216
217     NSUInteger count = _addons.count;
218     NSMutableArray *filteredItems = [[NSMutableArray alloc] initWithCapacity:count];
219     NSDictionary *currentItem;
220     for (NSUInteger x = 0; x < count; x++) {
221         currentItem = _addons[x];
222         if (type != -1) {
223             if ([[currentItem objectForKey:@"type"] intValue] == type) {
224                 if (installedOnly) {
225                     if ([[currentItem objectForKey:@"state"] intValue] == ADDON_INSTALLED)
226                         [filteredItems addObject:currentItem];
227                 } else
228                     [filteredItems addObject:currentItem];
229             }
230         } else {
231             if (installedOnly) {
232                 if ([[currentItem objectForKey:@"state"] intValue] == ADDON_INSTALLED)
233                     [filteredItems addObject:currentItem];
234             } else
235                 [filteredItems addObject:currentItem];
236         }
237     }
238
239     if (_displayedAddons)
240         [_displayedAddons release];
241     _displayedAddons = [NSArray arrayWithArray:filteredItems];
242     [_displayedAddons retain];
243     [_addonsTable reloadData];
244 }
245
246 - (void)_findNewAddons
247 {
248     addons_manager_Gather(_manager, NULL);
249 }
250
251 /* FIXME: un-used */
252 - (void)_findDesignatedAddon:(NSString *)uri
253 {
254     addons_manager_Gather(_manager, [uri UTF8String]);
255 }
256
257 /* FIXME: un-used */
258 - (void)_findInstalled
259 {
260     addons_manager_LoadCatalog(_manager);
261 }
262
263 - (void)_installAddonWithID:(addon_uuid_t)addonid
264 {
265     addons_manager_Install(_manager, addonid);
266 }
267
268 - (void)_removeAddonWithID:(addon_uuid_t)addonid
269 {
270     addons_manager_Remove(_manager, addonid);
271 }
272
273 - (NSString *)_getAddonType:(int)i_type
274 {
275     switch (i_type)
276     {
277         case ADDON_SKIN2:
278             return _NS("Skins");
279         case ADDON_PLAYLIST_PARSER:
280             return _NS("Playlist parsers");
281         case ADDON_SERVICE_DISCOVERY:
282             return _NS("Service Discovery");
283         case ADDON_EXTENSION:
284             return _NS("Extensions");
285         default:
286             return _NS("Unknown");
287     }
288 }
289
290 @end