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