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 #if defined(HAVE_PLAYER_KEYPAD) || defined(HAVE_NEO_KEYPAD) || defined(HAVE_ONDIO_KEYPAD)
65 void player_change_volume(int button
)
75 case BUTTON_MENU
| BUTTON_RIGHT
:
76 case BUTTON_MENU
| BUTTON_RIGHT
| BUTTON_REPEAT
:
77 global_settings
.volume
++;
78 if(global_settings
.volume
> mpeg_sound_max(SOUND_VOLUME
))
79 global_settings
.volume
= mpeg_sound_max(SOUND_VOLUME
);
80 mpeg_sound_set(SOUND_VOLUME
, global_settings
.volume
);
81 wps_refresh(id3
, nid3
, 0, WPS_REFRESH_NON_STATIC
);
85 case BUTTON_MENU
| BUTTON_LEFT
:
86 case BUTTON_MENU
| BUTTON_LEFT
| BUTTON_REPEAT
:
87 global_settings
.volume
--;
88 if(global_settings
.volume
< mpeg_sound_min(SOUND_VOLUME
))
89 global_settings
.volume
= mpeg_sound_min(SOUND_VOLUME
);
90 mpeg_sound_set(SOUND_VOLUME
, global_settings
.volume
);
91 wps_refresh(id3
, nid3
, 0, WPS_REFRESH_NON_STATIC
);
95 case BUTTON_MENU
| BUTTON_REL
:
96 case BUTTON_MENU
| BUTTON_LEFT
| BUTTON_REL
:
97 case BUTTON_MENU
| BUTTON_RIGHT
| BUTTON_REL
:
102 snprintf(buffer
,sizeof(buffer
),"Vol: %d %% ",
103 mpeg_val2phys(SOUND_VOLUME
, global_settings
.volume
));
105 #ifdef HAVE_LCD_CHARCELLS
106 lcd_puts(0, 0, buffer
);
108 lcd_puts(2, 3, buffer
);
114 button
= button_get(true);
116 wps_refresh(id3
, nid3
, 0, WPS_REFRESH_ALL
);
120 void display_keylock_text(bool locked
)
124 #ifdef HAVE_LCD_CHARCELLS
126 s
= str(LANG_KEYLOCK_ON_PLAYER
);
128 s
= str(LANG_KEYLOCK_OFF_PLAYER
);
131 s
= str(LANG_KEYLOCK_ON_RECORDER
);
133 s
= str(LANG_KEYLOCK_OFF_RECORDER
);
138 void display_mute_text(bool muted
)
142 #ifdef HAVE_LCD_CHARCELLS
144 s
= str(LANG_MUTE_ON_PLAYER
);
146 s
= str(LANG_MUTE_OFF_PLAYER
);
149 s
= str(LANG_MUTE_ON_RECORDER
);
151 s
= str(LANG_MUTE_OFF_RECORDER
);
156 bool browse_id3(void)
162 char scroll_text
[MAX_PATH
];
164 if (!(mpeg_status() & MPEG_STATUS_PLAY
))
174 lcd_puts(0, 0, str(LANG_ID3_TITLE
));
175 lcd_puts_scroll(0, 1, id3
->title
? id3
->title
:
176 (char*)str(LANG_ID3_NO_TITLE
));
180 lcd_puts(0, 0, str(LANG_ID3_ARTIST
));
181 lcd_puts_scroll(0, 1,
182 id3
->artist
? id3
->artist
:
183 (char*)str(LANG_ID3_NO_ARTIST
));
187 lcd_puts(0, 0, str(LANG_ID3_ALBUM
));
188 lcd_puts_scroll(0, 1, id3
->album
? id3
->album
:
189 (char*)str(LANG_ID3_NO_ALBUM
));
193 lcd_puts(0, 0, str(LANG_ID3_TRACKNUM
));
196 snprintf(scroll_text
,sizeof(scroll_text
), "%d",
198 lcd_puts_scroll(0, 1, scroll_text
);
201 lcd_puts_scroll(0, 1, str(LANG_ID3_NO_TRACKNUM
));
205 lcd_puts(0, 0, str(LANG_ID3_GENRE
));
206 lcd_puts_scroll(0, 1,
209 (char*)str(LANG_ID3_NO_INFO
));
213 lcd_puts(0, 0, str(LANG_ID3_YEAR
));
215 snprintf(scroll_text
,sizeof(scroll_text
), "%d",
217 lcd_puts_scroll(0, 1, scroll_text
);
220 lcd_puts_scroll(0, 1, str(LANG_ID3_NO_INFO
));
224 lcd_puts(0, 0, str(LANG_ID3_LENGHT
));
225 snprintf(scroll_text
,sizeof(scroll_text
), "%d:%02d",
227 id3
->length
% 60000 / 1000 );
228 lcd_puts(0, 1, scroll_text
);
232 lcd_puts(0, 0, str(LANG_ID3_PLAYLIST
));
233 snprintf(scroll_text
,sizeof(scroll_text
), "%d/%d",
234 playlist_get_display_index(), playlist_amount());
235 lcd_puts_scroll(0, 1, scroll_text
);
240 lcd_puts(0, 0, str(LANG_ID3_BITRATE
));
241 snprintf(scroll_text
,sizeof(scroll_text
), "%d kbps",
243 lcd_puts(0, 1, scroll_text
);
247 lcd_puts(0, 0, str(LANG_ID3_FRECUENCY
));
248 snprintf(scroll_text
,sizeof(scroll_text
), "%d Hz",
250 lcd_puts(0, 1, scroll_text
);
254 lcd_puts(0, 0, str(LANG_ID3_PATH
));
255 lcd_puts_scroll(0, 1, id3
->path
);
260 button
= button_get(true);
265 #ifdef HAVE_RECORDER_KEYPAD
275 #ifdef HAVE_RECORDER_KEYPAD
278 if (menu_pos
< menu_max
)
294 /* eat release event */
300 if(default_event_handler(button
) == SYS_USB_CONNECTED
)
308 static bool ffwd_rew(int button
)
310 static const int ff_rew_steps
[] = {
311 1000, 2000, 3000, 4000,
312 5000, 6000, 8000, 10000,
313 15000, 20000, 25000, 30000,
317 unsigned int step
= 0; /* current ff/rewind step */
318 unsigned int max_step
= 0; /* maximum ff/rewind step */
319 int ff_rewind_count
= 0; /* current ff/rewind count (in ticks) */
320 int direction
= 1; /* forward=1 or backward=-1 */
321 long accel_tick
= 0; /* next time at which to bump the step size */
327 case BUTTON_LEFT
| BUTTON_REPEAT
:
328 case BUTTON_RIGHT
| BUTTON_REPEAT
:
333 /* fast forwarding, calc max step relative to end */
335 (id3
->length
- (id3
->elapsed
+ ff_rewind_count
)) *
336 FF_REWIND_MAX_PERCENT
/ 100;
340 /* rewinding, calc max step relative to start */
341 max_step
= (id3
->elapsed
+ ff_rewind_count
) *
342 FF_REWIND_MAX_PERCENT
/ 100;
345 max_step
= MAX(max_step
, MIN_FF_REWIND_STEP
);
350 ff_rewind_count
+= step
* direction
;
352 if (global_settings
.ff_rewind_accel
!= 0 &&
353 current_tick
>= accel_tick
)
356 accel_tick
= current_tick
+
357 global_settings
.ff_rewind_accel
*HZ
;
362 if ( (mpeg_status() & MPEG_STATUS_PLAY
) &&
367 #ifdef HAVE_PLAYER_KEYPAD
370 direction
= (button
& BUTTON_RIGHT
) ? 1 : -1;
373 status_set_ffmode(STATUS_FASTFORWARD
);
375 status_set_ffmode(STATUS_FASTBACKWARD
);
379 step
= ff_rew_steps
[global_settings
.ff_rewind_min_step
];
381 accel_tick
= current_tick
+
382 global_settings
.ff_rewind_accel
*HZ
;
389 if ((id3
->elapsed
+ ff_rewind_count
) > id3
->length
)
390 ff_rewind_count
= id3
->length
- id3
->elapsed
;
393 if ((int)(id3
->elapsed
+ ff_rewind_count
) < 0)
394 ff_rewind_count
= -id3
->elapsed
;
397 if(wps_time_countup
== false)
398 wps_refresh(id3
, nid3
, -ff_rewind_count
,
399 WPS_REFRESH_PLAYER_PROGRESS
|
400 WPS_REFRESH_DYNAMIC
);
402 wps_refresh(id3
, nid3
, ff_rewind_count
,
403 WPS_REFRESH_PLAYER_PROGRESS
|
404 WPS_REFRESH_DYNAMIC
);
408 case BUTTON_LEFT
| BUTTON_REL
:
409 case BUTTON_RIGHT
| BUTTON_REL
:
410 mpeg_ff_rewind(id3
->elapsed
+ff_rewind_count
);
413 status_set_ffmode(0);
416 #ifdef HAVE_LCD_CHARCELLS
417 wps_display(id3
, nid3
);
423 if(default_event_handler(button
) == SYS_USB_CONNECTED
) {
424 status_set_ffmode(0);
431 button
= button_get(true);
434 /* let mpeg thread update id3->elapsed before calling wps_refresh */
436 wps_refresh(id3
, nid3
, 0, WPS_REFRESH_ALL
);
440 static bool update(void)
442 bool track_changed
= mpeg_has_changed_track();
443 bool retcode
= false;
445 nid3
= mpeg_next_track();
449 id3
= mpeg_current_track();
450 if (wps_display(id3
, nid3
))
453 wps_refresh(id3
, nid3
, 0, WPS_REFRESH_ALL
);
456 memcpy(current_track_path
, id3
->path
, sizeof(current_track_path
));
460 wps_refresh(id3
, nid3
, 0, WPS_REFRESH_NON_STATIC
);
464 /* save resume data */
466 global_settings
.resume
&&
467 global_settings
.resume_offset
!= id3
->offset
) {
468 DEBUGF("R%X,%X (%X)\n", global_settings
.resume_offset
,
471 if (!playlist_get_resume_info(&global_settings
.resume_index
))
473 global_settings
.resume_offset
= id3
->offset
;
477 else if ( !id3
&& track_changed
) {
478 global_settings
.resume_index
= -1;
479 global_settings
.resume_offset
= -1;
486 static bool menu(void)
488 static bool muted
= false;
492 #ifdef HAVE_LCD_CHARCELLS
493 status_set_param(true);
498 int button
= button_get(true);
500 /* these are never locked */
504 #ifdef HAVE_RECORDER_KEYPAD
505 case BUTTON_F1
| BUTTON_DOWN
:
507 case BUTTON_MENU
| BUTTON_STOP
:
509 keys_locked
= !keys_locked
;
510 display_keylock_text(keys_locked
);
512 while (button_get(false)); /* clear button queue */
516 if(default_event_handler(button
) == SYS_USB_CONNECTED
) {
524 display_keylock_text(true);
530 #ifdef HAVE_RECORDER_KEYPAD
531 case BUTTON_F1
| BUTTON_REL
:
533 case BUTTON_MENU
| BUTTON_REL
:
536 if ( !last_button
&& !keys_locked
) {
541 #ifdef HAVE_LCD_BITMAP
542 if(global_settings
.statusbar
)
543 lcd_setmargins(0, STATUSBAR_HEIGHT
);
545 lcd_setmargins(0, 0);
552 case BUTTON_MENU
| BUTTON_PLAY
:
554 case BUTTON_F1
| BUTTON_PLAY
:
557 mpeg_sound_set(SOUND_VOLUME
, global_settings
.volume
);
559 mpeg_sound_set(SOUND_VOLUME
, 0);
561 #ifdef HAVE_LCD_CHARCELLS
562 status_set_param(false);
564 display_mute_text(muted
);
569 case BUTTON_MENU
| BUTTON_LEFT
:
570 case BUTTON_MENU
| BUTTON_LEFT
| BUTTON_REPEAT
:
571 case BUTTON_MENU
| BUTTON_RIGHT
:
572 case BUTTON_MENU
| BUTTON_RIGHT
| BUTTON_REPEAT
:
573 player_change_volume(button
);
579 case BUTTON_MENU
| BUTTON_ON
:
580 #ifdef HAVE_LCD_CHARCELLS
581 status_set_param(true);
582 status_set_audio(true);
586 case BUTTON_F1
| BUTTON_ON
:
589 lcd_puts(0, 0, str(LANG_ID3_INFO
));
590 lcd_puts(0, 1, str(LANG_ID3_SCREEN
));
596 #ifdef HAVE_PLAYER_KEYPAD
597 status_set_param(false);
598 status_set_audio(true);
603 last_button
= button
;
606 #ifdef HAVE_LCD_CHARCELLS
607 status_set_param(false);
613 static void fade(bool fade_in
)
617 int current_volume
= 20;
619 /* zero out the sound */
620 mpeg_sound_set(SOUND_VOLUME
, current_volume
);
622 sleep(HZ
/10); /* let mpeg thread run */
625 while (current_volume
< global_settings
.volume
) {
628 mpeg_sound_set(SOUND_VOLUME
, current_volume
);
630 mpeg_sound_set(SOUND_VOLUME
, global_settings
.volume
);
634 int current_volume
= global_settings
.volume
;
636 while (current_volume
> 20) {
639 mpeg_sound_set(SOUND_VOLUME
, current_volume
);
642 sleep(HZ
/5); /* let mpeg thread run */
644 /* reset volume to what it was before the fade */
645 mpeg_sound_set(SOUND_VOLUME
, global_settings
.volume
);
650 /* demonstrates showing different formats from playtune */
653 int button
= 0, lastbutton
= 0;
654 bool ignore_keyup
= true;
655 bool restore
= false;
657 bool update_track
= false;
660 current_track_path
[0] = '\0';
662 #ifdef HAVE_LCD_CHARCELLS
663 status_set_audio(true);
664 status_set_param(false);
666 if(global_settings
.statusbar
)
667 lcd_setmargins(0, STATUSBAR_HEIGHT
);
669 lcd_setmargins(0, 0);
674 if(mpeg_status() & MPEG_STATUS_PLAY
)
676 id3
= mpeg_current_track();
677 nid3
= mpeg_next_track();
679 if (wps_display(id3
, nid3
))
681 wps_refresh(id3
, nid3
, 0, WPS_REFRESH_ALL
);
683 memcpy(current_track_path
, id3
->path
, sizeof(current_track_path
));
691 bool mpeg_paused
= (mpeg_status() & MPEG_STATUS_PAUSE
)?true:false;
693 /* did someone else (i.e power thread) change mpeg pause mode? */
694 if (paused
!= mpeg_paused
) {
695 paused
= mpeg_paused
;
697 /* if another thread paused mpeg, we are probably in car mode,
698 about to shut down. lets save the settings. */
699 if (paused
&& global_settings
.resume
) {
707 #ifdef HAVE_LCD_BITMAP
708 /* when the peak meter is enabled we want to have a
709 few extra updates to make it look smooth. On the
710 other hand we don't want to waste energy if it
712 if (peak_meter_enabled
) {
715 /* In high performance mode we read out the mas as
716 often as we can. There is no sleep for cpu */
717 if (global_settings
.peak_meter_performance
) {
718 long next_refresh
= current_tick
;
719 long next_big_refresh
= current_tick
+ HZ
/ 5;
720 button
= BUTTON_NONE
;
721 while (!TIME_AFTER(current_tick
, next_big_refresh
)) {
722 button
= button_get(false);
723 if (button
!= BUTTON_NONE
) {
729 if (TIME_AFTER(current_tick
, next_refresh
)) {
730 wps_refresh(id3
, nid3
, 0, WPS_REFRESH_PEAK_METER
);
731 next_refresh
= current_tick
+ HZ
/ peak_meter_fps
;
736 /* In energy saver mode the cpu may sleep a
737 little bit while waiting for buttons */
739 for (i
= 0; i
< 4; i
++) {
740 button
= button_get_w_tmo(HZ
/ peak_meter_fps
);
744 wps_refresh(id3
, nid3
, 0, WPS_REFRESH_PEAK_METER
);
749 /* The peak meter is disabled
750 -> no additional screen updates needed */
752 button
= button_get_w_tmo(HZ
/5);
755 button
= button_get_w_tmo(HZ
/5);
758 /* discard first event if it's a button release */
759 if (button
&& ignore_keyup
)
761 ignore_keyup
= false;
762 /* Negative events are system events */
763 if (button
>= 0 && button
& BUTTON_REL
)
767 /* ignore non-remote buttons when keys are locked */
770 #ifdef HAVE_RECORDER_KEYPAD
771 (button
& BUTTON_F1
) ||
773 (button
& BUTTON_MENU
) ||
775 (button
== BUTTON_NONE
)
777 || (button
& BUTTON_REMOTE
)
781 while (button_get(false)); /* clear button queue */
782 display_keylock_text(true);
787 /* Exit if mpeg has stopped playing. This can happen if using the
788 sleep timer with the charger plugged or if starting a recording
797 #ifdef HAVE_RECORDER_KEYPAD
798 switch (on_screen()) {
801 return SYS_USB_CONNECTED
;
804 /* was on_screen used? */
807 /* pause may have been turned off by pitch screen */
808 if (paused
&& !(mpeg_status() & MPEG_STATUS_PAUSE
)) {
814 /* otherwise, exit to browser */
816 #ifdef HAVE_LCD_CHARCELLS
817 status_set_record(false);
818 status_set_audio(false);
823 /* set dir browser to current playing song */
824 if (global_settings
.browse_current
&&
825 current_track_path
[0] != '\0')
826 set_current_file(current_track_path
);
829 #ifdef HAVE_RECORDER_KEYPAD
833 #endif /* BUTTON_ON */
836 #ifdef BUTTON_RC_PLAY
842 if ( global_settings
.fade_on_stop
)
850 if ( global_settings
.fade_on_stop
)
854 if (global_settings
.resume
) {
864 #ifdef HAVE_RECORDER_KEYPAD
866 case BUTTON_UP
| BUTTON_REPEAT
:
868 #ifdef BUTTON_RC_VOL_UP
869 case BUTTON_RC_VOL_UP
:
871 global_settings
.volume
++;
872 if(global_settings
.volume
> mpeg_sound_max(SOUND_VOLUME
))
873 global_settings
.volume
= mpeg_sound_max(SOUND_VOLUME
);
874 mpeg_sound_set(SOUND_VOLUME
, global_settings
.volume
);
880 #ifdef HAVE_RECORDER_KEYPAD
882 case BUTTON_DOWN
| BUTTON_REPEAT
:
884 #ifdef BUTTON_RC_VOL_DOWN
885 case BUTTON_RC_VOL_DOWN
:
887 global_settings
.volume
--;
888 if(global_settings
.volume
< mpeg_sound_min(SOUND_VOLUME
))
889 global_settings
.volume
= mpeg_sound_min(SOUND_VOLUME
);
890 mpeg_sound_set(SOUND_VOLUME
, global_settings
.volume
);
895 /* fast forward / rewind */
896 case BUTTON_LEFT
| BUTTON_REPEAT
:
897 case BUTTON_RIGHT
| BUTTON_REPEAT
:
902 #ifdef BUTTON_RC_LEFT
905 case BUTTON_LEFT
| BUTTON_REL
:
906 #ifdef HAVE_RECORDER_KEYPAD
907 if ((button
== (BUTTON_LEFT
| BUTTON_REL
)) &&
908 (lastbutton
!= BUTTON_LEFT
))
911 if (!id3
|| (id3
->elapsed
< 3*1000)) {
926 #ifdef BUTTON_RC_RIGHT
927 case BUTTON_RC_RIGHT
:
929 case BUTTON_RIGHT
| BUTTON_REL
:
930 #ifdef HAVE_RECORDER_KEYPAD
931 if ((button
== (BUTTON_RIGHT
| BUTTON_REL
)) &&
932 (lastbutton
!= BUTTON_RIGHT
))
938 /* menu key functions */
945 return SYS_USB_CONNECTED
;
951 #ifdef HAVE_RECORDER_KEYPAD
954 if (quick_screen(CONTEXT_WPS
, BUTTON_F2
))
955 return SYS_USB_CONNECTED
;
959 /* screen settings */
961 if (quick_screen(CONTEXT_WPS
, BUTTON_F3
))
962 return SYS_USB_CONNECTED
;
967 /* stop and exit wps */
969 case BUTTON_OFF
| BUTTON_REL
:
971 case BUTTON_STOP
| BUTTON_REL
:
972 if ( lastbutton
!= BUTTON_STOP
)
975 #ifdef BUTTON_RC_STOP
981 case BUTTON_NONE
: /* Timeout */
986 if(default_event_handler(button
) == SYS_USB_CONNECTED
)
987 return SYS_USB_CONNECTED
;
995 /* set dir browser to current playing song */
996 if (global_settings
.browse_current
&&
997 current_track_path
[0] != '\0')
998 set_current_file(current_track_path
);
1002 update_track
= false;
1006 #ifdef HAVE_LCD_CHARCELLS
1007 status_set_record(false);
1008 status_set_audio(false);
1010 if (global_settings
.fade_on_stop
)
1014 bookmark_autobookmark();
1017 /* Keys can be locked when exiting, so either unlock here
1018 or implement key locking in tree.c too */
1021 /* set dir browser to current playing song */
1022 if (global_settings
.browse_current
&&
1023 current_track_path
[0] != '\0')
1024 set_current_file(current_track_path
);
1034 if (wps_display(id3
, nid3
))
1036 /* set dir browser to current playing song */
1037 if (global_settings
.browse_current
&&
1038 current_track_path
[0] != '\0')
1039 set_current_file(current_track_path
);
1045 wps_refresh(id3
, nid3
, 0, WPS_REFRESH_NON_STATIC
);
1047 if(button
!= BUTTON_NONE
)
1048 lastbutton
= button
;
1050 return 0; /* unreachable - just to reduce compiler warnings */