1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2002 Jerome Kuptz
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 ****************************************************************************/
27 #include "backlight.h"
35 #include "wps-display.h"
37 #include "mp3_playback.h"
40 #include "main_menu.h"
44 #ifdef HAVE_LCD_BITMAP
46 #include "peakmeter.h"
53 #define FF_REWIND_MAX_PERCENT 3 /* cap ff/rewind step size at max % of file */
54 /* 3% of 30min file == 54s step size */
55 #define MIN_FF_REWIND_STEP 500
57 bool keys_locked
= false;
58 static bool ff_rewind
= false;
59 static bool paused
= false;
60 static struct mp3entry
* id3
= NULL
;
61 static struct mp3entry
* nid3
= NULL
;
62 static char current_track_path
[MAX_PATH
+1];
64 /* button definitions */
65 #if CONFIG_KEYPAD == RECORDER_PAD
66 #define WPS_NEXT (BUTTON_RIGHT | BUTTON_REL)
67 #define WPS_NEXT_PRE BUTTON_RIGHT
68 #define WPS_PREV (BUTTON_LEFT | BUTTON_REL)
69 #define WPS_PREV_PRE BUTTON_LEFT
70 #define WPS_FFWD (BUTTON_RIGHT | BUTTON_REPEAT)
71 #define WPS_REW (BUTTON_LEFT | BUTTON_REPEAT)
72 #define WPS_INCVOL BUTTON_UP
73 #define WPS_DECVOL BUTTON_DOWN
74 #define WPS_PAUSE BUTTON_PLAY
75 #define WPS_MENU (BUTTON_F1 | BUTTON_REL)
76 #define WPS_MENU_PRE BUTTON_F1
77 #define WPS_BROWSE (BUTTON_ON | BUTTON_REL)
78 #define WPS_BROWSE_PRE BUTTON_ON
79 #define WPS_EXIT BUTTON_OFF
80 #define WPS_KEYLOCK (BUTTON_F1 | BUTTON_DOWN)
81 #define WPS_ID3 (BUTTON_F1 | BUTTON_ON)
83 #define WPS_RC_NEXT BUTTON_RC_RIGHT
84 #define WPS_RC_PREV BUTTON_RC_LEFT
85 #define WPS_RC_PAUSE BUTTON_RC_PLAY
86 #define WPS_RC_INCVOL BUTTON_RC_VOL_UP
87 #define WPS_RC_DECVOL BUTTON_RC_VOL_DOWN
88 #define WPS_RC_EXIT BUTTON_RC_STOP
90 #elif CONFIG_KEYPAD == PLAYER_PAD
91 #define WPS_NEXT (BUTTON_RIGHT | BUTTON_REL)
92 #define WPS_NEXT_PRE BUTTON_RIGHT
93 #define WPS_PREV (BUTTON_LEFT | BUTTON_REL)
94 #define WPS_PREV_PRE BUTTON_LEFT
95 #define WPS_FFWD (BUTTON_RIGHT | BUTTON_REPEAT)
96 #define WPS_REW (BUTTON_LEFT | BUTTON_REPEAT)
97 #define WPS_INCVOL (BUTTON_MENU | BUTTON_RIGHT)
98 #define WPS_DECVOL (BUTTON_MENU | BUTTON_LEFT)
99 #define WPS_PAUSE BUTTON_PLAY
100 #define WPS_MENU (BUTTON_MENU | BUTTON_REL)
101 #define WPS_MENU_PRE BUTTON_MENU
102 #define WPS_BROWSE (BUTTON_ON | BUTTON_REL)
103 #define WPS_BROWSE_PRE BUTTON_ON
104 #define WPS_EXIT BUTTON_STOP
105 #define WPS_KEYLOCK (BUTTON_MENU | BUTTON_STOP)
106 #define WPS_ID3 (BUTTON_MENU | BUTTON_ON)
108 #define WPS_RC_NEXT BUTTON_RC_RIGHT
109 #define WPS_RC_PREV BUTTON_RC_LEFT
110 #define WPS_RC_PAUSE BUTTON_RC_PLAY
111 #define WPS_RC_INCVOL BUTTON_RC_VOL_UP
112 #define WPS_RC_DECVOL BUTTON_RC_VOL_DOWN
113 #define WPS_RC_EXIT BUTTON_RC_STOP
115 #elif CONFIG_KEYPAD == ONDIO_PAD
116 #define WPS_NEXT (BUTTON_RIGHT | BUTTON_REL)
117 #define WPS_NEXT_PRE BUTTON_RIGHT
118 #define WPS_PREV (BUTTON_LEFT | BUTTON_REL)
119 #define WPS_PREV_PRE BUTTON_LEFT
120 #define WPS_FFWD (BUTTON_RIGHT | BUTTON_REPEAT)
121 #define WPS_REW (BUTTON_LEFT | BUTTON_REPEAT)
122 #define WPS_INCVOL BUTTON_UP
123 #define WPS_DECVOL BUTTON_DOWN
124 #define WPS_PAUSE BUTTON_OFF
125 #define WPS_MENU (BUTTON_MENU | BUTTON_REPEAT)
126 #define WPS_BROWSE (BUTTON_MENU | BUTTON_REL)
127 #define WPS_BROWSE_PRE BUTTON_MENU
128 #define WPS_KEYLOCK (BUTTON_MENU | BUTTON_DOWN)
133 return true if screen restore is needed
134 return false otherwise
136 static bool setvol(void)
138 if (global_settings
.volume
< mpeg_sound_min(SOUND_VOLUME
))
139 global_settings
.volume
= mpeg_sound_min(SOUND_VOLUME
);
140 if (global_settings
.volume
> mpeg_sound_max(SOUND_VOLUME
))
141 global_settings
.volume
= mpeg_sound_max(SOUND_VOLUME
);
142 mpeg_sound_set(SOUND_VOLUME
, global_settings
.volume
);
144 wps_refresh(id3
, nid3
, 0, WPS_REFRESH_NON_STATIC
);
146 #ifdef HAVE_LCD_CHARCELLS
147 splash(0, false, "Vol: %d %% ",
148 mpeg_val2phys(SOUND_VOLUME
, global_settings
.volume
));
154 static void display_keylock_text(bool locked
)
158 #ifdef HAVE_LCD_CHARCELLS
160 s
= str(LANG_KEYLOCK_ON_PLAYER
);
162 s
= str(LANG_KEYLOCK_OFF_PLAYER
);
165 s
= str(LANG_KEYLOCK_ON_RECORDER
);
167 s
= str(LANG_KEYLOCK_OFF_RECORDER
);
172 static bool ffwd_rew(int button
)
174 static const int ff_rew_steps
[] = {
175 1000, 2000, 3000, 4000,
176 5000, 6000, 8000, 10000,
177 15000, 20000, 25000, 30000,
181 unsigned int step
= 0; /* current ff/rewind step */
182 unsigned int max_step
= 0; /* maximum ff/rewind step */
183 int ff_rewind_count
= 0; /* current ff/rewind count (in ticks) */
184 int direction
= -1; /* forward=1 or backward=-1 */
185 long accel_tick
= 0; /* next time at which to bump the step size */
198 /* fast forwarding, calc max step relative to end */
200 (id3
->length
- (id3
->elapsed
+ ff_rewind_count
)) *
201 FF_REWIND_MAX_PERCENT
/ 100;
205 /* rewinding, calc max step relative to start */
206 max_step
= (id3
->elapsed
+ ff_rewind_count
) *
207 FF_REWIND_MAX_PERCENT
/ 100;
210 max_step
= MAX(max_step
, MIN_FF_REWIND_STEP
);
215 ff_rewind_count
+= step
* direction
;
217 if (global_settings
.ff_rewind_accel
!= 0 &&
218 current_tick
>= accel_tick
)
221 accel_tick
= current_tick
+
222 global_settings
.ff_rewind_accel
*HZ
;
227 if ( (mpeg_status() & MPEG_STATUS_PLAY
) &&
232 #if CONFIG_KEYPAD == PLAYER_PAD
236 status_set_ffmode(STATUS_FASTFORWARD
);
238 status_set_ffmode(STATUS_FASTBACKWARD
);
242 step
= ff_rew_steps
[global_settings
.ff_rewind_min_step
];
244 accel_tick
= current_tick
+
245 global_settings
.ff_rewind_accel
*HZ
;
252 if ((id3
->elapsed
+ ff_rewind_count
) > id3
->length
)
253 ff_rewind_count
= id3
->length
- id3
->elapsed
;
256 if ((int)(id3
->elapsed
+ ff_rewind_count
) < 0)
257 ff_rewind_count
= -id3
->elapsed
;
260 if(wps_time_countup
== false)
261 wps_refresh(id3
, nid3
, -ff_rewind_count
,
262 WPS_REFRESH_PLAYER_PROGRESS
|
263 WPS_REFRESH_DYNAMIC
);
265 wps_refresh(id3
, nid3
, ff_rewind_count
,
266 WPS_REFRESH_PLAYER_PROGRESS
|
267 WPS_REFRESH_DYNAMIC
);
273 mpeg_ff_rewind(id3
->elapsed
+ff_rewind_count
);
276 status_set_ffmode(0);
279 #ifdef HAVE_LCD_CHARCELLS
280 wps_display(id3
, nid3
);
286 if(default_event_handler(button
) == SYS_USB_CONNECTED
) {
287 status_set_ffmode(0);
294 button
= button_get(true);
297 /* let mpeg thread update id3->elapsed before calling wps_refresh */
299 wps_refresh(id3
, nid3
, 0, WPS_REFRESH_ALL
);
303 static bool update(void)
305 bool track_changed
= mpeg_has_changed_track();
306 bool retcode
= false;
308 nid3
= mpeg_next_track();
312 id3
= mpeg_current_track();
313 if (wps_display(id3
, nid3
))
316 wps_refresh(id3
, nid3
, 0, WPS_REFRESH_ALL
);
319 memcpy(current_track_path
, id3
->path
, sizeof(current_track_path
));
323 wps_refresh(id3
, nid3
, 0, WPS_REFRESH_NON_STATIC
);
327 /* save resume data */
329 global_settings
.resume
&&
330 global_settings
.resume_offset
!= id3
->offset
) {
331 DEBUGF("R%X,%X (%X)\n", global_settings
.resume_offset
,
334 if (!playlist_get_resume_info(&global_settings
.resume_index
))
336 global_settings
.resume_offset
= id3
->offset
;
340 else if ( !id3
&& track_changed
) {
341 global_settings
.resume_index
= -1;
342 global_settings
.resume_offset
= -1;
349 static void fade(bool fade_in
)
353 int current_volume
= 20;
355 /* zero out the sound */
356 mpeg_sound_set(SOUND_VOLUME
, current_volume
);
358 sleep(HZ
/10); /* let mpeg thread run */
361 while (current_volume
< global_settings
.volume
) {
364 mpeg_sound_set(SOUND_VOLUME
, current_volume
);
366 mpeg_sound_set(SOUND_VOLUME
, global_settings
.volume
);
370 int current_volume
= global_settings
.volume
;
372 while (current_volume
> 20) {
375 mpeg_sound_set(SOUND_VOLUME
, current_volume
);
378 sleep(HZ
/5); /* let mpeg thread run */
380 /* reset volume to what it was before the fade */
381 mpeg_sound_set(SOUND_VOLUME
, global_settings
.volume
);
386 static void waitfor_nokey(void)
388 /* wait until all keys are released */
389 while (button_get(false) != BUTTON_NONE
)
393 /* demonstrates showing different formats from playtune */
396 int button
= 0, lastbutton
= 0;
397 bool ignore_keyup
= true;
398 bool restore
= false;
399 long restoretimer
= 0; /* timer to delay screen redraw temporarily */
401 bool update_track
= false;
404 current_track_path
[0] = '\0';
406 #ifdef HAVE_LCD_CHARCELLS
407 status_set_audio(true);
408 status_set_param(false);
410 if(global_settings
.statusbar
)
411 lcd_setmargins(0, STATUSBAR_HEIGHT
);
413 lcd_setmargins(0, 0);
418 if(mpeg_status() & MPEG_STATUS_PLAY
)
420 id3
= mpeg_current_track();
421 nid3
= mpeg_next_track();
423 if (wps_display(id3
, nid3
))
425 wps_refresh(id3
, nid3
, 0, WPS_REFRESH_ALL
);
427 memcpy(current_track_path
, id3
->path
, sizeof(current_track_path
));
435 bool mpeg_paused
= (mpeg_status() & MPEG_STATUS_PAUSE
)?true:false;
437 /* did someone else (i.e power thread) change mpeg pause mode? */
438 if (paused
!= mpeg_paused
) {
439 paused
= mpeg_paused
;
441 /* if another thread paused mpeg, we are probably in car mode,
442 about to shut down. lets save the settings. */
443 if (paused
&& global_settings
.resume
) {
451 #ifdef HAVE_LCD_BITMAP
452 /* when the peak meter is enabled we want to have a
453 few extra updates to make it look smooth. On the
454 other hand we don't want to waste energy if it
456 if (peak_meter_enabled
) {
459 /* In high performance mode we read out the mas as
460 often as we can. There is no sleep for cpu */
461 if (global_settings
.peak_meter_performance
) {
462 long next_refresh
= current_tick
;
463 long next_big_refresh
= current_tick
+ HZ
/ 5;
464 button
= BUTTON_NONE
;
465 while (!TIME_AFTER(current_tick
, next_big_refresh
)) {
466 button
= button_get(false);
467 if (button
!= BUTTON_NONE
) {
473 if (TIME_AFTER(current_tick
, next_refresh
)) {
474 wps_refresh(id3
, nid3
, 0, WPS_REFRESH_PEAK_METER
);
475 next_refresh
= current_tick
+ HZ
/ peak_meter_fps
;
480 /* In energy saver mode the cpu may sleep a
481 little bit while waiting for buttons */
483 for (i
= 0; i
< 4; i
++) {
484 button
= button_get_w_tmo(HZ
/ peak_meter_fps
);
488 wps_refresh(id3
, nid3
, 0, WPS_REFRESH_PEAK_METER
);
493 /* The peak meter is disabled
494 -> no additional screen updates needed */
496 button
= button_get_w_tmo(HZ
/5);
499 button
= button_get_w_tmo(HZ
/5);
502 /* discard first event if it's a button release */
503 if (button
&& ignore_keyup
)
505 ignore_keyup
= false;
506 /* Negative events are system events */
507 if (button
>= 0 && button
& BUTTON_REL
)
512 /* ignore non-remote buttons when keys are locked */
515 (button
== BUTTON_NONE
) ||
516 ((button
& WPS_KEYLOCK
) == WPS_KEYLOCK
) ||
517 (button
& BUTTON_REMOTE
)
520 if (!(button
& BUTTON_REL
))
521 display_keylock_text(true);
523 button
= BUTTON_NONE
;
527 /* Exit if mpeg has stopped playing. This can happen if using the
528 sleep timer with the charger plugged or if starting a recording
536 #ifdef WPS_BROWSE_PRE
537 if (lastbutton
!= WPS_BROWSE_PRE
)
540 #ifdef HAVE_LCD_CHARCELLS
541 status_set_record(false);
542 status_set_audio(false);
546 /* set dir browser to current playing song */
547 if (global_settings
.browse_current
&&
548 current_track_path
[0] != '\0')
549 set_current_file(current_track_path
);
562 if ( global_settings
.fade_on_stop
)
570 if ( global_settings
.fade_on_stop
)
574 if (global_settings
.resume
) {
585 case WPS_INCVOL
| BUTTON_REPEAT
:
589 global_settings
.volume
++;
592 restoretimer
= current_tick
+ HZ
;
598 case WPS_DECVOL
| BUTTON_REPEAT
:
602 global_settings
.volume
--;
605 restoretimer
= current_tick
+ HZ
;
609 /* fast forward / rewind */
625 if (lastbutton
!= WPS_PREV_PRE
)
628 if (!id3
|| (id3
->elapsed
< 3*1000)) {
648 if (lastbutton
!= WPS_NEXT_PRE
)
654 /* menu key functions */
657 if (lastbutton
!= WPS_MENU_PRE
)
664 #ifdef HAVE_LCD_BITMAP
665 if (global_settings
.statusbar
)
666 lcd_setmargins(0, STATUSBAR_HEIGHT
);
668 lcd_setmargins(0, 0);
675 case WPS_KEYLOCK
| BUTTON_REPEAT
:
676 keys_locked
= !keys_locked
;
677 display_keylock_text(keys_locked
);
682 #if CONFIG_KEYPAD == RECORDER_PAD
685 if (quick_screen(CONTEXT_WPS
, BUTTON_F2
))
686 return SYS_USB_CONNECTED
;
690 /* screen settings */
692 if (quick_screen(CONTEXT_WPS
, BUTTON_F3
))
693 return SYS_USB_CONNECTED
;
698 case BUTTON_ON
| BUTTON_REPEAT
:
699 if (2 == pitch_screen())
700 return SYS_USB_CONNECTED
;
705 /* stop and exit wps */
722 case BUTTON_NONE
: /* Timeout */
727 if(default_event_handler(button
) == SYS_USB_CONNECTED
)
728 return SYS_USB_CONNECTED
;
736 /* set dir browser to current playing song */
737 if (global_settings
.browse_current
&&
738 current_track_path
[0] != '\0')
739 set_current_file(current_track_path
);
743 update_track
= false;
747 #ifdef HAVE_LCD_CHARCELLS
748 status_set_record(false);
749 status_set_audio(false);
751 if (global_settings
.fade_on_stop
)
755 bookmark_autobookmark();
758 /* Keys can be locked when exiting, so either unlock here
759 or implement key locking in tree.c too */
762 /* set dir browser to current playing song */
763 if (global_settings
.browse_current
&&
764 current_track_path
[0] != '\0')
765 set_current_file(current_track_path
);
774 ((restoretimer
== 0) ||
775 (restoretimer
< current_tick
)))
779 if (wps_display(id3
, nid3
))
781 /* set dir browser to current playing song */
782 if (global_settings
.browse_current
&&
783 current_track_path
[0] != '\0')
784 set_current_file(current_track_path
);
790 wps_refresh(id3
, nid3
, 0, WPS_REFRESH_NON_STATIC
);
792 if (button
!= BUTTON_NONE
)
795 return 0; /* unreachable - just to reduce compiler warnings */