]> git.0d.be Git - jack_mixer.git/commitdiff
Allow manual setting of MIDI control change numbers (#8)
authorChristopher Arndt <SpotlightKid@users.noreply.github.com>
Thu, 25 Jun 2020 09:36:16 +0000 (11:36 +0200)
committerGitHub <noreply@github.com>
Thu, 25 Jun 2020 09:36:16 +0000 (04:36 -0500)
* Allow manual setting of MIDI control change numbers

* Changes controls for MIDI controllers in channel new / edit dialog to
  `Gtk.SpinButton`s with range (-1, 127).
* Adds tooltip to controls.
* Changes `Channel` object in C extension to add methods for auto-assigning
  the CC # for each control (volume, balance, mute, solo) individually.
* When editing channel, channel is only renamed when name actually
  changes.

* Fix updating of spinbutton in MIDI learn callback

Signed-off-by: Christopher Arndt <chris@chrisarndt.de>
channel.py
jack_mixer.c
jack_mixer.h
jack_mixer.py
jack_mixer_c.c

index ece791e8ce30e497699e07739ed7bf3561fb1108..8783ff46b20a0ef946c30e9d8ef787e3d2c7598e 100644 (file)
@@ -764,11 +764,10 @@ class ChannelPropertiesDialog(Gtk.Dialog):
         table.set_row_spacings(5)
         table.set_col_spacings(5)
 
+        cc_tooltip = "{} MIDI Control Change number (0-127, set to -1 to assign next free CC #)"
         table.attach(Gtk.Label(label='Volume'), 0, 1, 0, 1)
-        self.entry_volume_cc = Gtk.Entry()
-        self.entry_volume_cc.set_activates_default(True)
-        self.entry_volume_cc.set_editable(False)
-        self.entry_volume_cc.set_width_chars(3)
+        self.entry_volume_cc = Gtk.SpinButton.new_with_range(-1, 127, 1)
+        self.entry_volume_cc.set_tooltip_text(cc_tooltip.format("Volume"))
         table.attach(self.entry_volume_cc, 1, 2, 0, 1)
         self.button_sense_midi_volume = Gtk.Button('Autoset')
         self.button_sense_midi_volume.connect('clicked',
@@ -776,10 +775,8 @@ class ChannelPropertiesDialog(Gtk.Dialog):
         table.attach(self.button_sense_midi_volume, 2, 3, 0, 1)
 
         table.attach(Gtk.Label(label='Balance'), 0, 1, 1, 2)
-        self.entry_balance_cc = Gtk.Entry()
-        self.entry_balance_cc.set_activates_default(True)
-        self.entry_balance_cc.set_width_chars(3)
-        self.entry_balance_cc.set_editable(False)
+        self.entry_balance_cc = Gtk.SpinButton.new_with_range(-1, 127, 1)
+        self.entry_balance_cc.set_tooltip_text(cc_tooltip.format("Balance"))
         table.attach(self.entry_balance_cc, 1, 2, 1, 2)
         self.button_sense_midi_balance = Gtk.Button('Autoset')
         self.button_sense_midi_balance.connect('clicked',
@@ -787,10 +784,8 @@ class ChannelPropertiesDialog(Gtk.Dialog):
         table.attach(self.button_sense_midi_balance, 2, 3, 1, 2)
 
         table.attach(Gtk.Label(label='Mute'), 0, 1, 2, 3)
-        self.entry_mute_cc = Gtk.Entry()
-        self.entry_mute_cc.set_activates_default(True)
-        self.entry_mute_cc.set_editable(False)
-        self.entry_mute_cc.set_width_chars(3)
+        self.entry_mute_cc = Gtk.SpinButton.new_with_range(-1, 127, 1)
+        self.entry_mute_cc.set_tooltip_text(cc_tooltip.format("Mute"))
         table.attach(self.entry_mute_cc, 1, 2, 2, 3)
         self.button_sense_midi_mute = Gtk.Button('Autoset')
         self.button_sense_midi_mute.connect('clicked',
@@ -800,10 +795,8 @@ class ChannelPropertiesDialog(Gtk.Dialog):
         if (isinstance(self, NewChannelDialog) or (self.channel and
             isinstance(self.channel, InputChannel))):
             table.attach(Gtk.Label(label='Solo'), 0, 1, 3, 4)
-            self.entry_solo_cc = Gtk.Entry()
-            self.entry_solo_cc.set_activates_default(True)
-            self.entry_solo_cc.set_editable(False)
-            self.entry_solo_cc.set_width_chars(3)
+            self.entry_solo_cc = Gtk.SpinButton.new_with_range(-1, 127, 1)
+            self.entry_solo_cc.set_tooltip_text(cc_tooltip.format("Solo"))
             table.attach(self.entry_solo_cc, 1, 2, 3, 4)
             self.button_sense_midi_solo = Gtk.Button('Autoset')
             self.button_sense_midi_solo.connect('clicked',
@@ -819,11 +812,11 @@ class ChannelPropertiesDialog(Gtk.Dialog):
         else:
             self.mono.set_active(True)
         self.mode_hbox.set_sensitive(False)
-        self.entry_volume_cc.set_text('%s' % self.channel.channel.volume_midi_cc)
-        self.entry_balance_cc.set_text('%s' % self.channel.channel.balance_midi_cc)
-        self.entry_mute_cc.set_text('%s' % self.channel.channel.mute_midi_cc)
+        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)
         if (self.channel and isinstance(self.channel, InputChannel)):
-            self.entry_solo_cc.set_text('%s' % self.channel.channel.solo_midi_cc)
+            self.entry_solo_cc.set_value(self.channel.channel.solo_midi_cc)
 
     def sense_popup_dialog(self, entry):
         window = Gtk.Window.new(Gtk.WindowType.TOPLEVEL)
@@ -845,53 +838,40 @@ class ChannelPropertiesDialog(Gtk.Dialog):
             timeout_label.set_text('This window will close in %d seconds.' % window.timeout)
             if window.timeout == 0:
                 window.destroy()
-                entry.set_text('%s' % self.mixer.last_midi_channel)
+                entry.set_value(self.mixer.last_midi_channel)
                 return False
             return True
         window.show_all()
         GObject.timeout_add_seconds(1, close_sense_timeout, window, entry)
 
     def on_sense_midi_volume_clicked(self, *args):
-        self.mixer.last_midi_channel = int(self.entry_volume_cc.get_text())
+        self.mixer.last_midi_channel = int(self.entry_volume_cc.get_value())
         self.sense_popup_dialog(self.entry_volume_cc)
 
     def on_sense_midi_balance_clicked(self, *args):
-        self.mixer.last_midi_channel = int(self.entry_balance_cc.get_text())
+        self.mixer.last_midi_channel = int(self.entry_balance_cc.get_value())
         self.sense_popup_dialog(self.entry_balance_cc)
 
     def on_sense_midi_mute_clicked(self, *args):
-        self.mixer.last_midi_channel = int(self.entry_mute_cc.get_text())
+        self.mixer.last_midi_channel = int(self.entry_mute_cc.get_value())
         self.sense_popup_dialog(self.entry_mute_cc)
 
     def on_sense_midi_solo_clicked(self, *args):
-        self.mixer.last_midi_channel = int(self.entry_solo_cc.get_text())
+        self.mixer.last_midi_channel = int(self.entry_solo_cc.get_value())
         self.sense_popup_dialog(self.entry_solo_cc)
 
     def on_response_cb(self, dlg, response_id, *args):
         self.channel.channel_properties_dialog = None
         name = self.entry_name.get_text()
         if response_id == Gtk.ResponseType.APPLY:
-            self.channel.channel_name = name
-            try:
-                if self.entry_volume_cc.get_text() != '-1':
-                    self.channel.channel.volume_midi_cc = int(self.entry_volume_cc.get_text())
-            except ValueError:
-                pass
-            try:
-                if self.entry_balance_cc.get_text() != '-1':
-                    self.channel.channel.balance_midi_cc = int(self.entry_balance_cc.get_text())
-            except ValueError:
-                pass
-            try:
-                if self.entry_mute_cc.get_text() != '-1':
-                    self.channel.channel.mute_midi_cc = int(self.entry_mute_cc.get_text())
-            except ValueError:
-                pass
-            try:
-                if hasattr(self, 'entry_solo_cc') and self.entry_solo_cc.get_text() != '-1':
-                    self.channel.channel.solo_midi_cc = int(self.entry_solo_cc.get_text())
-            except ValueError:
-                pass
+            if name != self.channel.channel_name:
+                self.channel.channel_name = name
+            for control in ('volume', 'balance', 'mute', 'solo'):
+                widget = getattr(self, 'entry_{}_cc'.format(control), None)
+                if widget is not None:
+                    value = int(widget.get_value())
+                    if value != -1:
+                        setattr(self.channel.channel, '{}_midi_cc'.format(control), value)
         self.destroy()
 
     def on_entry_name_changed(self, entry):
@@ -921,18 +901,18 @@ class NewChannelDialog(ChannelPropertiesDialog):
         self.set_default_response(Gtk.ResponseType.OK);
 
     def fill_ui(self):
-        self.entry_volume_cc.set_text('-1')
-        self.entry_balance_cc.set_text('-1')
-        self.entry_mute_cc.set_text('-1')
-        self.entry_solo_cc.set_text('-1')
+        self.entry_volume_cc.set_value(-1)
+        self.entry_balance_cc.set_value(-1)
+        self.entry_mute_cc.set_value(-1)
+        self.entry_solo_cc.set_value(-1)
 
     def get_result(self):
         return {'name': self.entry_name.get_text(),
                 'stereo': self.stereo.get_active(),
-                'volume_cc': self.entry_volume_cc.get_text(),
-                'balance_cc': self.entry_balance_cc.get_text(),
-                'mute_cc': self.entry_mute_cc.get_text(),
-                'solo_cc': self.entry_solo_cc.get_text()
+                'volume_cc': int(self.entry_volume_cc.get_value()),
+                'balance_cc': int(self.entry_balance_cc.get_value()),
+                'mute_cc': int(self.entry_mute_cc.get_value()),
+                'solo_cc': int(self.entry_solo_cc.get_value())
                }
 
 class OutputChannelPropertiesDialog(ChannelPropertiesDialog):
@@ -976,16 +956,16 @@ class NewOutputChannelDialog(OutputChannelPropertiesDialog):
         self.set_default_response(Gtk.ResponseType.OK);
 
     def fill_ui(self):
-        self.entry_volume_cc.set_text('-1')
-        self.entry_balance_cc.set_text('-1')
-        self.entry_mute_cc.set_text('-1')
+        self.entry_volume_cc.set_value(-1)
+        self.entry_balance_cc.set_value(-1)
+        self.entry_mute_cc.set_value(-1)
 
     def get_result(self):
         return {'name': self.entry_name.get_text(),
                 'stereo': self.stereo.get_active(),
-                'volume_cc': self.entry_volume_cc.get_text(),
-                'balance_cc': self.entry_balance_cc.get_text(),
-                'mute_cc': self.entry_mute_cc.get_text(),
+                'volume_cc': int(self.entry_volume_cc.get_value()),
+                'balance_cc': int(self.entry_balance_cc.get_value()),
+                'mute_cc': int(self.entry_mute_cc.get_value()),
                 'display_solo_buttons': self.display_solo_buttons.get_active(),
                }
 
index 461e395a203599cd73da9e9bb9c5c93c7a5944ec..e18ea8af12ecdbbaf8f65831a0c3e96809a56d4c 100644 (file)
@@ -355,15 +355,12 @@ channel_set_solo_midi_cc(
 }
 
 void
-channel_autoset_midi_cc(
+channel_autoset_volume_midi_cc(
   jack_mixer_channel_t channel)
 {
-  struct jack_mixer *mixer_ptr;
-  int i;
-
-  mixer_ptr = channel_ptr->mixer_ptr;
+  struct jack_mixer *mixer_ptr = channel_ptr->mixer_ptr;
 
-  for (i = 11 ; i < 128 ; i++)
+  for (int i = 11 ; i < 128 ; i++)
   {
     if (mixer_ptr->midi_cc_map[i] == NULL)
     {
@@ -375,8 +372,15 @@ channel_autoset_midi_cc(
       break;
     }
   }
+}
 
-  for (; i < 128 ; i++)
+void
+channel_autoset_balance_midi_cc(
+  jack_mixer_channel_t channel)
+{
+  struct jack_mixer *mixer_ptr = channel_ptr->mixer_ptr;
+
+  for (int i = 11; i < 128 ; i++)
   {
     if (mixer_ptr->midi_cc_map[i] == NULL)
     {
@@ -388,8 +392,15 @@ channel_autoset_midi_cc(
       break;
     }
   }
+}
 
-  for (; i < 128 ; i++)
+void
+channel_autoset_mute_midi_cc(
+  jack_mixer_channel_t channel)
+{
+  struct jack_mixer *mixer_ptr = channel_ptr->mixer_ptr;
+
+  for (int i = 11; i < 128 ; i++)
   {
     if (mixer_ptr->midi_cc_map[i] == NULL)
     {
@@ -401,8 +412,15 @@ channel_autoset_midi_cc(
       break;
     }
   }
+}
+
+void
+channel_autoset_solo_midi_cc(
+  jack_mixer_channel_t channel)
+{
+  struct jack_mixer *mixer_ptr = channel_ptr->mixer_ptr;
 
-  for (; i < 128 ; i++)
+  for (int i = 11; i < 128 ; i++)
   {
     if (mixer_ptr->midi_cc_map[i] == NULL)
     {
index 6c64b17616cbb35bbc749059b4c84e27c88f7ccb..df96b11bbc33dbe48ec466b13f7be7719e9b472a 100644 (file)
@@ -159,7 +159,19 @@ channel_set_solo_midi_cc(
   int new_cc);
 
 void
-channel_autoset_midi_cc(
+channel_autoset_volume_midi_cc(
+  jack_mixer_channel_t channel);
+
+void
+channel_autoset_balance_midi_cc(
+  jack_mixer_channel_t channel);
+
+void
+channel_autoset_mute_midi_cc(
+  jack_mixer_channel_t channel);
+
+void
+channel_autoset_solo_midi_cc(
   jack_mixer_channel_t channel);
 
 void
index 01fa39527ac6f18449a526e6a0f6004358652230..e682c901c71495c6f53203561c680ac9cb7f95b6 100755 (executable)
@@ -440,17 +440,22 @@ class JackMixer(SerializedObject):
             err.run()
             err.destroy()
             return
-        if volume_cc != '-1':
-            channel.channel.volume_midi_cc = int(volume_cc)
-        if balance_cc != '-1':
-            channel.channel.balance_midi_cc = int(balance_cc)
-        if mute_cc != '-1':
-            channel.channel.mute_midi_cc = int(mute_cc)
-        if solo_cc != '-1':
-            channel.channel.solo_midi_cc = int(solo_cc)
-        if (volume_cc == '-1' and balance_cc == '-1' and mute_cc == '-1' and solo_cc == '-1'):
-            channel.channel.autoset_midi_cc()
-
+        if volume_cc != -1:
+            channel.channel.volume_midi_cc = volume_cc
+        else:
+            channel.channel.autoset_volume_midi_cc()
+        if balance_cc != -1:
+            channel.channel.balance_midi_cc = balance_cc
+        else:
+            channel.channel.autoset_balance_midi_cc()
+        if mute_cc != -1:
+            channel.channel.mute_midi_cc = mute_cc
+        else:
+            channel.channel.autoset_mute_midi_cc()
+        if solo_cc != -1:
+            channel.channel.solo_midi_cc = solo_cc
+        else:
+            channel.channel.autoset_solo_midi_cc()
         return channel
 
     def add_channel_precreated(self, channel):
@@ -506,12 +511,19 @@ class JackMixer(SerializedObject):
             err.run()
             err.destroy()
             return
-        if volume_cc != '-1':
-            channel.channel.volume_midi_cc = int(volume_cc)
-        if balance_cc != '-1':
-            channel.channel.balance_midi_cc = int(balance_cc)
-        if mute_cc != '-1':
-            channel.channel.mute_midi_cc = int(mute_cc)
+
+        if volume_cc != -1:
+            channel.channel.volume_midi_cc = volume_cc
+        else:
+            channel.channel.autoset_volume_midi_cc()
+        if balance_cc != -1:
+            channel.channel.balance_midi_cc = balance_cc
+        else:
+            channel.channel.autoset_balance_midi_cc()
+        if mute_cc != -1:
+            channel.channel.mute_midi_cc = mute_cc
+        else:
+            channel.channel.autoset_mute_midi_cc()
         return channel
 
     def add_output_channel_precreated(self, channel):
index 62946e7ef278eaef398c697ffbcd7a39c4a2468c..be419db01417c8096c77db7b976422c6330e77e8 100644 (file)
@@ -557,17 +557,51 @@ Channel_remove(ChannelObject *self, PyObject *args)
 }
 
 static PyObject*
-Channel_autoset_midi_cc(ChannelObject *self, PyObject *args)
+Channel_autoset_volume_midi_cc(ChannelObject *self, PyObject *args)
 {
        if (! PyArg_ParseTuple(args, "")) return NULL;
-       channel_autoset_midi_cc(self->channel);
+       channel_autoset_volume_midi_cc(self->channel);
+       Py_INCREF(Py_None);
+       return Py_None;
+}
+
+static PyObject*
+Channel_autoset_balance_midi_cc(ChannelObject *self, PyObject *args)
+{
+       if (! PyArg_ParseTuple(args, "")) return NULL;
+       channel_autoset_balance_midi_cc(self->channel);
+       Py_INCREF(Py_None);
+       return Py_None;
+}
+
+static PyObject*
+Channel_autoset_mute_midi_cc(ChannelObject *self, PyObject *args)
+{
+       if (! PyArg_ParseTuple(args, "")) return NULL;
+       channel_autoset_mute_midi_cc(self->channel);
+       Py_INCREF(Py_None);
+       return Py_None;
+}
+
+static PyObject*
+Channel_autoset_solo_midi_cc(ChannelObject *self, PyObject *args)
+{
+       if (! PyArg_ParseTuple(args, "")) return NULL;
+       channel_autoset_solo_midi_cc(self->channel);
        Py_INCREF(Py_None);
        return Py_None;
 }
 
 static PyMethodDef channel_methods[] = {
        {"remove", (PyCFunction)Channel_remove, METH_VARARGS, "Remove"},
-       {"autoset_midi_cc", (PyCFunction)Channel_autoset_midi_cc, METH_VARARGS, "Autoset MIDI CC"},
+       {"autoset_volume_midi_cc",
+               (PyCFunction)Channel_autoset_volume_midi_cc, METH_VARARGS, "Autoset Volume MIDI CC"},
+       {"autoset_balance_midi_cc",
+               (PyCFunction)Channel_autoset_balance_midi_cc, METH_VARARGS, "Autoset Balance MIDI CC"},
+       {"autoset_mute_midi_cc",
+               (PyCFunction)Channel_autoset_mute_midi_cc, METH_VARARGS, "Autoset Mute MIDI CC"},
+       {"autoset_solo_midi_cc",
+               (PyCFunction)Channel_autoset_solo_midi_cc, METH_VARARGS, "Autoset Solo MIDI CC"},
        {NULL}
 };