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: FInal State Machine..need feedback on FSM definition for videoplayer  (Read 7952 times)
eco_bach
Courseware Beta
Sr. Member
***
Posts: 81


View Profile Email
« on: September 06, 2009, 07:42:32 »

This is what I have so far, unless I'm mistaken I don't see the need for any entering or exiting guards.
Can anyone suggest whether I'm on the right track?

//CODE START
<fsm initial={Main.STATE_READY}>
            <state name={Main.STATE_READY}  >
                <transition action={Main.ACTION_START} target={Main.STATE_PLAYING}/>
            </state>
            <state name={Main.STATE_PLAYING} >
                <transition action={Main.ACTION_PAUSE} target={Main.STATE_PAUSED}/>
                <transition action={Main.ACTION_STOP}  target={Main.STATE_STOPPED}/>
            </state>
            <state name={Main.STATE_PAUSED} >
                <transition action={Main.ACTION_RESUME} target={Main.STATE_PLAYING}/>
            </state>
            <state name={Main.STATE_STOPPED}>
                <transition action={Main.ACTION_RESET} target={Main.STATE_READY}/>
            </state>
         </fsm>;

//CODE END


and then in my ApplicationFacade

//CODE START
override protected function initializeController () : void
      {
         super.initializeController();
         registerCommand( STARTUP,       StartupCommand );   
registerCommand( Main.ACTION_RESET,       ReadyCommand );
registerCommand( Main.ACTION_START,       PlayCommand );
registerCommand(  Main.ACTION_STOP,       StopCommand );
registerCommand(  Main.ACTION_PAUSE,       PauseCommand );
registerCommand(  Main.ACTION_RESUME,       PlayCommand );
}
//CODE END
« Last Edit: September 06, 2009, 08:01:12 by eco_bach » Logged
mariusht
Full Member
***
Posts: 26


View Profile Email
« Reply #1 on: September 07, 2009, 06:33:19 »

I dont think you are on the right track.

You send StateMachine.ACTION notification from application(command or mediator) to StateMachine which triggers a transition. No need to register commands with StateMachine.ACTION notification. You should add 'changed' property to each state.

<fsm initial={Main.STATE_READY}>
            <state name={Main.STATE_READY}  changed={Main.READY}>
                <transition action={Main.ACTION_START} target={Main.STATE_PLAYING}/>
            </state>
            <state name={Main.STATE_PLAYING} changed={Main.PLAY}>
                <transition action={Main.ACTION_PAUSE} target={Main.STATE_PAUSED}/>
                <transition action={Main.ACTION_STOP}  target={Main.STATE_STOPPED}/>
            </state>
            <state name={Main.STATE_PAUSED} changed={Main.PAUSE}>
                <transition action={Main.ACTION_RESUME} target={Main.STATE_PLAYING}/>
            </state>
            <state name={Main.STATE_STOPPED} changed={Main.STOP}>
                <transition action={Main.ACTION_RESET} target={Main.STATE_READY}/>
            </state>
         </fsm>;

Now your StateMachine sends notification(READY, PLAY, PAUSE, STOP) every time state is changed. If you need, you can register commands with these notifications or simply make mediator(s) to listen for them.

override protected function initializeController () : void
      {
         super.initializeController();
         registerCommand( STARTUP,       StartupCommand );   
registerCommand( Main.READY,       ReadyCommand );
registerCommand( Main.PLAY,       PlayCommand );
registerCommand(  Main.STOP,       StopCommand );
registerCommand(  Main.PAUSE,       PauseCommand );
}

Look at the SOAMusicPlayer source code http://seaofarrows.com/srcview/

Mariush T.
http://mariusht.com/blog
Logged
eco_bach
Courseware Beta
Sr. Member
***
Posts: 81


View Profile Email
« Reply #2 on: September 08, 2009, 04:12:07 »

Thanks I'll try that. I was referencing the Stopwatch demo that doesn't use Changed Notification name constants.
I was under the impression that StateMachine.CHANGED notifications were always sent, and you weren't required to explicitly include them in your definition.

