{
String dataSourceClassName = (String) dataSourceList.get(i);
try
{
final Class dataSourceClass = Class.forName(dataSourceClassName);
final DataSource dataSource = (DataSource) dataSourceClass.newInstance();
dataSource.setLocator(sourceLocator);
dataSource.connect();
return createPlayer(dataSource);
// TODO: JMF seems to disconnect data sources in this method, based on this stack trace:
// java.lang.NullPointerException
// at com.sun.media.protocol.rtp.DataSource.disconnect(DataSource.java:207)
// at javax.media.Manager.createPlayer(Manager.java:425)
// at net.sf.fmj.ui.application.ContainerPlayer.createNewPlayer(ContainerPlayer.java:357)
// TODO: JMF appears to get the streams from the data source (somewhere near) here. If the stream is null, we get (from JMF:)
// javax.media.NoPlayerException: Error instantiating class: com.sun.media.content.unknown.Handler : java.io.IOException: Got a null stream from the DataSource
// at javax.media.Manager.createPlayerForSource(Manager.java:1502)
// at javax.media.Manager.createPlayer(Manager.java:500)
// more specifically, it callse getStreams, and if there are no streams or only a null streams, it throws an exception.
// it then calls isRandomAccess on the stream (or streams?).
// perhaps calling random access is necessary to determine whether some kind of buffered clone of the source is needed
// OR whether the datasource needs to be closed and re-opened, for the case when one handler is tried, and rejects
// the source. If the source is not random access, then you'd have to throw it a way if a handler opened it, read
// from it, and rejected it.
// see comments below with URLDataSource connection, below.
// this is one of the weaknesses of the JMF architecture, that it potentially needs to open a media data source multiple times
// in order to figure out what to do with it.
}
catch (NoPlayerException e)
{ // no need to log, will be logged by call to createPlayer.
continue;
}
catch (ClassNotFoundException e)
{
logger.finer("createPlayer: " + e); // no need for call stack
continue;
}
catch (IOException e)
{
logger.log(Level.FINE, "" + e, e);
if (RETHROW_IO_EXCEPTIONS)
throw e;
else
continue;
}
catch (NoClassDefFoundError e)
{
logger.log(Level.FINE, "" + e, e);
continue;
}
catch (Exception e)
{
logger.log(Level.FINE, "" + e, e);
continue;
}
}
// if none found, try URLDataSource:
final URL url;
try
{
url = sourceLocator.getURL();
}
catch (Exception e)
{ logger.log(Level.WARNING, "" + e, e);
throw new NoPlayerException();
}
final URLDataSource dataSource = new URLDataSource(url);
dataSource.connect(); // TODO: there is a problem because we connect to the datasource here, but
// the following call may try twice or more to use the datasource with a player, once
// for the right content type, and multiple times for unknown. The first attempt (for example) may actually
// read data, in which case the second one will be missing data when it reads.
// really, the datasource needs to be recreated.
// The workaround for now is that URLDataSource (and others) allows repeated connect() calls.