1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2002 Jerome Kuptz
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
30 #include "backlight.h"
33 #include "filetypes.h"
38 #include "gwps-common.h"
45 #ifdef HAVE_LCD_BITMAP
47 #include "peakmeter.h"
59 #include "ata_idle_notify.h"
60 #include "root_menu.h"
62 #include "quickscreen.h"
63 #include "pitchscreen.h"
64 #include "appevents.h"
67 /* currently only one wps_state is needed */
68 struct wps_state wps_state
;
69 struct gui_wps gui_wps
[NB_SCREENS
];
70 static struct wps_data wps_datas
[NB_SCREENS
];
72 /* initial setup of wps_data */
73 static void wps_state_init(void);
75 static void prev_track(unsigned skip_thresh
)
77 if (!wps_state
.id3
|| (wps_state
.id3
->elapsed
< skip_thresh
*1000)) {
81 if (cuesheet_is_enabled() && wps_state
.id3
->cuesheet_type
)
83 curr_cuesheet_skip(-1, wps_state
.id3
->elapsed
);
87 if (!wps_state
.paused
)
88 #if (CONFIG_CODEC == SWCODEC)
89 audio_pre_ff_rewind();
96 #if (CONFIG_CODEC != SWCODEC)
97 if (!wps_state
.paused
)
103 static void next_track(void)
105 /* take care of if we're playing a cuesheet */
106 if (cuesheet_is_enabled() && wps_state
.id3
->cuesheet_type
)
108 if (curr_cuesheet_skip(1, wps_state
.id3
->elapsed
))
110 /* if the result was false, then we really want
111 to skip to the next track */
118 static int fix_wps_bars(void)
120 #ifdef HAVE_LCD_BITMAP
122 int wpsbars
= VP_SB_HIDE_ALL
;
125 bool draw
= global_settings
.statusbar
;
126 if (gui_wps
[i
].data
->wps_sb_tag
)
127 draw
= gui_wps
[i
].data
->show_sb_on_wps
;
129 wpsbars
|= (VP_SB_ONSCREEN(i
) | VP_SB_IGNORE_SETTING(i
));
133 return VP_SB_ALLSCREENS
;
137 long gui_wps_show(void)
140 bool restore
= false;
141 long restoretimer
= 0; /* timer to delay screen redraw temporarily */
143 bool bookmark
= false;
144 bool update_track
= false;
146 long last_left
= 0, last_right
= 0;
147 int wpsbars
, oldbars
;
151 #ifdef HAVE_LCD_CHARCELLS
152 status_set_audio(true);
153 status_set_param(false);
157 #endif /* LCD_DEPTH > 1 */
160 #if defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1
161 show_remote_wps_backdrop();
164 #ifdef AB_REPEAT_ENABLE
169 oldbars
= viewportmanager_set_statusbar(VP_SB_HIDE_ALL
);
170 if(audio_status() & AUDIO_STATUS_PLAY
)
172 wps_state
.id3
= audio_current_track();
173 wps_state
.nid3
= audio_next_track();
175 if (gui_wps_display())
181 wpsbars
= fix_wps_bars();
182 viewportmanager_set_statusbar(wpsbars
);
186 bool audio_paused
= (audio_status() & AUDIO_STATUS_PAUSE
)?true:false;
188 /* did someone else (i.e power thread) change audio pause mode? */
189 if (wps_state
.paused
!= audio_paused
) {
190 wps_state
.paused
= audio_paused
;
192 /* if another thread paused audio, we are probably in car mode,
193 about to shut down. lets save the settings. */
194 if (wps_state
.paused
) {
196 #if !defined(HAVE_RTC_RAM) && !defined(HAVE_SW_POWEROFF)
197 call_storage_idle_notifys(true);
202 #ifdef HAVE_LCD_BITMAP
203 /* when the peak meter is enabled we want to have a
204 few extra updates to make it look smooth. On the
205 other hand we don't want to waste energy if it
210 if(gui_wps
[i
].data
->peak_meter_enabled
)
215 long next_refresh
= current_tick
;
216 long next_big_refresh
= current_tick
+ HZ
/ 5;
217 button
= BUTTON_NONE
;
218 while (TIME_BEFORE(current_tick
, next_big_refresh
)) {
219 button
= get_action(CONTEXT_WPS
|ALLOW_SOFTLOCK
,TIMEOUT_NOBLOCK
);
220 if (button
!= ACTION_NONE
) {
224 sleep(0); /* Sleep until end of current tick. */
226 if (TIME_AFTER(current_tick
, next_refresh
)) {
229 if(gui_wps
[i
].data
->peak_meter_enabled
)
230 gui_wps_refresh(&gui_wps
[i
], 0,
231 WPS_REFRESH_PEAK_METER
);
232 next_refresh
+= HZ
/ PEAK_METER_FPS
;
239 /* The peak meter is disabled
240 -> no additional screen updates needed */
242 button
= get_action(CONTEXT_WPS
|ALLOW_SOFTLOCK
,HZ
/5);
245 button
= get_action(CONTEXT_WPS
|ALLOW_SOFTLOCK
,HZ
/5);
248 /* Exit if audio has stopped playing. This can happen if using the
249 sleep timer with the charger plugged or if starting a recording
253 /* The iPods/X5/M5 use a single button for the A-B mode markers,
254 defined as ACTION_WPSAB_SINGLE in their config files. */
255 #ifdef ACTION_WPSAB_SINGLE
256 if (!global_settings
.party_mode
&& ab_repeat_mode_enabled())
258 static int wps_ab_state
= 0;
259 if (button
== ACTION_WPSAB_SINGLE
)
261 switch (wps_ab_state
)
263 case 0: /* set the A spot */
264 button
= ACTION_WPS_ABSETA_PREVDIR
;
266 case 1: /* set the B spot */
267 button
= ACTION_WPS_ABSETB_NEXTDIR
;
270 button
= ACTION_WPS_ABRESET
;
273 wps_ab_state
= (wps_ab_state
+1) % 3;
279 case ACTION_WPS_CONTEXT
:
282 show_main_backdrop();
284 #if defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1
285 show_remote_main_backdrop();
287 viewportmanager_set_statusbar(oldbars
);
288 /* if music is stopped in the context menu we want to exit the wps */
289 if (onplay(wps_state
.id3
->path
,
290 FILE_ATTR_AUDIO
, CONTEXT_WPS
) == ONPLAY_MAINMENU
293 viewportmanager_set_statusbar(wpsbars
);
294 /* track might have changed */
300 #if defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1
301 show_remote_wps_backdrop();
307 case ACTION_WPS_BROWSE
:
308 #ifdef HAVE_LCD_CHARCELLS
309 status_set_record(false);
310 status_set_audio(false);
313 gui_wps
[i
].display
->stop_scroll();
314 return GO_TO_PREVIOUS_BROWSER
;
318 case ACTION_WPS_PLAY
:
319 if (global_settings
.party_mode
)
321 if ( wps_state
.paused
)
323 wps_state
.paused
= false;
324 if ( global_settings
.fade_on_stop
)
331 wps_state
.paused
= true;
332 if ( global_settings
.fade_on_stop
)
337 #if !defined(HAVE_RTC_RAM) && !defined(HAVE_SW_POWEROFF)
338 call_storage_idle_notifys(true); /* make sure resume info is saved */
344 case ACTION_WPS_VOLUP
:
347 gui_wps
[i
].data
->button_time_volume
= current_tick
;
348 global_settings
.volume
++;
353 if(update_onvol_change(&gui_wps
[i
]))
358 restoretimer
= current_tick
+ HZ
;
364 case ACTION_WPS_VOLDOWN
:
367 gui_wps
[i
].data
->button_time_volume
= current_tick
;
368 global_settings
.volume
--;
373 if(update_onvol_change(&gui_wps
[i
]))
378 restoretimer
= current_tick
+ HZ
;
383 OR next dir if this is straight after ACTION_WPS_SKIPNEXT
384 OR if skip length set, next track if straight after SKIPPREV. */
385 case ACTION_WPS_SEEKFWD
:
386 if (global_settings
.party_mode
)
388 if (global_settings
.skip_length
== 0
389 && current_tick
-last_right
< HZ
)
391 if (cuesheet_is_enabled() && wps_state
.id3
->cuesheet_type
)
400 else if (global_settings
.skip_length
> 0
401 && current_tick
-last_left
< HZ
) {
405 else ffwd_rew(ACTION_WPS_SEEKFWD
);
406 last_right
= last_left
= 0;
409 OR prev dir if this is straight after ACTION_WPS_SKIPPREV,
410 OR if skip length set, beg of track or prev track if this is
411 straight after SKIPPREV */
412 case ACTION_WPS_SEEKBACK
:
413 if (global_settings
.party_mode
)
415 if (global_settings
.skip_length
== 0
416 && current_tick
-last_left
< HZ
)
418 if (cuesheet_is_enabled() && wps_state
.id3
->cuesheet_type
)
420 if (!wps_state
.paused
)
421 #if (CONFIG_CODEC == SWCODEC)
422 audio_pre_ff_rewind();
433 else if (global_settings
.skip_length
> 0
434 && current_tick
-last_right
< HZ
)
436 prev_track(3+global_settings
.skip_length
);
439 else ffwd_rew(ACTION_WPS_SEEKBACK
);
440 last_left
= last_right
= 0;
444 case ACTION_WPS_SKIPPREV
:
445 if (global_settings
.party_mode
)
447 last_left
= current_tick
;
450 #ifdef AB_REPEAT_ENABLE
451 /* if we're in A/B repeat mode and the current position
452 is past the A marker, jump back to the A marker... */
453 if ( ab_repeat_mode_enabled() )
455 if ( ab_after_A_marker(wps_state
.id3
->elapsed
) )
457 ab_jump_to_A_marker();
459 #if (AB_REPEAT_ENABLE == 2)
465 /* ...otherwise, do it normally */
468 if (global_settings
.skip_length
> 0)
474 OR if skip length set, hop by predetermined amount. */
475 case ACTION_WPS_SKIPNEXT
:
476 if (global_settings
.party_mode
)
478 last_right
= current_tick
;
481 #ifdef AB_REPEAT_ENABLE
482 /* if we're in A/B repeat mode and the current position is
483 before the A marker, jump to the A marker... */
484 if ( ab_repeat_mode_enabled() )
486 if ( ab_before_A_marker(wps_state
.id3
->elapsed
) )
488 ab_jump_to_A_marker();
490 #if (AB_REPEAT_ENABLE == 2)
496 /* ...otherwise, do it normally */
499 if (global_settings
.skip_length
> 0)
503 /* next / prev directories */
504 /* and set A-B markers if in a-b mode */
505 case ACTION_WPS_ABSETB_NEXTDIR
:
506 if (global_settings
.party_mode
)
508 #if defined(AB_REPEAT_ENABLE)
509 if (ab_repeat_mode_enabled())
511 ab_set_B_marker(wps_state
.id3
->elapsed
);
512 ab_jump_to_A_marker();
518 if (global_settings
.skip_length
> 0)
520 else audio_next_dir();
523 case ACTION_WPS_ABSETA_PREVDIR
:
524 if (global_settings
.party_mode
)
526 #if defined(AB_REPEAT_ENABLE)
527 if (ab_repeat_mode_enabled())
528 ab_set_A_marker(wps_state
.id3
->elapsed
);
532 if (global_settings
.skip_length
> 0)
534 else audio_prev_dir();
537 /* menu key functions */
538 case ACTION_WPS_MENU
:
540 gui_wps
[i
].display
->stop_scroll();
545 #ifdef HAVE_QUICKSCREEN
546 case ACTION_WPS_QUICKSCREEN
:
548 viewportmanager_set_statusbar(oldbars
);
550 show_main_backdrop();
552 #if defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1
553 show_remote_main_backdrop();
555 if (quick_screen_quick(button
))
556 return SYS_USB_CONNECTED
;
557 wpsbars
= fix_wps_bars();
558 viewportmanager_set_statusbar(wpsbars
);
562 #if defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1
563 show_remote_wps_backdrop();
568 #endif /* HAVE_QUICKSCREEN */
570 /* screen settings */
574 viewportmanager_set_statusbar(oldbars
);
576 show_main_backdrop();
578 #if defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1
579 show_remote_main_backdrop();
581 if (quick_screen_f3(BUTTON_F3
))
582 return SYS_USB_CONNECTED
;
584 wpsbars
= fix_wps_bars();
585 viewportmanager_set_statusbar(wpsbars
);
588 #endif /* BUTTON_F3 */
591 #ifdef HAVE_PITCHSCREEN
592 case ACTION_WPS_PITCHSCREEN
:
594 viewportmanager_set_statusbar(oldbars
);
596 show_main_backdrop();
598 #if defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1
599 show_remote_main_backdrop();
601 if (1 == gui_syncpitchscreen_run())
602 return SYS_USB_CONNECTED
;
606 #if defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1
607 show_remote_wps_backdrop();
610 viewportmanager_set_statusbar(wpsbars
);
613 #endif /* HAVE_PITCHSCREEN */
615 #ifdef AB_REPEAT_ENABLE
616 /* reset A&B markers */
617 case ACTION_WPS_ABRESET
:
618 if (ab_repeat_mode_enabled())
624 #endif /* AB_REPEAT_ENABLE */
626 /* stop and exit wps */
627 case ACTION_WPS_STOP
:
628 if (global_settings
.party_mode
)
634 case ACTION_WPS_ID3SCREEN
:
636 viewportmanager_set_statusbar(oldbars
);
638 show_main_backdrop();
640 #if defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1
641 show_remote_main_backdrop();
647 #if defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1
648 show_remote_wps_backdrop();
651 viewportmanager_set_statusbar(wpsbars
);
655 case ACTION_REDRAW
: /* yes are locked, just redraw */
658 case ACTION_NONE
: /* Timeout */
660 ffwd_rew(button
); /* hopefully fix the ffw/rwd bug */
662 #ifdef HAVE_RECORDING
668 viewportmanager_set_statusbar(oldbars
);
670 show_main_backdrop();
672 #if defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1
673 show_remote_main_backdrop();
675 default_event_handler(SYS_POWEROFF
);
679 if(default_event_handler(button
) == SYS_USB_CONNECTED
)
689 if(update(&gui_wps
[i
]))
692 update_track
= false;
696 ((restoretimer
== 0) ||
697 (restoretimer
< current_tick
)))
701 if (gui_wps_display()) {
707 viewportmanager_set_statusbar(oldbars
);
708 #ifdef HAVE_LCD_CHARCELLS
709 status_set_record(false);
710 status_set_audio(false);
712 if (global_settings
.fade_on_stop
)
716 gui_wps
[i
].display
->stop_scroll();
718 bookmark_autobookmark();
720 #ifdef AB_REPEAT_ENABLE
723 #ifdef HAVE_RECORDING
724 if (button
== ACTION_WPS_REC
)
725 return GO_TO_RECSCREEN
;
727 if (global_settings
.browse_current
)
728 return GO_TO_PREVIOUS_BROWSER
;
729 return GO_TO_PREVIOUS
;
732 if (button
&& !IS_SYSEVENT(button
) )
735 return GO_TO_ROOT
; /* unreachable - just to reduce compiler warnings */
738 /* needs checking if needed end*/
742 static void wps_state_init(void)
744 wps_state
.ff_rewind
= false;
745 wps_state
.paused
= false;
746 wps_state
.id3
= NULL
;
747 wps_state
.nid3
= NULL
;
752 #ifdef HAVE_LCD_BITMAP
753 static void statusbar_toggle_handler(void *data
)
757 bool draw
= global_settings
.statusbar
;
761 struct wps_viewport
*vp
= &gui_wps
[i
].data
->viewports
[0];
762 if (gui_wps
[i
].data
->wps_sb_tag
)
763 draw
= gui_wps
[i
].data
->show_sb_on_wps
;
767 vp
->vp
.height
= screens
[i
].lcdheight
;
771 vp
->vp
.y
= STATUSBAR_HEIGHT
;
772 vp
->vp
.height
= screens
[i
].lcdheight
- STATUSBAR_HEIGHT
;
778 void gui_sync_wps_init(void)
783 wps_data_init(&wps_datas
[i
]);
785 wps_datas
[i
].wps_uses_albumart
= 0;
787 #ifdef HAVE_REMOTE_LCD
788 wps_datas
[i
].remote_wps
= (i
!= 0);
790 gui_wps
[i
].data
= &wps_datas
[i
];
791 gui_wps
[i
].display
= &screens
[i
];
792 /* Currently no seperate wps_state needed/possible
793 so use the only aviable ( "global" ) one */
794 gui_wps
[i
].state
= &wps_state
;
796 #ifdef HAVE_LCD_BITMAP
797 add_event(GUI_EVENT_STATUSBAR_TOGGLE
, false, statusbar_toggle_handler
);
800 unload_wps_backdrop();
802 #if defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1
803 unload_remote_wps_backdrop();
808 /* Returns true if at least one of the gui_wps screens has an album art
809 tag in its wps structure */
810 bool gui_sync_wps_uses_albumart(void)
814 struct gui_wps
*gwps
= &gui_wps
[i
];
815 if (gwps
->data
&& (gwps
->data
->wps_uses_albumart
!= WPS_ALBUMART_NONE
))