And that mapping the StateMachine.ACTION  actions to commands was a best practice when making changes to your proxy.

Examining the definition in the SOA example I can see how important naming your constants becomes, though 'STOPPED' or 'STATE_STOPPED' seem a lot more intuitive as state names than 'STOPPING', and using NO suffix makes more sense in describing ACTION. To simplify even further, I would drop the 'ING' suffix altogether and simply use the 'ED' suffix for both state names and CHANGED constants, or use 'ING' for both names and CHANGED constants when it makes sense, ie PLAYING. In any case, you are simplifying constant use, repurposing one and using 2 instead of 3.

Statemachine Definition Constants

ACTION (should end in 'ED' ie STARTED)- notifications sent TO StateMachine
CHANGED (should have no suffix ie START)- notifications sent FROM StateMachine
NAME (should end in 'ING' ie STARTING) - actual state names used internally by StateMachine

my revised suggested naming scheme

ACTION (should have no suffix ie START)- notifications sent TO StateMachine
CHANGED (should end in either 'ED' ie STARTED or 'ING' ie STARTING )- notifications sent FROM StateMachine
NAME (should end in either 'ED' ie STARTED or 'ING' ie STARTING) - actual state names used internally by StateMachine


So my suggested much simplified definition becomes the following. The only departure from my suggested scheme is that I am using a RESET action to get to a 'READY' state , and I can probably further simplify by eliminating 'RESUME' and simply use 'PLAY' instead. I've also eliminated a 'STOPPED' state, since it was essentially the same as a 'PAUSED' state.

//CODE START
<fsm initial={Main.READY} >
            <state name={Main.READY} changed={Main.READY}>
                <transition action={Main.PLAY} target={Main.PLAYING}/>
            </state>
            <state name={Main.PLAYING} changed={Main.PLAYING}>
                <transition action={Main.PAUSE} target={Main.PAUSED}/>
                <transition action={Main.RESET} target={Main.READY}/>
            </state>
            <state name={Main.PAUSED} changed={Main.PAUSED} >
                <transition action={Main.RESUME} target={Main.PLAYING}/>
                              <transition action={Main.RESET} target={Main.READY}/>
            </state>
            
         </fsm>;
//CODE END
« Last Edit: September 08, 2009, 05:40:44 by eco_bach » Logged
Jason MacDonald
Sr. Member
****
Posts: 243


View Profile Email
« Reply #3 on: September 08, 2009, 06:56:20 »

Just for reference sake, here is the FSM definition I use for my video player.

