Custom Media Types - Constructing a Media Type

XIMPEL is designed such that new media types can easily be added. There are three requirements that a media type implementation should adhere to:

  1. Constructor function: instances of your media type are created by a constructor function (a function that is used with new keyword).
  2. Media type API: the object created by the constructor function implements the media type interace (ie. the object contains a number of functions that each media type should have).
  3. Media type registration: your media type has to be registered with XIMPEL.
We will discuss each of these requirements by working out an example custom media type. Our media type is simple and will only print a text message when its played. We will call our media type Message and we will be able to use our media in the playlist by doing: <message text="message to show" />.


1. Create a constructor function

The first step is to create a constructor function. This is the function that XIMPEL uses to construct an instance of a media type. Lets create the constructor function for our media type.

media_type_message.js

						ximpel.mediaTypeDefinitions.Message = function( customEl, customAttr, $el, player ){
							this.customElements = customEl;
							this.customAttributes = customAttr;
							this.$parentElement = $el;
							this.player = player;
						}
						ximpel.mediaTypeDefinitions.Message.prototype = new ximpel.MediaType();

We defined a function and stored it in ximpel.mediaTypeDefinitions.Message. Then on line 7 we construct a ximpel.MediaType() object and use that as the prototype property of our function.

We could have stored our constructor function in any variable but we stored it as ximpel.mediaTypeDefinitions.Message because ximpel.mediaTypeDefinitions is the namespace that is used by the core XIMPEL media types.

Because the XIMPEL parser knows nothing about our media type, it can't process the attributes and child element of our <message> tag. Only the media type implementation itself knows the meaning of those attributes and child elements. XIMPEL calls the media type constructor function with the custom elements and custom attributes as arguments. This allows the media type implementation to determine what to do with it. XIMPEL also passes the player element to the constructor function, so that the Media Type knows to which DOM element it should attach its content.


2. Implement the media type API

Ok so now we have a constructor function which can create instances of our media type. This is what XIMPEL does when it creates an instance of a media type:
						var messageMediaItem = new ximpel.mediaTypeDefinitions.Message( ... );
Now we need to make sure our instances implement the required functions that each media type is supposed to have. These functions are:
  • mediaPlay: starts/resumes the media item
  • mediaPause: pauses the media item
  • mediaStop: stops the media item entirely (ie. it will start playing from its original starting state when play() is called)
  • mediaIsPlaying: should return true if the media item is playing, false otherwise
  • mediaIsPaused: should return true if the media item is paused, false otherwise.
  • mediaIsStopped: should return true if the media item is stopped, false otherwise.
Let's create those functions for our Message media type.
						ximpel.mediaTypeDefinitions.Message.prototype.mediaPlay = function(){
							this.state = 'playing';
							this.$parentElement.append( this.$messageSpan );
						}

						ximpel.mediaTypeDefinitions.Message.prototype.mediaPause = function(){
							this.state = 'paused';
						}

						ximpel.mediaTypeDefinitions.Message.prototype.mediaStop = function(){
							this.state = 'stopped';
							this.$messageSpan.detach();
						}

						ximpel.mediaTypeDefinitions.Message.prototype.mediaIsPlaying = function(){
							return this.state === 'playing';
						}

						ximpel.mediaTypeDefinitions.Message.prototype.mediaIsPaused = function(){
							return this.state === 'paused';
						}

						ximpel.mediaTypeDefinitions.Message.prototype.mediaIsStopped = function(){
							return this.state === 'stopped';
						}

That's it, our media type implemented all the required functions and is ready to be registered for use.


3. Media type registration

Now that we have a constructor function that can create instances of our media type, we need to register our media type with XIMPEL. By doing so XIMPEL will recognize our <message> tag in the playlist and will be able to create instances of our media type.

Registering the media type is done using the ximpel.registerMediaType(); function. This function takes one argument: a ximpel.MediaTypeRegistration object. We can create this object and register it like this:

					    var r = new ximpel.MediaTypeRegistration( 'message', ximpel.mediaTypeDefinitions.Message, {
							'allowedAttributes': ['text'],
							'requiredAttributes': ['text'],
							'allowedChildren': [],
							'requiredChildren': [],
						} );
						ximpel.registerMediaType( r );

First we create a MediaTypeRegistration object by passing three arguments. The first argument message is the tag name of our media type (<message>). The second argument ximpel.mediaTypeDefinitions.Message is the pointer to the constructor function of our media type so XIMPEL knows how to create instances of our media type. The third argument is an object with four properties:

  1. allowedAttributes: specifies an array containing all the attributes that can be used on the media type tag
  2. requiredAttributes: specifies an array containing all the attributes that are required on the media type tag.
  3. allowedChildren: specifies an array containing all the element names that are allowed for the media type tag.
  4. requiredChildren: specifies an array containing all the element names that are required for the media type tag.


Putting it all together

Store all the code in a javascript file (Message.js):

Message.js

						ximpel.mediaTypeDefinitions.Message = function( customEl, customAttr, $el, player ){
						    this.customElements = customEl;
						    this.customAttributes = customAttr;
						    this.$parentElement = $el;
						    this.player = player;
						 
						    this.$messageSpan = $('');
						    this.$messageSpan.html( this.customAttributes.text );
						    this.$messageSpan.css({
						        'color': 'red',
						        'font-size': '100px'
						    });
						 
						    this.state = 'stopped';
						}
						ximpel.mediaTypeDefinitions.Message.prototype = new ximpel.MediaType();
						 
						ximpel.mediaTypeDefinitions.Message.prototype.mediaPlay = function(){
						    this.state = 'playing';
						    this.$parentElement.append( this.$messageSpan );
						}
						 
						ximpel.mediaTypeDefinitions.Message.prototype.mediaPause = function(){
						    this.state = 'paused';
						}
						 
						ximpel.mediaTypeDefinitions.Message.prototype.mediaStop = function(){
						    this.state = 'stopped';
						    this.$messageSpan.detach();
						}
						 
						ximpel.mediaTypeDefinitions.Message.prototype.mediaIsPlaying = function(){
						    return this.state === 'playing';
						}
						 
						ximpel.mediaTypeDefinitions.Message.prototype.mediaIsPaused = function(){
						    return this.state === 'paused';
						}
						 
						ximpel.mediaTypeDefinitions.Message.prototype.mediaIsStopped = function(){
						    return this.state === 'stopped';
						}

						// Register the media type with XIMPEL
						var r = new ximpel.MediaTypeRegistration('message', ximpel.mediaTypeDefinitions.Message, {
						        'allowedAttributes': ['text'],
						        'requiredAttributes': ['text'],
						        'allowedChildren': [],
						        'requiredChildren': [],
						} );
						ximpel.registerMediaType( r );

In the HTML page you include our Message.js script after jQuery and the XIMPEL core:

				        <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
				        <script type="text/javascript" src="ximpel.js"></script>
				        <script type="text/javascript" src="Message.js"></script>

Let XIMPEL run the following playlist:

				        <ximpel>
						<playlist>
						<subject id="subject1" leadsTo="subject1">
						    <media>
						    	<message text="abcd" duration="5" />
						    	<youtube id="4HoD30-vqPQ" duration="60" />
						    </media>
						</subject>
						</playlist>
						</ximpel>
You will see the text message when XIMPEL starts playing. After five seconds the duration has been exceeded causing our message media item to stop and the youtube media item to play.