Package com.aelitis.azureus.core.download

Source Code of com.aelitis.azureus.core.download.StreamManager$SMDImpl

/*
* Created on Jun 21, 2010
* Created by Paul Gardner
*
* Copyright 2010 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.download;

import java.util.*;
import java.lang.reflect.Method;
import java.net.URL;


import org.gudy.azureus2.core3.config.COConfigurationManager;
import org.gudy.azureus2.core3.download.DownloadManager;
import org.gudy.azureus2.core3.internat.MessageText;
import org.gudy.azureus2.core3.util.AERunnable;
import org.gudy.azureus2.core3.util.AESemaphore;
import org.gudy.azureus2.core3.util.AEThread2;
import org.gudy.azureus2.core3.util.AsyncDispatcher;
import org.gudy.azureus2.core3.util.Constants;
import org.gudy.azureus2.core3.util.Debug;
import org.gudy.azureus2.core3.util.DisplayFormatters;
import org.gudy.azureus2.core3.util.SystemTime;
import org.gudy.azureus2.core3.util.TimeFormatter;
import org.gudy.azureus2.plugins.PluginInterface;
import org.gudy.azureus2.plugins.PluginListener;
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.DownloadStats;
import org.gudy.azureus2.plugins.torrent.TorrentAttribute;
import org.gudy.azureus2.pluginsimpl.local.PluginCoreUtils;
import org.gudy.azureus2.pluginsimpl.local.PluginInitializer;

import com.aelitis.azureus.core.AzureusCoreFactory;
import com.aelitis.azureus.core.devices.Device;
import com.aelitis.azureus.core.devices.DeviceManager;
import com.aelitis.azureus.core.devices.DeviceManagerFactory;
import com.aelitis.azureus.core.devices.DeviceMediaRenderer;
import com.aelitis.azureus.core.devices.TranscodeAnalysisListener;
import com.aelitis.azureus.core.devices.TranscodeException;
import com.aelitis.azureus.core.devices.TranscodeJob;
import com.aelitis.azureus.core.devices.TranscodeManager;
import com.aelitis.azureus.core.devices.TranscodeProfile;
import com.aelitis.azureus.core.devices.TranscodeProviderAnalysis;
import com.aelitis.azureus.core.devices.TranscodeQueue;
import com.aelitis.azureus.ui.UIFunctions;
import com.aelitis.azureus.ui.swt.plugininstall.SimplePluginInstaller;

public class
StreamManager
{
  private static final int BUFFER_SECS     = 30;
  private static final int BUFFER_MIN_SECS  = 3;
 

  private static StreamManager    singleton = new StreamManager();
 
  public static StreamManager
  getSingleton()
  {
    return( singleton );
  }
 
  private TorrentAttribute  mi_ta;
 
  private AsyncDispatcher  dispatcher = new AsyncDispatcher();
 
  private List<SMDImpl>    streamers = new ArrayList<SMDImpl>();
 
  private
  StreamManager()
  {
    PluginInterface default_pi = PluginInitializer.getDefaultInterface();

    mi_ta = default_pi.getTorrentManager().getPluginAttribute( "sm_metainfo" );
   
    default_pi.addListener(
      new PluginListener()
      {
        public void
        initializationComplete()
        {
         
        }
       
        public void
        closedownInitiated()
        {
          dispatcher.dispatch(
            new AERunnable()
            {
              public void
              runSupport()
              {
                List<SMDImpl>  to_cancel;
               
                synchronized( StreamManager.this ){
                 
                  to_cancel = new ArrayList<SMDImpl>( streamers );
                 
                  streamers.clear();
                }
               
                for ( SMDImpl s: to_cancel ){
                 
                  s.cancel();
                }
              }
            });
        }
       
        public void
        closedownComplete()
        {
         
        }
      });
  }
 
  public boolean
  isStreamingUsable()
  {
      // need win or osx 10.5+
   
    if ( !( Constants.isWindows || Constants.isOSX_10_5_OrHigher )){
     
      return( false );
    }
   
    try{
      PluginManager plug_man = AzureusCoreFactory.getSingleton().getPluginManager();
     
      PluginInterface xcode_pi = plug_man.getPluginInterfaceByID( "vuzexcode", false );
 
      if ( xcode_pi != null && !xcode_pi.getPluginState().isOperational()){
       
          // can't use if xcode borked
       
        return( false );
      }
     
        // otherwise xcode will be installed on demand
     
      PluginInterface emp_pi = plug_man.getPluginInterfaceByID( "azemp", false );
 
      if ( emp_pi == null ){
       
          // will be installed on demand
       
        return( true );
      }
     
      if ( !emp_pi.getPluginState().isOperational()){
       
          // can't use if emp borked
       
        return( false );
      }
     
        // emp installed but need version with prepareWindow, wait for update
     
      Class<?> epwClass = emp_pi.getPlugin().getClass().getClassLoader().loadClass( "com.azureus.plugins.azemp.ui.swt.emp.EmbeddedPlayerWindowSWT" );
     
      Method method = epwClass.getMethod( "prepareWindow", new Class[] { String.class });
     
      return( method != null );
     
    }catch( Throwable e ){
     
      return( false );
    }
  }
 
  public StreamManagerDownload
  stream(
    DownloadManager          dm,
    int                file_index,
    URL                url,
    boolean              preview_mode,
    StreamManagerDownloadListener  listener )
  {
    SMDImpl  result = new SMDImpl( dm, file_index, url, preview_mode, listener );
     
    synchronized( StreamManager.this ){
     
      streamers.add( result );
    }
   
    return( result );
  }


  private class
  SMDImpl
    extends AERunnable
    implements StreamManagerDownload
  {
    private DownloadManager            dm;
    private int                  file_index;
    private URL                  url;
    private StreamManagerDownloadListener    listener;
     
    private int            existing_dl_limit;
   
    private boolean          preview_mode;
    private long          preview_mode_last_change = 0;
   
    private AESemaphore        active_sem;
    private TranscodeJob      active_job;
   
    private EnhancedDownloadManager  active_edm;
    private boolean          active_edm_activated;

    private volatile boolean    cancelled;
   
    private
    SMDImpl(
      DownloadManager          _dm,
      int                _file_index,
      URL                _url,
      boolean              _preview_mode,
      StreamManagerDownloadListener  _listener )
    {
      dm        = _dm;
      file_index    = _file_index;
      url        = _url;
      preview_mode  = _preview_mode;
      listener    = _listener;
     
      dispatcher.dispatch( this );
    }
   
    public DownloadManager
    getDownload()
    {
      return( dm );
    }
   
    public int
    getFileIndex()
    {
      return( file_index );
    }
   
    public URL
    getURL()
    {
      return( url );
    }
   
    public boolean
    getPreviewMode()
    {
      return( preview_mode );
    }
   
    public void
    setPreviewMode(
      boolean  _preview_mode )
    {
      long  now = SystemTime.getMonotonousTime();
     
      if (   preview_mode_last_change == 0 ||
          now - preview_mode_last_change > 500 ){
       
        preview_mode_last_change = now;
       
        preview_mode = _preview_mode;
       
        listener.updateActivity( "Preview mode changed to " + preview_mode );
      }
    }
   
    public void
    runSupport()
    {
      try{
        synchronized( StreamManager.this ){
         
          if ( cancelled ){
           
            throw( new Exception( "Cancelled" ));
          }

          active_edm = DownloadManagerEnhancer.getSingleton().getEnhancedDownload( dm );
        }

        final long stream_start = SystemTime.getMonotonousTime();
       
        final Download download = PluginCoreUtils.wrap( dm );
       
        final DiskManagerFileInfo file = download.getDiskManagerFileInfo( file_index );
               
        PluginInterface emp_pi = checkPlugin( "azemp", "media player" );

        checkPlugin( "vuzexcode", "media analyser" );

        Class<?> epwClass = emp_pi.getPlugin().getClass().getClassLoader().loadClass( "com.azureus.plugins.azemp.ui.swt.emp.EmbeddedPlayerWindowSWT" );
       
        Method method = epwClass.getMethod( "prepareWindow", new Class[] { String.class });
       
        final Object player = method.invoke(null, new Object[] { file.getFile( true ).getName() });
     
        final Method buffering_method  = player.getClass().getMethod( "bufferingPlayback", new Class[] { Map.class });
        final Method is_active_method  = player.getClass().getMethod( "isActive", new Class[] {});

        final StreamManagerDownloadListener original_listener = listener;
       
        listener =
          new StreamManagerDownloadListener()
          {
            public void
            updateActivity(
              String    str )
            {
              original_listener.updateActivity(str);
            }
           
            public void
            updateStats(
              int      secs_until_playable,
              int      buffer_secs,
              long    buffer_bytes,
              int      target_buffer_secs )
            {
              original_listener.updateStats(secs_until_playable, buffer_secs, buffer_bytes, target_buffer_secs);
            }
           
            public void
            ready()
            {
              original_listener.ready();
            }
           
            public void
            failed(
              Throwable   error )
            {
              try{
                original_listener.failed(error);
               
                Map<String,Object> b_map = new HashMap<String,Object>();
               
                b_map.put( "state", new Integer( 3 ));
                b_map.put( "msg", Debug.getNestedExceptionMessage( error ));
               
                try{
                  buffering_method.invoke(player, new Object[] { b_map });
 
                }catch( Throwable e ){
                 
                  Debug.out( e );
                }
              }finally{
               
                cancel();
              }
            }
          };
       
        Map<String,Map<String,Object>>  map = (Map<String,Map<String,Object>>)download.getMapAttribute( mi_ta );
       
        Long  l_duration     = null;
        Long  l_video_width   = null;
        Long  l_video_height   = null;
       
        if ( map != null ){
         
          Map<String,Object> file_map = map.get( String.valueOf( file_index ));
         
          if ( file_map != null ){
           
            l_duration     = (Long)file_map.get( "duration" );
            l_video_width   = (Long)file_map.get( "video_width" );
            l_video_height   = (Long)file_map.get( "video_height" );
          }
        }
       
        final long duration;
        long video_width;
        long video_height;
       
        if ( l_duration == null ){
           
          active_edm.prepareForProgressiveMode( true );
         
          try{
            DeviceManager dm = DeviceManagerFactory.getSingleton();
           
            TranscodeManager tm = dm.getTranscodeManager();
           
            DeviceMediaRenderer dmr =
              (DeviceMediaRenderer)dm.addVirtualDevice(
                Device.DT_MEDIA_RENDERER,
                "18a0b53a-a466-6795-1d0f-cf38c830ca0e",
                "generic",
                "Media Analyser" );
 
            dmr.setHidden(true);
 
            TranscodeQueue queue = tm.getQueue();
           
            TranscodeJob[] jobs = queue.getJobs();
           
            for ( TranscodeJob job: jobs ){
             
              if ( job.getTarget() == dmr ){
               
                job.removeForce();
              }
            }
           
            TranscodeProfile[] profiles = dmr.getTranscodeProfiles();
           
            TranscodeProfile profile = null;
           
            for (TranscodeProfile p : profiles) {
             
              if ( p.getName().equals( "Generic MP4" )){
               
                profile = p;
 
                break;
              }
            }
           
            if ( profile == null ){
             
              throw( new Exception( "Analyser transcode profile not found" ));
            }
           
            listener.updateActivity( "Analysing media" );
           
            final Map<String,Object> b_map = new HashMap<String,Object>();
           
            b_map.put( "state", new Integer( 1 ));
            b_map.put( "msg", MessageText.getString( "stream.analysing.media" ));
           
            buffering_method.invoke(player, new Object[] { b_map });

            final TranscodeJob tj = queue.add( dmr, profile, file, true );
                     
            try{
              final AESemaphore sem = new AESemaphore( "analyserWait" );

              synchronized( StreamManager.this ){
               
                if ( cancelled ){
                 
                  throw( new Exception( "Cancelled" ));
                }
               
                active_sem  = sem;
                active_job   = tj;
              }
               
              final long[] properties = new long[3];
             
              final Throwable[] error = { null };
             
              tj.analyseNow(
                new TranscodeAnalysisListener()
                {
                  public void
                  analysisComplete(
                    TranscodeJob          file,
                    TranscodeProviderAnalysis    analysis )
                  {
                    try{                     
                      properties[0] = analysis.getLongProperty( TranscodeProviderAnalysis.PT_DURATION_MILLIS );
                      properties[1] = analysis.getLongProperty( TranscodeProviderAnalysis.PT_VIDEO_WIDTH );
                      properties[2] = analysis.getLongProperty( TranscodeProviderAnalysis.PT_VIDEO_HEIGHT );
                     
                      tj.removeForce();
                     
                    }finally{
                     
                      sem.releaseForever();
                    }
                  }
                 
                  public void
                  analysisFailed(
                    TranscodeJob    file,
                    TranscodeException  e )
                  {
                    try{
                      error[0] = e;
                   
                      tj.removeForce();
                     
                    }finally{
                     
                      sem.releaseForever();
                    }
                  }
                });
             
              new AEThread2( "SM:anmon" )
                {
                  public void
                  run()
                  {
                    boolean  last_preview_mode = preview_mode;
                   
                    while( !sem.isReleasedForever() && !cancelled ){
                     
                      if ( !sem.reserve( 250 )){
                     
                        if ( cancelled ){
                         
                          return;
                        }
                         
                        try{
                          Boolean b = (Boolean)is_active_method.invoke( player, new Object[0] );
                         
                          if ( !b ){
                           
                            cancel();
                           
                            break;
                          }
                        }catch( Throwable e ){ 
                        }
                       
                        if ( last_preview_mode != preview_mode ){
                         
                          last_preview_mode = preview_mode;
                         
                          b_map.put( "msg", MessageText.getString( last_preview_mode?"stream.analysing.media.preview":"stream.analysing.media" ));

                        }
                        DownloadStats stats = download.getStats();
                       
                        b_map.put( "dl_rate", stats.getDownloadAverage());
                        b_map.put( "dl_size", stats.getDownloaded());
                        b_map.put( "dl_time", SystemTime.getMonotonousTime() - stream_start );
                       
                        try{
                          buffering_method.invoke(player, new Object[] { b_map });

                        }catch( Throwable e ){
                         
                        }
                      }
                    }
                  }
                }.start();
               
              sem.reserve();
             
              synchronized( StreamManager.this ){
               
                if ( cancelled ){
                   
                  throw( new Exception( "Cancelled" ));
                }
               
                active_job   = null;
                active_sem  = null;
              }
             
              if ( error[0] != null ){
               
                throw( error[0] );
              }
             
              duration     = properties[0];
              video_width    = properties[1];
              video_height  = properties[2];
             
              if ( duration > 0 ){
               
                if ( map == null ){
                 
                  map = new HashMap<String, Map<String,Object>>();
                 
                }else{
                 
                  map = new HashMap<String, Map<String,Object>>( map );
                }
               
                Map<String,Object> file_map = map.get( String.valueOf( file_index ));
               
                if ( file_map == null ){
               
                  file_map = new HashMap<String, Object>();
                 
                  map.put( String.valueOf( file_index ), file_map );
                }
               
                file_map.put( "duration", duration );
                file_map.put( "video_width", video_width );
                file_map.put( "video_height", video_height );
               
                download.setMapAttribute( mi_ta, map );
              }
             
            }catch( Throwable e ){
             
              tj.removeForce();
             
              throw( e );
            }
           
          }catch( Throwable e ){
           
            throw( new Exception( "Media analysis failed", e ));
           
          }finally{
           
          }
        }else{
           
          duration     = l_duration;
          video_width    = l_video_width==null?0:l_video_width;
          video_height  = l_video_height==null?0:l_video_height;
        }
         
        if ( video_width == 0 || video_height == 0){
         
          throw( new Exception( "Media analysis failed - video stream not found" ));
        }
       
        if ( duration == 0 ){
         
          throw( new Exception( "Media analysis failed - duration unknown" ));
        }
       
        listener.updateActivity( "MetaData read: duration=" + TimeFormatter.formatColon( duration/1000) + ", width=" + video_width + ", height=" + video_height );
       
        Method smd_method = player.getClass().getMethod( "setMetaData", new Class[] { Map.class });
       
        Map<String,Object>  md_map = new HashMap<String,Object>();
       
        md_map.put( "duration", duration );
        md_map.put( "width", video_width );
        md_map.put( "height", video_height );
       
        smd_method.invoke( player, new Object[] { md_map });

        final long  bytes_per_sec = file.getLength() / (duration/1000);
     
        long  dl_lim_max     = COConfigurationManager.getIntParameter( "Plugin.azemp.azemp.config.dl_lim_max" ) * 1024L;
        long  dl_lim_extra   = COConfigurationManager.getIntParameter( "Plugin.azemp.azemp.config.dl_lim_extra" ) * 1024L;

        existing_dl_limit = download.getDownloadRateLimitBytesPerSecond();
       
        long  required_limit = Math.max( dl_lim_max, bytes_per_sec + dl_lim_extra );

        if ( required_limit > 0 ){
       
          download.setDownloadRateLimitBytesPerSecond((int)required_limit );
        }
       
        listener.updateActivity( "Average rate=" + DisplayFormatters.formatByteCountToKiBEtcPerSec( bytes_per_sec ) + ", applied dl limit=" + DisplayFormatters.formatByteCountToKiBEtcPerSec( required_limit ));

        synchronized( StreamManager.this ){
         
          if ( cancelled ){
           
            throw( new Exception( "Cancelled" ));
          }
                                                   
          active_edm.setExplicitProgressive( BUFFER_SECS, bytes_per_sec, file_index );
         
          if ( !active_edm.setProgressiveMode( true )){
           
            throw( new Exception( "Failed to set download as progressive" ));
          }
         
          active_edm_activated = true;
        }
       
        new AEThread2( "streamMon" )
        {
         
          public void
          run()
          { 
            final int TIMER_PERIOD     = 250;
            final int PLAY_STATS_PERIOD  = 5000;
            final int PLAY_STATS_TICKS  = PLAY_STATS_PERIOD / TIMER_PERIOD;
           
            final int DL_STARTUP_PERIOD  = 5000;
            final int DL_STARTUP_TICKS  = DL_STARTUP_PERIOD / TIMER_PERIOD;
     
            boolean playback_started   = false;
            boolean  playback_paused    = false;

            boolean  error_reported = false;
           
            try{
              Method start_method     = player.getClass().getMethod( "startPlayback", new Class[] { URL.class });
              Method pause_method     = player.getClass().getMethod( "pausePlayback", new Class[] {});
              Method resume_method     = player.getClass().getMethod( "resumePlayback", new Class[] {});
              Method buffering_method    = player.getClass().getMethod( "bufferingPlayback", new Class[] { Map.class });
              Method play_stats_method  = player.getClass().getMethod( "playStats", new Class[] { Map.class });

              int tick_count = 0;
             
              while( !cancelled ){
                 
                tick_count++;
               
                int dm_state = dm.getState();
               
                boolean complete = file.getLength() == file.getDownloaded();

                if ( !complete ){
                 
                  if (   dm_state == DownloadManager.STATE_ERROR ||
                      dm_state == DownloadManager.STATE_STOPPED ||
                      dm_state == DownloadManager.STATE_QUEUED ){
                   
                    if ( tick_count >= DL_STARTUP_TICKS ){
                   
                      throw( new Exception( "Streaming abandoned, download isn't running" ));
                    }
                  }
 
                  if ( !active_edm.getProgressiveMode()){
                 
                    complete = file.getLength() == file.getDownloaded();
                   
                    if ( !complete ){
                   
                      throw( new Exception( "Streaming mode abandoned for download" ));
                    }
                  }
                }
             
                long[] details = updateETA( active_edm );
               
                int    eta     = (int)details[0];
                int    buffer_secs  = (int)details[1];
                long  buffer    = details[2];
               
                listener.updateStats( eta, buffer_secs, buffer, BUFFER_SECS );

                boolean playable;
               
                int  buffer_to_use = playback_started?BUFFER_MIN_SECS:BUFFER_SECS;
               
                if ( complete ){
                 
                  playable = true;
                 
                }else{
                 
                  playable = buffer_secs > buffer_to_use;
               
                  playable = playable && ( eta <= || (playback_started && !playback_paused ) || preview_mode );
                }
               
                if ( playback_started ){
                 
                  if ( playable ){
                   
                    if ( playback_paused ){
                     
                      listener.updateActivity( "Resuming playback" );
                     
                      resume_method.invoke(player, new Object[] {});

                      playback_paused = false;
                    }
                  }else{
                     
                    if ( !playback_paused ){
                     
                      listener.updateActivity( "Pausing playback to prevent stall" );
                                             
                      pause_method.invoke(player, new Object[] {});
 
                      playback_paused = true;
                    }
                  }
                }else{
                 
                  if ( playable ){
                   
                    listener.ready();
                     
                    start_method.invoke(player, new Object[] { url });
                   
                    playback_started = true;
                  }
                }
             
                if ( playable ){
                 
                  if ( tick_count % PLAY_STATS_TICKS == 0 ){
                     
                    long contiguous_done = active_edm.getContiguousAvailableBytes( active_edm.getPrimaryFile().getIndex(), 0, 0 );
                 
                    Map<String,Object> map = new HashMap<String,Object>();
                   
                    map.put( "buffer_min", new Long( BUFFER_SECS ));
                    map.put( "buffer_secs", new Integer( buffer_secs ));
                    map.put( "buffer_bytes", new Long( buffer ));
                   
                    map.put( "stream_rate", bytes_per_sec );
                   
                    DownloadStats stats = download.getStats();
                   
                    map.put( "dl_rate", stats.getDownloadAverage());
                    map.put( "dl_size", stats.getDownloaded());
                    map.put( "dl_time", SystemTime.getMonotonousTime() - stream_start );
 
                    map.put( "duration", duration );
                    map.put( "file_size", file.getLength());
                    map.put( "cont_done", contiguous_done );
                   
                    play_stats_method.invoke(player, new Object[] { map });
                  }
                }else{
                 
                  DownloadStats stats = download.getStats();

                  Map<String,Object> map = new HashMap<String,Object>();
                 
                  map.put( "state", new Integer( 2 ));

                  if ( preview_mode && !complete ){
                   
                    long rate = stats.getDownloadAverage();
                   
                    int  preview_eta;
                   
                    if ( rate <= 0 ){
                     
                      preview_eta = Integer.MAX_VALUE;
                     
                    }else{
                     
                      double secs_per_sec = ((double)bytes_per_sec)/rate;
                   
                      preview_eta = (int)(( buffer_to_use - buffer_secs ) * secs_per_sec);
                    }
                   
                    map.put( "eta", new Integer( preview_eta ));
                   
                    map.put( "preview", 1 );
                   
                  }else{
                   
                    map.put( "eta", new Integer( eta ));
                   
                    map.put( "preview", 0 );
                  }
                 
                  map.put( "buffer_min", new Long( BUFFER_SECS ));
                  map.put( "buffer_secs", new Integer( buffer_secs ));
                  map.put( "buffer_bytes", new Long( buffer ));
                 
                  map.put( "stream_rate", bytes_per_sec );
                 
                  map.put( "dl_rate", stats.getDownloadAverage());
                  map.put( "dl_size", stats.getDownloaded());
                  map.put( "dl_time", SystemTime.getMonotonousTime() - stream_start );
                 
                  buffering_method.invoke(player, new Object[] { map });
                }
               
                Thread.sleep( TIMER_PERIOD );
               
                try{
                  Boolean b = (Boolean)is_active_method.invoke( player, new Object[0] );
                 
                  if ( !b ){
                   
                    cancel();
                   
                    break;
                  }
                }catch( Throwable e ){ 
                }
              }
            }catch( Throwable e ){
             
              error_reported = true;
             
              listener.failed( e );
             
            }finally{
             
              if ( !( error_reported || cancelled )){
               
                if ( !playback_started ){
               
                  listener.failed( new Exception( "Streaming failed, reason unknown" ));
                }
              }
            }
          }
        }.start();
               
      }catch( Throwable e ){
           
        try{
          listener.failed( e );
         
        }finally{
         
          cancel();
        }
      }
    }
   
    private long[]
    updateETA(
      EnhancedDownloadManager   edm )
    {
      long _eta = edm.getProgressivePlayETA();
         
      int  eta = _eta>=Integer.MAX_VALUE?Integer.MAX_VALUE:(int)_eta;
     
      EnhancedDownloadManager.progressiveStats stats = edm.getProgressiveStats();
     
      long provider_pos = stats.getCurrentProviderPosition( false );
     
      long buffer = edm.getContiguousAvailableBytes( edm.getPrimaryFile().getIndex(), provider_pos, 0 );
     
      long bps = stats.getStreamBytesPerSecondMin();
           
      int  buffer_secs = bps<=0?Integer.MAX_VALUE:(int)(buffer/bps);
                     
      return( new long[]{ eta, buffer_secs, buffer });
    }
   
    public void
    cancel()
    {
      TranscodeJob  job;
     
      EnhancedDownloadManager  edm;
      boolean          edm_activated;
     
      synchronized( StreamManager.this ){
       
        cancelled = true;
     
        job = active_job;
       
        if ( active_sem != null ){
         
          active_sem.releaseForever();
        }
       
        edm       = active_edm;
        edm_activated  = active_edm_activated;
       
        streamers.remove( this );
      }
     
      if ( job != null ){
       
        job.removeForce();
      }
     
      if ( edm != null ){
       
        if ( edm_activated ){
       
          edm.setProgressiveMode( false );
         
        }else{
         
          edm.prepareForProgressiveMode( false );
        }
      }
     
      final Download download = PluginCoreUtils.wrap( dm );

      download.setDownloadRateLimitBytesPerSecond( existing_dl_limit );
    }
   
    public boolean
    isCancelled()
    {
      return( cancelled );
    }
   
    private PluginInterface
    checkPlugin(
      String    id,
      String    name )
   
      throws Throwable
    {
      PluginManager plug_man = AzureusCoreFactory.getSingleton().getPluginManager();
     
      PluginInterface pi = plug_man.getPluginInterfaceByID( id, false );
     
      if ( pi == null ){
       
        listener.updateActivity( "Installing " + name );
       
        final AESemaphore sem = new AESemaphore( "analyserWait" );

        synchronized( StreamManager.this ){
         
          if ( cancelled ){
           
            throw( new Exception( "Cancelled" ));
          }
         
          active_sem  = sem;
        }
       
        final Throwable[] error = { null };
       
        new SimplePluginInstaller(
            id,
              "dlg.install." + id,
              new UIFunctions.actionListener()
            {
              public void
              actionComplete(
                Object    result )
              {
                try{
                  if ( result instanceof Boolean ){
                   
                  }else{
                   
                    error[0] = (Throwable)result;
                  }
                }finally{
                 
                  sem.release();
                }
              }
            });
       
        sem.reserve();
       
        synchronized( StreamManager.this ){
         
          if ( cancelled ){
             
            throw( new Exception( "Cancelled" ));
          }
         
          active_sem  = null;
        }

        if( error[0] != null ){
         
          throw( error[0] );
        }
       
        long start = SystemTime.getMonotonousTime();
       
        listener.updateActivity( "Waiting for plugin initialisation" );
       
        while( true ){
         
          if ( cancelled ){
           
            throw( new Exception( "Cancelled" ));
          }
         
          if ( SystemTime.getMonotonousTime() - start >= 30*1000 ){
           
            throw( new Exception( "Timeout waiting for " + name + " to initialise" ));
          }
         
          pi = plug_man.getPluginInterfaceByID( id, false );

          if ( pi != null && pi.getPluginState().isOperational()){
           
            return( pi );
          }
         
          Thread.sleep(250);
        }
      }else if ( !pi.getPluginState().isOperational()){
       
        throw( new Exception( name + " not operational" ));
       
      }else{
       
        return( pi );
      }
    }
  }   
}
TOP

Related Classes of com.aelitis.azureus.core.download.StreamManager$SMDImpl

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.