/********************************************************************************* * TotalCross Software Development Kit * * Copyright (C) 2000-2012 SuperWaba Ltda. * * All Rights Reserved * * * * This library and virtual machine is distributed in the hope that it will * * be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * * * * This file is covered by the GNU LESSER GENERAL PUBLIC LICENSE VERSION 3.0 * * A copy of this license is located in file license.txt at the root of this * * SDK or can be downloaded here: * * http://www.gnu.org/licenses/lgpl-3.0.txt * * * *********************************************************************************/ package totalcross.ui.media; import totalcross.io.File; import totalcross.io.IOException; import totalcross.io.RandomAccessStream; public class MediaClip4D { Object mediaClipRef; RandomAccessStream mediaStream; protected String path; byte[] mediaHeader = new byte[46]; int mediaDataSize; int currentState; boolean loaded; int size; boolean dontFinalize; boolean stopped; boolean finished; boolean isRecording; int dataPos; int internalState; public final static int UNREALIZED = 0; public final static int REALIZED = 1; public final static int PREFETCHED = 2; public final static int STARTED = 3; public final static int CLOSED = 4; public static final int VOICE = 8000; public static final int LOW = 11025; public static final int MEDIUM = 22050; public static final int HIGH = 44100; public MediaClip4D(RandomAccessStream stream) throws IOException { mediaStream = stream; if (stream instanceof File) this.path = ((File) stream).getPath(); create(); currentState = UNREALIZED; } final native private void create(); public int getCurrentState() { return currentState; } final public void start() throws IOException { if (currentState == PREFETCHED) { // resume nativeStart(); } else if (currentState == UNREALIZED) { int subChunkId; int subChunkSize; // REALIZE WAVE FILE dataPos += mediaStream.readBytes(mediaHeader, 0, 36); subChunkSize = (((mediaHeader[19] & 0xFF) << 24) | ((mediaHeader[18] & 0xFF) << 16) | ((mediaHeader[17] & 0xFF) << 8) | (mediaHeader[16] & 0xFF)); if (subChunkSize > 16) { dataPos += mediaStream.readBytes(mediaHeader, 36, 2); subChunkSize = (((mediaHeader[37] & 0xFF) << 8) | (mediaHeader[36] & 0xFF)); } else subChunkSize = 0; do { if (subChunkSize > 0) { dataPos += mediaStream.skipBytes(subChunkSize); } dataPos += mediaStream.readBytes(mediaHeader, 38, 4); subChunkId = (((mediaHeader[41] & 0xFF) << 24) | ((mediaHeader[40] & 0xFF) << 16) | ((mediaHeader[39] & 0xFF) << 8) | (mediaHeader[38] & 0xFF)); dataPos += mediaStream.readBytes(mediaHeader, 42, 4); subChunkSize = (((mediaHeader[45] & 0xFF) << 24) | ((mediaHeader[44] & 0xFF) << 16) | ((mediaHeader[43] & 0xFF) << 8) | (mediaHeader[42] & 0xFF)); } while (subChunkId != 0x61746164); // 'data' in big endian mediaDataSize = subChunkSize; // PREFETCH - prepare stuff before starting // START - actually start playing nativeStart(); } } final native private void nativeStart(); final native public void stop(); final native public void reset(); final native private void nativeClose(); final public void close() throws totalcross.io.IOException { if (currentState != CLOSED) { dontFinalize = true; nativeClose(); } } public void onEvent(MediaClipEvent evt) { } native public void record(int samplesPerSecond, int bitsPerSample, boolean stereo) throws totalcross.io.IOException; public void finalize() { if (currentState != CLOSED) { try { this.close(); } catch (IOException e) { } } } }