:
// Create the FSM definition
            var fsm:XML =
                <fsm initial={MediaPlayerConstants.STARTING}>
                   
                    <!-- STARTUP THE MEDIA PLAYER -->
                    <state name={MediaPlayerConstants.STARTING}>
                        <transition action={MediaPlayerConstants.MEDIA_LOAD} target={MediaPlayerConstants.MEDIA_LOADING}/>
                        <transition action={MediaPlayerConstants.STARTUP_FAILED} target={MediaPlayerConstants.FAILING}/>
                    </state>
                   
                    <!-- Media Loading -->
                    <state name={MediaPlayerConstants.MEDIA_LOADING} changed={MediaPlayerConstants.LOAD}>
                        <transition action={MediaPlayerConstants.MEDIA_PLAY} target={MediaPlayerConstants.MEDIA_PLAYING}/>
                        <transition action={MediaPlayerConstants.MEDIA_STOP} target={MediaPlayerConstants.MEDIA_STOPPING}/>
                        <transition action={MediaPlayerConstants.MEDIA_PAUSE} target={MediaPlayerConstants.MEDIA_PAUSING}/>
                        <transition action={MediaPlayerConstants.MEDIA_LOAD} target={MediaPlayerConstants.MEDIA_LOADING}/>
                        <transition action={MediaPlayerConstants.MEDIA_LOADING_FAILED} target={MediaPlayerConstants.FAILING}/>
                    </state>
                   
                   
                    <!-- Media Playing -->
                    <state name={MediaPlayerConstants.MEDIA_PLAYING} changed={MediaPlayerConstants.PLAY}>
                        <transition action={MediaPlayerConstants.MEDIA_PAUSE} target={MediaPlayerConstants.MEDIA_PAUSING}/>
                        <transition action={MediaPlayerConstants.MEDIA_STOP} target={MediaPlayerConstants.MEDIA_STOPPING}/>
                        <transition action={MediaPlayerConstants.MEDIA_MENU} target={MediaPlayerConstants.MEDIA_MENU_SHOWING}/>
                        <transition action={MediaPlayerConstants.MEDIA_END} target={MediaPlayerConstants.MEDIA_STOPPING}/>
                        <transition action={MediaPlayerConstants.MEDIA_LOAD} target={MediaPlayerConstants.MEDIA_LOADING}/>
                        <transition action={MediaPlayerConstants.MEDIA_PLAY_FAILED} target={MediaPlayerConstants.FAILING}/>
                    </state>
                   
                    <!-- Media Pausing -->
                    <state name={MediaPlayerConstants.MEDIA_PAUSING} changed={MediaPlayerConstants.PAUSED}>
                        <transition action={MediaPlayerConstants.MEDIA_PLAY} target={MediaPlayerConstants.MEDIA_PLAYING}/>
                        <transition action={MediaPlayerConstants.MEDIA_STOP} target={MediaPlayerConstants.MEDIA_STOPPING}/>
                        <transition action={MediaPlayerConstants.MEDIA_MENU} target={MediaPlayerConstants.MEDIA_MENU_SHOWING}/>
                        <transition action={MediaPlayerConstants.MEDIA_LOAD} target={MediaPlayerConstants.MEDIA_LOADING}/>
                        <transition action={MediaPlayerConstants.MEDIA_PAUSE_FAILED} target={MediaPlayerConstants.FAILING}/>
                    </state>
                   
                    <!-- Media Stop -->
                    <state name={MediaPlayerConstants.MEDIA_STOPPING} changed={MediaPlayerConstants.STOPPED}>
                        <transition action={MediaPlayerConstants.MEDIA_PLAY} target={MediaPlayerConstants.MEDIA_PLAYING}/>
                        <transition action={MediaPlayerConstants.MEDIA_PAUSE} target={MediaPlayerConstants.MEDIA_PAUSING}/>
                        <transition action={MediaPlayerConstants.MEDIA_LOAD} target={MediaPlayerConstants.MEDIA_LOADING}/>
                        <transition action={MediaPlayerConstants.MEDIA_MENU} target={MediaPlayerConstants.MEDIA_MENU_SHOWING}/>
                        <transition action={MediaPlayerConstants.MEDIA_STOP_FAILED} target={MediaPlayerConstants.FAILING}/>
                    </state>
                   
                    <!-- Media Menu -->
                    <state name={MediaPlayerConstants.MEDIA_MENU_SHOWING} changed={MediaPlayerConstants.MENU}>
                        <transition action={MediaPlayerConstants.MEDIA_PLAY} target={MediaPlayerConstants.MEDIA_PLAYING}/>
                        <transition action={MediaPlayerConstants.MEDIA_STOP} target={MediaPlayerConstants.MEDIA_STOPPING}/>
                        <transition action={MediaPlayerConstants.MEDIA_PAUSE} target={MediaPlayerConstants.MEDIA_PAUSING}/>
                        <transition action={MediaPlayerConstants.MEDIA_LOAD} target={MediaPlayerConstants.MEDIA_LOADING}/>
                        <transition action={MediaPlayerConstants.MEDIA_MENU_FAILED} target={MediaPlayerConstants.FAILING}/>
                    </state>
                   
                    <!-- REPORT FAILURE FROM ANY STATE -->
                    <state name={MediaPlayerConstants.FAILING} changed={MediaPlayerConstants.FAIL}/>
                </fsm>;
« Last Edit: September 08, 2009, 06:59:15 by Jason MacDonald » Logged
Pages: [1]
Print