/* Change playlist. The response comes as plain XML. */ public void sendChangePlaylist( ChannelListener listener, Playlist playlist, String xml, String packetDescription) throws DespotifyException { /* Create channel and buffer. */ Channel channel = new Channel("Change-Playlist-Channel", Channel.Type.TYPE_PLAYLIST, listener); byte[] xmlBytes = xml.getBytes(); ByteBuffer buffer = ByteBuffer.allocate(2 + 17 + 4 + 4 + 4 + 1 + 1 + xmlBytes.length); /* Append channel id, playlist id and some bytes... */ buffer.putShort((short) channel.getId()); buffer.put(playlist.getByteUUID()); /* 16 bytes */ buffer.put((byte) 0x00); // 0x00 for adding tracks, 0x02 for the rest? buffer.putInt(playlist.getRevision().intValue()); buffer.putInt(playlist.getTracks().size()); buffer.putInt(playlist.getChecksum().intValue()); /* -1: Create playlist. */ buffer.put((byte) (playlist.isCollaborative() ? 0x01 : 0x00)); buffer.put((byte) 0x03); /* Unknown */ buffer.put(xmlBytes); buffer.flip(); /* Register channel. */ Channel.register(channel); /* Send packet. */ this.sendPacket(PacketType.changePlaylist, buffer, packetDescription); }
/* Request image using a 20 byte id. The response is a JPG. */ public void sendImageRequest(ChannelListener listener, String id) throws DespotifyException { /* Create channel and buffer. */ Channel channel = new Channel("Image-Channel", Channel.Type.TYPE_IMAGE, listener); ByteBuffer buffer = ByteBuffer.allocate(2 + 20); /* Append channel id and image hash. */ buffer.putShort((short) channel.getId()); buffer.put(Hex.toBytes(id)); buffer.flip(); /* Register channel. */ Channel.register(channel); /* Send packet. */ this.sendPacket(PacketType.image, buffer); }
/* Request ads. The response is GZIP compressed XML. */ public void sendAdRequest(ChannelListener listener, int type) throws DespotifyException { /* Create channel and buffer. */ Channel channel = new Channel("Ad-Channel", Channel.Type.TYPE_AD, listener); ByteBuffer buffer = ByteBuffer.allocate(2 + 1); /* Append channel id and ad type. */ buffer.putShort((short) channel.getId()); buffer.put((byte) type); buffer.flip(); /* Register channel. */ Channel.register(channel); /* Send packet. */ this.sendPacket(PacketType.requestAd, buffer); }
/* Request AES key for a track. */ public void sendAesKeyRequest(ChannelListener listener, Track track) throws DespotifyException { /* Create channel and buffer. */ Channel channel = new Channel("AES-Key-Channel", Channel.Type.TYPE_AESKEY, listener); ByteBuffer buffer = ByteBuffer.allocate(20 + 16 + 2 + 2); /* Request the AES key for this file by sending the file id and track id. */ buffer.put(Hex.toBytes(track.getFiles().get(0))); /* 20 bytes */ buffer.put(track.getByteUUID()); /* 16 bytes */ buffer.putShort((short) 0x0000); buffer.putShort((short) channel.getId()); buffer.flip(); /* Register channel. */ Channel.register(channel); /* Send packet. */ this.sendPacket(PacketType.requestKey, buffer); }
/* * Request a part of the encrypted file from the server. * * The data should be decrypted using AES key in CTR mode * with AES key provided and a static IV, incremented for * each 16 byte data processed. */ public void sendSubstreamRequest(ChannelListener listener, Track track, int offset, int length) throws DespotifyException { /* Create channel and buffer. */ Channel channel = new Channel("Substream-Channel", Channel.Type.TYPE_SUBSTREAM, listener); ByteBuffer buffer = ByteBuffer.allocate(2 + 2 + 2 + 2 + 2 + 2 + 4 + 20 + 4 + 4); /* Append channel id. */ buffer.putShort((short) channel.getId()); /* Unknown 10 bytes. */ buffer.putShort((short) 0x0800); buffer.putShort((short) 0x0000); buffer.putShort((short) 0x0000); buffer.putShort((short) 0x0000); buffer.putShort((short) 0x4e20); /* Unknown (static value) */ buffer.putInt(200 * 1000); /* 20 bytes file id. */ buffer.put(Hex.toBytes(track.getFiles().get(0))); if (offset % 4096 != 0 || length % 4096 != 0) { throw new IllegalArgumentException("Offset and length need to be a multiple of 4096."); } offset >>= 2; length >>= 2; /* Append offset and length. */ buffer.putInt(offset); buffer.putInt(offset + length); buffer.flip(); /* Register channel. */ Channel.register(channel); /* Send packet. */ this.sendPacket(PacketType.getSubStream, buffer); }