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)
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):
790 gtk.Alignment.__init__(self, 0.5, 0.5, 0, 0)
791 self.output_channel = output_channel
797 mute = gtk.ToggleButton()
799 #mute.set_active(self.channel.mute)
800 #mute.connect("toggled", self.on_mute_toggled)
801 hbox.pack_start(mute, False)
803 solo = gtk.ToggleButton()
806 #solo.set_active(self.channel.solo)
807 #solo.connect("toggled", self.on_solo_toggled)
808 if self.output_channel.display_solo_buttons:
809 hbox.pack_start(solo, True)
811 mute.modify_bg(gtk.STATE_PRELIGHT, output_channel.color_tuple[0])
812 mute.modify_bg(gtk.STATE_NORMAL, output_channel.color_tuple[1])
813 mute.modify_bg(gtk.STATE_ACTIVE, output_channel.color_tuple[2])
814 solo.modify_bg(gtk.STATE_PRELIGHT, output_channel.color_tuple[0])
815 solo.modify_bg(gtk.STATE_NORMAL, output_channel.color_tuple[1])
816 solo.modify_bg(gtk.STATE_ACTIVE, output_channel.color_tuple[2])
819 if self.output_channel.display_solo_buttons:
820 if not self.solo in self.hbox.get_children():
821 self.hbox.pack_start(self.solo, True)
824 if self.solo in self.hbox.get_children():
825 self.hbox.remove(self.solo)