Updated our source code header to explicitly mention that we are GPL v2 or
[Rockbox.git] / apps / gui / gwps.c
blobd752cb3da58544509347e9662aea730036e92de3
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
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 ****************************************************************************/
21 #include <stdio.h>
22 #include <string.h>
23 #include <stdlib.h>
24 #include "config.h"
26 #include "system.h"
27 #include "file.h"
28 #include "lcd.h"
29 #include "font.h"
30 #include "backlight.h"
31 #include "action.h"
32 #include "kernel.h"
33 #include "filetypes.h"
34 #include "debug.h"
35 #include "sprintf.h"
36 #include "settings.h"
37 #include "gwps.h"
38 #include "gwps-common.h"
39 #include "audio.h"
40 #include "usb.h"
41 #include "status.h"
42 #include "ata.h"
43 #include "screens.h"
44 #include "playlist.h"
45 #ifdef HAVE_LCD_BITMAP
46 #include "icons.h"
47 #include "peakmeter.h"
48 #endif
49 #include "action.h"
50 #include "lang.h"
51 #include "bookmark.h"
52 #include "misc.h"
53 #include "sound.h"
54 #include "onplay.h"
55 #include "abrepeat.h"
56 #include "playback.h"
57 #include "splash.h"
58 #include "cuesheet.h"
59 #include "ata_idle_notify.h"
60 #include "root_menu.h"
61 #include "backdrop.h"
62 #include "quickscreen.h"
64 /* currently only on wps_state is needed */
65 struct wps_state wps_state;
66 struct gui_wps gui_wps[NB_SCREENS];
67 static struct wps_data wps_datas[NB_SCREENS];
69 /* change the path to the current played track */
70 static void wps_state_update_ctp(const char *path);
71 /* initial setup of wps_data */
72 static void wps_state_init(void);
73 /* initial setup of a wps */
74 static void gui_wps_init(struct gui_wps *gui_wps);
75 /* connects a wps with a format-description of the displayed content */
76 static void gui_wps_set_data(struct gui_wps *gui_wps, struct wps_data *data);
77 /* connects a wps with a screen */
78 static void gui_wps_set_disp(struct gui_wps *gui_wps, struct screen *display);
79 /* connects a wps with a statusbar*/
80 static void gui_wps_set_statusbar(struct gui_wps *gui_wps, struct gui_statusbar *statusbar);
82 static void prev_track(unsigned skip_thresh)
84 if (!wps_state.id3 || (wps_state.id3->elapsed < skip_thresh*1000)) {
85 audio_prev();
87 else {
88 if (cuesheet_is_enabled() && wps_state.id3->cuesheet_type)
90 curr_cuesheet_skip(-1, wps_state.id3->elapsed);
91 return;
94 if (!wps_state.paused)
95 #if (CONFIG_CODEC == SWCODEC)
96 audio_pre_ff_rewind();
97 #else
98 audio_pause();
99 #endif
101 audio_ff_rewind(0);
103 #if (CONFIG_CODEC != SWCODEC)
104 if (!wps_state.paused)
105 audio_resume();
106 #endif
110 static void next_track(void)
112 /* take care of if we're playing a cuesheet */
113 if (cuesheet_is_enabled() && wps_state.id3->cuesheet_type)
115 if (curr_cuesheet_skip(1, wps_state.id3->elapsed))
117 /* if the result was false, then we really want
118 to skip to the next track */
119 return;
123 audio_next();
127 long gui_wps_show(void)
129 long button = 0;
130 bool restore = false;
131 long restoretimer = 0; /* timer to delay screen redraw temporarily */
132 bool exit = false;
133 bool bookmark = false;
134 bool update_track = false;
135 int i;
136 long last_left = 0, last_right = 0;
138 wps_state_init();
140 #ifdef HAVE_LCD_CHARCELLS
141 status_set_audio(true);
142 status_set_param(false);
143 #else
144 #if LCD_DEPTH > 1
145 show_wps_backdrop();
146 #endif /* LCD_DEPTH > 1 */
147 #endif
149 #if defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1
150 show_remote_wps_backdrop();
151 #endif
153 #ifdef AB_REPEAT_ENABLE
154 ab_repeat_init();
155 ab_reset_markers();
156 #endif
158 if(audio_status() & AUDIO_STATUS_PLAY)
160 wps_state.id3 = audio_current_track();
161 wps_state.nid3 = audio_next_track();
162 if (wps_state.id3) {
163 if (gui_wps_display())
164 return 0;
165 FOR_NB_SCREENS(i)
166 gui_wps_refresh(&gui_wps[i], 0, WPS_REFRESH_ALL);
167 wps_state_update_ctp(wps_state.id3->path);
170 restore = true;
172 while ( 1 )
174 bool audio_paused = (audio_status() & AUDIO_STATUS_PAUSE)?true:false;
176 /* did someone else (i.e power thread) change audio pause mode? */
177 if (wps_state.paused != audio_paused) {
178 wps_state.paused = audio_paused;
180 /* if another thread paused audio, we are probably in car mode,
181 about to shut down. lets save the settings. */
182 if (wps_state.paused) {
183 settings_save();
184 #if !defined(HAVE_RTC_RAM) && !defined(HAVE_SW_POWEROFF)
185 call_ata_idle_notifys(true);
186 #endif
190 #ifdef HAVE_LCD_BITMAP
191 /* when the peak meter is enabled we want to have a
192 few extra updates to make it look smooth. On the
193 other hand we don't want to waste energy if it
194 isn't displayed */
195 bool pm=false;
196 FOR_NB_SCREENS(i)
198 if(gui_wps[i].data->peak_meter_enabled)
199 pm = true;
202 if (pm) {
203 long next_refresh = current_tick;
204 long next_big_refresh = current_tick + HZ / 5;
205 button = BUTTON_NONE;
206 while (TIME_BEFORE(current_tick, next_big_refresh)) {
207 button = get_action(CONTEXT_WPS|ALLOW_SOFTLOCK,TIMEOUT_NOBLOCK);
208 if (button != ACTION_NONE) {
209 break;
211 peak_meter_peek();
212 sleep(0); /* Sleep until end of current tick. */
214 if (TIME_AFTER(current_tick, next_refresh)) {
215 FOR_NB_SCREENS(i)
217 if(gui_wps[i].data->peak_meter_enabled)
218 gui_wps_refresh(&gui_wps[i], 0,
219 WPS_REFRESH_PEAK_METER);
220 next_refresh += HZ / PEAK_METER_FPS;
227 /* The peak meter is disabled
228 -> no additional screen updates needed */
229 else {
230 button = get_action(CONTEXT_WPS|ALLOW_SOFTLOCK,HZ/5);
232 #else
233 button = get_action(CONTEXT_WPS|ALLOW_SOFTLOCK,HZ/5);
234 #endif
236 /* Exit if audio has stopped playing. This can happen if using the
237 sleep timer with the charger plugged or if starting a recording
238 from F1 */
239 if (!audio_status())
240 exit = true;
241 #ifdef ACTION_WPSAB_SINGLE
242 if (!global_settings.party_mode && ab_repeat_mode_enabled())
244 static int wps_ab_state = 0;
245 if (button == ACTION_WPSAB_SINGLE)
247 switch (wps_ab_state)
249 case 0: /* set the A spot */
250 button = ACTION_WPS_ABSETA_PREVDIR;
251 break;
252 case 1: /* set the B spot */
253 button = ACTION_WPS_ABSETB_NEXTDIR;
254 break;
255 case 2:
256 button = ACTION_WPS_ABRESET;
257 break;
259 wps_ab_state = (wps_ab_state+1) % 3;
262 #endif
263 switch(button)
265 case ACTION_WPS_CONTEXT:
266 #if LCD_DEPTH > 1
267 show_main_backdrop();
268 #endif
269 #if defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1
270 show_remote_main_backdrop();
271 #endif
272 /* if music is stopped in the context menu we want to exit the wps */
273 if (onplay(wps_state.id3->path,
274 FILE_ATTR_AUDIO, CONTEXT_WPS) == ONPLAY_MAINMENU
275 || !audio_status())
276 return GO_TO_ROOT;
278 /* track might have changed */
279 update_track = true;
281 #if LCD_DEPTH > 1
282 show_wps_backdrop();
283 #endif
284 #if defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1
285 show_remote_wps_backdrop();
286 #endif
287 restore = true;
288 break;
290 case ACTION_WPS_BROWSE:
291 #ifdef HAVE_LCD_CHARCELLS
292 status_set_record(false);
293 status_set_audio(false);
294 #endif
295 FOR_NB_SCREENS(i)
296 gui_wps[i].display->stop_scroll();
297 return GO_TO_PREVIOUS_BROWSER;
298 break;
300 /* play/pause */
301 case ACTION_WPS_PLAY:
302 if (global_settings.party_mode)
303 break;
304 if ( wps_state.paused )
306 wps_state.paused = false;
307 if ( global_settings.fade_on_stop )
308 fade(true, true);
309 else
310 audio_resume();
312 else
314 wps_state.paused = true;
315 if ( global_settings.fade_on_stop )
316 fade(false, true);
317 else
318 audio_pause();
319 settings_save();
320 #if !defined(HAVE_RTC_RAM) && !defined(HAVE_SW_POWEROFF)
321 call_ata_idle_notifys(true); /* make sure resume info is saved */
322 #endif
324 break;
326 /* volume up */
327 case ACTION_WPS_VOLUP:
329 global_settings.volume++;
330 bool res = false;
331 setvol();
332 FOR_NB_SCREENS(i)
334 if(update_onvol_change(&gui_wps[i]))
335 res = true;
337 if (res) {
338 restore = true;
339 restoretimer = current_tick + HZ;
342 break;
344 /* volume down */
345 case ACTION_WPS_VOLDOWN:
347 global_settings.volume--;
348 setvol();
349 bool res = false;
350 FOR_NB_SCREENS(i)
352 if(update_onvol_change(&gui_wps[i]))
353 res = true;
355 if (res) {
356 restore = true;
357 restoretimer = current_tick + HZ;
360 break;
361 /* fast forward
362 OR next dir if this is straight after ACTION_WPS_SKIPNEXT
363 OR in study mode, next track if straight after SKIPPREV. */
364 case ACTION_WPS_SEEKFWD:
365 if (global_settings.party_mode)
366 break;
367 if (!global_settings.study_mode
368 && current_tick -last_right < HZ)
370 if (cuesheet_is_enabled() && wps_state.id3->cuesheet_type)
372 audio_next();
374 else
376 audio_next_dir();
379 else if(global_settings.study_mode
380 && current_tick -last_left < HZ) {
381 next_track();
382 update_track = true;
384 else ffwd_rew(ACTION_WPS_SEEKFWD);
385 last_right = last_left = 0;
386 break;
387 /* fast rewind
388 OR prev dir if this is straight after ACTION_WPS_SKIPPREV,
389 OR in study mode, beg of track or prev track if this is
390 straight after SKIPPREV */
391 case ACTION_WPS_SEEKBACK:
392 if (global_settings.party_mode)
393 break;
394 if (!global_settings.study_mode
395 && current_tick -last_left < HZ)
397 if (cuesheet_is_enabled() && wps_state.id3->cuesheet_type)
399 if (!wps_state.paused)
400 #if (CONFIG_CODEC == SWCODEC)
401 audio_pre_ff_rewind();
402 #else
403 audio_pause();
404 #endif
405 audio_ff_rewind(0);
407 else
409 audio_prev_dir();
412 else if(global_settings.study_mode
413 && current_tick -last_right < HZ)
415 prev_track(3+global_settings.study_hop_step);
416 update_track = true;
418 else ffwd_rew(ACTION_WPS_SEEKBACK);
419 last_left = last_right = 0;
420 break;
422 /* prev / restart */
423 case ACTION_WPS_SKIPPREV:
424 if (global_settings.party_mode)
425 break;
426 last_left = current_tick;
427 update_track = true;
429 #ifdef AB_REPEAT_ENABLE
430 /* if we're in A/B repeat mode and the current position
431 is past the A marker, jump back to the A marker... */
432 if ( ab_repeat_mode_enabled() )
434 if ( ab_after_A_marker(wps_state.id3->elapsed) )
436 ab_jump_to_A_marker();
437 break;
438 #if (AB_REPEAT_ENABLE == 2)
439 } else {
440 ab_reset_markers();
441 #endif
444 /* ...otherwise, do it normally */
445 #endif
447 if(global_settings.study_mode)
448 play_hop(-1);
449 else prev_track(3);
450 break;
452 /* next
453 OR in study mode, hop by predetermined amount. */
454 case ACTION_WPS_SKIPNEXT:
455 if (global_settings.party_mode)
456 break;
457 last_right = current_tick;
458 update_track = true;
460 #ifdef AB_REPEAT_ENABLE
461 /* if we're in A/B repeat mode and the current position is
462 before the A marker, jump to the A marker... */
463 if ( ab_repeat_mode_enabled() )
465 if ( ab_before_A_marker(wps_state.id3->elapsed) )
467 ab_jump_to_A_marker();
468 break;
469 #if (AB_REPEAT_ENABLE == 2)
470 } else {
471 ab_reset_markers();
472 #endif
475 /* ...otherwise, do it normally */
476 #endif
478 if(global_settings.study_mode)
479 play_hop(1);
480 else next_track();
481 break;
482 /* next / prev directories */
483 /* and set A-B markers if in a-b mode */
484 case ACTION_WPS_ABSETB_NEXTDIR:
485 if (global_settings.party_mode)
486 break;
487 #if defined(AB_REPEAT_ENABLE)
488 if (ab_repeat_mode_enabled())
490 ab_set_B_marker(wps_state.id3->elapsed);
491 ab_jump_to_A_marker();
492 update_track = true;
494 else
495 #endif
497 if(global_settings.study_mode)
498 next_track();
499 else audio_next_dir();
501 break;
502 case ACTION_WPS_ABSETA_PREVDIR:
503 if (global_settings.party_mode)
504 break;
505 #if defined(AB_REPEAT_ENABLE)
506 if (ab_repeat_mode_enabled())
507 ab_set_A_marker(wps_state.id3->elapsed);
508 else
509 #endif
511 if(global_settings.study_mode)
512 prev_track(3);
513 else audio_prev_dir();
515 break;
516 /* menu key functions */
517 case ACTION_WPS_MENU:
518 FOR_NB_SCREENS(i)
519 gui_wps[i].display->stop_scroll();
520 return GO_TO_ROOT;
521 break;
524 #ifdef HAVE_QUICKSCREEN
525 case ACTION_WPS_QUICKSCREEN:
526 #if LCD_DEPTH > 1
527 show_main_backdrop();
528 #endif
529 #if defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1
530 show_remote_main_backdrop();
531 #endif
532 if (quick_screen_quick(button))
533 return SYS_USB_CONNECTED;
534 #if LCD_DEPTH > 1
535 show_wps_backdrop();
536 #endif
537 #if defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1
538 show_remote_wps_backdrop();
539 #endif
540 restore = true;
541 break;
542 #endif /* HAVE_QUICKSCREEN */
544 /* screen settings */
545 #ifdef BUTTON_F3
546 case ACTION_F3:
547 #if LCD_DEPTH > 1
548 show_main_backdrop();
549 #endif
550 #if defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1
551 show_remote_main_backdrop();
552 #endif
553 if (quick_screen_f3(BUTTON_F3))
554 return SYS_USB_CONNECTED;
555 restore = true;
556 break;
557 #endif /* BUTTON_F3 */
559 /* pitch screen */
560 #ifdef HAVE_PITCHSCREEN
561 case ACTION_WPS_PITCHSCREEN:
562 #if LCD_DEPTH > 1
563 show_main_backdrop();
564 #endif
565 #if defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1
566 show_remote_main_backdrop();
567 #endif
568 if (1 == pitch_screen())
569 return SYS_USB_CONNECTED;
570 #if LCD_DEPTH > 1
571 show_wps_backdrop();
572 #endif
573 #if defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1
574 show_remote_wps_backdrop();
575 #endif
576 restore = true;
577 break;
578 #endif /* HAVE_PITCHSCREEN */
580 #ifdef AB_REPEAT_ENABLE
581 /* reset A&B markers */
582 case ACTION_WPS_ABRESET:
583 if (ab_repeat_mode_enabled())
585 ab_reset_markers();
586 update_track = true;
588 break;
589 #endif /* AB_REPEAT_ENABLE */
591 /* stop and exit wps */
592 case ACTION_WPS_STOP:
593 if (global_settings.party_mode)
594 break;
595 bookmark = true;
596 exit = true;
597 break;
599 case ACTION_WPS_ID3SCREEN:
600 #if LCD_DEPTH > 1
601 show_main_backdrop();
602 #endif
603 #if defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1
604 show_remote_main_backdrop();
605 #endif
606 browse_id3();
607 #if LCD_DEPTH > 1
608 show_wps_backdrop();
609 #endif
610 #if defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1
611 show_remote_wps_backdrop();
612 #endif
613 restore = true;
614 break;
616 case ACTION_REDRAW: /* yes are locked, just redraw */
617 restore = true;
618 break;
619 case ACTION_NONE: /* Timeout */
620 update_track = true;
621 ffwd_rew(button); /* hopefully fix the ffw/rwd bug */
622 break;
623 #ifdef HAVE_RECORDING
624 case ACTION_WPS_REC:
625 exit = true;
626 break;
627 #endif
628 case SYS_POWEROFF:
629 #if LCD_DEPTH > 1
630 show_main_backdrop();
631 #endif
632 #if defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1
633 show_remote_main_backdrop();
634 #endif
635 default_event_handler(SYS_POWEROFF);
636 break;
638 default:
639 if(default_event_handler(button) == SYS_USB_CONNECTED)
640 return GO_TO_ROOT;
641 update_track = true;
642 break;
645 if (update_track)
647 FOR_NB_SCREENS(i)
649 if(update(&gui_wps[i]))
650 exit = true;
652 update_track = false;
655 if (restore &&
656 ((restoretimer == 0) ||
657 (restoretimer < current_tick)))
659 restore = false;
660 restoretimer = 0;
661 if (gui_wps_display()) {
662 exit = true;
664 else if (wps_state.id3){
665 FOR_NB_SCREENS(i)
666 gui_wps_refresh(&gui_wps[i], 0, WPS_REFRESH_NON_STATIC);
670 if (exit) {
671 #ifdef HAVE_LCD_CHARCELLS
672 status_set_record(false);
673 status_set_audio(false);
674 #endif
675 if (global_settings.fade_on_stop)
676 fade(false, true);
678 FOR_NB_SCREENS(i)
679 gui_wps[i].display->stop_scroll();
680 if (bookmark)
681 bookmark_autobookmark();
682 audio_stop();
683 #ifdef AB_REPEAT_ENABLE
684 ab_reset_markers();
685 #endif
686 #ifdef HAVE_RECORDING
687 if (button == ACTION_WPS_REC)
688 return GO_TO_RECSCREEN;
689 #endif
690 if (global_settings.browse_current)
691 return GO_TO_PREVIOUS_BROWSER;
692 return GO_TO_PREVIOUS;
695 if ( button )
696 ata_spin();
698 return GO_TO_ROOT; /* unreachable - just to reduce compiler warnings */
701 /* needs checking if needed end*/
703 /* wps_state */
705 static void wps_state_init(void)
707 wps_state.ff_rewind = false;
708 wps_state.paused = false;
709 wps_state.id3 = NULL;
710 wps_state.nid3 = NULL;
711 wps_state.current_track_path[0] = '\0';
714 #if 0
715 /* these are obviously not used? */
717 void wps_state_update_ff_rew(bool ff_rew)
719 wps_state.ff_rewind = ff_rew;
722 void wps_state_update_paused(bool paused)
724 wps_state.paused = paused;
726 void wps_state_update_id3_nid3(struct mp3entry *id3, struct mp3entry *nid3)
728 wps_state.id3 = id3;
729 wps_state.nid3 = nid3;
731 #endif
733 static void wps_state_update_ctp(const char *path)
735 strncpy(wps_state.current_track_path, path,
736 sizeof(wps_state.current_track_path));
737 wps_state.current_track_path[sizeof(wps_state.current_track_path)-1] = '\0';
739 /* wps_state end*/
741 /* initial setup of a wps */
742 static void gui_wps_init(struct gui_wps *gui_wps)
744 gui_wps->data = NULL;
745 gui_wps->display = NULL;
746 gui_wps->statusbar = NULL;
747 /* Currently no seperate wps_state needed/possible
748 so use the only aviable ( "global" ) one */
749 gui_wps->state = &wps_state;
752 /* connects a wps with a format-description of the displayed content */
753 static void gui_wps_set_data(struct gui_wps *gui_wps, struct wps_data *data)
755 gui_wps->data = data;
758 /* connects a wps with a screen */
759 static void gui_wps_set_disp(struct gui_wps *gui_wps, struct screen *display)
761 gui_wps->display = display;
764 static void gui_wps_set_statusbar(struct gui_wps *gui_wps, struct gui_statusbar *statusbar)
766 gui_wps->statusbar = statusbar;
768 /* gui_wps end */
770 void gui_sync_wps_screen_init(void)
772 int i;
773 FOR_NB_SCREENS(i)
774 gui_wps_set_disp(&gui_wps[i], &screens[i]);
776 #ifdef HAVE_LCD_BITMAP
777 static void statusbar_toggle_handler(void *data)
779 (void)data;
780 int i;
781 bool draw = global_settings.statusbar;
783 FOR_NB_SCREENS(i)
785 struct wps_viewport *vp = &gui_wps[i].data->viewports[0];
786 if (gui_wps[i].data->wps_sb_tag)
787 draw = gui_wps[i].data->show_sb_on_wps;
788 if (!global_settings.statusbar && !draw)
790 vp->vp.y = 0;
791 vp->vp.height = screens[i].height;
793 else
795 vp->vp.y = STATUSBAR_HEIGHT;
796 vp->vp.height = screens[i].height - STATUSBAR_HEIGHT;
800 #endif
802 void gui_sync_wps_init(void)
804 int i;
805 FOR_NB_SCREENS(i)
807 wps_data_init(&wps_datas[i]);
808 #ifdef HAVE_REMOTE_LCD
809 wps_datas[i].remote_wps = (i != 0);
810 #endif
811 gui_wps_init(&gui_wps[i]);
812 gui_wps_set_data(&gui_wps[i], &wps_datas[i]);
813 gui_wps_set_statusbar(&gui_wps[i], &statusbars.statusbars[i]);
815 #ifdef HAVE_LCD_BITMAP
816 add_event(STATUSBAR_TOGGLE_EVENT, false, statusbar_toggle_handler);
817 #endif
818 #if LCD_DEPTH > 1
819 unload_wps_backdrop();
820 #endif
821 #if defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1
822 unload_remote_wps_backdrop();
823 #endif
826 #ifdef HAVE_ALBUMART
827 /* Returns true if at least one of the gui_wps screens has an album art
828 tag in its wps structure */
829 bool gui_sync_wps_uses_albumart(void)
831 int i;
832 FOR_NB_SCREENS(i) {
833 struct gui_wps *gwps = &gui_wps[i];
834 if (gwps->data && (gwps->data->wps_uses_albumart != WPS_ALBUMART_NONE))
835 return true;
837 return false;
839 #endif