3 # This file is part of jack_mixer
5 # Copyright (C) 2006 Nedko Arnaudov <nedko@arnaudov.name>
7 # This program is free software; you can redistribute it and/or modify
8 # it under the terms of the GNU General Public License as published by
9 # the Free Software Foundation; version 2 of the License
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software
18 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
29 from serialization
import serialized_object
34 print "PHAT audio widgets not found, some features will not be available"
39 class channel(gtk
.VBox
, serialized_object
):
40 '''Widget with slider and meter used as base class for more specific channel widgets'''
41 def __init__(self
, app
, name
, stereo
):
42 gtk
.VBox
.__init
__(self
)
44 self
.mixer
= app
.mixer
45 self
.gui_factory
= app
.gui_factory
46 self
._channel
_name
= name
48 self
.meter_scale
= self
.gui_factory
.get_default_meter_scale()
49 self
.slider_scale
= self
.gui_factory
.get_default_slider_scale()
50 self
.slider_adjustment
= slider
.adjustment_dBFS(self
.slider_scale
, 0.0)
51 self
.balance_adjustment
= gtk
.Adjustment(0.0, -1.0, 1.0, 0.02)
52 self
.future_volume_midi_cc
= None
53 self
.future_balance_midi_cc
= None
55 def get_channel_name(self
):
56 return self
._channel
_name
60 def set_channel_name(self
, name
):
61 self
._channel
_name
= name
63 self
.label_name
.set_text(name
)
65 self
.channel
.name
= name
66 channel_name
= property(get_channel_name
, set_channel_name
)
69 #print "Realizing channel \"%s\"" % self.channel_name
71 self
.slider_adjustment
.connect("volume-changed", self
.on_volume_changed
)
72 self
.balance_adjustment
.connect("value-changed", self
.on_balance_changed
)
73 self
.connect('midi-event-received', self
.on_midi_event_received
)
76 self
.create_slider_widget()
79 self
.meter
= meter
.stereo(self
.meter_scale
)
81 self
.meter
= meter
.mono(self
.meter_scale
)
82 self
.on_vumeter_color_changed(self
.gui_factory
)
84 self
.meter
.set_events(gtk
.gdk
.SCROLL_MASK
)
86 self
.gui_factory
.connect("default-meter-scale-changed", self
.on_default_meter_scale_changed
)
87 self
.gui_factory
.connect("default-slider-scale-changed", self
.on_default_slider_scale_changed
)
88 self
.gui_factory
.connect('vumeter-color-changed', self
.on_vumeter_color_changed
)
89 self
.gui_factory
.connect('vumeter-color-scheme-changed', self
.on_vumeter_color_changed
)
90 self
.gui_factory
.connect('use-custom-widgets-changed', self
.on_custom_widgets_changed
)
92 self
.abspeak
= abspeak
.widget()
93 self
.abspeak
.connect("reset", self
.on_abspeak_reset
)
94 self
.abspeak
.connect("volume-adjust", self
.on_abspeak_adjust
)
96 self
.volume_digits
= gtk
.Entry()
97 self
.volume_digits
.connect("key-press-event", self
.on_volume_digits_key_pressed
)
98 self
.volume_digits
.connect("focus-out-event", self
.on_volume_digits_focus_out
)
100 self
.connect("key-press-event", self
.on_key_pressed
)
101 self
.connect("scroll-event", self
.on_scroll
)
104 #print "Unrealizing channel \"%s\"" % self.channel_name
107 def create_balance_widget(self
):
108 if self
.gui_factory
.use_custom_widgets
and phat
:
109 self
.balance
= phat
.HFanSlider()
110 self
.balance
.set_default_value(0)
111 self
.balance
.set_adjustment(self
.balance_adjustment
)
113 self
.balance
= gtk
.HScale(self
.balance_adjustment
)
114 self
.balance
.set_draw_value(False)
115 self
.pack_start(self
.balance
, False)
118 def create_slider_widget(self
):
121 parent
= self
.slider
.get_parent()
122 self
.slider
.destroy()
123 if self
.gui_factory
.use_custom_widgets
:
124 self
.slider
= slider
.CustomSliderWidget(self
.slider_adjustment
)
126 self
.slider
= slider
.GtkSlider(self
.slider_adjustment
)
128 parent
.pack_start(self
.slider
)
129 parent
.reorder_child(self
.slider
, 0)
132 def on_default_meter_scale_changed(self
, gui_factory
, scale
):
133 #print "Default meter scale change detected."
134 self
.meter
.set_scale(scale
)
136 def on_default_slider_scale_changed(self
, gui_factory
, scale
):
137 #print "Default slider scale change detected."
138 self
.slider_scale
= scale
139 self
.slider_adjustment
.set_scale(scale
)
140 self
.channel
.set_midi_scale(self
.slider_scale
.scale
)
142 def on_vumeter_color_changed(self
, gui_factory
, *args
):
143 color
= gui_factory
.get_vumeter_color()
144 color_scheme
= gui_factory
.get_vumeter_color_scheme()
145 if color_scheme
!= 'solid':
146 self
.meter
.set_color(None)
148 self
.meter
.set_color(gtk
.gdk
.color_parse(color
))
150 def on_custom_widgets_changed(self
, gui_factory
, value
):
151 self
.balance
.destroy()
152 self
.create_balance_widget()
153 self
.create_slider_widget()
155 def on_abspeak_adjust(self
, abspeak
, adjust
):
156 #print "abspeak adjust %f" % adjust
157 self
.slider_adjustment
.set_value_db(self
.slider_adjustment
.get_value_db() + adjust
)
158 self
.channel
.abspeak
= None
159 #self.update_volume(False) # We want to update gui even if actual decibels have not changed (scale wrap for example)
161 def on_abspeak_reset(self
, abspeak
):
162 #print "abspeak reset"
163 self
.channel
.abspeak
= None
165 def on_volume_digits_key_pressed(self
, widget
, event
):
166 if (event
.keyval
== gtk
.keysyms
.Return
or event
.keyval
== gtk
.keysyms
.KP_Enter
):
167 db_text
= self
.volume_digits
.get_text()
170 #print "Volume digits confirmation \"%f dBFS\"" % db
171 except (ValueError), e
:
172 #print "Volume digits confirmation ignore, reset to current"
173 self
.update_volume(False)
175 self
.slider_adjustment
.set_value_db(db
)
177 #self.update_volume(False) # We want to update gui even if actual decibels have not changed (scale wrap for example)
179 def on_volume_digits_focus_out(self
, widget
, event
):
180 #print "volume digits focus out detected"
181 self
.update_volume(False)
183 def read_meter(self
):
185 meter_left
, meter_right
= self
.channel
.meter
186 self
.meter
.set_values(meter_left
, meter_right
)
188 self
.meter
.set_value(self
.channel
.meter
[0])
190 self
.abspeak
.set_peak(self
.channel
.abspeak
)
192 def on_scroll(self
, widget
, event
):
193 if event
.direction
== gtk
.gdk
.SCROLL_DOWN
:
194 self
.slider_adjustment
.step_down()
195 elif event
.direction
== gtk
.gdk
.SCROLL_UP
:
196 self
.slider_adjustment
.step_up()
199 def update_volume(self
, update_engine
):
200 db
= self
.slider_adjustment
.get_value_db()
202 db_text
= "%.2f" % db
203 self
.volume_digits
.set_text(db_text
)
206 #print "Setting engine volume to " + db_text
207 self
.channel
.volume
= db
209 def on_volume_changed(self
, adjustment
):
210 self
.update_volume(True)
212 def on_balance_changed(self
, adjustment
):
213 balance
= self
.balance_adjustment
.get_value()
214 #print "%s balance: %f" % (self.channel_name, balance)
215 self
.channel
.balance
= balance
217 def on_key_pressed(self
, widget
, event
):
218 if (event
.keyval
== gtk
.keysyms
.Up
):
219 #print self.channel_name + " Up"
220 self
.slider_adjustment
.step_up()
222 elif (event
.keyval
== gtk
.keysyms
.Down
):
223 #print self.channel_name + " Down"
224 self
.slider_adjustment
.step_down()
229 def serialize(self
, object_backend
):
230 object_backend
.add_property("volume", "%f" % self
.slider_adjustment
.get_value_db())
231 object_backend
.add_property("balance", "%f" % self
.balance_adjustment
.get_value())
233 if self
.channel
.volume_midi_cc
:
234 object_backend
.add_property('volume_midi_cc', str(self
.channel
.volume_midi_cc
))
235 if self
.channel
.balance_midi_cc
:
236 object_backend
.add_property('balance_midi_cc', str(self
.channel
.balance_midi_cc
))
238 def unserialize_property(self
, name
, value
):
240 self
.slider_adjustment
.set_value_db(float(value
))
242 if name
== "balance":
243 self
.balance_adjustment
.set_value(float(value
))
245 if name
== 'volume_midi_cc':
246 self
.future_volume_midi_cc
= int(value
)
248 if name
== 'balance_midi_cc':
249 self
.future_balance_midi_cc
= int(value
)
253 def on_midi_event_received(self
, *args
):
254 self
.slider_adjustment
.set_value_db(self
.channel
.volume
)
255 self
.balance_adjustment
.set_value(self
.channel
.balance
)
257 def midi_change_callback(self
, *args
):
258 # the changes are not applied directly to the widgets as they
259 # absolutely have to be done from the gtk thread.
260 self
.emit('midi-event-received')
262 gobject
.signal_new('midi-event-received', channel
,
263 gobject
.SIGNAL_RUN_FIRST | gobject
.SIGNAL_ACTION
,
264 gobject
.TYPE_NONE
, ())
266 class input_channel(channel
):
267 def __init__(self
, app
, name
, stereo
):
268 channel
.__init
__(self
, app
, name
, stereo
)
271 self
.channel
= self
.mixer
.add_channel(self
.channel_name
, self
.stereo
)
272 if self
.channel
== None:
273 raise Exception,"Cannot create a channel"
274 channel
.realize(self
)
275 if self
.future_volume_midi_cc
:
276 self
.channel
.volume_midi_cc
= self
.future_volume_midi_cc
277 if self
.future_balance_midi_cc
:
278 self
.channel
.balance_midi_cc
= self
.future_balance_midi_cc
279 self
.channel
.midi_scale
= self
.slider_scale
.scale
280 self
.channel
.midi_change_callback
= self
.midi_change_callback
282 self
.on_volume_changed(self
.slider_adjustment
)
283 self
.on_balance_changed(self
.balance_adjustment
)
285 # vbox child at upper part
286 self
.vbox
= gtk
.VBox()
287 self
.pack_start(self
.vbox
, False)
288 self
.label_name
= gtk
.Label()
289 self
.label_name
.set_text(self
.channel_name
)
290 self
.label_name
.set_size_request(0, -1)
291 self
.label_name_event_box
= gtk
.EventBox()
292 self
.label_name_event_box
.connect("button-press-event", self
.on_label_mouse
)
293 self
.label_name_event_box
.add(self
.label_name
)
294 self
.vbox
.pack_start(self
.label_name_event_box
, True)
295 # self.label_stereo = gtk.Label()
297 # self.label_stereo.set_text("stereo")
299 # self.label_stereo.set_text("mono")
300 # self.label_stereo.set_size_request(0, -1)
301 # self.vbox.pack_start(self.label_stereo, True)
303 # hbox for mute and solo buttons
304 self
.hbox_mutesolo
= gtk
.HBox()
306 self
.mute
= gtk
.ToggleButton()
307 self
.mute
.set_label("M")
308 self
.mute
.set_active(self
.channel
.mute
)
309 self
.mute
.connect("toggled", self
.on_mute_toggled
)
310 self
.hbox_mutesolo
.pack_start(self
.mute
, True)
312 self
.solo
= gtk
.ToggleButton()
313 self
.solo
.set_label("S")
314 self
.solo
.set_active(self
.channel
.solo
)
315 self
.solo
.connect("toggled", self
.on_solo_toggled
)
316 self
.hbox_mutesolo
.pack_start(self
.solo
, True)
318 self
.vbox
.pack_start(self
.hbox_mutesolo
, False)
321 frame
.set_shadow_type(gtk
.SHADOW_IN
)
322 frame
.add(self
.abspeak
);
323 self
.pack_start(frame
, False)
325 # hbox child at lower part
326 self
.hbox
= gtk
.HBox()
327 self
.hbox
.pack_start(self
.slider
, True)
329 frame
.set_shadow_type(gtk
.SHADOW_IN
)
330 frame
.add(self
.meter
);
331 self
.hbox
.pack_start(frame
, True)
333 frame
.set_shadow_type(gtk
.SHADOW_IN
)
334 frame
.add(self
.hbox
);
335 self
.pack_start(frame
, True)
337 self
.volume_digits
.set_size_request(0, -1)
338 self
.pack_start(self
.volume_digits
, False)
340 self
.create_balance_widget()
342 def add_control_group(self
, channel
):
343 control_group
= ControlGroup(channel
, self
)
344 control_group
.show_all()
345 self
.vbox
.pack_start(control_group
, False)
347 def update_control_group(self
, channel
):
348 for control_group
in self
.vbox
.get_children():
349 if isinstance(control_group
, ControlGroup
):
350 if control_group
.output_channel
is channel
:
351 control_group
.update()
354 channel
.unrealize(self
)
355 self
.channel
.remove()
358 channel_properties_dialog
= None
359 def on_channel_properties(self
):
360 if not self
.channel_properties_dialog
:
361 self
.channel_properties_dialog
= ChannelPropertiesDialog(self
)
362 self
.channel_properties_dialog
.show()
363 self
.channel_properties_dialog
.present()
365 def on_label_mouse(self
, widget
, event
):
366 if event
.type == gtk
.gdk
._2BUTTON
_PRESS
:
367 if event
.button
== 1:
368 self
.on_channel_properties()
370 def on_mute_toggled(self
, button
):
371 self
.channel
.mute
= self
.mute
.get_active()
373 def on_solo_toggled(self
, button
):
374 self
.channel
.solo
= self
.solo
.get_active()
376 def serialization_name(self
):
377 return input_channel_serialization_name()
379 def serialize(self
, object_backend
):
380 object_backend
.add_property("name", self
.channel_name
)
382 object_backend
.add_property("type", "stereo")
384 object_backend
.add_property("type", "mono")
385 channel
.serialize(self
, object_backend
)
387 def unserialize_property(self
, name
, value
):
389 self
.channel_name
= str(value
)
392 if value
== "stereo":
398 return channel
.unserialize_property(self
, name
, value
)
400 def input_channel_serialization_name():
401 return "input_channel"
404 available_colours
= [
405 ('#ef2929', '#cc0000', '#a40000'),
406 ('#729fcf', '#3465a4', '#204a87'),
407 ('#8aa234', '#73d216', '#4e9a06'),
408 ('#fce84f', '#edd400', '#c4a000'),
409 ('#fcaf3e', '#f57900', '#ce5c00'),
410 ('#e9b96e', '#c17d11', '#8f5902'),
411 ('#ad7fa8', '#75507b', '#5c3566'),
414 class output_channel(channel
):
415 colours
= available_colours
[:]
416 _display_solo_buttons
= False
418 def __init__(self
, app
, name
, stereo
):
419 channel
.__init
__(self
, app
, name
, stereo
)
421 def get_display_solo_buttons(self
):
422 return self
._display
_solo
_buttons
424 def set_display_solo_buttons(self
, value
):
425 self
._display
_solo
_buttons
= value
426 # notifying control groups
427 for inputchannel
in self
.app
.channels
:
428 inputchannel
.update_control_group(self
)
430 display_solo_buttons
= property(get_display_solo_buttons
, set_display_solo_buttons
)
433 channel
.realize(self
)
434 self
.channel
= self
.mixer
.add_output_channel(self
.channel_name
, self
.stereo
)
435 if self
.channel
== None:
436 raise Exception,"Cannot create a channel"
437 channel
.realize(self
)
439 self
.channel
.midi_scale
= self
.slider_scale
.scale
440 self
.channel
.midi_change_callback
= self
.midi_change_callback
442 self
.on_volume_changed(self
.slider_adjustment
)
443 self
.on_balance_changed(self
.balance_adjustment
)
445 # vbox child at upper part
446 self
.vbox
= gtk
.VBox()
447 self
.pack_start(self
.vbox
, False)
448 self
.label_name
= gtk
.Label()
449 self
.label_name
.set_text(self
.channel_name
)
450 self
.label_name
.set_size_request(0, -1)
451 self
.label_name_event_box
= gtk
.EventBox()
452 self
.label_name_event_box
.connect('button-press-event', self
.on_label_mouse
)
453 self
.label_name_event_box
.add(self
.label_name
)
455 self
.colours
= available_colours
[:]
456 for color
in self
.colours
:
457 self
.color_tuple
= [gtk
.gdk
.color_parse(color
[x
]) for x
in range(3)]
458 self
.colours
.remove(color
)
460 self
.label_name_event_box
.modify_bg(gtk
.STATE_NORMAL
, self
.color_tuple
[1])
461 self
.vbox
.pack_start(self
.label_name_event_box
, True)
463 frame
.set_shadow_type(gtk
.SHADOW_IN
)
464 frame
.add(self
.abspeak
);
465 self
.vbox
.pack_start(frame
, False)
467 # hbox child at lower part
468 self
.hbox
= gtk
.HBox()
469 self
.hbox
.pack_start(self
.slider
, True)
471 frame
.set_shadow_type(gtk
.SHADOW_IN
)
472 frame
.add(self
.meter
);
473 self
.hbox
.pack_start(frame
, True)
475 frame
.set_shadow_type(gtk
.SHADOW_IN
)
476 frame
.add(self
.hbox
);
477 self
.pack_start(frame
, True)
479 self
.volume_digits
.set_size_request(0, -1)
480 self
.pack_start(self
.volume_digits
, False)
482 self
.create_balance_widget()
484 channel_properties_dialog
= None
485 def on_channel_properties(self
):
486 if not self
.channel_properties_dialog
:
487 self
.channel_properties_dialog
= OutputChannelPropertiesDialog(self
)
488 self
.channel_properties_dialog
.show()
489 self
.channel_properties_dialog
.present()
491 def on_label_mouse(self
, widget
, event
):
492 if event
.type == gtk
.gdk
._2BUTTON
_PRESS
:
493 if event
.button
== 1:
494 self
.on_channel_properties()
497 channel
.unrealize(self
)
500 def serialization_name(self
):
501 return output_channel_serialization_name()
503 def serialize(self
, object_backend
):
504 object_backend
.add_property("name", self
.channel_name
)
506 object_backend
.add_property("type", "stereo")
508 object_backend
.add_property("type", "mono")
509 if self
.display_solo_buttons
:
510 object_backend
.add_property("solo_buttons", "true")
511 channel
.serialize(self
, object_backend
)
513 def unserialize_property(self
, name
, value
):
515 self
.channel_name
= str(value
)
518 if value
== "stereo":
524 if name
== "solo_buttons":
526 self
.display_solo_buttons
= True
527 return channel
.unserialize_property(self
, name
, value
)
529 def output_channel_serialization_name():
530 return "output_channel"
532 class main_mix(channel
):
533 def __init__(self
, app
):
534 channel
.__init
__(self
, app
, "MAIN", True)
537 channel
.realize(self
)
538 self
.channel
= self
.mixer
.main_mix_channel
539 self
.channel
.midi_scale
= self
.slider_scale
.scale
540 self
.channel
.midi_change_callback
= self
.midi_change_callback
542 self
.on_volume_changed(self
.slider_adjustment
)
543 self
.on_balance_changed(self
.balance_adjustment
)
545 # vbox child at upper part
546 self
.vbox
= gtk
.VBox()
547 self
.pack_start(self
.vbox
, False)
548 self
.label_name
= gtk
.Label()
549 self
.label_name
.set_text(self
.channel_name
)
550 self
.label_name
.set_size_request(0, -1)
551 self
.vbox
.pack_start(self
.label_name
, False)
553 frame
.set_shadow_type(gtk
.SHADOW_IN
)
554 frame
.add(self
.abspeak
);
555 self
.vbox
.pack_start(frame
, False)
557 # hbox child at lower part
558 self
.hbox
= gtk
.HBox()
559 self
.hbox
.pack_start(self
.slider
, True)
561 frame
.set_shadow_type(gtk
.SHADOW_IN
)
562 frame
.add(self
.meter
);
563 self
.hbox
.pack_start(frame
, True)
565 frame
.set_shadow_type(gtk
.SHADOW_IN
)
566 frame
.add(self
.hbox
);
567 self
.pack_start(frame
, True)
569 self
.volume_digits
.set_size_request(0, -1)
570 self
.pack_start(self
.volume_digits
, False)
572 self
.create_balance_widget()
575 channel
.unrealize(self
)
578 def serialization_name(self
):
579 return main_mix_serialization_name()
581 def main_mix_serialization_name():
582 return "main_mix_channel"
585 class ChannelPropertiesDialog(gtk
.Dialog
):
586 def __init__(self
, parent
):
587 self
.channel
= parent
588 self
.mixer
= self
.channel
.mixer
589 gtk
.Dialog
.__init
__(self
,
590 'Channel "%s" Properties' % self
.channel
.channel_name
,
591 self
.channel
.gui_factory
.topwindow
)
593 self
.add_button(gtk
.STOCK_CANCEL
, gtk
.RESPONSE_CANCEL
)
594 self
.ok_button
= self
.add_button(gtk
.STOCK_APPLY
, gtk
.RESPONSE_APPLY
)
599 self
.connect('response', self
.on_response_cb
)
600 self
.connect('delete-event', self
.on_response_cb
)
602 def create_frame(self
, label
, child
):
603 frame
= gtk
.Frame('')
604 frame
.set_border_width(3)
605 #frame.set_shadow_type(gtk.SHADOW_NONE)
606 frame
.get_label_widget().set_markup('<b>%s</b>' % label
)
608 alignment
= gtk
.Alignment(0, 0, 1, 1)
609 alignment
.set_padding(0, 0, 12, 0)
619 table
= gtk
.Table(2, 2, False)
620 vbox
.pack_start(self
.create_frame('Properties', table
))
621 table
.set_row_spacings(5)
622 table
.set_col_spacings(5)
624 table
.attach(gtk
.Label('Name'), 0, 1, 0, 1)
625 self
.entry_name
= gtk
.Entry()
626 self
.entry_name
.set_activates_default(True)
627 self
.entry_name
.connect('changed', self
.on_entry_name_changed
)
628 table
.attach(self
.entry_name
, 1, 2, 0, 1)
630 table
.attach(gtk
.Label('Mode'), 0, 1, 1, 2)
631 self
.mode_hbox
= gtk
.HBox()
632 table
.attach(self
.mode_hbox
, 1, 2, 1, 2)
633 self
.mono
= gtk
.RadioButton(label
='Mono')
634 self
.stereo
= gtk
.RadioButton(label
='Stereo', group
=self
.mono
)
635 self
.mode_hbox
.pack_start(self
.mono
)
636 self
.mode_hbox
.pack_start(self
.stereo
)
638 table
= gtk
.Table(2, 3, False)
639 vbox
.pack_start(self
.create_frame('MIDI Control Channels', table
))
640 table
.set_row_spacings(5)
641 table
.set_col_spacings(5)
643 table
.attach(gtk
.Label('Volume'), 0, 1, 0, 1)
644 self
.entry_volume_cc
= gtk
.Entry()
645 self
.entry_volume_cc
.set_activates_default(True)
646 self
.entry_volume_cc
.set_editable(False)
647 self
.entry_volume_cc
.set_width_chars(3)
648 table
.attach(self
.entry_volume_cc
, 1, 2, 0, 1)
649 self
.button_sense_midi_volume
= gtk
.Button('Autoset')
650 self
.button_sense_midi_volume
.connect('clicked',
651 self
.on_sense_midi_volume_clicked
)
652 table
.attach(self
.button_sense_midi_volume
, 2, 3, 0, 1)
654 table
.attach(gtk
.Label('Balance'), 0, 1, 1, 2)
655 self
.entry_balance_cc
= gtk
.Entry()
656 self
.entry_balance_cc
.set_activates_default(True)
657 self
.entry_balance_cc
.set_width_chars(3)
658 self
.entry_balance_cc
.set_editable(False)
659 table
.attach(self
.entry_balance_cc
, 1, 2, 1, 2)
660 self
.button_sense_midi_balance
= gtk
.Button('Autoset')
661 self
.button_sense_midi_balance
.connect('clicked',
662 self
.on_sense_midi_balance_clicked
)
663 table
.attach(self
.button_sense_midi_balance
, 2, 3, 1, 2)
668 self
.entry_name
.set_text(self
.channel
.channel_name
)
669 if self
.channel
.channel
.is_stereo
:
670 self
.stereo
.set_active(True)
672 self
.mono
.set_active(True)
673 self
.mode_hbox
.set_sensitive(False)
674 self
.entry_volume_cc
.set_text('%s' % self
.channel
.channel
.volume_midi_cc
)
675 self
.entry_balance_cc
.set_text('%s' % self
.channel
.channel
.balance_midi_cc
)
677 def sense_popup_dialog(self
, entry
):
678 window
= gtk
.Window(gtk
.WINDOW_TOPLEVEL
)
679 window
.set_destroy_with_parent(True)
680 window
.set_transient_for(self
)
681 window
.set_decorated(False)
682 window
.set_modal(True)
683 window
.set_position(gtk
.WIN_POS_CENTER_ON_PARENT
)
684 window
.set_border_width(10)
689 vbox
.pack_start(gtk
.Label('Please move the MIDI control you want to use for this function.'))
690 timeout_label
= gtk
.Label('This window will close in 5 seconds')
691 vbox
.pack_start(timeout_label
)
692 def close_sense_timeout(window
, entry
):
694 timeout_label
.set_text('This window will close in %d seconds.' % window
.timeout
)
695 if window
.timeout
== 0:
697 entry
.set_text('%s' % self
.mixer
.last_midi_channel
)
701 glib
.timeout_add_seconds(1, close_sense_timeout
, window
, entry
)
703 def on_sense_midi_volume_clicked(self
, *args
):
704 self
.sense_popup_dialog(self
.entry_volume_cc
)
706 def on_sense_midi_balance_clicked(self
, *args
):
707 self
.sense_popup_dialog(self
.entry_balance_cc
)
709 def on_response_cb(self
, dlg
, response_id
, *args
):
710 self
.channel
.channel_properties_dialog
= None
712 if response_id
== gtk
.RESPONSE_APPLY
:
713 name
= self
.entry_name
.get_text()
714 self
.channel
.channel_name
= name
715 self
.channel
.channel
.volume_midi_cc
= int(self
.entry_volume_cc
.get_text())
716 self
.channel
.channel
.balance_midi_cc
= int(self
.entry_balance_cc
.get_text())
718 def on_entry_name_changed(self
, entry
):
719 self
.ok_button
.set_sensitive(len(entry
.get_text()))
721 class NewChannelDialog(ChannelPropertiesDialog
):
722 def __init__(self
, parent
, mixer
):
723 gtk
.Dialog
.__init
__(self
, 'New Channel', parent
)
727 self
.stereo
.set_active(True) # default to stereo
729 self
.add_button(gtk
.STOCK_CANCEL
, gtk
.RESPONSE_CANCEL
)
730 self
.ok_button
= self
.add_button(gtk
.STOCK_ADD
, gtk
.RESPONSE_OK
)
731 self
.ok_button
.set_sensitive(False)
732 self
.set_default_response(gtk
.RESPONSE_OK
);
734 def get_result(self
):
735 return {'name': self
.entry_name
.get_text(),
736 'stereo': self
.stereo
.get_active(),
737 'volume_cc': self
.entry_volume_cc
.get_text(),
738 'balance_cc': self
.entry_balance_cc
.get_text()
741 class OutputChannelPropertiesDialog(ChannelPropertiesDialog
):
743 ChannelPropertiesDialog
.create_ui(self
)
746 self
.vbox
.pack_start(self
.create_frame('Input Channels', vbox
))
748 self
.display_solo_buttons
= gtk
.CheckButton('Display solo buttons')
749 vbox
.pack_start(self
.display_solo_buttons
)
754 ChannelPropertiesDialog
.fill_ui(self
)
755 self
.display_solo_buttons
.set_active(self
.channel
.display_solo_buttons
)
757 def on_response_cb(self
, dlg
, response_id
, *args
):
758 ChannelPropertiesDialog
.on_response_cb(self
, dlg
, response_id
, *args
)
759 if response_id
== gtk
.RESPONSE_APPLY
:
760 self
.channel
.display_solo_buttons
= self
.display_solo_buttons
.get_active()
763 class NewOutputChannelDialog(OutputChannelPropertiesDialog
):
764 def __init__(self
, parent
, mixer
):
765 gtk
.Dialog
.__init
__(self
, 'New Output Channel', parent
)
769 # TODO: disable mode for output channels as mono output channels may
770 # not be correctly handled yet.
771 self
.mode_hbox
.set_sensitive(False)
772 self
.stereo
.set_active(True) # default to stereo
774 self
.add_button(gtk
.STOCK_CANCEL
, gtk
.RESPONSE_CANCEL
)
775 self
.ok_button
= self
.add_button(gtk
.STOCK_ADD
, gtk
.RESPONSE_OK
)
776 self
.ok_button
.set_sensitive(False)
777 self
.set_default_response(gtk
.RESPONSE_OK
);
779 def get_result(self
):
780 return {'name': self
.entry_name
.get_text(),
781 'stereo': self
.stereo
.get_active(),
782 'volume_cc': self
.entry_volume_cc
.get_text(),
783 'balance_cc': self
.entry_balance_cc
.get_text(),
784 'display_solo_buttons': self
.display_solo_buttons
.get_active(),
788 class ControlGroup(gtk
.Alignment
):
789 def __init__(self
, output_channel
, input_channel
):
790 gtk
.Alignment
.__init
__(self
, 0.5, 0.5, 0, 0)
791 self
.output_channel
= output_channel
792 self
.input_channel
= input_channel
798 mute
= gtk
.ToggleButton()
800 #mute.set_active(self.channel.mute)
801 mute
.connect("toggled", self
.on_mute_toggled
)
802 hbox
.pack_start(mute
, False)
804 solo
= gtk
.ToggleButton()
807 #solo.set_active(self.channel.solo)
808 solo
.connect("toggled", self
.on_solo_toggled
)
809 if self
.output_channel
.display_solo_buttons
:
810 hbox
.pack_start(solo
, True)
812 mute
.modify_bg(gtk
.STATE_PRELIGHT
, output_channel
.color_tuple
[0])
813 mute
.modify_bg(gtk
.STATE_NORMAL
, output_channel
.color_tuple
[1])
814 mute
.modify_bg(gtk
.STATE_ACTIVE
, output_channel
.color_tuple
[2])
815 solo
.modify_bg(gtk
.STATE_PRELIGHT
, output_channel
.color_tuple
[0])
816 solo
.modify_bg(gtk
.STATE_NORMAL
, output_channel
.color_tuple
[1])
817 solo
.modify_bg(gtk
.STATE_ACTIVE
, output_channel
.color_tuple
[2])
820 if self
.output_channel
.display_solo_buttons
:
821 if not self
.solo
in self
.hbox
.get_children():
822 self
.hbox
.pack_start(self
.solo
, True)
825 if self
.solo
in self
.hbox
.get_children():
826 self
.hbox
.remove(self
.solo
)
828 def on_mute_toggled(self
, button
):
829 self
.output_channel
.channel
.set_muted(self
.input_channel
.channel
, button
.get_active())
831 def on_solo_toggled(self
, button
):
832 self
.output_channel
.channel
.set_solo(self
.input_channel
.channel
, button
.get_active())