1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
|
/*
* Copyright (C) Texas Instruments - http://www.ti.com/
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#define LOG_TAG "APE_TAG"
#include <utils/Log.h>
#include "include/APE.h"
namespace android {
APE::APE(){
}
APE::~APE(){
}
bool APE::isAPE(uint8_t *apeTag) const {
if(apeTag[0] == 'A' && apeTag[1] == 'P' && apeTag[2] == 'E' &&
apeTag[3] == 'T' && apeTag[4] == 'A' && apeTag[5] == 'G' &&
apeTag[6] == 'E' && apeTag[7] == 'X'){
return true;
}
return false;
}
size_t sizeItemKey(const sp<DataSource> &source, off64_t offset){
off64_t ItemKeyOffset = offset;
uint8_t keyTerminator = 0;
size_t keySize = 0;
while (keyTerminator != 0){
source->readAt(ItemKeyOffset, &keyTerminator, 1);
ItemKeyOffset++;
keySize++;
}
return keySize - 1;
}
bool APE::parseAPE(const sp<DataSource> &source, off64_t offset,
sp<MetaData> &meta){
struct Map {
int key;
const char *tag;
} const kMap[] = {
{ kKeyAlbum, "Album" },
{ kKeyArtist, "Artist" },
{ kKeyAlbumArtist, "Album" },
{ kKeyComposer, "Composer" },
{ kKeyGenre, "Genre" },
{ kKeyTitle, "Title" },
{ kKeyYear, "Year" },
{ kKeyCDTrackNumber, "Track" },
{ kKeyDate, "Record Date"},
};
static const size_t kNumMapEntries = sizeof(kMap) / sizeof(kMap[0]);
off64_t headerOffset = offset;
headerOffset += 16;
itemNumber = 0;
if (source->readAt(headerOffset, &itemNumber, 1) == 0)
return false;
headerOffset += 16;
for(uint32_t it = 0; it < itemNumber; it++){
lenValue = 0;
if (source->readAt(headerOffset, &lenValue, 1) == 0)
return false;
headerOffset += 4;
itemFlags = 0;
if (source->readAt(headerOffset, &itemFlags, 1) == 0)
return false;
headerOffset += 4;
size_t sizeKey = sizeItemKey(source, headerOffset);
char *key = new char[sizeKey];
if (source->readAt(headerOffset, key, sizeKey) == 0)
return false;
key[sizeKey] = '\0';
headerOffset += sizeKey + 1;
char *val = new char[lenValue + 1];
if (source->readAt(headerOffset, val, lenValue) == 0)
return false;
val[lenValue] = '\0';
for (size_t i = 0; i < kNumMapEntries; i++){
if (!strcmp(key, kMap[i].tag)){
if (itemFlags == 0)
meta->setCString(kMap[i].key, (const char *)val);
break;
}
}
headerOffset += lenValue;
delete[] key;
delete[] val;
}
return true;
}
} //namespace android
|