HD300 - plugins keymaps
[kugel-rb.git] / apps / plugins / midi / midiplay.c
blob9bf4d50822bfef678d2d3a2e0456da3d5d865bdc
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2005 Karl Kurbjun based on midi2wav by Stepan Moskovchenko
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.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
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"
29 /* variable button definitions */
30 #if (CONFIG_KEYPAD == IRIVER_H100_PAD) || (CONFIG_KEYPAD == IRIVER_H300_PAD)
31 #define BTN_QUIT BUTTON_OFF
32 #define BTN_RIGHT BUTTON_RIGHT
33 #define BTN_UP BUTTON_UP
34 #define BTN_DOWN BUTTON_DOWN
35 #define BTN_LEFT BUTTON_LEFT
36 #define BTN_RC_QUIT BUTTON_RC_STOP
37 #define BTN_PLAY BUTTON_ON
39 #elif (CONFIG_KEYPAD == IPOD_4G_PAD) || (CONFIG_KEYPAD == IPOD_3G_PAD) || \
40 (CONFIG_KEYPAD == IPOD_1G2G_PAD)
41 #define BTN_QUIT (BUTTON_SELECT | BUTTON_MENU)
42 #define BTN_RIGHT BUTTON_RIGHT
43 #define BTN_LEFT BUTTON_LEFT
44 #define BTN_UP BUTTON_SCROLL_FWD
45 #define BTN_DOWN BUTTON_SCROLL_BACK
46 #define BTN_PLAY BUTTON_PLAY
49 #elif (CONFIG_KEYPAD == GIGABEAT_PAD)
50 #define BTN_QUIT BUTTON_POWER
51 #define BTN_RIGHT BUTTON_RIGHT
52 #define BTN_LEFT BUTTON_LEFT
53 #define BTN_UP BUTTON_UP
54 #define BTN_DOWN BUTTON_DOWN
55 #define BTN_PLAY BUTTON_A
58 #elif (CONFIG_KEYPAD == GIGABEAT_S_PAD)
59 #define BTN_QUIT BUTTON_POWER
60 #define BTN_RIGHT BUTTON_RIGHT
61 #define BTN_LEFT BUTTON_LEFT
62 #define BTN_UP BUTTON_UP
63 #define BTN_DOWN BUTTON_DOWN
64 #define BTN_PLAY BUTTON_PLAY
67 #elif (CONFIG_KEYPAD == SANSA_E200_PAD)
68 #define BTN_QUIT BUTTON_POWER
69 #define BTN_RIGHT BUTTON_RIGHT
70 #define BTN_LEFT BUTTON_LEFT
71 #define BTN_UP BUTTON_SCROLL_FWD
72 #define BTN_DOWN BUTTON_SCROLL_BACK
73 #define BTN_PLAY BUTTON_UP
75 #elif (CONFIG_KEYPAD == SANSA_FUZE_PAD)
76 #define BTN_QUIT (BUTTON_HOME|BUTTON_REPEAT)
77 #define BTN_RIGHT BUTTON_RIGHT
78 #define BTN_LEFT BUTTON_LEFT
79 #define BTN_UP BUTTON_SCROLL_FWD
80 #define BTN_DOWN BUTTON_SCROLL_BACK
81 #define BTN_PLAY BUTTON_UP
84 #elif (CONFIG_KEYPAD == SANSA_C200_PAD) || \
85 (CONFIG_KEYPAD == SANSA_CLIP_PAD) || \
86 (CONFIG_KEYPAD == SANSA_M200_PAD)
87 #define BTN_QUIT BUTTON_POWER
88 #define BTN_RIGHT BUTTON_RIGHT
89 #define BTN_LEFT BUTTON_LEFT
90 #define BTN_UP BUTTON_VOL_UP
91 #define BTN_DOWN BUTTON_VOL_DOWN
92 #define BTN_PLAY BUTTON_UP
95 #elif CONFIG_KEYPAD == IAUDIO_X5M5_PAD
96 #define BTN_QUIT BUTTON_POWER
97 #define BTN_RIGHT BUTTON_RIGHT
98 #define BTN_LEFT BUTTON_LEFT
99 #define BTN_UP BUTTON_UP
100 #define BTN_DOWN BUTTON_DOWN
101 #define BTN_PLAY BUTTON_PLAY
104 #elif CONFIG_KEYPAD == IRIVER_H10_PAD
105 #define BTN_QUIT BUTTON_POWER
106 #define BTN_RIGHT BUTTON_RIGHT
107 #define BTN_LEFT BUTTON_LEFT
108 #define BTN_UP BUTTON_SCROLL_UP
109 #define BTN_DOWN BUTTON_SCROLL_DOWN
110 #define BTN_PLAY BUTTON_PLAY
113 #elif CONFIG_KEYPAD == MROBE500_PAD
114 #define BTN_QUIT BUTTON_POWER
115 #define BTN_RIGHT BUTTON_RIGHT
116 #define BTN_LEFT BUTTON_LEFT
117 #define BTN_UP BUTTON_RC_PLAY
118 #define BTN_DOWN BUTTON_RC_DOWN
119 #define BTN_PLAY BUTTON_RC_HEART
122 #elif (CONFIG_KEYPAD == MROBE100_PAD)
123 #define BTN_QUIT BUTTON_POWER
124 #define BTN_RIGHT BUTTON_RIGHT
125 #define BTN_LEFT BUTTON_LEFT
126 #define BTN_UP BUTTON_UP
127 #define BTN_DOWN BUTTON_DOWN
128 #define BTN_PLAY BUTTON_DISPLAY
131 #elif CONFIG_KEYPAD == IAUDIO_M3_PAD
132 #define BTN_QUIT BUTTON_RC_REC
133 #define BTN_RIGHT BUTTON_RC_FF
134 #define BTN_LEFT BUTTON_RC_REW
135 #define BTN_UP BUTTON_RC_VOL_UP
136 #define BTN_DOWN BUTTON_RC_VOL_DOWN
137 #define BTN_PLAY BUTTON_RC_PLAY
140 #elif CONFIG_KEYPAD == COWON_D2_PAD
141 #define BTN_QUIT BUTTON_POWER
143 #elif CONFIG_KEYPAD == IAUDIO67_PAD
144 #define BTN_QUIT BUTTON_POWER
145 #define BTN_RIGHT BUTTON_RIGHT
146 #define BTN_LEFT BUTTON_LEFT
147 #define BTN_UP BUTTON_STOP
148 #define BTN_DOWN BUTTON_PLAY
149 #define BTN_PLAY BUTTON_MENU
151 #elif CONFIG_KEYPAD == CREATIVEZVM_PAD
152 #define BTN_QUIT BUTTON_BACK
153 #define BTN_RIGHT BUTTON_RIGHT
154 #define BTN_LEFT BUTTON_LEFT
155 #define BTN_UP BUTTON_UP
156 #define BTN_DOWN BUTTON_DOWN
157 #define BTN_PLAY BUTTON_PLAY
159 #elif CONFIG_KEYPAD == PHILIPS_HDD1630_PAD
160 #define BTN_QUIT BUTTON_POWER
161 #define BTN_RIGHT BUTTON_RIGHT
162 #define BTN_LEFT BUTTON_LEFT
163 #define BTN_UP BUTTON_UP
164 #define BTN_DOWN BUTTON_DOWN
165 #define BTN_PLAY BUTTON_MENU
167 #elif CONFIG_KEYPAD == PHILIPS_HDD6330_PAD
168 #define BTN_QUIT BUTTON_POWER
169 #define BTN_RIGHT BUTTON_RIGHT
170 #define BTN_LEFT BUTTON_LEFT
171 #define BTN_UP BUTTON_UP
172 #define BTN_DOWN BUTTON_DOWN
173 #define BTN_PLAY BUTTON_MENU
175 #elif CONFIG_KEYPAD == PHILIPS_SA9200_PAD
176 #define BTN_QUIT BUTTON_POWER
177 #define BTN_RIGHT BUTTON_NEXT
178 #define BTN_LEFT BUTTON_PREV
179 #define BTN_UP BUTTON_UP
180 #define BTN_DOWN BUTTON_DOWN
181 #define BTN_PLAY BUTTON_MENU
183 #elif CONFIG_KEYPAD == ONDAVX747_PAD
184 #define BTN_QUIT BUTTON_POWER
185 #elif CONFIG_KEYPAD == ONDAVX777_PAD
186 #define BTN_QUIT BUTTON_POWER
188 #elif CONFIG_KEYPAD == SAMSUNG_YH_PAD
189 #define BTN_QUIT BUTTON_REW
190 #define BTN_RIGHT BUTTON_RIGHT
191 #define BTN_LEFT BUTTON_LEFT
192 #define BTN_UP BUTTON_UP
193 #define BTN_DOWN BUTTON_DOWN
194 #define BTN_PLAY BUTTON_PLAY
196 #elif CONFIG_KEYPAD == PBELL_VIBE500_PAD
197 #define BTN_QUIT BUTTON_REC
198 #define BTN_RIGHT BUTTON_NEXT
199 #define BTN_LEFT BUTTON_PREV
200 #define BTN_UP BUTTON_UP
201 #define BTN_DOWN BUTTON_DOWN
202 #define BTN_PLAY BUTTON_PLAY
204 #elif CONFIG_KEYPAD == MPIO_HD200_PAD
205 #define BTN_QUIT (BUTTON_REC | BUTTON_PLAY)
206 #define BTN_RIGHT BUTTON_VOL_DOWN
207 #define BTN_LEFT BUTTON_VOL_UP
208 #define BTN_UP BUTTON_REW
209 #define BTN_DOWN BUTTON_FF
210 #define BTN_PLAY BUTTON_PLAY
212 #elif CONFIG_KEYPAD == MPIO_HD300_PAD
213 #define BTN_QUIT (BUTTON_REC | BUTTON_REPEAT)
214 #define BTN_RIGHT BUTTON_FF
215 #define BTN_LEFT BUTTON_REW
216 #define BTN_UP BUTTON_UP
217 #define BTN_DOWN BUTTON_DOWN
218 #define BTN_PLAY BUTTON_PLAY
220 #else
221 #error No keymap defined!
222 #endif
224 #ifdef HAVE_TOUCHSCREEN
225 #ifndef BTN_QUIT
226 #define BTN_QUIT BUTTON_TOPLEFT
227 #endif
228 #ifndef BTN_RIGHT
229 #define BTN_RIGHT BUTTON_MIDRIGHT
230 #endif
231 #ifndef BTN_LEFT
232 #define BTN_LEFT BUTTON_MIDLEFT
233 #endif
234 #ifndef BTN_UP
235 #define BTN_UP BUTTON_TOPMIDDLE
236 #endif
237 #ifndef BTN_DOWN
238 #define BTN_DOWN BUTTON_BOTTOMMIDDLE
239 #endif
240 #ifndef BTN_PLAY
241 #define BTN_PLAY BUTTON_CENTER
242 #endif
243 #endif
245 #undef SYNC
247 #ifdef SIMULATOR
248 #define SYNC
249 #endif
251 struct MIDIfile * mf IBSS_ATTR;
253 int number_of_samples IBSS_ATTR; /* the number of samples in the current tick */
254 int playing_time IBSS_ATTR; /* How many seconds into the file have we been playing? */
255 int samples_this_second IBSS_ATTR; /* How many samples produced during this second so far? */
256 long bpm IBSS_ATTR;
258 int32_t gmbuf[BUF_SIZE*NBUF];
259 static unsigned int samples_in_buf;
261 bool quit = false;
262 bool swap = false;
263 bool lastswap = true;
265 static inline void synthbuf(void)
267 int32_t *outptr;
268 int i = BUF_SIZE;
270 #ifndef SYNC
271 if (lastswap == swap)
272 return;
273 lastswap = swap;
275 outptr = (swap ? gmbuf : gmbuf+BUF_SIZE);
276 #else
277 outptr = gmbuf;
278 #endif
280 /* synth samples for as many whole ticks as we can fit in the buffer */
281 for (; i >= number_of_samples; i -= number_of_samples)
283 synthSamples((int32_t*)outptr, number_of_samples);
284 outptr += number_of_samples;
285 #ifndef SYNC
286 /* synthbuf is called in interrupt context is SYNC is defined so it cannot yield
287 that bug causing the sim to crach when not using SYNC should really be fixed */
288 rb->yield();
289 #endif
290 if (tick() == 0)
291 quit = true;
294 /* how many samples did we write to the buffer? */
295 samples_in_buf = BUF_SIZE-i;
298 void get_more(unsigned char** start, size_t* size)
300 #ifndef SYNC
301 if(lastswap != swap)
303 midi_debug("Buffer miss!"); /* Comment out the midi_debug to make missses less noticable. */
306 #else
307 synthbuf(); /* For some reason midiplayer crashes when an update is forced */
308 #endif
310 *size = samples_in_buf*sizeof(int32_t);
311 #ifndef SYNC
312 *start = (unsigned char*)((swap ? gmbuf : gmbuf + BUF_SIZE));
313 swap = !swap;
314 #else
315 *start = (unsigned char*)(gmbuf);
316 #endif
319 static int midimain(const void * filename)
321 int a, notes_used, vol;
322 bool is_playing = true; /* false = paused */
324 midi_debug("Loading file");
325 mf = loadFile(filename);
327 if (mf == NULL)
329 midi_debug("Error loading file.");
330 return -1;
333 if (initSynth(mf, ROCKBOX_DIR "/patchset/patchset.cfg",
334 ROCKBOX_DIR "/patchset/drums.cfg") == -1)
335 return -1;
337 rb->pcm_play_stop();
338 #if INPUT_SRC_CAPS != 0
339 /* Select playback */
340 rb->audio_set_input_source(AUDIO_SRC_PLAYBACK, SRCF_PLAYBACK);
341 rb->audio_set_output_source(AUDIO_SRC_PLAYBACK);
342 #endif
343 rb->pcm_set_frequency(SAMPLE_RATE); /* 44100 22050 11025 */
346 * tick() will do one MIDI clock tick. Then, there's a loop here that
347 * will generate the right number of samples per MIDI tick. The whole
348 * MIDI playback is timed in terms of this value.. there are no forced
349 * delays or anything. It just produces enough samples for each tick, and
350 * the playback of these samples is what makes the timings right.
352 * This seems to work quite well. On a laptop, anyway.
355 midi_debug("Okay, starting sequencing");
357 bpm = mf->div*1000000/tempo;
358 number_of_samples = SAMPLE_RATE/bpm;
360 /* Skip over any junk in the beginning of the file, so start playing */
361 /* after the first note event */
364 notes_used = 0;
365 for (a = 0; a < MAX_VOICES; a++)
366 if (voices[a].isUsed)
367 notes_used++;
368 tick();
369 } while (notes_used == 0);
371 playing_time = 0;
372 samples_this_second = 0;
374 synthbuf();
375 rb->pcm_play_data(&get_more, NULL, 0);
377 while (!quit)
379 #ifndef SYNC
380 synthbuf();
381 #endif
382 rb->yield();
384 /* Prevent idle poweroff */
385 rb->reset_poweroff_timer();
387 /* Code taken from Oscilloscope plugin */
388 switch (rb->button_get(false))
390 case BTN_UP:
391 case BTN_UP | BUTTON_REPEAT:
393 vol = rb->global_settings->volume;
394 if (vol < rb->sound_max(SOUND_VOLUME))
396 vol++;
397 rb->sound_set(SOUND_VOLUME, vol);
398 rb->global_settings->volume = vol;
400 break;
403 case BTN_DOWN:
404 case BTN_DOWN | BUTTON_REPEAT:
406 vol = rb->global_settings->volume;
407 if (vol > rb->sound_min(SOUND_VOLUME))
409 vol--;
410 rb->sound_set(SOUND_VOLUME, vol);
411 rb->global_settings->volume = vol;
413 break;
416 case BTN_LEFT:
418 /* Rewinding is tricky. Basically start the file over */
419 /* but run through the tracks without the synth running */
420 rb->pcm_play_stop();
421 seekBackward(5);
422 midi_debug("Rewind to %d:%02d\n", playing_time/60, playing_time%60);
423 if (is_playing)
424 rb->pcm_play_data(&get_more, NULL, 0);
425 break;
428 case BTN_RIGHT:
430 rb->pcm_play_stop();
431 seekForward(5);
432 midi_debug("Skip to %d:%02d\n", playing_time/60, playing_time%60);
433 if (is_playing)
434 rb->pcm_play_data(&get_more, NULL, 0);
435 break;
438 case BTN_PLAY:
440 if (is_playing)
442 midi_debug("Paused at %d:%02d\n", playing_time/60, playing_time%60);
443 is_playing = false;
444 rb->pcm_play_stop();
445 } else
447 midi_debug("Playing from %d:%02d\n", playing_time/60, playing_time%60);
448 is_playing = true;
449 rb->pcm_play_data(&get_more, NULL, 0);
451 break;
454 #ifdef BTN_RC_QUIT
455 case BTN_RC_QUIT:
456 #endif
457 case BTN_QUIT:
458 quit = true;
461 return 0;
464 enum plugin_status plugin_start(const void* parameter)
466 int retval;
468 if (parameter == NULL)
470 rb->splash(HZ*2, " Play .MID file ");
471 return PLUGIN_OK;
473 rb->lcd_setfont(0);
475 #if defined(HAVE_ADJUSTABLE_CPU_FREQ)
476 rb->cpu_boost(true);
477 #endif
479 midi_debug("%s", parameter);
480 /* rb->splash(HZ, true, parameter); */
482 #ifdef RB_PROFILE
483 rb->profile_thread();
484 #endif
486 retval = midimain(parameter);
488 #ifdef RB_PROFILE
489 rb->profstop();
490 #endif
492 rb->pcm_play_stop();
493 rb->pcm_set_frequency(HW_SAMPR_DEFAULT);
495 #if defined(HAVE_ADJUSTABLE_CPU_FREQ)
496 rb->cpu_boost(false);
497 #endif
498 rb->splash(HZ, "FINISHED PLAYING");
500 if (retval == -1)
501 return PLUGIN_ERROR;
502 return PLUGIN_OK;