Futurescale, Inc. PureMVC Home

The PureMVC Framework Code at the Speed of Thought


Over 10 years of community discussion and knowledge are maintained here as a read-only archive.

New discussions should be taken up in issues on the appropriate projects at https://github.com/PureMVC

Pages: [1]
Print
Author Topic: Architecting a simple videoplayer in PureMVC and Flex  (Read 12751 times)
dzeikei
Newbie
*
Posts: 3


View Profile Email
« on: October 24, 2008, 04:58:49 »

Hi, I am new to PureMVC and MVC in general and I need help architecting my first PureMVC application.
Basically, my application loads a playlist from an external xml and populates a tilelist with thumbnails of the videos. When you click on a thumbnail it will load the video in the video player and plays it. The urls of thumbnails/flvs are blowfish encrypted in the xml therefore the proxy needs to decryptthem once the xml is loaded. On a side note, is there any point in using blowfish in flex when swf files when can easily decompiled to expose the key?

Should I create:
- a PlaylistProxy which will load the xml using a PlaylistDeligate, create VideoVOs containing the decrypted thumbnail jpg url and flv url, pass it in the notification and let the component load the thumbnail and flv using the urls?
- a PlaylistProxy which will load the xml using a PlaylistDeligate, create VideoVOs which contains the loader for thumbnail and netstream,netconnection for flv file ready for the component/mediator to use?
- a PlaylistProxy which will load the xml using a PlaylistDeligate and load the thumbnail and video data separately using VideoProxy+VideoDeligate and ThumbnailProxy+ThumbnailDeligate?

or is there a better way to do this? I am confused about the extent I should go with MVC. Should deligates only be used for serverside script access? or for any file that is loaded externally?
Logged
Jason MacDonald
Sr. Member
****
Posts: 243


View Profile Email
« Reply #1 on: October 25, 2008, 09:13:28 »

In my opinion, the first option is best. You should let your view handle the actual loading of the media. Have your proxy pass simple VO's (or collection of VO's) that contain the URL through notifications, along with any other data like text/thumbnail urls, and let the view handle it from there.
Logged
dzeikei
Newbie
*
Posts: 3


View Profile Email
« Reply #2 on: October 27, 2008, 01:58:43 »

Thanks for your reply jason!

I have another question. So if only the url is to be passed to the view, is it best practice to create the loader/netconnection/netstream in the MXML component or the mediator?

Thanks in advance :)
Logged
puremvc
Global Moderator
Hero Member
*****
Posts: 2871



View Profile WWW Email
« Reply #3 on: October 27, 2008, 05:28:45 »

Managing i/o with the server is really more the job of a Proxy in PureMVC. Its the job of the Mediator to hook the view component to that data.

-=Cliff>
Logged
Jason MacDonald
Sr. Member
****
Posts: 243


View Profile Email
« Reply #4 on: October 27, 2008, 06:18:40 »

It's funny that you should posted a topic like this as my job involves development of a Media Player(images, swf's, 360's, video and Motion VR's) for use in the travel industry. Our newest version utilizes PMVC, though it's not public yet.

I have another question. So if only the url is to be passed to the view, is it best practice to create the loader/netconnection/netstream in the MXML component or the mediator?

I keep our NetStream and NetConnection in a proxy which passes the connection to the video player Mediator via a Command when needed. As Cliff mentions this is communicating with the server so it's best to have it "managed" by a proxy.

For things like thumbnails I simply pass my VO collection to the view (a thumbnail tile list type component) since my components handle the loading of images internally. This is common in a lot of Flash Components that utilize the Loader class. For instances a thumbnail component  handles the loading of it's image internally, so it has only one input called load(url:String). For things like this, using a proxy depends on how your structure your components. Do they load the media internally? Or do you pass the loaded media (image) into the component for display? The latter works well with a proxy, the former does not. Both are valid ways of doing it imho.
Logged
Gallo_Teo
Newbie
*
Posts: 8


View Profile Email
« Reply #5 on: December 06, 2008, 10:43:47 »

when i used cairngorm i implemented netStreams and NetConnection in delegates in order to call them with a command.

now i tried to make something like a remoteproxy but i really don't know if this is a good solution.
One of the most amazing thing which is troubling my mind is that i wrote a lot of code to write a simple videoPlayer. Another thing which i was thinking about is: Have i to instantiate many netStreams proxies such how many streams i have or is better to notify application about stream event and specify the stream involved ?

i really don't know if this could be a good solution, it works but could it be done better?

