]>
Commit | Line | Data |
---|---|---|
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> | |
36 | 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> | |
42 | void on_exit(Event const&,FSM& ) {std::cout << "finishing: PlayingMode::Playing" << std::endl;} | |
43 | 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> | |
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;} | |
56 | }; | |
57 | struct WaitingForNextPrev : public msm::front::state<> | |
58 | { | |
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;} | |
63 | }; | |
64 | struct WaitingForEnd : public msm::front::state<> | |
65 | { | |
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;} | |
70 | }; | |
71 | struct NoForward : public msm::front::state<> | |
72 | { | |
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;} | |
77 | }; | |
78 | struct ForwardPressed : public msm::front::state<> | |
79 | { | |
80 | template <class Event,class FSM> | |
81 | void on_entry(Event const&,FSM& ) | |
82 | { | |
83 | std::cout << "starting: PlayingMode::ForwardPressed," << "start timer" << std::endl; | |
84 | } | |
85 | template <class Event,class FSM> | |
86 | 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> | |
94 | void on_entry(Event const&,FSM& ) | |
95 | { | |
96 | std::cout << "starting: PlayingMode::FastForward," << "start timer" << std::endl; | |
97 | } | |
98 | template <class Event,class FSM> | |
99 | 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> | |
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;} | |
110 | }; | |
111 | struct SetPosition : public msm::front::state<> | |
112 | { | |
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;} | |
118 | }; | |
119 | struct SetMark : public msm::front::state<> | |
120 | { | |
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;} | |
125 | }; | |
126 | struct PlayingExit : public msm::front::exit_pseudo_state<EndPlay> | |
127 | { | |
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;} | |
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> | |
137 | 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 | ||
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> | |
168 | 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> | |
185 | void operator()(EVT const& ,FSM& fsm,SourceState& ,TargetState& ) | |
186 | { | |
187 | fsm.process_event(NextSong()); | |
188 | } | |
189 | }; | |
190 | ||
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> | |
200 | 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 | > {}; | |
239 | PlayingMode_(): | |
240 | m_SongIndex(1), | |
241 | // for simplicity we decide there are 5 songs | |
242 | m_NumberOfSongs(5){} | |
243 | ||
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 |