from gi.repository import GObject
import os
import configparser
+from serialization import SerializedObject
try:
import xdg
return scale
return None
-class Factory(GObject.GObject):
+class Factory(GObject.GObject, SerializedObject):
+
def __init__(self, topwindow, meter_scales, slider_scales):
+ self.midi_behavior_modes = { 'Jump To Value' : 0, 'Pick Up' : 1 }
GObject.GObject.__init__(self)
self.topwindow = topwindow
self.meter_scales = meter_scales
self.slider_scales = slider_scales
-
+ self.set_default_preferences()
if xdg:
self.config = configparser.ConfigParser()
self.path = os.path.join(BaseDirectory.save_config_path('jack_mixer'), 'preferences.ini')
if os.path.isfile(self.path):
self.read_preferences()
else:
- self.set_default_preferences()
self.write_preferences()
else:
print("Cannot load PyXDG. Your preferences will not be preserved across jack_mixer invocations")
- self.set_default_preferences()
def set_default_preferences(self):
self.default_meter_scale = self.meter_scales[0]
self.vumeter_color = '#ccb300'
self.vumeter_color_scheme = 'default'
self.use_custom_widgets = False
+ self.midi_behavior_mode = 'Jump To Value'
def read_preferences(self):
self.config.read(self.path)
self.write_preferences()
self.emit('use-custom-widgets-changed', self.use_custom_widgets)
+ def set_midi_behavior_mode(self, mode):
+ self.midi_behavior_mode = mode
+ self.emit("midi-behavior-mode-changed", self.midi_behavior_modes[self.midi_behavior_mode])
+
def get_default_meter_scale(self):
return self.default_meter_scale
def get_use_custom_widgets(self):
return self.use_custom_widgets
+ def get_midi_behavior_mode(self):
+ return self.midi_behavior_mode
+
+ @classmethod
+ def serialization_name(cls):
+ return 'gui_factory'
+
+ def serialize(self, object_backend):
+ object_backend.add_property("midi_behavior_mode", self.get_midi_behavior_mode())
+
+ def unserialize_property(self, name, value):
+ if name == "midi_behavior_mode":
+ self.set_midi_behavior_mode(value)
+ return True
+ return False
+
GObject.signal_new("default-meter-scale-changed", Factory,
GObject.SignalFlags.RUN_FIRST | GObject.SignalFlags.ACTION,
None, [GObject.TYPE_PYOBJECT])
GObject.signal_new('use-custom-widgets-changed', Factory,
GObject.SignalFlags.RUN_FIRST | GObject.SignalFlags.ACTION,
None, [bool])
+GObject.signal_new('midi-behavior-mode-changed', Factory,
+ GObject.SignalFlags.RUN_FIRST | GObject.SignalFlags.ACTION,
+ None, [int])
#include "jack_compat.h"
#define VOLUME_TRANSITION_SECONDS 0.01
+
+#define MIDI_PICK_UP_DIFF 20
+
#define PEAK_FRAMES_CHUNK 4800
+
// we don't know how much to allocate, but we don't want to wait with
// allocating until we're in the process() callback, so we just take a
// fairly big chunk: 4 periods per buffer, 4096 samples per period.
jack_port_t * port_midi_in;
jack_port_t * port_midi_out;
int last_midi_channel;
+ enum midi_behavior_mode midi_behavior;
struct channel* midi_cc_map[128];
};
}
else if (channel_ptr->midi_cc_volume_index == in_event.buffer[1])
{
- if (channel_ptr->volume_new != channel_ptr->volume) {
- channel_ptr->volume = channel_ptr->volume + channel_ptr->volume_idx *
- (channel_ptr->volume_new - channel_ptr->volume) /
- channel_ptr->num_volume_transition_steps;
+ int current_midi = (int)(127 * scale_db_to_scale(channel_ptr->midi_scale, value_to_db(channel_ptr->volume)));
+ if ((mixer_ptr->midi_behavior == Pick_Up && abs(in_event.buffer[2] -current_midi) <= MIDI_PICK_UP_DIFF) || mixer_ptr->midi_behavior == Jump_To_Value) {
+ if (channel_ptr->volume_new != channel_ptr->volume) {
+ channel_ptr->volume = channel_ptr->volume + channel_ptr->volume_idx *
+ (channel_ptr->volume_new - channel_ptr->volume) /
+ channel_ptr->num_volume_transition_steps;
+ }
+ channel_ptr->volume_idx = 0;
+ channel_ptr->volume_new = db_to_value(scale_scale_to_db(channel_ptr->midi_scale,
+ (double)in_event.buffer[2] / 127));
+ LOG_DEBUG("\"%s\" volume -> %f", channel_ptr->name, channel_ptr->volume_new);
}
- channel_ptr->volume_idx = 0;
- channel_ptr->volume_new = db_to_value(scale_scale_to_db(channel_ptr->midi_scale,
- (double)in_event.buffer[2] / 127));
- LOG_DEBUG("\"%s\" volume -> %f", channel_ptr->name, channel_ptr->volume_new);
}
else if (channel_ptr->midi_cc_mute_index == in_event.buffer[1])
{
mixer_ptr->last_midi_channel = -1;
+ mixer_ptr->midi_behavior = Jump_To_Value;
+
for (i = 0 ; i < 128 ; i++)
{
mixer_ptr->midi_cc_map[i] = NULL;
return 0;
}
+int
+get_midi_behavior_mode(
+ jack_mixer_t mixer)
+{
+ return mixer_ctx_ptr->midi_behavior;
+}
+
+unsigned int
+set_midi_behavior_mode(
+ jack_mixer_t mixer,
+ enum midi_behavior_mode mode)
+{
+ mixer_ctx_ptr->midi_behavior = mode;
+ return 0;
+}
+
jack_mixer_channel_t
add_channel(
jack_mixer_t mixer,
typedef void * jack_mixer_output_channel_t;
typedef void * jack_mixer_threshold_t;
+enum midi_behavior_mode { Jump_To_Value, Pick_Up };
+
jack_mixer_t
create(
const char * jack_client_name_ptr,
jack_mixer_t mixer,
int new_channel);
+
+int
+get_midi_behavior_mode(
+ jack_mixer_t mixer);
+
+unsigned int
+set_midi_behavior_mode(
+ jack_mixer_t mixer,
+ enum midi_behavior_mode mode);
+
jack_mixer_channel_t
add_channel(
jack_mixer_t mixer,
self.mixer = jack_mixer_c.Mixer(client_name)
if not self.mixer:
sys.exit(1)
+
+ #self.mixer.midi_behavior_mode = self.gui_factory.midi_behavior_modes[self.gui_factory.get_midi_behavior_mode()]
+
self.window.set_title(client_name)
self.monitor_channel = self.mixer.add_output_channel("Monitor", True, True)
self.window = Gtk.Window(type=Gtk.WindowType.TOPLEVEL)
self.window.set_icon_name('jack_mixer')
self.gui_factory = gui.Factory(self.window, self.meter_scales, self.slider_scales)
-
+ self.gui_factory.connect('midi-behavior-mode-changed', self.on_midi_behavior_mode_changed)
self.vbox_top = Gtk.VBox()
self.window.add(self.vbox_top)
def nsm_exit_cb(self, path, session_name, client_name):
Gtk.main_quit()
+ def on_midi_behavior_mode_changed(self, gui_factory, value):
+ print('on_midi_behavior_mode_changed', value)
+ self.mixer.midi_behavior_mode = value
+
def on_delete_event(self, widget, event):
return False
self.unserialized_channels.append(channel)
return channel
+ if name == gui.Factory.serialization_name():
+ self.gui_factory = gui.Factory(self.window, self.meter_scales, self.slider_scales)
+ self.gui_factory.connect('midi-behavior-mode-changed', self.on_midi_behavior_mode_changed)
+ return self.gui_factory
+
def serialization_get_childs(self):
- '''Get child objects tha required and support serialization'''
- childs = self.channels[:] + self.output_channels[:]
+ '''Get child objects that required and support serialization'''
+ childs = self.channels[:] + self.output_channels[:] + [self.gui_factory]
return childs
def serialization_name(self):
return -1;
}
+static PyObject*
+Mixer_get_midi_behavior_mode(MixerObject *self, void *closure)
+{
+ return PyLong_FromLong(get_midi_behavior_mode(self->mixer));
+}
+
+static int
+Mixer_set_midi_behavior_mode(MixerObject *self, PyObject *value, void *closure)
+{
+ int mode;
+ unsigned int result;
+
+ mode = PyLong_AsLong(value);
+ result = set_midi_behavior_mode(self->mixer, mode);
+ if (result == 0) {
+ return 0;
+ }
+ return -1;
+}
+
+
+
static PyGetSetDef Mixer_getseters[] = {
{"channels_count", (getter)Mixer_get_channels_count, NULL,
"channels count", NULL},
{"last_midi_channel", (getter)Mixer_get_last_midi_channel, (setter)Mixer_set_last_midi_channel,
"last midi channel", NULL},
+ {"midi_behavior_mode", (getter)Mixer_get_midi_behavior_mode, (setter)Mixer_set_midi_behavior_mode,
+ "midi behavior mode", NULL},
{NULL}
};
vbox.pack_start(self.create_frame('Scales', table), True, True, 0)
+ table = Gtk.Table(1, 2, False)
+ table.set_row_spacings(5)
+ table.set_col_spacings(5)
+
+ table.attach(Gtk.Label(label='Midi behavior'), 0, 1, 0, 1)
+ self.midi_behavior_combo = self.create_midi_behavior_combo()
+ table.attach(self.midi_behavior_combo, 1, 2, 0, 1)
+
+ vbox.pack_start(self.create_frame('Midi Behavior', table), True, True, 0)
self.vbox.show_all()
self.add_button(Gtk.STOCK_CLOSE, Gtk.ResponseType.CLOSE)
return slider_scale_combo
+ def create_midi_behavior_combo(self):
+ combo = Gtk.ComboBoxText()
+ combo.append('Jump To Value', 'Jump To Value')
+ combo.append('Pick Up', 'Pick Up')
+ combo.set_active_id(self.app.gui_factory.get_midi_behavior_mode())
+ combo.connect('changed', self.on_midi_behavior_combo_changed)
+ return combo
+
def on_response_cb(self, dlg, response_id, *args):
self.app.preferences_dialog = None
self.destroy()
scale = self.slider_store.get(active_iter, 1)[0]
self.app.gui_factory.set_default_slider_scale(scale)
+ def on_midi_behavior_combo_changed(self, *args):
+ active_id = self.midi_behavior_combo.get_active_id()
+ self.app.gui_factory.set_midi_behavior_mode(active_id)
+
def on_vumeter_color_change(self, *args):
color_scheme = 'default'
if self.vumeter_color_checkbutton.get_active():