:
public class StreamProxy extends Proxy
{
/*CONST */
public static const NAME : String = "streamProxy" ;

/* protected */
protected var streamList : Dictionary  ; 


/*****************************************************************
* PROPERTIES
* **************************************************************/


/*****************************************************************
* CONSTRUCTOR
* **************************************************************/
public function StreamProxy(proxyName:String=null, data:Object=null)
{
super(proxyName, data);
init () ;
}

private function init () : void {

streamList = new Dictionary () ;

}



/*****************************************************************
* FUNCTIONS
* **************************************************************/


/**
*
* getStream
* helper function to mange multiple streams
* */
protected function getStream (nc : NetConnection, streamName : String ) : ExtendedNetStream {

var ns : ExtendedNetStream ;

//-- check if NetStreamAlreadyExists
if (! streamList.hasOwnProperty( streamName )) {

ns = new ExtendedNetStream ( nc ) ;
ns.addEventListener(AsyncErrorEvent.ASYNC_ERROR, onAsyncError ) ;
ns.addEventListener(IOErrorEvent.IO_ERROR, onIOError ) ;
ns.addEventListener(NetStatusEvent.NET_STATUS, onNetStatus ) ;
ns.addEventListener( ExtendedNetStreamEvent.META_DATA, onMetaData ) ;
ns.addEventListener( ExtendedNetStreamEvent.PLAY_STATUS, onPlayStatus ) ;
streamList[ streamName ] = ns ;
}
else
ns = streamList[ streamName ] as ExtendedNetStream ;


return ns

}



/**
*
* @ playStream
* */
public function playStream (nc : NetConnection, streamName : String, seek : Number = 0 ) : ExtendedNetStream {

var ns : ExtendedNetStream = getStream( nc , streamName ) ;

if ( ns.state == PlayerState.PAUSE_STATE ){
ns.resume();
}
else
ns.play( streamName ); 

ns.state = PlayerState.PLAY_STATE

return ns ;
}


/**
*
* @pauseStream
* */
public function pauseStream ( nc :NetConnection, streamName : String )  : ExtendedNetStream {

var ns : ExtendedNetStream = getStream( nc , streamName ) ;
ns.pause();

ns.state = PlayerState.PAUSE_STATE;

return ns ;
}


/**
*
* @stopStream
* */
public function stopStream ( nc :NetConnection, streamName : String ) : ExtendedNetStream {

var ns : ExtendedNetStream = getStream( nc , streamName ) ;
ns.close();

ns.state = PlayerState.STOP_STATE;
return ns ; 

}


/**
*
* @seek
* */
public function seek ( nc :NetConnection, streamName : String , position : Number ) : ExtendedNetStream {


var ns : ExtendedNetStream = getStream( nc , streamName ) ;
ns.seek( position ) ;
return ns ;
}


/**
*
* @ getSeek
* get the current seek position of a
* selected netStream
* */
public function getSeek ( streamName : String) : Number {

var ns :ExtendedNetStream = streamList[ streamName ] as ExtendedNetStream ;
if (! ns )
return -1 ;

return ns.time / ns.duration *100 ;
}


/*****************************************************************
* EVENTS
* **************************************************************/
private function onAsyncError ( e: AsyncErrorEvent ) : void {
facade.sendNotification( MainFacade.NS_ASYNC_ERROR ,e ) ;
}

private function onIOError ( e : IOErrorEvent ) : void {
facade.sendNotification( MainFacade.NS_IO_ERROR, e ) ;
}

private function onNetStatus ( e : NetStatusEvent ) : void {

trace ("[ StreamProxy ]",  e.target, e.info.code );

switch ( e.info.code ){

case "NetStream.Play.Stop" :
// TODO : send to interface state == STOP
break ;
}
}


/**
*
* onMetaData
* */
private function onMetaData ( e : ExtendedNetStreamEvent ) : void {
try {
//-- save in a dynaimc var the
(e.target as ExtendedNetStream ).duration = (e.info as Array)["duration"];
}catch (err : Error){}

}


/**
*
* @ onPlayStatus
* */
private function onPlayStatus ( e : ExtendedNetStreamEvent ): void {

trace (e.info.code) ;


switch (e.info.code) {

case "NetStream.Play.Complete":

(e.target as ExtendedNetStream).close() ;

facade.sendNotification( MainFacade.NOTIFY_PLAY_COMPLETE, e.target as NetStream) ;
break ;
}
}




thanks
Teo
Logged
Pages: [1]
Print