Package com.aelitis.azureus.core.devices.impl

Source Code of com.aelitis.azureus.core.devices.impl.DeviceUPnPImpl

/*
* Created on Jan 28, 2009
* Created by Paul Gardner
*
* Copyright 2009 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.core.devices.impl;

import java.io.IOException;
import java.io.InputStream;
import java.net.InetAddress;
import java.net.URL;
import java.util.*;

import org.gudy.azureus2.core3.config.COConfigurationManager;
import org.gudy.azureus2.core3.util.Debug;
import org.gudy.azureus2.core3.util.IndentWriter;
import org.gudy.azureus2.core3.util.SystemTime;
import org.gudy.azureus2.plugins.disk.DiskManagerFileInfo;
import org.gudy.azureus2.plugins.download.Download;
import org.gudy.azureus2.plugins.download.DownloadAttributeListener;
import org.gudy.azureus2.plugins.download.DownloadManager;
import org.gudy.azureus2.plugins.download.DownloadManagerListener;
import org.gudy.azureus2.plugins.ipc.IPCInterface;
import org.gudy.azureus2.plugins.torrent.Torrent;
import org.gudy.azureus2.pluginsimpl.local.PluginInitializer;
import org.gudy.azureus2.plugins.torrent.TorrentAttribute;

import com.aelitis.azureus.core.AzureusCore;
import com.aelitis.azureus.core.AzureusCoreRunningListener;
import com.aelitis.azureus.core.AzureusCoreFactory;
import com.aelitis.azureus.core.content.AzureusContentDownload;
import com.aelitis.azureus.core.content.AzureusContentFile;
import com.aelitis.azureus.core.content.AzureusPlatformContentDirectory;
import com.aelitis.azureus.core.devices.TranscodeException;
import com.aelitis.azureus.core.devices.TranscodeFile;
import com.aelitis.azureus.core.devices.TranscodeJob;
import com.aelitis.azureus.core.devices.TranscodeProfile;
import com.aelitis.azureus.core.devices.TranscodeTarget;
import com.aelitis.azureus.core.devices.TranscodeTargetListener;
import com.aelitis.azureus.core.devices.DeviceManager.UnassociatedDevice;
import com.aelitis.azureus.core.download.DiskManagerFileInfoStream;
import com.aelitis.azureus.core.torrent.PlatformTorrentUtils;
import com.aelitis.azureus.core.util.UUIDGenerator;
import com.aelitis.net.upnp.UPnPDevice;
import com.aelitis.net.upnp.UPnPRootDevice;

public abstract class
DeviceUPnPImpl
  extends DeviceImpl
  implements TranscodeTargetListener, DownloadManagerListener
{
  private static final Object UPNPAV_FILE_KEY = new Object();
   
  private static final Map<String,AzureusContentFile>  acf_map = new WeakHashMap<String,AzureusContentFile>();
 
  protected static String
  getDisplayName(
    UPnPDevice    device )
  {
    UPnPDevice  root = device.getRootDevice().getDevice();
   
    String fn = root.getFriendlyName();
   
    if ( fn == null || fn.length() == 0 ){
     
      fn = device.getFriendlyName();
    }
   
    String  dn = root.getModelName();
   
    if ( dn == null || dn.length() == 0 ){
   
      dn = device.getModelName();
    }
   
    if ( dn != null && dn.length() > 0 ){
     
      if ( !fn.contains( dn ) && ( !dn.contains( "Azureus" ) || dn.contains( "Vuze" ))){
     
        fn += " (" + dn + ")";
      }
    }
   
    return( fn );
  }
 
  private final String MY_ACF_KEY;

 
  private final DeviceManagerUPnPImpl  upnp_manager;
  private volatile UPnPDevice    device_may_be_null;
 
  private IPCInterface    upnpav_ipc;
  private TranscodeProfile  dynamic_transcode_profile;
  private Map<String,AzureusContentFile>  dynamic_xcode_map;
 
 
  protected
  DeviceUPnPImpl(
    DeviceManagerImpl    _manager,
    UPnPDevice        _device,
    int            _type )
  {
    super( _manager, _type, _type + "/" + _device.getRootDevice().getUSN(), getDisplayName( _device ), false );
   
    upnp_manager    = _manager.getUPnPManager();
    device_may_be_null   = _device;
   
    MY_ACF_KEY = getACFKey();
 
 
  protected
  DeviceUPnPImpl(
    DeviceManagerImpl  _manager,
    int          _type,
    String        _classification )

  {
    super( _manager, _type, UUIDGenerator.generateUUIDString(), _classification, true );
   
    upnp_manager    = _manager.getUPnPManager();
   
    MY_ACF_KEY = getACFKey();
  }
 
  protected
  DeviceUPnPImpl(
    DeviceManagerImpl  _manager,
    int          _type,
    String        _uuid,
    String        _classification,
    boolean        _manual,
    String        _name )

  {
    super( _manager, _type, _uuid==null?UUIDGenerator.generateUUIDString():_uuid, _classification, _manual, _name );
   
    upnp_manager    = _manager.getUPnPManager();
   
    MY_ACF_KEY = getACFKey();
  }
 
  protected
  DeviceUPnPImpl(
    DeviceManagerImpl  _manager,
    int          _type,
    String        _uuid,
    String        _classification,
    boolean        _manual )

  {
    super( _manager, _type, _uuid, _classification, _manual );
   
    upnp_manager    = _manager.getUPnPManager();
   
    MY_ACF_KEY = getACFKey();
  }
 
  protected
  DeviceUPnPImpl(
    DeviceManagerImpl  _manager,
    Map          _map )
 
    throws IOException
  {
    super(_manager, _map );
   
    upnp_manager    = _manager.getUPnPManager();
   
    MY_ACF_KEY = getACFKey();
  }
 
  protected String
  getACFKey()
  {
    return( "DeviceUPnPImpl:device:" + getID());
  }
 
  @Override
  protected boolean
  updateFrom(
    DeviceImpl    _other,
    boolean      _is_alive )
  {
    if ( !super.updateFrom( _other, _is_alive )){
     
      return( false );
    }
   
    if ( !( _other instanceof DeviceUPnPImpl )){
     
      Debug.out( "Inconsistent" );
     
      return( false );
    }
   
    DeviceUPnPImpl other = (DeviceUPnPImpl)_other;
   
    device_may_be_null  = other.device_may_be_null;
   
    return( true );
  }
 
  @Override
  protected void
  initialise()
  {
    super.initialise();
  }
 
  protected void
  UPnPInitialised()
  {
  }
 
  @Override
  protected void
  destroy()
  {
    super.destroy();
  }
 
  protected DeviceManagerUPnPImpl
  getUPnPDeviceManager()
  {
    return( upnp_manager );
  }
 
  protected UPnPDevice
  getUPnPDevice()
  {
    return( device_may_be_null );
  }
 
  public boolean
  isBrowsable()
  {
    return( true );
  }
 
  public browseLocation[]
  getBrowseLocations()
  {
    List<browseLocation>  locs = new ArrayList<browseLocation>();
 
    UPnPDevice device = device_may_be_null;
   
    if ( device != null ){
     
      URL    presentation = getPresentationURL( device );

      if ( presentation != null ){
         
        locs.add( new browseLocationImpl( "device.upnp.present_url", presentation ));
      }
     
      int userMode = COConfigurationManager.getIntParameter("User Mode");
     
      if ( userMode > 1 ){
     
        locs.add( new browseLocationImpl( "device.upnp.desc_url", device.getRootDevice().getLocation()));
      }
    }
   
    return( locs.toArray( new browseLocation[ locs.size() ]));
  }
 
  public boolean
  canFilterFilesView()
  {
    return( true );
  }
 
  public void
  setFilterFilesView(
    boolean  filter )
  {
    boolean  existing = getFilterFilesView();
   
    if ( existing != filter ){
   
      setPersistentBooleanProperty( PP_FILTER_FILES, filter );
   
      IPCInterface ipc = upnpav_ipc;
     
      if ( ipc != null ){
       
        try{
          ipc.invoke( "invalidateDirectory", new Object[]{});

        }catch( Throwable e ){
        }
      }
    }
  }
 
  public boolean
  getFilterFilesView()
  {
    return( getPersistentBooleanProperty( PP_FILTER_FILES, true ));
  }
 
  public boolean
  isLivenessDetectable()
  {
    return( true );
  }
 
  protected URL
  getLocation()
  {
    UPnPDevice device = device_may_be_null;
   
    if ( device != null ){
     
      UPnPRootDevice root = device.getRootDevice();
     
      return( root.getLocation());
    }
   
    return( null );
  }
 
  public boolean
  canAssociate()
  {
    return( true );
  }
 
  public void
  associate(
    UnassociatedDevice  assoc )
  {
    if ( isAlive()){
     
      return;
    }
   
    setAddress( assoc.getAddress());
   
    alive();
  }
 
  public InetAddress
  getAddress()
  {
    try{

      UPnPDevice device = device_may_be_null;
 
      if ( device != null ){
       
        UPnPRootDevice root = device.getRootDevice();
       
        URL location = root.getLocation();
       
        return( InetAddress.getByName( location.getHost() ));
       
      }else{
       
        InetAddress address = (InetAddress)getTransientProperty( TP_IP_ADDRESS );
       
        if ( address != null ){
         
          return( address );
        }
       
        String last = getPersistentStringProperty( PP_IP_ADDRESS );
       
        if ( last != null && last.length() > 0 ){
         
          return( InetAddress.getByName( last ));
        }
      }
    }catch( Throwable e ){
     
      Debug.printStackTrace(e);
   
    }
   
    return( null );
  }
 
  public void
  setAddress(
    InetAddress  address )
  {
    setTransientProperty( TP_IP_ADDRESS, address );
   
    setPersistentStringProperty( PP_IP_ADDRESS, address.getHostAddress());
  }
 
  public boolean
  canRestrictAccess()
  {
    return( true );
  }
 
  public String
  getAccessRestriction()
  {
    return( getPersistentStringProperty( PP_RESTRICT_ACCESS, "" ));
  }
 
  public void
  setAccessRestriction(
    String    str )
  {
    setPersistentStringProperty( PP_RESTRICT_ACCESS, str );
  }
 
  protected URL
  getStreamURL(
    TranscodeFileImpl    file )
  {
    return( getStreamURL( file, null ));
  }
 
  protected URL
  getStreamURL(
    TranscodeFileImpl    file,
    String          host )
  {
    browseReceived();
   
    return( super.getStreamURL( file, host ));
  }
 
  protected String
  getMimeType(
    TranscodeFileImpl    file )
  {
    browseReceived();
   
    return( super.getMimeType(file));
  }
 
  protected void
  browseReceived()
  {
    IPCInterface ipc = upnp_manager.getUPnPAVIPC();
   
    if ( ipc == null ){
     
      return;
    }
   
    TranscodeProfile default_profile = getDefaultTranscodeProfile();
   
    if ( default_profile == null ){
     
      TranscodeProfile[] profiles = getTranscodeProfiles();
     
      for ( TranscodeProfile p: profiles ){
       
        if ( p.isStreamable()){
         
          default_profile = p;
         
          break;
        }
      }
    }
   
    synchronized( this ){
     
      if ( upnpav_ipc != null ){
       
        return;
      }
     
      upnpav_ipc = ipc;
     
      if ( default_profile != null && default_profile.isStreamable()){
       
        dynamic_transcode_profile  = default_profile;
      }
    }
   
    if ( dynamic_transcode_profile != null && this instanceof TranscodeTarget ){
     
      // In theory this is a plugin, so there should be a core..
      // However, check just in case
      AzureusCoreFactory.addCoreRunningListener(new AzureusCoreRunningListener() {
     
        public void azureusCoreRunning(AzureusCore core) {
         
          DownloadManager dm = PluginInitializer.getDefaultInterface().getDownloadManager();
         
          dm.addListener( DeviceUPnPImpl.this, true );
        }
      });
    }
       
    addListener( this );

    TranscodeFile[]  transcode_files = getFiles();
   
    for ( TranscodeFile file: transcode_files ){
     
      fileAdded( file, false );
    }
  }
 
  protected void
  resetUPNPAV()
  {   
    Set<String>  to_remove = new HashSet<String>();
   
    synchronized( this ){
     
      if ( upnpav_ipc == null ){
       
        return;
      }
     
      upnpav_ipc = null;
     
      dynamic_transcode_profile = null;
     
      dynamic_xcode_map = null;
    
      DownloadManager dm = PluginInitializer.getDefaultInterface().getDownloadManager();

      dm.removeListener( this );
     
      removeListener( this );
     
      TranscodeFileImpl[]  transcode_files = getFiles();
     
      for ( TranscodeFileImpl file: transcode_files ){

        file.setTransientProperty( UPNPAV_FILE_KEY, null );
       
        to_remove.add( file.getKey());
      }
    }
   
    synchronized( acf_map ){
     
      for (String key: to_remove ){
     
        acf_map.remove( key );
      }
    }
  }
 
  public void
  downloadAdded(
    Download  download )
  {
    Torrent torrent = download.getTorrent();
   
    if ( torrent != null && PlatformTorrentUtils.isContent( torrent, false )){
               
      addDynamicXCode( download.getDiskManagerFileInfo()[0]);
    }
  }
 
  public void
  downloadRemoved(
    Download  download )
  {
    Torrent torrent = download.getTorrent();
   
    if ( torrent != null && PlatformTorrentUtils.isContent( torrent, false )){
               
      removeDynamicXCode( download.getDiskManagerFileInfo()[0]);
    }
  }
   
  protected void
  addDynamicXCode(
    final DiskManagerFileInfo    source )
  {
    final TranscodeProfile profile = dynamic_transcode_profile;
   
    IPCInterface      ipc  = upnpav_ipc;
   
    if ( profile == null || ipc == null ){
     
      return;
    }
   
    try{
      TranscodeFileImpl transcode_file = allocateFile( profile, false, source, false );
     
      AzureusContentFile acf = (AzureusContentFile)transcode_file.getTransientProperty( UPNPAV_FILE_KEY );

      if ( acf != null ){
       
        return;
      }
     
      final String tf_key = transcode_file.getKey();

      synchronized( acf_map ){
       
        acf = acf_map.get( tf_key );
      }
     
      if ( acf != null ){
       
        return;
      }
     
      final DiskManagerFileInfo stream_file =
        new DiskManagerFileInfoStream(
          new DiskManagerFileInfoStream.StreamFactory()
          {
            private List<Object>  current_requests = new ArrayList<Object>();
           
            public StreamDetails
            getStream(
              Object    request )
           
              throws IOException
            {           
              try{
                TranscodeJobImpl job = getManager().getTranscodeManager().getQueue().add(
                    (TranscodeTarget)DeviceUPnPImpl.this,
                    profile,
                    source,
                    false,
                    true,
                    TranscodeTarget.TRANSCODE_UNKNOWN );
                 
                synchronized( this ){
               
                  current_requests.add( request );
                }
               
                while( true ){
                 
                  InputStream is = job.getStream( 1000 );
                 
                  if ( is != null ){
                   
                    return( new StreamWrapper( is, job ));
                  }
                 
                  int  state = job.getState();
                 
                  if ( state == TranscodeJobImpl.ST_FAILED ){
                   
                    throw( new IOException( "Transcode failed: " + job.getError()));
                   
                  }else if ( state == TranscodeJobImpl.ST_CANCELLED ){
                   
                    throw( new IOException( "Transcode failed: job cancelled" ));
 
                  }else if ( state == TranscodeJobImpl.ST_COMPLETE ){
                   
                    throw( new IOException( "Job complete but no stream!" ));
                  }
                 
                  synchronized( this ){
                   
                    if ( !current_requests.contains( request )){
                     
                      break;
                    }
                  }
                 
                  System.out.println( "waiting for stream" );
                 
                }
               
                IOException error = new IOException( "Stream request cancelled" );
               
                job.failed( error );
               
                throw( error );
               
              }catch( IOException e ){
               
                throw( e );
               
              }catch( Throwable e ){
               
                throw( new IOException( "Failed to add transcode job: " + Debug.getNestedExceptionMessage(e)));
               
              }finally{
               
                synchronized( this ){
               
                  current_requests.remove( request );
                }
              }
            }
           
            public void
            destroyed(
              Object request )
            {
              synchronized( this ){
               
                current_requests.remove( request );
              }
            }
          },
          transcode_file.getCacheFile());
                   
      acf =  new AzureusContentFile()
          { 
               public DiskManagerFileInfo
               getFile()
               {
                 return( stream_file );
               }
              
            public Object
            getProperty(
              String    name )
            {
                // TODO: duration etc

              if ( name.equals( MY_ACF_KEY )){
               
                return( new Object[]{ DeviceUPnPImpl.this, tf_key });
               
              }else if ( name.equals( PT_PERCENT_DONE )){
               
                return( new Long(1000));
               
              }else if ( name.equals( PT_ETA )){
               
                return( new Long(0));
              }
             
              return( null );
            }
          };
     
      synchronized( acf_map ){

        acf_map.put( tf_key, acf );
      }
         
      transcode_file.setTransientProperty( UPNPAV_FILE_KEY, acf );

      syncCategories( transcode_file, true );
         
      synchronized( this ){
       
        if ( dynamic_xcode_map == null ){
         
          dynamic_xcode_map = new HashMap<String,AzureusContentFile>();
        }
       
        dynamic_xcode_map.put( tf_key, acf );
      }
     
      ipc.invoke( "addContent", new Object[]{ acf });
     
    }catch( Throwable e ){
     
      Debug.out( e );
    }
  }
 
  protected void
  removeDynamicXCode(
    final DiskManagerFileInfo    source )
  {
    final TranscodeProfile profile = dynamic_transcode_profile;
   
    IPCInterface      ipc  = upnpav_ipc;
   
    if ( profile == null || ipc == null ){
     
      return;
    }
   
    try{
      TranscodeFileImpl transcode_file = lookupFile( profile, source );

        // if the file completed transcoding then we leave the result around for
        // the user to re-use
     
      if ( transcode_file != null && !transcode_file.isComplete()){
       
        AzureusContentFile acf = null;
       
        synchronized( this ){
 
          if ( dynamic_xcode_map != null ){
         
            acf = dynamic_xcode_map.get( transcode_file.getKey());
          }
        }
       
        transcode_file.delete( true );
       
        if ( acf != null ){
       
          ipc.invoke( "removeContent", new Object[]{ acf });
        }
       
        synchronized( acf_map ){
         
          acf_map.remove( transcode_file.getKey());
        }
      }
    }catch( Throwable e ){
     
      Debug.out( e );
    }
  }
 
  protected boolean
  setupStreamXCode(
    TranscodeFileImpl    transcode_file )
  {
    final TranscodeJobImpl  job = transcode_file.getJob();
   
    if ( job == null ){
     
        // may have just completed, say things are OK as caller can continue
     
      return( transcode_file.isComplete());
    }
   
    final String tf_key = transcode_file.getKey();

    AzureusContentFile  acf;
   
    synchronized( acf_map ){
     
      acf = acf_map.get( tf_key );
    }
   
    if ( acf != null ){
     
      return( true );
    }
   
    IPCInterface      ipc  = upnpav_ipc;

    if ( ipc == null ){
     
      return( false );
    }
   
    if ( transcode_file.getDurationMillis() == 0 ){
     
      return( false );
    }
   
    try{
      final DiskManagerFileInfo stream_file =
        new TranscodeJobOutputLeecher( job, transcode_file );
                   
      acf =  new AzureusContentFile()
          { 
               public DiskManagerFileInfo
               getFile()
               {
                 return( stream_file );
               }
              
            public Object
            getProperty(
              String    name )
            {
                // TODO: duration etc
 
              if ( name.equals( MY_ACF_KEY )){
               
                return( new Object[]{ DeviceUPnPImpl.this, tf_key });
               
              }else if ( name.equals( PT_PERCENT_DONE )){
               
                return( new Long(1000));
               
              }else if ( name.equals( PT_ETA )){
               
                return( new Long(0));
              }
             
              return( null );
            }
          };
     
      synchronized( acf_map ){
 
        acf_map.put( tf_key, acf );
      }
   
      ipc.invoke( "addContent", new Object[]{ acf });

      log( "Set up stream-xcode for " + transcode_file.getName());
     
      return( true );
     
    }catch( Throwable e ){
     
      return( false );
    }
  }
 
  protected boolean
  isVisible(
    AzureusContentDownload    file )
  {
    return( !getFilterFilesView());
  }
 
  protected boolean
  isVisible(
    AzureusContentFile    file )
  { 
    boolean  result;
   
    if ( getFilterFilesView()){
   
      Object[] x = (Object[])file.getProperty( MY_ACF_KEY );
     
      if ( x != null && x[0] == this ){
         
        String  tf_key = (String)x[1];
         
        result = getTranscodeFile( tf_key ) != null;
       
      }else{
       
        result = false;
      }
    }else{
     
      result = true;
    }
   
    return( result );
  }
 
  public void
  fileAdded(
    TranscodeFile    _transcode_file )
  {
    fileAdded( _transcode_file, true );
  }
 
  public void
  fileAdded(
    TranscodeFile    _transcode_file,
    boolean        _new_file )
  {
    TranscodeFileImpl  transcode_file = (TranscodeFileImpl)_transcode_file;
   
    IPCInterface ipc = upnpav_ipc;
   
    synchronized( this ){
     
      if ( ipc == null ){

        return;
      }
     
      if ( !transcode_file.isComplete()){
       
        syncCategories( transcode_file, _new_file );

        return;
      }
     
      AzureusContentFile acf = (AzureusContentFile)transcode_file.getTransientProperty( UPNPAV_FILE_KEY );
     
      if ( acf != null ){
       
        return;
      }

      final String tf_key  = transcode_file.getKey();

      synchronized( acf_map ){
       
        acf = acf_map.get( tf_key );
      }
     
      if ( acf != null ){
       
        return;
      }

      try{
        final DiskManagerFileInfo   f     = transcode_file.getTargetFile();
             
        acf =
          new AzureusContentFile()
          {
            public DiskManagerFileInfo
              getFile()
            {
              return( f );
            }
           
            public Object
            getProperty(
              String    name )
            {           
              ifname.equals( MY_ACF_KEY )){
               
                return( new Object[]{ DeviceUPnPImpl.this, tf_key });
               
              }else if ( name.equals( PT_CATEGORIES )){
               
                TranscodeFileImpl  tf = getTranscodeFile( tf_key );

                if ( tf != null ){
                 
                  return( tf.getCategories());
                }
             
                return( new String[0] );
               
              }else{
               
                TranscodeFileImpl  tf = getTranscodeFile( tf_key );
               
                if ( tf != null ){
                 
                  long  res = 0;
                 
                  if ( name.equals( PT_DURATION )){
                   
                    res = tf.getDurationMillis();
                   
                  }else if ( name.equals( PT_VIDEO_WIDTH )){
                   
                    res = tf.getVideoWidth();
                   
                  }else if ( name.equals( PT_VIDEO_HEIGHT )){
                   
                    res = tf.getVideoHeight();
                   
                  }else if ( name.equals( PT_DATE )){

                    res = tf.getCreationDateMillis();
                   
                  }else if ( name.equals( PT_PERCENT_DONE )){

                    if ( tf.isComplete()){
                     
                      res = 1000;
                     
                    }else{
                     
                      TranscodeJob job = tf.getJob();
                     
                      if ( job == null ){
                       
                        res = 0;
                       
                      }else{
                       
                        res = 10*job.getPercentComplete();
                      }
                    }
                   
                    return( res );
                   
                  }else if ( name.equals( PT_ETA )){

                    if ( tf.isComplete()){
                     
                      res = 0;
                     
                    }else{
                     
                      TranscodeJob job = tf.getJob();
                     
                      if ( job == null ){
                       
                        res = Long.MAX_VALUE;
                       
                      }else{
                       
                        res = job.getETASecs();
                      }
                    }
                   
                    return( res );
                  }
                 
                  if ( res > 0 ){
                   
                    return( new Long( res ));
                  }
                }
              }
             
              return( null );
            }
          };
       
        transcode_file.setTransientProperty( UPNPAV_FILE_KEY, acf );

        synchronized( acf_map ){

          acf_map.put( tf_key, acf );
       
       
        syncCategories( transcode_file, _new_file );
         
        try{
          ipc.invoke( "addContent", new Object[]{ acf });
       
        }catch( Throwable e ){
         
          Debug.out( e );
        }   
      }catch( TranscodeException e ){
       
        // file deleted
      }
    }
  }
 
  protected void
  syncCategories(
    TranscodeFileImpl    tf,
    boolean          inherit_from_download )
  {
    try{
      Download dl = tf.getSourceFile().getDownload();
     
      if ( dl != null ){
       
          // only overwrite categories with the downloads ones if none already set
       
        if ( inherit_from_download ){
       
          setCategories( tf, dl );
        }
       
        final String tf_key = tf.getKey();
       
        dl.addAttributeListener(
          new DownloadAttributeListener()
          {
            public void
            attributeEventOccurred(
              Download       download,
              TorrentAttribute   attribute,
              int         eventType)
            {
              TranscodeFileImpl tf = getTranscodeFile( tf_key );
             
              if ( tf != null ){
               
                setCategories( tf, download );
              }
            }
          },
          upnp_manager.getCategoryAttibute(),
          DownloadAttributeListener.WRITTEN );
      }
    }catch( Throwable e ){
     
    }
  }
 
  protected void
  setCategories(
    TranscodeFileImpl    tf,
    Download        dl )
  {
    String  cat = dl.getCategoryName();
   
    if ( cat != null && cat.length() > 0 && !cat.equals( "Categories.uncategorized" )){
     
      tf.setCategories( new String[]{ cat });
     
    }else{
     
      tf.setCategories( new String[0] );
    }
  }
 
  public void
  fileChanged(
    TranscodeFile    file,
    int          type,
    Object        data )
  {
    if ( file.isComplete()){
     
      fileAdded( file, false );
    }
   
    if ( type == TranscodeTargetListener.CT_PROPERTY ){
     
      if ( data == TranscodeFile.PT_CATEGORY ){
       
        AzureusContentFile  acf;
       
        synchronized( acf_map ){
       
          acf = acf_map.get(((TranscodeFileImpl)file).getKey());
        }
       
        if ( acf != null ){
         
          AzureusPlatformContentDirectory.fireChanged( acf );
        }
      }
    }
  }
 
  public void
  fileRemoved(
    TranscodeFile    file )
  {
    IPCInterface ipc = upnp_manager.getUPnPAVIPC();
   
    if ( ipc == null ){
     
      return;
    }

    synchronized( this ){

      AzureusContentFile acf = (AzureusContentFile)file.getTransientProperty( UPNPAV_FILE_KEY );

      if ( acf == null ){
   
        return;
      }
     
      file.setTransientProperty( UPNPAV_FILE_KEY, null );

      try{
        ipc.invoke( "removeContent", new Object[]{ acf });
     
       
      }catch( Throwable e ){
       
        Debug.out( e );
      }
    }
   
    synchronized( acf_map ){

      acf_map.remove( ((TranscodeFileImpl)file).getKey());
   
  }
 
  protected URL
  getPresentationURL(
    UPnPDevice    device )
  {
    String  presentation = device.getRootDevice().getDevice().getPresentation();
   
    if ( presentation != null ){
     
      try{
        URL url = new URL( presentation );
       
        return( url );

      }catch( Throwable e ){       
      }
    }
   
    return( null );
  }
 
  protected void
  getDisplayProperties(
    List<String[]>  dp )
  {
    super.getDisplayProperties( dp );
   
    UPnPDevice device = device_may_be_null;
   
    if ( device != null ){
     
      UPnPRootDevice root = device.getRootDevice();
     
      URL location = root.getLocation();
     
      addDP( dp, "dht.reseed.ip", location.getHost() + ":" + location.getPort());
 
      String  model_details   = device.getModelName();
      String  model_url    = device.getModelURL();
     
      if ( model_url != null && model_url.length() > 0 ){
        model_details += " (" + model_url + ")";
      }
     
      String  manu_details   = device.getManufacturer();
      String  manu_url    = device.getManufacturerURL();
     
      if ( manu_url != null && manu_url.length() > 0 ){
        manu_details += " (" + manu_url + ")";
      }
     
      addDP( dp, "device.model.desc", device.getModelDescription());
      addDP( dp, "device.model.name", model_details );
      addDP( dp, "device.model.num", device.getModelNumber());
      addDP( dp, "device.manu.desc", manu_details );
    }else{
     
      InetAddress ia = getAddress();
     
      if ( ia != null ){
       
        addDP( dp, "dht.reseed.ip", ia.getHostAddress());
      }
    }
  }
 
  public void
  generate(
    IndentWriter    writer )
  {
    super.generate( writer );
   
    try{
      writer.indent();
     
      UPnPDevice device = device_may_be_null;
     
      if ( device == null ){
       
        writer.println( "upnp_device=null" );
       
      }else{
       
        writer.println( "upnp_device=" + device.getFriendlyName());
      }
 
      writer.println( "dyn_xcode=" + (dynamic_transcode_profile==null?"null":dynamic_transcode_profile.getName()));
    }finally{
     
      writer.exdent();
    }
  }
 
  protected static class
  StreamWrapper
    implements DiskManagerFileInfoStream.StreamFactory.StreamDetails
  {
    private InputStream    is;
    private TranscodeJob  job;
   
    protected
    StreamWrapper(
      InputStream    _is,
      TranscodeJob  _job )
    {
      is    = _is;
      job    = _job;
    }
   
    public InputStream
    getStream()
    {
      return( is );
    }
   
    public boolean
    hasFailed()
    {
      long start = SystemTime.getMonotonousTime();
   
      while( true ){
       
        int state = job.getState();
             
          // timing issues - we can get here during teh fail process so
          // hang around a little if we're still running
       
        if ( state == TranscodeJobImpl.ST_RUNNING ){
         
          if ( SystemTime.getMonotonousTime() - start > 5*1000 ){
           
            return( true );
           
          }else{
           
            try{
              Thread.sleep(250);
             
              continue;
             
            }catch( Throwable e ){
             
              return( true );
            }
          }
        }
       
        if (   state == TranscodeJobImpl.ST_FAILED ||
            state == TranscodeJobImpl.ST_CANCELLED ||
            state == TranscodeJobImpl.ST_REMOVED ||
            state == TranscodeJobImpl.ST_STOPPED ){
         
            // might have completed and then been removed
         
          TranscodeFile tf = job.getTranscodeFile();
         
          if ( tf != null && tf.isComplete()){
           
            return( false );
          }
         
          return( true );
        }
      }
    }
  }
}
TOP

Related Classes of com.aelitis.azureus.core.devices.impl.DeviceUPnPImpl

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.