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"
51 #define FF_REWIND_MAX_PERCENT 3 /* cap ff/rewind step size at max % of file */
52 /* 3% of 30min file == 54s step size */
53 #define MIN_FF_REWIND_STEP 500
55 bool keys_locked
= false;
56 static bool ff_rewind
= false;
57 static bool paused
= false;
58 static struct mp3entry
* id3
= NULL
;
59 static struct mp3entry
* nid3
= NULL
;
60 static char current_track_path
[MAX_PATH
+1];
62 #if defined(HAVE_PLAYER_KEYPAD) || defined(HAVE_NEO_KEYPAD)
63 void player_change_volume(int button
)
73 case BUTTON_MENU
| BUTTON_RIGHT
:
74 case BUTTON_MENU
| BUTTON_RIGHT
| BUTTON_REPEAT
:
75 global_settings
.volume
++;
76 if(global_settings
.volume
> mpeg_sound_max(SOUND_VOLUME
))
77 global_settings
.volume
= mpeg_sound_max(SOUND_VOLUME
);
78 mpeg_sound_set(SOUND_VOLUME
, global_settings
.volume
);
79 wps_refresh(id3
, nid3
, 0, WPS_REFRESH_NON_STATIC
);
83 case BUTTON_MENU
| BUTTON_LEFT
:
84 case BUTTON_MENU
| BUTTON_LEFT
| BUTTON_REPEAT
:
85 global_settings
.volume
--;
86 if(global_settings
.volume
< mpeg_sound_min(SOUND_VOLUME
))
87 global_settings
.volume
= mpeg_sound_min(SOUND_VOLUME
);
88 mpeg_sound_set(SOUND_VOLUME
, global_settings
.volume
);
89 wps_refresh(id3
, nid3
, 0, WPS_REFRESH_NON_STATIC
);
93 case BUTTON_MENU
| BUTTON_REL
:
94 case BUTTON_MENU
| BUTTON_LEFT
| BUTTON_REL
:
95 case BUTTON_MENU
| BUTTON_RIGHT
| BUTTON_REL
:
100 snprintf(buffer
,sizeof(buffer
),"Vol: %d %% ",
101 mpeg_val2phys(SOUND_VOLUME
, global_settings
.volume
));
103 #ifdef HAVE_LCD_CHARCELLS
104 lcd_puts(0, 0, buffer
);
106 lcd_puts(2, 3, buffer
);
112 button
= button_get(true);
114 wps_refresh(id3
, nid3
, 0, WPS_REFRESH_ALL
);
118 void display_keylock_text(bool locked
)
122 #ifdef HAVE_LCD_CHARCELLS
124 s
= str(LANG_KEYLOCK_ON_PLAYER
);
126 s
= str(LANG_KEYLOCK_OFF_PLAYER
);
129 s
= str(LANG_KEYLOCK_ON_RECORDER
);
131 s
= str(LANG_KEYLOCK_OFF_RECORDER
);
136 void display_mute_text(bool muted
)
140 #ifdef HAVE_LCD_CHARCELLS
142 lcd_puts(0, 0, str(LANG_MUTE_ON_PLAYER
));
144 lcd_puts(0, 0, str(LANG_MUTE_OFF_PLAYER
));
147 lcd_puts(2, 3, str(LANG_MUTE_ON_RECORDER
));
149 lcd_puts(2, 3, 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 */
299 case SYS_USB_CONNECTED
:
300 status_set_playmode(STATUS_STOP
);
309 static bool ffwd_rew(int button
)
311 static int ff_rew_steps
[] = {
312 1000, 2000, 3000, 4000,
313 5000, 6000, 8000, 10000,
314 15000, 20000, 25000, 30000,
318 unsigned int step
= 0; /* current ff/rewind step */
319 unsigned int max_step
= 0; /* maximum ff/rewind step */
320 int ff_rewind_count
= 0; /* current ff/rewind count (in ticks) */
321 int direction
= 1; /* forward=1 or backward=-1 */
322 long accel_tick
= 0; /* next time at which to bump the step size */
328 case BUTTON_LEFT
| BUTTON_REPEAT
:
329 case BUTTON_RIGHT
| BUTTON_REPEAT
:
334 /* fast forwarding, calc max step relative to end */
336 (id3
->length
- (id3
->elapsed
+ ff_rewind_count
)) *
337 FF_REWIND_MAX_PERCENT
/ 100;
341 /* rewinding, calc max step relative to start */
342 max_step
= (id3
->elapsed
+ ff_rewind_count
) *
343 FF_REWIND_MAX_PERCENT
/ 100;
346 max_step
= MAX(max_step
, MIN_FF_REWIND_STEP
);
351 ff_rewind_count
+= step
* direction
;
353 if (global_settings
.ff_rewind_accel
!= 0 &&
354 current_tick
>= accel_tick
)
357 accel_tick
= current_tick
+
358 global_settings
.ff_rewind_accel
*HZ
;
363 if ( (mpeg_status() & MPEG_STATUS_PLAY
) &&
368 #ifdef HAVE_PLAYER_KEYPAD
371 direction
= (button
& BUTTON_RIGHT
) ? 1 : -1;
374 status_set_playmode(STATUS_FASTFORWARD
);
376 status_set_playmode(STATUS_FASTBACKWARD
);
380 step
= ff_rew_steps
[global_settings
.ff_rewind_min_step
];
382 accel_tick
= current_tick
+
383 global_settings
.ff_rewind_accel
*HZ
;
390 if ((id3
->elapsed
+ ff_rewind_count
) > id3
->length
)
391 ff_rewind_count
= id3
->length
- id3
->elapsed
;
394 if ((int)(id3
->elapsed
+ ff_rewind_count
) < 0)
395 ff_rewind_count
= -id3
->elapsed
;
398 if(wps_time_countup
== false)
399 wps_refresh(id3
, nid3
, -ff_rewind_count
,
400 WPS_REFRESH_PLAYER_PROGRESS
|
401 WPS_REFRESH_DYNAMIC
);
403 wps_refresh(id3
, nid3
, ff_rewind_count
,
404 WPS_REFRESH_PLAYER_PROGRESS
|
405 WPS_REFRESH_DYNAMIC
);
409 case BUTTON_LEFT
| BUTTON_REL
:
410 case BUTTON_RIGHT
| BUTTON_REL
:
411 mpeg_ff_rewind(id3
->elapsed
+ff_rewind_count
);
415 status_set_playmode(STATUS_PAUSE
);
418 status_set_playmode(STATUS_PLAY
);
420 #ifdef HAVE_LCD_CHARCELLS
421 wps_display(id3
, nid3
);
426 case SYS_USB_CONNECTED
:
427 status_set_playmode(STATUS_STOP
);
434 button
= button_get(true);
437 /* let mpeg thread update id3->elapsed before calling wps_refresh */
439 wps_refresh(id3
, nid3
, 0, WPS_REFRESH_ALL
);
443 static bool update(void)
445 bool track_changed
= mpeg_has_changed_track();
446 bool retcode
= false;
448 nid3
= mpeg_next_track();
452 id3
= mpeg_current_track();
453 if (wps_display(id3
, nid3
))
456 wps_refresh(id3
, nid3
, 0, WPS_REFRESH_ALL
);
459 memcpy(current_track_path
, id3
->path
, sizeof(current_track_path
));
463 wps_refresh(id3
, nid3
, 0, WPS_REFRESH_NON_STATIC
);
467 /* save resume data */
469 global_settings
.resume
&&
470 global_settings
.resume_offset
!= id3
->offset
) {
471 DEBUGF("R%X,%X (%X)\n", global_settings
.resume_offset
,
474 if (!playlist_get_resume_info(&global_settings
.resume_index
))
476 global_settings
.resume_offset
= id3
->offset
;
480 else if ( !id3
&& track_changed
) {
481 global_settings
.resume_index
= -1;
482 global_settings
.resume_offset
= -1;
489 static bool menu(void)
491 static bool muted
= false;
495 #ifdef HAVE_LCD_CHARCELLS
496 status_set_param(true);
501 int button
= button_get(true);
505 #ifdef HAVE_RECORDER_KEYPAD
506 case BUTTON_F1
| BUTTON_REL
:
508 case BUTTON_MENU
| BUTTON_REL
:
511 if ( !last_button
&& !keys_locked
) {
516 #ifdef HAVE_LCD_BITMAP
517 if(global_settings
.statusbar
)
518 lcd_setmargins(0, STATUSBAR_HEIGHT
);
520 lcd_setmargins(0, 0);
527 case BUTTON_MENU
| BUTTON_PLAY
:
529 case BUTTON_F1
| BUTTON_PLAY
:
532 mpeg_sound_set(SOUND_VOLUME
, global_settings
.volume
);
534 mpeg_sound_set(SOUND_VOLUME
, 0);
536 #ifdef HAVE_LCD_CHARCELLS
537 status_set_param(false);
539 display_mute_text(muted
);
543 #ifdef HAVE_RECORDER_KEYPAD
544 case BUTTON_F1
| BUTTON_DOWN
:
546 case BUTTON_MENU
| BUTTON_STOP
:
548 keys_locked
= !keys_locked
;
549 display_keylock_text(keys_locked
);
551 while (button_get(false)); /* clear button queue */
556 case BUTTON_MENU
| BUTTON_LEFT
:
557 case BUTTON_MENU
| BUTTON_LEFT
| BUTTON_REPEAT
:
558 case BUTTON_MENU
| BUTTON_RIGHT
:
559 case BUTTON_MENU
| BUTTON_RIGHT
| BUTTON_REPEAT
:
560 player_change_volume(button
);
566 case BUTTON_MENU
| BUTTON_ON
:
567 status_set_param(true);
568 status_set_audio(true);
571 case BUTTON_F1
| BUTTON_ON
:
574 lcd_puts(0, 0, str(LANG_ID3_INFO
));
575 lcd_puts(0, 1, str(LANG_ID3_SCREEN
));
581 #ifdef HAVE_PLAYER_KEYPAD
582 status_set_param(false);
583 status_set_audio(true);
588 case SYS_USB_CONNECTED
:
589 status_set_playmode(STATUS_STOP
);
593 last_button
= button
;
596 #ifdef HAVE_LCD_CHARCELLS
597 status_set_param(false);
603 static void fade(bool fade_in
)
607 int current_volume
= 20;
609 /* zero out the sound */
610 mpeg_sound_set(SOUND_VOLUME
, current_volume
);
612 sleep(HZ
/10); /* let mpeg thread run */
615 while (current_volume
< global_settings
.volume
) {
618 mpeg_sound_set(SOUND_VOLUME
, current_volume
);
620 mpeg_sound_set(SOUND_VOLUME
, global_settings
.volume
);
624 int current_volume
= global_settings
.volume
;
626 while (current_volume
> 20) {
629 mpeg_sound_set(SOUND_VOLUME
, current_volume
);
632 sleep(HZ
/5); /* let mpeg thread run */
634 /* reset volume to what it was before the fade */
635 mpeg_sound_set(SOUND_VOLUME
, global_settings
.volume
);
640 /* demonstrates showing different formats from playtune */
643 int button
= 0, lastbutton
= 0;
644 bool ignore_keyup
= true;
645 bool restore
= false;
647 bool update_track
= false;
650 current_track_path
[0] = '\0';
652 #ifdef HAVE_LCD_CHARCELLS
653 status_set_audio(true);
654 status_set_param(false);
656 if(global_settings
.statusbar
)
657 lcd_setmargins(0, STATUSBAR_HEIGHT
);
659 lcd_setmargins(0, 0);
664 if(mpeg_status() & MPEG_STATUS_PLAY
)
666 id3
= mpeg_current_track();
667 nid3
= mpeg_next_track();
669 if (wps_display(id3
, nid3
))
671 wps_refresh(id3
, nid3
, 0, WPS_REFRESH_ALL
);
673 memcpy(current_track_path
, id3
->path
, sizeof(current_track_path
));
681 bool mpeg_paused
= (mpeg_status() & MPEG_STATUS_PAUSE
)?true:false;
682 status_set_playmode(paused
? STATUS_PAUSE
: STATUS_PLAY
);
684 /* did someone else (i.e power thread) change mpeg pause mode? */
685 if (paused
!= mpeg_paused
) {
686 paused
= mpeg_paused
;
688 /* if another thread paused mpeg, we are probably in car mode,
689 about to shut down. lets save the settings. */
690 if (paused
&& global_settings
.resume
) {
698 #ifdef HAVE_LCD_BITMAP
699 /* when the peak meter is enabled we want to have a
700 few extra updates to make it look smooth. On the
701 other hand we don't want to waste energy if it
703 if (peak_meter_enabled
) {
706 /* In high performance mode we read out the mas as
707 often as we can. There is no sleep for cpu */
708 if (global_settings
.peak_meter_performance
) {
709 long next_refresh
= current_tick
;
710 long next_big_refresh
= current_tick
+ HZ
/ 5;
711 button
= BUTTON_NONE
;
712 while (!TIME_AFTER(current_tick
, next_big_refresh
)) {
713 button
= button_get(false);
714 if (button
!= BUTTON_NONE
) {
720 if (TIME_AFTER(current_tick
, next_refresh
)) {
721 wps_refresh(id3
, nid3
, 0, WPS_REFRESH_PEAK_METER
);
722 next_refresh
= current_tick
+ HZ
/ peak_meter_fps
;
727 /* In energy saver mode the cpu may sleep a
728 little bit while waiting for buttons */
730 for (i
= 0; i
< 4; i
++) {
731 button
= button_get_w_tmo(HZ
/ peak_meter_fps
);
735 wps_refresh(id3
, nid3
, 0, WPS_REFRESH_PEAK_METER
);
740 /* The peak meter is disabled
741 -> no additional screen updates needed */
743 button
= button_get_w_tmo(HZ
/5);
746 button
= button_get_w_tmo(HZ
/5);
749 /* discard first event if it's a button release */
750 if (button
&& ignore_keyup
)
752 ignore_keyup
= false;
753 if (button
& BUTTON_REL
&& button
!= SYS_USB_CONNECTED
)
757 /* ignore non-remote buttons when keys are locked */
759 #ifdef HAVE_RECORDER_KEYPAD
760 ! ((button
& BUTTON_F1
) ||
762 ! ((button
& BUTTON_MENU
) ||
764 (button
== BUTTON_NONE
) ||
765 (button
== SYS_USB_CONNECTED
)
767 || (button
& BUTTON_REMOTE
)
771 while (button_get(false)); /* clear button queue */
772 display_keylock_text(true);
777 /* Exit if mpeg has stopped playing. This can happen if using the
778 sleep timer with the charger plugged or if starting a recording
787 #ifdef HAVE_RECORDER_KEYPAD
788 switch (on_screen()) {
791 return SYS_USB_CONNECTED
;
794 /* was on_screen used? */
797 /* pause may have been turned off by pitch screen */
798 if (paused
&& !(mpeg_status() & MPEG_STATUS_PAUSE
)) {
800 status_set_playmode(STATUS_PLAY
);
805 /* otherwise, exit to browser */
807 status_set_record(false);
808 status_set_audio(false);
812 /* set dir browser to current playing song */
813 if (global_settings
.browse_current
&&
814 current_track_path
[0] != '\0')
815 set_current_file(current_track_path
);
818 #ifdef HAVE_RECORDER_KEYPAD
822 #endif /* BUTTON_ON */
825 #ifdef BUTTON_RC_PLAY
831 status_set_playmode(STATUS_PLAY
);
832 if ( global_settings
.fade_on_stop
)
840 status_set_playmode(STATUS_PAUSE
);
841 if ( global_settings
.fade_on_stop
)
845 if (global_settings
.resume
) {
855 #ifdef HAVE_RECORDER_KEYPAD
857 case BUTTON_UP
| BUTTON_REPEAT
:
859 #ifdef BUTTON_RC_VOL_UP
860 case BUTTON_RC_VOL_UP
:
862 global_settings
.volume
++;
863 if(global_settings
.volume
> mpeg_sound_max(SOUND_VOLUME
))
864 global_settings
.volume
= mpeg_sound_max(SOUND_VOLUME
);
865 mpeg_sound_set(SOUND_VOLUME
, global_settings
.volume
);
871 #ifdef HAVE_RECORDER_KEYPAD
873 case BUTTON_DOWN
| BUTTON_REPEAT
:
875 #ifdef BUTTON_RC_VOL_DOWN
876 case BUTTON_RC_VOL_DOWN
:
878 global_settings
.volume
--;
879 if(global_settings
.volume
< mpeg_sound_min(SOUND_VOLUME
))
880 global_settings
.volume
= mpeg_sound_min(SOUND_VOLUME
);
881 mpeg_sound_set(SOUND_VOLUME
, global_settings
.volume
);
886 /* fast forward / rewind */
887 case BUTTON_LEFT
| BUTTON_REPEAT
:
888 case BUTTON_RIGHT
| BUTTON_REPEAT
:
893 #ifdef BUTTON_RC_LEFT
896 case BUTTON_LEFT
| BUTTON_REL
:
897 #ifdef HAVE_RECORDER_KEYPAD
898 if ((button
== (BUTTON_LEFT
| BUTTON_REL
)) &&
899 (lastbutton
!= BUTTON_LEFT
))
902 if (!id3
|| (id3
->elapsed
< 3*1000)) {
917 #ifdef BUTTON_RC_RIGHT
918 case BUTTON_RC_RIGHT
:
920 case BUTTON_RIGHT
| BUTTON_REL
:
921 #ifdef HAVE_RECORDER_KEYPAD
922 if ((button
== (BUTTON_RIGHT
| BUTTON_REL
)) &&
923 (lastbutton
!= BUTTON_RIGHT
))
929 /* menu key functions */
936 return SYS_USB_CONNECTED
;
942 #ifdef HAVE_RECORDER_KEYPAD
945 if (quick_screen(CONTEXT_WPS
, BUTTON_F2
))
946 return SYS_USB_CONNECTED
;
950 /* screen settings */
952 if (quick_screen(CONTEXT_WPS
, BUTTON_F3
))
953 return SYS_USB_CONNECTED
;
958 /* stop and exit wps */
960 case BUTTON_OFF
| BUTTON_REL
:
962 case BUTTON_STOP
| BUTTON_REL
:
963 if ( lastbutton
!= BUTTON_STOP
)
966 #ifdef BUTTON_RC_STOP
972 case SYS_USB_CONNECTED
:
973 status_set_playmode(STATUS_STOP
);
975 return SYS_USB_CONNECTED
;
977 case BUTTON_NONE
: /* Timeout */
986 /* set dir browser to current playing song */
987 if (global_settings
.browse_current
&&
988 current_track_path
[0] != '\0')
989 set_current_file(current_track_path
);
993 update_track
= false;
997 #ifdef HAVE_LCD_CHARCELLS
998 status_set_record(false);
999 status_set_audio(false);
1001 if (global_settings
.fade_on_stop
)
1005 bookmark_autobookmark();
1007 status_set_playmode(STATUS_STOP
);
1009 /* Keys can be locked when exiting, so either unlock here
1010 or implement key locking in tree.c too */
1013 /* set dir browser to current playing song */
1014 if (global_settings
.browse_current
&&
1015 current_track_path
[0] != '\0')
1016 set_current_file(current_track_path
);
1026 if (wps_display(id3
, nid3
))
1028 /* set dir browser to current playing song */
1029 if (global_settings
.browse_current
&&
1030 current_track_path
[0] != '\0')
1031 set_current_file(current_track_path
);
1037 wps_refresh(id3
, nid3
, 0, WPS_REFRESH_NON_STATIC
);
1039 if(button
!= BUTTON_NONE
)
1040 lastbutton
= button
;
1042 return 0; /* unreachable - just to reduce compiler warnings */