123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271 |
- // Copyright 2010 Christophe Henry
- // henry UNDERSCORE christophe AT hotmail DOT com
- // This is an extended version of the state machine available in the boost::mpl library
- // Distributed under the same license as the original.
- // Copyright for the original version:
- // Copyright 2005 David Abrahams and Aleksey Gurtovoy. Distributed
- // under the Boost Software License, Version 1.0. (See accompanying
- // file LICENSE_1_0.txt or copy at
- // http://www.boost.org/LICENSE_1_0.txt)
- #include <vector>
- #include <set>
- #include <string>
- #include <iostream>
- // we need more than the default 20 states
- #define FUSION_MAX_VECTOR_SIZE 20
- // we need more than the default 20 transitions
- #include "boost/mpl/vector/vector50.hpp"
- #include <boost/msm/back/state_machine.hpp>
- #include <boost/msm/front/euml/euml.hpp>
- using namespace std;
- using namespace boost::msm::front::euml;
- namespace msm = boost::msm;
- // attribute names and types
- BOOST_MSM_EUML_DECLARE_ATTRIBUTE(int,m_Selected)
- BOOST_MSM_EUML_DECLARE_ATTRIBUTE(int,m_SongIndex)
- BOOST_MSM_EUML_DECLARE_ATTRIBUTE(int,m_NumberOfSongs)
- #include "ipod_functors.hpp"
- namespace // Concrete FSM implementation
- {
- //flags
- BOOST_MSM_EUML_FLAG(MenuActive)
- BOOST_MSM_EUML_FLAG(NoFastFwd)
- // hardware-generated events
- BOOST_MSM_EUML_EVENT(Hold)
- BOOST_MSM_EUML_EVENT(NoHold)
- BOOST_MSM_EUML_EVENT(SouthPressed)
- BOOST_MSM_EUML_EVENT(SouthReleased)
- BOOST_MSM_EUML_EVENT(MiddleButton)
- BOOST_MSM_EUML_EVENT(EastPressed)
- BOOST_MSM_EUML_EVENT(EastReleased)
- BOOST_MSM_EUML_EVENT(Off)
- BOOST_MSM_EUML_EVENT(MenuButton)
- // internally defined events
- BOOST_MSM_EUML_EVENT(PlayPause)
- BOOST_MSM_EUML_EVENT(EndPlay)
- struct CloseMenu_impl : euml_event<CloseMenu_impl>
- {
- CloseMenu_impl(){}//defined only for stt
- template<class EVENT>
- CloseMenu_impl(EVENT const &) {}
- };
- CloseMenu_impl const CloseMenu;
- BOOST_MSM_EUML_EVENT(OnOffTimer)
- BOOST_MSM_EUML_EVENT(MenuMiddleButton)
- BOOST_MSM_EUML_EVENT(SelectSong)
- BOOST_MSM_EUML_EVENT(SongFinished)
- BOOST_MSM_EUML_ATTRIBUTES((attributes_ << m_Selected ), StartSongAttributes)
- BOOST_MSM_EUML_EVENT_WITH_ATTRIBUTES(StartSong,StartSongAttributes)
- BOOST_MSM_EUML_EVENT(PreviousSong)
- BOOST_MSM_EUML_EVENT(NextSong)
- BOOST_MSM_EUML_EVENT(ForwardTimer)
- BOOST_MSM_EUML_EVENT(PlayingMiddleButton)
- // Concrete iPod implementation
- // The list of iPod states
- BOOST_MSM_EUML_STATE(( NotHolding_Entry ),NotHolding)
- BOOST_MSM_EUML_INTERRUPT_STATE(( NoHold,Holding_Entry ),Holding)
- BOOST_MSM_EUML_STATE(( NotPlaying_Entry ),NotPlaying)
- BOOST_MSM_EUML_STATE(( NoMenuMode_Entry ),NoMenuMode)
- BOOST_MSM_EUML_STATE(( NoOnOffButton_Entry ),NoOnOffButton)
- BOOST_MSM_EUML_STATE(( OffDown_Entry ),OffDown)
- BOOST_MSM_EUML_STATE(( PlayerOff_Entry ),PlayerOff)
- BOOST_MSM_EUML_STATE(( CheckMiddleButton_Entry ),CheckMiddleButton)
- // Concrete PlayingMode_ implementation
- // The list of PlayingMode_ states
- BOOST_MSM_EUML_STATE(( Playing_Entry ),Playing)
- BOOST_MSM_EUML_STATE(( WaitingForNextPrev_Entry ),WaitingForNextPrev)
- BOOST_MSM_EUML_STATE(( Paused_Entry ),Paused)
- BOOST_MSM_EUML_STATE(( WaitingForEnd_Entry ),WaitingForEnd)
- BOOST_MSM_EUML_STATE(( NoForward_Entry ),NoForward)
- BOOST_MSM_EUML_STATE(( ForwardPressed_Entry,ForwardPressed_Exit ),ForwardPressed)
- BOOST_MSM_EUML_STATE(( FastForward_Entry,FastForward_Exit ),FastForward)
- BOOST_MSM_EUML_STATE(( StdDisplay_Entry ),StdDisplay)
- BOOST_MSM_EUML_STATE(( SetPosition_Entry ),SetPosition)
- BOOST_MSM_EUML_STATE(( SetMark_Entry ),SetMark)
- BOOST_MSM_EUML_EXIT_STATE(( EndPlay,PlayingExit_Entry ),PlayingExit)
- //stt
- BOOST_MSM_EUML_TRANSITION_TABLE((
- // +------------------------------------------------------------------------------+
- Paused == Playing + PlayPause ,
- Paused == Playing + Off ,
- Playing == Playing + StartSong
- / (if_then_(event_(m_Selected) > Int_<0>() &&
- event_(m_Selected) < fsm_(m_NumberOfSongs),
- fsm_(m_SongIndex) = event_(m_Selected) ),show_selected_song) ,
- Playing == Playing + SongFinished
- / (if_then_else_(++fsm_(m_SongIndex) <= fsm_(m_NumberOfSongs), /*if*/
- show_playing_song, /*then*/
- (fsm_(m_SongIndex)=Int_<1>(),process_(EndPlay))/*else*/ ) ) ,
- Playing == Paused + PlayPause ,
- Playing == Paused + StartSong
- / (if_then_(event_(m_Selected) > Int_<0>() &&
- event_(m_Selected) < fsm_(m_NumberOfSongs),
- fsm_(m_SongIndex) = event_(m_Selected) ),show_selected_song) ,
- WaitingForNextPrev == WaitingForNextPrev+ PreviousSong
- /( if_then_else_(--fsm_(m_SongIndex) > Int_<0>(), /*if*/
- show_playing_song, /*then*/
- (fsm_(m_SongIndex)=Int_<1>(),process_(EndPlay)) /*else*/ ) ) ,
- WaitingForNextPrev == WaitingForNextPrev+ NextSong
- / (if_then_else_(++fsm_(m_SongIndex) <= fsm_(m_NumberOfSongs), /*if*/
- show_playing_song, /*then*/
- (fsm_(m_SongIndex)=Int_<1>(),process_(EndPlay)) /*else*/ ) ),
- PlayingExit == WaitingForEnd + EndPlay ,
- ForwardPressed == NoForward + EastPressed [!is_flag_(NoFastFwd)] ,
- NoForward == ForwardPressed + EastReleased / process_(NextSong) ,
- FastForward == ForwardPressed + ForwardTimer / do_fast_forward ,
- FastForward == FastForward + ForwardTimer / do_fast_forward ,
- FastForward == NoForward + EastReleased ,
- SetPosition == StdDisplay + PlayingMiddleButton ,
- StdDisplay == SetPosition + StartSong ,
- SetMark == SetPosition + PlayingMiddleButton ,
- StdDisplay == SetMark + PlayingMiddleButton ,
- StdDisplay == SetMark + StartSong
- // +------------------------------------------------------------------------------+
- ),playingmode_transition_table )
- BOOST_MSM_EUML_DECLARE_STATE_MACHINE( (playingmode_transition_table, //STT
- init_ << Playing << WaitingForNextPrev << WaitingForEnd
- << NoForward << StdDisplay, // Init States
- fsm_(m_NumberOfSongs)=Int_<5>(), // entry
- no_action, // exit
- attributes_ << m_SongIndex << m_NumberOfSongs, //attributes
- configure_<< NoFastFwd // Flags, Deferred events, configuration
- ),PlayingMode_)
- // choice of back-end
- typedef msm::back::state_machine<PlayingMode_> PlayingMode_type;
- PlayingMode_type const PlayingMode;
- // Concrete MenuMode_ implementation
- // The list of MenuMode_ states
- BOOST_MSM_EUML_STATE(( WaitingForSongChoice_Entry ),WaitingForSongChoice)
- BOOST_MSM_EUML_STATE(( StartCurrentSong_Entry ),StartCurrentSong)
- BOOST_MSM_EUML_EXIT_STATE(( CloseMenu,MenuExit_Entry ),MenuExit)
- //stt
- BOOST_MSM_EUML_TRANSITION_TABLE((
- // +------------------------------------------------------------------------------+
- StartCurrentSong == WaitingForSongChoice + MenuMiddleButton ,
- MenuExit == StartCurrentSong + SelectSong
- // +------------------------------------------------------------------------------+
- ),menumode_transition_table )
- BOOST_MSM_EUML_DECLARE_STATE_MACHINE( (menumode_transition_table, //STT
- init_ << WaitingForSongChoice, // Init States
- no_action, // entry
- no_action, // exit
- attributes_ << no_attributes_, //attributes
- configure_<< MenuActive // Flags, Deferred events, configuration
- ),MenuMode_)
- typedef msm::back::state_machine<MenuMode_> MenuMode_type;
- MenuMode_type const MenuMode;
- // iPod stt
- BOOST_MSM_EUML_TRANSITION_TABLE((
- // +------------------------------------------------------------------------------+
- Holding == NotHolding + Hold ,
- NotHolding == Holding + NoHold ,
- PlayingMode == NotPlaying + PlayPause ,
- NotPlaying == exit_pt_(PlayingMode,PlayingExit) + EndPlay
- / process_(MenuButton) ,
- MenuMode == NoMenuMode + MenuButton ,
- NoMenuMode == exit_pt_(MenuMode,MenuExit)+ CloseMenu
- / process2_(StartSong,Int_<5>()) ,
- OffDown == NoOnOffButton + SouthPressed ,
- NoOnOffButton == OffDown + SouthReleased
- / process_(PlayPause) ,
- PlayerOff == OffDown + OnOffTimer
- / (show_player_off,process_(Off)) ,
- NoOnOffButton == PlayerOff + SouthPressed / show_player_on ,
- NoOnOffButton == PlayerOff + NoHold / show_player_on ,
- CheckMiddleButton == CheckMiddleButton + MiddleButton
- [is_flag_(MenuActive)] / process_(PlayingMiddleButton) ,
- CheckMiddleButton == CheckMiddleButton + MiddleButton
- [!is_flag_(MenuActive)] / process_(PlayingMiddleButton)
- // +------------------------------------------------------------------------------+
- ),ipod_transition_table )
- BOOST_MSM_EUML_DECLARE_STATE_MACHINE(( ipod_transition_table, //STT
- init_ << NotHolding << NotPlaying << NoMenuMode
- << NoOnOffButton << CheckMiddleButton
- ),
- iPod_) //fsm name
- typedef msm::back::state_machine<iPod_> iPod;
-
- void test()
- {
- iPod sm;
- sm.start();
- // we first press Hold
- std::cout << "pressing hold" << std::endl;
- sm.process_event(Hold);
- // pressing a button is now ignored
- std::cout << "pressing a button" << std::endl;
- sm.process_event(SouthPressed);
- // or even one contained in a submachine
- sm.process_event(EastPressed);
- // no more holding
- std::cout << "no more holding, end interrupt event sent" << std::endl;
- sm.process_event(NoHold);
- std::cout << "pressing South button a short time" << std::endl;
- sm.process_event(SouthPressed);
- // we suppose a short pressing leading to playing a song
- sm.process_event(SouthReleased);
- // we move to the next song
- std::cout << "we move to the next song" << std::endl;
- sm.process_event(NextSong);
- // then back to no song => exit from playing, menu active
- std::cout << "we press twice the West button (simulated)=> end of playing" << std::endl;
- sm.process_event(PreviousSong);
- sm.process_event(PreviousSong);
- // even in menu mode, pressing play will start playing the first song
- std::cout << "pressing play/pause" << std::endl;
- sm.process_event(SouthPressed);
- sm.process_event(SouthReleased);
- // of course pausing must be possible
- std::cout << "pressing play/pause" << std::endl;
- sm.process_event(SouthPressed);
- sm.process_event(SouthReleased);
- std::cout << "pressing play/pause" << std::endl;
- sm.process_event(SouthPressed);
- sm.process_event(SouthReleased);
- // while playing, you can fast forward
- std::cout << "pressing East button a long time" << std::endl;
- sm.process_event(EastPressed);
- // let's suppose the timer just fired
- sm.process_event(ForwardTimer);
- sm.process_event(ForwardTimer);
- // end of fast forwarding
- std::cout << "releasing East button" << std::endl;
- sm.process_event(EastReleased);
- // we now press the middle button to set playing at a given position
- std::cout << "pressing Middle button, fast forwarding disabled" << std::endl;
- sm.process_event(MiddleButton);
- std::cout <<"pressing East button to fast forward" << std::endl;
- sm.process_event(EastPressed);
- // we switch off and on
- std::cout <<"switch off player" << std::endl;
- sm.process_event(SouthPressed);
- sm.process_event(OnOffTimer);
- std::cout <<"switch on player" << std::endl;
- sm.process_event(SouthPressed);
- }
- }
- int main()
- {
- test();
- return 0;
- }
|