📄 basicplayer.java
字号:
/*
* Created on 2005-9-27 by pcy
*
* TODO To change the template for this generated file go to
* Window - Preferences - Java - Code Style - Code Templates
*/
package a.a.a.mmedia;
import javax.microedition.media.*;
import javax.microedition.media.control.*;
import java.util.*;
import java.io.*;
import javax.microedition.io.*;
public abstract class BasicPlayer implements Player, VolumeControl {
private static int pcount = -1;
private static Hashtable mplayers = new Hashtable(4);
private static Object idLock = new Object();
private String locator;
int state = UNREALIZED;
int loopCountSet = 1, loopCount;
boolean EOM = false;
boolean loopAfterEOM = false;
Vector listeners = new Vector(2);
EvtQ evtQ = null;
Object evtLock = new Object();
protected int pID = 0;
public BasicPlayer() {
synchronized (idLock) {
pcount = (pcount+1) % 32767;
pID = pcount;
}
mplayers.put(new Integer(pID), this);
}
protected void chkClosed(boolean unrealized) {
if (state == CLOSED || (unrealized && state == UNREALIZED)) {
throw new IllegalStateException("The Player is " +
(state == CLOSED ? "closed" : "unrealized"));
}
}
public void setLoopCount(int count) throws IllegalArgumentException, IllegalStateException {
chkClosed(false);
if (state == STARTED){
throw new IllegalStateException("setLoopCount");
}
if (count == 0 || count < -1){
throw new IllegalArgumentException("setLoopCount");
}
loopCountSet = count;
loopCount = count;
}
public synchronized void realize() throws MediaException {
chkClosed(false);
if (state >= REALIZED)
return;
doRealize();
state = REALIZED;
}
abstract protected void doRealize() throws MediaException;
public synchronized void prefetch() throws MediaException {
chkClosed(false);
if (state >= PREFETCHED)
return;
if (state < REALIZED)
realize();
doPrefetch();
state = PREFETCHED;
}
abstract protected void doPrefetch() throws MediaException;
public synchronized void start() throws MediaException {
chkClosed(false);
if (state >= STARTED){
return;
}
if (state < REALIZED){
realize();
}
if (state < PREFETCHED){
prefetch();
}
// If it's at the EOM, it will automatically
// loop back to the beginning.
if (EOM){
setMediaTime(0);
}
if (!doStart()){
throw new MediaException("start");
}
state = STARTED;
sendEvent(PlayerListener.STARTED, new Long(getMediaTime()));
}
abstract protected boolean doStart();
public synchronized void stop() {
chkClosed(false);
loopAfterEOM = false;
if (state < STARTED){
return;
}
doStop();
state = PREFETCHED;
sendEvent(PlayerListener.STOPPED, new Long(getMediaTime()));
}
abstract protected void doStop();
public synchronized void deallocate() {
chkClosed(false);
loopAfterEOM = false;
if (state < PREFETCHED){
return;
}
if (state == STARTED){
stop();
}
doDeallocate();
state = REALIZED;
}
abstract protected void doDeallocate();
public synchronized void close() {
if (state == CLOSED){
return;
}
deallocate();
doClose();
state = CLOSED;
try {
if (stream != null)
stream.close();
} catch (IOException e) { }
sendEvent(PlayerListener.CLOSED, null);
mplayers.remove(new Integer(pID));
}
abstract protected void doClose();
public synchronized long setMediaTime(long now) throws MediaException {
chkClosed(true);
if (now < 0)
now = 0;
long theDur = getDuration();
if ((theDur != TIME_UNKNOWN) && (now > theDur))
now = theDur;
long rtn = doSetMediaTime(now);
EOM = false;
return rtn;
}
abstract protected long doSetMediaTime(long now) throws MediaException;
public long getMediaTime() {
chkClosed(false);
return doGetMediaTime();
}
abstract protected long doGetMediaTime();
public int getState() {
return state;
}
public long getDuration() {
chkClosed(false);
return doGetDuration();
}
abstract protected long doGetDuration();
public void addPlayerListener(PlayerListener playerListener) {
chkClosed(false);
if (playerListener != null){
listeners.addElement(playerListener);
}
}
public void removePlayerListener(PlayerListener playerListener) {
chkClosed(false);
listeners.removeElement(playerListener);
}
public void sendEvent(String evt, Object evtData) {
// There's always one listener for EOM -- itself.
if (listeners.size() == 0 && evt != PlayerListener.END_OF_MEDIA){
return;
}
// Deliver the event to the listeners.
synchronized (evtLock) {
if (evtQ == null)
evtQ = new EvtQ(this);
evtQ.sendEvent(evt, evtData);
}
}
synchronized void doLoop() {
// If a loop count is set, we'll loop back to the beginning.
if ((loopCount > 1) || (loopCount == -1)) {
try {
if (setMediaTime(0) == 0) {
if (loopCount > 1){
loopCount--;
}
start();
} else{
loopCount = 1;
}
} catch (MediaException ex) {
loopCount = 1;
}
} else if (loopCountSet > 1){
loopCount = loopCountSet;
}
loopAfterEOM = false;
}
public Control[] getControls() {
chkClosed(true);
return new Control[] { this };
}
public Control getControl(String type) {
chkClosed(true);
// Prepend the package name if the type given does not
// have the package prefix.
if (type.indexOf('.') < 0){
return doGetControl("javax.microedition.media.control." + type);
}
return doGetControl(type);
}
abstract protected Control doGetControl(String type);
public static BasicPlayer get(int pid) {
return (BasicPlayer)(mplayers.get(new Integer(pid)));
}
/**
* ==========================
* Methods for VolumeControl.
* ==========================
*/
private int level = -1;
private boolean mute;
protected abstract int doSetLevel(int vol);
public void setMute(boolean mute) {
if (mute && !this.mute) {
doSetLevel(0);
this.mute = true;
sendEvent(PlayerListener.VOLUME_CHANGED, this);
} else if (!mute && this.mute) {
this.level = doSetLevel(level);
this.mute = false;
sendEvent(PlayerListener.VOLUME_CHANGED, this);
}
}
public boolean isMuted() {
return mute;
}
public int setLevel(int ll) {
int newl;
if (ll < 0) {
ll = 0;
} else if (ll > 100) {
ll = 100;
}
if (!mute) {
newl = doSetLevel(ll);
if (newl != level) {
level = newl;
sendEvent(PlayerListener.VOLUME_CHANGED, this);
}
}
return level;
}
public int getLevel() {
return level;
}
/**
* ================
* Input functions.
* ================
*/
protected InputStream stream;
long location;
public void setLocator(String locator, boolean con) throws IOException, MediaException {
this.locator = locator;
if (con){
openConnection();
}
}
public void setStrm(InputStream stream) {
this.stream = stream;
}
private void openConnection() throws IOException, MediaException {
try {
HttpConnection httpCon = (HttpConnection)Connector.open(locator);
int rescode = httpCon.getResponseCode();
// both 4XX and 5XX are error codes
if (rescode >= 400) {
httpCon.close();
throw new IOException("bad url");
} else {
stream = httpCon.openInputStream();
String ctype = httpCon.getType();
boolean supportedCT = false;
if (locator.endsWith(".wav")) {
supportedCT = true;
} else if (ctype != null &&
ctype.toLowerCase().equals("audio/x-wav")) {
supportedCT = true;
}
httpCon.close();
if (!supportedCT) {
stream.close();
stream = null;
throw new MediaException("unsupported media type");
}
}
} catch (IOException ioex) {
throw ioex;
} catch (MediaException mex) {
throw mex;
} catch (Exception ex) {
new IOException(ex.getMessage() + " failed to connect");
}
location = 0;
}
protected int readStrm(byte buffer[], int offset, int length)throws IOException {
int len = stream.read(buffer, offset, length);
if (len > 0){
location += len;
}
return len;
}
protected long seekStrm(long where) throws IOException, MediaException {
if (stream == null){
return location;
}
long skipped, oldLocation = location;
if (where < oldLocation) { // seek backward
reopenStrm();
location = 0;
skipped = stream.skip(where);
} else {
skipped = stream.skip((where - oldLocation));
}
if (skipped > 0){
location += skipped;
}
return location;
}
protected long skipStrm(int numBytes) throws IOException {
long skipped = stream.skip(numBytes);
/*if (skipped > 0){
location += skipped;
}*/
if (skipped < numBytes){
throw new IOException("skipped over eom");
}
return (skipped);
}
private void reopenStrm() throws IOException, MediaException {
try {
stream.reset();
return;
} catch (IOException ex) {
if (locator == null){
throw ex;
}
}
try {
stream.close();
stream = null;
} catch (IOException e) {}
openConnection();
}
protected long getStrmLoc() {
return location;
}
}
class EvtQ extends Thread {
private BasicPlayer p;
private String[] evtQ;
private Object[] evtDataQ;
private int head, tail;
private static final int size = 12;
EvtQ(BasicPlayer p) {
this.p = p;
evtQ = new String[size];
evtDataQ = new Object[size];
start();
}
synchronized void sendEvent(String evt, Object evtData) {
while ((head + 1) % size == tail) {
try {
wait();
} catch (Exception e) { }
}
evtQ[head] = evt;
evtDataQ[head] = evtData;
if (++head == size){
head = 0;
}
notify();
}
/**
* the run method for interface Runnable
*/
public void run() {
String evt = "";
Object evtData = null;
boolean evtToGo = false;
for (;;) {
synchronized (this) {
// If the queue is empty, we'll wait for at most
// 5 secs.
if (head == tail) {
try {
wait(5000);
} catch (Exception e) {
}
}
if (head != tail) {
evt = evtQ[tail];
evtData = evtDataQ[tail];
// For garbage collection.
evtDataQ[tail] = null;
evtToGo = true;
if (++tail == size)
tail = 0;
notify();
} else
evtToGo = false;
} // synchronized this
if (evtToGo) {
if (evt == PlayerListener.END_OF_MEDIA) {
synchronized (p) {
p.EOM = true;
p.loopAfterEOM = false;
if (p.state > Player.PREFETCHED) {
p.state = Player.PREFETCHED;
if (p.loopCount > 1 || p.loopCount == -1) {
p.loopAfterEOM = true;
}
}
}
}
synchronized (p.listeners) {
PlayerListener l;
for (int i = 0; i < p.listeners.size(); i++) {
try {
l = (PlayerListener)p.listeners.elementAt(i);
l.playerUpdate(p, evt, evtData);
} catch (Exception e) {
System.err.println("Error in playerUpdate: " + e);
}
}
}
if (p.loopAfterEOM)
p.doLoop();
}
if (!evtToGo || evt == PlayerListener.CLOSED) {
// If there's no event waking up after 5 secs,
// we'll kill the thread.
synchronized (p.evtLock) {
p.evtQ = null;
break;
}
}
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -