package com.mpatric.mp3agic; import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.Arrays; public class ID3v2ChapterTOCFrameData extends AbstractID3v2FrameData { protected boolean isRoot; protected boolean isOrdered; protected String id; protected String[] children; protected ArrayList<ID3v2Frame> subframes = new ArrayList<ID3v2Frame>(); public ID3v2ChapterTOCFrameData(boolean unsynchronisation) { super(unsynchronisation); } public ID3v2ChapterTOCFrameData(boolean unsynchronisation, boolean isRoot, boolean isOrdered, String id, String[] children) { super(unsynchronisation); this.isRoot = isRoot; this.isOrdered = isOrdered; this.id = id; this.children = children; } public ID3v2ChapterTOCFrameData(boolean unsynchronisation, byte[] bytes) throws InvalidDataException { super(unsynchronisation); synchroniseAndUnpackFrameData(bytes); } protected void unpackFrameData(byte[] bytes) throws InvalidDataException { ByteBuffer bb = ByteBuffer.wrap(bytes); id = ByteBufferUtils.extractNullTerminatedString(bb); byte flags = bb.get(); if ((flags & 0x01) == 0x01) { isRoot = true; } if ((flags & 0x02) == 0x02) { isOrdered = true; } int childCount = bb.get(); // TODO: 0xFF -> int = 255; byte = -128; children = new String[childCount]; for (int i = 0; i < childCount; i++) { children[i] = ByteBufferUtils.extractNullTerminatedString(bb); } for (int offset = bb.position(); offset < bytes.length;) { ID3v2Frame frame = new ID3v2Frame(bytes, offset); offset += frame.getLength(); subframes.add(frame); } } public void addSubframe(String id, AbstractID3v2FrameData frame) { subframes.add(new ID3v2Frame(id, frame.toBytes())); } protected byte[] packFrameData() { ByteBuffer bb = ByteBuffer.allocate(getLength()); bb.put(id.getBytes()); bb.put((byte) 0); bb.put(getFlags()); bb.put((byte)children.length); for(String child: children) { bb.put(child.getBytes()); bb.put((byte) 0); } for (ID3v2Frame frame : subframes) { try { bb.put(frame.toBytes()); } catch (NotSupportedException e) { e.printStackTrace(); } } return bb.array(); } private byte getFlags() { byte b = 0; if(isRoot) { b |= 0x01; } if(isOrdered) { b |= 0x02; } return b; } public boolean isRoot() { return isRoot; } public void setRoot(boolean isRoot) { this.isRoot = isRoot; } public boolean isOrdered() { return isOrdered; } public void setOrdered(boolean isOrdered) { this.isOrdered = isOrdered; } public String getId() { return id; } public void setId(String id) { this.id = id; } public String[] getChildren() { return children; } public void setChildren(String[] children) { this.children = children; } @Deprecated public String[] getChilds() { return children; } @Deprecated public void setChilds(String[] childs) { this.children = childs; } public ArrayList<ID3v2Frame> getSubframes() { return subframes; } public void setSubframes(ArrayList<ID3v2Frame> subframes) { this.subframes = subframes; } @Override protected int getLength() { int length = 3; if (id != null) length += id.length(); if (children != null) { length += children.length; for (String child : children) { length += child.length(); } } if (subframes != null) { for (ID3v2Frame frame : subframes) { length += frame.getLength(); } } return length; } @Override public String toString() { StringBuilder builder = new StringBuilder(); builder.append("ID3v2ChapterTOCFrameData [isRoot="); builder.append(isRoot); builder.append(", isOrdered="); builder.append(isOrdered); builder.append(", id="); builder.append(id); builder.append(", children="); builder.append(Arrays.toString(children)); builder.append(", subframes="); builder.append(subframes); builder.append("]"); return builder.toString(); } @Override public int hashCode() { final int prime = 31; int result = super.hashCode(); result = prime * result + Arrays.hashCode(children); result = prime * result + ((id == null) ? 0 : id.hashCode()); result = prime * result + (isOrdered ? 1231 : 1237); result = prime * result + (isRoot ? 1231 : 1237); result = prime * result + ((subframes == null) ? 0 : subframes.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (!super.equals(obj)) return false; if (getClass() != obj.getClass()) return false; ID3v2ChapterTOCFrameData other = (ID3v2ChapterTOCFrameData) obj; if (!Arrays.equals(children, other.children)) return false; if (id == null) { if (other.id != null) return false; } else if (!id.equals(other.id)) return false; if (isOrdered != other.isOrdered) return false; if (isRoot != other.isRoot) return false; if (subframes == null) { if (other.subframes != null) return false; } else if (!subframes.equals(other.subframes)) return false; return true; } }