9 Replies Latest reply on Oct 5, 2010 10:38 AM by bringrags

    can you use multiple plugins on one piece of media?

    jper1

      can you use multiple plugins on one piece of media?

       

      ...so for example have one plugin for a UI control bar, another for tracking, and another for advertising?

       

      If this is possible how? What types of plugin would each plugin be and what sort of media element would be required?

       

      Or is this not the correct approach? If not what would the correct approach be?

       

      Thanks in advance for support.

        • 1. Re: can you use multiple plugins on one piece of media?
          rshin Level 3

          You may use multiple plugins into one player.  Then you can do whatever you needs for your media using plugins. Is there any specific needs for them to do in one media?

           

          The types of plugins and elements are totally up to your need and implementation.  For instance of your example, "control bar plugin"  for UI control bar ) , "Tube Mogul" plugin as an tracking plugin, and MAST/VAST plugin  as an ad plugin can be loaded into one player.  Once the plugins are loaded, you can use the necessary APIs to implement your own media playback.  If "ad" is part of it, it might make sense to use "serialElement".

          Note though, there might be a glitch when multiple plugins are interacting each other which the team is looking into for improvement.  For that sense, your feedback would be appreciated based on your experience.

           

           

           

          BTW, Control bar plugin and MAST/VAST plugin and their sample apps are located in SVN, plugin samples, and the tracking plugin information is below.

           

          [Tracking plugin information]

          Omniture's plug-in has been released, but it is only available to SiteCatalyst customers.  If you have a SiteCatalyst account, you can access the plug-in by logging into your account.  (http://www.omniture.com/static/2143)

           

          Another option for an analytics plug-in is TubeMogul's.  They have a free version available.  http://tubemogul.com/public/showPage/osmf_plugin

           

          Ryan

          • 2. Re: can you use multiple plugins on one piece of media?
            jper1 Level 1

            Hi Ryan,

             

            Thanks for your response.

             

            As a first step I am trying to get a plugin to work.

             

            I have created a ProxyPlugin. Just to see how they work. I want to get this ProxyPlugin to trace the current time of the proxied media element.

             

            I think the issue is understanding when and how the proxied media element gets set when using a proxy plugin?

            But it may be something else.

             

            Here's what's in the code I have:

             

            In my Proxy plugin, (which I got from the plugin dev doc and amended):

             

            The mediaElementCreationCallback does this:

             

            private function mediaElementCreationCallback():MediaElement
            {
                   trace('mediaElementCreationCallback ' + ID)

                   // this traces out correctly
                   return new TraceListenerProxyElement(null);

            }

             

            The  mediaElementCreationNotificationCallback does this:

             

            private function mediaElementCreationNotificationCallback(target:MediaElement):void
                    {
                        trace('mediaElementCreationNotificationCallback')

                       // this traces out correctly (VideoElement)
                        this.target = target;
                        trace(target)
                    }

             

            In the plugin developer doc it days:

            // The ProxyElement generated by this function will wrap, or
            // proxy, another MediaElement generated by the MediaFactory.
            // This method should *not* assign a value to the proxiedElement,
            // the MediaFactory in the player application will do that.

             

             

            I got the TraceListenerProxyElement out of one of the samples in the SVN.

            It's constructor function does the below...

            ...however when the trace(wrappedElement) is called it traces a value of null.

            And then dispatcher eventlisteners never fire, presumably because the wrappedElement is null.

            When does the wrappedElement get set when using a proxy plugin?

             

            public function TraceListenerProxyElement(wrappedElement:MediaElement)
                    {
                        trace('TraceListenerProxyElement')

                       // this traces correctly
                        super(wrappedElement);
                        trace(wrappedElement);

                       // this traces null
                        dispatcher = new TraitEventDispatcher();
                        dispatcher.media = wrappedElement;
                                   
                        dispatcher.addEventListener(AudioEvent.MUTED_CHANGE, processMutedChange);
                        dispatcher.addEventListener(AudioEvent.PAN_CHANGE, processPanChange);
                        dispatcher.addEventListener(AudioEvent.VOLUME_CHANGE, processVolumeChange);
                        dispatcher.addEventListener(BufferEvent.BUFFER_TIME_CHANGE, processBufferTimeChange);
                        dispatcher.addEventListener(BufferEvent.BUFFERING_CHANGE, processBufferingChange);
                        dispatcher.addEventListener(DisplayObjectEvent.DISPLAY_OBJECT_CHANGE, processDisplayObjectChange);
                        dispatcher.addEventListener(DisplayObjectEvent.MEDIA_SIZE_CHANGE, processMediaSizeChange);
                        dispatcher.addEventListener(DRMEvent.DRM_STATE_CHANGE, processDRMStateChange);
                        dispatcher.addEventListener(DynamicStreamEvent.AUTO_SWITCH_CHANGE, processAutoSwitchChange);
                        dispatcher.addEventListener(DynamicStreamEvent.NUM_DYNAMIC_STREAMS_CHANGE, processNumDynamicStreamsChange);
                        dispatcher.addEventListener(DynamicStreamEvent.SWITCHING_CHANGE, processSwitchingChange);
                        dispatcher.addEventListener(LoadEvent.BYTES_TOTAL_CHANGE, processBytesTotalChange);
                        dispatcher.addEventListener(LoadEvent.LOAD_STATE_CHANGE, processLoadStateChange); 
                        dispatcher.addEventListener(PlayEvent.CAN_PAUSE_CHANGE, processCanPauseChange);
                        dispatcher.addEventListener(PlayEvent.PLAY_STATE_CHANGE, processPlayStateChange);
                        dispatcher.addEventListener(SeekEvent.SEEKING_CHANGE, processSeekingChange);
                        dispatcher.addEventListener(TimeEvent.COMPLETE, processComplete);
                        dispatcher.addEventListener(TimeEvent.DURATION_CHANGE, processDurationChange);
                       
                        wrappedElement.addEventListener(MediaElementEvent.TRAIT_ADD, processTraitAdd);
                        wrappedElement.addEventListener(MediaElementEvent.TRAIT_REMOVE, processTraitRemove);           
                    }

            • 3. Re: can you use multiple plugins on one piece of media?
              rshin Level 3

              Have you overwritten set proxyiedElement in your proxy-plugin?  If you look at the proxyElement.as there is getter and setter for mediaElement(proxiedElement).

               

              For instance of a proxy element of a plugin here,

               

                  public class sampleProxyElement extends ProxyElement
                  {   
                      public function sampleProxyElement(proxiedElement:MediaElement)
                      {
                          super(proxiedElement);
                 
                      }
                     
                      override public function set proxiedElement(value:MediaElement):void
                      {
                          super.proxiedElement = value;
                          this.addEventListener(MediaElementEvent.TRAIT_ADD, onTraitAdd);
                      }

               

              .....

               

              Also there is an example of proxy plugin (if that's the type of plugin you wanted to do):  VideoQoSPlugin.  In the example, VideoQosProxyElement wraps a media element for getting QoS data.

              http://opensource.adobe.com/svn/opensource/osmf/trunk/apps/samples/plugins/VideoQoSPlugin/ src/org/osmf/qos/

               

               

              Ryan

              • 4. Re: can you use multiple plugins on one piece of media?
                David_RealEyes

                Only thing I would add is when using proxy pluins in the override for the proxiedElement we had to usual wrap the contents in an if statement that checks for null. Havnt figured out why but seems like it runs the first time a lot with null as the value and pending on what you are doing inside the function it can error silently.

                 

                       override public function set proxiedElement(value:MediaElement):void
                        {
                            if( value)

                            {

                               super.proxiedElement = value;
                                 this.addEventListener(MediaElementEvent.TRAIT_ADD, onTraitAdd);

                            }
                        }

                • 5. Re: can you use multiple plugins on one piece of media?
                  rshin Level 3

                  The guideline of a proxy-plugin is not to have its proxied element set.  (see the below points regarding to a proxy plug-in).

                  So, the above question from iper1 is in principal, like an example of TraceListenerProxyElement or Unseekab leProxyElement that don't have a set of proxied, is set in super(wrappedElement) when the media element is assigned.  However, there are other examples of proxy-pugins that sets a proxiedElement when needed such as in VideoQoS example when it needs modify the logic.

                   

                  If you see a null, please first check if you have set MediaFactoryItemType as "Proxy" in your MediaFactoryItem.

                   

                  // Create the MediaFactoryItem and add to our list of items.
                  var item:MediaFactoryItem = new MediaFactoryItem
                  ( "com.example.proxyplugin"
                  , canHandleResourceFunction
                  , mediaElementCreationFunction
                  , MediaFactoryItemType.PROXY)

                   

                   

                  There are a few key points to be aware of when building a proxy plug-in:
                  1. The MediaFactoryItem must specify a MediaFactoryItemType of PROXY.
                  2. The MediaFactoryItem’s mediaElement method must return a ProxyElement or subclass of ProxyElement. The created ProxyElement should not have its proxiedElement set, the MediaFactory will assign a value to the proxiedElement property.
                  3. The MediaFactoryItem’s canHandleResourceFunction should return true for any resource whose corresponding MediaElement should be proxied by the ProxyElement.

                   

                  "Any method or property that the player application invokes will return the value from the proxied MediaElement, unless the ProxyElement itself intercepts that request to modify the behavior"

                   

                   

                  http://opensource.adobe.com/wiki/download/attachments/34373765/osmf_plugin_dev_guide.pdf

                   

                   

                  Ryan

                  • 6. Re: can you use multiple plugins on one piece of media?
                    David_RealEyes Level 1

                    We match and follow all those rules and criteria yet many times in the override for the setter we get null - I think its when the class is instantiated.

                    • 7. Re: can you use multiple plugins on one piece of media?
                      jper1 Level 1

                      I have got this plugin to set it's proxiedElement.

                      To do so, I needed to follow David_RealEyes advice too.

                       

                      But I still can not acheive what I set out to find out, all I was trying to do was trace the current time of the videoElement, to begin to understand how plugins work. Can anyone advise please? Thanks in advance for support.

                       

                      I thought to acheive this I would just need to add  a listener for like this:

                      dispatcher.addEventListener(TimeEvent.CURRENT_TIME_CHANGE,  onTimeChange);

                       

                      Then write the function like this:      

                      private function onTimeChange(e:TimeEvent):void
                               {
                                   trace('**********onTimeChange: '+ e.time)
                               }

                       

                      ...But this doesn't work.

                      What am I doing wrong?

                       

                      Here's the class now for the TraceListenerProxyElement

                       

                      package
                      {
                          import org.osmf.elements.*;
                          import org.osmf.events.*;
                          import org.osmf.media.*;
                          import org.osmf.metadata.*;
                          import org.osmf.traits.*;
                         
                          public class TraceListenerProxyElement extends ProxyElement
                          {
                              public function TraceListenerProxyElement(wrappedElement:MediaElement)
                              {
                                  trace('TraceListenerProxyElement')
                                  super(wrappedElement);
                                  /*
                                  */
                              }
                             
                             
                              // Overrides
                              //
                              override public function set proxiedElement(value:MediaElement):void
                              {
                                  trace('override set proxy')
                                  trace('value: ' + value)
                                 
                                  if(value)
                                  {
                                     super.proxiedElement = value;
                                     trace('proxied element set')
                                     enableListeners()

                       

                                  }
                                 
                                  super.proxiedElement = value;
                                  trace('proxied el: ' + proxiedElement)
                              }
                             
                              private function enableListeners():void
                              {
                                  trace('enableListeners')
                                  dispatcher = new TraitEventDispatcher();
                                  dispatcher.media = proxiedElement;
                                             
                                  dispatcher.addEventListener(AudioEvent.MUTED_CHANGE, processMutedChange);
                                  dispatcher.addEventListener(AudioEvent.PAN_CHANGE, processPanChange);
                                  dispatcher.addEventListener(AudioEvent.VOLUME_CHANGE, processVolumeChange);
                                  dispatcher.addEventListener(BufferEvent.BUFFER_TIME_CHANGE, processBufferTimeChange);
                                  dispatcher.addEventListener(BufferEvent.BUFFERING_CHANGE, processBufferingChange);
                                  dispatcher.addEventListener(DisplayObjectEvent.DISPLAY_OBJECT_CHANGE, processDisplayObjectChange);
                                  dispatcher.addEventListener(DisplayObjectEvent.MEDIA_SIZE_CHANGE, processMediaSizeChange);
                                  dispatcher.addEventListener(DRMEvent.DRM_STATE_CHANGE, processDRMStateChange);
                                  dispatcher.addEventListener(DynamicStreamEvent.AUTO_SWITCH_CHANGE, processAutoSwitchChange);
                                  dispatcher.addEventListener(DynamicStreamEvent.NUM_DYNAMIC_STREAMS_CHANGE, processNumDynamicStreamsChange);
                                  dispatcher.addEventListener(DynamicStreamEvent.SWITCHING_CHANGE, processSwitchingChange);
                                  dispatcher.addEventListener(LoadEvent.BYTES_TOTAL_CHANGE, processBytesTotalChange);
                                  dispatcher.addEventListener(LoadEvent.LOAD_STATE_CHANGE, processLoadStateChange); 
                                  dispatcher.addEventListener(PlayEvent.CAN_PAUSE_CHANGE, processCanPauseChange);
                                  dispatcher.addEventListener(PlayEvent.PLAY_STATE_CHANGE, processPlayStateChange);
                                  dispatcher.addEventListener(SeekEvent.SEEKING_CHANGE, processSeekingChange);
                                  dispatcher.addEventListener(TimeEvent.COMPLETE, processComplete);
                                  dispatcher.addEventListener(TimeEvent.DURATION_CHANGE, processDurationChange);
                                  dispatcher.addEventListener(TimeEvent.CURRENT_TIME_CHANGE, onTimeChange);
                                 
                                  proxiedElement.addEventListener(MediaElementEvent.TRAIT_ADD, processTraitAdd);
                                  proxiedElement.addEventListener(MediaElementEvent.TRAIT_REMOVE, processTraitRemove);
                              }
                             
                              private function onTimeChange(e:TimeEvent):void
                              {
                                  trace('**********onTimeChange: '+ e.time)
                              }
                              private function processAutoSwitchChange(event:DynamicStreamEvent):void
                              {
                                  trace("autoSwitchChange", event.autoSwitch);
                              }
                             
                              private function processBufferingChange(event:BufferEvent):void
                              {
                                  trace("bufferingChange", event.buffering);
                              }
                             
                              private function processBufferTimeChange(event:BufferEvent):void
                              {
                                  trace("bufferTimeChange", event.bufferTime);
                              }
                             
                              private function processComplete(event:TimeEvent):void
                              {
                                  trace("complete");
                              }
                             
                              private function processCanPauseChange(event:PlayEvent):void
                              {
                                  trace("canPauseChange", event.canPause);
                              }
                             
                              private function processDisplayObjectChange(event:DisplayObjectEvent):void
                              {
                                  trace("displayObjectChange");
                              }
                             
                              private function processDurationChange(event:TimeEvent):void
                              {
                                  trace("durationChange", event.time);
                              }
                             
                              private function processLoadStateChange(event:LoadEvent):void
                              {
                                  trace("loadStateChange", event.loadState);
                              }
                             
                              private function processBytesTotalChange(event:LoadEvent):void
                              {
                                  trace("bytesTotalChange", event.bytes);
                              }
                             
                             
                              private function processMediaSizeChange(event:DisplayObjectEvent):void
                              {
                                  trace("mediaSizeChange", event.newWidth, event.newHeight);
                              }
                             
                              private function processMutedChange(event:AudioEvent):void
                              {
                                  trace("mutedChange", event.muted);
                              }
                             
                              private function processNumDynamicStreamsChange(event:DynamicStreamEvent):void
                              {
                                  trace("numDynamicStreamsChange");
                              }
                             
                              private function processPanChange(event:AudioEvent):void
                              {
                                  trace("panChange", event.pan);
                              }
                             
                              private function processPlayStateChange(event:PlayEvent):void
                              {
                                  trace("playStateChange", event.playState);
                              }
                             
                              private function processSeekingChange(event:SeekEvent):void
                              {
                                  trace("seekingChange", event.seeking, event.time);
                              }
                             
                              private function processSwitchingChange(event:DynamicStreamEvent):void
                              {
                                  trace("switchingChange", event.switching);
                              }
                             
                              private function processVolumeChange(event:AudioEvent):void
                              {
                                  trace("volumeChange", event.volume);
                              }
                             
                              private function processDRMStateChange(event:DRMEvent):void
                              {
                                  trace("drmStateChange", event.drmState);
                              }
                             
                              private function processTraitAdd(event:MediaElementEvent):void
                              {
                                  trace("Trait Add: " + event.traitType);
                              }
                         
                              private function processTraitRemove(event:MediaElementEvent):void
                              {
                                  trace("Trait Remove: " + event.traitType);
                              }
                         
                             
                              private var dispatcher:TraitEventDispatcher;
                          }
                      }

                      • 8. Re: can you use multiple plugins on one piece of media?
                        B3N$MiTH

                        for one reason or another the TimeEvent.CURRENT_TIME_CHANGE dose not update when the playhead changes, I know this is a bit missleading and had me scratching my head for some time.

                         

                        Unfortunately the only way of tracking the playhead's current time is by creating a Timer and checking the TimeTrait.currentTime value every 1 sec or so. You will see this technique used to update the playhead of the scrub bar for instance.

                         

                         

                        • 9. Re: can you use multiple plugins on one piece of media?
                          bringrags Level 4

                          Yes, a MediaElement's TimeTrait does not dispatch the TimeEvent.CURRENT_TIME_CHANGE event regularly, as we would have had to implement a Timer in the framework (and pick an arbitrary interval) in order to do so (and not every client would want to carry the burden of an additional Timer just to get playhead change events).

                           

                          At the MediaPlayer level, we do dispatch such an event (and the client can specify the interval with the currentTimeUpdateInterval property) for convenience (though MediaPlayer is typically not available within a plugin).