Implement a nicer version of str() for Python wrapper objects.
[calfbox.git] / test.py
blob5a7fddb6f49a0b88a63ed684ec61c899a07df0b8
1 import os
2 import sys
3 import struct
4 import time
5 import unittest
7 from calfbox import cbox
8 cbox.init_engine("")
9 cbox.start_noaudio(44100)
11 cbox.Config.add_section("drumpattern:pat1", """
12 title=Straight - Verse
13 beats=4
14 track1=bd
15 track2=sd
16 track3=hh
17 track4=ho
18 bd_note=c1
19 sd_note=d1
20 hh_note=f#1
21 ho_note=a#1
22 bd_trigger=9... .... 9.6. ....
23 sd_trigger=.... 9..5 .2.. 9...
24 hh_trigger=9353 7353 7353 73.3
25 ho_trigger=.... .... .... ..3.
26 """)
27 cbox.Config.add_section("fxpreset:piano_reverb", """
28 engine=reverb
29 """)
30 cbox.Config.add_section("instrument:vintage", """
31 engine=sampler
32 """)
34 global Document
35 Document = cbox.Document
37 Document.dump()
39 class TestCbox(unittest.TestCase):
40 def verify_uuid(self, uuid, class_name, path = None):
41 self.assertEqual(cbox.GetThings(Document.uuid_cmd(uuid, "/get_class_name"), ['class_name'], []).class_name, class_name)
42 if path is not None:
43 self.assertEqual(cbox.GetThings(path + "/status", ['uuid'], []).uuid, uuid)
44 self.assertEqual(cbox.GetThings(Document.uuid_cmd(uuid, "/status"), ['uuid'], []).uuid, uuid)
46 def test_scene(self):
47 scene = Document.get_scene()
49 scene.clear()
50 scene.add_new_instrument_layer("test_instr", "sampler")
52 scene_status = scene.status()
53 layer = scene_status.layers[0]
54 self.verify_uuid(scene.uuid, "cbox_scene", "/scene")
55 self.verify_uuid(layer.uuid, "cbox_layer", "/scene/layer/1")
57 layers = scene.status().layers
58 self.assertEqual(len(layers), 1)
59 self.assertEqual(layers[0].uuid, layer.uuid)
60 layers[0].set_consume(0)
61 self.assertEqual(layers[0].status().consume, 0)
62 layers[0].set_consume(1)
63 self.assertEqual(layers[0].status().consume, 1)
64 layers[0].set_enable(0)
65 self.assertEqual(layers[0].status().enable, 0)
66 layers[0].set_enable(1)
67 self.assertEqual(layers[0].status().enable, 1)
69 layer_status = layers[0].status()
70 instr_uuid = layer_status.instrument.uuid
71 iname = layer_status.instrument_name
72 self.assertEqual(iname, 'test_instr')
73 self.verify_uuid(instr_uuid, "cbox_instrument", "/scene/instr/%s" % iname)
75 aux = scene.load_aux("piano_reverb")
76 module = aux.slot.engine
77 self.verify_uuid(aux.uuid, "cbox_aux_bus", "/scene/aux/piano_reverb")
78 scene.delete_aux("piano_reverb")
80 def test_aux_scene(self):
81 scene = Document.new_scene(44100, 1024)
82 scene.add_instrument_layer("vintage")
83 scene_status = scene.status()
84 layer = scene_status.layers[0]
85 self.verify_uuid(scene.uuid, "cbox_scene")
86 self.verify_uuid(layer.uuid, "cbox_layer", scene.make_path("/layer/1"))
88 layers = scene.status().layers
89 self.assertEqual(len(layers), 1)
90 self.assertEqual(layers[0].uuid, layer.uuid)
91 layers[0].set_consume(0)
92 self.assertEqual(layers[0].status().consume, 0)
93 layers[0].set_consume(1)
94 self.assertEqual(layers[0].status().consume, 1)
95 layers[0].set_enable(0)
96 self.assertEqual(layers[0].status().enable, 0)
97 layers[0].set_enable(1)
98 self.assertEqual(layers[0].status().enable, 1)
100 layer_status = layers[0].status()
101 instr_uuid = layer_status.instrument.uuid
102 iname = layer_status.instrument_name
103 self.verify_uuid(instr_uuid, "cbox_instrument", scene.make_path("/instr/%s" % iname))
105 aux = scene.load_aux("piano_reverb")
106 module = aux.slot.engine
107 self.verify_uuid(aux.uuid, "cbox_aux_bus", scene.make_path("/aux/piano_reverb"))
108 scene.delete_aux("piano_reverb")
110 def test_sampler_api(self):
111 scene = Document.new_scene(44100, 1024)
112 scene.add_new_instrument_layer("temporary", "sampler")
113 scene_status = scene.status()
114 layer = scene_status.layers[0]
115 self.verify_uuid(scene.uuid, "cbox_scene")
116 self.verify_uuid(layer.uuid, "cbox_layer", scene.make_path("/layer/1"))
117 instrument = layer.get_instrument()
118 self.assertEqual(instrument.status().engine, "sampler")
120 instrument.engine.load_patch_from_string(0, '.', '<group> resonance=3 <region> unknown=123 key=36 sample=impulse.wav cutoff=1000 <region> key=37 sample=impulse.wav cutoff=2000', 'test_sampler_api')
121 patches = instrument.engine.get_patches()
122 patches_dict = {}
123 self.assertEqual(len(patches), 1)
124 for (patchid, patchdata) in patches.items():
125 patchname, program, patchchannelcount = patchdata
126 self.verify_uuid(program.uuid, 'sampler_program')
127 self.assertEqual(program.status().program_no, patchid)
128 self.assertEqual(program.status().name, 'test_sampler_api')
129 self.assertEqual(program.status().sample_dir, '.')
130 self.assertEqual(program.status().program_no, 0)
131 self.assertEqual(program.status().in_use, 0)
132 instrument.engine.set_patch(1, 0)
133 self.assertEqual(program.status().in_use, 1)
134 instrument.engine.set_patch(2, 0)
135 self.assertEqual(program.status().in_use, 2)
136 regions = program.get_regions()
137 patches_dict[patchid] = (patchname, len(regions))
138 for region in regions:
139 region_str = Document.map_uuid(region.uuid).as_string()
140 print (patchname, region.uuid, region_str)
141 if patchname == 'test_sampler_api':
142 self.assertTrue('impulse.wav' in region_str)
143 self.assertTrue('key=c' in region_str)
144 if 'key=c2' in region_str:
145 self.assertTrue('unknown=123' in region_str)
146 self.assertTrue('cutoff=1000' in region_str)
147 else:
148 self.assertFalse('unknown=123' in region_str)
149 self.assertTrue('cutoff=2000' in region_str)
150 program.add_control_init(11, 64)
151 self.assertTrue((11,64) in program.get_control_inits())
152 program.delete_control_init(11, 0)
153 program.add_control_init(11, 0)
154 program.add_control_init(11, 64)
155 self.assertTrue((11,0) in program.get_control_inits())
156 self.assertTrue((11,64) in program.get_control_inits())
157 program.delete_control_init(11, 0)
158 self.assertTrue((11,0) not in program.get_control_inits())
159 self.assertTrue((11,64) in program.get_control_inits())
160 program.delete_control_init(11, 0)
161 self.assertTrue((11,0) not in program.get_control_inits())
162 self.assertTrue((11,64) not in program.get_control_inits())
163 program.add_control_init(11, 0)
164 program.add_control_init(11, 64)
165 program.delete_control_init(11, -1)
166 self.assertTrue((11,0) not in program.get_control_inits())
167 self.assertTrue((11,64) not in program.get_control_inits())
168 self.assertEqual(patches_dict, {0 : ('test_sampler_api', 2)})
169 group = region.status().parent_group
170 self.assertTrue("resonance=3" in group.as_string())
171 region.set_param("cutoff", 9000)
172 self.assertTrue('cutoff=9000' in region.as_string())
173 region.set_param("sample", 'test.wav')
174 self.assertTrue('test.wav' in region.as_string())
175 region.set_param("key", '12')
176 self.assertTrue('key=c0' in region.as_string())
177 print (region.status())
178 print (group.as_string())
179 print (region.as_string())
181 def test_rt(self):
182 rt = Document.get_rt()
183 self.assertEqual(cbox.GetThings(Document.uuid_cmd(rt.uuid, "/status"), ['uuid'], []).uuid, rt.uuid)
185 def test_recorder_api(self):
186 scene = Document.get_scene()
187 scene.clear()
188 scene.add_new_instrument_layer("temporary", "sampler")
189 layer = scene.status().layers[0]
190 instr = layer.status().instrument
191 self.assertEqual(instr.get_things("/output/1/rec_dry/status", ['*handler']).handler, [])
193 meter_uuid = cbox.GetThings("/new_meter", ['uuid'], []).uuid
194 instr.cmd('/output/1/rec_dry/attach', None, meter_uuid)
195 self.assertEqual(instr.get_things("/output/1/rec_dry/status", ['*handler']).handler, [meter_uuid])
196 instr.cmd('/output/1/rec_dry/detach', None, meter_uuid)
197 self.assertEqual(instr.get_things("/output/1/rec_dry/status", ['*handler']).handler, [])
199 rec_uuid = cbox.GetThings("/new_recorder", ['uuid'], ['test.wav']).uuid
200 instr.cmd('/output/1/rec_dry/attach', None, rec_uuid)
201 self.assertEqual(instr.get_things("/output/1/rec_dry/status", ['*handler']).handler, [rec_uuid])
202 instr.cmd('/output/1/rec_dry/detach', None, rec_uuid)
203 self.assertEqual(instr.get_things("/output/1/rec_dry/status", ['*handler']).handler, [])
204 self.assertTrue(os.path.exists('test.wav'))
205 self.assertTrue(os.path.getsize('test.wav') < 512)
207 rec_uuid = cbox.GetThings("/new_recorder", ['uuid'], ['test.wav']).uuid
208 instr.cmd('/output/1/rec_dry/attach', None, rec_uuid)
209 self.assertEqual(instr.get_things("/output/1/rec_dry/status", ['*handler']).handler, [rec_uuid])
210 data = struct.unpack_from("512f", cbox.GetThings("/scene/render_stereo", ['data'], [512]).data)
211 instr.cmd('/output/1/rec_dry/detach', None, rec_uuid)
212 self.assertEqual(instr.get_things("/output/1/rec_dry/status", ['*handler']).handler, [])
213 self.assertTrue(os.path.exists('test.wav'))
214 self.assertTrue(os.path.getsize('test.wav') > 512 * 4 * 2)
216 def test_song(self):
217 song = Document.get_song()
218 song.clear()
219 tp = song.status()
220 self.assertEqual(tp.tracks, [])
221 self.assertEqual(tp.patterns, [])
222 self.assertEqual(tp.mtis, [])
224 track = song.add_track()
225 pattern = song.load_drum_pattern('pat1')
226 track.add_clip(0, 0, 192, pattern)
228 song = Document.get_song()
229 tp = song.status()
230 self.assertEqual(tp.tracks[0].name, 'Unnamed')
231 self.assertEqual(tp.patterns[0].name, 'pat1')
232 track = tp.tracks[0].track
233 pattern = tp.patterns[0].pattern
235 track.set_name("Now named")
236 self.assertEqual(track.status().name, 'Now named')
237 pattern.set_name("pat1alt")
238 self.assertEqual(pattern.status().name, 'pat1alt')
240 tp = song.status()
241 self.assertEqual(tp.tracks[0].name, 'Now named')
242 self.assertEqual(tp.patterns[0].name, 'pat1alt')
244 clips = track.status().clips
245 self.assertEqual(clips[0].pos, 0)
246 self.assertEqual(clips[0].offset, 0)
247 self.assertEqual(clips[0].length, 192)
248 self.assertEqual(clips[0].pattern, pattern)
249 clip1 = clips[0].clip
251 clip2 = track.add_clip(192, 96, 48, pattern)
253 clip2_data = clip2.status()
254 self.assertEqual(clip2_data.pos, 192)
255 self.assertEqual(clip2_data.offset, 96)
256 self.assertEqual(clip2_data.length, 48)
257 self.assertEqual(clip2_data.pattern, pattern)
259 clips = track.status().clips
260 self.assertEqual(clips, [cbox.ClipItem(0, 0, 192, pattern.uuid, clip1.uuid), cbox.ClipItem(192, 96, 48, pattern.uuid, clip2.uuid)])
262 clip1.delete()
264 clips = track.status().clips
265 self.assertEqual(clips, [cbox.ClipItem(192, 96, 48, pattern.uuid, clip2.uuid)])
267 def test_mti(self):
268 MtiItem = cbox.MtiItem
269 song = Document.get_song()
270 song.clear()
271 tp = song.status()
272 self.assertEqual(tp.tracks, [])
273 self.assertEqual(tp.patterns, [])
274 self.assertEqual(tp.mtis, [])
275 song.set_mti(0, 120.0)
276 self.assertEqual(song.status().mtis, [MtiItem(0, 120.0, 0, 0)])
277 song.set_mti(60, 150.0)
278 self.assertEqual(song.status().mtis, [MtiItem(0, 120.0, 0, 0), MtiItem(60, 150.0, 0, 0)])
279 song.set_mti(90, 180.0)
280 self.assertEqual(song.status().mtis, [MtiItem(0, 120.0, 0, 0), MtiItem(60, 150.0, 0, 0), MtiItem(90, 180.0, 0, 0)])
281 song.set_mti(60, 180.0)
282 self.assertEqual(song.status().mtis, [MtiItem(0, 120.0, 0, 0), MtiItem(60, 180.0, 0, 0), MtiItem(90, 180.0, 0, 0)])
283 song.set_mti(65, 210.0)
284 self.assertEqual(song.status().mtis, [MtiItem(0, 120.0, 0, 0), MtiItem(60, 180.0, 0, 0), MtiItem(65, 210.0, 0, 0), MtiItem(90, 180.0, 0, 0)])
286 song.set_mti(60, 0.0, 0, 0)
287 self.assertEqual(song.status().mtis, [MtiItem(0, 120.0, 0, 0), MtiItem(65, 210.0, 0, 0), MtiItem(90, 180.0, 0, 0)])
288 song.set_mti(65, 0.0, 0, 0)
289 self.assertEqual(song.status().mtis, [MtiItem(0, 120.0, 0, 0), MtiItem(90, 180.0, 0, 0)])
290 song.set_mti(68, 0.0, 0, 0)
291 self.assertEqual(song.status().mtis, [MtiItem(0, 120.0, 0, 0), MtiItem(90, 180.0, 0, 0)])
292 song.set_mti(0, 0.0, 0, 0)
293 self.assertEqual(song.status().mtis, [MtiItem(0, 0, 0, 0), MtiItem(90, 180.0, 0, 0)])
294 song.set_mti(90, 0.0, 0, 0)
295 self.assertEqual(song.status().mtis, [MtiItem(0, 0, 0, 0)])
297 def test_error(self):
298 thrown = False
299 try:
300 Document.get_scene().cmd('transpose', None, cbox)
301 except ValueError as ve:
302 self.assertTrue("class 'module'" in str(ve))
303 thrown = True
304 self.assertTrue(thrown)
306 unittest.main()
308 cbox.stop_audio()
309 cbox.shutdown_engine()