blob: 99f05718d6d9c8356f9bd830dec981c15a5e9cc3 [file] [log] [blame]
Stepan Moskovchenkob2f1b5d2006-05-01 23:22:59 +00001/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
Nils Wallménius0e496052007-09-24 15:57:32 +00008 * $Id$
Stepan Moskovchenkob2f1b5d2006-05-01 23:22:59 +00009 *
10 * Copyright (C) 2005 Karl Kurbjun based on midi2wav by Stepan Moskovchenko
11 *
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
Nils Wallménius0e496052007-09-24 15:57:32 +000019#include "plugin.h"
20#include "guspat.h"
21#include "midiutil.h"
22#include "synth.h"
23#include "sequencer.h"
24#include "midifile.h"
Stepan Moskovchenkob2f1b5d2006-05-01 23:22:59 +000025
26PLUGIN_HEADER
Michael Sevakisacc29d92006-11-18 02:18:29 +000027PLUGIN_IRAM_DECLARE
Stepan Moskovchenko595a2042006-05-07 07:27:07 +000028
29/* variable button definitions */
30#if CONFIG_KEYPAD == RECORDER_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
36#elif CONFIG_KEYPAD == ONDIO_PAD
37#define BTN_QUIT BUTTON_OFF
38#define BTN_RIGHT BUTTON_RIGHT
39#define BTN_UP BUTTON_UP
40#define BTN_DOWN BUTTON_DOWN
41
42#elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || (CONFIG_KEYPAD == IRIVER_H300_PAD)
43#define BTN_QUIT BUTTON_OFF
44#define BTN_RIGHT BUTTON_RIGHT
45#define BTN_UP BUTTON_UP
46#define BTN_DOWN BUTTON_DOWN
47
Kevin Ferrare0e027bd2006-06-30 16:43:47 +000048#define BTN_RC_QUIT BUTTON_RC_STOP
49
Jens Arnoldb7013222007-07-27 09:57:27 +000050#elif (CONFIG_KEYPAD == IPOD_4G_PAD) || (CONFIG_KEYPAD == IPOD_3G_PAD) || \
51 (CONFIG_KEYPAD == IPOD_1G2G_PAD)
Stepan Moskovchenko595a2042006-05-07 07:27:07 +000052#define BTN_QUIT (BUTTON_SELECT | BUTTON_MENU)
53#define BTN_RIGHT BUTTON_RIGHT
54#define BTN_UP BUTTON_SCROLL_FWD
55#define BTN_DOWN BUTTON_SCROLL_BACK
56
57#elif (CONFIG_KEYPAD == GIGABEAT_PAD)
58#define BTN_QUIT BUTTON_POWER
59#define BTN_RIGHT BUTTON_RIGHT
Marcoen Hirschberga7168fe2007-05-19 23:38:09 +000060#define BTN_UP BUTTON_UP
61#define BTN_DOWN BUTTON_DOWN
Stepan Moskovchenko595a2042006-05-07 07:27:07 +000062
Marianne Arnold12ddb8e2007-09-20 10:49:48 +000063#elif (CONFIG_KEYPAD == SANSA_E200_PAD) || \
64(CONFIG_KEYPAD == SANSA_C200_PAD)
Barry Wardell24f4a2a2006-10-26 13:38:09 +000065#define BTN_QUIT BUTTON_POWER
66#define BTN_RIGHT BUTTON_RIGHT
67#define BTN_UP BUTTON_UP
68#define BTN_DOWN BUTTON_DOWN
69
Jens Arnold85a226d2007-03-16 23:02:39 +000070#elif CONFIG_KEYPAD == IAUDIO_X5M5_PAD
Stepan Moskovchenko595a2042006-05-07 07:27:07 +000071#define BTN_QUIT BUTTON_POWER
72#define BTN_RIGHT BUTTON_RIGHT
73#define BTN_UP BUTTON_UP
74#define BTN_DOWN BUTTON_DOWN
75
Daniel Stenberg1e88be52006-08-03 20:17:25 +000076#elif CONFIG_KEYPAD == IRIVER_H10_PAD
77#define BTN_QUIT BUTTON_POWER
78#define BTN_RIGHT BUTTON_RIGHT
79#define BTN_UP BUTTON_SCROLL_UP
80#define BTN_DOWN BUTTON_SCROLL_DOWN
81
Stepan Moskovchenko595a2042006-05-07 07:27:07 +000082#endif
83
Stepan Moskovchenkob2f1b5d2006-05-01 23:22:59 +000084#undef SYNC
Stepan Moskovchenko9cf76172007-01-11 20:13:15 +000085
86#ifdef SIMULATOR
87 #define SYNC
88#endif
89
Stepan Moskovchenkob2f1b5d2006-05-01 23:22:59 +000090struct MIDIfile * mf IBSS_ATTR;
91
92int numberOfSamples IBSS_ATTR;
93long bpm IBSS_ATTR;
94
Nils Wallméniusff7b3c52007-09-24 16:47:34 +000095int32_t gmbuf[BUF_SIZE*NBUF];
Stepan Moskovchenkob2f1b5d2006-05-01 23:22:59 +000096
97int quit=0;
98struct plugin_api * rb;
99
Nils Wallménius6386dbe2007-09-30 11:21:25 +0000100static int midimain(void * filename);
101
Stepan Moskovchenkob2f1b5d2006-05-01 23:22:59 +0000102enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
103{
Stepan Moskovchenko47efba82006-05-03 05:18:18 +0000104 int retval = 0;
Stepan Moskovchenkob2f1b5d2006-05-01 23:22:59 +0000105
Tomasz Malesinski80da8b12006-11-26 18:31:41 +0000106 PLUGIN_IRAM_INIT(api)
107
108 rb = api;
Stepan Moskovchenko47efba82006-05-03 05:18:18 +0000109 if(parameter == NULL)
110 {
Jens Arnoldf3455d12007-03-16 22:09:52 +0000111 rb->splash(HZ*2, " Play .MID file ");
Stepan Moskovchenko47efba82006-05-03 05:18:18 +0000112 return PLUGIN_OK;
113 }
114 rb->lcd_setfont(0);
Stepan Moskovchenkob2f1b5d2006-05-01 23:22:59 +0000115
Christian Gmeiner98d52122006-06-12 00:13:00 +0000116#if defined(HAVE_ADJUSTABLE_CPU_FREQ)
Stepan Moskovchenko47efba82006-05-03 05:18:18 +0000117 rb->cpu_boost(true);
Stepan Moskovchenkob2f1b5d2006-05-01 23:22:59 +0000118#endif
119
Jens Arnoldb1f00492007-04-21 05:35:17 +0000120 printf("%s", parameter);
Stepan Moskovchenko47efba82006-05-03 05:18:18 +0000121 /* rb->splash(HZ, true, parameter); */
Stepan Moskovchenkob2f1b5d2006-05-01 23:22:59 +0000122
123#ifdef RB_PROFILE
Stepan Moskovchenko47efba82006-05-03 05:18:18 +0000124 rb->profile_thread();
Stepan Moskovchenkob2f1b5d2006-05-01 23:22:59 +0000125#endif
126
Stepan Moskovchenko47efba82006-05-03 05:18:18 +0000127 retval = midimain(parameter);
Stepan Moskovchenkob2f1b5d2006-05-01 23:22:59 +0000128
129#ifdef RB_PROFILE
Stepan Moskovchenko47efba82006-05-03 05:18:18 +0000130 rb->profstop();
Stepan Moskovchenkob2f1b5d2006-05-01 23:22:59 +0000131#endif
132
Stepan Moskovchenko47efba82006-05-03 05:18:18 +0000133 rb->pcm_play_stop();
Steve Bavin18b84ee2007-03-14 16:43:21 +0000134 rb->pcm_set_frequency(HW_SAMPR_DEFAULT);
Stepan Moskovchenkob2f1b5d2006-05-01 23:22:59 +0000135
Christian Gmeiner98d52122006-06-12 00:13:00 +0000136#if defined(HAVE_ADJUSTABLE_CPU_FREQ)
Stepan Moskovchenko47efba82006-05-03 05:18:18 +0000137 rb->cpu_boost(false);
Stepan Moskovchenkob2f1b5d2006-05-01 23:22:59 +0000138#endif
Jens Arnoldf3455d12007-03-16 22:09:52 +0000139 rb->splash(HZ, "FINISHED PLAYING");
Stepan Moskovchenkob2f1b5d2006-05-01 23:22:59 +0000140
Stepan Moskovchenko47efba82006-05-03 05:18:18 +0000141 if(retval == -1)
142 return PLUGIN_ERROR;
143 return PLUGIN_OK;
Stepan Moskovchenkob2f1b5d2006-05-01 23:22:59 +0000144}
145
146bool swap=0;
147bool lastswap=1;
148
Nils Wallméniusc6c7b732007-09-29 16:06:16 +0000149static inline void synthbuf(void)
Stepan Moskovchenkob2f1b5d2006-05-01 23:22:59 +0000150{
Nils Wallméniusf619f812007-10-08 19:28:41 +0000151 int32_t *outptr;
152 int i;
Stepan Moskovchenkob2f1b5d2006-05-01 23:22:59 +0000153
154#ifndef SYNC
Nils Wallméniusf619f812007-10-08 19:28:41 +0000155 if(lastswap==swap) return;
156 lastswap=swap;
Stepan Moskovchenkob2f1b5d2006-05-01 23:22:59 +0000157
Nils Wallméniusf619f812007-10-08 19:28:41 +0000158 outptr=(swap ? gmbuf : gmbuf+BUF_SIZE);
Stepan Moskovchenkob2f1b5d2006-05-01 23:22:59 +0000159#else
Nils Wallméniusf619f812007-10-08 19:28:41 +0000160 outptr=gmbuf;
Stepan Moskovchenkob2f1b5d2006-05-01 23:22:59 +0000161#endif
162
Nils Wallméniusf619f812007-10-08 19:28:41 +0000163 for(i=0; i<BUF_SIZE/numberOfSamples; i++)
164 {
165 synthSamples((int32_t*)outptr, numberOfSamples);
166 outptr += numberOfSamples;
167 if( tick() == 0 )
168 quit=1;
169 }
170
171 if(BUF_SIZE%numberOfSamples)
172 {
173 synthSamples((int32_t*)outptr, BUF_SIZE%numberOfSamples);
174 outptr += BUF_SIZE%numberOfSamples;
175 }
Stepan Moskovchenkob2f1b5d2006-05-01 23:22:59 +0000176}
177
178void get_more(unsigned char** start, size_t* size)
179{
180#ifndef SYNC
Stepan Moskovchenko47efba82006-05-03 05:18:18 +0000181 if(lastswap!=swap)
182 {
183 printf("Buffer miss!"); // Comment out the printf to make missses less noticable.
Stepan Moskovchenkob2f1b5d2006-05-01 23:22:59 +0000184 }
185
186#else
Stepan Moskovchenko47efba82006-05-03 05:18:18 +0000187 synthbuf(); // For some reason midiplayer crashes when an update is forced
Stepan Moskovchenkob2f1b5d2006-05-01 23:22:59 +0000188#endif
189
Nils Wallméniusc6c7b732007-09-29 16:06:16 +0000190 *size = sizeof(gmbuf)/NBUF;
Stepan Moskovchenkob2f1b5d2006-05-01 23:22:59 +0000191#ifndef SYNC
Stepan Moskovchenko47efba82006-05-03 05:18:18 +0000192 *start = (unsigned char*)((swap ? gmbuf : gmbuf + BUF_SIZE));
193 swap=!swap;
Stepan Moskovchenkob2f1b5d2006-05-01 23:22:59 +0000194#else
Stepan Moskovchenko47efba82006-05-03 05:18:18 +0000195 *start = (unsigned char*)(gmbuf);
Stepan Moskovchenkob2f1b5d2006-05-01 23:22:59 +0000196#endif
197}
198
Nils Wallménius6386dbe2007-09-30 11:21:25 +0000199static int midimain(void * filename)
Stepan Moskovchenkob2f1b5d2006-05-01 23:22:59 +0000200{
Stepan Moskovchenko68af7ba2006-05-07 07:12:07 +0000201 int notesUsed = 0;
202 int a=0;
Jens Arnoldb1f00492007-04-21 05:35:17 +0000203 printf("Loading file");
Stepan Moskovchenko47efba82006-05-03 05:18:18 +0000204 mf= loadFile(filename);
Stepan Moskovchenkob2f1b5d2006-05-01 23:22:59 +0000205
Stepan Moskovchenkob9b2bcd2006-05-08 02:43:29 +0000206 if(mf == NULL)
207 {
Jens Arnoldb1f00492007-04-21 05:35:17 +0000208 printf("Error loading file.");
Stepan Moskovchenkob9b2bcd2006-05-08 02:43:29 +0000209 return -1;
210 }
Stepan Moskovchenko68af7ba2006-05-07 07:12:07 +0000211
Nils Wallménius04b34352007-09-10 09:46:36 +0000212 if (initSynth(mf, ROCKBOX_DIR "/patchset/patchset.cfg",
213 ROCKBOX_DIR "/patchset/drums.cfg") == -1)
Stepan Moskovchenko47efba82006-05-03 05:18:18 +0000214 return -1;
Stepan Moskovchenkob2f1b5d2006-05-01 23:22:59 +0000215
Stepan Moskovchenko47efba82006-05-03 05:18:18 +0000216 rb->pcm_play_stop();
Michael Sevakis4597ebe2007-06-10 02:10:47 +0000217#if INPUT_SRC_CAPS != 0
218 /* Select playback */
219 rb->audio_set_input_source(AUDIO_SRC_PLAYBACK, SRCF_PLAYBACK);
220 rb->audio_set_output_source(AUDIO_SRC_PLAYBACK);
221#endif
Stepan Moskovchenko47efba82006-05-03 05:18:18 +0000222 rb->pcm_set_frequency(SAMPLE_RATE); // 44100 22050 11025
Stepan Moskovchenkob2f1b5d2006-05-01 23:22:59 +0000223
Stepan Moskovchenko47efba82006-05-03 05:18:18 +0000224 /*
225 * tick() will do one MIDI clock tick. Then, there's a loop here that
226 * will generate the right number of samples per MIDI tick. The whole
227 * MIDI playback is timed in terms of this value.. there are no forced
228 * delays or anything. It just produces enough samples for each tick, and
229 * the playback of these samples is what makes the timings right.
230 *
231 * This seems to work quite well. On a laptop, anyway.
232 */
Stepan Moskovchenkob2f1b5d2006-05-01 23:22:59 +0000233
Jens Arnoldb1f00492007-04-21 05:35:17 +0000234 printf("Okay, starting sequencing");
Stepan Moskovchenkob2f1b5d2006-05-01 23:22:59 +0000235
Stepan Moskovchenko47efba82006-05-03 05:18:18 +0000236 bpm=mf->div*1000000/tempo;
237 numberOfSamples=SAMPLE_RATE/bpm;
Stepan Moskovchenkob2f1b5d2006-05-01 23:22:59 +0000238
Stepan Moskovchenko68af7ba2006-05-07 07:12:07 +0000239
240
241 /* Skip over any junk in the beginning of the file, so start playing */
242 /* after the first note event */
243 do
244 {
245 notesUsed = 0;
246 for(a=0; a<MAX_VOICES; a++)
247 if(voices[a].isUsed == 1)
248 notesUsed++;
249 tick();
250 } while(notesUsed == 0);
Stepan Moskovchenkob2f1b5d2006-05-01 23:22:59 +0000251
Stepan Moskovchenko47efba82006-05-03 05:18:18 +0000252 synthbuf();
Stepan Moskovchenko47efba82006-05-03 05:18:18 +0000253 rb->pcm_play_data(&get_more, NULL, 0);
Stepan Moskovchenkob2f1b5d2006-05-01 23:22:59 +0000254
Stepan Moskovchenko68af7ba2006-05-07 07:12:07 +0000255 int vol=0;
Stepan Moskovchenkob2f1b5d2006-05-01 23:22:59 +0000256
Stepan Moskovchenko47efba82006-05-03 05:18:18 +0000257 while(!quit)
258 {
259 #ifndef SYNC
260 synthbuf();
261 #endif
262 rb->yield();
Stepan Moskovchenko68af7ba2006-05-07 07:12:07 +0000263
Linus Nielsen Feltzinga416cc92007-05-19 20:37:02 +0000264 /* Prevent idle poweroff */
265 rb->reset_poweroff_timer();
266
Stepan Moskovchenko68af7ba2006-05-07 07:12:07 +0000267 /* Code taken from Oscilloscope plugin */
268 switch(rb->button_get(false))
269 {
Stepan Moskovchenko595a2042006-05-07 07:27:07 +0000270 case BTN_UP:
271 case BTN_UP | BUTTON_REPEAT:
Stepan Moskovchenko68af7ba2006-05-07 07:12:07 +0000272 vol = rb->global_settings->volume;
273 if (vol < rb->sound_max(SOUND_VOLUME))
274 {
275 vol++;
276 rb->sound_set(SOUND_VOLUME, vol);
277 rb->global_settings->volume = vol;
278 }
279 break;
280
Stepan Moskovchenko595a2042006-05-07 07:27:07 +0000281 case BTN_DOWN:
282 case BTN_DOWN | BUTTON_REPEAT:
Stepan Moskovchenko68af7ba2006-05-07 07:12:07 +0000283 vol = rb->global_settings->volume;
284 if (vol > rb->sound_min(SOUND_VOLUME))
285 {
286 vol--;
287 rb->sound_set(SOUND_VOLUME, vol);
288 rb->global_settings->volume = vol;
289 }
290 break;
291
Stepan Moskovchenko595a2042006-05-07 07:27:07 +0000292 case BTN_RIGHT:
Stepan Moskovchenko68af7ba2006-05-07 07:12:07 +0000293 {
294 /* Skip 3 seconds */
295 /* Should skip length be retrieved from the RB settings? */
296 int samp = 3*SAMPLE_RATE;
297 int tickCount = samp / numberOfSamples;
298 int a=0;
299 for(a=0; a<tickCount; a++)
300 tick();
301 break;
302 }
Kevin Ferrare0e027bd2006-06-30 16:43:47 +0000303#ifdef BTN_RC_QUIT
304 case BTN_RC_QUIT:
305#endif
Stepan Moskovchenko595a2042006-05-07 07:27:07 +0000306 case BTN_QUIT:
Stepan Moskovchenko68af7ba2006-05-07 07:12:07 +0000307 quit=1;
308 }
309
310
Stepan Moskovchenko47efba82006-05-03 05:18:18 +0000311 }
Stepan Moskovchenkob2f1b5d2006-05-01 23:22:59 +0000312
Stepan Moskovchenko47efba82006-05-03 05:18:18 +0000313 return 0;
Stepan Moskovchenkob2f1b5d2006-05-01 23:22:59 +0000314}