/*
Реализация спецификаций CLDC версии 1.1 (JSR-139), MIDP версии 2.1 (JSR-118)
и других спецификаций для функционирования компактных приложений на языке
Java (мидлетов) в среде программного обеспечения Малик Эмулятор.
Copyright © 2016, 2019 Малик Разработчик
Это свободная программа: вы можете перераспространять ее и/или изменять
ее на условиях Меньшей Стандартной общественной лицензии GNU в том виде,
в каком она была опубликована Фондом свободного программного обеспечения;
либо версии 3 лицензии, либо (по вашему выбору) любой более поздней версии.
Эта программа распространяется в надежде, что она будет полезной,
но БЕЗО ВСЯКИХ ГАРАНТИЙ; даже без неявной гарантии ТОВАРНОГО ВИДА
или ПРИГОДНОСТИ ДЛЯ ОПРЕДЕЛЕННЫХ ЦЕЛЕЙ. Подробнее см. в Меньшей Стандартной
общественной лицензии GNU.
Вы должны были получить копию Меньшей Стандартной общественной лицензии GNU
вместе с этой программой. Если это не так, см.
<https://www.gnu.org/licenses/>.
*/
package malik.emulator.io.j2me;
import javax.microedition.media.*;
public abstract class CustomPlayer extends Object
implements Control, Controllable, Player
{
private static final PlayerEventsListenerThread EVENTS_LISTENER;
private static final TimeBase SYSTEM_TIME_BASE;
static
{
PlayerEventsListenerThread t;
EVENTS_LISTENER = t = new PlayerEventsListenerThread();
SYSTEM_TIME_BASE = new SystemTimeBase();
t.start();
}
public static final TimeBase getSystemTimeBase()
{
return SYSTEM_TIME_BASE;
}
final class Event extends Object
{
private String event;
private Object data;
public Event(String event, Object data)
{
this.event = event;
this.data = data;
}
public void invokePlayerUpdateFromListeners()
{
int i;
PlayerListener[] listeners;
PlayerListener listener;
CustomPlayer player = CustomPlayer.this;
String event = this.event;
Object data = this.data;
for(i = (listeners = player.listeners) != null ? listeners.length : 0; i-- > 0; )
{
if((listener = listeners[i]) == null)
{
continue;
}
try
{
listener.playerUpdate(player, event, data);
}
catch(RuntimeException e)
{
e.printRealStackTrace();
}
}
if(PlayerListener.CLOSED.equals(event))
{
player.listeners = null;
}
}
}
protected int state;
protected Object lock;
private PlayerListener[] listeners;
protected CustomPlayer()
{
this.state = UNREALIZED;
this.lock = new Object();
}
public abstract void close();
public abstract void start()
throws MediaException;
public abstract void stop()
throws MediaException;
public abstract void setLoopCount(int loopCount);
public abstract long setMediaTime(long time)
throws MediaException;
public abstract long getMediaTime();
public abstract long getDuration();
public void realize()
throws MediaException
{
}
public void prefetch()
throws MediaException
{
}
public void deallocate()
{
switch(state)
{
default:
return;
case CLOSED:
throw new IllegalStateException("Player.deallocate: " +
"проигрыватель закрыт.");
case UNREALIZED:
unrealize();
return;
case PREFETCHED:
case STARTED:
unprefetch();
return;
}
}
public void setTimeBase(TimeBase master)
throws MediaException
{
if(master != null && !(master instanceof SystemTimeBase))
{
throw new MediaException("Player.setTimeBase: " +
"установка других способов исчисления времени не поддерживается.");
}
}
public TimeBase getTimeBase()
{
return SYSTEM_TIME_BASE;
}
public final Control[] getControls()
{
switch(state)
{
case UNREALIZED:
deliverEvent(PlayerListener.ERROR, "Player.getControls: " +
"невозможно получить «рычаги» проигрывателя.");
/* fall through */
case CLOSED:
throw new IllegalStateException("Player.getControls: " +
"невозможно получить «рычаги» проигрывателя.");
default:
return getPlayerControls();
}
}
public final Control getControl(String type)
{
switch(state)
{
case UNREALIZED:
deliverEvent(PlayerListener.ERROR, "Player.getControl: " +
"невозможно получить «рычаги» проигрывателя.");
/* fall through */
case CLOSED:
throw new IllegalStateException("Player.getControl: " +
"невозможно получить «рычаги» проигрывателя.");
default:
return getPlayerControl(type);
}
}
public final void addPlayerListener(PlayerListener listener)
{
int i;
PlayerListener[] listeners;
if(state == CLOSED)
{
throw new IllegalStateException("Player.addPlayerListener: " +
"проигрыватель закрыт.");
}
if(listener == null)
{
return;
}
synchronized(lock)
{
if((listeners = this.listeners) == null)
{
listeners = this.listeners = new PlayerListener[2];
}
if(indexOfListener(listener) < 0)
{
if((i = indexOfListener(null)) < 0)
{
Array.copy(listeners, 0, listeners = this.listeners =
new PlayerListener[(i = listeners.length) << 1], 0, i);
}
listeners[i] = listener;
}
}
}
public final void removePlayerListener(PlayerListener listener)
{
int i;
PlayerListener[] listeners;
if(state == CLOSED)
{
throw new IllegalStateException("Player.removePlayerListener: " +
"проигрыватель закрыт.");
}
if(listener == null)
{
return;
}
synchronized(lock)
{
if((listeners = this.listeners) != null && (i = indexOfListener(listener)) >= 0)
{
listeners[i] = null;
}
}
}
public final int getState()
{
return state;
}
public final String getContentType()
{
switch(state)
{
case UNREALIZED:
deliverEvent(PlayerListener.ERROR, "Player.getContentType: " +
"невозможно получить тип содержимого проигрывателя.");
/* fall through */
case CLOSED:
throw new IllegalStateException("Player.getContentType: " +
"невозможно получить тип содержимого проигрывателя.");
default:
return getPlayerContentType();
}
}
protected abstract String getPlayerContentType();
protected void unrealize()
{
}
protected void unprefetch()
{
state = REALIZED;
}
protected Control[] getPlayerControls()
{
return new Control[] {
this
};
}
protected Control getPlayerControl(String type)
{
Class controlClass;
Control result;
if(type.indexOf('.') < 0)
{
type = "javax.microedition.media.control.".concat(type);
}
try
{
result = Class.forName("javax.microedition.media.Control").
isAssignableFrom(controlClass = Class.forName(type)) &&
controlClass.isAssignableFrom(getClass()) ? this : null;
}
catch(ClassNotFoundException e)
{
e.printRealStackTrace();
result = null;
}
return result;
}
protected final void deliverEvent(String event, Object data)
{
if(listeners != null)
{
EVENTS_LISTENER.pushEvent(this, event, data);
}
}
private int indexOfListener(PlayerListener listener)
{
int i;
PlayerListener[] listeners;
for(i = (listeners = this.listeners).length; i-- > 0; )
{
if(listeners[i] == listener)
{
return i;
}
}
return -1;
}
}