1
package org.jaudiotagger.audio.asf.io;
3
import org.jaudiotagger.audio.asf.data.*;
4
import org.jaudiotagger.audio.asf.util.Utils;
6
import java.io.IOException;
7
import java.io.InputStream;
8
import java.math.BigInteger;
11
* Reads an interprets "Metadata Object", "Metadata Library
12
* Object" and "Extended Content Description" of ASF files.<br>
14
* @author Christian Laireiter
16
public class MetadataReader implements ChunkReader {
19
* The GUID this reader {@linkplain #getApplyingIds() applies to}
21
private final static GUID[] APPLYING = {
22
ContainerType.EXTENDED_CONTENT.getContainerGUID(),
23
ContainerType.METADATA_OBJECT.getContainerGUID(),
24
ContainerType.METADATA_LIBRARY_OBJECT.getContainerGUID() };
29
public boolean canFail() {
36
public GUID[] getApplyingIds() {
37
return APPLYING.clone();
43
public Chunk read(final GUID guid, final InputStream stream,
44
final long streamPosition) throws IOException {
45
final BigInteger chunkLen = Utils.readBig64(stream);
47
final MetadataContainer result = new MetadataContainer(guid,
48
streamPosition, chunkLen);
49
// isExtDesc will be set to true, if a extended content description
51
// otherwise it is a metadata object, there are only slight differences
52
final boolean isExtDesc = result.getContainerType() == ContainerType.EXTENDED_CONTENT;
53
final int recordCount = Utils.readUINT16(stream);
54
for (int i = 0; i < recordCount; i++) {
55
int languageIndex = 0;
59
* Metadata objects have a language index and a stream number
61
languageIndex = Utils.readUINT16(stream);
62
assert languageIndex >= 0
63
&& languageIndex < MetadataDescriptor.MAX_LANG_INDEX;
64
assert result.getContainerType() == ContainerType.METADATA_LIBRARY_OBJECT
65
|| languageIndex == 0;
66
streamNumber = Utils.readUINT16(stream);
67
assert streamNumber >= 0
68
&& streamNumber <= MetadataDescriptor.MAX_STREAM_NUMBER;
70
final int nameLen = Utils.readUINT16(stream);
71
String recordName = null;
73
recordName = Utils.readFixedSizeUTF16Str(stream, nameLen);
75
final int dataType = Utils.readUINT16(stream);
76
assert dataType >= 0 && dataType <= 6;
77
final long dataLen = isExtDesc ? Utils.readUINT16(stream) : Utils
80
assert result.getContainerType() == ContainerType.METADATA_LIBRARY_OBJECT
81
|| dataLen <= MetadataDescriptor.DWORD_MAXVALUE;
83
recordName = Utils.readFixedSizeUTF16Str(stream, nameLen);
85
final MetadataDescriptor descriptor = new MetadataDescriptor(result
86
.getContainerType(), recordName, dataType, streamNumber,
89
case MetadataDescriptor.TYPE_STRING:
90
descriptor.setStringValue(Utils.readFixedSizeUTF16Str(stream,
93
case MetadataDescriptor.TYPE_BINARY:
94
descriptor.setBinaryValue(Utils.readBinary(stream, dataLen));
96
case MetadataDescriptor.TYPE_BOOLEAN:
97
assert isExtDesc && dataLen == 4 || !isExtDesc && dataLen == 2;
98
descriptor.setBooleanValue(readBoolean(stream, (int) dataLen));
100
case MetadataDescriptor.TYPE_DWORD:
102
descriptor.setDWordValue(Utils.readUINT32(stream));
104
case MetadataDescriptor.TYPE_WORD:
106
descriptor.setWordValue(Utils.readUINT16(stream));
108
case MetadataDescriptor.TYPE_QWORD:
110
descriptor.setQWordValue(Utils.readUINT64(stream));
112
case MetadataDescriptor.TYPE_GUID:
113
assert dataLen == GUID.GUID_LENGTH;
114
descriptor.setGUIDValue(Utils.readGUID(stream));
117
// Unknown, hopefully the convention for the size of the
119
// is given, so we could read it binary
120
descriptor.setStringValue("Invalid datatype: "
121
+ new String(Utils.readBinary(stream, dataLen)));
123
result.addDescriptor(descriptor);
129
* Reads the given amount of bytes and checks the last byte, if its equal to
130
* one or zero (true / false).<br>
131
* All other bytes must be zero. (if assertions enabled).
134
* stream to read from.
137
* @return <code>true</code> or <code>false</code>.
138
* @throws IOException
141
private boolean readBoolean(final InputStream stream, final int bytes)
143
final byte[] tmp = new byte[bytes];
145
boolean result = false;
146
for (int i = 0; i < bytes; i++) {
147
if (i == bytes - 1) {
148
result = tmp[i] == 1;
149
assert tmp[i] == 0 || tmp[i] == 1;