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.
25 #include "exceptions.h"
26 #include <boost/format.hpp>
28 void mngrestart(std::istream
*is
);
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; }
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
{
50 MNGFileException(const char * m
, int e
) throw() : creaturesException(m
) { error
= e
; }
53 class MNGNamedNode
: public MNGNode
{
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
) {
65 for (std::list
<MNGNode
*>::iterator i
= c
->begin(); i
!= c
->end(); i
++) t
= t
+ (*i
)->dump() + "\n";
69 class MNGStageNode
: public MNGNode
{ // stage
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
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
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
97 MNGEffectNode(std::string n
) : MNGNamedNode(n
) { }
98 virtual std::string
dump() { return std::string("Effect(") + name
+ ")"; }
101 class MNGExpression
: public MNGNode
{ // (expression)
103 virtual float evaluate() = 0;
106 class MNGBinaryExpression
: public MNGExpression
{
108 MNGExpression
*one
, *two
;
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
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
{
128 MNGExpression
*subnode
;
131 MNGExpressionContainer(MNGExpression
*n
) { subnode
= n
; }
132 virtual void postProcess(processState
*s
) { subnode
->postProcess(s
); }
135 class MNGPanNode
: public MNGExpressionContainer
{ // pan
137 MNGPanNode(MNGExpression
*n
) : MNGExpressionContainer(n
) { }
138 std::string
dump() { return std::string("Pan(") + subnode
->dump() + ")"; }
141 class MNGLayerVolumeNode
: public MNGExpressionContainer
{ // layervolume
143 MNGLayerVolumeNode(MNGExpression
*n
) : MNGExpressionContainer(n
) { }
144 std::string
dump() { return std::string("Volume(") + subnode
->dump() + ")"; }
147 class MNGEffectVolumeNode
: public MNGExpressionContainer
{ // effectvolume
149 MNGEffectVolumeNode(MNGExpression
*n
) : MNGExpressionContainer(n
) { }
150 std::string
dump() { return std::string("Volume(") + subnode
->dump() + ")"; }
153 class MNGDelayNode
: public MNGExpressionContainer
{ // delay
155 MNGDelayNode(MNGExpression
*n
) : MNGExpressionContainer(n
) { }
156 std::string
dump() { return std::string("Delay(") + subnode
->dump() + ")"; }
159 class MNGRandomNode
: public MNGBinaryExpression
{ // random
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
168 MNGTempoDelayNode(MNGExpression
*n
) : MNGExpressionContainer(n
) { }
169 std::string
dump() { return std::string("TempoDelay(") + subnode
->dump() + ")"; }
172 class MNGFadeInNode
: public MNGExpressionContainer
{ // fadein
174 MNGFadeInNode(MNGExpression
*n
) : MNGExpressionContainer(n
) { }
175 std::string
dump() { return std::string("FadeIn(") + subnode
->dump() + ")"; }
178 class MNGFadeOutNode
: public MNGExpressionContainer
{ // fadeout
180 MNGFadeOutNode(MNGExpression
*n
) : MNGExpressionContainer(n
) { }
181 std::string
dump() { return std::string("FadeOut(") + subnode
->dump() + ")"; }
184 class MNGBeatLengthNode
: public MNGExpressionContainer
{ // beatlength
186 MNGBeatLengthNode(MNGExpression
*n
) : MNGExpressionContainer(n
) { }
187 std::string
dump() { return std::string("BeatLength(") + subnode
->dump() + ")"; }
190 class MNGLayer
: public MNGNamedNode
{
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
) {
198 for (std::list
<MNGNode
*>::iterator i
= children
->begin(); i
!= children
->end(); i
++)
199 (*i
)->postProcess(s
);
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
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
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
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
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
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
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
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
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
261 MNGBeatSynchNode(MNGExpression
*n
) : MNGExpressionContainer(n
) { }
262 std::string
dump() { return std::string("BeatSynch(") + subnode
->dump() + ")"; }
265 class MNGUpdateRateNode
: public MNGExpressionContainer
{ // updaterate
267 MNGUpdateRateNode(MNGExpression
*n
) : MNGExpressionContainer(n
) { }
268 std::string
dump() { return std::string("UpdateRate(") + subnode
->dump() + ")"; }
271 class MNGIntervalNode
: public MNGExpressionContainer
{ // interval
273 MNGIntervalNode(MNGExpression
*n
) : MNGExpressionContainer(n
) { }
274 std::string
dump() { return std::string("Interval(") + subnode
->dump() + ")"; }
277 class MNGVariableDecNode
: public MNGNamedNode
{
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
295 variabletypes variabletype
;
296 MNGVariableDecNode
*real
;
299 class MNGLayer
*layer
;
300 class MNGVoiceNode
*voice
;
301 class MNGStageNode
*stage
;
302 class MNGTrackDecNode
*track
;
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
) {
312 // TODO: make sure variables[name] exists, if not, look up globally
313 real
= s
->layer
->variables
[name
];
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
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
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
336 throw creaturesException("wah, unknown variabletype in variable node"); // TODO
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
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
365 MNGVariableNode
*variable
;
366 MNGExpression
*expression
;
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";
382 class MNGConditionNode
: public MNGNode
{ // condition
384 MNGVariableNode
*variable
;
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
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
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
; }
417 int numsamples
, scriptoffset
, scriptlength
, scriptend
;
419 unsigned int sampleno
;
422 std::map
<std::string
, class MNGVariableDecNode
*> variables
; // TODO: should be private?
423 MNGFile(std::string
);
424 void enumerateSamples();
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
;
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
;
450 extern MNGFile
*g_mngfile
;
452 class MNGWaveNode
: public MNGNamedNode
{ // wave
454 std::pair
<char *, int> *sample
;
457 MNGWaveNode(std::string n
) : MNGNamedNode(n
) { sample
= g_mngfile
->getNextSample(); }
458 std::string
dump() { return std::string("Wave(") + name
+ ")"; }