try to make build portable: remove SDL_mixer dependency, remove -f from cp command...
[openc2e.git] / mngfile.h
blobf372d99e7481f1c9fae77ee2662d0b48388f1185
1 /*
2 * mngfile.h
3 * openc2e
5 * Created by Alyssa Milburn on Tue 16 Nov 2004.
6 * Copyright (c) 2004-2006 Alyssa Milburn. All rights reserved.
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
19 #include <string>
20 #include <vector>
21 #include <list>
22 #include <map>
23 #include <istream>
24 #include <cmath>
25 #include "exceptions.h"
26 #include <boost/format.hpp>
28 void mngrestart(std::istream *is);
30 struct processState {
31 class MNGLayer *layer;
32 class MNGFile *mngfile;
33 class MNGVoiceNode *voice;
34 class MNGStageNode *stage;
35 class MNGTrackDecNode *track;
37 processState(class MNGFile *m) { mngfile = m; layer = 0; voice = 0; stage = 0; track = 0; }
40 class MNGNode {
41 public:
42 virtual std::string dump() { return "[unknown node]"; }
43 virtual void postProcess(processState *s) { } // walk the tree, setting up parent pointers correctly
44 virtual ~MNGNode() { }
47 class MNGFileException : public creaturesException {
48 public:
49 int error;
50 MNGFileException(const char * m, int e) throw() : creaturesException(m) { error = e; }
53 class MNGNamedNode : public MNGNode {
54 protected:
55 std::string name;
57 public:
58 MNGNamedNode(std::string n) { name = n; }
59 std::string getName() { return name; }
60 virtual std::string dump() { return std::string("[unknown named node: ") + getName() + "]"; }
63 inline std::string dumpChildren(std::list<MNGNode *> *c) {
64 std::string t = "\n";
65 for (std::list<MNGNode *>::iterator i = c->begin(); i != c->end(); i++) t = t + (*i)->dump() + "\n";
66 return t;
69 class MNGStageNode : public MNGNode { // stage
70 public:
71 std::list<MNGNode *> *children; // stagesettinglist
72 virtual std::string dump() { return std::string("Stage { ") + dumpChildren(children) + "}\n"; }
73 virtual void postProcess(processState *s) { s->stage = this; for (std::list<MNGNode *>::iterator i = children->begin(); i != children->end(); i++) (*i)->postProcess(s); s->stage = 0; }
74 virtual ~MNGStageNode() { for (std::list<MNGNode *>::iterator i = children->begin(); i != children->end(); i++) delete *i; delete children; }
77 class MNGEffectDecNode : public MNGNamedNode { // effectdec
78 public:
79 MNGEffectDecNode(std::string n) : MNGNamedNode(n) { }
80 std::list<class MNGStageNode *> *children; // stagelist
81 virtual std::string dump() { return std::string("Effect(" + name + ") { ") + /*dumpEffectChildren(children)*/ + "}\n"; } // TODO!!!
82 virtual void postProcess(processState *s) { for (std::list<MNGStageNode *>::iterator i = children->begin(); i != children->end(); i++) (*i)->postProcess(s); }
83 virtual ~MNGEffectDecNode() { for (std::list<MNGStageNode *>::iterator i = children->begin(); i != children->end(); i++) delete *i; delete children; }
86 class MNGTrackDecNode : public MNGNamedNode { // trackdec
87 public:
88 MNGTrackDecNode(std::string n) : MNGNamedNode(n) { }
89 std::list<MNGNode *> *children; // track
90 virtual std::string dump() { return std::string("Track(" + name + ") { ") + dumpChildren(children) + "}\n"; }
91 virtual void postProcess(processState *s) { s->track = this; for (std::list<MNGNode *>::iterator i = children->begin(); i != children->end(); i++) (*i)->postProcess(s); s->track = 0; }
92 virtual ~MNGTrackDecNode() { for (std::list<MNGNode *>::iterator i = children->begin(); i != children->end(); i++) delete *i; delete children; }
95 class MNGEffectNode : public MNGNamedNode { // effect
96 public:
97 MNGEffectNode(std::string n) : MNGNamedNode(n) { }
98 virtual std::string dump() { return std::string("Effect(") + name + ")"; }
101 class MNGExpression : public MNGNode { // (expression)
102 public:
103 virtual float evaluate() = 0;
106 class MNGBinaryExpression : public MNGExpression {
107 protected:
108 MNGExpression *one, *two;
110 public:
111 MNGBinaryExpression(MNGExpression *o, MNGExpression *t) { one = o; two = t; }
112 virtual void postProcess(processState *s) { one->postProcess(s); two->postProcess(s); }
113 virtual ~MNGBinaryExpression() { delete one; delete two; }
116 class MNGConstantNode : public MNGExpression { // MNG_number
117 protected:
118 float value;
120 public:
121 MNGConstantNode(float n) { value = n; }
122 std::string dump() { return boost::str(boost::format("%f") % value); }
123 float evaluate() { return value; }
126 class MNGExpressionContainer : public MNGNode {
127 protected:
128 MNGExpression *subnode;
130 public:
131 MNGExpressionContainer(MNGExpression *n) { subnode = n; }
132 virtual void postProcess(processState *s) { subnode->postProcess(s); }
135 class MNGPanNode : public MNGExpressionContainer { // pan
136 public:
137 MNGPanNode(MNGExpression *n) : MNGExpressionContainer(n) { }
138 std::string dump() { return std::string("Pan(") + subnode->dump() + ")"; }
141 class MNGLayerVolumeNode : public MNGExpressionContainer { // layervolume
142 public:
143 MNGLayerVolumeNode(MNGExpression *n) : MNGExpressionContainer(n) { }
144 std::string dump() { return std::string("Volume(") + subnode->dump() + ")"; }
147 class MNGEffectVolumeNode : public MNGExpressionContainer { // effectvolume
148 public:
149 MNGEffectVolumeNode(MNGExpression *n) : MNGExpressionContainer(n) { }
150 std::string dump() { return std::string("Volume(") + subnode->dump() + ")"; }
153 class MNGDelayNode : public MNGExpressionContainer { // delay
154 public:
155 MNGDelayNode(MNGExpression *n) : MNGExpressionContainer(n) { }
156 std::string dump() { return std::string("Delay(") + subnode->dump() + ")"; }
159 class MNGRandomNode : public MNGBinaryExpression { // random
160 public:
161 MNGRandomNode(MNGExpression *o, MNGExpression *t) : MNGBinaryExpression(o, t) { }
162 std::string dump() { return std::string("Random(") + one->dump() + ", " + two->dump() + ")"; }
163 float evaluate() { float l = one->evaluate(); return ((float)rand() / RAND_MAX) * (two->evaluate() - l) + l;}
166 class MNGTempoDelayNode : public MNGExpressionContainer { // tempodelay
167 public:
168 MNGTempoDelayNode(MNGExpression *n) : MNGExpressionContainer(n) { }
169 std::string dump() { return std::string("TempoDelay(") + subnode->dump() + ")"; }
172 class MNGFadeInNode : public MNGExpressionContainer { // fadein
173 public:
174 MNGFadeInNode(MNGExpression *n) : MNGExpressionContainer(n) { }
175 std::string dump() { return std::string("FadeIn(") + subnode->dump() + ")"; }
178 class MNGFadeOutNode : public MNGExpressionContainer { // fadeout
179 public:
180 MNGFadeOutNode(MNGExpression *n) : MNGExpressionContainer(n) { }
181 std::string dump() { return std::string("FadeOut(") + subnode->dump() + ")"; }
184 class MNGBeatLengthNode : public MNGExpressionContainer { // beatlength
185 public:
186 MNGBeatLengthNode(MNGExpression *n) : MNGExpressionContainer(n) { }
187 std::string dump() { return std::string("BeatLength(") + subnode->dump() + ")"; }
190 class MNGLayer : public MNGNamedNode {
191 public:
192 MNGLayer(std::string n) : MNGNamedNode(n) { }
193 std::list<MNGNode *> *children;
194 std::map<std::string, class MNGVariableDecNode *> variables;
195 void setChildren(std::list<MNGNode *> *);
196 virtual void postProcess(processState *s) {
197 s->layer = this;
198 for (std::list<MNGNode *>::iterator i = children->begin(); i != children->end(); i++)
199 (*i)->postProcess(s);
200 s->layer = 0;
202 virtual ~MNGLayer() { for (std::list<MNGNode *>::iterator i = children->begin(); i != children->end(); i++) delete *i; delete children; }
205 class MNGLoopLayerNode : public MNGLayer { // looplayerdec
206 public:
207 MNGLoopLayerNode(std::string n) : MNGLayer(n) { }
208 virtual std::string dump() { return std::string("LoopLayer(" + name + ") { ") + dumpChildren(children) + "}\n"; }
211 class MNGAleotoricLayerNode : public MNGLayer { // aleotoriclayerdec
212 public:
213 MNGAleotoricLayerNode(std::string n) : MNGLayer(n) { }
214 virtual std::string dump() { return std::string("AleotoricLayer(" + name + ") { ") + dumpChildren(children) + "}\n"; }
217 class MNGAddNode : public MNGBinaryExpression { // add
218 public:
219 MNGAddNode(MNGExpression *o, MNGExpression *t) : MNGBinaryExpression(o, t) { }
220 virtual std::string dump() { return std::string("Add(") + one->dump() + ", " + two->dump() + ")"; }
221 float evaluate() { return one->evaluate() + two->evaluate(); }
224 class MNGSubtractNode : public MNGBinaryExpression { // subtract
225 public:
226 MNGSubtractNode(MNGExpression *o, MNGExpression *t) : MNGBinaryExpression(o, t) { }
227 virtual std::string dump() { return std::string("Subtract(") + one->dump() + ", " + two->dump() + ")"; }
228 float evaluate() { return one->evaluate() - two->evaluate(); }
231 class MNGMultiplyNode : public MNGBinaryExpression { // multiply
232 public:
233 MNGMultiplyNode(MNGExpression *o, MNGExpression *t) : MNGBinaryExpression(o, t) { }
234 virtual std::string dump() { return std::string("Multiply(") + one->dump() + ", " + two->dump() + ")"; }
235 float evaluate() { return one->evaluate() * two->evaluate(); }
238 class MNGDivideNode : public MNGBinaryExpression { // divide
239 public:
240 MNGDivideNode(MNGExpression *o, MNGExpression *t) : MNGBinaryExpression(o, t) { }
241 virtual std::string dump() { return std::string("Divide(") + one->dump() + ", " + two->dump() + ")"; }
242 float evaluate() { return one->evaluate() / two->evaluate(); }
245 class MNGSineWaveNode : public MNGBinaryExpression { // sinewave
246 public:
247 MNGSineWaveNode(MNGExpression *o, MNGExpression *t) : MNGBinaryExpression(o, t) { }
248 virtual std::string dump() { return std::string("SineWave(") + one->dump() + ", " + two->dump() + ")"; }
249 float evaluate() { return sin(one->evaluate() / two->evaluate() * 2 * M_PI); } // from GR's code
252 class MNGCosineWaveNode : public MNGBinaryExpression { // cosinewave
253 public:
254 MNGCosineWaveNode(MNGExpression *o, MNGExpression *t) : MNGBinaryExpression(o, t) { }
255 virtual std::string dump() { return std::string("CosineWave(") + one->dump() + ", " + two->dump() + ")"; }
256 float evaluate() { return cos(one->evaluate() / two->evaluate() * 2 * M_PI); } // from GR's code
259 class MNGBeatSynchNode : public MNGExpressionContainer { // beatsynch
260 public:
261 MNGBeatSynchNode(MNGExpression *n) : MNGExpressionContainer(n) { }
262 std::string dump() { return std::string("BeatSynch(") + subnode->dump() + ")"; }
265 class MNGUpdateRateNode : public MNGExpressionContainer { // updaterate
266 public:
267 MNGUpdateRateNode(MNGExpression *n) : MNGExpressionContainer(n) { }
268 std::string dump() { return std::string("UpdateRate(") + subnode->dump() + ")"; }
271 class MNGIntervalNode : public MNGExpressionContainer { // interval
272 public:
273 MNGIntervalNode(MNGExpression *n) : MNGExpressionContainer(n) { }
274 std::string dump() { return std::string("Interval(") + subnode->dump() + ")"; }
277 class MNGVariableDecNode : public MNGNamedNode {
278 protected:
279 float value;
281 public:
282 // TODO: we should ensure the expression passed here is a constant.. ?
283 MNGVariableDecNode(std::string n, MNGExpression *e) : MNGNamedNode(n) { value = e->evaluate(); delete e; }
284 std::string dump() { return std::string("Variable(") + name + ", " + MNGConstantNode(value).dump() + ")"; } // TODO: note this gives the /current/ value. also, hacky.
285 void set(float n) { value = n; }
286 float evaluate() { return value; }
287 virtual void postProcess(processState *s) { s->layer->variables[name] = this; }
290 enum variabletypes { NAMED, INTERVAL, VOLUME, PAN };
292 class MNGVariableNode : public MNGExpression { // variable
293 protected:
294 std::string name;
295 variabletypes variabletype;
296 MNGVariableDecNode *real;
298 union {
299 class MNGLayer *layer;
300 class MNGVoiceNode *voice;
301 class MNGStageNode *stage;
302 class MNGTrackDecNode *track;
305 public:
306 // TODO: i'm assuming layer clears them all, ie, it really is a union. is that right? - fuzzie
307 MNGVariableNode(std::string n) { layer = 0; variabletype = NAMED; name = n; }
308 MNGVariableNode(variabletypes t) { layer = 0; variabletype = t; }
309 virtual void postProcess(processState *s) {
310 switch (variabletype) {
311 case NAMED:
312 // TODO: make sure variables[name] exists, if not, look up globally
313 real = s->layer->variables[name];
314 break;
316 case INTERVAL:
317 if (s->voice) voice = s->voice;
318 else if (s->layer) layer = s->layer;
319 else throw creaturesException("wah, interval in variable node confused me"); // TODO
320 break;
322 case PAN:
323 if (s->stage) stage = s->stage;
324 else if (s->layer) layer = s->layer;
325 else throw creaturesException("wah, pan in variable node confused me"); // TODO
326 break;
328 case VOLUME:
329 if (s->stage) stage = s->stage;
330 else if (s->layer) layer = s->layer;
331 else if (s->track) track = s->track;
332 else throw creaturesException("wah, volume in variable node confused me"); // TODO
333 break;
335 default:
336 throw creaturesException("wah, unknown variabletype in variable node"); // TODO
339 std::string dump() {
340 switch (variabletype) {
341 case NAMED: return name;
342 case INTERVAL: return "Interval";
343 case VOLUME: return "Volume";
344 case PAN: return "Pan";
347 return "MNGVariableNodeIsConfused"; // TODO: exception? :P
350 void set(float n) { assert(variabletype == NAMED); real->set(n); } // TODO
351 float evaluate() {
352 switch (variabletype) {
353 case NAMED: return real->evaluate();
354 case INTERVAL: return 0; // TODO
355 case VOLUME: return 0; // TODO
356 case PAN: return 0; // TODO
359 return 0; // TODO: exception!
363 class MNGAssignmentNode : public MNGNode { // assignment
364 protected:
365 MNGVariableNode *variable;
366 MNGExpression *expression;
368 public:
369 MNGAssignmentNode(MNGVariableNode *v, MNGExpression *e) { variable = v; expression = e; }
370 std::string dump() { return variable->dump() + " = " + expression->dump(); }
371 virtual ~MNGAssignmentNode() { delete variable; delete expression; }
372 void evaluate() { variable->set(expression->evaluate()); }
373 virtual void postProcess(processState *s) { variable->postProcess(s); expression->postProcess(s); }
376 inline std::string dumpAssignmentChildren(std::list<MNGAssignmentNode *> *c) {
377 std::string t = "\n";
378 for (std::list<MNGAssignmentNode *>::iterator i = c->begin(); i != c->end(); i++) t = t + (*i)->dump() + "\n";
379 return t;
382 class MNGConditionNode : public MNGNode { // condition
383 protected:
384 MNGVariableNode *variable;
385 float one, two;
387 public:
388 MNGConditionNode(MNGVariableNode *v, float o, float t) { variable = v; one = o; two = t; }
389 std::string dump() { return "Condition(" + variable->dump() + ", " + MNGConstantNode(one).dump() + ", " + MNGConstantNode(two).dump() + ")"; } // hacky..
390 virtual void postProcess(processState *s) { variable->postProcess(s); }
391 virtual ~MNGConditionNode() { delete variable; }
394 class MNGUpdateNode : public MNGNode { // update
395 public:
396 std::list<MNGAssignmentNode *> *children; // assignmentlist
397 virtual std::string dump() { return std::string("Update { ") + dumpAssignmentChildren(children) + "}\n"; }
398 virtual void postProcess(processState *s) { for (std::list<MNGAssignmentNode *>::iterator i = children->begin(); i != children->end(); i++) (*i)->postProcess(s); }
399 virtual ~MNGUpdateNode() { for (std::list<MNGAssignmentNode *>::iterator i = children->begin(); i != children->end(); i++) delete *i; delete children; }
400 void evaluate() { for (std::list<MNGAssignmentNode *>::iterator i = children->begin(); i != children->end(); i++) (*i)->evaluate(); }
403 class MNGVoiceNode : public MNGNode { // voiceblock
404 public:
405 std::list<MNGNode *> *children; // voicecommands
406 virtual std::string dump() { return std::string("Voice { ") + dumpChildren(children) + "}\n"; }
407 virtual void postProcess(processState *s) { s->voice = this; for (std::list<MNGNode *>::iterator i = children->begin(); i != children->end(); i++) (*i)->postProcess(s); s->voice = 0; }
408 virtual ~MNGVoiceNode() { for (std::list<MNGNode *>::iterator i = children->begin(); i != children->end(); i++) delete *i; delete children; }
411 class MNGFile {
412 private:
413 FILE * f;
414 long filesize;
415 char * map;
416 std::string name;
417 int numsamples, scriptoffset, scriptlength, scriptend;
418 char * script;
419 unsigned int sampleno;
421 public:
422 std::map<std::string, class MNGVariableDecNode *> variables; // TODO: should be private?
423 MNGFile(std::string);
424 void enumerateSamples();
425 ~MNGFile();
426 void add(class MNGEffectDecNode *n) { effects[n->getName()] = n; }
427 void add(class MNGTrackDecNode *n) { tracks[n->getName()] = n; }
428 void add(class MNGVariableDecNode *n) { variables[n->getName()] = n; }
429 std::pair<char *, int> *getNextSample() { sampleno++; return &samples[sampleno - 1]; }
430 std::vector< std::pair< char *, int > > samples;
431 std::map<std::string, class MNGEffectDecNode *> effects;
432 std::map<std::string, class MNGTrackDecNode *> tracks;
434 std::string dump() {
435 std::ostringstream oss;
437 std::map<std::string, class MNGEffectDecNode *>::iterator ei;
438 std::map<std::string, class MNGTrackDecNode *>::iterator ti;
440 for (ei = effects.begin(); ei != effects.end(); ei++)
441 oss << ei->first << " " << ei->second->dump() << std::endl;
443 for (ti = tracks.begin(); ti != tracks.end(); ti++)
444 oss << ti->first << " " << ti->second->dump() << std::endl;
446 return oss.str();
450 extern MNGFile *g_mngfile;
452 class MNGWaveNode : public MNGNamedNode { // wave
453 protected:
454 std::pair<char *, int> *sample;
456 public:
457 MNGWaveNode(std::string n) : MNGNamedNode(n) { sample = g_mngfile->getNextSample(); }
458 std::string dump() { return std::string("Wave(") + name + ")"; }