1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2005 Dave Chapman
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 ****************************************************************************/
29 #include "metadata_common.h"
30 #include "metadata_parsers.h"
33 /* Define LOGF_ENABLE to enable logf output in this file */
34 /*#define LOGF_ENABLE*/
41 long packet_remaining
;
45 /* Read an Ogg page header. file->packet_remaining is set to the size of the
46 * first packet on the page; file->packet_ended is set to true if the packet
47 * ended on the current page. Returns true if the page header was
50 static bool file_read_page_header(struct file
* file
)
52 unsigned char buffer
[64];
55 /* Size of page header without segment table */
56 if (read(file
->fd
, buffer
, 27) != 27)
61 if (memcmp("OggS", buffer
, 4))
66 /* Skip pattern (4), version (1), flags (1), granule position (8),
67 * serial (4), pageno (4), checksum (4)
69 table_left
= buffer
[26];
70 file
->packet_remaining
= 0;
72 /* Read segment table for the first packet */
75 ssize_t count
= MIN(sizeof(buffer
), (size_t) table_left
);
78 if (read(file
->fd
, buffer
, count
) < count
)
85 for (i
= 0; i
< count
; i
++)
87 file
->packet_remaining
+= buffer
[i
];
91 file
->packet_ended
= true;
93 /* Skip remainder of the table */
94 if (lseek(file
->fd
, table_left
, SEEK_CUR
) < 0)
104 while (table_left
> 0);
110 /* Read (up to) buffer_size of data from the file. If buffer is NULL, just
111 * skip ahead buffer_size bytes (like lseek). Returns number of bytes read,
112 * 0 if there is no more data to read (in the packet or the file), < 0 if a
113 * read error occurred.
115 static ssize_t
file_read(struct file
* file
, void* buffer
, size_t buffer_size
)
122 if (file
->packet_remaining
<= 0)
124 if (file
->packet_ended
)
129 if (!file_read_page_header(file
))
136 count
= MIN(buffer_size
, (size_t) file
->packet_remaining
);
140 count
= read(file
->fd
, buffer
, count
);
144 if (lseek(file
->fd
, count
, SEEK_CUR
) < 0)
160 buffer_size
-= count
;
162 file
->packet_remaining
-= count
;
164 while (buffer_size
> 0);
166 return (count
< 0 ? count
: done
);
170 /* Read an int32 from file. Returns false if a read error occurred.
172 static bool file_read_int32(struct file
* file
, int32_t* value
)
174 char buf
[sizeof(int32_t)];
176 if (file_read(file
, buf
, sizeof(buf
)) < (ssize_t
) sizeof(buf
))
181 *value
= get_long_le(buf
);
186 /* Read a string from the file. Read up to buffer_size bytes, or, if eos
187 * != -1, until the eos character is found (eos is not stored in buf,
188 * unless it is nil). Writes up to buffer_size chars to buf, always
189 * terminating with a nil. Returns number of chars read or < 0 if a read
192 * Unfortunately this is a slightly modified copy of read_string() in
193 * metadata_common.c...
195 static long file_read_string(struct file
* file
, char* buffer
,
196 long buffer_size
, int eos
, long size
)
204 if (file_read(file
, &c
, 1) != 1)
213 if ((eos
!= -1) && (eos
== (unsigned char) c
))
225 /* No point in reading any more, skip remaining data */
226 if (file_read(file
, NULL
, size
) < 0)
244 /* Init struct file for reading from fd. type is the AFMT_* codec type of
245 * the file, and determines if Ogg pages are to be read. remaining is the
246 * max amount to read if codec type is FLAC; it is ignored otherwise.
247 * Returns true if the file was successfully initialized.
249 static bool file_init(struct file
* file
, int fd
, int type
, int remaining
)
251 memset(file
, 0, sizeof(*file
));
254 if (type
== AFMT_OGG_VORBIS
|| type
== AFMT_SPEEX
)
256 if (!file_read_page_header(file
))
262 if (type
== AFMT_OGG_VORBIS
)
266 /* Read packet header (type and id string) */
267 if (file_read(file
, buffer
, sizeof(buffer
)) < (ssize_t
) sizeof(buffer
))
272 /* The first byte of a packet is the packet type; comment packets
280 else if (type
== AFMT_FLAC
)
282 file
->packet_remaining
= remaining
;
283 file
->packet_ended
= true;
290 /* Read the items in a Vorbis comment packet. For Ogg files, the file must
291 * be located on a page start, for other files, the beginning of the comment
292 * data (i.e., the vendor string length). Returns total size of the
293 * comments, or 0 if there was a read error.
295 long read_vorbis_tags(int fd
, struct mp3entry
*id3
,
299 char *buf
= id3
->id3v2buf
;
300 int32_t comment_count
;
302 long comment_size
= 0;
303 int buf_remaining
= sizeof(id3
->id3v2buf
) + sizeof(id3
->id3v1buf
);
306 if (!file_init(&file
, fd
, id3
->codectype
, tag_remaining
))
311 /* Skip vendor string */
313 if (!file_read_int32(&file
, &len
) || (file_read(&file
, NULL
, len
) < 0))
318 if (!file_read_int32(&file
, &comment_count
))
323 comment_size
+= 4 + len
+ 4;
325 for (i
= 0; i
< comment_count
&& file
.packet_remaining
> 0; i
++)
327 char name
[TAG_NAME_LENGTH
];
330 if (!file_read_int32(&file
, &len
))
335 comment_size
+= 4 + len
;
336 read_len
= file_read_string(&file
, name
, sizeof(name
), '=', len
);
345 if (file_read_string(&file
, id3
->path
, sizeof(id3
->path
), -1, len
) < 0)
350 logf("Vorbis comment %d: %s=%s", i
, name
, id3
->path
);
351 len
= parse_tag(name
, id3
->path
, id3
, buf
, buf_remaining
,
354 buf_remaining
-= len
;
357 /* Skip to the end of the block (needed by FLAC) */
358 if (file
.packet_remaining
)
360 if (file_read(&file
, NULL
, file
.packet_remaining
) < 0)