A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita
audio
rust
zig
deno
mpris
rockbox
mpd
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2005 Karl Kurbjun based on midi2wav by Stepan Moskovchenko
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21#include "plugin.h"
22#include "guspat.h"
23#include "midiutil.h"
24#include "synth.h"
25#include "sequencer.h"
26#include "midifile.h"
27
28
29/* variable button definitions */
30#if (CONFIG_KEYPAD == IRIVER_H100_PAD) || (CONFIG_KEYPAD == IRIVER_H300_PAD)
31#define MIDI_QUIT BUTTON_OFF
32#define MIDI_FFWD BUTTON_RIGHT
33#define MIDI_VOL_UP BUTTON_UP
34#define MIDI_VOL_DOWN BUTTON_DOWN
35#define MIDI_REWIND BUTTON_LEFT
36#define MIDI_RC_QUIT BUTTON_RC_STOP
37#define MIDI_PLAYPAUSE BUTTON_ON
38
39#elif (CONFIG_KEYPAD == IPOD_4G_PAD) || (CONFIG_KEYPAD == IPOD_3G_PAD) || \
40 (CONFIG_KEYPAD == IPOD_1G2G_PAD)
41#define MIDI_QUIT (BUTTON_SELECT | BUTTON_MENU)
42#define MIDI_FFWD BUTTON_RIGHT
43#define MIDI_REWIND BUTTON_LEFT
44#define MIDI_VOL_UP BUTTON_SCROLL_FWD
45#define MIDI_VOL_DOWN BUTTON_SCROLL_BACK
46#define MIDI_PLAYPAUSE BUTTON_PLAY
47
48
49#elif (CONFIG_KEYPAD == GIGABEAT_PAD)
50#define MIDI_QUIT BUTTON_POWER
51#define MIDI_FFWD BUTTON_RIGHT
52#define MIDI_REWIND BUTTON_LEFT
53#define MIDI_VOL_UP BUTTON_UP
54#define MIDI_VOL_DOWN BUTTON_DOWN
55#define MIDI_PLAYPAUSE BUTTON_A
56
57
58#elif (CONFIG_KEYPAD == GIGABEAT_S_PAD)
59#define MIDI_QUIT BUTTON_POWER
60#define MIDI_FFWD BUTTON_RIGHT
61#define MIDI_REWIND BUTTON_LEFT
62#define MIDI_VOL_UP BUTTON_UP
63#define MIDI_VOL_DOWN BUTTON_DOWN
64#define MIDI_PLAYPAUSE BUTTON_PLAY
65
66
67#elif (CONFIG_KEYPAD == SANSA_E200_PAD)
68#define MIDI_QUIT BUTTON_POWER
69#define MIDI_FFWD BUTTON_RIGHT
70#define MIDI_REWIND BUTTON_LEFT
71#define MIDI_VOL_UP BUTTON_SCROLL_FWD
72#define MIDI_VOL_DOWN BUTTON_SCROLL_BACK
73#define MIDI_PLAYPAUSE BUTTON_UP
74
75#elif (CONFIG_KEYPAD == SANSA_FUZE_PAD)
76#define MIDI_QUIT (BUTTON_HOME|BUTTON_REPEAT)
77#define MIDI_FFWD BUTTON_RIGHT
78#define MIDI_REWIND BUTTON_LEFT
79#define MIDI_VOL_UP BUTTON_SCROLL_FWD
80#define MIDI_VOL_DOWN BUTTON_SCROLL_BACK
81#define MIDI_PLAYPAUSE BUTTON_UP
82
83
84#elif (CONFIG_KEYPAD == SANSA_C200_PAD) || \
85(CONFIG_KEYPAD == SANSA_CLIP_PAD) || \
86(CONFIG_KEYPAD == SANSA_M200_PAD)
87#define MIDI_QUIT BUTTON_POWER
88#define MIDI_FFWD BUTTON_RIGHT
89#define MIDI_REWIND BUTTON_LEFT
90#define MIDI_VOL_UP BUTTON_VOL_UP
91#define MIDI_VOL_DOWN BUTTON_VOL_DOWN
92#define MIDI_PLAYPAUSE BUTTON_UP
93
94
95#elif CONFIG_KEYPAD == IAUDIO_X5M5_PAD
96#define MIDI_QUIT BUTTON_POWER
97#define MIDI_FFWD BUTTON_RIGHT
98#define MIDI_REWIND BUTTON_LEFT
99#define MIDI_VOL_UP BUTTON_UP
100#define MIDI_VOL_DOWN BUTTON_DOWN
101#define MIDI_PLAYPAUSE BUTTON_PLAY
102
103
104#elif CONFIG_KEYPAD == IRIVER_H10_PAD
105#define MIDI_QUIT BUTTON_POWER
106#define MIDI_FFWD BUTTON_RIGHT
107#define MIDI_REWIND BUTTON_LEFT
108#define MIDI_VOL_UP BUTTON_SCROLL_UP
109#define MIDI_VOL_DOWN BUTTON_SCROLL_DOWN
110#define MIDI_PLAYPAUSE BUTTON_PLAY
111
112
113#elif CONFIG_KEYPAD == MROBE500_PAD
114#define MIDI_QUIT BUTTON_POWER
115#define MIDI_FFWD BUTTON_RIGHT
116#define MIDI_REWIND BUTTON_LEFT
117#define MIDI_VOL_UP BUTTON_RC_PLAY
118#define MIDI_VOL_DOWN BUTTON_RC_DOWN
119#define MIDI_PLAYPAUSE BUTTON_RC_HEART
120
121
122#elif (CONFIG_KEYPAD == MROBE100_PAD)
123#define MIDI_QUIT BUTTON_POWER
124#define MIDI_FFWD BUTTON_RIGHT
125#define MIDI_REWIND BUTTON_LEFT
126#define MIDI_VOL_UP BUTTON_UP
127#define MIDI_VOL_DOWN BUTTON_DOWN
128#define MIDI_PLAYPAUSE BUTTON_DISPLAY
129
130
131#elif CONFIG_KEYPAD == IAUDIO_M3_PAD
132#define MIDI_QUIT BUTTON_RC_REC
133#define MIDI_FFWD BUTTON_RC_FF
134#define MIDI_REWIND BUTTON_RC_REW
135#define MIDI_VOL_UP BUTTON_RC_VOL_UP
136#define MIDI_VOL_DOWN BUTTON_RC_VOL_DOWN
137#define MIDI_PLAYPAUSE BUTTON_RC_PLAY
138
139
140#elif CONFIG_KEYPAD == COWON_D2_PAD
141#define MIDI_QUIT BUTTON_POWER
142
143#elif CONFIG_KEYPAD == CREATIVEZVM_PAD
144#define MIDI_QUIT BUTTON_BACK
145#define MIDI_FFWD BUTTON_RIGHT
146#define MIDI_REWIND BUTTON_LEFT
147#define MIDI_VOL_UP BUTTON_UP
148#define MIDI_VOL_DOWN BUTTON_DOWN
149#define MIDI_PLAYPAUSE BUTTON_PLAY
150
151#elif CONFIG_KEYPAD == CREATIVE_ZENXFI3_PAD
152#define MIDI_QUIT (BUTTON_PLAY|BUTTON_REPEAT)
153#define MIDI_FFWD BUTTON_MENU
154#define MIDI_REWIND BUTTON_BACK
155#define MIDI_VOL_UP BUTTON_VOL_UP
156#define MIDI_VOL_DOWN BUTTON_VOL_DOWN
157#define MIDI_PLAYPAUSE (BUTTON_PLAY|BUTTON_REL)
158
159#elif CONFIG_KEYPAD == PHILIPS_HDD1630_PAD
160#define MIDI_QUIT BUTTON_POWER
161#define MIDI_FFWD BUTTON_RIGHT
162#define MIDI_REWIND BUTTON_LEFT
163#define MIDI_VOL_UP BUTTON_UP
164#define MIDI_VOL_DOWN BUTTON_DOWN
165#define MIDI_PLAYPAUSE BUTTON_MENU
166
167#elif CONFIG_KEYPAD == PHILIPS_HDD6330_PAD
168#define MIDI_QUIT BUTTON_POWER
169#define MIDI_FFWD BUTTON_RIGHT
170#define MIDI_REWIND BUTTON_LEFT
171#define MIDI_VOL_UP BUTTON_UP
172#define MIDI_VOL_DOWN BUTTON_DOWN
173#define MIDI_PLAYPAUSE BUTTON_MENU
174
175#elif CONFIG_KEYPAD == PHILIPS_SA9200_PAD
176#define MIDI_QUIT BUTTON_POWER
177#define MIDI_FFWD BUTTON_NEXT
178#define MIDI_REWIND BUTTON_PREV
179#define MIDI_VOL_UP BUTTON_UP
180#define MIDI_VOL_DOWN BUTTON_DOWN
181#define MIDI_PLAYPAUSE BUTTON_MENU
182
183#elif CONFIG_KEYPAD == ONDAVX747_PAD
184#define MIDI_QUIT BUTTON_POWER
185#elif CONFIG_KEYPAD == ONDAVX777_PAD
186#define MIDI_QUIT BUTTON_POWER
187
188#elif (CONFIG_KEYPAD == SAMSUNG_YH820_PAD) || \
189 (CONFIG_KEYPAD == SAMSUNG_YH92X_PAD)
190#define MIDI_QUIT (BUTTON_PLAY|BUTTON_REPEAT)
191#define MIDI_FFWD BUTTON_RIGHT
192#define MIDI_REWIND BUTTON_LEFT
193#define MIDI_VOL_UP BUTTON_UP
194#define MIDI_VOL_DOWN BUTTON_DOWN
195#define MIDI_PLAYPAUSE BUTTON_PLAY
196
197#elif CONFIG_KEYPAD == PBELL_VIBE500_PAD
198#define MIDI_QUIT BUTTON_REC
199#define MIDI_FFWD BUTTON_NEXT
200#define MIDI_REWIND BUTTON_PREV
201#define MIDI_VOL_UP BUTTON_UP
202#define MIDI_VOL_DOWN BUTTON_DOWN
203#define MIDI_PLAYPAUSE BUTTON_PLAY
204
205#elif CONFIG_KEYPAD == MPIO_HD200_PAD
206#define MIDI_QUIT (BUTTON_REC | BUTTON_PLAY)
207#define MIDI_FFWD BUTTON_FF
208#define MIDI_REWIND BUTTON_REW
209#define MIDI_VOL_UP BUTTON_VOL_UP
210#define MIDI_VOL_DOWN BUTTON_VOL_DOWN
211#define MIDI_PLAYPAUSE BUTTON_PLAY
212
213#elif CONFIG_KEYPAD == MPIO_HD300_PAD
214#define MIDI_QUIT (BUTTON_MENU | BUTTON_REPEAT)
215#define MIDI_FFWD BUTTON_FF
216#define MIDI_REWIND BUTTON_REW
217#define MIDI_VOL_UP BUTTON_UP
218#define MIDI_VOL_DOWN BUTTON_DOWN
219#define MIDI_PLAYPAUSE BUTTON_PLAY
220
221#elif CONFIG_KEYPAD == SANSA_FUZEPLUS_PAD
222#define MIDI_QUIT BUTTON_POWER
223#define MIDI_FFWD BUTTON_RIGHT
224#define MIDI_REWIND BUTTON_LEFT
225#define MIDI_VOL_UP BUTTON_UP
226#define MIDI_VOL_DOWN BUTTON_DOWN
227#define MIDI_PLAYPAUSE BUTTON_PLAYPAUSE
228
229#elif CONFIG_KEYPAD == SANSA_CONNECT_PAD
230#define MIDI_QUIT BUTTON_POWER
231#define MIDI_FFWD BUTTON_RIGHT
232#define MIDI_REWIND BUTTON_LEFT
233#define MIDI_VOL_UP BUTTON_UP
234#define MIDI_VOL_DOWN BUTTON_DOWN
235#define MIDI_PLAYPAUSE BUTTON_SELECT
236
237#elif CONFIG_KEYPAD == SAMSUNG_YPR0_PAD
238#define MIDI_QUIT BUTTON_BACK
239#define MIDI_FFWD BUTTON_RIGHT
240#define MIDI_REWIND BUTTON_LEFT
241#define MIDI_VOL_UP BUTTON_UP
242#define MIDI_VOL_DOWN BUTTON_DOWN
243#define MIDI_PLAYPAUSE BUTTON_USER
244
245#elif (CONFIG_KEYPAD == HM60X_PAD) || \
246 (CONFIG_KEYPAD == HM801_PAD)
247#define MIDI_QUIT BUTTON_POWER
248#define MIDI_FFWD BUTTON_RIGHT
249#define MIDI_REWIND BUTTON_LEFT
250#define MIDI_VOL_UP BUTTON_UP
251#define MIDI_VOL_DOWN BUTTON_DOWN
252#define MIDI_PLAYPAUSE BUTTON_SELECT
253
254#elif (CONFIG_KEYPAD == SONY_NWZ_PAD)
255#define MIDI_QUIT BUTTON_BACK
256#define MIDI_FFWD BUTTON_RIGHT
257#define MIDI_REWIND BUTTON_LEFT
258#define MIDI_VOL_UP BUTTON_UP
259#define MIDI_VOL_DOWN BUTTON_DOWN
260#define MIDI_PLAYPAUSE BUTTON_PLAY
261
262#elif (CONFIG_KEYPAD == CREATIVE_ZEN_PAD)
263#define MIDI_QUIT BUTTON_BACK
264#define MIDI_FFWD BUTTON_RIGHT
265#define MIDI_REWIND BUTTON_LEFT
266#define MIDI_VOL_UP BUTTON_UP
267#define MIDI_VOL_DOWN BUTTON_DOWN
268#define MIDI_PLAYPAUSE BUTTON_PLAYPAUSE
269
270#elif CONFIG_KEYPAD == DX50_PAD
271#define MIDI_QUIT BUTTON_POWER
272#define MIDI_FFWD BUTTON_RIGHT
273#define MIDI_REWIND BUTTON_LEFT
274#define MIDI_VOL_UP BUTTON_VOL_UP
275#define MIDI_VOL_DOWN BUTTON_VOL_DOWN
276
277#elif CONFIG_KEYPAD == CREATIVE_ZENXFI2_PAD
278#define MIDI_QUIT BUTTON_POWER
279
280#elif CONFIG_KEYPAD == AGPTEK_ROCKER_PAD
281#define MIDI_QUIT BUTTON_POWER
282#define MIDI_FFWD BUTTON_RIGHT
283#define MIDI_REWIND BUTTON_LEFT
284#define MIDI_VOL_UP BUTTON_VOLUP
285#define MIDI_VOL_DOWN BUTTON_VOLDOWN
286#define MIDI_PLAYPAUSE BUTTON_SELECT
287
288#elif CONFIG_KEYPAD == XDUOO_X3_PAD || CONFIG_KEYPAD == XDUOO_X3II_PAD || CONFIG_KEYPAD == XDUOO_X20_PAD
289#define MIDI_QUIT BUTTON_POWER
290#define MIDI_FFWD BUTTON_NEXT
291#define MIDI_REWIND BUTTON_PREV
292#define MIDI_VOL_UP BUTTON_VOL_UP
293#define MIDI_VOL_DOWN BUTTON_VOL_DOWN
294#define MIDI_PLAYPAUSE BUTTON_PLAY
295
296#elif CONFIG_KEYPAD == FIIO_M3K_LINUX_PAD
297#define MIDI_QUIT BUTTON_POWER
298#define MIDI_FFWD BUTTON_NEXT
299#define MIDI_REWIND BUTTON_PREV
300#define MIDI_VOL_UP BUTTON_VOL_UP
301#define MIDI_VOL_DOWN BUTTON_VOL_DOWN
302#define MIDI_PLAYPAUSE BUTTON_PLAY
303
304#elif CONFIG_KEYPAD == IHIFI_770_PAD || CONFIG_KEYPAD == IHIFI_800_PAD
305#define MIDI_QUIT BUTTON_POWER
306#define MIDI_FFWD BUTTON_VOL_DOWN
307#define MIDI_REWIND BUTTON_HOME
308#define MIDI_VOL_UP BUTTON_PREV
309#define MIDI_VOL_DOWN BUTTON_NEXT
310#define MIDI_PLAYPAUSE BUTTON_PLAY
311
312#elif CONFIG_KEYPAD == EROSQ_PAD
313#define MIDI_QUIT BUTTON_POWER
314#define MIDI_FFWD BUTTON_NEXT
315#define MIDI_REWIND BUTTON_PREV
316#define MIDI_VOL_UP BUTTON_VOL_UP
317#define MIDI_VOL_DOWN BUTTON_VOL_DOWN
318#define MIDI_PLAYPAUSE BUTTON_PLAY
319
320#elif CONFIG_KEYPAD == FIIO_M3K_PAD
321#define MIDI_QUIT BUTTON_POWER
322#define MIDI_FFWD BUTTON_LEFT
323#define MIDI_REWIND BUTTON_RIGHT
324#define MIDI_VOL_UP BUTTON_VOL_UP
325#define MIDI_VOL_DOWN BUTTON_VOL_DOWN
326#define MIDI_PLAYPAUSE BUTTON_PLAY
327
328#elif CONFIG_KEYPAD == SHANLING_Q1_PAD
329/* use touchscreen */
330
331#elif CONFIG_KEYPAD == MA_PAD
332#define MIDI_QUIT BUTTON_BACK
333#define MIDI_FFWD BUTTON_RIGHT
334#define MIDI_REWIND BUTTON_LEFT
335#define MIDI_VOL_UP BUTTON_UP
336#define MIDI_VOL_DOWN BUTTON_DOWN
337#define MIDI_PLAYPAUSE BUTTON_PLAY
338
339#elif CONFIG_KEYPAD == RG_NANO_PAD
340#define MIDI_QUIT BUTTON_START
341#define MIDI_FFWD BUTTON_RIGHT
342#define MIDI_REWIND BUTTON_LEFT
343#define MIDI_VOL_UP BUTTON_UP
344#define MIDI_VOL_DOWN BUTTON_DOWN
345#define MIDI_PLAYPAUSE BUTTON_A
346
347#else
348#error No keymap defined!
349#endif
350
351#ifdef HAVE_TOUCHSCREEN
352#ifndef MIDI_QUIT
353#define MIDI_QUIT BUTTON_TOPLEFT
354#endif
355#ifndef MIDI_FFWD
356#define MIDI_FFWD BUTTON_MIDRIGHT
357#endif
358#ifndef MIDI_REWIND
359#define MIDI_REWIND BUTTON_MIDLEFT
360#endif
361#ifndef MIDI_VOL_UP
362#define MIDI_VOL_UP BUTTON_TOPMIDDLE
363#endif
364#ifndef MIDI_VOL_DOWN
365#define MIDI_VOL_DOWN BUTTON_BOTTOMMIDDLE
366#endif
367#ifndef MIDI_PLAYPAUSE
368#define MIDI_PLAYPAUSE BUTTON_CENTER
369#endif
370#endif
371
372#undef SYNC
373
374#ifdef SIMULATOR
375#define SYNC
376#endif
377
378#ifndef ALIGNED_ATTR
379#define ALIGNED_ATTR(x) __attribute__((aligned(x)))
380#endif
381
382struct MIDIfile * mf IBSS_ATTR;
383
384int number_of_samples IBSS_ATTR; /* the number of samples in the current tick */
385int playing_time IBSS_ATTR; /* How many seconds into the file have we been playing? */
386int samples_this_second IBSS_ATTR; /* How many samples produced during this second so far? */
387long bpm IBSS_ATTR;
388
389#ifndef SYNC
390/* Small silence clip. ~5.80ms @ 44.1kHz */
391static int32_t silence[256] ALIGNED_ATTR(4) = { 0 };
392
393static int32_t gmbuf[BUF_SIZE * NBUF] ALIGNED_ATTR(4);
394
395static volatile bool swap = false;
396static volatile bool lastswap = true;
397#else
398static int32_t gmbuf[BUF_SIZE] ALIGNED_ATTR(4);
399#endif
400
401static volatile size_t samples_in_buf;
402
403static volatile bool midi_end = false;
404static volatile bool quit = false;
405
406static int32_t samp_buf[MAX_SAMPLES * 2] IBSS_ATTR;
407
408static struct dsp_config *dsp;
409static struct dsp_buffer src;
410static struct dsp_buffer dst;
411
412static inline void synthbuf(void)
413{
414 int32_t *outptr;
415 int available = BUF_SIZE;
416
417#ifndef SYNC
418 if (lastswap == swap)
419 return;
420
421 outptr = (swap ? gmbuf : gmbuf+BUF_SIZE);
422#else
423 outptr = gmbuf;
424#endif
425
426#if defined(HAVE_ADJUSTABLE_CPU_FREQ)
427 rb->cpu_boost(true);
428#endif
429 /* synth samples for as many whole ticks as we can fit in the buffer */
430 while (available > 0)
431 {
432 if ((dst.remcount <= 0) && !midi_end)
433 {
434 int nsamples = synthSamples(samp_buf, number_of_samples);
435 if (nsamples < number_of_samples)
436 number_of_samples -= nsamples;
437 else if (!tick())
438 midi_end = true; /* no more midi data to play */
439 src.remcount = nsamples;
440 src.pin[0] = &samp_buf[0];
441 src.pin[1] = &samp_buf[1];
442 src.proc_mask = 0;
443 }
444 dst.remcount = 0;
445 dst.bufcount = available;
446 dst.p16out = (int16_t *)outptr;
447 rb->dsp_process(dsp, &src, &dst, true);
448 if (dst.remcount > 0)
449 {
450 outptr += dst.remcount;
451 available -= dst.remcount;
452 }
453 else if (midi_end)
454 break;
455 }
456
457 /* how many samples did we write to the buffer? */
458 samples_in_buf = BUF_SIZE - available;
459#ifndef SYNC
460 lastswap = swap;
461#endif
462#if defined(HAVE_ADJUSTABLE_CPU_FREQ)
463 rb->cpu_boost(false);
464#endif
465}
466
467static void get_more(const void** start, size_t* size)
468{
469#ifndef SYNC
470 swap = !swap;
471 if(lastswap == swap)
472 {
473 *start = silence;
474 *size = sizeof(silence);
475 swap = !swap;
476 return;
477 }
478 else if (samples_in_buf)
479 *start = swap ? (gmbuf + BUF_SIZE) : gmbuf;
480#else
481 synthbuf(); /* For some reason midiplayer crashes when an update is forced */
482 if (samples_in_buf)
483 *start = gmbuf;
484#endif
485 else
486 {
487 *start = NULL;
488 quit = true; /* this was the last buffer to play */
489 }
490 *size = samples_in_buf*sizeof(int32_t);
491}
492
493static int midimain(const void * filename)
494{
495 int a, notes_used, vol;
496 bool is_playing = true; /* false = paused */
497
498#if defined(HAVE_ADJUSTABLE_CPU_FREQ)
499 rb->cpu_boost(true);
500#endif
501 midi_debug("Loading file");
502 mf = loadFile(filename);
503
504 if (mf == NULL)
505 {
506 midi_debug("Error loading file.");
507#if defined(HAVE_ADJUSTABLE_CPU_FREQ)
508 rb->cpu_boost(false);
509#endif
510 return -1;
511 }
512
513 if (initSynth(mf, ROCKBOX_DIR "/patchset/patchset.cfg",
514 ROCKBOX_DIR "/patchset/drums.cfg") == -1)
515 {
516#if defined(HAVE_ADJUSTABLE_CPU_FREQ)
517 rb->cpu_boost(false);
518#endif
519 return -1;
520 }
521
522 rb->talk_force_shutup();
523 rb->pcm_play_stop();
524#if INPUT_SRC_CAPS != 0
525 /* Select playback */
526 rb->audio_set_input_source(AUDIO_SRC_PLAYBACK, SRCF_PLAYBACK);
527 rb->audio_set_output_source(AUDIO_SRC_PLAYBACK);
528#endif
529
530 dst.remcount = 0;
531 dsp = rb->dsp_get_config(CODEC_IDX_AUDIO);
532 rb->dsp_configure(dsp, DSP_RESET, 0);
533 rb->dsp_configure(dsp, DSP_FLUSH, 0);
534 rb->dsp_configure(dsp, DSP_SET_OUT_FREQUENCY, rb->mixer_get_frequency());
535#ifdef HAVE_PITCHCONTROL
536 rb->sound_set_pitch(PITCH_SPEED_100);
537 rb->dsp_set_timestretch(PITCH_SPEED_100);
538#endif
539 rb->dsp_configure(dsp, DSP_SET_SAMPLE_DEPTH, 22);
540 rb->dsp_configure(dsp, DSP_SET_FREQUENCY, SAMPLE_RATE); /* 44100 22050 11025 */
541 rb->dsp_configure(dsp, DSP_SET_STEREO_MODE, STEREO_INTERLEAVED);
542
543 /*
544 * tick() will do one MIDI clock tick. Then, there's a loop here that
545 * will generate the right number of samples per MIDI tick. The whole
546 * MIDI playback is timed in terms of this value.. there are no forced
547 * delays or anything. It just produces enough samples for each tick, and
548 * the playback of these samples is what makes the timings right.
549 *
550 * This seems to work quite well. On a laptop, anyway.
551 */
552
553 midi_debug("Okay, starting sequencing");
554
555 bpm = mf->div*1000000/tempo;
556 number_of_samples = SAMPLE_RATE/bpm;
557
558 /* Skip over any junk in the beginning of the file, so start playing */
559 /* after the first note event */
560 do
561 {
562 notes_used = 0;
563 for (a = 0; a < MAX_VOICES; a++)
564 if (voices[a].isUsed)
565 notes_used++;
566 tick();
567 } while (notes_used == 0);
568
569#if defined(HAVE_ADJUSTABLE_CPU_FREQ)
570 rb->cpu_boost(false);
571#endif
572
573 playing_time = 0;
574 samples_this_second = 0;
575
576#ifndef SYNC
577 synthbuf();
578#endif
579
580 rb->pcmbuf_fade(false, true);
581 rb->mixer_channel_play_data(PCM_MIXER_CHAN_PLAYBACK, get_more, NULL, 0);
582
583 while (!quit)
584 {
585 #ifndef SYNC
586 synthbuf();
587 #endif
588 rb->yield();
589
590 /* Prevent idle poweroff */
591 rb->reset_poweroff_timer();
592
593 /* Code taken from Oscilloscope plugin */
594 switch (rb->button_get(false))
595 {
596 case MIDI_VOL_UP:
597 case MIDI_VOL_UP | BUTTON_REPEAT:
598 {
599 vol = rb->global_status->volume;
600 if (vol < rb->sound_max(SOUND_VOLUME))
601 {
602 vol++;
603 rb->sound_set(SOUND_VOLUME, vol);
604 }
605 break;
606 }
607
608 case MIDI_VOL_DOWN:
609 case MIDI_VOL_DOWN | BUTTON_REPEAT:
610 {
611 vol = rb->global_status->volume;
612 if (vol > rb->sound_min(SOUND_VOLUME))
613 {
614 vol--;
615 rb->sound_set(SOUND_VOLUME, vol);
616 }
617 break;
618 }
619
620 case MIDI_REWIND:
621 {
622 /* Rewinding is tricky. Basically start the file over */
623 /* but run through the tracks without the synth running */
624 rb->mixer_channel_stop(PCM_MIXER_CHAN_PLAYBACK);
625 rb->dsp_configure(dsp, DSP_FLUSH, 0);
626 dst.remcount = 0;
627#if defined(HAVE_ADJUSTABLE_CPU_FREQ)
628 rb->cpu_boost(true);
629#endif
630 seekBackward(5);
631#if defined(HAVE_ADJUSTABLE_CPU_FREQ)
632 rb->cpu_boost(false);
633#endif
634#ifndef SYNC
635 lastswap = !swap;
636 synthbuf();
637#endif
638 midi_debug("Rewind to %d:%02d\n", playing_time/60, playing_time%60);
639 if (is_playing)
640 rb->mixer_channel_play_data(PCM_MIXER_CHAN_PLAYBACK, get_more, NULL, 0);
641 break;
642 }
643
644 case MIDI_FFWD:
645 {
646 rb->mixer_channel_stop(PCM_MIXER_CHAN_PLAYBACK);
647 rb->dsp_configure(dsp, DSP_FLUSH, 0);
648 dst.remcount = 0;
649#if defined(HAVE_ADJUSTABLE_CPU_FREQ)
650 rb->cpu_boost(true);
651#endif
652 seekForward(5);
653#if defined(HAVE_ADJUSTABLE_CPU_FREQ)
654 rb->cpu_boost(false);
655#endif
656#ifndef SYNC
657 lastswap = !swap;
658 synthbuf();
659#endif
660 midi_debug("Skip to %d:%02d\n", playing_time/60, playing_time%60);
661 if (is_playing)
662 rb->mixer_channel_play_data(PCM_MIXER_CHAN_PLAYBACK, get_more, NULL, 0);
663 break;
664 }
665
666 case MIDI_PLAYPAUSE:
667 {
668 is_playing = !is_playing;
669 midi_debug("%s %d:%02d\n",
670 is_playing ? "Playing from" : "Paused at",
671 playing_time/60, playing_time%60);
672 rb->mixer_channel_play_pause(PCM_MIXER_CHAN_PLAYBACK, is_playing);
673 break;
674 }
675
676#ifdef MIDI_RC_QUIT
677 case MIDI_RC_QUIT:
678#endif
679 case MIDI_QUIT:
680 quit = true;
681 }
682 }
683
684 rb->pcmbuf_fade(false, false);
685 rb->mixer_channel_stop(PCM_MIXER_CHAN_PLAYBACK);
686
687 return 0;
688}
689
690enum plugin_status plugin_start(const void* parameter)
691{
692 int retval;
693
694 if (parameter == NULL)
695 {
696 rb->splash(HZ*2, " Play .MID file ");
697 return PLUGIN_OK;
698 }
699 rb->lcd_setfont(FONT_SYSFIXED);
700
701 midi_debug("%s", parameter);
702 /* rb->splash(HZ, true, parameter); */
703
704#ifdef RB_PROFILE
705 rb->profile_thread();
706#endif
707
708 retval = midimain(parameter);
709
710#ifdef RB_PROFILE
711 rb->profstop();
712#endif
713
714 rb->splash(HZ, "FINISHED PLAYING");
715
716 if (retval == -1)
717 return PLUGIN_ERROR;
718 return PLUGIN_OK;
719}