1
/***************************************************************************
2
copyright : (C) 2005 by Martin Aumueller
3
email : aumuell@reserv.at
5
copyright : (C) 2005 by Andy Leadbetter
6
email : andrew.leadbetter@gmail.com
7
(original mp4 implementation)
8
***************************************************************************/
10
/***************************************************************************
11
* This library is free software; you can redistribute it and/or modify *
12
* it under the terms of the GNU Lesser General Public License version *
13
* 2.1 as published by the Free Software Foundation. *
15
* This library is distributed in the hope that it will be useful, but *
16
* WITHOUT ANY WARRANTY; without even the implied warranty of *
17
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
18
* Lesser General Public License for more details. *
20
* You should have received a copy of the GNU Lesser General Public *
21
* License along with this library; if not, write to the Free Software *
22
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, *
24
***************************************************************************/
26
#include "audibletag.h"
33
#if !defined(_WIN32) && !defined(_WIN64)
34
#include <netinet/in.h> // ntohl
39
using namespace TagLib;
42
m_title = String::null;
43
m_artist = String::null;
44
m_album = String::null;
45
m_comment = String::null;
46
m_genre = String::null;
53
Audible::Tag::~Tag() {
56
bool Audible::Tag::isEmpty() const {
57
return m_title == String::null &&
58
m_artist == String::null &&
59
m_album == String::null &&
60
m_comment == String::null &&
61
m_genre == String::null &&
67
void Audible::Tag::duplicate(const Tag *source, Tag *target, bool overwrite) {
68
// No nonstandard information stored yet
69
TagLib::Tag::duplicate(source, target, overwrite);
72
#define OFF_PRODUCT_ID 197
75
void Audible::Tag::readTags( FILE *fp )
78
if ( fseek(fp, OFF_PRODUCT_ID, SEEK_SET) != 0 )
81
if ( fread(buf, strlen("product_id"), 1, fp) != 1 )
84
if(memcmp(buf, "product_id", strlen("product_id")))
87
fprintf(stderr, "no valid Audible aa file: %s\n", buf);
93
fseek(fp, OFF_TAGS, SEEK_SET);
94
char *name = 0, *value = 0;
96
m_tagsEndOffset = OFF_TAGS;
101
lasttag = !readTag(fp, &name, &value);
102
if(!strcmp(name, "title"))
104
m_title = String(value, String::Latin1);
106
else if(!strcmp(name, "author"))
108
m_artist = String(value, String::Latin1);
110
else if(!strcmp(name, "long_description"))
112
m_comment = String(value, String::Latin1);
114
else if(!strcmp(name, "description"))
116
if( m_comment.isNull() )
117
m_comment = String(value, String::Latin1);
119
else if(!strcmp(name, "pubdate"))
123
char *p = value ? strrchr(value, '-') : 0;
125
m_year = strtol(p+1, NULL, 10);
127
else if(!strcmp(name, "user_id"))
129
m_userID = value ? strtol(value, NULL, 10) : -1;
138
m_album = String("", String::Latin1);
140
m_genre = String("Audiobook", String::Latin1);
143
bool Audible::Tag::readTag( FILE *fp, char **name, char **value)
145
// arbitrary value that has to be smaller than 2^32-1 and that should be large enough for all tags
146
const uint32_t maxtaglen = 100000;
149
if ( fread(&nlen, sizeof(nlen), 1, fp) != 1 )
153
//fprintf(stderr, "tagname len=%x\n", (unsigned)nlen);
156
*name = new char[nlen+1];
159
(*name)[nlen] = '\0';
162
if ( fread(&vlen, sizeof(vlen), 1, fp) != 1 )
170
if (vlen > maxtaglen)
176
//fprintf(stderr, "tag len=%x\n", (unsigned)vlen);
177
if ( fread(*name, nlen, 1, fp) != 1 )
184
*value = new char[vlen+1];
191
(*value)[vlen] = '\0';
193
if ( fread(*value, vlen, 1, fp) != 1 )
201
if ( fread(&lasttag, 1, 1, fp) != 1 )
204
//fprintf(stderr, "%s: \"%s\"\n", *name, *value);
206
m_tagsEndOffset += 2 * 4 + nlen + vlen + 1;
211
int Audible::Tag::getTagsEndOffset()
213
return m_tagsEndOffset;