package eu.hgross.blaubotcam.audio; import android.content.Context; import android.media.MediaPlayer; import android.media.audiofx.Visualizer; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.charset.Charset; import java.util.UUID; import java.util.concurrent.CountDownLatch; import eu.hgross.blaubot.util.Log; /** * Message to be sent */ public class WalkieTalkieMessage { public static final String LOG_TAG = WalkieTalkieMessage.class.getSimpleName(); private static final ByteOrder BYTE_ORDER = ByteOrder.BIG_ENDIAN; private static final Charset CHARSET = Charset.forName("UTF-8"); private byte[] audioBytes; private String senderUniqueDeviceId; private WalkieTalkieMessage() { } public WalkieTalkieMessage(byte[] audioBytes, String senderUniqueDeviceId) { this.senderUniqueDeviceId = senderUniqueDeviceId; this.audioBytes = audioBytes; } public byte[] getAudioBytes() { return audioBytes; } public String getSenderUniqueDeviceId() { return senderUniqueDeviceId; } /** * Plays the containing audio message. * Blocks until playback was completed. * * @throws IOException if there is not enough space to store the temp audio file */ public void play(Context context) throws IOException { final File outputFile = File.createTempFile("BlaubotTemp" + UUID.randomUUID(), "3gp", context.getCacheDir()); FileOutputStream fos = new FileOutputStream(outputFile); fos.write(getAudioBytes()); fos.close(); final MediaPlayer player = new MediaPlayer(); try { final CountDownLatch latch = new CountDownLatch(1); player.setDataSource(outputFile.getAbsolutePath()); player.prepare(); player.setOnCompletionListener(new MediaPlayer.OnCompletionListener() { @Override public void onCompletion(MediaPlayer mp) { Log.d(LOG_TAG, "MediaPlayer.onCompletion()"); player.release(); outputFile.delete(); latch.countDown(); } }); player.start(); try { latch.await(); } catch (InterruptedException e) { } } catch (IOException e) { if (Log.logErrorMessages()) { Log.e(LOG_TAG, "prepare() to play failed: " + e.getMessage()); } } } /** * Serializes the message to a byte array * * @return the byte array */ public byte[] toBytes() { // allocate buffer for 2 ints inidicating the length and the actual lenghts of the data attributes ByteBuffer bb = ByteBuffer.allocate(4 + 4 + audioBytes.length + senderUniqueDeviceId.length()); bb.order(BYTE_ORDER); bb.putInt(audioBytes.length); bb.putInt(senderUniqueDeviceId.length()); bb.put(audioBytes); bb.put(senderUniqueDeviceId.getBytes(CHARSET)); bb.flip(); return bb.array(); } /** * Deserializes the message from a byte array * * @param bytes the bytes to deserialize * @return the deserialized message */ public static WalkieTalkieMessage fromBytes(byte[] bytes) { ByteBuffer bb = ByteBuffer.wrap(bytes); // get size of needed buffers final int audioBytesLength = bb.getInt(); final int senderUniqueDeviceIdLength = bb.getInt(); // allocate byte arrays byte[] audioBytesBuffer = new byte[audioBytesLength]; byte[] senderUniqueDeviceIdBuffer = new byte[senderUniqueDeviceIdLength]; // fill buffers bb.get(audioBytesBuffer, 0, audioBytesLength); bb.get(senderUniqueDeviceIdBuffer, 0, senderUniqueDeviceIdLength); // construct message final WalkieTalkieMessage message = new WalkieTalkieMessage(); message.audioBytes = audioBytesBuffer; message.senderUniqueDeviceId = new String(senderUniqueDeviceIdBuffer, CHARSET); return message; } }