1
package org.jaudiotagger.tag.mp4.field;
3
import org.jaudiotagger.tag.TagTextField;
4
import org.jaudiotagger.tag.TagField;
5
import org.jaudiotagger.tag.mp4.atom.Mp4MeanBox;
6
import org.jaudiotagger.tag.mp4.atom.Mp4NameBox;
7
import org.jaudiotagger.tag.mp4.atom.Mp4DataBox;
8
import org.jaudiotagger.tag.mp4.Mp4TagField;
9
import org.jaudiotagger.tag.mp4.Mp4FieldKey;
10
import org.jaudiotagger.audio.mp4.atom.Mp4BoxHeader;
11
import org.jaudiotagger.audio.generic.Utils;
13
import java.io.UnsupportedEncodingException;
14
import java.io.ByteArrayOutputStream;
15
import java.io.IOException;
16
import java.nio.ByteBuffer;
19
* Represents reverse dns field, used for custom information
21
* <p>Originally only used by Itunes for information that was iTunes specific but now used in a wide range of uses,
22
* for example Musicbrainz uses it for many of its fields.
24
* These fields have a more complex setup
25
* Box ---- shows this is a reverse dns metadata field
26
* Box mean the issuer in the form of reverse DNS domain (e.g com.apple.iTunes)
27
* Box name descriptor identifying the type of contents
30
* The raw data passed starts from the mean box
32
public class Mp4TagReverseDnsField extends Mp4TagField implements TagTextField
34
public static final String IDENTIFIER = "----";
36
protected int dataSize;
39
private String issuer;
42
private String descriptor;
44
//Data Content, TODO assuming always text at the moment
45
protected String content;
48
* Construct from existing file data
51
* @throws UnsupportedEncodingException
53
public Mp4TagReverseDnsField(ByteBuffer data) throws UnsupportedEncodingException
59
* Newly created Reverse Dns field
64
public Mp4TagReverseDnsField(Mp4FieldKey id, String content)
66
super(id.getFieldName());
67
this.issuer = id.getIssuer();
68
this.descriptor = id.getIdentifier();
69
this.content = content;
72
public Mp4FieldType getFieldType()
74
//TODO always assuming text at moment but may not always be the case (though dont have any concrete
76
return Mp4FieldType.TEXT;
79
protected void build(ByteBuffer data) throws UnsupportedEncodingException
81
//Read mean box, set the issuer and skip over data
82
Mp4BoxHeader meanBoxHeader = new Mp4BoxHeader(data);
83
Mp4MeanBox meanBox = new Mp4MeanBox(meanBoxHeader,data);
84
setIssuer(meanBox.getIssuer());
85
data.position(data.position()+meanBoxHeader.getDataLength());
87
//Read name box, identify what type of field it is
88
Mp4BoxHeader nameBoxHeader = new Mp4BoxHeader(data);
89
Mp4NameBox nameBox = new Mp4NameBox(nameBoxHeader,data);
90
setDescriptor(nameBox.getName());
91
data.position(data.position()+nameBoxHeader.getDataLength());
93
//Read data box, identify the data
94
Mp4BoxHeader dataBoxHeader = new Mp4BoxHeader(data);
95
Mp4DataBox dataBox = new Mp4DataBox(dataBoxHeader,data);
96
setContent(dataBox.getContent());
97
data.position(data.position()+dataBoxHeader.getDataLength());
99
//Now calculate the id which in order to be unique needs to use all htree values
100
id=IDENTIFIER+":"+issuer+":"+descriptor;
105
public void copyContent(TagField field)
107
if (field instanceof Mp4TagReverseDnsField)
109
this.issuer = ((Mp4TagReverseDnsField) field).getIssuer();
110
this.descriptor = ((Mp4TagReverseDnsField) field).getDescriptor();
111
this.content = ((Mp4TagReverseDnsField) field).getContent();
119
public String getContent()
125
protected byte[] getDataBytes() throws UnsupportedEncodingException
127
return content.getBytes(getEncoding());
130
public String getEncoding()
132
return Mp4BoxHeader.CHARSET_UTF_8;
136
* Convert back to raw content, includes ----,mean,name and data atom as views as one thing externally
139
* @throws UnsupportedEncodingException
141
public byte[] getRawContent() throws UnsupportedEncodingException
145
ByteArrayOutputStream baos = new ByteArrayOutputStream();
147
//Create Meanbox data
148
byte [] issuerRawData = issuer.getBytes(getEncoding());
149
baos.write(Utils.getSizeBigEndian(Mp4BoxHeader.HEADER_LENGTH
150
+ Mp4MeanBox.PRE_DATA_LENGTH
151
+ issuerRawData.length));
152
baos.write(Utils.getDefaultBytes(Mp4MeanBox.IDENTIFIER,"ISO-8859-1"));
153
baos.write(new byte[]{0, 0, 0, 0});
154
baos.write(issuerRawData);
156
//Create Namebox data
157
byte [] nameRawData = descriptor.getBytes(getEncoding());
158
baos.write(Utils.getSizeBigEndian(Mp4BoxHeader.HEADER_LENGTH
159
+ Mp4NameBox.PRE_DATA_LENGTH
160
+ nameRawData.length));
161
baos.write(Utils.getDefaultBytes(Mp4NameBox.IDENTIFIER,"ISO-8859-1"));
162
baos.write(new byte[]{0, 0, 0, 0});
163
baos.write(nameRawData);
165
//Create DataBox data
166
baos.write(getRawContentDataOnly());
168
//Now wrap with reversedns box
169
ByteArrayOutputStream outerbaos = new ByteArrayOutputStream();
170
outerbaos.write(Utils.getSizeBigEndian(Mp4BoxHeader.HEADER_LENGTH + baos.size()));
171
outerbaos.write(Utils.getDefaultBytes(IDENTIFIER,"ISO-8859-1"));
172
outerbaos.write(baos.toByteArray());
173
return outerbaos.toByteArray();
175
catch(IOException ioe)
177
//This should never happen as were not actually writing to/from a file
178
throw new RuntimeException(ioe);
182
public byte[] getRawContentDataOnly() throws UnsupportedEncodingException
184
logger.fine("Getting Raw data for:"+getId());
187
//Create DataBox data
188
ByteArrayOutputStream baos = new ByteArrayOutputStream();
189
byte [] dataRawData = content.getBytes(getEncoding());
190
baos.write(Utils.getSizeBigEndian(Mp4BoxHeader.HEADER_LENGTH
191
+ Mp4DataBox.PRE_DATA_LENGTH
192
+ dataRawData.length));
193
baos.write(Utils.getDefaultBytes(Mp4DataBox.IDENTIFIER,"ISO-8859-1"));
194
baos.write(new byte[]{0});
195
baos.write(new byte[]{0, 0, (byte) getFieldType().getFileClassId()});
196
baos.write(new byte[]{0, 0, 0, 0});
197
baos.write(dataRawData);
198
return baos.toByteArray();
200
catch (IOException ioe)
202
//This should never happen as were not actually writing to/from a file
203
throw new RuntimeException(ioe);
207
public boolean isBinary()
212
public boolean isEmpty()
214
return this.content.trim().equals("");
217
public void setContent(String s)
222
public void setEncoding(String s)
227
public String toString()
236
public String getIssuer()
243
* @return the descriptor
245
public String getDescriptor()
251
* Set the issuer, usually reverse dns of the Companies domain
255
public void setIssuer(String issuer)
257
this.issuer = issuer;
261
* Set the descriptor for the data (what type of data it is)
265
public void setDescriptor(String descriptor)
267
this.descriptor = descriptor;