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 == IRIVER_H100_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_ON
75 #define WPS_MENU (BUTTON_MODE | BUTTON_REL)
76 #define WPS_MENU_PRE BUTTON_MODE
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_MODE | BUTTON_DOWN)
81 #define WPS_ID3 (BUTTON_MODE | BUTTON_ON)
83 #elif CONFIG_KEYPAD == RECORDER_PAD
84 #define WPS_NEXT (BUTTON_RIGHT | BUTTON_REL)
85 #define WPS_NEXT_PRE BUTTON_RIGHT
86 #define WPS_PREV (BUTTON_LEFT | BUTTON_REL)
87 #define WPS_PREV_PRE BUTTON_LEFT
88 #define WPS_FFWD (BUTTON_RIGHT | BUTTON_REPEAT)
89 #define WPS_REW (BUTTON_LEFT | BUTTON_REPEAT)
90 #define WPS_INCVOL BUTTON_UP
91 #define WPS_DECVOL BUTTON_DOWN
92 #define WPS_PAUSE BUTTON_PLAY
93 #define WPS_MENU (BUTTON_F1 | BUTTON_REL)
94 #define WPS_MENU_PRE BUTTON_F1
95 #define WPS_BROWSE (BUTTON_ON | BUTTON_REL)
96 #define WPS_BROWSE_PRE BUTTON_ON
97 #define WPS_EXIT BUTTON_OFF
98 #define WPS_KEYLOCK (BUTTON_F1 | BUTTON_DOWN)
99 #define WPS_ID3 (BUTTON_F1 | BUTTON_ON)
101 #define WPS_RC_NEXT BUTTON_RC_RIGHT
102 #define WPS_RC_PREV BUTTON_RC_LEFT
103 #define WPS_RC_PAUSE BUTTON_RC_PLAY
104 #define WPS_RC_INCVOL BUTTON_RC_VOL_UP
105 #define WPS_RC_DECVOL BUTTON_RC_VOL_DOWN
106 #define WPS_RC_EXIT BUTTON_RC_STOP
108 #elif CONFIG_KEYPAD == PLAYER_PAD
109 #define WPS_NEXT (BUTTON_RIGHT | BUTTON_REL)
110 #define WPS_NEXT_PRE BUTTON_RIGHT
111 #define WPS_PREV (BUTTON_LEFT | BUTTON_REL)
112 #define WPS_PREV_PRE BUTTON_LEFT
113 #define WPS_FFWD (BUTTON_RIGHT | BUTTON_REPEAT)
114 #define WPS_REW (BUTTON_LEFT | BUTTON_REPEAT)
115 #define WPS_INCVOL (BUTTON_MENU | BUTTON_RIGHT)
116 #define WPS_DECVOL (BUTTON_MENU | BUTTON_LEFT)
117 #define WPS_PAUSE BUTTON_PLAY
118 #define WPS_MENU (BUTTON_MENU | BUTTON_REL)
119 #define WPS_MENU_PRE BUTTON_MENU
120 #define WPS_BROWSE (BUTTON_ON | BUTTON_REL)
121 #define WPS_BROWSE_PRE BUTTON_ON
122 #define WPS_EXIT BUTTON_STOP
123 #define WPS_KEYLOCK (BUTTON_MENU | BUTTON_STOP)
124 #define WPS_ID3 (BUTTON_MENU | BUTTON_ON)
126 #define WPS_RC_NEXT BUTTON_RC_RIGHT
127 #define WPS_RC_PREV BUTTON_RC_LEFT
128 #define WPS_RC_PAUSE BUTTON_RC_PLAY
129 #define WPS_RC_INCVOL BUTTON_RC_VOL_UP
130 #define WPS_RC_DECVOL BUTTON_RC_VOL_DOWN
131 #define WPS_RC_EXIT BUTTON_RC_STOP
133 #elif CONFIG_KEYPAD == ONDIO_PAD
134 #define WPS_NEXT (BUTTON_RIGHT | BUTTON_REL)
135 #define WPS_NEXT_PRE BUTTON_RIGHT
136 #define WPS_PREV (BUTTON_LEFT | BUTTON_REL)
137 #define WPS_PREV_PRE BUTTON_LEFT
138 #define WPS_FFWD (BUTTON_RIGHT | BUTTON_REPEAT)
139 #define WPS_REW (BUTTON_LEFT | BUTTON_REPEAT)
140 #define WPS_INCVOL BUTTON_UP
141 #define WPS_DECVOL BUTTON_DOWN
142 #define WPS_PAUSE BUTTON_OFF
143 #define WPS_MENU (BUTTON_MENU | BUTTON_REPEAT)
144 #define WPS_BROWSE (BUTTON_MENU | BUTTON_REL)
145 #define WPS_BROWSE_PRE BUTTON_MENU
146 #define WPS_KEYLOCK (BUTTON_MENU | BUTTON_DOWN)
147 #define WPS_EXIT (BUTTON_OFF | BUTTON_REPEAT)
152 return true if screen restore is needed
153 return false otherwise
155 static bool setvol(void)
157 if (global_settings
.volume
< mpeg_sound_min(SOUND_VOLUME
))
158 global_settings
.volume
= mpeg_sound_min(SOUND_VOLUME
);
159 if (global_settings
.volume
> mpeg_sound_max(SOUND_VOLUME
))
160 global_settings
.volume
= mpeg_sound_max(SOUND_VOLUME
);
161 mpeg_sound_set(SOUND_VOLUME
, global_settings
.volume
);
163 wps_refresh(id3
, nid3
, 0, WPS_REFRESH_NON_STATIC
);
165 #ifdef HAVE_LCD_CHARCELLS
166 splash(0, false, "Vol: %d %% ",
167 mpeg_val2phys(SOUND_VOLUME
, global_settings
.volume
));
173 static void display_keylock_text(bool locked
)
177 #ifdef HAVE_LCD_CHARCELLS
179 s
= str(LANG_KEYLOCK_ON_PLAYER
);
181 s
= str(LANG_KEYLOCK_OFF_PLAYER
);
184 s
= str(LANG_KEYLOCK_ON_RECORDER
);
186 s
= str(LANG_KEYLOCK_OFF_RECORDER
);
191 static bool ffwd_rew(int button
)
193 static const int ff_rew_steps
[] = {
194 1000, 2000, 3000, 4000,
195 5000, 6000, 8000, 10000,
196 15000, 20000, 25000, 30000,
200 unsigned int step
= 0; /* current ff/rewind step */
201 unsigned int max_step
= 0; /* maximum ff/rewind step */
202 int ff_rewind_count
= 0; /* current ff/rewind count (in ticks) */
203 int direction
= -1; /* forward=1 or backward=-1 */
204 long accel_tick
= 0; /* next time at which to bump the step size */
217 /* fast forwarding, calc max step relative to end */
219 (id3
->length
- (id3
->elapsed
+ ff_rewind_count
)) *
220 FF_REWIND_MAX_PERCENT
/ 100;
224 /* rewinding, calc max step relative to start */
225 max_step
= (id3
->elapsed
+ ff_rewind_count
) *
226 FF_REWIND_MAX_PERCENT
/ 100;
229 max_step
= MAX(max_step
, MIN_FF_REWIND_STEP
);
234 ff_rewind_count
+= step
* direction
;
236 if (global_settings
.ff_rewind_accel
!= 0 &&
237 current_tick
>= accel_tick
)
240 accel_tick
= current_tick
+
241 global_settings
.ff_rewind_accel
*HZ
;
246 if ( (mpeg_status() & MPEG_STATUS_PLAY
) &&
251 #if CONFIG_KEYPAD == PLAYER_PAD
255 status_set_ffmode(STATUS_FASTFORWARD
);
257 status_set_ffmode(STATUS_FASTBACKWARD
);
261 step
= ff_rew_steps
[global_settings
.ff_rewind_min_step
];
263 accel_tick
= current_tick
+
264 global_settings
.ff_rewind_accel
*HZ
;
271 if ((id3
->elapsed
+ ff_rewind_count
) > id3
->length
)
272 ff_rewind_count
= id3
->length
- id3
->elapsed
;
275 if ((int)(id3
->elapsed
+ ff_rewind_count
) < 0)
276 ff_rewind_count
= -id3
->elapsed
;
279 if(wps_time_countup
== false)
280 wps_refresh(id3
, nid3
, -ff_rewind_count
,
281 WPS_REFRESH_PLAYER_PROGRESS
|
282 WPS_REFRESH_DYNAMIC
);
284 wps_refresh(id3
, nid3
, ff_rewind_count
,
285 WPS_REFRESH_PLAYER_PROGRESS
|
286 WPS_REFRESH_DYNAMIC
);
292 mpeg_ff_rewind(id3
->elapsed
+ff_rewind_count
);
295 status_set_ffmode(0);
298 #ifdef HAVE_LCD_CHARCELLS
299 wps_display(id3
, nid3
);
305 if(default_event_handler(button
) == SYS_USB_CONNECTED
) {
306 status_set_ffmode(0);
313 button
= button_get(true);
316 /* let mpeg thread update id3->elapsed before calling wps_refresh */
318 wps_refresh(id3
, nid3
, 0, WPS_REFRESH_ALL
);
322 static bool update(void)
324 bool track_changed
= mpeg_has_changed_track();
325 bool retcode
= false;
327 nid3
= mpeg_next_track();
331 id3
= mpeg_current_track();
332 if (wps_display(id3
, nid3
))
335 wps_refresh(id3
, nid3
, 0, WPS_REFRESH_ALL
);
338 memcpy(current_track_path
, id3
->path
, sizeof(current_track_path
));
342 wps_refresh(id3
, nid3
, 0, WPS_REFRESH_NON_STATIC
);
346 /* save resume data */
348 global_settings
.resume
&&
349 global_settings
.resume_offset
!= id3
->offset
) {
351 if (!playlist_get_resume_info(&global_settings
.resume_index
))
353 global_settings
.resume_offset
= id3
->offset
;
357 else if ( !id3
&& track_changed
) {
358 global_settings
.resume_index
= -1;
359 global_settings
.resume_offset
= -1;
366 static void fade(bool fade_in
)
370 int current_volume
= 20;
372 /* zero out the sound */
373 mpeg_sound_set(SOUND_VOLUME
, current_volume
);
375 sleep(HZ
/10); /* let mpeg thread run */
378 while (current_volume
< global_settings
.volume
) {
381 mpeg_sound_set(SOUND_VOLUME
, current_volume
);
383 mpeg_sound_set(SOUND_VOLUME
, global_settings
.volume
);
387 int current_volume
= global_settings
.volume
;
389 while (current_volume
> 20) {
392 mpeg_sound_set(SOUND_VOLUME
, current_volume
);
395 sleep(HZ
/5); /* let mpeg thread run */
397 /* reset volume to what it was before the fade */
398 mpeg_sound_set(SOUND_VOLUME
, global_settings
.volume
);
403 static void waitfor_nokey(void)
405 /* wait until all keys are released */
406 while (button_get(false) != BUTTON_NONE
)
410 /* demonstrates showing different formats from playtune */
413 int button
= 0, lastbutton
= 0;
414 bool ignore_keyup
= true;
415 bool restore
= false;
416 long restoretimer
= 0; /* timer to delay screen redraw temporarily */
418 bool update_track
= false;
421 current_track_path
[0] = '\0';
423 #ifdef HAVE_LCD_CHARCELLS
424 status_set_audio(true);
425 status_set_param(false);
427 if(global_settings
.statusbar
)
428 lcd_setmargins(0, STATUSBAR_HEIGHT
);
430 lcd_setmargins(0, 0);
435 if(mpeg_status() & MPEG_STATUS_PLAY
)
437 id3
= mpeg_current_track();
438 nid3
= mpeg_next_track();
440 if (wps_display(id3
, nid3
))
442 wps_refresh(id3
, nid3
, 0, WPS_REFRESH_ALL
);
444 memcpy(current_track_path
, id3
->path
, sizeof(current_track_path
));
452 bool mpeg_paused
= (mpeg_status() & MPEG_STATUS_PAUSE
)?true:false;
454 /* did someone else (i.e power thread) change mpeg pause mode? */
455 if (paused
!= mpeg_paused
) {
456 paused
= mpeg_paused
;
458 /* if another thread paused mpeg, we are probably in car mode,
459 about to shut down. lets save the settings. */
460 if (paused
&& global_settings
.resume
) {
468 #ifdef HAVE_LCD_BITMAP
469 /* when the peak meter is enabled we want to have a
470 few extra updates to make it look smooth. On the
471 other hand we don't want to waste energy if it
473 if (peak_meter_enabled
) {
476 /* In high performance mode we read out the mas as
477 often as we can. There is no sleep for cpu */
478 if (global_settings
.peak_meter_performance
) {
479 long next_refresh
= current_tick
;
480 long next_big_refresh
= current_tick
+ HZ
/ 5;
481 button
= BUTTON_NONE
;
482 while (!TIME_AFTER(current_tick
, next_big_refresh
)) {
483 button
= button_get(false);
484 if (button
!= BUTTON_NONE
) {
490 if (TIME_AFTER(current_tick
, next_refresh
)) {
491 wps_refresh(id3
, nid3
, 0, WPS_REFRESH_PEAK_METER
);
492 next_refresh
= current_tick
+ HZ
/ peak_meter_fps
;
497 /* In energy saver mode the cpu may sleep a
498 little bit while waiting for buttons */
500 for (i
= 0; i
< 4; i
++) {
501 button
= button_get_w_tmo(HZ
/ peak_meter_fps
);
505 wps_refresh(id3
, nid3
, 0, WPS_REFRESH_PEAK_METER
);
510 /* The peak meter is disabled
511 -> no additional screen updates needed */
513 button
= button_get_w_tmo(HZ
/5);
516 button
= button_get_w_tmo(HZ
/5);
519 /* discard first event if it's a button release */
520 if (button
&& ignore_keyup
)
522 ignore_keyup
= false;
523 /* Negative events are system events */
524 if (button
>= 0 && button
& BUTTON_REL
)
529 /* ignore non-remote buttons when keys are locked */
532 (button
== BUTTON_NONE
) ||
533 ((button
& WPS_KEYLOCK
) == WPS_KEYLOCK
) ||
534 (button
& BUTTON_REMOTE
)
537 if (!(button
& BUTTON_REL
))
538 display_keylock_text(true);
540 button
= BUTTON_NONE
;
544 /* Exit if mpeg has stopped playing. This can happen if using the
545 sleep timer with the charger plugged or if starting a recording
553 #ifdef WPS_BROWSE_PRE
554 if (lastbutton
!= WPS_BROWSE_PRE
)
557 #ifdef HAVE_LCD_CHARCELLS
558 status_set_record(false);
559 status_set_audio(false);
563 /* set dir browser to current playing song */
564 if (global_settings
.browse_current
&&
565 current_track_path
[0] != '\0')
566 set_current_file(current_track_path
);
579 if ( global_settings
.fade_on_stop
)
587 if ( global_settings
.fade_on_stop
)
591 if (global_settings
.resume
) {
602 case WPS_INCVOL
| BUTTON_REPEAT
:
606 global_settings
.volume
++;
609 restoretimer
= current_tick
+ HZ
;
615 case WPS_DECVOL
| BUTTON_REPEAT
:
619 global_settings
.volume
--;
622 restoretimer
= current_tick
+ HZ
;
626 /* fast forward / rewind */
639 if (lastbutton
!= WPS_PREV_PRE
)
645 if (!id3
|| (id3
->elapsed
< 3*1000)) {
662 if (lastbutton
!= WPS_NEXT_PRE
)
671 /* menu key functions */
674 if (lastbutton
!= WPS_MENU_PRE
)
681 #ifdef HAVE_LCD_BITMAP
682 if (global_settings
.statusbar
)
683 lcd_setmargins(0, STATUSBAR_HEIGHT
);
685 lcd_setmargins(0, 0);
692 case WPS_KEYLOCK
| BUTTON_REPEAT
:
693 keys_locked
= !keys_locked
;
694 display_keylock_text(keys_locked
);
699 #if CONFIG_KEYPAD == RECORDER_PAD
702 if (quick_screen(CONTEXT_WPS
, BUTTON_F2
))
703 return SYS_USB_CONNECTED
;
707 /* screen settings */
709 if (quick_screen(CONTEXT_WPS
, BUTTON_F3
))
710 return SYS_USB_CONNECTED
;
715 case BUTTON_ON
| BUTTON_REPEAT
:
716 if (2 == pitch_screen())
717 return SYS_USB_CONNECTED
;
722 /* stop and exit wps */
739 case BUTTON_NONE
: /* Timeout */
744 if(default_event_handler(button
) == SYS_USB_CONNECTED
)
745 return SYS_USB_CONNECTED
;
753 /* set dir browser to current playing song */
754 if (global_settings
.browse_current
&&
755 current_track_path
[0] != '\0')
756 set_current_file(current_track_path
);
760 update_track
= false;
764 #ifdef HAVE_LCD_CHARCELLS
765 status_set_record(false);
766 status_set_audio(false);
768 if (global_settings
.fade_on_stop
)
772 bookmark_autobookmark();
775 /* Keys can be locked when exiting, so either unlock here
776 or implement key locking in tree.c too */
779 /* set dir browser to current playing song */
780 if (global_settings
.browse_current
&&
781 current_track_path
[0] != '\0')
782 set_current_file(current_track_path
);
791 ((restoretimer
== 0) ||
792 (restoretimer
< current_tick
)))
796 if (wps_display(id3
, nid3
))
798 /* set dir browser to current playing song */
799 if (global_settings
.browse_current
&&
800 current_track_path
[0] != '\0')
801 set_current_file(current_track_path
);
807 wps_refresh(id3
, nid3
, 0, WPS_REFRESH_NON_STATIC
);
809 if (button
!= BUTTON_NONE
)
812 return 0; /* unreachable - just to reduce compiler warnings */