1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2004 Matthias Wientapper
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.
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
18 ****************************************************************************/
19 #include "pluginlib_actions.h"
20 #include "metronome.h"
23 #define METRONOME_QUIT PLA_QUIT
24 #define METRONOME_VOL_UP PLA_INC
25 #define METRONOME_VOL_DOWN PLA_DEC
26 #define METRONOME_VOL_UP_REP PLA_INC_REPEAT
27 #define METRONOME_VOL_DOWN_REP PLA_DEC_REPEAT
28 #define METRONOME_LEFT PLA_LEFT
29 #define METRONOME_RIGHT PLA_RIGHT
30 #define METRONOME_LEFT_REP PLA_LEFT_REPEAT
31 #define METRONOME_RIGHT_REP PLA_RIGHT_REPEAT
33 METRONOME_PLAY_TAP
= LAST_PLUGINLIB_ACTION
+1,
34 #if CONFIG_KEYPAD == ONDIO_PAD
36 #endif /* ONDIO_PAD */
37 #if (CONFIG_KEYPAD == IRIVER_H100_PAD) || (CONFIG_KEYPAD == IRIVER_H300_PAD)
39 #endif /* IRIVER_H100_PAD||IRIVER_H300_PAD */
43 #if CONFIG_KEYPAD == ONDIO_PAD
44 #define METRONOME_TAP PLA_START
45 #define METRONOME_MSG_START "start: mode"
46 #define METRONOME_MSG_STOP "pause: hold mode"
47 static const struct button_mapping ondio_action
[] =
49 {METRONOME_PLAY_TAP
, BUTTON_MENU
|BUTTON_REL
, BUTTON_MENU
},
50 {METRONOME_PAUSE
, BUTTON_MENU
|BUTTON_REPEAT
, BUTTON_NONE
},
51 {CONTEXT_CUSTOM
,BUTTON_NONE
,BUTTON_NONE
}
53 #else /* !ONDIO_PAD */
54 #define METRONOME_TAP PLA_FIRE
55 #define METRONOME_PLAYPAUSE PLA_START
56 #define METRONOME_MSG_START "press play"
57 #define METRONOME_MSG_STOP "press pause"
59 #if (CONFIG_KEYPAD == IRIVER_H100_PAD) || (CONFIG_KEYPAD == IRIVER_H300_PAD)
61 static const struct button_mapping iriver_syncaction
[] =
63 {METRONOME_SYNC
, BUTTON_REC
, BUTTON_NONE
},
64 {CONTEXT_CUSTOM
,BUTTON_NONE
,BUTTON_NONE
}
66 #endif /* IRIVER_H100_PAD||IRIVER_H300_PAD */
67 #endif /* #if CONFIG_KEYPAD == ONDIO_PAD */
69 const struct button_mapping
*plugin_contexts
[]={
70 generic_increase_decrease
,
72 #if CONFIG_KEYPAD == ONDIO_PAD
74 #elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || (CONFIG_KEYPAD == IRIVER_H300_PAD)
79 #define PLA_ARRAY_COUNT sizeof(plugin_contexts)/sizeof(plugin_contexts[0])
81 static const struct plugin_api
* rb
;
83 MEM_FUNCTION_WRAPPERS(rb
);
86 static int period
= 0;
87 static int minitick
= 0;
89 static bool sound_active
= false;
90 static bool sound_paused
= true;
92 static char buffer
[30];
94 static bool reset_tap
= false;
95 static int tap_count
= 0;
96 static int tap_time
= 0;
97 static int tap_timeout
= 0;
99 int bpm_step_counter
= 0;
101 #if CONFIG_CODEC != SWCODEC
103 #define MET_IS_PLAYING rb->mp3_is_playing()
104 #define MET_PLAY_STOP rb->mp3_play_stop()
106 void callback(unsigned char** start
, size_t* size
){
107 (void)start
; /* unused parameter, avoid warning */
108 *size
= 0; /* end of data */
109 sound_active
= false;
113 void play_tock(void){
116 rb
->mp3_play_data(sound
, sizeof(sound
), callback
);
117 rb
->mp3_play_pause(true); /* kickoff audio */
120 #else /* CONFIG_CODEC == SWCODEC */
122 #define MET_IS_PLAYING rb->pcm_is_playing()
123 #define MET_PLAY_STOP rb->audio_stop()
127 bool need_to_play
= false;
129 short sndbuf
[sizeof(sound
)*2];
131 /* Convert the mono "tock" sample to interleaved stereo */
132 void prepare_tock(void)
135 for(i
= 0;i
< (int)sizeof(sound
)/2;i
++) {
136 sndbuf
[i
*2] = sound
[i
];
137 sndbuf
[i
*2+1] = sound
[i
];
141 void play_tock(void) {
142 rb
->pcm_play_data(NULL
,(unsigned char *)sndbuf
,sizeof(sndbuf
));
146 #endif /* CONFIG_CODEC != SWCODEC */
148 void calc_period(void)
150 period
= 61440/bpm
-1; /* (60*1024)/bpm; */
154 void metronome_draw(struct screen
* display
)
156 display
->clear_display();
158 #ifdef HAVE_LCD_BITMAP
159 display
->setfont(FONT_SYSFIXED
);
160 display
->puts(0, 0, "Metronome");
161 if(display
->screen_type
==SCREEN_MAIN
)
163 display
->puts(0, 5, "Select to TAP");
164 display
->puts(0, 6, "Rec to SYNC");
166 #ifdef HAVE_REMOTE_LCD
169 display
->puts(0, 5, "Rec to TAP");
170 display
->puts(0, 6, "Mode to SYNC");
173 #endif /* HAVE_LCD_BITMAP */
175 rb
->snprintf(buffer
, sizeof(buffer
), "BPM: %d ",bpm
);
176 #ifdef HAVE_LCD_BITMAP
177 display
->puts(0,3, buffer
);
179 display
->puts(0,0, buffer
);
180 #endif /* HAVE_LCD_BITMAP */
182 rb
->snprintf(buffer
, sizeof(buffer
), "Vol: %d",
183 rb
->global_settings
->volume
);
184 #ifdef HAVE_LCD_BITMAP
185 display
->puts(10, 3, buffer
);
187 display
->puts(0,1, buffer
);
188 #endif /* HAVE_LCD_BITMAP */
190 #ifdef HAVE_LCD_BITMAP
191 display
->hline(0, 111, 12);
193 display
->puts(0,2,METRONOME_MSG_START
);
195 display
->puts(0,2,METRONOME_MSG_STOP
);
196 display
->setfont(FONT_UI
);
197 #endif /* HAVE_LCD_BITMAP */
201 void draw_display(void)
205 metronome_draw(rb
->screens
[i
]);
208 /* helper function to change the volume by a certain amount, +/-
209 ripped from video.c */
210 void change_volume(int delta
){
211 int minvol
= rb
->sound_min(SOUND_VOLUME
);
212 int maxvol
= rb
->sound_max(SOUND_VOLUME
);
213 int vol
= rb
->global_settings
->volume
+ delta
;
215 if (vol
> maxvol
) vol
= maxvol
;
216 else if (vol
< minvol
) vol
= minvol
;
217 if (vol
!= rb
->global_settings
->volume
) {
218 rb
->sound_set(SOUND_VOLUME
, vol
);
219 rb
->global_settings
->volume
= vol
;
224 /*function to accelerate bpm change*/
225 void change_bpm(int direction
){
226 if((bpm_step_counter
< 20)
229 bpm
= bpm
+ direction
;
230 else if (bpm_step_counter
< 60)
231 bpm
= bpm
+ direction
* 2;
233 bpm
= bpm
+ direction
* 9;
235 if (bpm
> 400) bpm
= 400;
236 if (bpm
< 1) bpm
= 1;
242 void timer_callback(void)
244 if(minitick
>= period
){
246 if(!sound_active
&& !sound_paused
&& !tap_count
) {
247 #if CONFIG_CODEC == SWCODEC
248 /* On SWCODEC we can't call play_tock() directly from an ISR. */
253 rb
->reset_poweroff_timer();
262 if (tap_count
> 1 && tap_time
> tap_timeout
)
267 void cleanup(void *parameter
)
271 rb
->timer_unregister();
272 MET_PLAY_STOP
; /* stop audio ISR */
278 if (tap_count
== 0 || tap_time
< tap_count
) {
283 bpm
= 61440/(tap_time
/tap_count
);
292 tap_timeout
= (tap_count
+2)*tap_time
/tap_count
;
296 minitick
= 0; /* sync tock to tapping */
302 enum plugin_status
plugin_start(const struct plugin_api
* api
, const void* parameter
){
304 enum plugin_status status
;
310 MET_PLAY_STOP
; /* stop audio IS */
312 #if CONFIG_CODEC != SWCODEC
313 rb
->bitswap(sound
, sizeof(sound
));
316 #if INPUT_SRC_CAPS != 0
317 /* Select playback */
318 rb
->audio_set_input_source(AUDIO_SRC_PLAYBACK
, SRCF_PLAYBACK
);
319 rb
->audio_set_output_source(AUDIO_SRC_PLAYBACK
);
321 rb
->pcm_set_frequency(SAMPR_44
);
322 #endif /* CONFIG_CODEC != SWCODEC */
325 rb
->timer_register(1, NULL
, TIMER_FREQ
/1024, 1, timer_callback
IF_COP(, CPU
));
332 #if CONFIG_CODEC == SWCODEC
333 button
= pluginlib_getaction(rb
,1,plugin_contexts
,PLA_ARRAY_COUNT
);
336 need_to_play
= false;
340 button
= pluginlib_getaction(rb
,TIMEOUT_BLOCK
,
341 plugin_contexts
,PLA_ARRAY_COUNT
);
346 /* get out of here */
351 #if CONFIG_KEYPAD == ONDIO_PAD
352 case METRONOME_PLAY_TAP
:
354 sound_paused
= false;
362 case METRONOME_PAUSE
:
370 case METRONOME_PLAYPAUSE
:
372 sound_paused
= false;
378 #endif /* ONDIO_PAD */
380 case METRONOME_VOL_UP
:
381 case METRONOME_VOL_UP_REP
:
386 case METRONOME_VOL_DOWN
:
387 case METRONOME_VOL_DOWN_REP
:
393 bpm_step_counter
= 0;
394 case METRONOME_LEFT_REP
:
398 case METRONOME_RIGHT
:
399 bpm_step_counter
= 0;
400 case METRONOME_RIGHT_REP
:
417 if (rb
->default_event_handler_ex(button
, cleanup
, NULL
)
418 == SYS_USB_CONNECTED
)
420 status
= PLUGIN_USB_CONNECTED
;
433 #if CONFIG_CODEC == SWCODEC
434 rb
->pcm_set_frequency(HW_SAMPR_DEFAULT
);