Vyew Client-side API


Overview

Vyew plugins (also called sub-pods), are created in Adobe Flash, compiled, then imported into Vyew just like you normally would import any other document. There is one difference though:

When importing a plugin into Vyew, make sure you check the box “Interactive Object”, so that it can retain all its functionality


Example Plugin Sourcode

File type: Flash 8 (.FLA file) and Actionscript 2 (.AS files)
vyew-subpod-plugin-example.zip


Setting up your FLA / .AS file

  1. Download this zip file for some examples:
    • COMING SOON - I'm still in the process of packaging this and uploading it. Please read the rest of the documentation and familiarize yourself with it.
  2. Create a single movieclip on the root timeline of your swf
    • Instance name: 'pod'
    • Link it to an AS2 class. For example, “as.subpods.ExampleSubPod”
    • This movieclip is for communication with vyew & server. You can put other things on the root of your swf if you want, but good practice is to have everything self-contained.
  3. Create the corresponding .AS file, for example “as/subpods/ExampleSubPod.as”
  4. Fill in this required AS skeleton. (Look at the ExampleSubPod AS file to see an example of a completed one)
  class as.subpods.ExampleSubPod extends MovieClip {
 
	//this is needed for vyew to recognize this swf as a plugin
	public var isSubPod:Boolean = true;
 
	//this is needed so that vyew will accept this as a user-created plugin.
	//otherwise, it will attempt to talk to it securely, and some data will not work.
	public var userPlugin:Boolean = true;
 
	//If this is set to true, then the tab / skin for the plugin will NOT
	// be created. If you want to be able to enable/disable the tab, use the
	// hideMySkin(hide) function instead
	public var hideSkin:Boolean = false;
 
        // If this flag is set to true, then only one of this plugin will be allowed to load
        // on a page at a time.
	public var disableMultiple:Boolean = false;
 
	public function setSize(w:Number, h:Number):Void {
		// resize the pod's contents
                // bg._width = w; bg._height = h;
	}
 
	public function getSize():Object {
		// return the current size of the contents
                // return {w:bg._width, h:bg._height};
	}
 
	public function handlePodEvent(type:String, args_in:String):Void {
		var args:Object = JSON.decodeSafe(args_in);
		
		switch(type) {
		//handle events from other sub pods including this one
		case 'onUsertypeChanged':
			//args.data.usertype contains new usertype
		break;
 
		case 'setPodItem':
			//if setPodItem is called with sync=true, args.k contains the key and args.d contains the data
		break;
 
		case 'setPodElement':
		case 'pushPodElement':
			//if setPodItem or pushPodElement is called with sync=true, 
			//args.k contains the key, args.i contains the index, and args.d contains the data
		break;
		}
	}
 
	public function onInit():Void {
		//called from subPodMgr when everything is ready
	}
 
	function gotPodData(data_in:String) {	
		var data:Object = JSON.decodeSafe(data_in);
		// callback for recieving requested stored data
		// this function gets called when we request the stored data
	}
 
	function destroy():Void {
		// This function will be called right before your plugin is deleted
		// from the page. Use it to free memory, stop sounds, etc
	}
	
 
	// These functions will be populated at runtime.
	// The declarations are here for compile-time type-checking.
	// Nothing needs to be written, the code in there is just so that you can kind of test it on it's own.
	
	
	// Send an event to all other instances of this subPod on other clients
	function sendPodEvent(args:Object):Void {}
	
	// Store data on server
	function setPodData(data:Object):Void {}
	
	// Retrieve stored data on server
	function getPodData():Void {}
 
	// remove ourself
	function removeMe():Void {}
 
	// begin transform
	function beginTransform():Void {}
 
	// move & resize ourself. dx, dy are RELATIVE, not absolute.
	function applyTransform(dx:Number, dy:Number, w:Number, h:Number):Void {}
	
	// function to hide the tab controls
	function hideMySkin(doHide):Void{}
	
	// return info about ourself.
	// This returns a 'Media' object, see as.pods.layer.Media for all the available attributes
	function getInfo():Object {return null;}
	
	/// One object
	
	// return one object in pod data
	function getPodItem(key:String, callback:Function):Void {}
	
	// set one object in pod data
	function setPodItem(key:String, data:Object, sync:Boolean):Void {}
	
	// delete a pod data item or array
	function delPodItem(key:String, sync:Boolean):Void	{}
	
	/// Arrays											
	
	// Create an array in the pod data
	function createPodArray(key:String):Void {}
	
	// return a single element from an array
	function getPodElement(key:String, index:Number, callback:Function):Void {}
	
	// set a single element in an array
	function setPodElement(key:String, index:Number, data:Object, sync:Boolean):Void {}
	
	// add a single element to the end of an array
	function pushPodElement(key:String, data:Object, sync:Boolean):Void {}
 
	// delete one or more elements from an array
	function splicePodElement(key:String, index:Number, length:Number, sync:Boolean):Void {}		
	
	// return the length of an array
	function getPodArrayLength(key:String, callback:Function):Void {}
	
	// decode an item. If you use createPodArray, but later call getPodItem to get the whole array,
	// then individual elements will be encoded. You must decode them manually.
	// They are automatically decoded when using the various *podElement methods.
	function decode(o) {return as.JSON.decodeSafe(o);}
 
 
  }//END CLASS

