/******************************************************************************* * Copyright (c) 2013 Jens Kristian Villadsen. * All rights reserved. This program and the accompanying materials * are made available under the terms of the GNU Public License v3.0 * which accompanies this distribution, and is available at * http://www.gnu.org/licenses/gpl.html * * Contributors: * Jens Kristian Villadsen - Lead developer, owner and creator ******************************************************************************/ /* * Digital Audio Access Protocol (DAAP) Library * Copyright (C) 2004-2010 Roger Kapsi * * 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. */ package org.dyndns.jkiddo.dmp; import java.io.BufferedOutputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.OutputStream; import org.dyndns.jkiddo.dmp.chunks.BooleanChunk; import org.dyndns.jkiddo.dmp.chunks.ByteChunk; import org.dyndns.jkiddo.dmp.chunks.Chunk; import org.dyndns.jkiddo.dmp.chunks.ContainerChunk; import org.dyndns.jkiddo.dmp.chunks.DateChunk; import org.dyndns.jkiddo.dmp.chunks.IntChunk; import org.dyndns.jkiddo.dmp.chunks.LongChunk; import org.dyndns.jkiddo.dmp.chunks.RawChunk; import org.dyndns.jkiddo.dmp.chunks.ShortChunk; import org.dyndns.jkiddo.dmp.chunks.StringChunk; import org.dyndns.jkiddo.dmp.chunks.VersionChunk; public class DmapOutputStream extends BufferedOutputStream { public DmapOutputStream(OutputStream out) { super(out); } public void writeShort(int i) throws IOException { write((i >> 8) & 0xFF); write(i & 0xFF); } public void writeInt(int i) throws IOException { write((i >> 24) & 0xFF); write((i >> 16) & 0xFF); write((i >> 8) & 0xFF); write(i & 0xFF); } public void writeLong(long l) throws IOException { write((int) ((l >> 56l) & 0xFF)); write((int) ((l >> 48l) & 0xFF)); write((int) ((l >> 40l) & 0xFF)); write((int) ((l >> 32l) & 0xFF)); write((int) ((l >> 24l) & 0xFF)); write((int) ((l >> 16l) & 0xFF)); write((int) ((l >> 8l) & 0xFF)); write((int) (l & 0xFF)); } /* * public void writeString(String s) throws IOException { if (s != null && s.length() > 0) { write(s.getBytes(DaapUtil.UTF_8)); } } */ public void writeContentCode(int contentCode) throws IOException { writeInt(contentCode); } public void writeLength(int length) throws IOException { writeInt(length); } public void writeByteChunk(ByteChunk chunk) throws IOException { int value = chunk.getValue(); // Don't write booleans if state is false b/c // the presence of the chunk is interpereted // as true or false (i.e. value is don't care)! if(value == 0 && chunk instanceof BooleanChunk) { return; } writeContentCode(chunk.getContentCode()); writeLength(1); write(value); } public void writeShortChunk(ShortChunk chunk) throws IOException { int value = chunk.getValue(); writeContentCode(chunk.getContentCode()); writeLength(2); writeShort(value); } public void writeIntChunk(IntChunk chunk) throws IOException { int value = chunk.getValue(); writeContentCode(chunk.getContentCode()); writeLength(4); writeInt(value); } public void writeLongChunk(LongChunk chunk) throws IOException { long value = chunk.getValue(); writeContentCode(chunk.getContentCode()); writeLength(8); writeLong(value); } public void writeStringChunk(StringChunk chunk) throws IOException { byte[] value = chunk.getBytes(); writeContentCode(chunk.getContentCode()); writeLength(value.length); write(value); //write(value, 0, value.length); } public void writeRawChunk(RawChunk chunk) throws IOException { byte[] value = chunk.getValue(); writeContentCode(chunk.getContentCode()); writeLength(value.length); write(value); //write(value, 0, value.length); } public void writeDateChunk(DateChunk chunk) throws IOException { int value = (int) (chunk.getValue() & 0xFFFFFFFF); writeContentCode(chunk.getContentCode()); writeLength(4); writeInt(value); } public void writeVersionChunk(VersionChunk chunk) throws IOException { int value = (int) (chunk.getValue() & 0xFFFFFFFF); writeContentCode(chunk.getContentCode()); writeLength(4); writeInt(value); } public void writeContainerChunk(ContainerChunk chunk) throws IOException { ByteArrayOutputStream buffer = new ByteArrayOutputStream(); DmapOutputStream out = new DmapOutputStream(buffer); for(Chunk chnk : chunk) out.writeChunk(chnk); out.close(); byte[] b = buffer.toByteArray(); writeContentCode(chunk.getContentCode()); writeLength(b.length); write(b, 0, b.length); } public void writeChunk(Chunk chunk) throws IOException { if(chunk == null) { throw new NullPointerException("Cannot write null Chunk"); } if(chunk instanceof ByteChunk) { writeByteChunk((ByteChunk) chunk); } else if(chunk instanceof ShortChunk) { writeShortChunk((ShortChunk) chunk); } else if(chunk instanceof IntChunk) { writeIntChunk((IntChunk) chunk); } else if(chunk instanceof LongChunk) { writeLongChunk((LongChunk) chunk); } else if(chunk instanceof StringChunk) { writeStringChunk((StringChunk) chunk); } else if(chunk instanceof RawChunk) { writeRawChunk((RawChunk) chunk); } else if(chunk instanceof DateChunk) { writeDateChunk((DateChunk) chunk); } else if(chunk instanceof VersionChunk) { writeVersionChunk((VersionChunk) chunk); } else if(chunk instanceof ContainerChunk) { writeContainerChunk((ContainerChunk) chunk); } else { throw new RuntimeException("Unknown Chunk Type: " + chunk + ", " + chunk.getClass()); } } }