1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2004 Matthias Wientapper
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 "pluginlib_actions.h"
22 #include "metronome.h"
25 #define METRONOME_QUIT PLA_QUIT
26 #define METRONOME_VOL_UP PLA_INC
27 #define METRONOME_VOL_DOWN PLA_DEC
28 #define METRONOME_VOL_UP_REP PLA_INC_REPEAT
29 #define METRONOME_VOL_DOWN_REP PLA_DEC_REPEAT
30 #define METRONOME_LEFT PLA_LEFT
31 #define METRONOME_RIGHT PLA_RIGHT
32 #define METRONOME_LEFT_REP PLA_LEFT_REPEAT
33 #define METRONOME_RIGHT_REP PLA_RIGHT_REPEAT
35 METRONOME_PLAY_TAP
= LAST_PLUGINLIB_ACTION
+1,
36 #if CONFIG_KEYPAD == ONDIO_PAD
38 #endif /* ONDIO_PAD */
39 #if (CONFIG_KEYPAD == IRIVER_H100_PAD) || (CONFIG_KEYPAD == IRIVER_H300_PAD)
41 #endif /* IRIVER_H100_PAD||IRIVER_H300_PAD */
45 #if CONFIG_KEYPAD == ONDIO_PAD
46 #define METRONOME_TAP PLA_START
47 #define METRONOME_MSG_START "start: mode"
48 #define METRONOME_MSG_STOP "pause: hold mode"
49 static const struct button_mapping ondio_action
[] =
51 {METRONOME_PLAY_TAP
, BUTTON_MENU
|BUTTON_REL
, BUTTON_MENU
},
52 {METRONOME_PAUSE
, BUTTON_MENU
|BUTTON_REPEAT
, BUTTON_NONE
},
53 {CONTEXT_CUSTOM
,BUTTON_NONE
,BUTTON_NONE
}
55 #else /* !ONDIO_PAD */
56 #define METRONOME_TAP PLA_FIRE
57 #define METRONOME_PLAYPAUSE PLA_START
58 #define METRONOME_MSG_START "press play"
59 #define METRONOME_MSG_STOP "press pause"
61 #if (CONFIG_KEYPAD == IRIVER_H100_PAD) || (CONFIG_KEYPAD == IRIVER_H300_PAD)
63 static const struct button_mapping iriver_syncaction
[] =
65 {METRONOME_SYNC
, BUTTON_REC
, BUTTON_NONE
},
66 {CONTEXT_CUSTOM
,BUTTON_NONE
,BUTTON_NONE
}
68 #endif /* IRIVER_H100_PAD||IRIVER_H300_PAD */
69 #endif /* #if CONFIG_KEYPAD == ONDIO_PAD */
71 const struct button_mapping
*plugin_contexts
[]={
72 generic_increase_decrease
,
74 #if CONFIG_KEYPAD == ONDIO_PAD
76 #elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || (CONFIG_KEYPAD == IRIVER_H300_PAD)
81 #define PLA_ARRAY_COUNT sizeof(plugin_contexts)/sizeof(plugin_contexts[0])
83 static const struct plugin_api
* rb
;
85 MEM_FUNCTION_WRAPPERS(rb
);
88 static int period
= 0;
89 static int minitick
= 0;
91 static bool sound_active
= false;
92 static bool sound_paused
= true;
94 static char buffer
[30];
96 static bool reset_tap
= false;
97 static int tap_count
= 0;
98 static int tap_time
= 0;
99 static int tap_timeout
= 0;
101 int bpm_step_counter
= 0;
103 #if CONFIG_CODEC != SWCODEC
105 #define MET_IS_PLAYING rb->mp3_is_playing()
106 #define MET_PLAY_STOP rb->mp3_play_stop()
108 void callback(unsigned char** start
, size_t* size
){
109 (void)start
; /* unused parameter, avoid warning */
110 *size
= 0; /* end of data */
111 sound_active
= false;
115 void play_tock(void){
118 rb
->mp3_play_data(sound
, sizeof(sound
), callback
);
119 rb
->mp3_play_pause(true); /* kickoff audio */
122 #else /* CONFIG_CODEC == SWCODEC */
124 #define MET_IS_PLAYING rb->pcm_is_playing()
125 #define MET_PLAY_STOP rb->audio_stop()
129 bool need_to_play
= false;
131 short sndbuf
[sizeof(sound
)*2];
133 /* Convert the mono "tock" sample to interleaved stereo */
134 void prepare_tock(void)
137 for(i
= 0;i
< (int)sizeof(sound
)/2;i
++) {
138 sndbuf
[i
*2] = sound
[i
];
139 sndbuf
[i
*2+1] = sound
[i
];
143 void play_tock(void) {
144 rb
->pcm_play_data(NULL
,(unsigned char *)sndbuf
,sizeof(sndbuf
));
148 #endif /* CONFIG_CODEC != SWCODEC */
150 void calc_period(void)
152 period
= 61440/bpm
-1; /* (60*1024)/bpm; */
156 void metronome_draw(struct screen
* display
)
158 display
->clear_display();
160 #ifdef HAVE_LCD_BITMAP
161 display
->setfont(FONT_SYSFIXED
);
162 display
->puts(0, 0, "Metronome");
163 if(display
->screen_type
==SCREEN_MAIN
)
165 display
->puts(0, 5, "Select to TAP");
166 display
->puts(0, 6, "Rec to SYNC");
168 #ifdef HAVE_REMOTE_LCD
171 display
->puts(0, 5, "Rec to TAP");
172 display
->puts(0, 6, "Mode to SYNC");
175 #endif /* HAVE_LCD_BITMAP */
177 rb
->snprintf(buffer
, sizeof(buffer
), "BPM: %d ",bpm
);
178 #ifdef HAVE_LCD_BITMAP
179 display
->puts(0,3, buffer
);
181 display
->puts(0,0, buffer
);
182 #endif /* HAVE_LCD_BITMAP */
184 rb
->snprintf(buffer
, sizeof(buffer
), "Vol: %d",
185 rb
->global_settings
->volume
);
186 #ifdef HAVE_LCD_BITMAP
187 display
->puts(10, 3, buffer
);
189 display
->puts(0,1, buffer
);
190 #endif /* HAVE_LCD_BITMAP */
192 #ifdef HAVE_LCD_BITMAP
193 display
->hline(0, 111, 12);
195 display
->puts(0,2,METRONOME_MSG_START
);
197 display
->puts(0,2,METRONOME_MSG_STOP
);
198 display
->setfont(FONT_UI
);
199 #endif /* HAVE_LCD_BITMAP */
203 void draw_display(void)
207 metronome_draw(rb
->screens
[i
]);
210 /* helper function to change the volume by a certain amount, +/-
211 ripped from video.c */
212 void change_volume(int delta
){
213 int minvol
= rb
->sound_min(SOUND_VOLUME
);
214 int maxvol
= rb
->sound_max(SOUND_VOLUME
);
215 int vol
= rb
->global_settings
->volume
+ delta
;
217 if (vol
> maxvol
) vol
= maxvol
;
218 else if (vol
< minvol
) vol
= minvol
;
219 if (vol
!= rb
->global_settings
->volume
) {
220 rb
->sound_set(SOUND_VOLUME
, vol
);
221 rb
->global_settings
->volume
= vol
;
226 /*function to accelerate bpm change*/
227 void change_bpm(int direction
){
228 if((bpm_step_counter
< 20)
231 bpm
= bpm
+ direction
;
232 else if (bpm_step_counter
< 60)
233 bpm
= bpm
+ direction
* 2;
235 bpm
= bpm
+ direction
* 9;
237 if (bpm
> 400) bpm
= 400;
238 if (bpm
< 1) bpm
= 1;
244 void timer_callback(void)
246 if(minitick
>= period
){
248 if(!sound_active
&& !sound_paused
&& !tap_count
) {
249 #if CONFIG_CODEC == SWCODEC
250 /* On SWCODEC we can't call play_tock() directly from an ISR. */
255 rb
->reset_poweroff_timer();
264 if (tap_count
> 1 && tap_time
> tap_timeout
)
269 void cleanup(void *parameter
)
273 rb
->timer_unregister();
274 MET_PLAY_STOP
; /* stop audio ISR */
280 if (tap_count
== 0 || tap_time
< tap_count
) {
285 bpm
= 61440/(tap_time
/tap_count
);
294 tap_timeout
= (tap_count
+2)*tap_time
/tap_count
;
298 minitick
= 0; /* sync tock to tapping */
304 enum plugin_status
plugin_start(const struct plugin_api
* api
, const void* parameter
){
306 enum plugin_status status
;
312 MET_PLAY_STOP
; /* stop audio IS */
314 #if CONFIG_CODEC != SWCODEC
315 rb
->bitswap(sound
, sizeof(sound
));
318 #if INPUT_SRC_CAPS != 0
319 /* Select playback */
320 rb
->audio_set_input_source(AUDIO_SRC_PLAYBACK
, SRCF_PLAYBACK
);
321 rb
->audio_set_output_source(AUDIO_SRC_PLAYBACK
);
323 rb
->pcm_set_frequency(SAMPR_44
);
324 #endif /* CONFIG_CODEC != SWCODEC */
327 rb
->timer_register(1, NULL
, TIMER_FREQ
/1024, 1, timer_callback
IF_COP(, CPU
));
334 #if CONFIG_CODEC == SWCODEC
335 button
= pluginlib_getaction(rb
,1,plugin_contexts
,PLA_ARRAY_COUNT
);
338 need_to_play
= false;
342 button
= pluginlib_getaction(rb
,TIMEOUT_BLOCK
,
343 plugin_contexts
,PLA_ARRAY_COUNT
);
348 /* get out of here */
353 #if CONFIG_KEYPAD == ONDIO_PAD
354 case METRONOME_PLAY_TAP
:
356 sound_paused
= false;
364 case METRONOME_PAUSE
:
372 case METRONOME_PLAYPAUSE
:
374 sound_paused
= false;
380 #endif /* ONDIO_PAD */
382 case METRONOME_VOL_UP
:
383 case METRONOME_VOL_UP_REP
:
388 case METRONOME_VOL_DOWN
:
389 case METRONOME_VOL_DOWN_REP
:
395 bpm_step_counter
= 0;
396 case METRONOME_LEFT_REP
:
400 case METRONOME_RIGHT
:
401 bpm_step_counter
= 0;
402 case METRONOME_RIGHT_REP
:
419 if (rb
->default_event_handler_ex(button
, cleanup
, NULL
)
420 == SYS_USB_CONNECTED
)
422 status
= PLUGIN_USB_CONNECTED
;
435 #if CONFIG_CODEC == SWCODEC
436 rb
->pcm_set_frequency(HW_SAMPR_DEFAULT
);