1 // Copyright 2010 Christophe Henry 2 // henry UNDERSCORE christophe AT hotmail DOT com 3 // This is an extended version of the state machine available in the boost::mpl library 4 // Distributed under the same license as the original. 5 // Copyright for the original version: 6 // Copyright 2005 David Abrahams and Aleksey Gurtovoy. Distributed 7 // under the Boost Software License, Version 1.0. (See accompanying 8 // file LICENSE_1_0.txt or copy at 9 // http://www.boost.org/LICENSE_1_0.txt) 10 11 #ifndef PLAYING_MODE_HPP 12 #define PLAYING_MODE_HPP 13 14 #include <iostream> 15 #include <boost/any.hpp> 16 #define FUSION_MAX_VECTOR_SIZE 20 17 18 #include "Events.hpp" 19 #include <boost/msm/back/favor_compile_time.hpp> 20 #include <boost/msm/back/state_machine.hpp> 21 #include <boost/msm/front/state_machine_def.hpp> 22 #include <boost/msm/front/euml/euml.hpp> 23 24 using namespace std; 25 namespace msm = boost::msm; 26 namespace euml = boost::msm::front::euml; 27 28 struct PlayingMode_ : public msm::front::state_machine_def<PlayingMode_> 29 { 30 //flags 31 struct NoFastFwd{}; 32 33 struct Playing : public msm::front::state<default_base_state,msm::front::sm_ptr> 34 { 35 template <class Event,class FSM> on_entryPlayingMode_::Playing36 void on_entry(Event const&,FSM& ) 37 { 38 std::cout << "starting: PlayingMode::Playing" << std::endl; 39 std::cout << "playing song:" << m_fsm->get_current_song() << std::endl; 40 } 41 template <class Event,class FSM> on_exitPlayingMode_::Playing42 void on_exit(Event const&,FSM& ) {std::cout << "finishing: PlayingMode::Playing" << std::endl;} set_sm_ptrPlayingMode_::Playing43 void set_sm_ptr(PlayingMode_* pl) 44 { 45 m_fsm = pl; 46 } 47 private: 48 PlayingMode_* m_fsm; 49 }; 50 struct Paused : public msm::front::state<> 51 { 52 template <class Event,class FSM> on_entryPlayingMode_::Paused53 void on_entry(Event const&,FSM& ) {std::cout << "starting: PlayingMode::Paused" << std::endl;} 54 template <class Event,class FSM> on_exitPlayingMode_::Paused55 void on_exit(Event const&,FSM& ) {std::cout << "finishing: PlayingMode::Paused" << std::endl;} 56 }; 57 struct WaitingForNextPrev : public msm::front::state<> 58 { 59 template <class Event,class FSM> on_entryPlayingMode_::WaitingForNextPrev60 void on_entry(Event const&,FSM& ) {std::cout << "starting: PlayingMode::WaitingForNextPrev" << std::endl;} 61 template <class Event,class FSM> on_exitPlayingMode_::WaitingForNextPrev62 void on_exit(Event const&,FSM& ) {std::cout << "finishing: PlayingMode::WaitingForNextPrev" << std::endl;} 63 }; 64 struct WaitingForEnd : public msm::front::state<> 65 { 66 template <class Event,class FSM> on_entryPlayingMode_::WaitingForEnd67 void on_entry(Event const&,FSM& ) {std::cout << "starting: PlayingMode::WaitingForEnd" << std::endl;} 68 template <class Event,class FSM> on_exitPlayingMode_::WaitingForEnd69 void on_exit(Event const&,FSM& ) {std::cout << "finishing: PlayingMode::WaitingForEnd" << std::endl;} 70 }; 71 struct NoForward : public msm::front::state<> 72 { 73 template <class Event,class FSM> on_entryPlayingMode_::NoForward74 void on_entry(Event const&,FSM& ) {std::cout << "starting: PlayingMode::NoForward" << std::endl;} 75 template <class Event,class FSM> on_exitPlayingMode_::NoForward76 void on_exit(Event const&,FSM& ) {std::cout << "finishing: PlayingMode::NoForward" << std::endl;} 77 }; 78 struct ForwardPressed : public msm::front::state<> 79 { 80 template <class Event,class FSM> on_entryPlayingMode_::ForwardPressed81 void on_entry(Event const&,FSM& ) 82 { 83 std::cout << "starting: PlayingMode::ForwardPressed," << "start timer" << std::endl; 84 } 85 template <class Event,class FSM> on_exitPlayingMode_::ForwardPressed86 void on_exit(Event const&,FSM& ) 87 { 88 std::cout << "finishing: PlayingMode::ForwardPressed," << "stop timer" << std::endl; 89 } 90 }; 91 struct FastForward : public msm::front::state<> 92 { 93 template <class Event,class FSM> on_entryPlayingMode_::FastForward94 void on_entry(Event const&,FSM& ) 95 { 96 std::cout << "starting: PlayingMode::FastForward," << "start timer" << std::endl; 97 } 98 template <class Event,class FSM> on_exitPlayingMode_::FastForward99 void on_exit(Event const&,FSM& ) 100 { 101 std::cout << "finishing: PlayingMode::FastForward," << "stop timer" << std::endl; 102 } 103 }; 104 struct StdDisplay : public msm::front::state<> 105 { 106 template <class Event,class FSM> on_entryPlayingMode_::StdDisplay107 void on_entry(Event const&,FSM& ) {std::cout << "starting: PlayingMode::StdDisplay" << std::endl;} 108 template <class Event,class FSM> on_exitPlayingMode_::StdDisplay109 void on_exit(Event const&,FSM& ) {std::cout << "finishing: PlayingMode::StdDisplay" << std::endl;} 110 }; 111 struct SetPosition : public msm::front::state<> 112 { 113 typedef mpl::vector1<NoFastFwd> flag_list; 114 template <class Event,class FSM> on_entryPlayingMode_::SetPosition115 void on_entry(Event const&,FSM& ) {std::cout << "starting: PlayingMode::SetPosition" << std::endl;} 116 template <class Event,class FSM> on_exitPlayingMode_::SetPosition117 void on_exit(Event const&,FSM& ) {std::cout << "finishing: PlayingMode::SetPosition" << std::endl;} 118 }; 119 struct SetMark : public msm::front::state<> 120 { 121 template <class Event,class FSM> on_entryPlayingMode_::SetMark122 void on_entry(Event const&,FSM& ) {std::cout << "starting: PlayingMode::SetMark" << std::endl;} 123 template <class Event,class FSM> on_exitPlayingMode_::SetMark124 void on_exit(Event const&,FSM& ) {std::cout << "finishing: PlayingMode::SetMark" << std::endl;} 125 }; 126 struct PlayingExit : public msm::front::exit_pseudo_state<EndPlay> 127 { 128 template <class Event,class FSM> on_entryPlayingMode_::PlayingExit129 void on_entry(Event const&,FSM& ) {std::cout << "starting: PlayingMode::PlayingExit" << std::endl;} 130 template <class Event,class FSM> on_exitPlayingMode_::PlayingExit131 void on_exit(Event const&,FSM& ) {std::cout << "finishing: PlayingMode::PlayingExit" << std::endl;} 132 }; 133 // transition action methods 134 struct inc_song_counter : euml::euml_action<inc_song_counter> 135 { 136 template <class FSM,class EVT,class SourceState,class TargetState> operator ()PlayingMode_::inc_song_counter137 void operator()(EVT const& ,FSM& fsm,SourceState& ,TargetState& ) 138 { 139 if (++fsm.m_SongIndex <= fsm.m_NumberOfSongs ) 140 { 141 std::cout << "playing song:" << fsm.m_SongIndex << std::endl; 142 } 143 else 144 { 145 // last song => end playing, next play will start at the beginning 146 fsm.m_SongIndex = 1; 147 fsm.process_event(EndPlay()); 148 } 149 } 150 }; 151 select_songPlayingMode_152 void select_song(StartSong const& evt) 153 { 154 if ((evt.m_Selected>0) && (evt.m_Selected<=m_NumberOfSongs)) 155 { 156 m_SongIndex = evt.m_Selected; 157 std::cout << "selecting song:" << m_SongIndex << std::endl; 158 } 159 else 160 { 161 // play current song 162 std::cout << "selecting song:" << m_SongIndex << std::endl; 163 } 164 } 165 struct dec_song_counter : euml::euml_action<dec_song_counter> 166 { 167 template <class FSM,class EVT,class SourceState,class TargetState> operator ()PlayingMode_::dec_song_counter168 void operator()(EVT const& ,FSM& fsm,SourceState& ,TargetState& ) 169 { 170 if (--fsm.m_SongIndex >0 ) 171 { 172 std::cout << "playing song:" << fsm.m_SongIndex << std::endl; 173 } 174 else 175 { 176 // before first song => end playing 177 fsm.m_SongIndex = 1; 178 fsm.process_event(EndPlay()); 179 } 180 } 181 }; 182 struct send_NextSong : euml::euml_action<send_NextSong> 183 { 184 template <class FSM,class EVT,class SourceState,class TargetState> operator ()PlayingMode_::send_NextSong185 void operator()(EVT const& ,FSM& fsm,SourceState& ,TargetState& ) 186 { 187 fsm.process_event(NextSong()); 188 } 189 }; 190 do_fast_forwardPlayingMode_191 void do_fast_forward(ForwardTimer const&) 192 { 193 std::cout << "moving song forward..." << std::endl; 194 } 195 196 // transition guard methods 197 struct fast_fwd_ok : euml::euml_action<fast_fwd_ok> 198 { 199 template <class FSM,class EVT,class SourceState,class TargetState> operator ()PlayingMode_::fast_fwd_ok200 bool operator()(EVT const& ,FSM& fsm,SourceState& ,TargetState& ) 201 { 202 // guard accepts only if fast forward is possible (No SetPosition mode) 203 return !fsm.is_flag_active<NoFastFwd>(); 204 } 205 }; 206 // initial states / orthogonal zones 207 typedef mpl::vector5<Playing,WaitingForNextPrev,WaitingForEnd,NoForward,StdDisplay> 208 initial_state; 209 typedef PlayingMode_ fsm; // makes transition table cleaner 210 // Transition table for player 211 struct transition_table : mpl::vector19< 212 // Start Event Next Action Guard 213 // +--------------------+---------------------+--------------------+--------------------------+----------------------+ 214 _row < Playing , PlayPause , Paused >, 215 _row < Playing , Off , Paused >, 216 a_row < Playing , StartSong , Playing , &fsm::select_song >, 217 _row < Paused , PlayPause , Playing >, 218 msm::front::Row < Playing , SongFinished , Playing , inc_song_counter , msm::front::none >, 219 a_row < Paused , StartSong , Playing , &fsm::select_song >, 220 // +--------------------+---------------------+--------------------+--------------------------+----------------------+ 221 msm::front::Row < WaitingForNextPrev , PreviousSong , WaitingForNextPrev , dec_song_counter , msm::front::none >, 222 msm::front::Row < WaitingForNextPrev , NextSong , WaitingForNextPrev , inc_song_counter , msm::front::none >, 223 // +--------------------+---------------------+--------------------+--------------------------+----------------------+ 224 _row < WaitingForEnd , EndPlay , PlayingExit >, 225 // +--------------------+---------------------+--------------------+--------------------------+----------------------+ 226 msm::front::Row < NoForward , EastPressed , ForwardPressed , msm::front::none , fast_fwd_ok >, 227 msm::front::Row < ForwardPressed , EastReleased , NoForward , send_NextSong , msm::front::none >, 228 a_row < ForwardPressed , ForwardTimer , FastForward , &fsm::do_fast_forward >, 229 a_row < FastForward , ForwardTimer , FastForward , &fsm::do_fast_forward >, 230 _row < FastForward , EastReleased , NoForward >, 231 // +--------------------+---------------------+---------------------+--------------------------+----------------------+ 232 _row < StdDisplay , PlayingMiddleButton , SetPosition >, 233 _row < SetPosition , StartSong , StdDisplay >, 234 _row < SetPosition , PlayingMiddleButton , SetMark >, 235 _row < SetMark , PlayingMiddleButton , StdDisplay >, 236 _row < SetMark , StartSong , StdDisplay > 237 // +--------------------+---------------------+---------------------+--------------------------+----------------------+ 238 > {}; PlayingMode_PlayingMode_239 PlayingMode_(): 240 m_SongIndex(1), 241 // for simplicity we decide there are 5 songs 242 m_NumberOfSongs(5){} 243 get_current_songPlayingMode_244 int get_current_song(){return m_SongIndex;} 245 int m_SongIndex; 246 int m_NumberOfSongs; 247 248 }; 249 typedef msm::back::state_machine<PlayingMode_> PlayingMode; 250 251 #endif // PLAYING_MODE_HPP 252