Server Communication

  • There are 2 ways of communicating with the server / other clients.
  • 1. Events.
    • These are things that happen instantly, and are broadcast to all the other clients, including the one who sent it.
    • The general flow of interaction is:
   User presses button ---> SubPod sends event ----> SubPod recieves event -> SubPod reacts 
                        | 
   			\-> SubPod updates state on Server 
  • The key is, that while one user will send the event, all users will recieve the event, thus everyone's screen will react the same when one user presses a button.
  • Functions:
    • sendPodEvent(args:Object) – This will broadcast to every client, and the corresponding
    • handlePodEvent(type:String, args_in:String) function will be called, with the same data passed. (NOTE: args_in is JSON encoded, make sure to decode first)
  • WARNING: MAKE SURE there is nothing the user can do which changes the interface or state, which does not also send an event & update state! Otherwise things will get out of sync!
  • 2. Storing Data.
  • This is for storing the current state of the pod, so that when someone new comes into the meeting, their screen will be updated to look the same as everyone elses.

Functions

  • callback – if specified, this function will be called with the requested data as the 1st param
  • sync – if set to 'true' all clients will recieve an event notifying them of the data change. The event type will be the same as the function name called, and the data will be in the format {k:String, i:Number, d:Object}, some or all values will be passed, depending on the function called. (d==data, or length. k==key. i==index)
  • Entire data object
    • setPodData(data:Object) – This stores (overwrites) the entire plugin data object
    • getPodData() – This requests the entire plugin data from the server, the data will be passed to the function: gotPodData(data_in:String). (NOTE: data_in is JSON encoded, make sure to decode first)
  • Storing separate data objects
    • setPodItem(key:String, data:Number, sync:Bool) – Store a named data item on the server
    • getPodItem(key:String, callback:Function) – Store a named data item on the server
    • delPodItem(key:String, sync:Bool) – Delete a named data item on the server
  • Storing arrays, one element at a time
    • createPodArray(key:String) – initalize a new named array
    • getPodArrayLength(key:String, callback:Function) – get the length of an array
    • setPodElement(key:String, index:Number, data:Number, sync:Bool) – set an item in a named array
    • pushPodElement(key:String, data:Number, sync:Bool) – append an item to a named array
    • splicePodElement(key:String, index:Number, length:Number, sync:Bool) – delete one or more elements from a named array
    • getPodElement(key:String, index:Number, callback:Function) – return an item in a named array
  • NOTE: When using setPodElement along with getPodData, you must call decode() on the array elements. This doesn't apply if you only use getPodElement and not getPodData. For example:
createPodArray('myArray'); // create an array
setPodElement('myArray', 3, {name:"Bob", age:99}); // store random data in element 3 of the array
...
getPodData(); // request entire datastructure from server
...
function gotPodData(data_in:String) { // this function recieves data object
   var data:Object = JSON.decodeSafe(data_in);
   var myArray:Array = data.myArray; // retrieve the array
   var item:Object = decode(myArray[3]); // we must decode each element in the array before using it.
   trace("Name is "+item.name+" and age is "+item.age); // trace out the values
}

Layout / Sizing

  • You need to write two functions, 'setSize(w, h)' should resize all your content to fill the given area. 'getSize()' should return the current size of your content
  • NOTE: These functions are REQUIRED. Without them, your plugin will sort of work, but there will be problems in vyew 2.0 with moving & sizing it.
  • Functions:
    • removeMe() – Calling this will make the plugin remove itself from the page.
    • beginTransform() – Calls up the transform rectangle, for moving & sizing
    • applyTransform(dx:Number, dy:Number, w:Number, h:Number) – moves & resizes the plugin. DX & DY are relitve, not absolute, position differences. W & H set the width and height of your plugin.
  • Disabling the plugin skin:
    • Add the property “var hideSkin:Boolean = true” to your plugin.
    • If you do this, you should provide the user some way of moving your plugin, either via beginTransform() (then vyew will handle it), or you can do it manually via applyTransform(). To see how to implement dragging, see ExampleSubPod. Make sure to note the extra required line in setSize() if you want to implement your own dragging (requres you to set _x and _y to 0)

Function flow.

  • Note: Whenever there is communication to [SERVER], there will be a delay, of an unknown amount.
    • Worst case scenario, could be up to 5 seconds, but average time usually is around 0.5 seconds
  1. [SERVER] → onInit()
    • Server will initially call your onInit function when it is ready
  2. sendPodEvent() → [SERVER] → handlePodEvent()
    • Calling sendPodEvent, will broadcast to all other clients
  3. getPodData() → [SERVER] → gotPodData();
    • Calling getPodData, only returns the data to the client that called it
  4. setPodData() → [SERVER]
    • there is no response to setPodData

Debugging Flash Movies

Different methods:

  1. Read how to use Xray – http://osflash.org/Xray
  2. Just put a textfield on the root of your swf, and write to that

Testing your movie outside of vyew.

Assuming you have copied the function skeleton exactly, including the API functions, then you will be able to do limited testing of your plugin without uploading it. Basically:

  1. setPodData() & getPodData() will work, but will not be persistant across different sessions
  2. calling sendPodEvent() will trigger a handlePodEvent() after about 0.2 seconds (to simulat network delay)
  3. You will need to manuall call onInit() from your constructor. REMEMBER to remove this call when uploading for live testing!



 
api/plugin.api.how-to.txt · Last modified: 2013/07/10 09:14 by simadmin     Back to top