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.
28 from serialization
import serialized_object
33 print "PHAT audio widgets not found, some features will not be available"
38 class channel(gtk
.VBox
, serialized_object
):
39 '''Widget with slider and meter used as base class for more specific channel widgets'''
40 def __init__(self
, gui_factory
, name
, stereo
):
41 gtk
.VBox
.__init
__(self
)
42 self
.gui_factory
= gui_factory
43 self
.channel_name
= name
45 self
.meter_scale
= gui_factory
.get_default_meter_scale()
46 self
.slider_scale
= gui_factory
.get_default_slider_scale()
47 self
.slider_adjustment
= slider
.adjustment_dBFS(self
.slider_scale
, 0.0)
48 self
.balance_adjustment
= gtk
.Adjustment(0.0, -1.0, 1.0, 0.02)
51 #print "Realizing channel \"%s\"" % self.channel_name
53 self
.slider_adjustment
.connect("volume-changed", self
.on_volume_changed
)
54 self
.balance_adjustment
.connect("value-changed", self
.on_balance_changed
)
56 self
.slider
= slider
.widget(self
.slider_adjustment
)
59 self
.meter
= meter
.stereo(self
.meter_scale
)
61 self
.meter
= meter
.mono(self
.meter_scale
)
63 self
.meter
.set_events(gtk
.gdk
.SCROLL_MASK
)
65 self
.gui_factory
.connect("default-meter-scale-changed", self
.on_default_meter_scale_changed
)
66 self
.gui_factory
.connect("default-slider-scale-changed", self
.on_default_slider_scale_changed
)
68 self
.abspeak
= abspeak
.widget()
69 self
.abspeak
.connect("reset", self
.on_abspeak_reset
)
70 self
.abspeak
.connect("volume-adjust", self
.on_abspeak_adjust
)
72 self
.volume_digits
= gtk
.Entry()
73 self
.volume_digits
.connect("key-press-event", self
.on_volume_digits_key_pressed
)
74 self
.volume_digits
.connect("focus-out-event", self
.on_volume_digits_focus_out
)
76 self
.connect("key-press-event", self
.on_key_pressed
)
77 self
.connect("scroll-event", self
.on_scroll
)
80 #print "Unrealizing channel \"%s\"" % self.channel_name
83 def on_default_meter_scale_changed(self
, gui_factory
, scale
):
84 #print "Default meter scale change detected."
85 self
.meter
.set_scale(scale
)
87 def on_default_slider_scale_changed(self
, gui_factory
, scale
):
88 #print "Default slider scale change detected."
89 self
.slider_adjustment
.set_scale(scale
)
91 def on_abspeak_adjust(self
, abspeak
, adjust
):
92 #print "abspeak adjust %f" % adjust
93 self
.slider_adjustment
.set_value_db(self
.slider_adjustment
.get_value_db() + adjust
)
94 jack_mixer_c
.channel_abspeak_reset(self
.channel
)
95 #self.update_volume(False) # We want to update gui even if actual decibels have not changed (scale wrap for example)
97 def on_abspeak_reset(self
, abspeak
):
98 #print "abspeak reset"
99 jack_mixer_c
.channel_abspeak_reset(self
.channel
)
101 def on_volume_digits_key_pressed(self
, widget
, event
):
102 if (event
.keyval
== gtk
.keysyms
.Return
or event
.keyval
== gtk
.keysyms
.KP_Enter
):
103 db_text
= self
.volume_digits
.get_text()
106 #print "Volume digits confirmation \"%f dBFS\"" % db
107 except (ValueError), e
:
108 #print "Volume digits confirmation ignore, reset to current"
109 self
.update_volume(False)
111 self
.slider_adjustment
.set_value_db(db
)
113 #self.update_volume(False) # We want to update gui even if actual decibels have not changed (scale wrap for example)
115 def on_volume_digits_focus_out(self
, widget
, event
):
116 #print "volume digits focus out detected"
117 self
.update_volume(False)
119 def read_meter(self
):
121 meter_left
, meter_right
= jack_mixer_c
.channel_stereo_meter_read(self
.channel
)
122 self
.meter
.set_values(meter_left
, meter_right
)
124 self
.meter
.set_value(jack_mixer_c
.channel_mono_meter_read(self
.channel
))
126 self
.abspeak
.set_peak(jack_mixer_c
.channel_abspeak_read(self
.channel
))
128 def on_scroll(self
, widget
, event
):
129 if event
.direction
== gtk
.gdk
.SCROLL_DOWN
:
130 self
.slider_adjustment
.step_down()
131 elif event
.direction
== gtk
.gdk
.SCROLL_UP
:
132 self
.slider_adjustment
.step_up()
135 def update_volume(self
, update_engine
):
136 db
= self
.slider_adjustment
.get_value_db()
138 db_text
= "%.2f" % db
139 self
.volume_digits
.set_text(db_text
)
142 #print "Setting engine volume to " + db_text
143 jack_mixer_c
.channel_volume_write(self
.channel
, db
)
145 def on_volume_changed(self
, adjustment
):
146 self
.update_volume(True)
148 def on_balance_changed(self
, adjustment
):
149 balance
= self
.balance_adjustment
.get_value()
150 #print "%s balance: %f" % (self.channel_name, balance)
151 jack_mixer_c
.channel_balance_write(self
.channel
, balance
)
153 def on_key_pressed(self
, widget
, event
):
154 if (event
.keyval
== gtk
.keysyms
.Up
):
155 #print self.channel_name + " Up"
156 self
.slider_adjustment
.step_up()
158 elif (event
.keyval
== gtk
.keysyms
.Down
):
159 #print self.channel_name + " Down"
160 self
.slider_adjustment
.step_down()
165 def serialize(self
, object_backend
):
166 object_backend
.add_property("volume", "%f" % self
.slider_adjustment
.get_value_db())
167 object_backend
.add_property("balance", "%f" % self
.balance_adjustment
.get_value())
169 def unserialize_property(self
, name
, value
):
171 self
.slider_adjustment
.set_value_db(float(value
))
173 if name
== "balance":
174 self
.balance_adjustment
.set_value(float(value
))
178 class input_channel(channel
):
179 def __init__(self
, gui_factory
, name
, stereo
):
180 channel
.__init
__(self
, gui_factory
, name
, stereo
)
183 channel
.realize(self
)
184 self
.channel
= jack_mixer_c
.add_channel(self
.channel_name
, self
.stereo
)
186 self
.on_volume_changed(self
.slider_adjustment
)
187 self
.on_balance_changed(self
.balance_adjustment
)
189 # vbox child at upper part
190 self
.vbox
= gtk
.VBox()
191 self
.pack_start(self
.vbox
, False)
192 self
.label_name
= gtk
.Label()
193 self
.label_name
.set_text(self
.channel_name
)
194 self
.label_name
.set_size_request(0, -1)
195 self
.label_name_event_box
= gtk
.EventBox()
196 self
.label_name_event_box
.connect("button-press-event", self
.on_label_mouse
)
197 self
.label_name_event_box
.add(self
.label_name
)
198 self
.vbox
.pack_start(self
.label_name_event_box
, True)
199 # self.label_stereo = gtk.Label()
201 # self.label_stereo.set_text("stereo")
203 # self.label_stereo.set_text("mono")
204 # self.label_stereo.set_size_request(0, -1)
205 # self.vbox.pack_start(self.label_stereo, True)
207 # hbox for mute and solo buttons
208 self
.hbox_mutesolo
= gtk
.HBox()
210 self
.mute
= gtk
.ToggleButton()
211 self
.mute
.set_label("M")
212 self
.mute
.set_active(jack_mixer_c
.channel_is_muted(self
.channel
))
213 self
.mute
.connect("toggled", self
.on_mute_toggled
)
214 self
.hbox_mutesolo
.pack_start(self
.mute
, True)
216 self
.solo
= gtk
.ToggleButton()
217 self
.solo
.set_label("S")
218 self
.solo
.set_active(jack_mixer_c
.channel_is_soloed(self
.channel
))
219 self
.solo
.connect("toggled", self
.on_solo_toggled
)
220 self
.hbox_mutesolo
.pack_start(self
.solo
, True)
222 self
.vbox
.pack_start(self
.hbox_mutesolo
, False)
225 frame
.set_shadow_type(gtk
.SHADOW_IN
)
226 frame
.add(self
.abspeak
);
227 self
.vbox
.pack_start(frame
, False)
229 # hbox child at lower part
230 self
.hbox
= gtk
.HBox()
231 self
.hbox
.pack_start(self
.slider
, True)
233 frame
.set_shadow_type(gtk
.SHADOW_IN
)
234 frame
.add(self
.meter
);
235 self
.hbox
.pack_start(frame
, True)
237 frame
.set_shadow_type(gtk
.SHADOW_IN
)
238 frame
.add(self
.hbox
);
239 self
.pack_start(frame
, True)
241 self
.volume_digits
.set_size_request(0, -1)
242 self
.pack_start(self
.volume_digits
, False)
245 self
.balance
= phat
.HFanSlider()
246 self
.balance
.set_default_value(0)
247 self
.balance
.set_adjustment(self
.balance_adjustment
)
248 self
.pack_start(self
.balance
, False)
251 channel
.unrealize(self
)
252 jack_mixer_c
.remove_channel(self
.channel
)
255 def on_rename_channel(self
):
256 result
= self
.gui_factory
.run_dialog_rename_channel(self
.channel_name
)
258 #print "renaming to \"%s\"" % result
259 self
.channel_name
= result
260 self
.label_name
.set_text(self
.channel_name
)
261 jack_mixer_c
.channel_rename(self
.channel
, self
.channel_name
)
263 def on_label_mouse(self
, widget
, event
):
264 if event
.type == gtk
.gdk
._2BUTTON
_PRESS
:
265 if event
.button
== 1:
266 self
.on_rename_channel()
268 def on_mute_toggled(self
, button
):
269 if self
.mute
.get_active():
271 jack_mixer_c
.channel_mute(self
.channel
)
274 jack_mixer_c
.channel_unmute(self
.channel
)
276 def on_solo_toggled(self
, button
):
277 if self
.solo
.get_active():
279 jack_mixer_c
.channel_solo(self
.channel
)
282 jack_mixer_c
.channel_unsolo(self
.channel
)
284 def serialization_name(self
):
285 return input_channel_serialization_name()
287 def serialize(self
, object_backend
):
288 object_backend
.add_property("name", self
.channel_name
)
290 object_backend
.add_property("type", "stereo")
292 object_backend
.add_property("type", "mono")
293 channel
.serialize(self
, object_backend
)
295 def unserialize_property(self
, name
, value
):
297 self
.channel_name
= str(value
)
300 if value
== "stereo":
306 return channel
.unserialize_property(self
, name
, value
)
308 def input_channel_serialization_name():
309 return "input_channel"
311 class main_mix(channel
):
312 def __init__(self
, gui_factory
):
313 channel
.__init
__(self
, gui_factory
, "MAIN", True)
316 channel
.realize(self
)
317 self
.channel
= jack_mixer_c
.get_main_mix_channel()
319 self
.on_volume_changed(self
.slider_adjustment
)
320 self
.on_balance_changed(self
.balance_adjustment
)
322 # vbox child at upper part
323 self
.vbox
= gtk
.VBox()
324 self
.pack_start(self
.vbox
, False)
325 self
.label_name
= gtk
.Label()
326 self
.label_name
.set_text(self
.channel_name
)
327 self
.label_name
.set_size_request(0, -1)
328 self
.vbox
.pack_start(self
.label_name
, False)
330 frame
.set_shadow_type(gtk
.SHADOW_IN
)
331 frame
.add(self
.abspeak
);
332 self
.vbox
.pack_start(frame
, False)
334 # hbox child at lower part
335 self
.hbox
= gtk
.HBox()
336 self
.hbox
.pack_start(self
.slider
, True)
338 frame
.set_shadow_type(gtk
.SHADOW_IN
)
339 frame
.add(self
.meter
);
340 self
.hbox
.pack_start(frame
, True)
342 frame
.set_shadow_type(gtk
.SHADOW_IN
)
343 frame
.add(self
.hbox
);
344 self
.pack_start(frame
, True)
346 self
.volume_digits
.set_size_request(0, -1)
347 self
.pack_start(self
.volume_digits
, False)
350 self
.balance
= phat
.HFanSlider()
351 self
.balance
.set_default_value(0)
352 self
.balance
.set_adjustment(self
.balance_adjustment
)
353 self
.pack_start(self
.balance
, False)
356 channel
.unrealize(self
)
359 def serialization_name(self
):
360 return main_mix_serialization_name()
362 def main_mix_serialization_name():
363 return "main_mix_channel"