Order Now AdSolution Sign Up | Login » Bits on the Run Sign Up | Login »

Forums

/

plugin to display a JPEG at certain intervals

7 replies [Last post]

Hi,

I'm looking to develop a plugin which would take in an XML file path containing something like:
<infocard time="34s" duration="5s">image1.jpg</infocard>

This would put up the image1.jpg for 5 seconds on the currently playing video when it gets to 34 seconds in duration.

Ideally, multiple infocard elements should be supported.

Anything like this exist I can expand on? Or any thoughts on how I should approach something like this?

I plan to use the latest JW player (version 5).

Thanks.

Thanks for the respone Alf. Per that thread, the plugin here: http://willswonders.myip.org:8074/player5/Simple_Slideshow_v5.html

is pretty close to what I'm looking to do.. but I want to overlay the jpegs on top of the video, not in a div. Unfortunately I don't see any source code posted for the plugin nor any contact info for the person who made it.

 
I can post the source if you need it.

The title, slide, and description are placed in division elements, which can be placed anywhere, including overlaid on the player.

That would be great Alf, thanks!

Hi Alf.. just checking to see if you were able to find/post the source code. Thanks!

 

/*
 * Slideshow Plugin; implements a timed Slideshow.
 */
package com.longtailvideo.plugins.slideshow
{

  import com.longtailvideo.jwplayer.events.MediaEvent;
  import com.longtailvideo.jwplayer.events.ViewEvent;
  import com.longtailvideo.jwplayer.events.PlaylistEvent;
  import com.longtailvideo.jwplayer.events.PlayerStateEvent;
  import com.longtailvideo.jwplayer.player.IPlayer;
  import com.longtailvideo.jwplayer.player.PlayerState;
  import com.longtailvideo.jwplayer.plugins.IPlugin;
  import com.longtailvideo.jwplayer.plugins.PluginConfig;
  import com.longtailvideo.jwplayer.utils.Configger;
  import com.longtailvideo.jwplayer.utils.Logger;

  import com.longtailvideo.jwplayer.parsers.XMLParser;
  
  import flash.display.DisplayObject;
  import flash.display.MovieClip;
  import flash.events.Event;
  import flash.net.*;
  import flash.text.*;

  import flash.external.ExternalInterface;

  public class Slideshow extends MovieClip implements IPlugin
  {
    [Embed(source='../../../../../assets/controlbar.png')]
    private const ControlbarIcon:Class;
    [Embed(source='../../../../../assets/dock.png')]
    private const DockIcon:Class;

    /** Reference to the player. **/
    private var _player:IPlayer;
    /** Reference to the plugin's configuration **/
    private var _config:PluginConfig;
    /** Reference to the dock _button. **/
    private var _button:MovieClip;
    /** Reference to the clip on stage. **/
    private var _icon:DisplayObject;
    /** XML connect and parse object. **/
    private var _loader:URLLoader;
    /** The current playlist item **/
    private var _currentIndex:Number;
    /** The current position inside a video. **/
    private var _position:Number = 0;

    /** The slideshow file, time, slide, title, description, current & previous slides, & global duration **/
    /** The array the slides are loaded into. **/
    private var _slides:Array;
    /** The current slide **/
    private var _current:Number;
    /** The current slide **/
    private var _duration:Number;

/** Textformat entry for the slides. **/
private var _format:TextFormat;   //...???

//...was for HD ???
/** reference to the original file. **/
private var _original:String;

//...testing
    /** The duration of the media file. **/
    private var _length:Number = 0;

    public function Slideshow():void
    {
      _loader = new URLLoader();
      _loader.addEventListener(Event.COMPLETE, loaderHandler);
    }

    /** The initialize call is invoked by the player. **/
    public function initPlugin(player:IPlayer, cfg:PluginConfig):void
    {
      _player = player;
      _config = cfg;

//ExternalInterface.call("(function(input){alert('Slideshow::initPlugin:: 1. config.state: ' + input);})", config.state);

/* what is this used for ???
      if(config.state == 'true')
      {
        config.state = true;
      }
      else
      {
        config.state = false;        
      }
*/

//ExternalInterface.call("(function(input){alert('Slideshow::initPlugin:: 2. config.state: ' + input);})", config.state);

      _player.addEventListener(MediaEvent.JWPLAYER_MEDIA_TIME,          timeHandler);
      _player.addEventListener(ViewEvent.JWPLAYER_VIEW_SEEK,            seekHandler);
      _player.addEventListener(PlayerStateEvent.JWPLAYER_PLAYER_STATE,  stateHandler);
      _player.addEventListener(PlaylistEvent.JWPLAYER_PLAYLIST_ITEM,    itemLocker);

//...testing
      _player.addEventListener(MediaEvent.JWPLAYER_MEDIA_META,          metaHandler);

//...what is this used for ???
      if(config.state)
      {
        config.file = config.file;
      }

//ExternalInterface.call("(function(input){alert('Slideshow::initPlugin:: 3. config.file: ' + input);})", config.file);

//...what is this used for ???
      if(config.state)
      {
        config.duration = config.duration;
      }

//ExternalInterface.call("(function(input){alert('Slideshow::initPlugin:: 4. config.duration: ' + input);})", config.duration);

      if(_player.config.dock)
      {
        if(_player.skin.getSkinElement('slideshow', 'dockIcon'))
        {
          _icon = _player.skin.getSkinElement('slideshow', 'dockIcon');
        }
        else
        {
          _icon = new DockIcon();
        }
        _button = _player.controls.dock.addButton(_icon, 'is on', clickHandler);
      }
      else
      {
        if(_player.skin.getSkinElement('slideshow', 'controlbarIcon'))
        {
          _icon = _player.skin.getSkinElement('slideshow', 'controlbarIcon');
        }
        else
        {
          _icon = new ControlbarIcon();
        }
        _player.controls.controlbar.addButton(_icon, 'SS', clickHandler);
      }

//...add listener here ??? (see Captions)

      setUI();
    };

    /** Upon resize, what to do here ???. **/
    public function resize(width:Number, height:Number):void
    {
      if(config.fullscreen && (_player.fullscreen != _player.state && _player.state != PlayerState.IDLE))
      {
        //...what ???
        //clickHandler();
      }
    };

    public function get config():PluginConfig
    {
      return _player.config.pluginConfig('slideshow');
    };
    

    public function get id():String
    {
      return _config.id;
    };

    /** Check current slide time and position to display a slide. **/
    private function timeHandler(evt:MediaEvent):void
    {

//var input:String = _current + '  ' + ((evt.position % 1 == 0) ? evt.position + '.0' : evt.position);
//ExternalInterface.call("(function(input){gid('position').innerHTML=input;})", input);

      if(config.state)
      {
        _position = evt.position;

//                                            5 > 3                                                                  10 < 3
      //if(_slides && ((_slides[_current]['time'] > _position) || (_slides[_current + 1] && _slides[_current + 1]['time'] < _position)))
        if(_slides && ((_slides[_current]['time'] < _position) || (_slides[_current + 1] && _slides[_current + 1]['time'] < _position)))
        {
          setSlide(_position);
        }
      }
    };

    /** On seek, reset current to 0. **/
    private function seekHandler(evt:ViewEvent):void
    {
      _current = 0;
    };

    /** On state=PLAY, reset current to 0. **/
    private function stateHandler(evt:PlayerStateEvent):void
    {
      if(evt.newstate == 'PLAYING')
      {
//ExternalInterface.call("(function(input){alert('Slideshow::stateHandler::evt.newstate: ' + input);})", evt.newstate);
        _current = 0;
      }

      if(evt.newstate == 'IDLE')
      {
        _current = 0;
        clearSlide();
      }
    };

//...for getting a new file when the item index changes - needed ??
    /** Locks the player and updates the current item **/
    private function itemLocker(evt:PlaylistEvent):void
    {
      if(_currentIndex != _player.playlist.currentIndex)
      {
        if(_original)
        {
          _player.playlist.getItemAt(_currentIndex).file = _original;
        }

        _currentIndex  = _player.playlist.currentIndex;
        _original      = _player.playlist.getItemAt(_currentIndex).file;
        _position      = 0;
        _player.lock(this, itemHandler);
      }
    };

    /** Check for a slidelist with a new item. **/
    private function itemHandler():void
    {
      _current        = 0;
      _slides         = new Array();
      config['file']  = undefined;
      var file:String;

//ExternalInterface.call("(function(input){alert('Slideshow::itemHandler:: Step 1 _current: ' + input);})", _current);

      if(_player.playlist.currentItem['slideshow.file'])
      {
        file = _player.playlist.currentItem['slideshow.file'];
      }
      else if(config['slideshow.file'])
      {
        file = config['slideshow.file'];
      }

//...shouldn't load slidelist here unless state=true
      if(file)
      {
        config['file'] = file;

//ExternalInterface.call("(function(input){alert('***Slideshow::itemHandler::File: ' + input);})", config['file']);

        try
        {
          _loader.load(new URLRequest(config['file']));
        }
        catch (err:Error)
        {
ExternalInterface.call("(function(input){alert('***Slideshow::itemHandler::Error: ' + input);})", err.message);
          Logger.log(err.message, 'slideshow');
        }
      }

      if(_player.locked)
      {
        _player.unlock(this);
      }
    };

//...more code needed here to toggle the slideshow display
    /** Slideshow button is clicked, so toggle the slideshow display. **/
    private function clickHandler(evt:Event = null):void
    {
//...reset the current slide index
_current = 0;
      config.state = !config.state;
      Configger.saveCookie(id + ".state", config.state);
      setUI();

      if(config.state)
      {
        itemHandler();
      }
      else
      {
        clearSlide();
      }
    };

    /** Parse XML into an array. **/
    private function loaderHandler(evt:Event):void
    {

//ExternalInterface.call("(function(input){alert('Slideshow::loaderHandler::evt.target.data.length: ' + input);})", evt.target.data.length);
//ExternalInterface.call("(function(input){alert('Slideshow::loaderHandler::evt.target.data: ' + input);})", evt.target.data);

      _slides = XMLParser.parseSlides(XML(evt.target.data));

//ExternalInterface.call("(function(input){alert('Slideshow::loaderHandler::_slides.length: ' + input);})", _slides.length);
//ExternalInterface.call("(function(input){alert('Slideshow::loaderHandler::_slides: ' + input);})", _slides);
//ExternalInterface.call("(function(input){alert('Slideshow::loaderHandler::_slides[0][\\'time\\']: ' + input);})",  _slides[0]['time']);
//ExternalInterface.call("(function(input){alert('Slideshow::loaderHandler::_slides[0][\\'title\\']: ' + input);})",  _slides[0]['title']);
//ExternalInterface.call("(function(input){alert('Slideshow::loaderHandler::_slides[15][\\'time\\']: ' + input);})", _slides[0]['time']);
//ExternalInterface.call("(function(input){alert('Slideshow::loaderHandler::_slides[15][\\'title\\']: ' + input);})", _slides[15]['title']);

      if(_slides.length == 0)
      {
        Logger.log('Not a valid Slidelist file.', 'slideshow');
      }
    };

    /** Display the title, image, and description. **/
    private function setSlide(pos:Number):void
    {
    //for(var i:Number = 0; i < _slides.length; i++)
      for(var i:Number = 0; i < _slides.length - 1; i++)
      {

//ExternalInterface.call("(function(input){alert('Slideshow::setSlide::Position: ' + input);})", pos);

      //if((_slides[i]['time'] < pos) && ((i == _slides.length - 1) || (_slides[i + 1]['time'] > pos)))
        if((_slides[i]['time'] < pos) && ((i == _slides.length - 2) || (_slides[i + 1]['time'] > pos)))
        {
          _current = i;
//...needs width & height
        //resize();
          Logger.log(_slides[i]['title'], 'slideshow');

          if((Number(_slides[_current]['time']) + _config.duration) < _position)
          {
clearSlide();
          }
          else
          {
            ExternalInterface.call("(function(input){gid('title').innerHTML=input;})",                           _slides[i]['title']);
            ExternalInterface.call("(function(input){gid('image').innerHTML='<img src=\"' + input + '\" />';})", _slides[i]['image']);
            ExternalInterface.call("(function(input){gid('description').innerHTML=input;})",                     _slides[i]['description']);
            ExternalInterface.call("(function(input){gid('time').innerHTML=input;})",                            _slides[i]['time']);
          }

//...finish this later
          if(config['listener'])
          {
            try
            {
              if((Number(_slides[_current]['time']) + _config.duration) < _position)
              {
                //...maybe also image and description ???
                ExternalInterface.call(config['listener'], '');
              }
              else
              {
                //...maybe also image and description ???
                ExternalInterface.call(config['listener'], _slides[i]['title']);
              }
            }
            catch(err:Error)
            {
            }
          }

        return;
        }
      }
    };

    /** Clear the slide title, image file, and description. **/
    private function clearSlide():void
    {
      ExternalInterface.call("(function(input){gid('title').innerHTML=input;})",       '');
      ExternalInterface.call("(function(input){gid('image').innerHTML=input;})",       '');
      ExternalInterface.call("(function(input){gid('description').innerHTML=input;})", '');
      ExternalInterface.call("(function(input){gid('time').innerHTML=input;})",        '');
    };

    /** Set the Slideshow _button state. **/
    private function setUI():void
    {
      if(config.state == false)
      {
        if(_button)
        {
          _button.field.text = 'is off';
        }
        else
        {
          _icon.alpha = 0.3;
        }
      }
      else
      {
        if(_button)
        {
          _button.field.text = 'is on';
        }
        else
        {
          _icon.alpha = 1;
        }
      }
    };

//...testing
    private function metaHandler(evt:MediaEvent):void
    {
      if(evt.metadata.duration != undefined)
      {
        _length = evt.metadata.duration;
      }

      ExternalInterface.call("(function(input){gid('duration').innerHTML='Duration: ' + input;})", _length);
    };

  }
}

Thanks, looks like I'll only need some minor customizations.