]> git.tdb.fi Git - libs/demoscene.git/blob - source/sequencer.h
1cd1ebc8f139bc9c1ad6b5af2d1e0bfa79da0615
[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 namespace Msp {
14 namespace DemoScene {
15
16 class Demo;
17
18 class Sequencer
19 {
20 public:
21         class Loader: public Msp::DataFile::ObjectLoader<Sequencer>
22         {
23         private:
24                 Demo &demo;
25                 float base_beat;
26
27         public:
28                 Loader(Sequencer &, Demo &);
29
30         private:
31                 void base(float);
32                 void define_action(const std::string &);
33                 void instant(float);
34                 void segment(float, float);
35         };
36
37 private:
38         class ActionDefLoader;
39         class SegmentLoader;
40
41         class RegisteredAction
42         {
43         public:
44                 typedef void (ActionDefLoader::*DefLoaderFunc)();
45                 typedef void (SegmentLoader::*LoaderFunc)();
46
47                 virtual ~RegisteredAction() { }
48                 virtual DefLoaderFunc get_def_loader_func() const = 0;
49                 virtual LoaderFunc get_loader_func() const = 0;
50         };
51
52         template<typename T>
53         class RegisteredActionType: public RegisteredAction
54         {
55         public:
56                 virtual DefLoaderFunc get_def_loader_func() const;
57                 virtual LoaderFunc get_loader_func() const;
58         };
59
60         class ActionDefLoader: public Msp::DataFile::ObjectLoader<Sequencer>
61         {
62         private:
63                 Demo &demo;
64                 Msp::RefPtr<Action> action;
65
66         public:
67                 ActionDefLoader(Sequencer &, Demo &);
68
69                 Action *get_action() { return action.release(); }
70
71         private:
72                 virtual void finished();
73
74                 template<typename T>
75                 void action_def();
76
77                 template<typename T>
78                 friend class RegisteredActionType;
79         };
80
81         struct Segment
82         {
83                 Action *action;
84                 float start_beat;
85                 float end_beat;
86         };
87
88         class SegmentLoader: public Msp::DataFile::ObjectLoader<Sequencer>
89         {
90         private:
91                 float start_beat;
92                 float end_beat;
93                 Demo &demo;
94
95         public:
96                 SegmentLoader(Sequencer &, float, float, Demo &);
97
98         private:
99                 template<typename T>
100                 void action();
101
102                 void apply(const std::string &);
103
104                 template<typename T>
105                 friend class RegisteredActionType;
106         };
107
108 public:
109         sigc::signal<void> signal_finished;
110
111 private:
112         std::map<std::string, RegisteredAction *> action_types;
113         std::map<std::string, Action *> named_actions;
114         std::vector<Action *> anonymous_actions;
115
116         Msp::Time::TimeDelta secs_per_beat;
117         std::vector<Action *> static_actions;
118         std::vector<Segment> segments;
119         std::vector<Segment>::const_iterator begin;
120         std::vector<Segment>::const_iterator end;
121         bool started;
122         float beat;
123         float next_event;
124
125 public:
126         Sequencer(float = 120.0f);
127
128         template<typename T>
129         void register_action_type(const std::string &);
130
131         void set_beats_per_minute(float);
132         float get_beats_per_minute() const { return Msp::Time::min/secs_per_beat; }
133         void add_static_action(Action &);
134         void add_action(Action &, float, float);
135
136         void start();
137         void seek(float);
138         void tick(const Msp::Time::TimeDelta &);
139 private:
140         void advance_to(float);
141         void update_next_event();
142 public:
143         float get_current_beat() const { return beat; }
144 };
145
146 template<typename T>
147 inline void Sequencer::register_action_type(const std::string &n)
148 {
149         if(action_types.count(n))
150                 throw Msp::key_error(n);
151
152         action_types[n] = new RegisteredActionType<T>;
153 }
154
155 template<typename T>
156 Sequencer::RegisteredAction::DefLoaderFunc Sequencer::RegisteredActionType<T>::get_def_loader_func() const
157 {
158         return &ActionDefLoader::action_def<T>;
159 }
160
161 template<typename T>
162 Sequencer::RegisteredAction::LoaderFunc Sequencer::RegisteredActionType<T>::get_loader_func() const
163 {
164         return &SegmentLoader::action<T>;
165 }
166
167 template<typename T>
168 void Sequencer::ActionDefLoader::action_def()
169 {
170         if(action)
171                 throw std::runtime_error("Only one action per definition is allowed");
172
173         Msp::RefPtr<T> act = new T;
174         load_sub(*act, demo);
175         action = act;
176 }
177
178 template<typename T>
179 void Sequencer::SegmentLoader::action()
180 {
181         Msp::RefPtr<T> act = new T;
182         load_sub(*act, demo);
183         obj.add_action(*act, start_beat, end_beat);
184         obj.anonymous_actions.push_back(act.release());
185 }
186
187 } // namespace DemoScene
188 } // namespace Msp
189
190 #endif