Commit | Line | Data |
---|---|---|
ef79bbde P |
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 |