]> git.0d.be Git - jack_mixer.git/blobdiff - channel.py
Set version to 14 in preparation for next release
[jack_mixer.git] / channel.py
index b4d5fa21dda523cd944081aba540af145972a6a8..f5a3c86739b7c8820f123fd2217f46b66088f5f1 100644 (file)
@@ -28,15 +28,10 @@ import meter
 import slider
 from serialization import SerializedObject
 
-try:
-    import phat
-except:
-    phat = None
-
 
 log = logging.getLogger(__name__)
 button_padding = 1
-css = b"""
+CSS = b"""
 .top_label {
     padding: 0px .1em;
     min-height: 1.5rem;
@@ -53,9 +48,21 @@ css = b"""
 button {
     padding: 0px
 }
+
+.vbox_fader {
+    border: 1px inset #111;
+}
+
+.readout {
+    font-size: 80%;
+    margin: .1em;
+    padding: 0;
+    border: 1px inset #111;
+    color: white;
+}
 """
 css_provider = Gtk.CssProvider()
-css_provider.load_from_data(css)
+css_provider.load_from_data(CSS)
 context = Gtk.StyleContext()
 screen = Gdk.Screen.get_default()
 context.add_provider_for_screen(screen, css_provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION)
@@ -102,10 +109,12 @@ def random_color():
 
 
 class Channel(Gtk.VBox, SerializedObject):
-    '''Widget with slider and meter used as base class for more specific
-       channel widgets'''
+    """Widget with slider and meter used as base class for more specific
+       channel widgets"""
+
     monitor_button = None
     num_instances = 0
+
     def __init__(self, app, name, stereo, value = None):
         Gtk.VBox.__init__(self)
         self.app = app
@@ -129,7 +138,7 @@ class Channel(Gtk.VBox, SerializedObject):
         self.label_name = None
         self.wide = True
         self.label_chars_wide = 12
-        self.label_chars_narrow = 8
+        self.label_chars_narrow = 7
         Channel.num_instances += 1
 
     def get_channel_name(self):
@@ -148,6 +157,63 @@ class Channel(Gtk.VBox, SerializedObject):
             self.post_fader_output_channel.name = "%s Out" % name;
     channel_name = property(get_channel_name, set_channel_name)
 
+    def create_balance_widget(self):
+        self.balance = slider.BalanceSlider(self.balance_adjustment, (20, 20), (0, 100))
+        self.balance.show()
+
+    def create_buttons(self):
+        # Mute, Solo and Monitor buttons
+        self.hbox_mutesolo = Gtk.Box(False, 0, orientation=Gtk.Orientation.HORIZONTAL)
+
+        self.mute = Gtk.ToggleButton()
+        self.mute.set_label("M")
+        self.mute.set_name("mute")
+        self.mute.set_active(self.channel.out_mute)
+        self.mute.connect("toggled", self.on_mute_toggled)
+        self.hbox_mutesolo.pack_start(self.mute, True, True, 0)
+
+        self.pack_start(self.hbox_mutesolo, False, False, 0)
+
+        self.monitor_button = Gtk.ToggleButton('MON')
+        self.monitor_button.connect('toggled', self.on_monitor_button_toggled)
+        self.pack_start(self.monitor_button, False, False, 0)
+
+    def create_fader(self):
+        # HBox for fader and meter
+        self.vbox_fader = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
+        self.vbox_fader.get_style_context().add_class('vbox_fader')
+
+        self.hbox_readouts = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL)
+        self.hbox_readouts.set_homogeneous(True)
+        self.hbox_readouts.pack_start(self.volume_digits, False, True, 0)
+        self.hbox_readouts.pack_start(self.abspeak, False, True, 0)
+        self.vbox_fader.pack_start(self.hbox_readouts, False, False, 0)
+
+        self.hbox_fader = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL)
+        self.hbox_fader.pack_start(self.slider, True, True, 0)
+        self.hbox_fader.pack_start(self.meter, True, True, 0)
+        self.vbox_fader.pack_start(self.hbox_fader, True, True, 0)
+        self.vbox_fader.pack_start(self.balance, False, True, 0)
+
+        self.pack_start(self.vbox_fader, True, True, 0)
+
+    def create_slider_widget(self):
+        parent = None
+        if self.slider:
+            parent = self.slider.get_parent()
+            self.slider.destroy()
+
+        if self.gui_factory.use_custom_widgets:
+            self.slider = slider.CustomSliderWidget(self.slider_adjustment)
+        else:
+            self.slider = slider.VolumeSlider(self.slider_adjustment)
+
+        if parent:
+            parent.pack_start(self.slider, True, True, 0)
+            parent.reorder_child(self.slider, 0)
+
+        self.slider.show()
+
     def realize(self):
         log.debug('Realizing channel "%s".', self.channel_name)
         if self.future_out_mute != None:
@@ -155,7 +221,7 @@ class Channel(Gtk.VBox, SerializedObject):
 
         # Widgets
         # Channel strip label
-        self.vbox = Gtk.VBox()
+        self.vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
         self.pack_start(self.vbox, False, True, 0)
         self.label_name = Gtk.Label()
         self.label_name.get_style_context().add_class('top_label')
@@ -170,17 +236,22 @@ class Channel(Gtk.VBox, SerializedObject):
         # Volume fader
         self.slider = None
         self.create_slider_widget()
+        self.create_balance_widget()
 
         # Volume entry
         self.volume_digits = Gtk.Entry()
+        self.volume_digits.set_has_frame(False)
+        self.volume_digits.set_width_chars(5)
         self.volume_digits.set_property('xalign', 0.5)
         self.volume_digits.connect("key-press-event", self.on_volume_digits_key_pressed)
         self.volume_digits.connect("focus-out-event", self.on_volume_digits_focus_out)
+        self.volume_digits.get_style_context().add_class('readout')
 
         # Peak level label
         self.abspeak = abspeak.AbspeakWidget()
         self.abspeak.connect("reset", self.on_abspeak_reset)
         self.abspeak.connect("volume-adjust", self.on_abspeak_adjust)
+        self.abspeak.get_style_context().add_class('readout')
 
         # Level meter
         if self.stereo:
@@ -212,61 +283,31 @@ class Channel(Gtk.VBox, SerializedObject):
 
     def unrealize(self):
         log.debug('Unrealizing channel "%s".', self.channel_name)
-        pass
 
-    def narrow(self):
-        self.wide = False
+    def widen(self, flag=True):
+        self.wide = flag
         ctx = self.label_name.get_style_context()
-        ctx.remove_class('wide')
-        ctx.add_class('narrow')
-        label = self.label_name.get_label()
-        self.label_name.set_max_width_chars(self.label_chars_narrow)
 
-        if len(label) > self.label_chars_narrow:
-            self.label_name.set_tooltip_text(label)
+        if flag:
+            ctx.remove_class('narrow')
+            ctx.add_class('wide')
+        else:
+            ctx.remove_class('wide')
+            ctx.add_class('narrow')
 
-    def widen(self):
-        self.wide = True
-        self.label_name.set_tooltip_text(None)
-        ctx = self.label_name.get_style_context()
-        ctx.remove_class('narrow')
-        ctx.add_class('wide')
         label = self.label_name.get_label()
-        self.label_name.set_max_width_chars(self.label_chars_wide)
+        label_width = self.label_chars_wide if flag else self.label_chars_narrow
+        self.label_name.set_max_width_chars(label_width)
 
-        if len(label) > self.label_chars_wide:
+        if len(label) > label_width:
             self.label_name.set_tooltip_text(label)
 
-    def balance_preferred_width(self):
-        return (20, 20)
+        self.meter.widen(flag)
+        self.hbox_readouts.set_orientation(
+            Gtk.Orientation.HORIZONTAL if flag else Gtk.Orientation.VERTICAL)
 
-    def _preferred_height(self):
-        return (0, 100)
-
-    def create_balance_widget(self):
-        if self.gui_factory.use_custom_widgets and phat:
-            self.balance = phat.HFanSlider()
-            self.balance.set_default_value(0)
-            self.balance.set_adjustment(self.balance_adjustment)
-        else:
-            self.balance = Gtk.Scale()
-            self.balance.get_preferred_width = self.balance_preferred_width
-            self.balance.get_preferred_height = self._preferred_height
-            self.balance.set_orientation(Gtk.Orientation.HORIZONTAL)
-            self.balance.set_adjustment(self.balance_adjustment)
-            self.balance.set_has_origin(False)
-            self.balance.set_draw_value(False)
-            self.balance.button_down = False
-            self.balance.connect('button-press-event', self.on_balance_button_press_event)
-            self.balance.connect('button-release-event', self.on_balance_button_release_event)
-            self.balance.connect("motion-notify-event", self.on_balance_motion_notify_event)
-            self.balance.connect("scroll-event", self.on_balance_scroll_event)
-
-
-        self.pack_start(self.balance, False, True, 0)
-        if self.monitor_button:
-            self.reorder_child(self.monitor_button, -1)
-        self.balance.show()
+    def narrow(self):
+        self.widen(False)
 
     def on_label_mouse(self, widget, event):
         if event.type == Gdk.EventType._2BUTTON_PRESS:
@@ -282,65 +323,6 @@ class Channel(Gtk.VBox, SerializedObject):
                 self.widen()
             return True
 
-    def on_balance_button_press_event(self, widget, event):
-        if event.button == 1 and event.type == Gdk.EventType.BUTTON_PRESS:
-            self.balance.button_down = True
-            self.balance.button_down_x = event.x
-            self.balance.button_down_value = self.balance.get_value()
-            return True
-        if event.button == 1 and event.type == Gdk.EventType._2BUTTON_PRESS:
-            self.balance_adjustment.set_balance(0)
-            return True
-        return False
-
-    def on_balance_button_release_event(self, widget, event):
-        self.balance.button_down = False
-        return False
-
-    def on_balance_motion_notify_event(self, widget, event):
-        slider_length = widget.get_allocation().width - widget.get_style_context().get_property('min-width', Gtk.StateFlags.NORMAL)
-        if self.balance.button_down:
-            delta_x = (event.x - self.balance.button_down_x) / slider_length
-            x = self.balance.button_down_value + 2 * delta_x
-            if x >= 1:
-                x = 1
-            elif x <= -1:
-                x = -1
-            self.balance_adjustment.set_balance(x)
-            return True
-
-    def on_balance_scroll_event(self, widget, event):
-        bal = self.balance
-        delta = bal.get_adjustment().get_step_increment()
-        value = bal.get_value()
-        if event.direction == Gdk.ScrollDirection.UP:
-            x = value - delta
-        elif event.direction == Gdk.ScrollDirection.DOWN:
-            x = value + delta
-        elif event.direction == Gdk.ScrollDirection.SMOOTH:
-            x = value - event.delta_y * delta
-
-        if x >= 1:
-            x = 1
-        elif x <= -1:
-            x = -1
-        bal.set_value(x)
-        return True
-
-    def create_slider_widget(self):
-        parent = None
-        if self.slider:
-            parent = self.slider.get_parent()
-            self.slider.destroy()
-        if self.gui_factory.use_custom_widgets:
-            self.slider = slider.CustomSliderWidget(self.slider_adjustment)
-        else:
-            self.slider = slider.GtkSlider(self.slider_adjustment)
-        if parent:
-            parent.pack_start(self.slider, True, True, 0)
-            parent.reorder_child(self.slider, 0)
-        self.slider.show()
-
     def on_default_meter_scale_changed(self, gui_factory, scale):
         log.debug("Default meter scale change detected.")
         self.meter.set_scale(scale)
@@ -463,7 +445,6 @@ class Channel(Gtk.VBox, SerializedObject):
         if self.channel.solo_midi_cc != -1:
             object_backend.add_property('solo_midi_cc', str(self.channel.solo_midi_cc))
 
-
     def unserialize_property(self, name, value):
         if name == "volume":
             self.slider_adjustment.set_value_db(float(value))
@@ -520,9 +501,19 @@ class Channel(Gtk.VBox, SerializedObject):
         self.color = color
         set_background_color(self.label_name_event_box, self.css_name, self.color)
 
+
 class InputChannel(Channel):
     post_fader_output_channel = None
 
+    def create_buttons(self):
+        super().create_buttons()
+        self.solo = Gtk.ToggleButton()
+        self.solo.set_label("S")
+        self.solo.set_name("solo")
+        self.solo.set_active(self.channel.solo)
+        self.solo.connect("toggled", self.on_solo_toggled)
+        self.hbox_mutesolo.pack_start(self.solo, True, True, 0)
+
     def realize(self):
         self.channel = self.mixer.add_channel(self.channel_name, self.stereo)
 
@@ -555,68 +546,28 @@ class InputChannel(Channel):
         self.connect_after("drag-data-received", self.on_drag_data_received)
 
         self.vbox.pack_start(self.label_name_event_box, True, True, 0)
