summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHardeep Sidhu <dyp@pobox.com>2003-12-10 00:11:25 +0000
committerHardeep Sidhu <dyp@pobox.com>2003-12-10 00:11:25 +0000
commit00acdfa6ef624e1d13b461210ddd71dd589d192e (patch)
treef31b42d33d417bef4dc040e412a9f8fea61a0ac9
parentc882d45ebba3861b973339564d927412cb04c5b2 (diff)
downloadrockbox-00acdfa6ef624e1d13b461210ddd71dd589d192e.tar.gz
rockbox-00acdfa6ef624e1d13b461210ddd71dd589d192e.zip
Added viewer for currently playing playlist. Accessed from Menu->Playlist Options->View Current Playlist.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@4124 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--apps/lang/english.lang17
-rw-r--r--apps/playlist.c171
-rw-r--r--apps/playlist.h18
-rw-r--r--apps/playlist_menu.c8
-rw-r--r--apps/playlist_viewer.c848
-rw-r--r--apps/playlist_viewer.h26
-rw-r--r--apps/wps.c29
-rw-r--r--firmware/drivers/lcd-recorder.c23
-rw-r--r--firmware/export/lcd.h1
-rw-r--r--uisimulator/win32/Makefile5
-rw-r--r--uisimulator/win32/rockbox.dsp4
-rw-r--r--uisimulator/x11/Makefile5
12 files changed, 1111 insertions, 44 deletions
diff --git a/apps/lang/english.lang b/apps/lang/english.lang
index 0a1cfaeb51..ce2b300d8c 100644
--- a/apps/lang/english.lang
+++ b/apps/lang/english.lang
@@ -1660,7 +1660,7 @@ new:
1660 1660
1661id: LANG_SAVE_DYNAMIC_PLAYLIST 1661id: LANG_SAVE_DYNAMIC_PLAYLIST
1662desc: in playlist menu. 1662desc: in playlist menu.
1663eng: "Save Dynamic Playlist" 1663eng: "Save Current Playlist"
1664new: 1664new:
1665 1665
1666id: LANG_PLAYLIST_MENU 1666id: LANG_PLAYLIST_MENU
@@ -1827,3 +1827,18 @@ id: LANG_FM_BUTTONBAR_RECORD
1827desc: in main menu 1827desc: in main menu
1828eng: "Record" 1828eng: "Record"
1829new: 1829new:
1830
1831id: LANG_VIEW_DYNAMIC_PLAYLIST
1832desc: in playlist menu.
1833eng: "View Current Playlist"
1834new:
1835
1836id: LANG_MOVE
1837desc: The verb/action Move
1838eng: "Move"
1839new:
1840
1841id: LANG_MOVE_FAILED
1842desc: Error message displayed in playlist viewer
1843eng: "Move failed"
1844new:
diff --git a/apps/playlist.c b/apps/playlist.c
index f834a3d5e7..1ededb2ba9 100644
--- a/apps/playlist.c
+++ b/apps/playlist.c
@@ -146,6 +146,7 @@ static int format_track_path(char *dest, char *src, int buf_length, int max,
146static void display_playlist_count(int count, char *fmt); 146static void display_playlist_count(int count, char *fmt);
147static void display_buffer_full(void); 147static void display_buffer_full(void);
148static int flush_pending_control(void); 148static int flush_pending_control(void);
149static int rotate_index(int index);
149 150
150/* 151/*
151 * remove any files and indices associated with the playlist 152 * remove any files and indices associated with the playlist
@@ -679,11 +680,7 @@ static int get_next_index(int steps)
679 { 680 {
680 case REPEAT_OFF: 681 case REPEAT_OFF:
681 { 682 {
682 /* Rotate indices such that first_index is considered index 0 to 683 current_index = rotate_index(current_index);
683 simplify next calculation */
684 current_index -= playlist.first_index;
685 if (current_index < 0)
686 current_index += playlist.amount;
687 684
688 next_index = current_index+steps; 685 next_index = current_index+steps;
689 if ((next_index < 0) || (next_index >= playlist.amount)) 686 if ((next_index < 0) || (next_index >= playlist.amount))
@@ -993,6 +990,18 @@ static int flush_pending_control(void)
993} 990}
994 991
995/* 992/*
993 * Rotate indices such that first_index is index 0
994 */
995static int rotate_index(int index)
996{
997 index -= playlist.first_index;
998 if (index < 0)
999 index += playlist.amount;
1000
1001 return index;
1002}
1003
1004/*
996 * Initialize playlist entries at startup 1005 * Initialize playlist entries at startup
997 */ 1006 */
998void playlist_init(void) 1007void playlist_init(void)
@@ -1604,25 +1613,108 @@ int playlist_insert_playlist(char *filename, int position, bool queue)
1604 return result; 1613 return result;
1605} 1614}
1606 1615
1607/* delete track at specified index */ 1616/*
1617 * Delete track at specified index. If index is PLAYLIST_DELETE_CURRENT then
1618 * we want to delete the current playing track.
1619 */
1608int playlist_delete(int index) 1620int playlist_delete(int index)
1609{ 1621{
1610 int result; 1622 int result = 0;
1611 1623
1612 if (playlist.control_fd < 0) 1624 if (playlist.control_fd < 0)
1613 { 1625 {
1614 splash(HZ*2, 0, true, str(LANG_PLAYLIST_CONTROL_ACCESS_ERROR)); 1626 splash(HZ*2, 0, true, str(LANG_PLAYLIST_CONTROL_ACCESS_ERROR));
1615 return -1; 1627 return -1;
1616 } 1628 }
1617 1629
1618 result = remove_track_from_playlist(index, true); 1630 if (index == PLAYLIST_DELETE_CURRENT)
1631 index = playlist.index;
1619 1632
1633 result = remove_track_from_playlist(index, true);
1634
1620 if (result != -1) 1635 if (result != -1)
1621 mpeg_flush_and_reload_tracks(); 1636 mpeg_flush_and_reload_tracks();
1622 1637
1623 return result; 1638 return result;
1624} 1639}
1625 1640
1641/*
1642 * Move track at index to new_index. Tracks between the two are shifted
1643 * appropriately. Returns 0 on success and -1 on failure.
1644 */
1645int playlist_move(int index, int new_index)
1646{
1647 int result;
1648 int seek;
1649 bool control_file;
1650 bool queue;
1651 bool current = false;
1652 int r = rotate_index(new_index);
1653 char filename[MAX_PATH];
1654
1655 if (index == new_index)
1656 return -1;
1657
1658 if (index == playlist.index)
1659 /* Moving the current track */
1660 current = true;
1661
1662 control_file = playlist.indices[index] & PLAYLIST_INSERT_TYPE_MASK;
1663 queue = playlist.indices[index] & PLAYLIST_QUEUE_MASK;
1664 seek = playlist.indices[index] & PLAYLIST_SEEK_MASK;
1665
1666 if (get_filename(seek, control_file, filename, sizeof(filename)) < 0)
1667 return -1;
1668
1669 /* Delete track from original position */
1670 result = remove_track_from_playlist(index, true);
1671
1672 if (result != -1)
1673 {
1674 /* We want to insert the track at the position that was specified by
1675 new_index. This may be different then new_index because of the
1676 shifting that occurred after the delete */
1677 if (r == 0)
1678 /* First index */
1679 new_index = PLAYLIST_PREPEND;
1680 else if (r == playlist.amount)
1681 /* Append */
1682 new_index = PLAYLIST_INSERT_LAST;
1683 else
1684 /* Calculate index of desired position */
1685 new_index = (r+playlist.first_index)%playlist.amount;
1686
1687 result = add_track_to_playlist(filename, new_index, queue, -1);
1688
1689 if (result != -1)
1690 {
1691 if (current)
1692 {
1693 /* Moved the current track */
1694 switch (new_index)
1695 {
1696 case PLAYLIST_PREPEND:
1697 playlist.index = playlist.first_index;
1698 break;
1699 case PLAYLIST_INSERT_LAST:
1700 playlist.index = playlist.first_index - 1;
1701 if (playlist.index < 0)
1702 playlist.index += playlist.amount;
1703 break;
1704 default:
1705 playlist.index = new_index;
1706 break;
1707 }
1708 }
1709
1710 fsync(playlist.control_fd);
1711 mpeg_flush_and_reload_tracks();
1712 }
1713 }
1714
1715 return result;
1716}
1717
1626/* shuffle newly created playlist using random seed. */ 1718/* shuffle newly created playlist using random seed. */
1627int playlist_shuffle(int random_seed, int start_index) 1719int playlist_shuffle(int random_seed, int start_index)
1628{ 1720{
@@ -1763,21 +1855,13 @@ int playlist_next(int steps)
1763 index = get_next_index(steps); 1855 index = get_next_index(steps);
1764 playlist.index = index; 1856 playlist.index = index;
1765 1857
1766 if (playlist.last_insert_pos >= 0) 1858 if (playlist.last_insert_pos >= 0 && steps > 0)
1767 { 1859 {
1768 /* check to see if we've gone beyond the last inserted track */ 1860 /* check to see if we've gone beyond the last inserted track */
1769 int rot_index = index; 1861 int cur = rotate_index(index);
1770 int rot_last_pos = playlist.last_insert_pos; 1862 int last_pos = rotate_index(playlist.last_insert_pos);
1771 1863
1772 rot_index -= playlist.first_index; 1864 if (cur > last_pos)
1773 if (rot_index < 0)
1774 rot_index += playlist.amount;
1775
1776 rot_last_pos -= playlist.first_index;
1777 if (rot_last_pos < 0)
1778 rot_last_pos += playlist.amount;
1779
1780 if (rot_index > rot_last_pos)
1781 { 1865 {
1782 /* reset last inserted track */ 1866 /* reset last inserted track */
1783 playlist.last_insert_pos = -1; 1867 playlist.last_insert_pos = -1;
@@ -1826,16 +1910,18 @@ int playlist_get_resume_info(short *resume_index)
1826 index into the playlist */ 1910 index into the playlist */
1827int playlist_get_display_index(void) 1911int playlist_get_display_index(void)
1828{ 1912{
1829 int index = playlist.index;
1830
1831 /* first_index should always be index 0 for display purposes */ 1913 /* first_index should always be index 0 for display purposes */
1832 index -= playlist.first_index; 1914 int index = rotate_index(playlist.index);
1833 if (index < 0)
1834 index += playlist.amount;
1835 1915
1836 return (index+1); 1916 return (index+1);
1837} 1917}
1838 1918
1919/* returns index of first track in playlist */
1920int playlist_get_first_index(void)
1921{
1922 return playlist.first_index;
1923}
1924
1839/* returns number of tracks in playlist (includes queued/inserted tracks) */ 1925/* returns number of tracks in playlist (includes queued/inserted tracks) */
1840int playlist_amount(void) 1926int playlist_amount(void)
1841{ 1927{
@@ -1860,6 +1946,39 @@ char *playlist_name(char *buf, int buf_size)
1860 return buf; 1946 return buf;
1861} 1947}
1862 1948
1949/* Fills info structure with information about track at specified index.
1950 Returns 0 on success and -1 on failure */
1951int playlist_get_track_info(int index, struct playlist_track_info* info)
1952{
1953 int seek;
1954 bool control_file;
1955
1956 if (index < 0 || index >= playlist.amount)
1957 return -1;
1958
1959 control_file = playlist.indices[index] & PLAYLIST_INSERT_TYPE_MASK;
1960 seek = playlist.indices[index] & PLAYLIST_SEEK_MASK;
1961
1962 if (get_filename(seek, control_file, info->filename,
1963 sizeof(info->filename)) < 0)
1964 return -1;
1965
1966 info->attr = 0;
1967
1968 if (control_file)
1969 {
1970 if (playlist.indices[index] & PLAYLIST_QUEUE_MASK)
1971 info->attr |= PLAYLIST_ATTR_QUEUED;
1972 else
1973 info->attr |= PLAYLIST_ATTR_INSERTED;
1974 }
1975
1976 info->index = index;
1977 info->display_index = rotate_index(index) + 1;
1978
1979 return 0;
1980}
1981
1863/* save the current dynamic playlist to specified file */ 1982/* save the current dynamic playlist to specified file */
1864int playlist_save(char *filename) 1983int playlist_save(char *filename)
1865{ 1984{
diff --git a/apps/playlist.h b/apps/playlist.h
index 45ecba505c..82d67bf0bb 100644
--- a/apps/playlist.h
+++ b/apps/playlist.h
@@ -47,6 +47,17 @@ struct playlist_info
47 struct mutex control_mutex; /* mutex for control file access */ 47 struct mutex control_mutex; /* mutex for control file access */
48}; 48};
49 49
50#define PLAYLIST_ATTR_QUEUED 0x01
51#define PLAYLIST_ATTR_INSERTED 0x02
52
53struct playlist_track_info
54{
55 char filename[MAX_PATH]; /* path name of mp3 file */
56 int attr; /* playlist attributes for track */
57 int index; /* index of track in playlist */
58 int display_index; /* index of track for display */
59};
60
50void playlist_init(void); 61void playlist_init(void);
51int playlist_create(char *dir, char *file); 62int playlist_create(char *dir, char *file);
52int playlist_resume(void); 63int playlist_resume(void);
@@ -56,6 +67,7 @@ int playlist_insert_directory(char *dirname, int position, bool queue,
56 bool recurse); 67 bool recurse);
57int playlist_insert_playlist(char *filename, int position, bool queue); 68int playlist_insert_playlist(char *filename, int position, bool queue);
58int playlist_delete(int index); 69int playlist_delete(int index);
70int playlist_move(int index, int new_index);
59int playlist_shuffle(int random_seed, int start_index); 71int playlist_shuffle(int random_seed, int start_index);
60int playlist_randomise(unsigned int seed, bool start_current); 72int playlist_randomise(unsigned int seed, bool start_current);
61int playlist_sort(bool start_current); 73int playlist_sort(bool start_current);
@@ -65,8 +77,10 @@ char *playlist_peek(int steps);
65int playlist_next(int steps); 77int playlist_next(int steps);
66int playlist_get_resume_info(short *resume_index); 78int playlist_get_resume_info(short *resume_index);
67int playlist_get_display_index(void); 79int playlist_get_display_index(void);
80int playlist_get_first_index(void);
68int playlist_amount(void); 81int playlist_amount(void);
69char *playlist_name(char *buf, int buf_size); 82char *playlist_name(char *buf, int buf_size);
83int playlist_get_track_info(int index, struct playlist_track_info* info);
70int playlist_save(char *filename); 84int playlist_save(char *filename);
71 85
72enum { 86enum {
@@ -76,4 +90,8 @@ enum {
76 PLAYLIST_INSERT_FIRST = -4 90 PLAYLIST_INSERT_FIRST = -4
77}; 91};
78 92
93enum {
94 PLAYLIST_DELETE_CURRENT = -1
95};
96
79#endif /* __PLAYLIST_H__ */ 97#endif /* __PLAYLIST_H__ */
diff --git a/apps/playlist_menu.c b/apps/playlist_menu.c
index 4223e3cf72..f4e4867a92 100644
--- a/apps/playlist_menu.c
+++ b/apps/playlist_menu.c
@@ -25,6 +25,7 @@
25#include "playlist.h" 25#include "playlist.h"
26#include "tree.h" 26#include "tree.h"
27#include "settings.h" 27#include "settings.h"
28#include "playlist_viewer.h"
28 29
29#include "lang.h" 30#include "lang.h"
30 31
@@ -64,9 +65,10 @@ bool playlist_menu(void)
64 bool result; 65 bool result;
65 66
66 struct menu_items items[] = { 67 struct menu_items items[] = {
67 { str(LANG_CREATE_PLAYLIST), create_playlist }, 68 { str(LANG_CREATE_PLAYLIST), create_playlist },
68 { str(LANG_SAVE_DYNAMIC_PLAYLIST), save_playlist }, 69 { str(LANG_VIEW_DYNAMIC_PLAYLIST), playlist_viewer },
69 { str(LANG_RECURSE_DIRECTORY), recurse_directory }, 70 { str(LANG_SAVE_DYNAMIC_PLAYLIST), save_playlist },
71 { str(LANG_RECURSE_DIRECTORY), recurse_directory },
70 }; 72 };
71 73
72 m = menu_init( items, sizeof items / sizeof(struct menu_items) ); 74 m = menu_init( items, sizeof items / sizeof(struct menu_items) );
diff --git a/apps/playlist_viewer.c b/apps/playlist_viewer.c
new file mode 100644
index 0000000000..555c9a7128
--- /dev/null
+++ b/apps/playlist_viewer.c
@@ -0,0 +1,848 @@
1/***************************************************************************
2 *
3 * __________ __ ___.
4 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
5 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
6 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
7 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
8 * \/ \/ \/ \/ \/
9 * $Id$
10 *
11 * Copyright (C) 2003 Hardeep Sidhu
12 *
13 * All files in this archive are subject to the GNU General Public License.
14 * See the file COPYING in the source tree root for full license agreement.
15 *
16 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
17 * KIND, either express or implied.
18 *
19 ****************************************************************************/
20
21#include <string.h>
22#include <sprintf.h>
23#include "playlist.h"
24#include "mpeg.h"
25#include "screens.h"
26#include "status.h"
27#include "settings.h"
28#include "icons.h"
29#include "menu.h"
30#include "plugin.h"
31
32#ifdef HAVE_LCD_BITMAP
33#include "widgets.h"
34#endif
35
36#include "lang.h"
37
38/* Defines for LCD display purposes. Taken from tree.c */
39#ifdef HAVE_LCD_BITMAP
40 #define CURSOR_X (global_settings.scrollbar && \
41 viewer.num_tracks>viewer.num_display_lines?1:0)
42 #define CURSOR_Y 0
43 #define CURSOR_WIDTH (global_settings.invert_cursor ? 0 : 4)
44
45 #define ICON_WIDTH ((viewer.char_width > 6) ? viewer.char_width : 6)
46
47 #define MARGIN_X ((global_settings.scrollbar && \
48 viewer.num_tracks > viewer.num_display_lines ? \
49 SCROLLBAR_WIDTH : 0) + CURSOR_WIDTH + ICON_WIDTH)
50 #define MARGIN_Y (global_settings.statusbar ? STATUSBAR_HEIGHT : 0)
51
52 #define LINE_X 0
53 #define LINE_Y (global_settings.statusbar ? 1 : 0)
54
55 #define SCROLLBAR_X 0
56 #define SCROLLBAR_Y lcd_getymargin()
57 #define SCROLLBAR_WIDTH 6
58#else
59 #define MARGIN_X 0
60 #define MARGIN_Y 0
61 #define LINE_X 2
62 #define LINE_Y 0
63 #define CURSOR_X 0
64 #define CURSOR_Y 0
65#endif
66
67/* Maximum number of tracks we can have loaded at one time */
68#define MAX_PLAYLIST_ENTRIES 200
69
70/* Index of track on display line _pos */
71#define INDEX(_pos) (viewer.first_display_index - viewer.first_index + (_pos))
72
73/* Global playlist viewer settings */
74struct playlist_viewer_info {
75 char *name_buffer; /* Buffer used to store track names */
76 int buffer_size; /* Size of name buffer */
77
78 int num_display_lines; /* Number of lines on lcd */
79 int line_height; /* Height (in pixels) of display line */
80 int char_width; /* Width (in pixels) of a character */
81
82 int num_tracks; /* Number of tracks in playlist */
83 short current_playing_track;/* Index of current playing track */
84
85 int num_loaded; /* Number of track entries loaded in viewer */
86 int first_index; /* Index of first loaded track */
87 int last_index; /* Index of last loaded track */
88 int first_display_index; /* Index of first track on display */
89 int last_display_index; /* Index of last track on display */
90 int cursor_pos; /* Line number of cursor */
91
92 int move_track; /* Playlist index of track to move or -1 */
93};
94
95/* Information about a specific track */
96struct playlist_entry {
97 char *name; /* Formatted track name */
98 int index; /* Playlist index */
99 int display_index; /* Display index */
100 bool queued; /* Is track queued? */
101};
102
103static struct playlist_viewer_info viewer;
104static struct playlist_entry tracks[MAX_PLAYLIST_ENTRIES];
105
106#ifdef HAVE_LCD_BITMAP
107extern unsigned char bitmap_icons_6x8[LastIcon][6];
108#endif
109
110static bool initialize(void);
111static void load_playlist_entries(int start_index);
112static void load_playlist_entries_r(int end_index);
113static int load_entry(int index, int pos, char* p, int size);
114static void format_name(char* dest, char* src);
115static void display_playlist(void);
116static void update_display_line(int line, bool scroll);
117static void scroll_display(int lines);
118static void update_first_index(void);
119static bool update_playlist(bool force);
120static int onplay_menu(int index);
121
122/* Initialize the playlist viewer */
123static bool initialize(void)
124{
125 if (!(mpeg_status() & MPEG_STATUS_PLAY))
126 /* Nothing is playing, exit */
127 return false;
128
129 viewer.name_buffer = plugin_get_buffer(&viewer.buffer_size);
130 if (!viewer.name_buffer)
131 return false;
132
133#ifdef HAVE_LCD_BITMAP
134 {
135 char icon_chars[] = "MQ"; /* characters used as icons */
136 unsigned int i;
137
138 viewer.char_width = 0;
139 viewer.line_height = 0;
140
141 /* Use icon characters to calculate largest possible width/height so
142 that we set proper margins */
143 for (i=0; i<sizeof(icon_chars); i++)
144 {
145 char str[2];
146 int w, h;
147
148 snprintf(str, sizeof(str), "%c", icon_chars[i]);
149 lcd_getstringsize(str, &w, &h);
150
151 if (w > viewer.char_width)
152 viewer.char_width = w;
153
154 if (h > viewer.line_height)
155 {
156 viewer.line_height = h;
157 viewer.num_display_lines = (LCD_HEIGHT - MARGIN_Y)/h;
158 }
159 }
160 }
161#else
162 viewer.num_display_lines = 2;
163 viewer.char_width = 1;
164 viewer.line_height = 1;
165#endif
166
167 viewer.cursor_pos = 0;
168 viewer.move_track = -1;
169
170 /* Start displaying at current playing track */
171 viewer.first_display_index = playlist_get_display_index() - 1;
172 update_first_index();
173
174 if (!update_playlist(true))
175 return false;
176
177 return true;
178}
179
180/* Load tracks starting at start_index */
181static void load_playlist_entries(int start_index)
182{
183 int num_entries = viewer.num_tracks - start_index;
184 char* p = viewer.name_buffer;
185 int remaining = viewer.buffer_size;
186 int i;
187
188 viewer.first_index = start_index;
189
190 if (num_entries > MAX_PLAYLIST_ENTRIES)
191 num_entries = MAX_PLAYLIST_ENTRIES;
192
193 for(i=0; i<num_entries; i++, start_index++)
194 {
195 int len = load_entry(start_index, i, p, remaining);
196 if (len < 0)
197 {
198 /* Out of name buffer space */
199 num_entries = i;
200 break;
201 }
202
203 p += len;
204 remaining -= len;
205 }
206
207 viewer.num_loaded = num_entries;
208 viewer.last_index = viewer.first_index + (viewer.num_loaded - 1);
209}
210
211/* Load tracks in reverse, ending at end_index */
212static void load_playlist_entries_r(int end_index)
213{
214 int num_entries = end_index;
215 char* p = viewer.name_buffer;
216 int remaining = viewer.buffer_size;
217 int i;
218
219 viewer.last_index = end_index;
220
221 if (num_entries > MAX_PLAYLIST_ENTRIES)
222 num_entries = MAX_PLAYLIST_ENTRIES;
223
224 for(i=num_entries; i>=0; i--, end_index--)
225 {
226 int len = load_entry(end_index, i, p, remaining);
227 if (len < 0)
228 {
229 int j;
230
231 /* Out of name buffer space */
232 num_entries -= i;
233
234 /* Shift loaded tracks up such that first track is index 0 */
235 for (j=0; j<num_entries; j++, i++)
236 {
237 tracks[j].name = tracks[i].name;
238 tracks[j].index = tracks[i].index;
239 tracks[j].display_index = tracks[i].display_index;
240 tracks[j].queued = tracks[i].queued;
241 }
242
243 break;
244 }
245
246 p += len;
247 remaining -= len;
248 }
249
250 viewer.first_index = viewer.last_index - num_entries;
251
252 num_entries++;
253 if (!viewer.first_index &&
254 num_entries < viewer.num_tracks &&
255 num_entries < MAX_PLAYLIST_ENTRIES)
256 {
257 /* Lets see if we can load more data at the end of the list */
258 int max = viewer.num_tracks;
259 if (max > MAX_PLAYLIST_ENTRIES)
260 max = MAX_PLAYLIST_ENTRIES;
261
262 for (i = num_entries; i<max; i++)
263 {
264 int len = load_entry(num_entries, num_entries, p, remaining);
265 if (len < 0)
266 /* Out of name buffer space */
267 break;
268
269 p += len;
270 remaining -= len;
271
272 num_entries++;
273 viewer.last_index++;
274 }
275 }
276
277 viewer.num_loaded = num_entries;
278}
279
280/* Load track at playlist index. pos is the position in the tracks array and
281 p is a pointer to the name buffer (max size), Returns -1 if buffer is
282 full. */
283static int load_entry(int index, int pos, char* p, int size)
284{
285 struct playlist_track_info info;
286 int len;
287 int result = 0;
288 char name[MAX_PATH];
289
290 /* Playlist viewer orders songs based on display index. We need to
291 convert to real playlist index to access track */
292 index = (index + playlist_get_first_index()) % viewer.num_tracks;
293 if (playlist_get_track_info(index, &info) < 0)
294 return -1;
295
296 format_name(name, info.filename);
297
298 len = strlen(name) + 1;
299
300 if (len <= size)
301 {
302 strcpy(p, name);
303
304 tracks[pos].name = p;
305 tracks[pos].index = info.index;
306 tracks[pos].display_index = info.display_index;
307 tracks[pos].queued = info.attr & PLAYLIST_ATTR_QUEUED;
308
309 result = len;
310 }
311 else
312 result = -1;
313
314 return result;
315}
316
317/* Format trackname for display purposes */
318static void format_name(char* dest, char* src)
319{
320 char* p = strrchr(src, '/');
321 int len;
322
323 /* Only display the mp3 filename */
324 strcpy(dest, p+1);
325 len = strlen(dest);
326
327 /* Remove the extension */
328 if (!strcasecmp(&dest[len-4], ".mp3") ||
329 !strcasecmp(&dest[len-4], ".mp2") ||
330 !strcasecmp(&dest[len-4], ".mpa"))
331 dest[len-4] = '\0';
332}
333
334/* Display tracks on screen */
335static void display_playlist(void)
336{
337 int i;
338 int num_display_tracks =
339 viewer.last_display_index - viewer.first_display_index;
340
341 lcd_clear_display();
342
343#ifdef HAVE_LCD_BITMAP
344 lcd_setmargins(MARGIN_X, MARGIN_Y);
345 lcd_setfont(FONT_UI);
346#endif
347
348 for (i=0; i<=num_display_tracks; i++)
349 {
350 /* Icons */
351 if (tracks[INDEX(i)].index == viewer.current_playing_track)
352 {
353 /* Current playing track */
354#ifdef HAVE_LCD_BITMAP
355 int offset=0;
356 if ( viewer.line_height > 8 )
357 offset = (viewer.line_height - 8) / 2;
358 lcd_bitmap(bitmap_icons_6x8[File],
359 CURSOR_X * 6 + CURSOR_WIDTH,
360 MARGIN_Y+(i*viewer.line_height) + offset,
361 6, 8, true);
362#else
363 lcd_putc(LINE_X-1, i, File);
364#endif
365 }
366 else if (tracks[INDEX(i)].index == viewer.move_track)
367 {
368 /* Track we are moving */
369#ifdef HAVE_LCD_BITMAP
370 lcd_putsxy(CURSOR_X * 6 + CURSOR_WIDTH,
371 MARGIN_Y+(i*viewer.line_height), "M");
372#else
373 lcd_putc(LINE_X-1, i, 'M');
374#endif
375 }
376 else if (tracks[INDEX(i)].queued)
377 {
378 /* Queued track */
379#ifdef HAVE_LCD_BITMAP
380 lcd_putsxy(CURSOR_X * 6 + CURSOR_WIDTH,
381 MARGIN_Y+(i*viewer.line_height), "Q");
382#else
383 lcd_putc(LINE_X-1, i, 'Q');
384#endif
385 }
386
387 update_display_line(i, false);
388 }
389
390#ifdef HAVE_LCD_BITMAP
391 if (global_settings.scrollbar &&
392 (viewer.num_tracks > viewer.num_display_lines))
393 scrollbar(SCROLLBAR_X, SCROLLBAR_Y, SCROLLBAR_WIDTH - 1,
394 LCD_HEIGHT - SCROLLBAR_Y, viewer.num_tracks-1,
395 viewer.first_display_index, viewer.last_display_index,
396 VERTICAL);
397#endif
398
399 put_cursorxy(CURSOR_X, CURSOR_Y + viewer.cursor_pos, true);
400 status_draw(true);
401}
402
403/* Scroll cursor or display by num lines */
404static void scroll_display(int lines)
405{
406 int new_index = viewer.first_display_index + viewer.cursor_pos + lines;
407 bool pagescroll = false;
408 bool wrap = false;
409
410 put_cursorxy(CURSOR_X, CURSOR_Y + viewer.cursor_pos, false);
411
412 if (lines > 1 || lines < -1)
413 pagescroll = true;
414
415 if (new_index < 0)
416 {
417 /* Wrap around if not pageup */
418 if (pagescroll)
419 new_index = 0;
420 else
421 {
422 new_index += viewer.num_tracks;
423 viewer.cursor_pos = viewer.num_display_lines-1;
424 wrap = true;
425 }
426 }
427 else if (new_index >= viewer.num_tracks)
428 {
429 /* Wrap around if not pagedown */
430 if (pagescroll)
431 new_index = viewer.num_tracks - 1;
432 else
433 {
434 new_index -= viewer.num_tracks;
435 viewer.cursor_pos = 0;
436 wrap = true;
437 }
438 }
439
440 if (new_index >= viewer.first_display_index &&
441 new_index <= viewer.last_display_index)
442 {
443 /* Just update the cursor */
444 viewer.cursor_pos = new_index - viewer.first_display_index;
445 }
446 else
447 {
448 /* New track is outside of display */
449 if (wrap)
450 viewer.first_display_index = new_index;
451 else
452 viewer.first_display_index = viewer.first_display_index + lines;
453
454 if (viewer.first_display_index < 0)
455 viewer.first_display_index = 0;
456
457 viewer.last_display_index =
458 viewer.first_display_index + (viewer.num_display_lines - 1);
459 if (viewer.last_display_index >= viewer.num_tracks)
460 {
461 /* display as many tracks as possible on screen */
462 if (viewer.first_display_index > 0)
463 {
464 viewer.first_display_index -=
465 (viewer.last_display_index - viewer.num_tracks + 1);
466 if (viewer.first_display_index < 0)
467 viewer.first_display_index = 0;
468 }
469
470 viewer.last_display_index = viewer.num_tracks - 1;
471 }
472
473 if (viewer.cursor_pos >
474 (viewer.last_display_index - viewer.first_display_index))
475 viewer.cursor_pos =
476 viewer.last_display_index - viewer.first_display_index;
477
478 /* Load more data if needed */
479 if (viewer.first_display_index < viewer.first_index)
480 load_playlist_entries_r(viewer.last_display_index);
481 else if (viewer.last_display_index > viewer.last_index)
482 load_playlist_entries(viewer.first_display_index);
483
484 display_playlist();
485 }
486
487 put_cursorxy(CURSOR_X, CURSOR_Y + viewer.cursor_pos, true);
488}
489
490/* Update lcd line. Scroll line if requested */
491static void update_display_line(int line, bool scroll)
492{
493 char str[MAX_PATH + 16];
494
495 snprintf(str, sizeof(str), "%d. %s",
496 tracks[INDEX(line)].display_index,
497 tracks[INDEX(line)].name);
498
499 if (scroll)
500 {
501#ifdef HAVE_LCD_BITMAP
502 if (global_settings.invert_cursor)
503 lcd_puts_scroll_style(LINE_X, line, str, STYLE_INVERT);
504 else
505#endif
506 lcd_puts_scroll(LINE_X, line, str);
507 }
508 else
509 lcd_puts(LINE_X, line, str);
510}
511
512/* Update first index, if necessary, to put as much as possible on the
513 screen */
514static void update_first_index(void)
515{
516 /* viewer.num_tracks may be invalid at this point */
517 int num_tracks = playlist_amount();
518
519 if ((num_tracks - viewer.first_display_index) < viewer.num_display_lines)
520 {
521 /* Try to display as much as possible */
522 int old_index = viewer.first_display_index;
523
524 viewer.first_display_index = num_tracks - viewer.num_display_lines;
525 if (viewer.first_display_index < 0)
526 viewer.first_display_index = 0;
527
528 /* Cursor should still point at current track */
529 viewer.cursor_pos += old_index - viewer.first_display_index;
530 }
531}
532
533/* Update playlist in case something has changed or forced */
534static bool update_playlist(bool force)
535{
536 playlist_get_resume_info(&viewer.current_playing_track);
537
538 if (force || playlist_amount() != viewer.num_tracks)
539 {
540 int index;
541
542 /* Reload tracks */
543 viewer.num_tracks = playlist_amount();
544 if (viewer.num_tracks < 0)
545 return false;
546
547 index = viewer.first_display_index;
548
549 load_playlist_entries(index);
550
551 if (viewer.num_loaded <= 0)
552 return false;
553
554 viewer.first_display_index = viewer.first_index;
555 viewer.last_display_index =
556 viewer.first_index + viewer.num_display_lines - 1;
557 if (viewer.last_display_index >= viewer.num_tracks)
558 viewer.last_display_index = viewer.num_tracks - 1;
559 }
560
561 display_playlist();
562
563 return true;
564}
565
566/* Menu of playlist commands. Invoked via ON+PLAY on main viewer screen.
567 Returns -1 if USB attached, 0 if no playlist change, and 1 if playlist
568 changed. */
569static int onplay_menu(int index)
570{
571 struct menu_items menu[2]; /* increase this if you add entries! */
572 int m, i=0, result, ret = 0;
573 bool current = (tracks[index].index == viewer.current_playing_track);
574
575 menu[i].desc = str(LANG_DELETE);
576 i++;
577
578 menu[i].desc = str(LANG_MOVE);
579 i++;
580
581 m = menu_init(menu, i);
582 result = menu_show(m);
583 if (result == MENU_ATTACHED_USB)
584 ret = -1;
585 else if (result >= 0)
586 {
587 /* Abort current move */
588 viewer.move_track = -1;
589
590 switch (result)
591 {
592 case 0:
593 /* delete track */
594 if (current)
595 mpeg_stop();
596
597 playlist_delete(tracks[index].index);
598
599 if (current)
600 {
601 /* Start playing new track except if it's the last track
602 in the playlist and repeat mode is disabled */
603 if (tracks[index].display_index != viewer.num_tracks ||
604 global_settings.repeat_mode == REPEAT_ALL)
605 {
606 mpeg_play(0);
607 viewer.current_playing_track = -1;
608 }
609 }
610
611 ret = 1;
612 break;
613 case 1:
614 /* move track */
615 viewer.move_track = tracks[index].index;
616 ret = 0;
617 break;
618 }
619 }
620
621 menu_exit(m);
622
623 return ret;
624}
625
626/* Main viewer function */
627bool playlist_viewer(void)
628{
629 bool exit=false; /* exit viewer */
630 bool update=true; /* update display */
631 bool cursor_on=true; /* used for flashing cursor */
632 int old_cursor_pos; /* last cursor position */
633 int button;
634
635 if (!initialize())
636 return false;
637
638 old_cursor_pos = viewer.cursor_pos;
639
640 while (!exit)
641 {
642 short track;
643
644 /* Timeout so we can determine if play status has changed */
645 button = button_get_w_tmo(HZ/2);
646
647 if (!(mpeg_status() & MPEG_STATUS_PLAY))
648 {
649 /* Play has stopped */
650#ifdef HAVE_LCD_CHARCELLS
651 splash(HZ, 0, true, str(LANG_END_PLAYLIST_PLAYER));
652#else
653 splash(HZ, 0, true, str(LANG_END_PLAYLIST_RECORDER));
654#endif
655 status_set_playmode(STATUS_STOP);
656 return false;;
657 }
658
659 if (viewer.move_track != -1 || !cursor_on)
660 {
661 /* Flash cursor to identify that we are moving a track */
662 cursor_on = !cursor_on;
663#ifdef HAVE_LCD_BITMAP
664 if (global_settings.invert_cursor)
665 {
666 lcd_invertrect(
667 MARGIN_X, MARGIN_Y+(viewer.cursor_pos*viewer.line_height),
668 LCD_WIDTH, viewer.line_height);
669 lcd_invertscroll(LINE_X, viewer.cursor_pos);
670 }
671 else
672 put_cursorxy(CURSOR_X, CURSOR_Y + viewer.cursor_pos,
673 cursor_on);
674
675 lcd_update_rect(
676 0, MARGIN_Y + (viewer.cursor_pos * viewer.line_height),
677 LCD_WIDTH, viewer.line_height);
678#else
679 put_cursorxy(CURSOR_X, CURSOR_Y + viewer.cursor_pos, cursor_on);
680 lcd_update();
681#endif
682 }
683
684 playlist_get_resume_info(&track);
685
686 if (track != viewer.current_playing_track ||
687 playlist_amount() != viewer.num_tracks)
688 {
689 /* Playlist has changed (new track started?) */
690 update_first_index();
691 if (!update_playlist(false))
692 exit = true;
693 else
694 update = true;
695
696 /* Abort move on playlist change */
697 viewer.move_track = -1;
698 }
699
700 switch (button)
701 {
702#ifdef HAVE_RECORDER_KEYPAD
703 case BUTTON_OFF:
704 case BUTTON_LEFT:
705#else
706 case BUTTON_STOP:
707#endif
708 exit = true;
709 break;
710
711#ifdef HAVE_RECORDER_KEYPAD
712 case BUTTON_UP:
713 case BUTTON_UP | BUTTON_REPEAT:
714#else
715 case BUTTON_LEFT:
716 case BUTTON_LEFT | BUTTON_REPEAT:
717#endif
718 scroll_display(-1);
719 update = true;
720 break;
721
722#ifdef HAVE_RECORDER_KEYPAD
723 case BUTTON_DOWN:
724 case BUTTON_DOWN | BUTTON_REPEAT:
725#else
726 case BUTTON_RIGHT:
727 case BUTTON_RIGHT | BUTTON_REPEAT:
728#endif
729 scroll_display(1);
730 update = true;
731 break;
732
733#ifdef HAVE_RECORDER_KEYPAD
734 case BUTTON_ON | BUTTON_UP:
735 case BUTTON_ON | BUTTON_UP | BUTTON_REPEAT:
736#else
737 case BUTTON_ON | BUTTON_LEFT:
738 case BUTTON_ON | BUTTON_LEFT | BUTTON_REPEAT:
739#endif
740 /* Pageup */
741 scroll_display(-viewer.num_display_lines);
742 update = true;
743 break;
744
745#ifdef HAVE_RECORDER_KEYPAD
746 case BUTTON_ON | BUTTON_DOWN:
747 case BUTTON_ON | BUTTON_DOWN | BUTTON_REPEAT:
748#else
749 case BUTTON_ON | BUTTON_RIGHT:
750 case BUTTON_ON | BUTTON_RIGHT | BUTTON_REPEAT:
751#endif
752 /* Pagedown */
753 scroll_display(viewer.num_display_lines);
754 update = true;
755 break;
756
757#ifdef HAVE_RECORDER_KEYPAD
758 case BUTTON_RIGHT:
759#endif
760 case BUTTON_PLAY:
761 if (viewer.move_track >= 0)
762 {
763 /* Move track */
764 int ret;
765
766 ret = playlist_move(viewer.move_track,
767 tracks[INDEX(viewer.cursor_pos)].index);
768 if (ret < 0)
769 splash(HZ, 0, true, str(LANG_MOVE_FAILED));
770
771 update_playlist(true);
772 viewer.move_track = -1;
773 }
774 else
775 {
776 /* Stop current track and play new track */
777 mpeg_stop();
778 playlist_start(tracks[INDEX(viewer.cursor_pos)].index, 0);
779 status_set_playmode(STATUS_PLAY);
780 update_playlist(false);
781 }
782
783 display_playlist();
784 update = true;
785 break;
786
787 case BUTTON_ON | BUTTON_PLAY:
788 {
789 /* ON+PLAY menu */
790 int ret;
791
792 ret = onplay_menu(INDEX(viewer.cursor_pos));
793
794 if (ret < 0)
795 /* USB attached */
796 return true;
797 else if (ret > 0)
798 {
799 /* Playlist changed */
800 update_first_index();
801 update_playlist(true);
802 if (viewer.num_tracks <= 0)
803 exit = true;
804 }
805 else
806 display_playlist();
807
808 update = true;
809 break;
810 }
811 case SYS_USB_CONNECTED:
812 usb_screen();
813 return true;
814 }
815
816 if (update && !exit)
817 {
818 lcd_stop_scroll();
819
820 if (viewer.cursor_pos >
821 (viewer.last_display_index - viewer.first_display_index))
822 {
823 /* Cursor position is invalid */
824 put_cursorxy(CURSOR_X, CURSOR_Y + viewer.cursor_pos, false);
825 viewer.cursor_pos =
826 viewer.last_display_index - viewer.first_display_index;
827 put_cursorxy(CURSOR_X, CURSOR_Y + viewer.cursor_pos, true);
828 }
829
830 if (viewer.cursor_pos != old_cursor_pos &&
831 old_cursor_pos <=
832 (viewer.last_display_index - viewer.first_display_index))
833 /* Stop scrolling previous line */
834 update_display_line(old_cursor_pos, false);
835
836 /* Scroll line at new cursor position */
837 update_display_line(viewer.cursor_pos, true);
838
839 lcd_update();
840
841 old_cursor_pos = viewer.cursor_pos;
842 cursor_on = true;
843 update = false;
844 }
845 }
846
847 return false;
848}
diff --git a/apps/playlist_viewer.h b/apps/playlist_viewer.h
new file mode 100644
index 0000000000..ecc5197566
--- /dev/null
+++ b/apps/playlist_viewer.h
@@ -0,0 +1,26 @@
1/***************************************************************************
2 *
3 * __________ __ ___.
4 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
5 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
6 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
7 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
8 * \/ \/ \/ \/ \/
9 * $Id$
10 *
11 * Copyright (C) 2003 Hardeep Sidhu
12 *
13 * All files in this archive are subject to the GNU General Public License.
14 * See the file COPYING in the source tree root for full license agreement.
15 *
16 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
17 * KIND, either express or implied.
18 *
19 ****************************************************************************/
20
21#ifndef _PLAYLIST_VIEWER_H_
22#define _PLAYLIST_VIEWER_H_
23
24bool playlist_viewer(void);
25
26#endif
diff --git a/apps/wps.c b/apps/wps.c
index 7044369ed5..a39f2ba30c 100644
--- a/apps/wps.c
+++ b/apps/wps.c
@@ -578,8 +578,6 @@ static bool menu(void)
578 status_set_param(false); 578 status_set_param(false);
579#endif 579#endif
580 580
581 wps_display(id3);
582 wps_refresh(id3, 0, WPS_REFRESH_ALL);
583 return false; 581 return false;
584} 582}
585 583
@@ -627,6 +625,7 @@ int wps_show(void)
627 bool ignore_keyup = true; 625 bool ignore_keyup = true;
628 bool restore = false; 626 bool restore = false;
629 bool exit = false; 627 bool exit = false;
628 bool update_track = false;
630 629
631 id3 = NULL; 630 id3 = NULL;
632 current_track_path[0] = '\0'; 631 current_track_path[0] = '\0';
@@ -902,6 +901,7 @@ int wps_show(void)
902 if (menu()) 901 if (menu())
903 return SYS_USB_CONNECTED; 902 return SYS_USB_CONNECTED;
904 903
904 update_track = true;
905 restore = true; 905 restore = true;
906 break; 906 break;
907 907
@@ -939,18 +939,24 @@ int wps_show(void)
939 return SYS_USB_CONNECTED; 939 return SYS_USB_CONNECTED;
940 940
941 case BUTTON_NONE: /* Timeout */ 941 case BUTTON_NONE: /* Timeout */
942 if (update()) 942 update_track = true;
943 {
944 /* set dir browser to current playing song */
945 if (global_settings.browse_current &&
946 current_track_path[0] != '\0')
947 set_current_file(current_track_path);
948
949 return 0;
950 }
951 break; 943 break;
952 } 944 }
953 945
946 if (update_track)
947 {
948 if (update())
949 {
950 /* set dir browser to current playing song */
951 if (global_settings.browse_current &&
952 current_track_path[0] != '\0')
953 set_current_file(current_track_path);
954
955 return 0;
956 }
957 update_track = false;
958 }
959
954 if (exit) { 960 if (exit) {
955#ifdef HAVE_LCD_CHARCELLS 961#ifdef HAVE_LCD_CHARCELLS
956 status_set_record(false); 962 status_set_record(false);
@@ -975,7 +981,6 @@ int wps_show(void)
975 return 0; 981 return 0;
976 } 982 }
977 983
978
979 if ( button ) 984 if ( button )
980 ata_spin(); 985 ata_spin();
981 986
diff --git a/firmware/drivers/lcd-recorder.c b/firmware/drivers/lcd-recorder.c
index 597c7d246a..a409c9fc63 100644
--- a/firmware/drivers/lcd-recorder.c
+++ b/firmware/drivers/lcd-recorder.c
@@ -543,6 +543,29 @@ void lcd_invertrect (int x, int y, int nx, int ny)
543 INVERT_PIXEL((x + i), (y + j)); 543 INVERT_PIXEL((x + i), (y + j));
544} 544}
545 545
546/* Reverse the invert setting of the scrolling line (if any) at given char
547 position. Setting will go into affect next time line scrolls. */
548void lcd_invertscroll(int x, int y)
549{
550 struct scrollinfo* s;
551 int index;
552
553 for ( index = 0; index < SCROLLABLE_LINES; index++ ) {
554 /* is this a scrolling line? */
555 if ( !(scrolling_lines&(1<<index)) )
556 continue;
557
558 s = &scroll[index];
559
560 if (s->startx == x && s->starty == y)
561 {
562 /* Found the line */
563 s->invert = !s->invert;
564 break;
565 }
566 }
567}
568
546void lcd_drawline( int x1, int y1, int x2, int y2 ) 569void lcd_drawline( int x1, int y1, int x2, int y2 )
547{ 570{
548 int numpixels; 571 int numpixels;
diff --git a/firmware/export/lcd.h b/firmware/export/lcd.h
index 3f3ea972c3..f4fa3372cf 100644
--- a/firmware/export/lcd.h
+++ b/firmware/export/lcd.h
@@ -126,6 +126,7 @@ extern void lcd_clearrect (int x, int y, int nx, int ny);
126extern void lcd_fillrect (int x, int y, int nx, int ny); 126extern void lcd_fillrect (int x, int y, int nx, int ny);
127extern void lcd_drawrect (int x, int y, int nx, int ny); 127extern void lcd_drawrect (int x, int y, int nx, int ny);
128extern void lcd_invertrect (int x, int y, int nx, int ny); 128extern void lcd_invertrect (int x, int y, int nx, int ny);
129extern void lcd_invertscroll(int x, int y);
129extern void lcd_drawline( int x1, int y1, int x2, int y2 ); 130extern void lcd_drawline( int x1, int y1, int x2, int y2 );
130extern void lcd_clearline( int x1, int y1, int x2, int y2 ); 131extern void lcd_clearline( int x1, int y1, int x2, int y2 );
131extern void lcd_drawpixel(int x, int y); 132extern void lcd_drawpixel(int x, int y);
diff --git a/uisimulator/win32/Makefile b/uisimulator/win32/Makefile
index cc5ac73ae2..f7b562c0b1 100644
--- a/uisimulator/win32/Makefile
+++ b/uisimulator/win32/Makefile
@@ -101,7 +101,7 @@ FIRMSRCS = $(LCDSRSC) id3.c mp3data.c usb.c mpeg.c powermgmt.c power.c \
101APPS = main.c tree.c menu.c credits.c main_menu.c icons.c language.c \ 101APPS = main.c tree.c menu.c credits.c main_menu.c icons.c language.c \
102 playlist.c wps.c wps-display.c settings.c status.c \ 102 playlist.c wps.c wps-display.c settings.c status.c \
103 screens.c peakmeter.c sleeptimer.c keyboard.c onplay.c\ 103 screens.c peakmeter.c sleeptimer.c keyboard.c onplay.c\
104 misc.c plugin.c 104 misc.c plugin.c playlist_viewer.c
105 105
106MENUS = settings_menu.c sound_menu.c playlist_menu.c 106MENUS = settings_menu.c sound_menu.c playlist_menu.c
107 107
@@ -200,6 +200,9 @@ $(OBJDIR)/onplay.o: $(APPDIR)/onplay.c
200$(OBJDIR)/playlist.o: $(APPDIR)/playlist.c 200$(OBJDIR)/playlist.o: $(APPDIR)/playlist.c
201 $(CC) $(APPCFLAGS) -c $< -o $@ 201 $(CC) $(APPCFLAGS) -c $< -o $@
202 202
203$(OBJDIR)/playlist_viewer.o: $(APPDIR)/playlist_viewer.c
204 $(CC) $(APPCFLAGS) -c $< -o $@
205
203$(OBJDIR)/plugin.o: $(APPDIR)/plugin.c plugin-win32.h 206$(OBJDIR)/plugin.o: $(APPDIR)/plugin.c plugin-win32.h
204 $(CC) $(APPCFLAGS) -c $< -o $@ 207 $(CC) $(APPCFLAGS) -c $< -o $@
205 208
diff --git a/uisimulator/win32/rockbox.dsp b/uisimulator/win32/rockbox.dsp
index dd1ada6dd3..ebfb98fa93 100644
--- a/uisimulator/win32/rockbox.dsp
+++ b/uisimulator/win32/rockbox.dsp
@@ -365,6 +365,10 @@ SOURCE=..\..\apps\playlist_menu.c
365# End Source File 365# End Source File
366# Begin Source File 366# Begin Source File
367 367
368SOURCE=..\..\apps\playlist_viewer.c
369# End Source File
370# Begin Source File
371
368SOURCE=..\..\apps\plugin.c 372SOURCE=..\..\apps\plugin.c
369# End Source File 373# End Source File
370# Begin Source File 374# Begin Source File
diff --git a/uisimulator/x11/Makefile b/uisimulator/x11/Makefile
index 94f4581865..c4b47790a5 100644
--- a/uisimulator/x11/Makefile
+++ b/uisimulator/x11/Makefile
@@ -101,7 +101,7 @@ FIRMSRCS = $(LCDSRSC) id3.c debug.c usb.c mpeg.c power.c\
101APPS = main.c tree.c menu.c credits.c main_menu.c language.c\ 101APPS = main.c tree.c menu.c credits.c main_menu.c language.c\
102 playlist.c wps.c wps-display.c settings.c status.c icons.c\ 102 playlist.c wps.c wps-display.c settings.c status.c icons.c\
103 screens.c peakmeter.c sleeptimer.c keyboard.c onplay.c\ 103 screens.c peakmeter.c sleeptimer.c keyboard.c onplay.c\
104 misc.c plugin.c 104 misc.c plugin.c playlist_viewer.c
105 105
106MENUS = settings_menu.c sound_menu.c playlist_menu.c 106MENUS = settings_menu.c sound_menu.c playlist_menu.c
107 107
@@ -197,6 +197,9 @@ $(OBJDIR)/onplay.o: $(APPDIR)/onplay.c
197$(OBJDIR)/playlist.o: $(APPDIR)/playlist.c 197$(OBJDIR)/playlist.o: $(APPDIR)/playlist.c
198 $(CC) $(APPCFLAGS) -c $< -o $@ 198 $(CC) $(APPCFLAGS) -c $< -o $@
199 199
200$(OBJDIR)/playlist_viewer.o: $(APPDIR)/playlist_viewer.c
201 $(CC) $(APPCFLAGS) -c $< -o $@
202
200$(OBJDIR)/build.lang: $(APPDIR)/lang/$(LANGUAGE).lang 203$(OBJDIR)/build.lang: $(APPDIR)/lang/$(LANGUAGE).lang
201 perl $(TOOLSDIR)/uplang $(APPDIR)/lang/english.lang $< > $@ 204 perl $(TOOLSDIR)/uplang $(APPDIR)/lang/english.lang $< > $@
202 205