summaryrefslogtreecommitdiff
path: root/libs/msm/doc/PDF/examples/iPod_distributed/iPod.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'libs/msm/doc/PDF/examples/iPod_distributed/iPod.cpp')
-rw-r--r--libs/msm/doc/PDF/examples/iPod_distributed/iPod.cpp243
1 files changed, 243 insertions, 0 deletions
diff --git a/libs/msm/doc/PDF/examples/iPod_distributed/iPod.cpp b/libs/msm/doc/PDF/examples/iPod_distributed/iPod.cpp
new file mode 100644
index 0000000000..d5b3b79945
--- /dev/null
+++ b/libs/msm/doc/PDF/examples/iPod_distributed/iPod.cpp
@@ -0,0 +1,243 @@
+// 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>
+#define FUSION_MAX_VECTOR_SIZE 20
+
+#include "boost/mpl/vector/vector50.hpp"
+#include <boost/msm/back/state_machine.hpp>
+#include <boost/msm/front/state_machine_def.hpp>
+
+#include "Events.hpp"
+#include "PlayingMode.hpp"
+#include "MenuMode.hpp"
+
+using namespace std;
+namespace msm = boost::msm;
+
+namespace // Concrete FSM implementation
+{
+ struct iPod_;
+ typedef msm::back::state_machine<iPod_,
+ ::boost::msm::back::favor_compile_time> iPod;
+
+ // Concrete FSM implementation
+ struct iPod_ : public msm::front::state_machine_def<iPod_>
+ {
+ // The list of FSM states
+ struct NotHolding : public msm::front::state<>
+ {
+ template <class Event,class FSM>
+ void on_entry(Event const&,FSM& ) {std::cout << "starting: NotHolding" << std::endl;}
+ template <class Event,class FSM>
+ void on_exit(Event const&,FSM& ) {std::cout << "finishing: NotHolding" << std::endl;}
+ };
+ struct Holding : public msm::front::interrupt_state<NoHold>
+ {
+ template <class Event,class FSM>
+ void on_entry(Event const&,FSM& ) {std::cout << "starting: Holding" << std::endl;}
+ template <class Event,class FSM>
+ void on_exit(Event const&,FSM& ) {std::cout << "finishing: Holding" << std::endl;}
+ };
+ struct NotPlaying : public msm::front::state<>
+ {
+ template <class Event,class FSM>
+ void on_entry(Event const&,FSM& ) {std::cout << "starting: NotPlaying" << std::endl;}
+ template <class Event,class FSM>
+ void on_exit(Event const&,FSM& ) {std::cout << "finishing: NotPlaying" << std::endl;}
+ };
+ struct NoMenuMode : public msm::front::state<>
+ {
+ template <class Event,class FSM>
+ void on_entry(Event const&,FSM& ) {std::cout << "starting: NoMenuMode" << std::endl;}
+ template <class Event,class FSM>
+ void on_exit(Event const&,FSM& ) {std::cout << "finishing: NoMenuMode" << std::endl;}
+ };
+ struct NoOnOffButton : public msm::front::state<>
+ {
+ template <class Event,class FSM>
+ void on_entry(Event const&,FSM& ) {std::cout << "starting: NoOnOffButton" << std::endl;}
+ template <class Event,class FSM>
+ void on_exit(Event const&,FSM& ) {std::cout << "finishing: NoOnOffButton" << std::endl;}
+ };
+ struct OffDown : public msm::front::state<>
+ {
+ template <class Event,class FSM>
+ void on_entry(Event const&,FSM& ) {std::cout << "starting: OffDown, start timer" << std::endl;}
+ template <class Event,class FSM>
+ void on_exit(Event const&,FSM& ) {std::cout << "finishing: OffDown, end timer" << std::endl;}
+ };
+ struct PlayerOff : public msm::front::state<>
+ {
+ template <class Event,class FSM>
+ void on_entry(Event const&,FSM& ) {std::cout << "starting: PlayerOff" << std::endl;}
+ template <class Event,class FSM>
+ void on_exit(Event const&,FSM& ) {std::cout << "finishing: PlayerOff" << std::endl;}
+ };
+ struct CheckMiddleButton : public msm::front::state<>
+ {
+ template <class Event,class FSM>
+ void on_entry(Event const&,FSM& ) {std::cout << "starting: CheckMiddleButton" << std::endl;}
+ template <class Event,class FSM>
+ void on_exit(Event const&,FSM& ) {std::cout << "finishing: CheckMiddleButton" << std::endl;}
+ };
+
+ // the initial state of the player SM. Must be defined
+ typedef mpl::vector5<NotHolding,NotPlaying,NoMenuMode,NoOnOffButton,CheckMiddleButton>
+ initial_state;
+ // transition actions
+ void send_ActivateMenu(EndPlay const&)
+ {
+ std::cout << "leaving Playing" << std::endl;
+ // we need to activate the menu and simulate its button
+ (static_cast<iPod*>(this))->process_event(MenuButton());
+ }
+ void send_StartSong(CloseMenu const&)
+ {
+ // we suppose the 5th song was selected
+ (static_cast<iPod*>(this))->process_event(StartSong(5));
+ }
+ void send_PlayPause(SouthReleased const&)
+ {
+ // action using the message queue to generate another event
+ (static_cast<iPod*>(this))->process_event(PlayPause());
+ }
+ void send_Off(OnOffTimer const&)
+ {
+ std::cout << "turning player off" << std::endl;
+ (static_cast<iPod*>(this))->process_event(Off());
+ }
+ void send_PlayingMiddleButton(MiddleButton const&)
+ {
+ (static_cast<iPod*>(this))->process_event(PlayingMiddleButton());
+ }
+ void send_MenuMiddleButton(MiddleButton const&)
+ {
+ (static_cast<iPod*>(this))->process_event(MenuMiddleButton());
+ }
+ // guard conditions
+ bool is_menu(MiddleButton const&)
+ {
+ return (static_cast<iPod*>(this))->is_flag_active<MenuActive>();
+ }
+ bool is_no_menu(MiddleButton const& evt)
+ {
+ return !is_menu(evt);
+ }
+ template <class EVENT>
+ void switch_on(EVENT const&)
+ {
+ std::cout << "turning player on" << std::endl;
+ }
+ typedef iPod_ fsm; // makes transition table cleaner
+
+ // Transition table for player
+ struct transition_table : mpl::vector<
+ // Start Event Next Action Guard
+ // +-------------------+---------------+-------------------+--------------------------------+----------------------+
+ _row < NotHolding , Hold , Holding >,
+ _row < Holding , NoHold , NotHolding >,
+ // +-------------------+---------------+-------------------+--------------------------------+----------------------+
+ _row < NotPlaying , PlayPause , PlayingMode >,
+ a_row < PlayingMode::exit_pt<PlayingMode_::
+ PlayingExit> , EndPlay , NotPlaying , &fsm::send_ActivateMenu >,
+ // +-------------------+---------------+-------------------+--------------------------------+----------------------+
+ _row < NoMenuMode , MenuButton , MenuMode >,
+ a_row < MenuMode::exit_pt<MenuMode_::
+ MenuExit> , CloseMenu , NoMenuMode , &fsm::send_StartSong >,
+ // +-------------------+---------------+-------------------+--------------------------------+----------------------+
+ _row < NoOnOffButton , SouthPressed , OffDown >,
+ a_row < OffDown , SouthReleased , NoOnOffButton , &fsm::send_PlayPause >,
+ a_row < OffDown , OnOffTimer , PlayerOff , &fsm::send_Off >,
+ a_row < PlayerOff , SouthPressed , NoOnOffButton , &fsm::switch_on >,
+ a_row < PlayerOff , NoHold , NoOnOffButton , &fsm::switch_on >,
+ // +-------------------+---------------+--------------------+--------------------------------+----------------------+
+ row < CheckMiddleButton , MiddleButton , CheckMiddleButton , &fsm::send_PlayingMiddleButton , &fsm::is_menu >,
+ row < CheckMiddleButton , MiddleButton , CheckMiddleButton , &fsm::send_MenuMiddleButton , &fsm::is_no_menu >
+ // +-------------------+---------------+--------------------+--------------------------------+----------------------+
+ > {};
+
+ // Replaces the default no-transition response.
+ template <class FSM,class Event>
+ void no_transition(Event const& e, FSM&,int state)
+ {
+ std::cout << "no transition from state " << state
+ << " on event " << typeid(e).name() << std::endl;
+ }
+ };
+
+ 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;
+}