-#         self.label_stereo = Gtk.Label()
-#         if self.stereo:
-#             self.label_stereo.set_text("stereo")
-#         else:
-#             self.label_stereo.set_text("mono")
-#         self.label_stereo.set_size_request(0, -1)
-#         self.vbox.pack_start(self.label_stereo, True)
-
-        frame = Gtk.Frame()
-        frame.set_shadow_type(Gtk.ShadowType.IN)
-        frame.add(self.abspeak);
-        self.pack_start(frame, False, True, 0)
-
-        # hbox child at lower part
-        self.hbox = Gtk.HBox()
-        self.hbox.pack_start(self.slider, True, True, 0)
-        frame = Gtk.Frame()
-        frame.set_shadow_type(Gtk.ShadowType.IN)
-        frame.add(self.meter);
-        self.hbox.pack_start(frame, True, True, 0)
-        frame = Gtk.Frame()
-        frame.set_shadow_type(Gtk.ShadowType.IN)
-        frame.add(self.hbox);
-        self.pack_start(frame, True, True, 0)
-
-        self.volume_digits.set_width_chars(6)
-        self.pack_start(self.volume_digits, False, False, 0)
-
-        self.create_balance_widget()
 
-        self.hbox_mutesolo = Gtk.Box(False, 0)
-
-        self.mute = Gtk.ToggleButton()
-        self.mute.set_label("M")
-        self.mute.set_name("mute")
-        self.mute.set_active(self.channel.out_mute)
-        self.mute.connect("toggled", self.on_mute_toggled)
-        self.hbox_mutesolo.pack_start(self.mute, True, True, 0)
-
-        self.solo = Gtk.ToggleButton()
-        self.solo.set_label("S")
-        self.solo.set_name("solo")
-        self.solo.set_active(self.channel.solo)
-        self.solo.connect("toggled", self.on_solo_toggled)
-        self.hbox_mutesolo.pack_start(self.solo, True, True, 0)
-
-        self.pack_start(self.hbox_mutesolo, False, False, 0)
-
-        self.monitor_button = Gtk.ToggleButton('MON')
-        self.monitor_button.connect('toggled', self.on_monitor_button_toggled)
-        self.pack_start(self.monitor_button, False, False, 0)
+        self.create_fader()
+        self.create_buttons()
 
         if not self.wide:
             self.narrow()
 
+    def unrealize(self):
+        super().unrealize()
+        if self.post_fader_output_channel:
+            self.post_fader_output_channel.remove()
+            self.post_fader_output_channel = None
+        self.channel.remove()
+        self.channel = None
+
     def narrow(self):
         super().narrow()
         for cg in self.get_control_groups():
             cg.narrow()
 
-    def widen(self):
-        super().widen()
+    def widen(self, flag=True):
+        super().widen(flag)
         for cg in self.get_control_groups():
             cg.widen()
 
@@ -647,7 +598,7 @@ class InputChannel(Channel):
                     control_group.update()
 
     def get_control_group(self, channel):
-        for control_group in self.get_control_groups:
+        for control_group in self.get_control_groups():
             if control_group.output_channel is channel:
                 return control_group
         return None
@@ -659,14 +610,6 @@ class InputChannel(Channel):
                 ctlgroups.append(c)
         return ctlgroups
 
-    def unrealize(self):
-        super().unrealize()
-        if self.post_fader_output_channel:
-            self.post_fader_output_channel.remove()
-            self.post_fader_output_channel = None
-        self.channel.remove()
-        self.channel = None
-
     channel_properties_dialog = None
 
     def on_channel_properties(self):
@@ -735,10 +678,12 @@ class InputChannel(Channel):
                 return True
         return super().unserialize_property(name, value)
 
+
 GObject.signal_new("input-channel-order-changed", InputChannel,
                 GObject.SignalFlags.RUN_FIRST | GObject.SignalFlags.ACTION,
                 None, [GObject.TYPE_STRING, GObject.TYPE_STRING])
 
+
 class OutputChannel(Channel):
     _display_solo_buttons = False
 
@@ -789,41 +734,9 @@ class OutputChannel(Channel):
             self.color = random_color()
         set_background_color(self.label_name_event_box, self.css_name, self.color)
         self.vbox.pack_start(self.label_name_event_box, True, True, 0)
-        frame = Gtk.Frame()
-        frame.set_shadow_type(Gtk.ShadowType.IN)
-        frame.add(self.abspeak);
-        self.vbox.pack_start(frame, False, True, 0)
-
-        # hbox child at lower part
-        self.hbox = Gtk.HBox()
-        self.hbox.pack_start(self.slider, True, True, 0)
-        frame = Gtk.Frame()
-        frame.set_shadow_type(Gtk.ShadowType.IN)
-        frame.add(self.meter);
-        self.hbox.pack_start(frame, True, True, 0)
-        frame = Gtk.Frame()
-        frame.set_shadow_type(Gtk.ShadowType.IN)
-        frame.add(self.hbox);
-        self.pack_start(frame, True, True, 0)
-
-        self.volume_digits.set_width_chars(6)
-        self.pack_start(self.volume_digits, False, True, 0)
 
