// Near Infinity - An Infinity Engine Browser and Editor
// Copyright (C) 2001 - 2005 Jon Olav Hauglid
// See LICENSE.txt for license information
package org.infinity.resource.video;
import java.util.ArrayDeque;
import java.util.Deque;
/**
* Represents a container for audio chunks returned by the MveDecoder.
*/
public class AudioQueue
{
private final Deque<AudioBlock> deque;
/**
* Constructs an empty audio queue.
*/
public AudioQueue()
{
deque = new ArrayDeque<AudioBlock>();
}
/**
* Returns whether one or more audio blocks are available.
* @return {@code true} if one or more audio blocks are available, {@code false} otherwise.
*/
public synchronized boolean hasNext()
{
return !deque.isEmpty();
}
/**
* Returns the index of the next audio block without actually removing it.
* @return The index of the next audio block, or -1 if no audio block is available.
*/
public synchronized int peekNextIndex()
{
return hasNext() ? deque.peekFirst().index : -1;
}
/**
* Returns the size of the next audio block without actually removing it.
* @return The size in bytes of the next audio block, or -1 if no audio block is available.
*/
public synchronized int peekNextDataSize()
{
return hasNext() ? deque.peekFirst().data.length : -1;
}
/**
* Returns the next available audio block without actually removing it.
* @return The next available audio block as byte array, or {@code null} otherwise.
*/
public synchronized byte[] peekNextData()
{
return hasNext() ? deque.peekFirst().data : null;
}
/**
* Returns the next available audio block.
* @return The next available audio block as byte array, or {@code null} otherwise.
*/
public synchronized byte[] getNextData()
{
return hasNext() ? deque.pollFirst().data : null;
}
/**
* Blocks the current thread until an audio block is available.
* @return The next available audio block as byte array.
*/
public byte[] getNextDataWait()
{
while (!hasNext()) {
try {
Thread.sleep(5);
} catch (InterruptedException e) {
}
}
synchronized (deque) {
return deque.pollFirst().data;
}
}
/**
* Removes the next available block in the queue.
* @return {@code true} if the next block in the queue has been discarded,
* {@code false} if no blocks were available.
*/
public boolean skipNext()
{
if (hasNext()) {
deque.pollFirst();
return true;
} else {
return false;
}
}
/**
* Removes all remaining audio blocks from the queue.
*/
public synchronized void clear()
{
deque.clear();
}
/**
* Adds a new audio block to the queue. Note: This is done automatically by the decoder.
* @param index The index of the audio block
* @param data The audio data
* @return {@code true} if a valid block has been added successfully, {@code false} otherwise.
*/
public synchronized boolean addAudioBlock(int index, byte[] data)
{
if (index >= 0 && data != null) {
try {
deque.addLast(new AudioBlock(index, data));
return true;
} catch (Throwable t) {
}
}
return false;
}
//----------------------------- INNER CLASSES -----------------------------
private class AudioBlock
{
public final int index; // sequential number, can be used to sort audio blocks
public final byte[] data; // uncompressed audio data in the globally specified audio format
public AudioBlock(int index, byte[] data)
{
this.index = index;
this.data = data;
}
}
}