1 /* OpenCP Module Player
2 * copyright (c) '07-'10 Stian Skjelstad <stian@nixia.no>
3 *
4 * FLACPlay interface routines
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21 #include "config.h"
22 #include <string.h>
23 #include "types.h"
24 #include "boot/plinkman.h"
25 #include "boot/psetting.h"
26 #include "cpiface/cpiface.h"
27 #include "dev/deviplay.h"
28 #include "dev/player.h"
29 #include "filesel/pfilesel.h"
30 #include "filesel/mdb.h"
31 #include "flacplay.h"
32 #include "stuff/compat.h"
33 #include "stuff/err.h"
34 #include "stuff/poutput.h"
35 #include "stuff/sets.h"
36
37 #define _MAX_FNAME 8
38 #define _MAX_EXT 4
39
40 static uint32_t flaclen;
41 static uint32_t flacrate;
42 static time_t starttime;
43 static time_t pausetime;
44 static char currentmodname[_MAX_FNAME+1];
45 static char currentmodext[_MAX_EXT+1];
46 static char *modname;
47 static char *composer;
48 static int16_t vol;
49 static int16_t bal;
50 static int16_t pan;
51 static char srnd;
52
53 static uint32_t amp;
54 static int16_t speed;
55 static int16_t reverb;
56 static int16_t chorus;
57 static char finespeed=8;
58
59 static time_t pausefadestart;
60 static uint8_t pausefaderelspeed;
61 static int8_t pausefadedirect;
62
startpausefade(void)63 static void startpausefade(void)
64 {
65 if (plPause)
66 starttime=starttime+dos_clock()-pausetime;
67
68 if (pausefadedirect)
69 {
70 if (pausefadedirect<0)
71 plPause=1;
72 pausefadestart=2*dos_clock()-DOS_CLK_TCK-pausefadestart;
73 } else
74 pausefadestart=dos_clock();
75
76 if (plPause)
77 {
78 plChanChanged=1;
79 flacPause(plPause=0);
80 pausefadedirect=1;
81 } else
82 pausefadedirect=-1;
83 }
84
dopausefade(void)85 static void dopausefade(void)
86 {
87 int16_t i;
88 if (pausefadedirect>0)
89 {
90 i=((int32_t)dos_clock()-pausefadestart)*64/DOS_CLK_TCK;
91 if (i<0)
92 i=0;
93 if (i>=64)
94 {
95 i=64;
96 pausefadedirect=0;
97 }
98 } else {
99 i=64-((int32_t)dos_clock()-pausefadestart)*64/DOS_CLK_TCK;
100 if (i>=64)
101 i=64;
102 if (i<=0)
103 {
104 i=0;
105 pausefadedirect=0;
106 pausetime=dos_clock();
107 flacPause(plPause=1);
108 plChanChanged=1;
109 flacSetSpeed(speed);
110 return;
111 }
112 }
113 pausefaderelspeed=i;
114 flacSetSpeed(speed*i/64);
115 }
116
flacDrawGStrings(uint16_t (* buf)[CONSOLE_MAX_X])117 static void flacDrawGStrings(uint16_t (*buf)[CONSOLE_MAX_X])
118 {
119 struct flacinfo inf;
120 uint32_t tim, tim2;
121 int l;
122 int p;
123
124 flacGetInfo(&inf);
125
126 /*
127 tim=inf.len*8/(flac_Bitrate*1000);*/
128 tim=inf.timelen;
129 l=(inf.len>>(10/*-inf.stereo-inf.bit16*/)); /* these now refer to offset in file */
130 if (!l) l=1;
131 p=(inf.pos>>(10/*-inf.stereo-inf.bit16*/)); /* these now refer to offset in file */
132
133 if (plPause)
134 tim2=(pausetime-starttime)/DOS_CLK_TCK;
135 else
136 tim2=(dos_clock()-starttime)/DOS_CLK_TCK;
137
138 if (plScrWidth<128)
139 {
140 memset(buf[0]+80, 0, (plScrWidth-80)*sizeof(uint16_t));
141 memset(buf[1]+80, 0, (plScrWidth-80)*sizeof(uint16_t));
142 memset(buf[2]+80, 0, (plScrWidth-80)*sizeof(uint16_t));
143
144 writestring(buf[0], 0, 0x09, " vol: \xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa ", 15);
145 writestring(buf[0], 15, 0x09, " srnd: \xfa pan: l\xfa\xfa\xfam\xfa\xfa\xfar bal: l\xfa\xfa\xfam\xfa\xfa\xfar ", 41);
146 writestring(buf[0], 56, 0x09, " spd: ---% \x1D ptch: ---% ", 24);
147 writestring(buf[0], 6, 0x0F, "\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe", (vol+4)>>3);
148 writestring(buf[0], 22, 0x0F, srnd?"x":"o", 1);
149 if (((pan+70)>>4)==4)
150 writestring(buf[0], 34, 0x0F, "m", 1);
151 else {
152 writestring(buf[0], 30+((pan+70)>>4), 0x0F, "r", 1);
153 writestring(buf[0], 38-((pan+70)>>4), 0x0F, "l", 1);
154 }
155 writestring(buf[0], 46+((bal+70)>>4), 0x0F, "I", 1);
156 _writenum(buf[0], 62, 0x0F, speed*100/256, 10, 3);
157 _writenum(buf[0], 75, 0x0F, speed*100/256, 10, 3);
158
159 writestring(buf[1], 57, 0x09, "amp: ...% filter: ... ", 23);
160 _writenum(buf[1], 62, 0x0F, amp*100/64, 10, 3);
161 writestring(buf[1], 75, 0x0F, "off", 3);
162
163 writestring(buf[1], 0, 0x09, " pos: ...% / ......k size: ......k len: ..:..", 57);
164 _writenum(buf[1], 7, 0x0F, p*100/l, 10, 3);
165 writenum(buf[1], 43, 0x0F, (tim/60)%60, 10, 2, 1);
166 writestring(buf[1], 45, 0x0F, ":", 1);
167 writenum(buf[1], 46, 0x0F, tim%60, 10, 2, 0);
168 writenum(buf[1], 29, 0x0F, l, 10, 6, 1);
169 writenum(buf[1], 14, 0x0F, p, 10, 6, 1);
170
171 writestring(buf[2], 0, 0x09, " FLAC \xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa.\xfa\xfa\xfa: ............................... time: ..:.. ", 80);
172 writestring(buf[2], 8, 0x0F, currentmodname, _MAX_FNAME);
173 writestring(buf[2], 16, 0x0F, currentmodext, _MAX_EXT);
174 writestring(buf[2], 22, 0x0F, modname, 31);
175 if (plPause)
176 writestring(buf[2], 57, 0x0C, " paused ", 8);
177 else {
178 /*
179 writestring(buf[2], 57, 0x09, "kbps: ", 6);
180 writenum(buf[2], 63, 0x0F, inf.bitrate, 10, 3, 1); TODO */
181 writestring(buf[2], 57, 0x0C, " ", 6);
182 }
183 writenum(buf[2], 74, 0x0F, (tim2/60)%60, 10, 2, 1);
184 writestring(buf[2], 76, 0x0F, ":", 1);
185 writenum(buf[2], 77, 0x0F, tim2%60, 10, 2, 0);
186 } else {
187 memset(buf[0]+128, 0, (plScrWidth-128)*sizeof(uint16_t));
188 memset(buf[1]+128, 0, (plScrWidth-128)*sizeof(uint16_t));
189 memset(buf[2]+128, 0, (plScrWidth-128)*sizeof(uint16_t));
190
191 writestring(buf[0], 0, 0x09, " volume: \xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa ", 30);
192 writestring(buf[0], 30, 0x09, " surround: \xfa panning: l\xfa\xfa\xfa\xfa\xfa\xfa\xfam\xfa\xfa\xfa\xfa\xfa\xfa\xfar balance: l\xfa\xfa\xfa\xfa\xfa\xfa\xfam\xfa\xfa\xfa\xfa\xfa\xfa\xfar ", 72);
193 writestring(buf[0], 102, 0x09, " speed: ---% \x1D pitch: ---% ", 30);
194 writestring(buf[0], 12, 0x0F, "\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe", (vol+2)>>2);
195 writestring(buf[0], 41, 0x0F, srnd?"x":"o", 1);
196 if (((pan+68)>>3)==8)
197 writestring(buf[0], 62, 0x0F, "m", 1);
198 else {
199 writestring(buf[0], 54+((pan+68)>>3), 0x0F, "r", 1);
200 writestring(buf[0], 70-((pan+68)>>3), 0x0F, "l", 1);
201 }
202 writestring(buf[0], 83+((bal+68)>>3), 0x0F, "I", 1);
203 _writenum(buf[0], 110, 0x0F, speed*100/256, 10, 3);
204 _writenum(buf[0], 124, 0x0F, speed*100/256, 10, 3);
205
206 writestring(buf[1], 0, 0x09, " position: ...% / ......k size: ......k length: ..:.. opt: .....Hz, .. bit, ......", 92);
207 _writenum(buf[1], 14, 0x0F, p*100/l, 10, 3);
208 writenum(buf[1], 53, 0x0F, (tim/60)%60, 10, 2, 1);
209 writestring(buf[1], 55, 0x0F, ":", 1);
210 writenum(buf[1], 56, 0x0F, tim%60, 10, 2, 0);
211 writenum(buf[1], 36, 0x0F, l, 10, 6, 1);
212 writenum(buf[1], 21, 0x0F, p, 10, 6, 1);
213 writenum(buf[1], 65, 0x0F, inf.rate, 10, 5, 1);
214 writenum(buf[1], 74, 0x0F, inf.bits, 10, 2, 1);
215 writestring(buf[1], 82, 0x0F, inf.stereo?"stereo":"mono", 6);
216
217 writestring(buf[1], 92, 0x09, " amplification: ...% filter: ... ", 40);
218 _writenum(buf[1], 110, 0x0F, amp*100/64, 10, 3);
219 writestring(buf[1], 124, 0x0F, "off", 3);
220
221
222 if (plPause)
223 tim2=(pausetime-starttime)/DOS_CLK_TCK;
224 else
225 tim2=(dos_clock()-starttime)/DOS_CLK_TCK;
226
227 writestring(buf[2], 0, 0x09, " FLAC \xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa.\xfa\xfa\xfa: ............................... composer: ............................... time: ..:.. ", 132);
228 writestring(buf[2], 11, 0x0F, currentmodname, _MAX_FNAME);
229 writestring(buf[2], 19, 0x0F, currentmodext, _MAX_EXT);
230 writestring(buf[2], 25, 0x0F, modname, 31);
231 writestring(buf[2], 68, 0x0F, composer, 31);
232 if (plPause)
233 writestring(buf[2], 100, 0x0C, "playback paused", 15);
234 else {
235 /*
236 writestring(buf[2], 100, 0x09, "kbps: ", 6);
237 writenum(buf[2], 106, 0x0F, inf.bitrate, 10, 3, 1);*/
238 writestring(buf[2], 100, 0x0C, " ", 15);
239 }
240 writenum(buf[2], 123, 0x0F, (tim2/60)%60, 10, 2, 1);
241 writestring(buf[2], 125, 0x0F, ":", 1);
242 writenum(buf[2], 126, 0x0F, tim2%60, 10, 2, 0);
243 }
244 }
245
normalize(void)246 static void normalize(void)
247 {
248 mcpNormalize(0);
249 speed=set.speed;
250 pan=set.pan;
251 bal=set.bal;
252 vol=set.vol;
253 amp=set.amp;
254 srnd=set.srnd;
255 reverb=set.reverb;
256 chorus=set.chorus;
257 flacSetAmplify(1024*amp);
258 flacSetVolume(vol, bal, pan, srnd);
259 flacSetSpeed(speed);
260 /* flacSetMasterReverbChorus(reverb, chorus); */
261 }
262
flacProcessKey(uint16_t key)263 static int flacProcessKey(uint16_t key)
264 {
265 switch (key)
266 {
267 case KEY_ALT_K:
268 cpiKeyHelp('p', "Start/stop pause with fade");
269 cpiKeyHelp('P', "Start/stop pause with fade");
270 cpiKeyHelp(KEY_CTRL_P, "Start/stop pause");
271 cpiKeyHelp('<', "Jump back (big)");
272 cpiKeyHelp(KEY_CTRL_LEFT, "Jump back (big)");
273 cpiKeyHelp('>', "Jump forward (big)");
274 cpiKeyHelp(KEY_CTRL_RIGHT, "Jump forward (big)");
275 cpiKeyHelp(KEY_CTRL_UP, "Jump back (small)");
276 cpiKeyHelp(KEY_CTRL_DOWN, "Jump forward (small)");
277 cpiKeyHelp('-', "Decrease volume (small)");
278 cpiKeyHelp('+', "Increase volume (small)");
279 cpiKeyHelp('/', "Move balance left (small)");
280 cpiKeyHelp('*', "Move balance right (small)");
281 cpiKeyHelp(',', "Move panning against normal (small)");
282 cpiKeyHelp('.', "Move panning against reverse (small)");
283 cpiKeyHelp(KEY_F(2), "Decrease volume");
284 cpiKeyHelp(KEY_F(3), "Increase volume");
285 cpiKeyHelp(KEY_F(4), "Toggle surround on/off");
286 cpiKeyHelp(KEY_F(5), "Move panning against normal");
287 cpiKeyHelp(KEY_F(6), "Move panning against reverse");
288 cpiKeyHelp(KEY_F(7), "Move balance left");
289 cpiKeyHelp(KEY_F(8), "Move balance right");
290 cpiKeyHelp(KEY_F(9), "Decrease pitch speed");
291 cpiKeyHelp(KEY_F(11), "Decrease pitch speed");
292 cpiKeyHelp(KEY_F(10), "Increase pitch speed");
293 cpiKeyHelp(KEY_F(12), "Increase pitch speed");
294 if (plrProcessKey)
295 plrProcessKey(key);
296 return 0;
297 case 'p': case 'P':
298 startpausefade();
299 break;
300 case KEY_CTRL_P:
301 pausefadedirect=0;
302 if (plPause)
303 starttime=starttime+dos_clock()-pausetime;
304 else
305 pausetime=dos_clock();
306 plPause=!plPause;
307 flacPause(plPause);
308 break;
309 case KEY_CTRL_UP:
310 /* case 0x8D00: //ctrl-up */
311 flacSetPos(flacGetPos()-flacrate);
312 break;
313 case KEY_CTRL_DOWN:
314 /* case 0x9100: //ctrl-down */
315 flacSetPos(flacGetPos()+flacrate);
316 break;
317 case '<':
318 case KEY_CTRL_LEFT:
319 /* case 0x7300: //ctrl-left */
320 {
321 uint64_t oldpos = flacGetPos();
322 unsigned int skip=flaclen>>5;
323 if (skip<128*1024)
324 skip=128*1024;
325 if (oldpos<skip)
326 flacSetPos(0);
327 else
328 flacSetPos(oldpos-skip);
329 }
330 break;
331 case '>':
332 case KEY_CTRL_RIGHT:
333 /* case 0x7400: //ctrl-right */
334 {
335 int skip=flaclen>>5;
336 if (skip<128*1024)
337 skip=128*1024;
338 flacSetPos(flacGetPos()+skip);
339 }
340 break;
341 /*
342 case 0x7700: //ctrl-home TODO keys
343 flacSetPos(0);
344 break;
345 */
346 case '-':
347 if (vol>=2)
348 vol-=2;
349 flacSetVolume(vol, bal, pan, srnd);
350 break;
351 case '+':
352 if (vol<=62)
353 vol+=2;
354 flacSetVolume(vol, bal, pan, srnd);
355 break;
356 case '/':
357 if ((bal-=4)<-64)
358 bal=-64;
359 flacSetVolume(vol, bal, pan, srnd);
360 break;
361 case '*':
362 if ((bal+=4)>64)
363 bal=64;
364 flacSetVolume(vol, bal, pan, srnd);
365 break;
366 case ',':
367 if ((pan-=4)<-64)
368 pan=-64;
369 flacSetVolume(vol, bal, pan, srnd);
370 break;
371 case '.':
372 if ((pan+=4)>64)
373 pan=64;
374 flacSetVolume(vol, bal, pan, srnd);
375 break;
376 case KEY_F(2):
377 if ((vol-=8)<0)
378 vol=0;
379 flacSetVolume(vol, bal, pan, srnd);
380 break;
381 case KEY_F(3):
382 if ((vol+=8)>64)
383 vol=64;
384 flacSetVolume(vol, bal, pan, srnd);
385 break;
386 case KEY_F(4):
387 flacSetVolume(vol, bal, pan, srnd=srnd?0:2);
388 break;
389 case KEY_F(5):
390 if ((pan-=16)<-64)
391 pan=-64;
392 flacSetVolume(vol, bal, pan, srnd);
393 break;
394 case KEY_F(6):
395 if ((pan+=16)>64)
396 pan=64;
397 flacSetVolume(vol, bal, pan, srnd);
398 break;
399 case KEY_F(7):
400 if ((bal-=16)<-64)
401 bal=-64;
402 flacSetVolume(vol, bal, pan, srnd);
403 break;
404 case KEY_F(8):
405 if ((bal+=16)>64)
406 bal=64;
407 flacSetVolume(vol, bal, pan, srnd);
408 break;
409 case KEY_F(9):
410 case KEY_F(11):
411 if ((speed-=finespeed)<16)
412 speed=16;
413 flacSetSpeed(speed);
414 break;
415 case KEY_F(10):
416 case KEY_F(12):
417 if ((speed+=finespeed)>2048)
418 speed=2048;
419 flacSetSpeed(speed);
420 break;
421 /*
422 case 0x5f00: // ctrl f2 TODO keys
423 if ((amp-=4)<4)
424 amp=4;
425 flacSetAmplify(1024*amp);
426 break;
427 case 0x6000: // ctrl f3 TODO keys
428 if ((amp+=4)>508)
429 amp=508;
430 flacSetAmplify(1024*amp);
431 break;
432 case 0x8900: // ctrl f11 TODO keys
433 finespeed=(finespeed==8)?1:8;
434 break;
435 case 0x6a00: // alt-f3 TODO keys
436 normalize();
437 break;
438 case 0x6900: // alt-f2 TODO keys
439 set.pan=pan;
440 set.bal=bal;
441 set.vol=vol;
442 set.speed=speed;
443 set.amp=amp;
444 set.srnd=srnd;
445 break;
446 case 0x6b00: // alt-f4 TODO keys
447 pan=64;
448 bal=0;
449 vol=64;
450 speed=256;
451 amp=64;
452 flacSetVolume(vol, bal, pan, srnd);
453 flacSetSpeed(speed);
454 flacSetAmplify(1024*amp);
455 break;
456 */
457 default:
458 if (plrProcessKey)
459 {
460 int ret=plrProcessKey(key);
461 if (ret==2)
462 cpiResetScreen();
463 if (ret)
464 return 1;
465 }
466 return 0;
467 }
468 return 1;
469 }
470
471
flacLooped(void)472 static int flacLooped(void)
473 {
474 if (pausefadedirect)
475 dopausefade();
476 flacSetLoop(fsLoopMods);
477 flacIdle();
478 if (plrIdle)
479 plrIdle();
480 return !fsLoopMods&&flacIsLooped();
481 }
482
483
flacCloseFile(void)484 static void flacCloseFile(void)
485 {
486 flacClosePlayer();
487
488 FlacInfoDone ();
489 FlacPicDone ();
490 }
491
flacOpenFile(struct moduleinfostruct * info,struct ocpfilehandle_t * flacf)492 static int flacOpenFile (struct moduleinfostruct *info, struct ocpfilehandle_t *flacf)
493 {
494 struct flacinfo inf;
495
496 if (!flacf)
497 return -1;
498
499 strncpy(currentmodname, info->name, _MAX_FNAME);
500 strncpy(currentmodext, info->name + _MAX_FNAME, _MAX_EXT);
501
502 modname=info->modname;
503 composer=info->composer;
504
505 fprintf(stderr, "loading %s%s...\n", currentmodname, currentmodext);
506
507 plIsEnd=flacLooped;
508 plProcessKey=flacProcessKey;
509 plDrawGStrings=flacDrawGStrings;
510 plGetMasterSample=plrGetMasterSample;
511 plGetRealMasterVolume=plrGetRealMasterVolume;
512
513 if (!flacOpenPlayer(flacf))
514 return -1;
515
516 starttime=dos_clock();
517 plPause=0;
518 normalize();
519 pausefadedirect=0;
520
521
522 flacGetInfo(&inf);
523 flaclen=inf.len;
524 flacrate=inf.rate;
525
526 FlacInfoInit ();
527 FlacPicInit ();
528
529 return errOk;
530 }
531
532 struct cpifaceplayerstruct flacPlayer = {flacOpenFile, flacCloseFile};
533 struct linkinfostruct dllextinfo = {.name = "playflac", .desc = "OpenCP FLAC Player (c) 2007-09 Stian Skjelstad", .ver = DLLVERSION, .size = 0};
534