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 "gwps-common.h"
39 #include "main_menu.h"
43 #ifdef HAVE_LCD_BITMAP
45 #include "peakmeter.h"
60 #define WPS_DEFAULTCFG WPS_DIR "/rockbox_default.wps"
61 #define RWPS_DEFAULTCFG WPS_DIR "/rockbox_default.rwps"
62 /* currently only on wps_state is needed */
63 struct wps_state wps_state
;
64 struct gui_wps gui_wps
[NB_SCREENS
];
65 static struct wps_data wps_datas
[NB_SCREENS
];
67 bool keys_locked
= false;
69 /* change the path to the current played track */
70 static void wps_state_update_ctp(const char *path
);
72 #ifdef HAVE_LCD_BITMAP
73 static void gui_wps_set_margin(struct gui_wps
*gwps
)
76 struct wps_data
*data
= gwps
->data
;
77 if(data
->wps_sb_tag
&& data
->show_sb_on_wps
)
78 offset
= STATUSBAR_HEIGHT
;
79 else if ( global_settings
.statusbar
&& !data
->wps_sb_tag
)
80 offset
= STATUSBAR_HEIGHT
;
81 gwps
->display
->setmargins(0, offset
);
85 long gui_wps_show(void)
87 long button
= 0, lastbutton
= 0;
88 bool ignore_keyup
= true;
90 long restoretimer
= 0; /* timer to delay screen redraw temporarily */
92 bool update_track
= false;
93 unsigned long right_lastclick
= 0;
94 unsigned long left_lastclick
= 0;
99 #ifdef HAVE_LCD_CHARCELLS
100 status_set_audio(true);
101 status_set_param(false);
105 gui_wps_set_margin(&gui_wps
[i
]);
107 #ifdef HAVE_LCD_COLOR
108 gui_wps
[SCREEN_MAIN
].data
->old_backdrop
= lcd_get_backdrop();
109 if (gui_wps
[SCREEN_MAIN
].data
->has_backdrop
) {
110 lcd_set_backdrop(&wps_backdrop
[0][0]);
115 #ifdef AB_REPEAT_ENABLE
120 if(audio_status() & AUDIO_STATUS_PLAY
)
122 wps_state
.id3
= audio_current_track();
123 wps_state
.nid3
= audio_next_track();
125 if (gui_wps_display())
128 gui_wps_refresh(&gui_wps
[i
], 0, WPS_REFRESH_ALL
);
129 wps_state_update_ctp(wps_state
.id3
->path
);
136 bool audio_paused
= (audio_status() & AUDIO_STATUS_PAUSE
)?true:false;
138 /* did someone else (i.e power thread) change audio pause mode? */
139 if (wps_state
.paused
!= audio_paused
) {
140 wps_state
.paused
= audio_paused
;
142 /* if another thread paused audio, we are probably in car mode,
143 about to shut down. lets save the settings. */
144 if (wps_state
.paused
) {
146 #if !defined(HAVE_RTC_RAM) && !defined(HAVE_SW_POWEROFF)
152 #ifdef HAVE_LCD_BITMAP
153 /* when the peak meter is enabled we want to have a
154 few extra updates to make it look smooth. On the
155 other hand we don't want to waste energy if it
160 if(gui_wps
[i
].data
->peak_meter_enabled
)
165 long next_refresh
= current_tick
;
166 long next_big_refresh
= current_tick
+ HZ
/ 5;
167 button
= BUTTON_NONE
;
168 while (TIME_BEFORE(current_tick
, next_big_refresh
)) {
169 button
= button_get(false);
170 if (button
!= BUTTON_NONE
) {
174 sleep(0); /* Sleep until end of current tick. */
176 if (TIME_AFTER(current_tick
, next_refresh
)) {
179 if(gui_wps
[i
].data
->peak_meter_enabled
)
180 gui_wps_refresh(&gui_wps
[i
], 0,
181 WPS_REFRESH_PEAK_METER
);
182 next_refresh
+= HZ
/ PEAK_METER_FPS
;
189 /* The peak meter is disabled
190 -> no additional screen updates needed */
192 button
= button_get_w_tmo(HZ
/5);
195 button
= button_get_w_tmo(HZ
/5);
198 /* discard first event if it's a button release */
199 if (button
&& ignore_keyup
)
201 ignore_keyup
= false;
202 /* Negative events are system events */
203 if (button
>= 0 && button
& BUTTON_REL
)
208 /* ignore non-remote buttons when keys are locked */
211 (button
== BUTTON_NONE
) ||
212 ((button
& WPS_KEYLOCK
) == WPS_KEYLOCK
) ||
213 (button
& BUTTON_REMOTE
)
216 if (!(button
& BUTTON_REL
))
217 display_keylock_text(true);
219 button
= BUTTON_NONE
;
223 /* Exit if audio has stopped playing. This can happen if using the
224 sleep timer with the charger plugged or if starting a recording
233 #ifdef WPS_RC_CONTEXT
236 #ifdef HAVE_LCD_COLOR
237 lcd_set_backdrop(gui_wps
[SCREEN_MAIN
].data
->old_backdrop
);
239 onplay(wps_state
.id3
->path
, TREE_ATTR_MPA
, CONTEXT_WPS
);
240 #ifdef HAVE_LCD_COLOR
241 if (gui_wps
[SCREEN_MAIN
].data
->has_backdrop
)
242 lcd_set_backdrop(&wps_backdrop
[0][0]);
244 #ifdef HAVE_LCD_BITMAP
247 gui_wps_set_margin(&gui_wps
[i
]);
258 #ifdef WPS_BROWSE_PRE
259 if ((lastbutton
!= WPS_BROWSE_PRE
)
260 #ifdef WPS_RC_BROWSE_PRE
261 && (lastbutton
!= WPS_RC_BROWSE_PRE
)
266 #ifdef HAVE_LCD_CHARCELLS
267 status_set_record(false);
268 status_set_audio(false);
271 gui_wps
[i
].display
->stop_scroll();
273 /* set dir browser to current playing song */
274 if (global_settings
.browse_current
&&
275 wps_state
.current_track_path
[0] != '\0')
276 set_current_file(wps_state
.current_track_path
);
284 if (lastbutton
!= WPS_PAUSE_PRE
)
289 if (global_settings
.party_mode
)
291 #ifdef WPS_RC_PAUSE_PRE
292 if ((button
== WPS_RC_PAUSE
) &&
293 (lastbutton
!= WPS_RC_PAUSE_PRE
))
297 if ( wps_state
.paused
)
299 wps_state
.paused
= false;
300 if ( global_settings
.fade_on_stop
)
307 wps_state
.paused
= true;
308 if ( global_settings
.fade_on_stop
)
313 #if !defined(HAVE_RTC_RAM) && !defined(HAVE_SW_POWEROFF)
314 ata_flush(); /* make sure resume info is saved */
321 case WPS_INCVOL
| BUTTON_REPEAT
:
324 case WPS_RC_INCVOL
| BUTTON_REPEAT
:
327 global_settings
.volume
++;
332 if(update_onvol_change(&gui_wps
[i
]))
337 restoretimer
= current_tick
+ HZ
;
344 case WPS_DECVOL
| BUTTON_REPEAT
:
347 case WPS_RC_DECVOL
| BUTTON_REPEAT
:
350 global_settings
.volume
--;
355 if(update_onvol_change(&gui_wps
[i
]))
360 restoretimer
= current_tick
+ HZ
;
365 /* fast forward / rewind */
370 if (global_settings
.party_mode
)
373 if (current_tick
- right_lastclick
< HZ
)
384 if (global_settings
.party_mode
)
387 if (current_tick
- left_lastclick
< HZ
)
400 if (lastbutton
!= WPS_PREV_PRE
)
405 if (global_settings
.party_mode
)
407 #ifdef WPS_RC_PREV_PRE
408 if ((button
== WPS_RC_PREV
) && (lastbutton
!= WPS_RC_PREV_PRE
))
412 left_lastclick
= current_tick
;
415 #ifdef AB_REPEAT_ENABLE
416 /* if we're in A/B repeat mode and the current position
417 is past the A marker, jump back to the A marker... */
418 if ( ab_repeat_mode_enabled() )
420 if ( ab_after_A_marker(wps_state
.id3
->elapsed
) )
422 ab_jump_to_A_marker();
424 #if (AB_REPEAT_ENABLE == 2)
430 /* ...otherwise, do it normally */
433 if (!wps_state
.id3
|| (wps_state
.id3
->elapsed
< 3*1000)) {
437 if (!wps_state
.paused
)
442 if (!wps_state
.paused
)
448 #ifdef WPS_RC_NEXT_DIR
449 case WPS_RC_NEXT_DIR
:
452 if (global_settings
.party_mode
)
454 #if defined(AB_REPEAT_ENABLE) && defined(WPS_AB_SHARE_DIR_BUTTONS)
455 if (ab_repeat_mode_enabled())
457 ab_set_B_marker(wps_state
.id3
->elapsed
);
458 ab_jump_to_A_marker();
469 #ifdef WPS_RC_PREV_DIR
470 case WPS_RC_PREV_DIR
:
473 if (global_settings
.party_mode
)
475 #if defined(AB_REPEAT_ENABLE) && defined(WPS_AB_SHARE_DIR_BUTTONS)
476 if (ab_repeat_mode_enabled())
477 ab_set_A_marker(wps_state
.id3
->elapsed
);
489 if (lastbutton
!= WPS_NEXT_PRE
)
494 if (global_settings
.party_mode
)
496 #ifdef WPS_RC_NEXT_PRE
497 if ((button
== WPS_RC_NEXT
) && (lastbutton
!= WPS_RC_NEXT_PRE
))
501 right_lastclick
= current_tick
;
504 #ifdef AB_REPEAT_ENABLE
505 /* if we're in A/B repeat mode and the current position is
506 before the A marker, jump to the A marker... */
507 if ( ab_repeat_mode_enabled() )
509 if ( ab_before_A_marker(wps_state
.id3
->elapsed
) )
511 ab_jump_to_A_marker();
513 #if (AB_REPEAT_ENABLE == 2)
519 /* ...otherwise, do it normally */
526 /* menu key functions */
529 if (lastbutton
!= WPS_MENU_PRE
)
534 #ifdef WPS_RC_MENU_PRE
535 if ((button
== WPS_RC_MENU
) && (lastbutton
!= WPS_RC_MENU_PRE
))
540 gui_wps
[i
].display
->stop_scroll();
542 #ifdef HAVE_LCD_COLOR
543 lcd_set_backdrop(gui_wps
[SCREEN_MAIN
].data
->old_backdrop
);
547 #ifdef HAVE_LCD_COLOR
548 if (gui_wps
[SCREEN_MAIN
].data
->has_backdrop
)
549 lcd_set_backdrop(&wps_backdrop
[0][0]);
551 #ifdef HAVE_LCD_BITMAP
554 gui_wps_set_margin(&gui_wps
[i
]);
559 #endif /* WPS_MENU */
564 case WPS_KEYLOCK
| BUTTON_REPEAT
:
565 keys_locked
= !keys_locked
;
566 display_keylock_text(keys_locked
);
572 #if (CONFIG_KEYPAD == RECORDER_PAD) || (CONFIG_KEYPAD == IRIVER_H100_PAD) \
573 || (CONFIG_KEYPAD == IRIVER_H300_PAD)
579 #ifdef HAVE_LCD_COLOR
580 lcd_set_backdrop(gui_wps
[SCREEN_MAIN
].data
->old_backdrop
);
582 if (quick_screen_quick(button
))
583 return SYS_USB_CONNECTED
;
584 #ifdef HAVE_LCD_COLOR
585 if (gui_wps
[SCREEN_MAIN
].data
->has_backdrop
)
586 lcd_set_backdrop(&wps_backdrop
[0][0]);
588 #ifdef HAVE_LCD_BITMAP
591 gui_wps_set_margin(&gui_wps
[i
]);
598 /* screen settings */
601 if (quick_screen_f3(button
))
602 return SYS_USB_CONNECTED
;
608 #if CONFIG_KEYPAD == RECORDER_PAD || CONFIG_KEYPAD == IRIVER_H100_PAD \
609 || CONFIG_KEYPAD == IRIVER_H300_PAD
610 case BUTTON_ON
| BUTTON_UP
:
611 case BUTTON_ON
| BUTTON_DOWN
:
612 #if CONFIG_KEYPAD == IRIVER_H100_PAD || CONFIG_KEYPAD == IRIVER_H300_PAD
613 case BUTTON_ON
| BUTTON_OFF
:
615 #ifdef HAVE_LCD_COLOR
616 lcd_set_backdrop(gui_wps
[SCREEN_MAIN
].data
->old_backdrop
);
618 if (2 == pitch_screen())
619 return SYS_USB_CONNECTED
;
620 #ifdef HAVE_LCD_COLOR
621 if (gui_wps
[SCREEN_MAIN
].data
->has_backdrop
)
622 lcd_set_backdrop(&wps_backdrop
[0][0]);
629 #ifdef AB_REPEAT_ENABLE
633 #ifdef WPS_AB_SINGLE_PRE
634 if (lastbutton
!= WPS_AB_SINGLE_PRE
)
637 /* If we are using the menu option to enable ab_repeat mode, don't do anything
638 * when it's disabled */
639 #if (AB_REPEAT_ENABLE == 1)
640 if (!ab_repeat_mode_enabled())
643 if (ab_A_marker_set()) {
645 if (ab_B_marker_set()) {
649 ab_set_B_marker(wps_state
.id3
->elapsed
);
650 ab_jump_to_A_marker();
653 ab_set_A_marker(wps_state
.id3
->elapsed
);
658 #ifdef WPS_AB_SET_A_MARKER
659 /* set A marker for A-B repeat */
660 case WPS_AB_SET_A_MARKER
:
661 if (ab_repeat_mode_enabled())
662 ab_set_A_marker(wps_state
.id3
->elapsed
);
666 #ifdef WPS_AB_SET_B_MARKER
667 /* set B marker for A-B repeat and jump to A */
668 case WPS_AB_SET_B_MARKER
:
669 if (ab_repeat_mode_enabled())
671 ab_set_B_marker(wps_state
.id3
->elapsed
);
672 ab_jump_to_A_marker();
678 #ifdef WPS_AB_RESET_AB_MARKERS
679 /* reset A&B markers */
680 case WPS_AB_RESET_AB_MARKERS
:
681 if (ab_repeat_mode_enabled())
689 #endif /* AB_REPEAT_ENABLE */
691 /* stop and exit wps */
695 if (lastbutton
!= WPS_EXIT_PRE
)
698 if (global_settings
.party_mode
)
703 #ifdef WPS_RC_EXIT_PRE
704 if (lastbutton
!= WPS_RC_EXIT_PRE
)
707 if (global_settings
.party_mode
)
721 case BUTTON_NONE
: /* Timeout */
726 bookmark_autobookmark();
727 default_event_handler(SYS_POWEROFF
);
731 if(default_event_handler(button
) == SYS_USB_CONNECTED
)
732 return SYS_USB_CONNECTED
;
739 bool update_failed
= false;
742 if(update(&gui_wps
[i
]))
743 update_failed
= true;
747 /* set dir browser to current playing song */
748 if (global_settings
.browse_current
&&
749 wps_state
.current_track_path
[0] != '\0')
750 set_current_file(wps_state
.current_track_path
);
754 update_track
= false;
758 #ifdef HAVE_LCD_CHARCELLS
759 status_set_record(false);
760 status_set_audio(false);
762 if (global_settings
.fade_on_stop
)
766 gui_wps
[i
].display
->stop_scroll();
767 bookmark_autobookmark();
769 #ifdef AB_REPEAT_ENABLE
773 /* Keys can be locked when exiting, so either unlock here
774 or implement key locking in tree.c too */
777 /* set dir browser to current playing song */
778 if (global_settings
.browse_current
&&
779 wps_state
.current_track_path
[0] != '\0')
780 set_current_file(wps_state
.current_track_path
);
789 ((restoretimer
== 0) ||
790 (restoretimer
< current_tick
)))
794 if (gui_wps_display())
796 /* set dir browser to current playing song */
797 if (global_settings
.browse_current
&&
798 wps_state
.current_track_path
[0] != '\0')
799 set_current_file(wps_state
.current_track_path
);
806 gui_wps_refresh(&gui_wps
[i
], 0, WPS_REFRESH_NON_STATIC
);
809 if (button
!= BUTTON_NONE
)
812 return 0; /* unreachable - just to reduce compiler warnings */
815 /* needs checking if needed end*/
818 #ifdef HAVE_LCD_BITMAP
819 /* Clear the WPS image cache */
820 static void wps_clear(struct wps_data
*data
)
823 /* set images to unloaded and not displayed */
824 for (i
= 0; i
< MAX_IMAGES
; i
++) {
825 data
->img
[i
].loaded
= false;
826 data
->img
[i
].display
= false;
827 data
->img
[i
].always_display
= false;
829 data
->wps_sb_tag
= false;
830 data
->show_sb_on_wps
= false;
831 data
->progressbar
.have_bitmap_pb
=false;
837 /* initial setup of wps_data */
838 void wps_data_init(struct wps_data
*wps_data
)
840 #ifdef HAVE_LCD_BITMAP
842 #else /* HAVE_LCD_CHARCELLS */
845 for(i
= 0; i
< 8; i
++)
846 wps_data
->wps_progress_pat
[i
] = 0;
847 wps_data
->full_line_progressbar
= 0;
850 wps_data
->format_buffer
[0] = '\0';
851 wps_data
->wps_loaded
= false;
852 wps_data
->peak_meter_enabled
= false;
853 #ifdef HAVE_LCD_COLOR
854 wps_data
->has_backdrop
= false;
858 static void wps_reset(struct wps_data
*data
)
860 data
->wps_loaded
= false;
861 memset(&data
->format_buffer
, 0, sizeof data
->format_buffer
);
865 /* to setup up the wps-data from a format-buffer (isfile = false)
866 from a (wps-)file (isfile = true)*/
867 bool wps_data_load(struct wps_data
*wps_data
,
873 if(!wps_data
|| !buf
)
879 strncpy(wps_data
->format_buffer
, buf
, sizeof(wps_data
->format_buffer
));
880 wps_data
->format_buffer
[sizeof(wps_data
->format_buffer
) - 1] = 0;
881 gui_wps_format(wps_data
);
887 * Hardcode loading WPS_DEFAULTCFG to cause a reset ideally this
888 * wants to be a virtual file. Feel free to modify dirbrowse()
889 * if you're feeling brave.
891 if (! strcmp(buf
, WPS_DEFAULTCFG
) )
894 global_settings
.wps_file
[0] = 0;
898 #ifdef HAVE_REMOTE_LCD
899 if (! strcmp(buf
, RWPS_DEFAULTCFG
) )
902 global_settings
.rwps_file
[0] = 0;
908 char *bmpdir
= strrchr(buf
, '.');
909 bmpdirlen
= bmpdir
- buf
;
911 fd
= open(buf
, O_RDONLY
);
915 unsigned int start
= 0;
918 #ifdef HAVE_LCD_BITMAP
919 wps_data
->img_buf_ptr
= wps_data
->img_buf
; /* where in image buffer */
921 wps_data
->img_buf_free
= IMG_BUFSIZE
; /* free space in image buffer */
923 while( ( read_line(fd
, &wps_data
->format_buffer
[start
],
924 sizeof(wps_data
->format_buffer
)-start
) ) > 0 )
926 if(!wps_data_preload_tags(wps_data
,
927 &wps_data
->format_buffer
[start
],
930 start
+= strlen(&wps_data
->format_buffer
[start
]);
932 if (start
< sizeof(wps_data
->format_buffer
) - 1)
934 wps_data
->format_buffer
[start
++] = '\n';
935 wps_data
->format_buffer
[start
] = 0;
942 gui_wps_format(wps_data
);
947 wps_data
->wps_loaded
= true;
960 void wps_state_init(void)
962 wps_state
.ff_rewind
= false;
963 wps_state
.paused
= false;
964 wps_state
.id3
= NULL
;
965 wps_state
.nid3
= NULL
;
966 wps_state
.current_track_path
[0] = '\0';
970 /* these are obviously not used? */
972 void wps_state_update_ff_rew(bool ff_rew
)
974 wps_state
.ff_rewind
= ff_rew
;
977 void wps_state_update_paused(bool paused
)
979 wps_state
.paused
= paused
;
981 void wps_state_update_id3_nid3(struct mp3entry
*id3
, struct mp3entry
*nid3
)
984 wps_state
.nid3
= nid3
;
988 static void wps_state_update_ctp(const char *path
)
990 memcpy(wps_state
.current_track_path
, path
,
991 sizeof(wps_state
.current_track_path
));
995 /* initial setup of a wps */
996 void gui_wps_init(struct gui_wps
*gui_wps
)
998 gui_wps
->data
= NULL
;
999 gui_wps
->display
= NULL
;
1000 gui_wps
->statusbar
= NULL
;
1001 /* Currently no seperate wps_state needed/possible
1002 so use the only aviable ( "global" ) one */
1003 gui_wps
->state
= &wps_state
;
1006 /* connects a wps with a format-description of the displayed content */
1007 void gui_wps_set_data(struct gui_wps
*gui_wps
, struct wps_data
*data
)
1009 gui_wps
->data
= data
;
1012 /* connects a wps with a screen */
1013 void gui_wps_set_disp(struct gui_wps
*gui_wps
, struct screen
*display
)
1015 gui_wps
->display
= display
;
1018 void gui_wps_set_statusbar(struct gui_wps
*gui_wps
, struct gui_statusbar
*statusbar
)
1020 gui_wps
->statusbar
= statusbar
;
1024 void gui_sync_wps_screen_init(void)
1028 gui_wps_set_disp(&gui_wps
[i
], &screens
[i
]);
1031 void gui_sync_wps_init(void)
1036 wps_data_init(&wps_datas
[i
]);
1037 gui_wps_init(&gui_wps
[i
]);
1038 gui_wps_set_data(&gui_wps
[i
], &wps_datas
[i
]);
1039 gui_wps_set_statusbar(&gui_wps
[i
], &statusbars
.statusbars
[i
]);