2 from gui_tools
import *
4 class StreamWindow(Gtk
.VBox
):
5 def __init__(self
, instrument
, iobj
):
6 Gtk
.Widget
.__init
__(self
)
7 self
.engine
= iobj
.engine
8 self
.path
= self
.engine
.path
10 panel
= Gtk
.VBox(spacing
=5)
12 self
.filebutton
= Gtk
.FileChooserButton("Streamed file")
13 self
.filebutton
.set_action(Gtk
.FileChooserAction
.OPEN
)
14 self
.filebutton
.set_local_only(True)
15 self
.filebutton
.set_filename(self
.engine
.status().filename
)
16 self
.filebutton
.add_filter(standard_filter(["*.wav", "*.WAV", "*.ogg", "*.OGG", "*.flac", "*.FLAC"], "All loadable audio files"))
17 self
.filebutton
.add_filter(standard_filter(["*.wav", "*.WAV"], "RIFF WAVE files"))
18 self
.filebutton
.add_filter(standard_filter(["*.ogg", "*.OGG"], "OGG container files"))
19 self
.filebutton
.add_filter(standard_filter(["*.flac", "*.FLAC"], "FLAC files"))
20 self
.filebutton
.add_filter(standard_filter(["*"], "All files"))
21 self
.filebutton
.connect('file-set', self
.file_set
)
22 hpanel
= Gtk
.HBox(spacing
= 5)
23 hpanel
.pack_start(Gtk
.Label
.new_with_mnemonic("_Play file:"), False, False, 5)
24 hpanel
.pack_start(self
.filebutton
, True, True, 5)
25 panel
.pack_start(hpanel
, False, False, 5)
27 self
.adjustment
= Gtk
.Adjustment()
28 self
.adjustment_handler
= self
.adjustment
.connect('value-changed', self
.pos_slider_moved
)
29 self
.progress
= standard_hslider(self
.adjustment
)
30 panel
.pack_start(self
.progress
, False, False, 5)
32 self
.play_button
= Gtk
.Button
.new_with_mnemonic("_Play")
33 self
.rewind_button
= Gtk
.Button
.new_with_mnemonic("_Rewind")
34 self
.stop_button
= Gtk
.Button
.new_with_mnemonic("_Stop")
35 buttons
= Gtk
.HBox(spacing
= 5)
36 buttons
.add(self
.play_button
)
37 buttons
.add(self
.rewind_button
)
38 buttons
.add(self
.stop_button
)
39 panel
.pack_start(buttons
, False, False, 5)
42 self
.play_button
.connect('clicked', lambda x
: self
.engine
.play())
43 self
.rewind_button
.connect('clicked', lambda x
: self
.engine
.seek(0))
44 self
.stop_button
.connect('clicked', lambda x
: self
.engine
.stop())
45 set_timer(self
, 30, self
.update
)
48 attribs
= cbox
.GetThings("%s/status" % self
.path
, ['filename', 'pos', 'length', 'playing'], [])
49 self
.progress
.set_sensitive(attribs
.length
is not None)
50 if attribs
.length
is not None:
52 self
.adjustment
.handler_block(self
.adjustment_handler
)
53 self
.adjustment
.set_properties(value
= attribs
.pos
, lower
= 0, upper
= attribs
.length
)
54 #self.adjustment.set_all(attribs.pos, 0, attribs.length, 44100, 44100 * 10, 0)
56 self
.adjustment
.handler_unblock(self
.adjustment_handler
)
59 def pos_slider_moved(self
, adjustment
):
60 self
.engine
.seek(adjustment
.get_value())
62 def file_set(self
, button
):
63 self
.engine
.load(button
.get_filename())
67 def __init__(self
, attribs
):
68 self
.patches
= Gtk
.ListStore(GObject
.TYPE_STRING
, GObject
.TYPE_INT
)
69 self
.patch_combos
= []
71 self
.table
= Gtk
.Table(2, 16)
72 self
.table
.set_col_spacings(5)
75 self
.table
.attach(bold_label("Channel %s" % (1 + i
)), 0, 1, i
, i
+ 1, Gtk
.AttachOptions
.SHRINK
, Gtk
.AttachOptions
.SHRINK
)
76 cb
= standard_combo(self
.patches
, None)
77 cb
.connect('changed', self
.patch_combo_changed
, i
+ 1)
78 self
.table
.attach(cb
, 1, 2, i
, i
+ 1, Gtk
.AttachOptions
.SHRINK
, Gtk
.AttachOptions
.SHRINK
)
79 self
.patch_combos
.append(cb
)
82 set_timer(self
, 500, self
.patch_combo_update
)
84 def update_model(self
):
86 patches
= self
.engine
.get_patches()
87 ch_patches
= self
.engine
.status().patches
90 self
.mapping
[id] = len(self
.mapping
)
91 self
.patches
.append((self
.fmt_patch_name(patches
[id], id), id))
92 self
.patch_combo_update()
94 def patch_combo_changed(self
, combo
, channel
):
95 if combo
.get_active() == -1:
97 self
.engine
.set_patch(channel
, self
.patches
[combo
.get_active()][1])
99 def patch_combo_update(self
):
100 patch
= self
.engine
.status().patches
102 cb
= self
.patch_combos
[i
]
103 old_patch_index
= cb
.get_active() if cb
.get_active() >= 0 else -1
104 patch_id
= patch
[i
+ 1][0]
105 current_patch_index
= self
.mapping
[patch_id
] if (patch_id
>= 0 and patch_id
in self
.mapping
) else -1
106 if old_patch_index
!= current_patch_index
:
107 cb
.set_active(current_patch_index
)
108 #self.status_label.set_markup(s)
111 def fmt_patch_name(self
, patch
, id):
112 return "%s (%s)" % (patch
, id)
114 class FluidsynthWindow(Gtk
.VBox
, WithPatchTable
):
115 def __init__(self
, instrument
, iobj
):
116 Gtk
.VBox
.__init
__(self
)
117 self
.engine
= iobj
.engine
118 self
.path
= self
.engine
.path
121 attribs
= iobj
.status()
123 panel
= Gtk
.VBox(spacing
=5)
124 table
= Gtk
.Table(2, 1)
125 IntSliderRow("Polyphony", "polyphony", 2, 256).add_row(table
, 0, cbox
.VarPath(self
.path
), attribs
)
127 WithPatchTable
.__init
__(self
, attribs
)
128 panel
.pack_start(standard_vscroll_window(-1, 160, self
.table
), True, True, 5)
130 hpanel
= Gtk
.HBox(spacing
= 5)
131 self
.filebutton
= Gtk
.FileChooserButton("Soundfont")
132 self
.filebutton
.set_action(Gtk
.FileChooserAction
.OPEN
)
133 self
.filebutton
.set_local_only(True)
134 self
.filebutton
.set_filename(cbox
.GetThings("%s/status" % self
.path
, ['soundfont'], []).soundfont
)
135 self
.filebutton
.add_filter(standard_filter(["*.sf2", "*.SF2"], "SF2 Soundfonts"))
136 self
.filebutton
.add_filter(standard_filter(["*"], "All files"))
137 hpanel
.pack_start(Gtk
.Label
.new_with_mnemonic("_Load SF2:"), False, False, 5)
138 hpanel
.pack_start(self
.filebutton
, True, True, 5)
139 unload
= Gtk
.Button
.new_with_mnemonic("_Unload")
140 hpanel
.pack_start(unload
, False, False, 5)
141 unload
.connect('clicked', self
.unload
)
142 panel
.pack_start(hpanel
, False, False, 5)
144 self
.filebutton
.connect('file-set', self
.file_set
)
147 def file_set(self
, button
):
148 self
.engine
.load_soundfont(button
.get_filename())
150 def unload(self
, button
):
151 self
.filebutton
.set_filename('')
153 class LoadProgramDialog(SelectObjectDialog
):
154 title
= "Load a sampler program"
155 def __init__(self
, parent
):
156 SelectObjectDialog
.__init
__(self
, parent
)
157 def update_model(self
, model
):
158 for s
in cbox
.Config
.sections("spgm:"):
161 model
.append((s
.name
[5:], "Program", s
.name
, title
))
163 model
.append((s
.name
[5:], "SFZ", s
.name
, title
))
165 class SamplerWindow(Gtk
.VBox
, WithPatchTable
):
166 def __init__(self
, instrument
, iobj
):
167 Gtk
.VBox
.__init
__(self
)
168 self
.engine
= iobj
.engine
169 self
.path
= self
.engine
.path
171 attribs
= self
.engine
.status()
173 panel
= Gtk
.VBox(spacing
=5)
174 table
= Gtk
.Table(2, 2)
175 table
.set_col_spacings(5)
176 IntSliderRow("Polyphony", "polyphony", 1, 128).add_row(table
, 0, cbox
.VarPath(self
.path
), attribs
)
177 self
.voices_widget
= add_display_row(table
, 1, "Voices in use", cbox
.VarPath(self
.path
), attribs
, "active_voices")
178 panel
.pack_start(table
, False, False, 5)
180 WithPatchTable
.__init
__(self
, attribs
)
181 panel
.pack_start(standard_vscroll_window(-1, 160, self
.table
), True, True, 5)
183 hpanel
= Gtk
.HBox(spacing
= 5)
185 hpanel
.pack_start(Gtk
.Label
.new_with_mnemonic("Add from _SFZ:"), False, False, 5)
186 self
.filebutton
= Gtk
.FileChooserButton("Soundfont")
187 self
.filebutton
.set_action(Gtk
.FileChooserAction
.OPEN
)
188 self
.filebutton
.set_local_only(True)
189 #self.filebutton.set_filename(cbox.GetThings("%s/status" % self.path, ['soundfont'], []).soundfont)
190 self
.filebutton
.add_filter(standard_filter(["*.sfz", "*.SFZ"], "SFZ Programs"))
191 self
.filebutton
.add_filter(standard_filter(["*"], "All files"))
192 self
.filebutton
.connect('file-set', self
.load_sfz
)
193 hpanel
.pack_start(self
.filebutton
, False, True, 5)
195 load_button
= Gtk
.Button
.new_with_mnemonic("Add from _config")
196 load_button
.connect('clicked', self
.load_config
)
197 hpanel
.pack_start(load_button
, False, True, 5)
198 panel
.pack_start(hpanel
, False, False, 5)
200 set_timer(self
, 200, self
.voices_update
)
201 self
.polyphony_labels
= {}
203 button
= Gtk
.Button("Dump SFZ")
204 button
.connect("clicked", self
.dump_sfz
, i
+ 1)
205 self
.table
.attach(button
, 2, 3, i
, i
+ 1, Gtk
.AttachOptions
.SHRINK
, Gtk
.AttachOptions
.SHRINK
)
206 label
= Gtk
.Label("")
207 self
.table
.attach(label
, 3, 4, i
, i
+ 1, Gtk
.AttachOptions
.SHRINK
, Gtk
.AttachOptions
.SHRINK
)
208 self
.polyphony_labels
[i
+ 1] = label
210 def dump_sfz(self
, w
, channel
):
211 attribs
= cbox
.GetThings("%s/status" % self
.path
, ['%patch', 'polyphony', 'active_voices'], [])
212 prog_no
, patch_name
= attribs
.patch
[channel
]
213 pname
, uuid
, in_use_cnt
= cbox
.GetThings("%s/patches" % self
.path
, ['%patch'], []).patch
[prog_no
]
214 print ("UUID=%s" % uuid
)
215 patch
= cbox
.Document
.map_uuid(uuid
)
216 groups
= patch
.get_groups()
217 for r
in groups
[0].get_children():
218 print ("<region> %s" % (r
.as_string()))
219 for grp
in patch
.get_groups()[1:]:
220 print ("<group> %s" % (grp
.as_string()))
221 for r
in grp
.get_children():
222 print ("<region> %s" % (r
.as_string()))
224 def load_config(self
, event
):
225 d
= LoadProgramDialog(self
.get_toplevel())
228 if response
== Gtk
.ResponseType
.OK
:
229 scene
= d
.get_selected_object()
230 pgm_id
= self
.engine
.get_unused_program()
231 self
.engine
.load_patch_from_cfg(pgm_id
, scene
[2], scene
[2][5:])
236 def load_sfz(self
, button
):
237 pgm_id
= self
.engine
.get_unused_program()
238 self
.engine
.load_patch_from_file(pgm_id
, self
.filebutton
.get_filename(), self
.filebutton
.get_filename())
241 def voices_update(self
):
242 status
= self
.engine
.status()
243 self
.voices_widget
.set_text(str(status
.active_voices
))
245 self
.polyphony_labels
[i
+ 1].set_text("%d voices" % (status
.channel_voices
[i
+ 1],))
249 def fmt_patch_name(self
, patch
, id):
250 return "%s (%s)" % (patch
[0], id)
252 class TonewheelOrganWindow(Gtk
.VBox
):
254 (1, 'Upper', 'upper_vibrato', [(0, 'Off'), (1, 'On')]),
255 (1, 'Lower', 'lower_vibrato', [(0, 'Off'), (1, 'On')]),
256 (1, 'Mode', 'vibrato_mode', [(0, '1'), (1, '2'), (2, '3')]),
257 (1, 'Chorus', 'vibrato_chorus', [(0, 'Off'), (1, 'On')]),
258 (2, 'Enable', 'percussion_enable', [(0, 'Off'), (1, 'On')]),
259 (2, 'Harmonic', 'percussion_3rd', [(0, '2nd'), (1, '3rd')]),
261 def __init__(self
, instrument
, iobj
):
262 Gtk
.VBox
.__init
__(self
)
263 self
.engine
= iobj
.engine
264 self
.path
= self
.engine
.path
265 panel
= Gtk
.VBox(spacing
=10)
266 table
= Gtk
.Table(4, 10)
267 table
.props
.row_spacing
= 10
268 table
.set_col_spacings(5)
271 self
.hboxes
[1] = Gtk
.HBox(spacing
= 10)
272 self
.hboxes
[1].pack_start(Gtk
.Label('Vibrato: '), False, False, 5)
273 self
.hboxes
[2] = Gtk
.HBox(spacing
= 10)
274 self
.hboxes
[2].pack_start(Gtk
.Label('Percussion: '), False, False, 5)
276 for row
, name
, flag
, options
in TonewheelOrganWindow
.combos
:
277 label
= Gtk
.Label(name
)
278 self
.hboxes
[row
].pack_start(label
, False, False, 5)
279 model
= Gtk
.ListStore(GObject
.TYPE_INT
, GObject
.TYPE_STRING
)
280 for oval
, oname
in options
:
281 model
.append((oval
, oname
))
282 combo
= standard_combo(model
, column
= 1)
283 self
.hboxes
[row
].pack_start(combo
, False, False, 5)
284 combo
.update_handler
= combo
.connect('changed', lambda w
, setter
: setter(w
.get_model()[w
.get_active()][0]), getattr(self
.engine
, 'set_' + flag
))
285 self
.combos
[flag
] = combo
286 panel
.pack_start(self
.hboxes
[1], False, False, 5)
287 panel
.pack_start(self
.hboxes
[2], False, False, 5)
288 table
.attach(Gtk
.Label("Upper"), 0, 1, 0, 1)
289 table
.attach(Gtk
.Label("Lower"), 0, 1, 1, 2)
291 slider
= Gtk
.VScale(adjustment
= Gtk
.Adjustment(0, 0, 8, 1, 1))
292 slider
.props
.digits
= 0
293 table
.attach(slider
, i
+ 1, i
+ 2, 0, 1)
294 self
.drawbars
['u%d' % i
] = slider
.get_adjustment()
295 slider
.get_adjustment().connect('value-changed', lambda adj
, drawbar
: self
.engine
.set_upper_drawbar(drawbar
, int(adj
.get_value())), i
)
296 slider
= Gtk
.VScale(adjustment
= Gtk
.Adjustment(0, 0, 8, 1, 1))
297 slider
.props
.digits
= 0
298 table
.attach(slider
, i
+ 1, i
+ 2, 1, 2)
299 self
.drawbars
['l%d' % i
] = slider
.get_adjustment()
300 slider
.get_adjustment().connect('value-changed', lambda adj
, drawbar
: self
.engine
.set_lower_drawbar(drawbar
, int(adj
.get_value())), i
)
306 attribs
= self
.engine
.status()
308 self
.drawbars
['u%d' % i
].set_value(attribs
.upper_drawbar
[i
])
309 self
.drawbars
['l%d' % i
].set_value(attribs
.lower_drawbar
[i
])
310 for row
, name
, flag
, options
in TonewheelOrganWindow
.combos
:
311 combo
= self
.combos
[flag
]
312 combo
.handler_block(combo
.update_handler
)
313 combo
.set_active(ls_index(combo
.get_model(), getattr(attribs
, flag
), 0))
314 combo
.handler_unblock(combo
.update_handler
)
316 instrument_window_map
= {
317 'stream_player' : StreamWindow
,
318 'fluidsynth' : FluidsynthWindow
,
319 'sampler' : SamplerWindow
,
320 'tonewheel_organ' : TonewheelOrganWindow