1 /* OpenCP Module Player
2 * copyright (c) '94-'10 Niklas Beisert <nbeisert@physik.tu-muenchen.de>
3 * copyright (c) '04-'21 Stian Skjelstad <stian.skjelstad@gmail.com>
4 *
5 * Main routine, calls fileselector and interface code
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., 675 Mass Ave, Cambridge, MA 02139, USA.
20 *
21 * revision history: (please note changes here)
22 * -nb980510 Niklas Beisert <nbeisert@physik.tu-muenchen.de>
23 * -first release
24 * -kb980717 Tammo Hinrichs
25 * -complete restructuring of fsMain_ etc. to enable non-playable
26 * file types which are handled differently
27 * -therefore, added "handler" line in CP.INI filetype entries
28 * -added routines to read out PLS and M3U play lists
29 * -as always, added dllinfo record ;)
30 * -fd981014 Felix Domke <tmbinc@gmx.net>
31 * -small bugfix (tf was closed, even if it was NULL)
32 * -ss040918 Stian Skjelstad <stian@nixia.no>
33 * -minor tweak.. Do not touch any screen functions after conRestore and
34 * before conSave
35 */
36
37 #define NO_PFILESEL_IMPORT
38 #include "config.h"
39 #include <assert.h>
40 #include <stdio.h>
41 #include <stdlib.h>
42 #include <string.h>
43 #include "types.h"
44
45 #include "boot/plinkman.h"
46 #include "boot/pmain.h"
47 #include "boot/psetting.h"
48 #include "dirdb.h"
49 #include "filesystem.h"
50 #include "mdb.h"
51 #include "pfilesel.h"
52 #include "stuff/err.h"
53 #include "stuff/poutput.h"
54
55 extern struct mdbreadinforegstruct fsReadInfoReg;
56
57 static struct moduleinfostruct nextinfo;
58 static struct moduleinfostruct plModuleInfo;
59
60 typedef enum
61 {
62 DoNotForceCallFS = 0,
63 DoForceCallFS = 1
64 } enumForceCallFS;
65
66 typedef enum
67 {
68 DoNotAutoCallFS = 0,
69 DoAutoCallFS = 1
70 } enumAutoCallFS;
71
72 typedef enum
73 {
74 DoNotForceNext=0,
75 DoForceNext=1,
76 DoForcePrev=2
77 } enumForceNext;
78
79 static enumAutoCallFS callfs;
80 static char firstfile;
81
82 static interfaceReturnEnum stop;
83
84 /* stop: 0 cont
85 * 1 next song
86 * 6 prev song
87 * 2 quit
88 * 3 iface : next song or fs
89 * 4 iface : call fs
90 * 5 iface : dosshell
91 */
92
93
94
95 /* return values:
96 * 0 - no files available (and user hit esc)
97 * 1 - we have a new song availble
98 * -1 - error occured
99 */
100
callselector(struct moduleinfostruct * info,struct ocpfilehandle_t ** fi,enumAutoCallFS callfs,enumForceCallFS forcecall,enumForceNext forcenext,struct interfacestruct ** iface)101 static int callselector (struct moduleinfostruct *info,
102 struct ocpfilehandle_t **fi,
103 enumAutoCallFS callfs,
104 enumForceCallFS forcecall,
105 enumForceNext forcenext,
106 struct interfacestruct **iface)
107 {
108 int ret;
109 int result;
110 struct interfacestruct *intr;
111 struct moduleinfostruct tmodinfo;
112 char secname[20];
113
114 if (*fi)
115 {
116 (*fi)->unref (*fi);
117 *fi = 0;
118 }
119 *iface=0;
120
121 do
122 {
123 ret=result=0;
124 if ((callfs && !fsFilesLeft())||forcecall)
125 ret=result=fsFileSelect();
126
127 if (!fsFilesLeft())
128 return 0;
129
130 while (ret || forcenext)
131 {
132 conRestore();
133
134 if (!fsFilesLeft())
135 {
136 conSave();
137 break;
138 }
139 if (forcenext==2)
140 {
141 if (!fsGetPrevFile(&tmodinfo, fi))
142 {
143 assert ((*fi)==NULL);
144 conSave();
145 continue;
146 }
147 } else {
148 if (!fsGetNextFile(&tmodinfo, fi))
149 {
150 assert ((*fi)==NULL);
151 conSave();
152 continue;
153 }
154 }
155
156 sprintf(secname, "filetype %d", tmodinfo.modtype&0xFF);
157 intr=plFindInterface(cfGetProfileString(secname, "interface", ""));
158 #if 0
159 hdlr=(struct filehandlerstruct *)_lnkGetSymbol(cfGetProfileString(secname, "handler", ""));
160 if (hdlr)
161 {
162 hdlr->Process(*dirdbref, &tmodinfo, &tf);
163 }
164 #endif
165
166 conSave();
167 {
168 unsigned int i;
169 for (i=0;i<plScrHeight;i++)
170 displayvoid(i, 0, plScrWidth);
171 }
172
173 if (intr)
174 {
175 ret=0;
176 *iface = intr;
177 *info = tmodinfo;
178
179 return result?-1:1;
180 } else {
181 /* we failed to get an interface for this file */
182 if (*fi)
183 {
184 fsForceRemove ((*fi)->dirdb_ref);
185 (*fi)->unref (*fi);
186 *fi = 0;
187 }
188 }
189 }
190 if (ret)
191 conSave();
192 } while (ret);
193
194 return 0;
195 }
196
_fsMain(int argc,char * argv[])197 static int _fsMain(int argc, char *argv[])
198 {
199 struct interfacestruct *plintr = 0;
200 struct interfacestruct *nextintr = 0;
201 struct ocpfilehandle_t *thisf=NULL;
202 struct ocpfilehandle_t *nextf=NULL;
203
204 conSave();
205
206 callfs=DoNotAutoCallFS;
207 stop=interfaceReturnContinue;
208 firstfile=1;
209
210 #ifdef DOS32
211 /* TODO.. this can be done on xterm consoles, and proc titles*/
212 setwintitle("OpenCP");
213 #endif
214
215 fsRescanDir();
216
217 while (1)
218 {
219 struct preprocregstruct *prep;
220
221 /*
222 while (ekbhit())
223 {
224 uint16_t key=egetch();
225 if ((key==0)||(key==3)||(key==27))
226 stop=interfaceReturnQuit;
227 }*/
228 if (stop==interfaceReturnQuit)
229 break;
230
231 if (!plintr)
232 {
233 int fsr;
234 conSave();
235 fsr=callselector (&nextinfo, &nextf, (callfs||firstfile), (stop==interfaceReturnCallFs)?DoForceCallFS:DoNotForceCallFS, DoForceNext, &nextintr);
236 if (!fsr)
237 {
238 break;
239 } else if (fsr==-1)
240 {
241 callfs=DoAutoCallFS;
242 }
243 conRestore();
244 }
245 stop=interfaceReturnContinue;
246
247 if (callfs)
248 firstfile=0;
249
250 if (nextintr)
251 {
252 conRestore();
253
254 if (plintr)
255 {
256 plintr->Close();
257 plintr=0;
258 /* _heapshrink(); */
259 }
260
261 if (thisf)
262 {
263 thisf->unref (thisf);
264 thisf=NULL;
265 }
266
267 thisf = nextf;
268 nextf = 0;
269 plModuleInfo=nextinfo;
270 plintr=nextintr;
271 nextintr=0;
272
273 stop=interfaceReturnContinue;
274
275 for (prep=plPreprocess; prep; prep=prep->next)
276 {
277 prep->Preprocess(&plModuleInfo, &thisf);
278 }
279
280 if (!plintr->Init(&plModuleInfo, thisf))
281 {
282 stop = interfaceReturnCallFs; /* file failed, exit to filebrowser, if we don't do this, we can end up with a freeze if we only have this invalid file in the playlist, optional we could remove the file... */
283 plintr=0;
284 } else {
285 /*
286 char wt[256];
287 char realname[13];
288 memset(wt,0,256);
289 fsConv12FileName(realname,plModuleInfo.name);
290 strncpy(wt,realname,12);
291 strcat(wt," - ");
292 strncat(wt,plModuleInfo.modname,32);
293 #ifdef DOS32
294 setwintitle(wt);
295 #endif
296 */
297 }
298 conSave();
299 }
300
301 if (plintr)
302 {
303 while (!stop) /* != interfaceReturnContinue */
304 {
305 stop=plintr->Run();
306 switch (stop)
307 {
308 case interfaceReturnContinue: /* 0 */
309 case interfaceReturnQuit:
310 break;
311 case interfaceReturnNextAuto: /* next playlist file (auto) */
312 if (callselector (&nextinfo, &nextf, DoAutoCallFS, DoNotForceCallFS, DoNotForceNext, &nextintr)==0)
313 {
314 if (fsFilesLeft())
315 {
316 callselector (&nextinfo, &nextf, DoNotAutoCallFS, DoNotForceCallFS, DoForceNext, &nextintr);
317 stop = interfaceReturnNextAuto;
318 } else
319 stop = interfaceReturnQuit;
320 } else
321 stop = interfaceReturnNextAuto;
322 break;
323 case interfaceReturnPrevManuel: /* prev playlist file (man) */
324 if (fsFilesLeft())
325 stop=callselector (&nextinfo, &nextf, DoNotAutoCallFS, DoNotForceCallFS, DoForcePrev, &nextintr)?interfaceReturnNextAuto:interfaceReturnContinue;
326 else
327 stop=callselector (&nextinfo, &nextf, DoAutoCallFS, DoNotForceCallFS, DoNotForceNext, &nextintr)?interfaceReturnNextAuto:interfaceReturnContinue;
328 break;
329 case interfaceReturnNextManuel: /* next playlist file (man) */
330 if (fsFilesLeft())
331 stop=callselector (&nextinfo, &nextf, DoNotAutoCallFS, DoNotForceCallFS, DoForceNext, &nextintr)?interfaceReturnNextAuto:interfaceReturnContinue;
332 else
333 stop=callselector (&nextinfo, &nextf, DoAutoCallFS, DoNotForceCallFS, DoNotForceNext, &nextintr)?interfaceReturnNextAuto:interfaceReturnContinue;
334 break;
335 case interfaceReturnCallFs: /* call fs */
336 stop=callselector (&nextinfo, &nextf, DoAutoCallFS, DoForceCallFS, DoNotForceNext, &nextintr)?interfaceReturnNextAuto:interfaceReturnContinue;
337 break;
338 case interfaceReturnDosShell: /* dos shell */
339 plSetTextMode(fsScrType);
340 if (conRestore())
341 break;
342 stop=interfaceReturnContinue;
343 plDosShell();
344 conSave();
345 /*
346 while (ekbhit())
347 egetch();*/
348 break;
349 }
350 }
351 firstfile=0;
352 }
353 }
354
355 plSetTextMode(fsScrType);
356 conRestore();
357 if (plintr)
358 plintr->Close();
359 if (thisf)
360 {
361 thisf->unref (thisf);
362 thisf = NULL;
363 }
364
365 return errOk;
366 }
367
fspreint(void)368 static int fspreint(void)
369 {
370 mdbRegisterReadInfo(&fsReadInfoReg);
371
372 fprintf(stderr, "initializing fileselector...\n");
373 if (!fsPreInit())
374 {
375 fprintf(stderr, "fileselector pre-init failed!\n");
376 return errGen;
377 }
378
379 return errOk;
380 }
381
fsint(void)382 static int fsint(void)
383 {
384 if (!fsInit())
385 {
386 fprintf(stderr, "fileselector init failed!\n");
387 return errGen;
388 }
389
390 return errOk;
391 }
392
fslateint(void)393 static int fslateint(void)
394 {
395 if (!fsLateInit())
396 {
397 fprintf(stderr, "fileselector post-init failed!\n");
398 return errGen;
399 }
400
401 return errOk;
402 }
403
fsclose()404 static void fsclose()
405 {
406 mdbUnregisterReadInfo(&fsReadInfoReg);
407
408 fsClose();
409 }
410
411 static struct mainstruct fsmain = { _fsMain };
412
init(void)413 static void __attribute__((constructor))init(void)
414 {
415 if (ocpmain)
416 fprintf(stderr, "pfsmain.c: ocpmain != NULL\n");
417 else
418 ocpmain = &fsmain;
419 }
420
done(void)421 static void __attribute__((destructor))done(void)
422 {
423 if (ocpmain!=&fsmain)
424 ocpmain = 0;
425 }
426
427 #ifndef SUPPORT_STATIC_PLUGINS
428 char *dllinfo = "";
429 #endif
430
431 DLLEXTINFO_PREFIX struct linkinfostruct dllextinfo = {.name = "pfilesel", .desc = "OpenCP Fileselector (c) 1994-'21 Niklas Beisert, Tammo Hinrichs, Stian Skjelstad", .ver = DLLVERSION, .size = 0, .PreInit = fspreint, .Init = fsint, .LateInit = fslateint, .LateClose = fsclose};
432