FaderPort::FaderPort (Session& s)
: ControlProtocol (s, _("Faderport"))
- , AbstractUI<FaderPortRequest> ("faderport")
+ , AbstractUI<FaderPortRequest> (name())
, gui (0)
, connection_state (ConnectionState (0))
, _device_active (false)
get_button (Undo).set_flash (true);
get_button (FP_Read).set_action (boost::bind (&FaderPort::read, this), true);
+ get_button (FP_Read).set_action (boost::bind (&FaderPort::off, this), false, LongPress);
get_button (FP_Write).set_action (boost::bind (&FaderPort::write, this), true);
+ get_button (FP_Write).set_action (boost::bind (&FaderPort::off, this), false, LongPress);
get_button (FP_Touch).set_action (boost::bind (&FaderPort::touch, this), true);
+ get_button (FP_Touch).set_action (boost::bind (&FaderPort::off, this), false, LongPress);
get_button (FP_Off).set_action (boost::bind (&FaderPort::off, this), true);
get_button (Play).set_action (boost::bind (&BasicUI::transport_play, this, true), true);
get_button (Loop).set_action (boost::bind (&BasicUI::add_marker, this, string()), true, ShiftDown);
get_button (Punch).set_action (boost::bind (&BasicUI::prev_marker, this), true, ShiftDown);
- get_button (User).set_action (boost::bind (&BasicUI::next_marker, this), true, ShiftDown);
+ get_button (User).set_action (boost::bind (&BasicUI::next_marker, this), true, ButtonState(ShiftDown|UserDown));
get_button (Mute).set_action (boost::bind (&FaderPort::mute, this), true);
get_button (Solo).set_action (boost::bind (&FaderPort::solo, this), true);
}
tear_down_gui ();
+
+ /* stop event loop */
+ DEBUG_TRACE (DEBUG::FaderPort, "BaseUI::quit ()\n");
+ BaseUI::quit ();
+}
+
+void*
+FaderPort::request_factory (uint32_t num_requests)
+{
+ /* AbstractUI<T>::request_buffer_factory() is a template method only
+ instantiated in this source module. To provide something visible for
+ use in the interface/descriptor, we have this static method that is
+ template-free.
+ */
+ return request_buffer_factory (num_requests);
}
void
{
struct sched_param rtparam;
- pthread_set_name (X_("FaderPort"));
+ pthread_set_name (event_loop_name().c_str());
- PBD::notify_gui_about_thread_creation (X_("gui"), pthread_self(), X_("FaderPort"), 2048);
- ARDOUR::SessionEvent::create_per_thread_pool (X_("FaderPort"), 128);
+ PBD::notify_event_loops_about_thread_creation (pthread_self(), event_loop_name(), 2048);
+ ARDOUR::SessionEvent::create_per_thread_pool (event_loop_name(), 128);
memset (&rtparam, 0, sizeof (rtparam));
rtparam.sched_priority = 9; /* XXX should be relative to audio (JACK) thread */
ButtonID id (ButtonID (tb->controller_number));
Button& button (get_button (id));
+ DEBUG_TRACE (DEBUG::FaderPort, string_compose ("button event for ID %1 press ? %2\n", (int) tb->controller_number, (tb->value ? "yes" : "no")));
+
if (tb->value) {
buttons_down.insert (id);
} else {
switch (id) {
case Shift:
- /* set this bit on press, do NOT clear it on release */
- if (tb->value) {
- bs = ShiftDown;
- }
+ bs = ShiftDown;
break;
case Stop:
bs = StopDown;
if (bs) {
button_state = (tb->value ? ButtonState (button_state|bs) : ButtonState (button_state&~bs));
- DEBUG_TRACE (DEBUG::FaderPort, string_compose ("reset button state to %1%2 using %3%4\n", hex, button_state, bs, dec));
+ DEBUG_TRACE (DEBUG::FaderPort, string_compose ("reset button state to %1 using %2\n", button_state, (int) bs));
}
if (button.uses_flash()) {
if (c == consumed.end()) {
button.invoke (button_state, tb->value ? true : false);
} else {
+ DEBUG_TRACE (DEBUG::FaderPort, "button was consumed, ignored\n");
consumed.erase (c);
}
-
- if (!tb->value && (id != Shift)) {
- /* non-shift key was released, clear shift modifier */
- button_state = ButtonState (button_state&~ShiftDown);
- DEBUG_TRACE (DEBUG::FaderPort, "clear shift modifier\n");
- }
-
- if (!tb->value && (id != User)) {
- consumed.insert (User);
- DEBUG_TRACE (DEBUG::FaderPort, "clear user modifier\n");
- }
}
void
if (gain) {
int ival = (fader_msb << 7) | fader_lsb;
float val = gain->interface_to_internal (ival/16384.0);
- _current_route->set_gain (val, this);
+ /* even though the faderport only controls a
+ single route at a time, allow the fader to
+ modify the group, if appropriate.
+ */
+ _current_route->set_gain (val, Controllable::UseGroup);
}
}
}
void
FaderPort::sysex_handler (MIDI::Parser &p, MIDI::byte *buf, size_t sz)
{
+ DEBUG_TRACE (DEBUG::FaderPort, string_compose ("sysex message received, size = %1\n", sz));
+
if (sz < 17) {
return;
}
blink_timeout->attach (main_loop()->get_context());
Glib::RefPtr<Glib::TimeoutSource> periodic_timeout = Glib::TimeoutSource::create (100); // milliseconds
- periodic_connection = blink_timeout->connect (sigc::mem_fun (*this, &FaderPort::periodic));
+ periodic_connection = periodic_timeout->connect (sigc::mem_fun (*this, &FaderPort::periodic));
periodic_timeout->attach (main_loop()->get_context());
} else {
*/
g_usleep (100000);
+ DEBUG_TRACE (DEBUG::FaderPort, "device now connected for both input and output\n");
connected ();
} else {
void
FaderPort::connected ()
{
- DEBUG_TRACE (DEBUG::FaderPort, "connection status changed\n");
+ DEBUG_TRACE (DEBUG::FaderPort, "sending device inquiry message...\n");
start_midi_handling ();
if (press) {
if ((x = on_press.find (bs)) == on_press.end()) {
- DEBUG_TRACE (DEBUG::FaderPort, string_compose ("no press action for button %1 state %2%3\%4\n", id, hex, bs, dec));
+ DEBUG_TRACE (DEBUG::FaderPort, string_compose ("no press action for button %1 state %2 @ %3 in %4\n", id, bs, this, &on_press));
return;
}
} else {
if ((x = on_release.find (bs)) == on_release.end()) {
- DEBUG_TRACE (DEBUG::FaderPort, string_compose ("no release action for button %1 state %2%3\%4\n", id, hex, bs, dec));
+ DEBUG_TRACE (DEBUG::FaderPort, string_compose ("no release action for button %1 state %2 @%3 in %4\n", id, bs, this, &on_release));
return;
}
}
todo.type = InternalFunction;
if (when_pressed) {
+ DEBUG_TRACE (DEBUG::FaderPort, string_compose ("set button %1 (%2) @ %5 to some functor on press + %3 in %4\n", id, name, bs, &on_press, this));
todo.function = f;
on_press[bs] = todo;
} else {
+ DEBUG_TRACE (DEBUG::FaderPort, string_compose ("set button %1 (%2) @ %5 to some functor on release + %3\n", id, name, bs, this));
todo.function = f;
on_release[bs] = todo;
}
state_pairs.push_back (make_pair (string ("shift"), ShiftDown));
state_pairs.push_back (make_pair (string ("long"), LongPress));
- on_press.clear ();
- on_release.clear ();
-
for (vector<state_pair_t>::const_iterator sp = state_pairs.begin(); sp != state_pairs.end(); ++sp) {
string propname;
void
FaderPort::map_auto ()
{
- /* December 14th 2015: setting the LED states of these buttons
- interferes with fader operation.
- */
-
- return;
+ /* Under no circumstances send a message to "enable" the LED state of
+ * the Off button, because this will disable the fader.
+ */
boost::shared_ptr<AutomationControl> control = _current_route->gain_control ();
const AutoState as = control->automation_state ();
get_button (FP_Read).set_led_state (_output_port, true);
get_button (FP_Write).set_led_state (_output_port, false);
get_button (FP_Touch).set_led_state (_output_port, false);
- get_button (FP_Off).set_led_state (_output_port, false);
break;
case ARDOUR::Write:
get_button (FP_Read).set_led_state (_output_port, false);
get_button (FP_Write).set_led_state (_output_port, true);
get_button (FP_Touch).set_led_state (_output_port, false);
- get_button (FP_Off).set_led_state (_output_port, false);
break;
case ARDOUR::Touch:
get_button (FP_Read).set_led_state (_output_port, false);
get_button (FP_Write).set_led_state (_output_port, false);
get_button (FP_Touch).set_led_state (_output_port, true);
- get_button (FP_Off).set_led_state (_output_port, false);
break;
case ARDOUR::Off:
get_button (FP_Read).set_led_state (_output_port, false);
get_button (FP_Write).set_led_state (_output_port, false);
get_button (FP_Touch).set_led_state (_output_port, false);
- get_button (FP_Off).set_led_state (_output_port, true);
break;
}