- node.add_child_nocopy (*child);
- child = new XMLNode (X_("Output"));
- child->add_child_nocopy (_async_out->get_state());
- node.add_child_nocopy (*child);
-
- node.add_property (X_("root"), to_string (_scale_root, std::dec));
- node.add_property (X_("root_octave"), to_string (_root_octave, std::dec));
- node.add_property (X_("in_key"), _in_key ? X_("yes") : X_("no"));
- node.add_property (X_("mode"), enum_2_string (_mode));
-
- return node;
-}
-
-int
-Push2::set_state (const XMLNode & node, int version)
-{
- DEBUG_TRACE (DEBUG::Push2, string_compose ("Push2::set_state: active %1\n", active()));
-
- int retval = 0;
-
- if (ControlProtocol::set_state (node, version)) {
- return -1;
- }
-
- XMLNode* child;
-
- if ((child = node.child (X_("Input"))) != 0) {
- XMLNode* portnode = child->child (Port::state_node_name.c_str());
- if (portnode) {
- _async_in->set_state (*portnode, version);
- }
- }
-
- if ((child = node.child (X_("Output"))) != 0) {
- XMLNode* portnode = child->child (Port::state_node_name.c_str());
- if (portnode) {
- _async_out->set_state (*portnode, version);
- }
- }
-
- XMLProperty const* prop;
-
- if ((prop = node.property (X_("root"))) != 0) {
- _scale_root = atoi (prop->value());
- }
-
- if ((prop = node.property (X_("root_octave"))) != 0) {
- _root_octave = atoi (prop->value());
- }
-
- if ((prop = node.property (X_("in_key"))) != 0) {
- _in_key = string_is_affirmative (prop->value());
- }
-
- if ((prop = node.property (X_("mode"))) != 0) {
- _mode = (MusicalMode::Type) string_2_enum (prop->value(), _mode);
- }
-
- return retval;
-}
-
-void
-Push2::switch_bank (uint32_t base)
-{
- if (!session) {
- return;
- }
-
- stripable_connections.drop_connections ();
-
- /* try to get the first stripable for the requested bank */
-
- stripable[0] = session->get_remote_nth_stripable (base, PresentationInfo::Flag (PresentationInfo::Route|PresentationInfo::VCA));
-
- if (!stripable[0]) {
- return;
- }
-
- /* at least one stripable in this bank */
- bank_start = base;
-
- stripable[1] = session->get_remote_nth_stripable (base+1, PresentationInfo::Flag (PresentationInfo::Route|PresentationInfo::VCA));
- stripable[2] = session->get_remote_nth_stripable (base+2, PresentationInfo::Flag (PresentationInfo::Route|PresentationInfo::VCA));
- stripable[3] = session->get_remote_nth_stripable (base+3, PresentationInfo::Flag (PresentationInfo::Route|PresentationInfo::VCA));
- stripable[4] = session->get_remote_nth_stripable (base+4, PresentationInfo::Flag (PresentationInfo::Route|PresentationInfo::VCA));
- stripable[5] = session->get_remote_nth_stripable (base+5, PresentationInfo::Flag (PresentationInfo::Route|PresentationInfo::VCA));
- stripable[6] = session->get_remote_nth_stripable (base+6, PresentationInfo::Flag (PresentationInfo::Route|PresentationInfo::VCA));
- stripable[7] = session->get_remote_nth_stripable (base+7, PresentationInfo::Flag (PresentationInfo::Route|PresentationInfo::VCA));
-
-
- for (int n = 0; n < 8; ++n) {
- if (!stripable[n]) {
- continue;
- }
-
- /* stripable goes away? refill the bank, starting at the same point */
-
- stripable[n]->DropReferences.connect (stripable_connections, MISSING_INVALIDATOR, boost::bind (&Push2::switch_bank, this, bank_start), this);
- boost::shared_ptr<AutomationControl> sc = stripable[n]->solo_control();
- if (sc) {
- sc->Changed.connect (stripable_connections, MISSING_INVALIDATOR, boost::bind (&Push2::solo_change, this, n), this);
- }
-
- boost::shared_ptr<AutomationControl> mc = stripable[n]->mute_control();
- if (mc) {
- mc->Changed.connect (stripable_connections, MISSING_INVALIDATOR, boost::bind (&Push2::mute_change, this, n), this);
- }
-
- stripable[n]->presentation_info().PropertyChanged.connect (stripable_connections, MISSING_INVALIDATOR, boost::bind (&Push2::stripable_property_change, this, _1, n), this);
-
- solo_change (n);
- mute_change (n);
-
- }
-
- /* master cannot be removed, so no need to connect to going-away signal */
- master = session->master_out ();
-}
-
-void
-Push2::stripable_property_change (PropertyChange const& what_changed, int which)
-{
- if (what_changed.contains (Properties::selected)) {
- if (!stripable[which]) {
- return;
- }
-
- /* cancel string, which will cause a redraw on the next update
- * cycle. The redraw will reflect selected status
- */
-
- mid_layout[which]->set_text (string());
- }
-}
-
-void
-Push2::stripable_selection_change (StripableNotificationListPtr selected)
-{
-
- boost::shared_ptr<MidiPort> pad_port = boost::dynamic_pointer_cast<AsyncMIDIPort>(_async_in)->shadow_port();
- boost::shared_ptr<MidiTrack> current_midi_track = current_pad_target.lock();
- boost::shared_ptr<MidiTrack> new_pad_target;
-
- /* See if there's a MIDI track selected */
-
- for (StripableNotificationList::iterator si = selected->begin(); si != selected->end(); ++si) {
-
- new_pad_target = boost::dynamic_pointer_cast<MidiTrack> ((*si).lock());
-
- if (new_pad_target) {
- break;
- }
- }
-
- if (new_pad_target) {
- cerr << "new midi pad target " << new_pad_target->name() << endl;
- } else {
- cerr << "no midi pad target\n";
- }
-
- if (current_midi_track == new_pad_target) {
- /* nothing to do */
- return;
- }
-
- if (!new_pad_target) {
- /* leave existing connection alone */
- return;
- }
-
- /* disconnect from pad port, if appropriate */
-
- if (current_midi_track && pad_port) {
- cerr << "Disconnect pads from " << current_midi_track->name() << endl;
- current_midi_track->input()->disconnect (current_midi_track->input()->nth(0), pad_port->name(), this);
- }
-
- /* now connect the pad port to this (newly) selected midi
- * track, if indeed there is one.
- */
-
- if (new_pad_target && pad_port) {
- cerr << "Reconnect pads to " << new_pad_target->name() << endl;
- new_pad_target->input()->connect (new_pad_target->input()->nth (0), pad_port->name(), this);
- current_pad_target = new_pad_target;
- } else {
- current_pad_target.reset ();
- }
-}
-
-
-void
-Push2::solo_change (int n)
-{
- ButtonID bid;
-
- switch (n) {
- case 0:
- bid = Upper1;
- break;
- case 1:
- bid = Upper2;
- break;
- case 2:
- bid = Upper3;
- break;
- case 3:
- bid = Upper4;
- break;
- case 4:
- bid = Upper5;
- break;
- case 5:
- bid = Upper6;
- break;
- case 6:
- bid = Upper7;
- break;
- case 7:
- bid = Upper8;
- break;
- default:
- return;
- }
-
- boost::shared_ptr<SoloControl> ac = stripable[n]->solo_control ();
- if (!ac) {
- return;
- }
-
- Button* b = id_button_map[bid];
-
- if (ac->soloed()) {
- b->set_color (LED::Green);
- } else {
- b->set_color (LED::Black);
- }
-
- if (ac->soloed_by_others_upstream() || ac->soloed_by_others_downstream()) {
- b->set_state (LED::Blinking4th);
- } else {
- b->set_state (LED::OneShot24th);
- }
-
- write (b->state_msg());
-}
-
-void
-Push2::mute_change (int n)
-{
- ButtonID bid;
-
- if (!stripable[n]) {
- return;
- }
-
- cerr << "Mute changed on " << n << ' ' << stripable[n]->name() << endl;
-
- switch (n) {
- case 0:
- bid = Lower1;
- break;
- case 1:
- bid = Lower2;
- break;
- case 2:
- bid = Lower3;
- break;
- case 3:
- bid = Lower4;
- break;
- case 4:
- bid = Lower5;
- break;
- case 5:
- bid = Lower6;
- break;
- case 6:
- bid = Lower7;
- break;
- case 7:
- bid = Lower8;
- break;
- default:
- return;
- }
-
- boost::shared_ptr<MuteControl> mc = stripable[n]->mute_control ();
-
- if (!mc) {
- return;
- }
-
- Button* b = id_button_map[bid];
-
- if (Config->get_show_solo_mutes() && !Config->get_solo_control_is_listen_control ()) {
-
- if (mc->muted_by_self ()) {
- /* full mute */
- b->set_color (LED::Blue);
- b->set_state (LED::OneShot24th);
- cerr << "FULL MUTE1\n";
- } else if (mc->muted_by_others_soloing () || mc->muted_by_masters ()) {
- /* this will reflect both solo mutes AND master mutes */
- b->set_color (LED::Blue);
- b->set_state (LED::Blinking4th);
- cerr << "OTHER MUTE1\n";
- } else {
- /* no mute at all */
- b->set_color (LED::Black);
- b->set_state (LED::OneShot24th);
- cerr << "NO MUTE1\n";
- }
-
- } else {
-
- if (mc->muted_by_self()) {
- /* full mute */
- b->set_color (LED::Blue);
- b->set_state (LED::OneShot24th);
- cerr << "FULL MUTE2\n";
- } else if (mc->muted_by_masters ()) {
- /* this shows only master mutes, not mute-by-others-soloing */
- b->set_color (LED::Blue);
- b->set_state (LED::Blinking4th);
- cerr << "OTHER MUTE1\n";
- } else {
- /* no mute at all */
- b->set_color (LED::Black);
- b->set_state (LED::OneShot24th);
- cerr << "NO MUTE2\n";
- }
- }