]> git.tdb.fi Git - libs/demoscene.git/blob - source/sequencer.h
Framework for loading sequences from files
[libs/demoscene.git] / source / sequencer.h
1 #ifndef MSP_DEMOSCENE_SEQUENCER_H_
2 #define MSP_DEMOSCENE_SEQUENCER_H_
3
4 #include <vector>
5 #include <sigc++/signal.h>
6 #include <msp/core/maputils.h>
7 #include <msp/core/refptr.h>
8 #include <msp/datafile/objectloader.h>
9 #include <msp/time/timedelta.h>
10 #include <msp/time/timestamp.h>
11 #include "action.h"
12
13 class Demo;
14
15 class Sequencer
16 {
17 public:
18         class Loader: public Msp::DataFile::ObjectLoader<Sequencer>
19         {
20         private:
21                 Demo &demo;
22
23         public:
24                 Loader(Sequencer &, Demo &);
25
26         private:
27                 void define_action(const std::string &);
28                 void instant(float);
29                 void segment(float, float);
30         };
31
32 private:
33         class ActionDefLoader;
34
35         class RegisteredAction
36         {
37         public:
38                 typedef void (ActionDefLoader::*LoaderFunc)();
39
40                 virtual ~RegisteredAction() { }
41                 virtual LoaderFunc get_loader_func() const = 0;
42         };
43
44         template<typename T>
45         class RegisteredActionType: public RegisteredAction
46         {
47         public:
48                 virtual LoaderFunc get_loader_func() const;
49         };
50
51         class ActionDefLoader: public Msp::DataFile::ObjectLoader<Sequencer>
52         {
53         private:
54                 Demo &demo;
55                 Msp::RefPtr<Action> action;
56
57         public:
58                 ActionDefLoader(Sequencer &, Demo &);
59
60                 Action *get_action() { return action.release(); }
61
62         private:
63                 virtual void finished();
64
65                 template<typename T>
66                 void action_def();
67
68                 template<typename T>
69                 friend class RegisteredActionType;
70         };
71
72         struct Segment
73         {
74                 Action *action;
75                 float start_beat;
76                 float end_beat;
77         };
78
79         class SegmentLoader: public Msp::DataFile::ObjectLoader<Sequencer>
80         {
81         private:
82                 float start_beat;
83                 float end_beat;
84
85         public:
86                 SegmentLoader(Sequencer &, float, float);
87
88         private:
89                 void apply(const std::string &);
90         };
91
92 public:
93         sigc::signal<void> signal_finished;
94
95 private:
96         std::map<std::string, RegisteredAction *> action_types;
97         std::map<std::string, Action *> named_actions;
98
99         Msp::Time::TimeDelta secs_per_beat;
100         std::vector<Action *> static_actions;
101         std::vector<Segment> segments;
102         std::vector<Segment>::const_iterator begin;
103         std::vector<Segment>::const_iterator end;
104         bool started;
105         float beat;
106         float next_event;
107
108 public:
109         Sequencer(float = 120.0f);
110
111         template<typename T>
112         void register_action_type(const std::string &);
113
114         void set_beats_per_minute(float);
115         float get_beats_per_minute() const { return Msp::Time::min/secs_per_beat; }
116         void add_static_action(Action &);
117         void add_action(Action &, float, float);
118
119         void start();
120         void seek(float);
121         void tick(const Msp::Time::TimeDelta &);
122 private:
123         void advance_to(float);
124         void update_next_event();
125 public:
126         float get_current_beat() const { return beat; }
127 };
128
129 template<typename T>
130 inline void Sequencer::register_action_type(const std::string &n)
131 {
132         if(action_types.count(n))
133                 throw Msp::key_error(n);
134
135         action_types[n] = new RegisteredActionType<T>;
136 }
137
138 template<typename T>
139 Sequencer::RegisteredAction::LoaderFunc Sequencer::RegisteredActionType<T>::get_loader_func() const
140 {
141         return &ActionDefLoader::action_def<T>;
142 }
143
144 template<typename T>
145 void Sequencer::ActionDefLoader::action_def()
146 {
147         if(action)
148                 throw std::runtime_error("Only one action per definition is allowed");
149
150         Msp::RefPtr<T> act = new T;
151         load_sub(*act, demo);
152         action = act;
153 }
154
155 #endif