pcsxr-1.9.92
[pcsx_rearmed.git] / macosx / PluginList.m
1 //
2 //  PluginList.m
3 //  Pcsx
4 //
5 //  Created by Gil Pedersen on Sun Sep 21 2003.
6 //  Copyright (c) 2003 __MyCompanyName__. All rights reserved.
7 //
8
9 #import "EmuThread.h"
10 #import "PluginList.h"
11 #import "PcsxPlugin.h"
12 #include "psxcommon.h"
13 #include "plugins.h"
14
15 //NSMutableArray *plugins;
16 static PluginList *sPluginList = nil;
17 const static int typeList[4] = {PSE_LT_GPU, PSE_LT_SPU, PSE_LT_CDR, PSE_LT_PAD};
18
19 @implementation PluginList
20
21 + (PluginList *)list
22 {
23         return sPluginList;
24 }
25
26 #if 0
27 + (void)loadPlugins
28 {
29     NSDirectoryEnumerator *dirEnum;
30     NSString *pname, *dir;
31     
32     // Make sure we only load the plugins once
33     if (plugins != nil)
34         return;
35     
36     plugins = [[NSMutableArray alloc] initWithCapacity: 20];
37
38     dir = [NSString stringWithCString:Config.PluginsDir];
39     dirEnum = [[NSFileManager defaultManager] enumeratorAtPath:dir];
40     
41     while (pname = [dirEnum nextObject]) {
42         if ([[pname pathExtension] isEqualToString:@"psxplugin"] || 
43             [[pname pathExtension] isEqualToString:@"so"]) {
44             [dirEnum skipDescendents]; /* don't enumerate this
45                                             directory */
46             
47             PcsxPlugin *plugin = [[PcsxPlugin alloc] initWithPath:pname];
48             if (plugin != nil) {
49                 [plugins addObject:plugin];
50             }
51         }
52     }
53 }
54
55 - (id)initWithType:(int)typeMask
56 {
57     unsigned int i;
58     
59     self = [super init];
60
61     [PluginList loadPlugins];
62     list = [[NSMutableArray alloc] initWithCapacity: 5];
63     
64     type = typeMask;
65     for (i=0; i<[plugins count]; i++) {
66         PcsxPlugin *plugin = [plugins objectAtIndex:i];
67         if ([plugin getType] == type) {
68             [list addObject:plugin];
69         }
70     }
71     
72     return self;
73 }
74
75 - (int)numberOfItems
76 {
77     return [list count];
78 }
79
80 - (id)objectAtIndex:(unsigned)index
81 {
82         return [list objectAtIndex:index];
83 }
84 #endif
85
86
87
88 - (id)init
89 {
90         int i;
91         
92         if (!(self = [super init]))
93                 return nil;
94         
95         NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
96         pluginList = [[NSMutableArray alloc] initWithCapacity:20];
97
98         activeGpuPlugin = activeSpuPlugin = activeCdrPlugin = activePadPlugin = nil;
99         
100         missingPlugins = NO;
101         for (i=0; i<sizeof(*typeList); i++) {
102                 NSString *path = [defaults stringForKey:[PcsxPlugin getDefaultKeyForType:typeList[i]]];
103                 if (nil == path) {
104                         missingPlugins = YES;
105                         continue;
106                 }
107                 if ([path isEqualToString:@"Disabled"])
108                         continue;
109                 
110                 if (![self hasPluginAtPath:path]) {
111                         PcsxPlugin *plugin = [[PcsxPlugin alloc] initWithPath:path];
112                         if (plugin) {
113                                 [pluginList addObject:plugin];
114                                 if (![self setActivePlugin:plugin forType:typeList[i]])
115                                         missingPlugins = YES;
116                         } else {
117                                 missingPlugins = YES;
118                         }
119                 }
120         }
121         
122         if (missingPlugins) {
123                 [self refreshPlugins];
124         }
125         
126         sPluginList = self;
127         
128         return self;
129 }
130
131 - (void)dealloc
132 {
133         [activeGpuPlugin release];
134         [activeSpuPlugin release];
135         [activeCdrPlugin release];
136         [activePadPlugin release];
137         
138         [pluginList release];
139         
140         if (sPluginList == self)
141                 sPluginList = nil;
142         
143         [super dealloc];
144 }
145
146 - (void)refreshPlugins
147 {
148         NSDirectoryEnumerator *dirEnum;
149         NSString *pname, *dir;
150         int i;
151         
152         // verify that the ones that are in list still works
153         for (i=0; i<[pluginList count]; i++) {
154                 if (![[pluginList objectAtIndex:i] verifyOK]) {
155                         [pluginList removeObjectAtIndex:i]; i--;
156                 }
157         }
158         
159         // look for new ones in the plugin directory
160         dir = [NSString stringWithCString:Config.PluginsDir];
161         dirEnum = [[NSFileManager defaultManager] enumeratorAtPath:dir];
162         
163         while (pname = [dirEnum nextObject]) {
164                 if ([[pname pathExtension] isEqualToString:@"psxplugin"] || 
165                         [[pname pathExtension] isEqualToString:@"so"]) {
166                         [dirEnum skipDescendents]; /* don't enumerate this
167                                                                                                                 directory */
168                         
169                         if (![self hasPluginAtPath:pname]) {
170                                 PcsxPlugin *plugin = [[PcsxPlugin alloc] initWithPath:pname];
171                                 if (plugin != nil) {
172                                         [pluginList addObject:plugin];
173                                 }
174                         }
175                 }
176         }
177         
178         // check the we have the needed plugins
179         missingPlugins = NO;
180         for (i=0; i<sizeof(*typeList); i++) {
181                 PcsxPlugin *plugin = [self activePluginForType:typeList[i]];
182                 if (nil == plugin) {
183                         NSArray *list = [self pluginsForType:typeList[i]];
184                         int j;
185                         
186                         for (j=0; j<[list count]; j++) {
187                                 if ([self setActivePlugin:[list objectAtIndex:j] forType:typeList[i]])
188                                         break;
189                         }
190                         if (j == [list count])
191                                 missingPlugins = YES;
192                 }
193         }
194 }
195
196 - (NSArray *)pluginsForType:(int)typeMask
197 {
198         NSMutableArray *types = [NSMutableArray array];
199         int i;
200         
201         for (i=0; i<[pluginList count]; i++) {
202                 PcsxPlugin *plugin = [pluginList objectAtIndex:i];
203                 
204                 if ([plugin getType] & typeMask) {
205                         [types addObject:plugin];
206                 }
207         }
208         
209         return types;
210 }
211
212 - (BOOL)hasPluginAtPath:(NSString *)path
213 {
214         if (nil == path)
215                 return NO;
216         
217         int i;
218         for (i=0; i<[pluginList count]; i++) {
219                 if ([[[pluginList objectAtIndex:i] path] isEqualToString:path])
220                         return YES;
221         }
222         
223         return NO;
224 }
225
226 // returns if all the required plugins are available
227 - (BOOL)configured
228 {
229         return !missingPlugins;
230 }
231
232 - (BOOL)doInitPlugins
233 {
234         BOOL bad = NO;
235         
236         if ([activeGpuPlugin initAs:PSE_LT_GPU] != 0) bad = YES;
237         if ([activeSpuPlugin initAs:PSE_LT_SPU] != 0) bad = YES;
238         if ([activeCdrPlugin initAs:PSE_LT_CDR] != 0) bad = YES;
239         if ([activePadPlugin initAs:PSE_LT_PAD] != 0) bad = YES;
240         
241         return !bad;
242 }
243
244 - (PcsxPlugin *)activePluginForType:(int)type
245 {
246         switch (type) {
247                 case PSE_LT_GPU: return activeGpuPlugin;
248                 case PSE_LT_CDR: return activeCdrPlugin;
249                 case PSE_LT_SPU: return activeSpuPlugin;
250                 case PSE_LT_PAD: return activePadPlugin;
251 //              case PSE_LT_NET: return activeNetPlugin;
252         }
253         
254         return nil;
255 }
256
257 - (BOOL)setActivePlugin:(PcsxPlugin *)plugin forType:(int)type
258 {
259         PcsxPlugin **pluginPtr;
260         switch (type) {
261                 case PSE_LT_GPU: pluginPtr = &activeGpuPlugin; break;
262                 case PSE_LT_CDR: pluginPtr = &activeCdrPlugin; break;
263                 case PSE_LT_SPU: pluginPtr = &activeSpuPlugin; break;
264                 case PSE_LT_PAD: pluginPtr = &activePadPlugin; break;
265 //              case PSE_LT_NET: pluginPtr = &activeNetPlugin; break;
266                 default: return NO;
267         }
268         
269         if (plugin == *pluginPtr)
270                 return YES;
271         
272         BOOL active = (*pluginPtr) && [EmuThread active];
273         BOOL wasPaused = NO;
274         if (active) {
275                 // TODO: temporary freeze?
276                 wasPaused = [EmuThread pauseSafe];
277                 ClosePlugins();
278                 ReleasePlugins();
279         }
280         
281         // stop the old plugin and start the new one
282         if (*pluginPtr) {
283                 [*pluginPtr shutdownAs:type];
284                 
285                 [*pluginPtr release];
286         }
287         *pluginPtr = [plugin retain];
288         if (*pluginPtr) {
289                 if ([*pluginPtr initAs:type] != 0) {
290                         [*pluginPtr release];
291                         *pluginPtr = nil;
292                 }
293         }
294         
295         // write path to the correct config entry
296         const char *str;
297         if (*pluginPtr != nil) {
298                 str = [[plugin path] fileSystemRepresentation];
299                 if (str == nil) {
300                         str = "Invalid Plugin";
301                 }
302         } else {
303                 str = "Invalid Plugin";
304         }
305         
306         char **dst = [PcsxPlugin getConfigEntriesForType:type];
307         while (*dst) {
308                 strncpy(*dst, str, 255);
309                 dst++;
310         }
311         
312         if (active) {
313                 LoadPlugins();
314                 OpenPlugins();
315                 
316                 if (!wasPaused) {
317                         [EmuThread resume];
318                 }
319         }
320         
321         return *pluginPtr != nil;
322 }
323
324 @end