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)
11 #ifndef PLAYING_MODE_HPP
12 #define PLAYING_MODE_HPP
15 #include <boost/any.hpp>
16 #define FUSION_MAX_VECTOR_SIZE 20
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>
25 namespace msm = boost::msm;
26 namespace euml = boost::msm::front::euml;
28 struct PlayingMode_ : public msm::front::state_machine_def<PlayingMode_>
33 struct Playing : public msm::front::state<default_base_state,msm::front::sm_ptr>
35 template <class Event,class FSM>
36 void on_entry(Event const&,FSM& )
38 std::cout << "starting: PlayingMode::Playing" << std::endl;
39 std::cout << "playing song:" << m_fsm->get_current_song() << std::endl;
41 template <class Event,class FSM>
42 void on_exit(Event const&,FSM& ) {std::cout << "finishing: PlayingMode::Playing" << std::endl;}
43 void set_sm_ptr(PlayingMode_* pl)
50 struct Paused : public msm::front::state<>
52 template <class Event,class FSM>
53 void on_entry(Event const&,FSM& ) {std::cout << "starting: PlayingMode::Paused" << std::endl;}
54 template <class Event,class FSM>
55 void on_exit(Event const&,FSM& ) {std::cout << "finishing: PlayingMode::Paused" << std::endl;}
57 struct WaitingForNextPrev : public msm::front::state<>
59 template <class Event,class FSM>
60 void on_entry(Event const&,FSM& ) {std::cout << "starting: PlayingMode::WaitingForNextPrev" << std::endl;}
61 template <class Event,class FSM>
62 void on_exit(Event const&,FSM& ) {std::cout << "finishing: PlayingMode::WaitingForNextPrev" << std::endl;}
64 struct WaitingForEnd : public msm::front::state<>
66 template <class Event,class FSM>
67 void on_entry(Event const&,FSM& ) {std::cout << "starting: PlayingMode::WaitingForEnd" << std::endl;}
68 template <class Event,class FSM>
69 void on_exit(Event const&,FSM& ) {std::cout << "finishing: PlayingMode::WaitingForEnd" << std::endl;}
71 struct NoForward : public msm::front::state<>
73 template <class Event,class FSM>
74 void on_entry(Event const&,FSM& ) {std::cout << "starting: PlayingMode::NoForward" << std::endl;}
75 template <class Event,class FSM>
76 void on_exit(Event const&,FSM& ) {std::cout << "finishing: PlayingMode::NoForward" << std::endl;}
78 struct ForwardPressed : public msm::front::state<>
80 template <class Event,class FSM>
81 void on_entry(Event const&,FSM& )
83 std::cout << "starting: PlayingMode::ForwardPressed," << "start timer" << std::endl;
85 template <class Event,class FSM>
86 void on_exit(Event const&,FSM& )
88 std::cout << "finishing: PlayingMode::ForwardPressed," << "stop timer" << std::endl;
91 struct FastForward : public msm::front::state<>
93 template <class Event,class FSM>
94 void on_entry(Event const&,FSM& )
96 std::cout << "starting: PlayingMode::FastForward," << "start timer" << std::endl;
98 template <class Event,class FSM>
99 void on_exit(Event const&,FSM& )
101 std::cout << "finishing: PlayingMode::FastForward," << "stop timer" << std::endl;
104 struct StdDisplay : public msm::front::state<>
106 template <class Event,class FSM>
107 void on_entry(Event const&,FSM& ) {std::cout << "starting: PlayingMode::StdDisplay" << std::endl;}
108 template <class Event,class FSM>
109 void on_exit(Event const&,FSM& ) {std::cout << "finishing: PlayingMode::StdDisplay" << std::endl;}
111 struct SetPosition : public msm::front::state<>
113 typedef mpl::vector1<NoFastFwd> flag_list;
114 template <class Event,class FSM>
115 void on_entry(Event const&,FSM& ) {std::cout << "starting: PlayingMode::SetPosition" << std::endl;}
116 template <class Event,class FSM>
117 void on_exit(Event const&,FSM& ) {std::cout << "finishing: PlayingMode::SetPosition" << std::endl;}
119 struct SetMark : public msm::front::state<>
121 template <class Event,class FSM>
122 void on_entry(Event const&,FSM& ) {std::cout << "starting: PlayingMode::SetMark" << std::endl;}
123 template <class Event,class FSM>
124 void on_exit(Event const&,FSM& ) {std::cout << "finishing: PlayingMode::SetMark" << std::endl;}
126 struct PlayingExit : public msm::front::exit_pseudo_state<EndPlay>
128 template <class Event,class FSM>
129 void on_entry(Event const&,FSM& ) {std::cout << "starting: PlayingMode::PlayingExit" << std::endl;}
130 template <class Event,class FSM>
131 void on_exit(Event const&,FSM& ) {std::cout << "finishing: PlayingMode::PlayingExit" << std::endl;}
133 // transition action methods
134 struct inc_song_counter : euml::euml_action<inc_song_counter>
136 template <class FSM,class EVT,class SourceState,class TargetState>
137 void operator()(EVT const& ,FSM& fsm,SourceState& ,TargetState& )
139 if (++fsm.m_SongIndex <= fsm.m_NumberOfSongs )
141 std::cout << "playing song:" << fsm.m_SongIndex << std::endl;
145 // last song => end playing, next play will start at the beginning
147 fsm.process_event(EndPlay());
152 void select_song(StartSong const& evt)
154 if ((evt.m_Selected>0) && (evt.m_Selected<=m_NumberOfSongs))
156 m_SongIndex = evt.m_Selected;
157 std::cout << "selecting song:" << m_SongIndex << std::endl;
162 std::cout << "selecting song:" << m_SongIndex << std::endl;
165 struct dec_song_counter : euml::euml_action<dec_song_counter>
167 template <class FSM,class EVT,class SourceState,class TargetState>
168 void operator()(EVT const& ,FSM& fsm,SourceState& ,TargetState& )
170 if (--fsm.m_SongIndex >0 )
172 std::cout << "playing song:" << fsm.m_SongIndex << std::endl;
176 // before first song => end playing
178 fsm.process_event(EndPlay());
182 struct send_NextSong : euml::euml_action<send_NextSong>
184 template <class FSM,class EVT,class SourceState,class TargetState>
185 void operator()(EVT const& ,FSM& fsm,SourceState& ,TargetState& )
187 fsm.process_event(NextSong());
191 void do_fast_forward(ForwardTimer const&)
193 std::cout << "moving song forward..." << std::endl;
196 // transition guard methods
197 struct fast_fwd_ok : euml::euml_action<fast_fwd_ok>
199 template <class FSM,class EVT,class SourceState,class TargetState>
200 bool operator()(EVT const& ,FSM& fsm,SourceState& ,TargetState& )
202 // guard accepts only if fast forward is possible (No SetPosition mode)
203 return !fsm.is_flag_active<NoFastFwd>();
206 // initial states / orthogonal zones
207 typedef mpl::vector5<Playing,WaitingForNextPrev,WaitingForEnd,NoForward,StdDisplay>
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 // +--------------------+---------------------+---------------------+--------------------------+----------------------+
241 // for simplicity we decide there are 5 songs
244 int get_current_song(){return m_SongIndex;}
249 typedef msm::back::state_machine<PlayingMode_> PlayingMode;
251 #endif // PLAYING_MODE_HPP