/**
* Created on Jun 1, 2008
*
* Copyright 2008 Vuze, Inc. All rights reserved.
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License only.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package com.aelitis.azureus.util;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import org.gudy.azureus2.core3.download.DownloadManager;
import org.gudy.azureus2.core3.download.DownloadManagerState;
import org.gudy.azureus2.core3.global.GlobalManager;
import org.gudy.azureus2.core3.logging.LogEvent;
import org.gudy.azureus2.core3.logging.LogIDs;
import org.gudy.azureus2.core3.logging.Logger;
import org.gudy.azureus2.core3.torrent.TOTorrent;
import org.gudy.azureus2.core3.torrent.TOTorrentException;
import org.gudy.azureus2.core3.util.Constants;
import org.gudy.azureus2.core3.util.Debug;
import org.gudy.azureus2.core3.util.SystemTime;
import org.gudy.azureus2.plugins.PluginInterface;
import org.gudy.azureus2.plugins.PluginManager;
import org.gudy.azureus2.plugins.disk.DiskManagerFileInfo;
import org.gudy.azureus2.plugins.download.Download;
import org.gudy.azureus2.plugins.download.DownloadException;
import org.gudy.azureus2.plugins.utils.FeatureManager;
import org.gudy.azureus2.pluginsimpl.local.PluginCoreUtils;
import org.gudy.azureus2.pluginsimpl.local.PluginInitializer;
import com.aelitis.azureus.activities.VuzeActivitiesEntry;
import com.aelitis.azureus.core.AzureusCoreFactory;
import com.aelitis.azureus.core.download.DownloadManagerEnhancer;
import com.aelitis.azureus.core.download.EnhancedDownloadManager;
import com.aelitis.azureus.core.download.StreamManager;
import com.aelitis.azureus.core.torrent.PlatformTorrentUtils;
import com.aelitis.azureus.ui.UIFunctions;
import com.aelitis.azureus.ui.UIFunctionsManager;
import com.aelitis.azureus.ui.selectedcontent.SelectedContentV3;
/**
* @author TuxPaper
* @created Jun 1, 2008
*
*/
public class PlayUtils
{
public static final boolean COMPLETE_PLAY_ONLY = true;
// deprecated but here for older versions of vzemp that still refer to it
public static final int fileSizeThreshold = 90;
/**
* Access to this static is deprecated - use get/setPlayableFileExtensions. For legacy EMP we need
* to keep it public for the moment...
*/
public static final String playableFileExtensions = ".avi .flv .flc .mp4 .divx .h264 .mkv .mov .mp2 .m4v .mp3 .aac, .mts, .m2ts";
private static volatile String actualPlayableFileExtensions = playableFileExtensions;
private static Boolean hasQuickTime;
//private static Method methodIsExternalPlayerInstalled;
public static boolean prepareForPlay(DownloadManager dm) {
EnhancedDownloadManager edm = DownloadManagerEnhancer.getSingleton().getEnhancedDownload(
dm);
if (edm != null) {
edm.setProgressiveMode(true);
return (true);
}
return (false);
}
public static boolean canProgressiveOrIsComplete(TOTorrent torrent) {
if (torrent == null) {
return false;
}
try {
DownloadManagerEnhancer enhancer = DownloadManagerEnhancer.getSingleton();
EnhancedDownloadManager edm = DownloadManagerEnhancer.getSingleton().getEnhancedDownload(
torrent.getHash());
if (edm == null) {
return enhancer.isProgressiveAvailable()
&& PlatformTorrentUtils.isContentProgressive(torrent);
}
boolean complete = edm.getDownloadManager().isDownloadComplete(false);
if (complete) {
return true;
}
// not complete
if (!edm.supportsProgressiveMode()) {
return false;
}
} catch (TOTorrentException e) {
return false;
}
return true;
}
public static boolean canUseEMP(DiskManagerFileInfo file ){
return( isExternallyPlayable( file ));
}
public static boolean canUseEMP(TOTorrent torrent, int file_index) {
return( canUseEMP( torrent, file_index, COMPLETE_PLAY_ONLY ));
}
public static boolean canUseEMP(TOTorrent torrent, int file_index, boolean complete_only ) {
if (torrent == null) {
return false;
}
if (canPlayViaExternalEMP(torrent, file_index, complete_only)) {
return true;
}
return false;
}
private static boolean canPlay(DownloadManager dm, int file_index) {
if (dm == null) {
return false;
}
TOTorrent torrent = dm.getTorrent();
return canUseEMP(torrent,file_index);
}
private static boolean canPlay(TOTorrent torrent, int file_index) {
if (!PlatformTorrentUtils.isContent(torrent, false)) {
return false;
}
if (!AzureusCoreFactory.isCoreRunning()) {
return false;
}
GlobalManager gm = AzureusCoreFactory.getSingleton().getGlobalManager();
DownloadManager dm = gm.getDownloadManager(torrent);
if (dm != null) {
return dm.getAssumedComplete() || canUseEMP(torrent, file_index);
}
return canUseEMP(torrent, file_index);
}
public static boolean canPlayDS(Object ds, int file_index ) {
if ( !( Constants.isWindows || Constants.isOSX )){
return( false );
}
if (ds == null) {
return false;
}
if (ds instanceof org.gudy.azureus2.core3.disk.DiskManagerFileInfo) {
org.gudy.azureus2.core3.disk.DiskManagerFileInfo fi = (org.gudy.azureus2.core3.disk.DiskManagerFileInfo) ds;
return canPlayDS(fi.getDownloadManager(), fi.getIndex());
}
DownloadManager dm = DataSourceUtils.getDM(ds);
if (dm != null) {
return canPlay(dm, file_index);
}
TOTorrent torrent = DataSourceUtils.getTorrent(ds);
if (torrent != null) {
return canPlay(torrent, file_index);
}
if (ds instanceof VuzeActivitiesEntry) {
return ((VuzeActivitiesEntry) ds).isPlayable();
}
if (ds instanceof SelectedContentV3) {
SelectedContentV3 sel = (SelectedContentV3) ds;
return sel.canPlay();
}
return false;
}
// stream stuff
public static boolean
isStreamPermitted()
{
FeatureManager fm = PluginInitializer.getDefaultInterface().getUtilities().getFeatureManager();
return( fm.isFeatureInstalled( "core" ));
}
private static boolean
canStream(
DownloadManager dm,
int file_index )
{
if ( dm == null ){
return( false );
}
org.gudy.azureus2.core3.disk.DiskManagerFileInfo file;
if ( file_index == -1 ){
file = dm.getDownloadState().getPrimaryFile();
if (file == null) {
org.gudy.azureus2.core3.disk.DiskManagerFileInfo[] files = dm.getDiskManagerFileInfoSet().getFiles();
if (files.length == 0) {
return false;
}
file = files[0];
}
file_index = file.getIndex();
}else{
file = dm.getDiskManagerFileInfoSet().getFiles()[ file_index ];
}
if ( file.getDownloaded() == file.getLength()){
return( false );
}
if ( !StreamManager.getSingleton().isStreamingUsable()){
return( false );
}
TOTorrent torrent = dm.getTorrent();
return( canUseEMP( torrent, file_index, false ));
}
public static boolean
canStreamDS(
Object ds,
int file_index )
{
if ( !( Constants.isWindows || Constants.isOSX )){
return( false );
}
if ( ds == null ){
return( false );
}
if (ds instanceof org.gudy.azureus2.core3.disk.DiskManagerFileInfo) {
org.gudy.azureus2.core3.disk.DiskManagerFileInfo fi = (org.gudy.azureus2.core3.disk.DiskManagerFileInfo) ds;
return canStreamDS(fi.getDownloadManager(), fi.getIndex());
}
DownloadManager dm = DataSourceUtils.getDM(ds);
if ( dm != null ){
return( canStream( dm, file_index ));
}
return( false );
}
/**
* @param dmContent
* @return
*
* @since 3.0.4.3
*/
/*
public static String getContentUrl(DownloadManager dmContent) {
String contentPath;
if (dmContent.isDownloadComplete(false)) {
//use the file path if download is complete.
org.gudy.azureus2.core3.disk.DiskManagerFileInfo primaryFile = dmContent.getDownloadState().getPrimaryFile();
if (primaryFile == null) {
return null;
}
File file = primaryFile.getFile(true);
try {
contentPath = file.toURL().toString();
} catch (MalformedURLException e) {
contentPath = file.getAbsolutePath();
}
} else {
//use the stream path if download is not complete.
contentPath = PlayUtils.getMediaServerContentURL(dmContent);
}
return contentPath;
}
public static String getMediaServerContentURL(DownloadManager dm) {
try {
return PlayUtils.getMediaServerContentURL(DownloadManagerImpl.getDownloadStatic(dm));
} catch (DownloadException e) {
}
return null;
}
*/
/**
* @param dl
*
* @since 3.0.2.3
*/
/*
public static String getMediaServerContentURL(Download dl) {
//TorrentListViewsUtils.debugDCAD("enter - getMediaServerContentURL");
PluginManager pm = AzureusCoreFactory.getSingleton().getPluginManager();
PluginInterface pi = pm.getPluginInterfaceByID("azupnpav", false);
if (pi == null) {
Logger.log(new LogEvent(LogIDs.UI3, "Media server plugin not found"));
return null;
}
if (!pi.getPluginState().isOperational()) {
Logger.log(new LogEvent(LogIDs.UI3, "Media server plugin not operational"));
return null;
}
try {
Program program = Program.findProgram(".qtl");
boolean hasQuickTime = program == null ? false
: (program.getName().toLowerCase().indexOf("quicktime") != -1);
pi.getIPC().invoke("setQuickTimeAvailable", new Object[] {
new Boolean(hasQuickTime)
});
Object url = pi.getIPC().invoke("getContentURL", new Object[] {
dl
});
if (url instanceof String) {
return (String) url;
}
} catch (Throwable e) {
Logger.log(new LogEvent(LogIDs.UI3, LogEvent.LT_WARNING,
"IPC to media server plugin failed", e));
}
return null;
}
*/
public static URL getMediaServerContentURL(DiskManagerFileInfo file) {
//TorrentListViewsUtils.debugDCAD("enter - getMediaServerContentURL");
PluginManager pm = AzureusCoreFactory.getSingleton().getPluginManager();
PluginInterface pi = pm.getPluginInterfaceByID("azupnpav", false);
if (pi == null) {
Logger.log(new LogEvent(LogIDs.UI3, "Media server plugin not found"));
return null;
}
if (!pi.getPluginState().isOperational()) {
Logger.log(new LogEvent(LogIDs.UI3, "Media server plugin not operational"));
return null;
}
try {
if ( hasQuickTime == null ){
UIFunctions uif = UIFunctionsManager.getUIFunctions();
if ( uif != null ){
hasQuickTime = uif.isProgramInstalled( ".qtl", "Quicktime" );
try{
pi.getIPC().invoke("setQuickTimeAvailable", new Object[] { hasQuickTime });
}catch( Throwable e ){
Logger.log(new LogEvent(LogIDs.UI3, LogEvent.LT_WARNING,
"IPC to media server plugin failed", e));
}
}
}
Object url = pi.getIPC().invoke("getContentURL", new Object[] { file });
if (url instanceof String) {
return new URL( (String) url);
}
} catch (Throwable e) {
Logger.log(new LogEvent(LogIDs.UI3, LogEvent.LT_WARNING,
"IPC to media server plugin failed", e));
}
return null;
}
/*
private static final boolean isExternalEMPInstalled() {
if(!loadEmpPluginClass()) {
return false;
}
if (methodIsExternalPlayerInstalled == null) {
return false;
}
try {
Object retObj = methodIsExternalPlayerInstalled.invoke(null, new Object[] {});
if (retObj instanceof Boolean) {
return ((Boolean) retObj).booleanValue();
}
} catch (Throwable e) {
e.printStackTrace();
if (e.getMessage() == null
|| !e.getMessage().toLowerCase().endsWith("only")) {
Debug.out(e);
}
}
return false;
}*/
private static AtomicInteger dm_uid = new AtomicInteger();
private static Map<String,Object[]> ext_play_cache =
new LinkedHashMap<String,Object[]>(100,0.75f,true)
{
protected boolean
removeEldestEntry(
Map.Entry<String,Object[]> eldest)
{
return size() > 100;
}
};
public static boolean isExternallyPlayable(Download d, int file_index, boolean complete_only ) {
if ( d == null ){
return( false );
}
boolean use_cache = d.getState() != Download.ST_DOWNLOADING;
String cache_key = null;
long now = 0;
if ( use_cache ){
Integer uid = (Integer)d.getUserData( PlayUtils.class );
if ( uid == null ){
uid = dm_uid.getAndIncrement();
d.setUserData( PlayUtils.class, uid );
}
cache_key = uid+"/"+file_index+"/"+complete_only;
Object[] cached;
synchronized( ext_play_cache ){
cached = ext_play_cache.get( cache_key );
}
now = SystemTime.getMonotonousTime();
if ( cached != null ){
if ( now - (Long)cached[0] < 60*1000 ){
return((Boolean)cached[1]);
}
}
}
boolean result = isExternallyPlayableSupport(d, file_index, complete_only);
if ( use_cache ){
synchronized( ext_play_cache ){
ext_play_cache.put( cache_key, new Object[]{ now, result });
}
}
return( result );
}
private static boolean isExternallyPlayableSupport(Download d, int file_index, boolean complete_only ) {
int primary_file_index = -1;
if ( file_index == -1 ){
DownloadManager dm = PluginCoreUtils.unwrap(d);
if ( dm == null ) {
return( false );
}
DiskManagerFileInfo file = null;
try {
file = PluginCoreUtils.wrap(dm.getDownloadState().getPrimaryFile());
} catch (DownloadException e) {
return false;
}
if ( file == null ){
return( false );
}
if ( file.getDownloaded() != file.getLength()) {
if ( complete_only || getMediaServerContentURL( file ) == null ){
return( false );
}
}
primary_file_index = file.getIndex();
}else{
DiskManagerFileInfo file = d.getDiskManagerFileInfo( file_index );
if ( file.getDownloaded() != file.getLength()) {
if ( complete_only || getMediaServerContentURL( file ) == null ){
return( false );
}
}
primary_file_index = file_index;
}
if ( primary_file_index == -1 ){
return false;
}
return( isExternallyPlayable( d.getDiskManagerFileInfo()[primary_file_index] ));
}
public static int[]
getExternallyPlayableFileIndexes(
Download d,
boolean complete_only)
{
DiskManagerFileInfo[] fileInfos = d.getDiskManagerFileInfo();
int count = d.getDiskManagerFileCount();
int[] playableIndexes = {};
for (int i = 0; i < count; i++) {
DiskManagerFileInfo fileInfo = d.getDiskManagerFileInfo(i);
if (complete_only && fileInfo.getLength() != fileInfo.getDownloaded()) {
continue;
}
if (isExternallyPlayable(fileInfo)) {
int[] newPlayableIndexes = new int[playableIndexes.length + 1];
System.arraycopy(playableIndexes, 0, newPlayableIndexes, 0,
playableIndexes.length);
newPlayableIndexes[playableIndexes.length] = i;
playableIndexes = newPlayableIndexes;
}
}
return playableIndexes;
}
private static boolean
isExternallyPlayable(
DiskManagerFileInfo file )
{
String name = file.getFile( true ).getName();
try{
Download dl = file.getDownload();
if ( dl != null ){
String is = PluginCoreUtils.unwrap( dl ).getDownloadState().getAttribute( DownloadManagerState.AT_INCOMP_FILE_SUFFIX );
if ( is != null && name.endsWith( is )){
name = name.substring( 0, name.length() - is.length());
}
}
}catch( Throwable e ){
}
int extIndex = name.lastIndexOf(".");
if ( extIndex > -1 ){
String ext = name.substring(extIndex);
if ( ext == null ){
return false;
}
ext = ext.toLowerCase();
if ( getPlayableFileExtensions().indexOf(ext) > -1 ){
return true;
}
}
return false;
}
public static boolean isExternallyPlayable(TOTorrent torrent, int file_index, boolean complete_only ) {
if (torrent == null) {
return false;
}
try {
Download download = AzureusCoreFactory.getSingleton().getPluginManager().getDefaultPluginInterface().getDownloadManager().getDownload(torrent.getHash());
if (download != null) {
return isExternallyPlayable(download, file_index, complete_only);
}
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
private static final boolean canPlayViaExternalEMP(TOTorrent torrent, int file_index, boolean complete_only ) {
if (torrent == null) {
return false;
}
return isExternallyPlayable(torrent, file_index, complete_only );
}
public static String
getPlayableFileExtensions()
{
return( actualPlayableFileExtensions );
}
/**
* This method available for player plugins to extend playable set if needed
* @param str
*/
public static void
setPlayableFileExtensions(
String str )
{
actualPlayableFileExtensions = str;
}
/**
* @deprecated but still used by EMP
*/
public static int getPrimaryFileIndex(Download dl) {
EnhancedDownloadManager edm = DownloadManagerEnhancer.getSingleton().getEnhancedDownload( PluginCoreUtils.unwrap(dl) );
if ( edm == null ) {
return -1;
}
return edm.getPrimaryFileIndex();
}
public static boolean
isEMPAvailable()
{
PluginInterface pi = AzureusCoreFactory.getSingleton().getPluginManager().getPluginInterfaceByID( "azemp");
if ( pi == null || pi.getPluginState().isDisabled()){
return( false );
}
return( true );
}
public static boolean
playURL(
URL url, String name )
{
try{
PluginInterface pi = AzureusCoreFactory.getSingleton().getPluginManager().getPluginInterfaceByID( "azemp");
if ( pi == null || pi.getPluginState().isDisabled()){
return( false );
}
Class<?> ewp_class = pi.getPlugin().getClass().getClassLoader().loadClass( "com.azureus.plugins.azemp.ui.swt.emp.EmbeddedPlayerWindowSWT" );
if ( ewp_class != null ){
Method ow = ewp_class.getMethod( "openWindow", URL.class, String.class );
if ( ow != null ){
ow.invoke( null, url, name );
return( true );
}
}
return( false );
}catch( Throwable e ){
Debug.out( e);
return( false );
}
}
}