summaryrefslogtreecommitdiff
path: root/apps/dbtree.c
diff options
context:
space:
mode:
authorBjörn Stenberg <bjorn@haxx.se>2005-01-17 11:39:46 +0000
committerBjörn Stenberg <bjorn@haxx.se>2005-01-17 11:39:46 +0000
commit8a5de5fec96171e739442b0601047d93079e3179 (patch)
tree5d0a66bea94f7296aaaacc6d42ceecb84e736242 /apps/dbtree.c
parentfc53fd708fc12e1a67217c102ea8180b2bde6a6f (diff)
downloadrockbox-8a5de5fec96171e739442b0601047d93079e3179.tar.gz
rockbox-8a5de5fec96171e739442b0601047d93079e3179.zip
Added ID3 database support. Still very early.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@5575 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps/dbtree.c')
-rw-r--r--apps/dbtree.c343
1 files changed, 343 insertions, 0 deletions
diff --git a/apps/dbtree.c b/apps/dbtree.c
new file mode 100644
index 0000000000..f9bd950057
--- /dev/null
+++ b/apps/dbtree.c
@@ -0,0 +1,343 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2002 by Björn Stenberg
11 *
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.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19#include <stdio.h>
20#include <string.h>
21#include "file.h"
22#include "screens.h"
23#include "kernel.h"
24#include "tree.h"
25#include "lcd.h"
26#include "font.h"
27#include "settings.h"
28#include "icons.h"
29#include "status.h"
30#include "debug.h"
31#include "button.h"
32#include "menu.h"
33#include "main_menu.h"
34#include "mpeg.h"
35#include "misc.h"
36#include "ata.h"
37#include "wps.h"
38#include "filetypes.h"
39#include "applimits.h"
40#include "dbtree.h"
41#include "icons.h"
42
43#ifdef LITTLE_ENDIAN
44#include <netinet/in.h>
45#define BE32(_x_) htonl(_x_)
46#else
47#define BE32(_x_) _x_
48#endif
49
50static int fd;
51
52static int
53 songstart, albumstart, artiststart,
54 songcount, albumcount, artistcount,
55 songlen, songarraylen,
56 albumlen, albumarraylen,
57 artistlen;
58
59int db_init(void)
60{
61 unsigned int version;
62 unsigned int buf[12];
63
64 fd = open(ROCKBOX_DIR "/rockbox.id3db", O_RDONLY);
65 if (fd < 0) {
66 DEBUGF("Failed opening database\n");
67 return -1;
68 }
69 read(fd, buf, 48);
70
71 version = BE32(buf[0]) & 0xff;
72 DEBUGF("Version: RDB%d\n", version);
73
74 songstart = BE32(buf[1]);
75 songcount = BE32(buf[2]);
76 songlen = BE32(buf[3]);
77 DEBUGF("Number of songs: %d\n", songcount);
78 DEBUGF("Songstart: %x\n", songstart);
79 DEBUGF("Songlen: %d\n", songlen);
80
81 albumstart = BE32(buf[4]);
82 albumcount = BE32(buf[5]);
83 albumlen = BE32(buf[6]);
84 songarraylen = BE32(buf[7]);
85 DEBUGF("Number of albums: %d\n", albumcount);
86 DEBUGF("Albumstart: %x\n", albumstart);
87 DEBUGF("Albumlen: %d\n", albumlen);
88
89 artiststart = BE32(buf[8]);
90 artistcount = BE32(buf[9]);
91 artistlen = BE32(buf[10]);
92 albumarraylen = BE32(buf[11]);
93 DEBUGF("Number of artists: %d\n", artistcount);
94 DEBUGF("Artiststart: %x\n", artiststart);
95 DEBUGF("Artistlen: %d\n", artistlen);
96
97 return 0;
98}
99
100int db_load(struct tree_context* c, bool* dir_buffer_full)
101{
102 int i, offset, len, rc;
103 int dcachesize = global_settings.max_files_in_dir * sizeof(struct entry);
104 int max_items, itemcount, stringlen;
105 unsigned int* nptr = (void*) c->name_buffer;
106 unsigned int* dptr = c->dircache;
107 unsigned int* safeplace = NULL;
108
109 int table = c->currtable;
110 int extra = c->currextra;
111 c->dentry_size = 2 * sizeof(int);
112
113 DEBUGF("db_load(%d, %x)\n", table, extra);
114
115 if (!table) {
116 table = allartists;
117 c->currtable = table;
118 }
119
120 switch (table) {
121 case allsongs:
122 offset = songstart;
123 itemcount = songcount;
124 stringlen = songlen;
125 break;
126
127 case allalbums:
128 offset = albumstart;
129 itemcount = albumcount;
130 stringlen = albumlen;
131 break;
132
133 case allartists:
134 offset = artiststart;
135 itemcount = artistcount;
136 stringlen = artistlen;
137 break;
138
139 case albums:
140 /* 'extra' is offset to the artist */
141 len = albumarraylen * 4;
142 safeplace = (void*)(c->name_buffer + c->name_buffer_size - len);
143 //DEBUGF("Seeking to %x\n", extra + artistlen);
144 lseek(fd, extra + artistlen, SEEK_SET);
145 rc = read(fd, safeplace, len);
146 if (rc < len)
147 return -1;
148
149#ifdef LITTLE_ENDIAN
150 for (i=0; i<albumarraylen; i++)
151 safeplace[i] = BE32(safeplace[i]);
152#endif
153
154 offset = safeplace[0];
155 itemcount = albumarraylen;
156 stringlen = albumlen;
157 break;
158
159 case songs:
160 /* 'extra' is offset to the album */
161 len = songarraylen * 4;
162 safeplace = (void*)(c->name_buffer + c->name_buffer_size - len);
163 //DEBUGF("Seeking to %x\n", extra + albumlen + 4);
164 lseek(fd, extra + albumlen + 4, SEEK_SET);
165 rc = read(fd, safeplace, len);
166 if (rc < len)
167 return -1;
168
169#ifdef LITTLE_ENDIAN
170 for (i=0; i<songarraylen; i++)
171 safeplace[i] = BE32(safeplace[i]);
172#endif
173 offset = safeplace[0];
174 itemcount = songarraylen;
175 stringlen = songlen;
176 break;
177
178 default:
179 DEBUGF("Unsupported table %d\n", table);
180 return -1;
181 }
182 max_items = dcachesize / c->dentry_size;
183
184 if (!safeplace) {
185 //DEBUGF("Seeking to %x\n", offset);
186 lseek(fd, offset, SEEK_SET);
187 }
188
189 /* name_buffer (nptr) contains only names, null terminated.
190 the first word of dcache (dptr) is a pointer to the name,
191 the rest is table specific. see below. */
192
193 if (itemcount > max_items)
194 if (dir_buffer_full)
195 *dir_buffer_full = true;
196
197 if (max_items > itemcount) {
198 max_items = itemcount;
199 }
200
201 for ( i=0; i < max_items; i++ ) {
202 int rc, skip=0;
203
204 if (safeplace) {
205 if (!safeplace[i])
206 break;
207 //DEBUGF("Seeking to %x\n", safeplace[i]);
208 lseek(fd, safeplace[i], SEEK_SET);
209 offset = safeplace[i];
210 }
211
212 /* read name */
213 rc = read(fd, nptr, stringlen);
214 if (rc < stringlen)
215 {
216 DEBUGF("%d read(%d) returned %d\n", i, stringlen, rc);
217 return -1;
218 }
219
220 /* store name pointer in dir cache */
221 dptr[0] = (unsigned int)nptr;
222
223 switch (table) {
224 case songs:
225 case allsongs:
226 /* save offset of this song */
227 skip = 12;
228 dptr[1] = offset;
229 break;
230
231 case allalbums:
232 case albums:
233 /* save offset of this album */
234 skip = songarraylen * 4 + 4;
235 dptr[1] = offset;
236 break;
237
238 case allartists:
239 /* save offset of this artist */
240 skip = albumarraylen * 4;
241 dptr[1] = offset;
242 break;
243 }
244
245 //DEBUGF("%x: %s\n", dptr[1], dptr[0]);
246
247 if (skip)
248 lseek(fd, skip, SEEK_CUR);
249
250 /* next name is stored immediately after this */
251 nptr = (void*)nptr + strlen((char*)nptr) + 1;
252 if ((void*)nptr > (void*)c->name_buffer + c->name_buffer_size) {
253 DEBUGF("Name buffer overflow (%d)\n",i);
254 break;
255 }
256 dptr = (void*)dptr + c->dentry_size;
257
258 if (!safeplace)
259 offset += stringlen + skip;
260 }
261
262 c->filesindir = i;
263
264 return i;
265}
266
267void db_enter(struct tree_context* c)
268{
269 switch (c->currtable) {
270 case allartists:
271 case albums:
272 c->dirpos[c->dirlevel] = c->dirstart;
273 c->cursorpos[c->dirlevel] = c->dircursor;
274 c->table_history[c->dirlevel] = c->currtable;
275 c->extra_history[c->dirlevel] = c->currextra;
276 c->dirlevel++;
277 break;
278
279 default:
280 break;
281 }
282
283 switch (c->currtable) {
284 case allartists:
285 c->currtable = albums;
286 c->currextra = ((int*)c->dircache)[(c->dircursor + c->dirstart)*2 + 1];
287 break;
288
289 case albums:
290 c->currtable = songs;
291 c->currextra = ((int*)c->dircache)[(c->dircursor + c->dirstart)*2 + 1];
292 break;
293
294 case songs:
295 splash(HZ,true,"No playing implemented yet");
296#if 0
297 /* find filenames, build playlist, play */
298 playlist_create(NULL,NULL);
299#endif
300 break;
301
302 default:
303 break;
304 }
305
306 c->dirstart = c->dircursor = 0;
307}
308
309void db_exit(struct tree_context* c)
310{
311 c->dirlevel--;
312 c->dirstart = c->dirpos[c->dirlevel];
313 c->dircursor = c->cursorpos[c->dirlevel];
314 c->currtable = c->table_history[c->dirlevel];
315 c->currextra = c->extra_history[c->dirlevel];
316}
317
318#ifdef HAVE_LCD_BITMAP
319const char* db_get_icon(struct tree_context* c)
320{
321 int icon;
322
323 switch (c->currtable)
324 {
325 case allsongs:
326 case songs:
327 icon = File;
328 break;
329
330 default:
331 icon = Folder;
332 break;
333 }
334
335 return bitmap_icons_6x8[icon];
336}
337#else
338int db_get_icon(struct tree_context* c)
339{
340 (void)c;
341 return Folder;
342}
343#endif