-        self.create_balance_widget()
-
-        self.mute = Gtk.ToggleButton()
-        self.mute.set_label("M")
-        self.mute.set_name("mute")
-        self.mute.set_active(self.channel.out_mute)
-        self.mute.connect("toggled", self.on_mute_toggled)
-
-        hbox = Gtk.HBox()
-        hbox.pack_start(self.mute, True, True, 0)
-        self.pack_start(hbox, False, False, 0)
-
-        self.monitor_button = Gtk.ToggleButton('MON')
-        self.monitor_button.connect('toggled', self.on_monitor_button_toggled)
-        self.pack_start(self.monitor_button, False, False, 0)
+        self.create_fader()
+        self.create_buttons()
 
         # add control groups to the input channels, and initialize them
         # appropriately
@@ -845,6 +758,15 @@ class OutputChannel(Channel):
         if not self.wide:
             self.narrow()
 
+    def unrealize(self):
+        # remove control groups from input channels
+        for input_channel in self.app.channels:
+            input_channel.remove_control_group(self)
+        # then remove itself
+        super().unrealize()
+        self.channel.remove()
+        self.channel = None
+
     def on_drag_data_get(self, widget, drag_context, data, info, time):
         channel = widget.get_parent().get_parent()
         data.set(data.get_target(), 8, channel._channel_name.encode('utf-8'))
@@ -869,15 +791,6 @@ class OutputChannel(Channel):
             self.mute.set_active(self.channel.out_mute)
             super().on_midi_event_received()
 
-    def unrealize(self):
-        # remove control groups from input channels
-        for input_channel in self.app.channels:
-            input_channel.remove_control_group(self)
-        # then remove itself
-        super().unrealize()
-        self.channel.remove()
-        self.channel = None
-
     @classmethod
     def serialization_name(cls):
         return 'output_channel'
@@ -940,6 +853,7 @@ class OutputChannel(Channel):
             return True
         return super().unserialize_property(name, value)
 
+
 class ChannelPropertiesDialog(Gtk.Dialog):
     channel = None
 
@@ -1063,7 +977,8 @@ class ChannelPropertiesDialog(Gtk.Dialog):
             self.stereo.set_active(True)
         else:
             self.mono.set_active(True)
-        self.mode_hbox.set_sensitive(False)
+        self.mono.set_sensitive(False)
+        self.stereo.set_sensitive(False)
         self.entry_volume_cc.set_value(self.channel.channel.volume_midi_cc)
         self.entry_balance_cc.set_value(self.channel.channel.balance_midi_cc)
         self.entry_mute_cc.set_value(self.channel.channel.mute_midi_cc)
@@ -1079,7 +994,7 @@ class ChannelPropertiesDialog(Gtk.Dialog):
         window.set_position(Gtk.WindowPosition.CENTER_ON_PARENT)
         window.set_border_width(10)
 
-        vbox = Gtk.VBox(10)
+        vbox = Gtk.Box(10, orientation=Gtk.Orientation.VERTICAL)
         window.add(vbox)
         window.timeout = 5
         vbox.pack_start(Gtk.Label(label='Please move the MIDI control you want to use for this function.'), True, True, 0)
@@ -1136,6 +1051,7 @@ class ChannelPropertiesDialog(Gtk.Dialog):
                 sensitive = True
         self.ok_button.set_sensitive(sensitive)
 
+
 GObject.signal_new("output-channel-order-changed", OutputChannel,
                 GObject.SignalFlags.RUN_FIRST | GObject.SignalFlags.ACTION,
                 None, [GObject.TYPE_STRING, GObject.TYPE_STRING])
@@ -1283,10 +1199,10 @@ class ControlGroup(Gtk.Alignment):
         self.input_channel = input_channel
         self.app = input_channel.app
 
-        self.hbox = Gtk.HBox()
-        self.vbox = Gtk.VBox()
+        self.hbox = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL)
+        self.vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
         self.add(self.vbox)
-        self.buttons_box = Gtk.Box(False, button_padding)
+        self.buttons_box = Gtk.Box(False, button_padding, orientation=Gtk.Orientation.HORIZONTAL)
 
         set_background_color(self.vbox, output_channel.css_name, output_channel.color)