1 /* 2 * This file is part of libbluray 3 * 4 * This library is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU Lesser General Public 6 * License as published by the Free Software Foundation; either 7 * version 2.1 of the License, or (at your option) any later version. 8 * 9 * This library is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 * Lesser General Public License for more details. 13 * 14 * You should have received a copy of the GNU Lesser General Public 15 * License along with this library. If not, see 16 * <http://www.gnu.org/licenses/>. 17 */ 18 19 package javax.media; 20 21 import java.io.IOException; 22 import java.net.URL; 23 import java.util.Vector; 24 25 import javax.media.protocol.DataSource; 26 import javax.media.protocol.URLDataSource; 27 28 import org.videolan.Logger; 29 30 /** 31 * This file is a stripped down version of the Manager class from FMJ (fmj-sf.net) 32 * @author Ken Larson 33 * 34 */ 35 public final class Manager { createPlayer(URL sourceURL)36 public static Player createPlayer(URL sourceURL) throws IOException, 37 NoPlayerException { 38 return createPlayer(new MediaLocator(sourceURL)); 39 } 40 createPlayer(MediaLocator sourceLocator)41 public static Player createPlayer(MediaLocator sourceLocator) 42 throws IOException, NoPlayerException { 43 final String protocol = sourceLocator.getProtocol(); 44 final Vector dataSourceList = getDataSourceList(protocol); 45 for (int i = 0; i < dataSourceList.size(); ++i) { 46 String dataSourceClassName = (String) dataSourceList.get(i); 47 try { 48 final Class dataSourceClass = Class.forName(dataSourceClassName); 49 final DataSource dataSource = (DataSource) dataSourceClass.newInstance(); 50 dataSource.setLocator(sourceLocator); 51 dataSource.connect(); 52 return createPlayer(dataSource); 53 54 // TODO: JMF seems to disconnect data sources in this method, based on this stack trace: 55 // java.lang.NullPointerException 56 // at com.sun.media.protocol.rtp.DataSource.disconnect(DataSource.java:207) 57 // at javax.media.Manager.createPlayer(Manager.java:425) 58 // at net.sf.fmj.ui.application.ContainerPlayer.createNewPlayer(ContainerPlayer.java:357) 59 } catch (NoPlayerException e) { 60 // no need to log, will be logged by call to createPlayer. 61 continue; 62 } catch (ClassNotFoundException e) { 63 logger.warning("createPlayer: " + e); // no need for call stack 64 continue; 65 } catch (IOException e) { 66 logger.warning("" + e); 67 continue; 68 } catch (NoClassDefFoundError e) { 69 logger.warning("" + e); 70 continue; 71 } catch (Exception e) { 72 logger.warning("" + e); 73 continue; 74 } 75 } 76 77 // if none found, try URLDataSource: 78 final URL url; 79 try { 80 url = sourceLocator.getURL(); 81 } catch (Exception e) { 82 logger.warning("" + e); 83 throw new NoPlayerException(); 84 } 85 final URLDataSource dataSource = new URLDataSource(url); 86 dataSource.connect(); // TODO: there is a problem because we connect to the datasource here, but 87 // the following call may try twice or more to use the datasource with a player, once 88 // for the right content type, and multiple times for unknown. The first attempt (for example) may actually 89 // read data, in which case the second one will be missing data when it reads. 90 // really, the datasource needs to be recreated. 91 // The workaround for now is that URLDataSource (and others) allows repeated connect() calls. 92 return createPlayer(dataSource); 93 } 94 createPlayer(DataSource source)95 public static Player createPlayer(DataSource source) throws IOException, NoPlayerException { 96 return createPlayer(source, source.getContentType()); 97 } 98 createDataSource(URL sourceURL)99 public static DataSource createDataSource(URL sourceURL) 100 throws IOException, NoDataSourceException { 101 return createDataSource(new MediaLocator(sourceURL)); 102 } 103 createDataSource(MediaLocator sourceLocator)104 public static DataSource createDataSource(MediaLocator sourceLocator) 105 throws IOException, NoDataSourceException { 106 final String protocol = sourceLocator.getProtocol(); 107 final Vector dataSourceList = getDataSourceList(protocol); 108 for (int i = 0; i < dataSourceList.size(); ++i) { 109 String dataSourceClassName = (String) dataSourceList.get(i); 110 try { 111 final Class dataSourceClass = Class.forName(dataSourceClassName); 112 final DataSource dataSource = (DataSource) dataSourceClass.newInstance(); 113 dataSource.setLocator(sourceLocator); 114 dataSource.connect(); 115 return dataSource; 116 } catch (ClassNotFoundException e) { 117 logger.warning("createDataSource: " + e); // no need for call stack 118 continue; 119 } catch (IOException e) { 120 logger.warning("" + e); 121 continue; 122 } catch (NoClassDefFoundError e) { 123 logger.warning("" + e); 124 continue; 125 } catch (Exception e) { 126 logger.warning("" + e); 127 continue; 128 } 129 } 130 131 // if none found, try URLDataSource: 132 final URL url; 133 try { 134 url = sourceLocator.getURL(); 135 } catch (Exception e) { 136 logger.warning("" + e); 137 throw new NoDataSourceException(); 138 } 139 final URLDataSource dataSource = new URLDataSource(url); 140 dataSource.connect(); 141 return dataSource; 142 } 143 getSystemTimeBase()144 public static TimeBase getSystemTimeBase() { 145 return systemTimeBase; 146 } 147 getDataSourceList(String protocolName)148 public static Vector getDataSourceList(String protocolName) { 149 return getClassList(protocolName, PackageManager.getProtocolPrefixList(), "protocol", "DataSource"); 150 } 151 getHandlerClassList(String contentName)152 public static Vector getHandlerClassList(String contentName) { 153 return getClassList(toPackageFriendly(contentName), PackageManager.getContentPrefixList(), "content", "Handler"); 154 } 155 createPlayer(DataSource source, String contentType)156 private static Player createPlayer(DataSource source, String contentType) 157 throws IOException, NoPlayerException { 158 final Vector handlerClassList = getHandlerClassList(contentType); 159 for (int i = 0; i < handlerClassList.size(); ++i) { 160 final String handlerClassName = (String) handlerClassList.get(i); 161 162 try { 163 System.out.println(handlerClassName); 164 final Class handlerClass = Class.forName(handlerClassName); 165 if (!Player.class.isAssignableFrom(handlerClass) && 166 !MediaProxy.class.isAssignableFrom(handlerClass)) { 167 continue; // skip any classes that will not be matched below. 168 } 169 final MediaHandler handler = (MediaHandler) handlerClass.newInstance(); 170 handler.setSource(source); 171 172 if (handler instanceof Player) { 173 return (Player) handler; 174 } else if (handler instanceof MediaProxy) { 175 final MediaProxy mediaProxy = (MediaProxy) handler; 176 return createPlayer(mediaProxy.getDataSource()); 177 } 178 } catch (ClassNotFoundException e) { 179 // no need for call stack 180 logger.warning("createPlayer: " + e); 181 continue; 182 } catch (IncompatibleSourceException e) { 183 // no need for call stack 184 logger.warning("createPlayer(" + source + ", " + contentType + "): " + e); 185 continue; 186 } catch (IOException e) { 187 logger.warning("" + e); 188 continue; 189 } catch (NoPlayerException e) { 190 // no need to log, will be logged by call to createPlayer. 191 continue; 192 } catch (NoClassDefFoundError e) { 193 logger.warning("" + e); 194 continue; 195 } catch (Exception e) { 196 logger.warning("" + e); 197 continue; 198 } 199 } 200 logger.error("No player found for " + contentType + " / " + source.getLocator()); 201 throw new NoPlayerException("No player found for " + source.getLocator()); 202 } 203 toPackageFriendly(char c)204 private static char toPackageFriendly(char c) { 205 if (c >= 'a' && c <= 'z') 206 return c; 207 else if (c >= 'A' && c <= 'Z') 208 return c; 209 else if (c >= '0' && c <= '9') 210 return c; 211 else if (c == '.') 212 return c; 213 else if (c == '/') 214 return '.'; 215 else 216 return '_'; 217 } 218 toPackageFriendly(String contentName)219 private static String toPackageFriendly(String contentName) { 220 final StringBuffer b = new StringBuffer(); 221 for (int i = 0; i < contentName.length(); ++i) { 222 final char c = contentName.charAt(i); 223 b.append(toPackageFriendly(c)); 224 } 225 return b.toString(); 226 } 227 getClassList(String contentName, Vector packages, String component2, String className)228 public static Vector getClassList(String contentName, Vector packages, String component2, String className) { 229 final Vector result = new Vector(); 230 //result.add("media." + component2 + "." + contentName + "." + className); 231 232 for (int i = 0; i < packages.size(); ++i) { 233 result.add(((String) packages.get(i)) + ".media." + component2 + "." + contentName + "." + className); 234 } 235 236 return result; 237 } 238 239 public static final String UNKNOWN_CONTENT_NAME = "unknown"; 240 241 private static final TimeBase systemTimeBase = new SystemTimeBase(); 242 private static final Logger logger = Logger.getLogger(Manager.class.getName()); 243 } 244