3 #include <boost/msm/back/state_machine.hpp>
5 #include <boost/msm/front/state_machine_def.hpp>
6 #include <boost/msm/front/euml/euml.hpp>
8 namespace msm
= boost::msm
;
9 namespace mpl
= boost::mpl
;
12 // entry/exit/action/guard logging functors
13 #include "logging_functors.h"
18 struct play_impl
: msm::front::euml::euml_event
<play_impl
> {};
19 struct end_pause_impl
: msm::front::euml::euml_event
<end_pause_impl
>{};
20 struct stop_impl
: msm::front::euml::euml_event
<stop_impl
>{};
21 struct pause_impl
: msm::front::euml::euml_event
<pause_impl
>{};
22 struct open_close_impl
: msm::front::euml::euml_event
<open_close_impl
>{};
23 struct cd_detected_impl
: msm::front::euml::euml_event
<cd_detected_impl
>{};
24 struct next_song_impl
: msm::front::euml::euml_event
<next_song_impl
>{};
25 struct previous_song_impl
: msm::front::euml::euml_event
<previous_song_impl
>{};
27 // define some dummy instances for use in the transition table
28 // it is also possible to default-construct them instead:
30 // inside the table: play()
32 end_pause_impl end_pause
;
35 open_close_impl open_close
;
36 cd_detected_impl cd_detected
;
37 next_song_impl next_song
;
38 previous_song_impl previous_song
;
40 // The list of FSM states
41 // they have to be declared outside of the front-end only to make VC happy :(
42 // note: gcc would have no problem
43 struct Empty_impl
: public msm::front::state
<> , public msm::front::euml::euml_state
<Empty_impl
>
45 // every (optional) entry/exit methods get the event passed.
46 template <class Event
,class FSM
>
47 void on_entry(Event
const&,FSM
& ) {std::cout
<< "entering: Empty" << std::endl
;}
48 template <class Event
,class FSM
>
49 void on_exit(Event
const&,FSM
& ) {std::cout
<< "leaving: Empty" << std::endl
;}
51 struct Open_impl
: public msm::front::state
<> , public msm::front::euml::euml_state
<Open_impl
>
53 template <class Event
,class FSM
>
54 void on_entry(Event
const& ,FSM
&) {std::cout
<< "entering: Open" << std::endl
;}
55 template <class Event
,class FSM
>
56 void on_exit(Event
const&,FSM
& ) {std::cout
<< "leaving: Open" << std::endl
;}
59 struct Stopped_impl
: public msm::front::state
<> , public msm::front::euml::euml_state
<Stopped_impl
>
61 template <class Event
,class FSM
>
62 void on_entry(Event
const& ,FSM
&) {std::cout
<< "entering: Stopped" << std::endl
;}
63 template <class Event
,class FSM
>
64 void on_exit(Event
const&,FSM
& ) {std::cout
<< "leaving: Stopped" << std::endl
;}
67 // Playing Submachine front-end
68 struct Playing_
: public msm::front::state_machine_def
<Playing_
>
70 template <class Event
,class FSM
>
71 void on_entry(Event
const& ,FSM
&) {std::cout
<< "entering: Playing" << std::endl
;}
72 template <class Event
,class FSM
>
73 void on_exit(Event
const&,FSM
& ) {std::cout
<< "leaving: Playing" << std::endl
;}
75 struct Song1_
: public msm::front::state
<> , public msm::front::euml::euml_state
<Song1_
>
77 template <class Event
,class FSM
>
78 void on_entry(Event
const& ,FSM
&) {std::cout
<< "entering: Song1" << std::endl
;}
79 template <class Event
,class FSM
>
80 void on_exit(Event
const&,FSM
& ) {std::cout
<< "leaving: Song1" << std::endl
;}
82 struct Song2_
: public msm::front::state
<> , public msm::front::euml::euml_state
<Song2_
>
84 template <class Event
,class FSM
>
85 void on_entry(Event
const& ,FSM
&) {std::cout
<< "entering: Song2" << std::endl
;}
86 template <class Event
,class FSM
>
87 void on_exit(Event
const&,FSM
& ) {std::cout
<< "leaving: Song2" << std::endl
;}
89 struct Song3_
: public msm::front::state
<> , public msm::front::euml::euml_state
<Song3_
>
91 template <class Event
,class FSM
>
92 void on_entry(Event
const& ,FSM
&) {std::cout
<< "entering: Song3" << std::endl
;}
93 template <class Event
,class FSM
>
94 void on_exit(Event
const&,FSM
& ) {std::cout
<< "leaving: Song3" << std::endl
;}
96 // to make the transition table more readable
97 // VC seems to need them static
101 typedef Song1_ initial_state
;
103 // Playing has a transition table
104 BOOST_MSM_EUML_DECLARE_TRANSITION_TABLE((
105 // +------------------------------------------------------------------------------+
106 Song2
== Song1
+ next_song
/ start_next_song
,
107 Song1
== Song2
+ previous_song
/ start_prev_song
,
108 Song3
== Song2
+ next_song
/ start_next_song
,
109 Song2
== Song3
+ previous_song
/ start_prev_song
110 // +------------------------------------------------------------------------------+
114 // Playing Submachine back-end
115 typedef boost::msm::back::state_machine
<Playing_
> Playing_impl
;
117 // state not defining any entry or exit
118 struct Paused_impl
: public msm::front::state
<> , public msm::front::euml::euml_state
<Paused_impl
>
121 //to make the transition table more readable
122 Empty_impl
const Empty
;
123 Open_impl
const Open
;
124 Stopped_impl
const Stopped
;
125 Playing_impl
const Playing
;
126 Paused_impl
const Paused
;
128 // front-end: define the FSM structure
129 struct player_
: public msm::front::state_machine_def
<player_
>
132 // the initial state of the player SM. Must be defined
133 typedef Empty_impl initial_state
;
135 // Transition table for player
136 // replaces the old transition table
137 BOOST_MSM_EUML_DECLARE_TRANSITION_TABLE((
138 Stopped
+ play
/ start_playback
== Playing
,
139 Stopped
+ open_close
/ open_drawer
== Open
,
140 Stopped
+ stop
== Stopped
,
141 // +------------------------------------------------------------------------------+
142 Open
+ open_close
/ close_drawer
== Empty
,
143 // +------------------------------------------------------------------------------+
144 Empty
+ open_close
/ open_drawer
== Open
,
145 Empty
+ cd_detected
/(store_cd_info
,
146 msm::front::euml::process_(play
)) == Stopped
,
147 // +------------------------------------------------------------------------------+
148 Playing
+ stop
/ stop_playback
== Stopped
,
149 Playing
+ pause
/ pause_playback
== Paused
,
150 Playing
+ open_close
/ stop_and_open
== Open
,
151 // +------------------------------------------------------------------------------+
152 Paused
+ end_pause
/ resume_playback
== Playing
,
153 Paused
+ stop
/ stop_playback
== Stopped
,
154 Paused
+ open_close
/ stop_and_open
== Open
155 // +------------------------------------------------------------------------------+
158 // Replaces the default no-transition response.
159 template <class FSM
,class Event
>
160 void no_transition(Event
const& e
, FSM
&,int state
)
162 std::cout
<< "no transition from state " << state
163 << " on event " << typeid(e
).name() << std::endl
;
167 typedef msm::back::state_machine
<player_
> player
;
170 // Testing utilities.
172 static char const* const state_names
[] = { "Stopped", "Open", "Empty", "Playing", "Paused" };
173 void pstate(player
const& p
)
175 std::cout
<< " -> " << state_names
[p
.current_state()[0]] << std::endl
;
181 // needed to start the highest-level SM. This will call on_entry and mark the start of the SM
183 // go to Open, call on_exit on Empty, then action, then on_entry on Open
184 p
.process_event(open_close
); pstate(p
);
185 p
.process_event(open_close
); pstate(p
);
186 p
.process_event(cd_detected
); pstate(p
);
188 // at this point, Play is active
189 // make transition happen inside it. Player has no idea about this event but it's ok.
190 p
.process_event(next_song
);pstate(p
); //2nd song active
191 p
.process_event(next_song
);pstate(p
);//3rd song active
192 p
.process_event(previous_song
);pstate(p
);//2nd song active
194 p
.process_event(pause
); pstate(p
);
195 // go back to Playing
196 p
.process_event(end_pause
); pstate(p
);
197 p
.process_event(pause
); pstate(p
);
198 p
.process_event(stop
); pstate(p
);
199 // event leading to the same state
200 // no action method called as it is not present in the transition table
201 p
.process_event(stop
); pstate(p
);