diff --git a/libs/surfaces/push2/buttons.cc b/libs/surfaces/push2/buttons.cc index b2312c4052..b009b148ff 100644 --- a/libs/surfaces/push2/buttons.cc +++ b/libs/surfaces/push2/buttons.cc @@ -1,8 +1,29 @@ +/* + Copyright (C) 2016 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "ardour/mute_control.h" #include "ardour/session.h" +#include "ardour/solo_control.h" #include "push2.h" using namespace ArdourSurface; +using namespace ARDOUR; void Push2::button_play () @@ -106,3 +127,41 @@ Push2::button_shift_release () modifier_state = ModifierState (modifier_state & ~ModShift); } +void +Push2::button_browse () +{ + switch_bank (max (0, bank_start - 8)); +} + +void +Push2::button_clip () +{ + switch_bank (max (0, bank_start + 8)); +} + +void +Push2::button_upper (uint32_t n) +{ + if (!stripable[n]) { + return; + } + + boost::shared_ptr sc = stripable[n]->solo_control (); + if (sc) { + sc->set_value (!sc->get_value(), PBD::Controllable::UseGroup); + } +} + +void +Push2::button_lower (uint32_t n) +{ + if (!stripable[n]) { + return; + } + + boost::shared_ptr mc = stripable[n]->mute_control (); + + if (mc) { + mc->set_value (!mc->get_value(), PBD::Controllable::UseGroup); + } +} diff --git a/libs/surfaces/push2/push2.cc b/libs/surfaces/push2/push2.cc index 34a0efcbd0..38415e35ca 100644 --- a/libs/surfaces/push2/push2.cc +++ b/libs/surfaces/push2/push2.cc @@ -21,6 +21,7 @@ #include #include "pbd/compose.h" +#include "pbd/convert.h" #include "pbd/debug.h" #include "pbd/failed_constructor.h" @@ -61,6 +62,7 @@ Push2::Push2 (ARDOUR::Session& s) , device_buffer (0) , frame_buffer (Cairo::ImageSurface::create (Cairo::FORMAT_ARGB32, cols, rows)) , modifier_state (None) + , bank_start (0) { context = Cairo::Context::create (frame_buffer); tc_clock_layout = Pango::Layout::create (context); @@ -70,7 +72,7 @@ Push2::Push2 (ARDOUR::Session& s) tc_clock_layout->set_font_description (fd); bbt_clock_layout->set_font_description (fd); - Pango::FontDescription fd2 ("Sans Bold 10"); + Pango::FontDescription fd2 ("Sans 10"); for (int n = 0; n < 8; ++n) { upper_layout[n] = Pango::Layout::create (context); upper_layout[n]->set_font_description (fd2); @@ -78,9 +80,12 @@ Push2::Push2 (ARDOUR::Session& s) lower_layout[n] = Pango::Layout::create (context); lower_layout[n]->set_font_description (fd2); lower_layout[n]->set_text ("mute"); + } + + Pango::FontDescription fd3 ("Sans Bold 10"); + for (int n = 0; n < 8; ++n) { mid_layout[n] = Pango::Layout::create (context); - mid_layout[n]->set_font_description (fd2); - mid_layout[n]->set_text (string_compose ("Inst %1", n)); + mid_layout[n]->set_font_description (fd3); } build_maps (); @@ -155,6 +160,7 @@ Push2::close () vblank_connection.disconnect (); periodic_connection.disconnect (); session_connections.drop_connections (); + stripable_connections.drop_connections (); if (handle) { libusb_release_interface (handle, 0x00); @@ -162,6 +168,10 @@ Push2::close () handle = 0; } + for (int n = 0; n < 8; ++n) { + stripable[n].reset (); + } + delete [] device_frame_buffer; device_frame_buffer = 0; @@ -333,6 +343,18 @@ Push2::redraw () bbt_clock_layout->set_text (bbt_clock_text); } + string mid_text; + + for (int n = 0; n < 8; ++n) { + if (stripable[n]) { + mid_text = short_version (stripable[n]->name(), 10); + if (mid_text != mid_layout[n]->get_text()) { + mid_layout[n]->set_text (mid_text); + dirty = true; + } + } + } + if (!dirty) { return false; } @@ -443,6 +465,7 @@ Push2::set_active (bool yn) periodic_timeout->attach (main_loop()->get_context()); init_buttons (); + switch_bank (0); } else { @@ -641,21 +664,22 @@ Push2::build_maps () cc_button_map.insert (make_pair (button->controller_number(), button)); \ id_button_map.insert (make_pair (button->id, button)) - MAKE_COLOR_BUTTON (Upper1, 102); - MAKE_COLOR_BUTTON (Upper2, 103); - MAKE_COLOR_BUTTON (Upper3, 104); - MAKE_COLOR_BUTTON (Upper4, 105); - MAKE_COLOR_BUTTON (Upper5, 106); - MAKE_COLOR_BUTTON (Upper6, 107); - MAKE_COLOR_BUTTON (Upper7, 108); - MAKE_COLOR_BUTTON (Upper8, 109); - MAKE_COLOR_BUTTON (Lower1, 21); - MAKE_COLOR_BUTTON (Lower2, 22); - MAKE_COLOR_BUTTON (Lower3, 23); - MAKE_COLOR_BUTTON (Lower4, 24); - MAKE_COLOR_BUTTON (Lower5, 25); - MAKE_COLOR_BUTTON (Lower6, 26); - MAKE_COLOR_BUTTON (Lower7, 27); + MAKE_COLOR_BUTTON_PRESS (Upper1, 102, &Push2::button_upper_1); + MAKE_COLOR_BUTTON_PRESS (Upper2, 103, &Push2::button_upper_2); + MAKE_COLOR_BUTTON_PRESS (Upper3, 104, &Push2::button_upper_3); + MAKE_COLOR_BUTTON_PRESS (Upper4, 105, &Push2::button_upper_4); + MAKE_COLOR_BUTTON_PRESS (Upper5, 106, &Push2::button_upper_5); + MAKE_COLOR_BUTTON_PRESS (Upper6, 107, &Push2::button_upper_6); + MAKE_COLOR_BUTTON_PRESS (Upper7, 108, &Push2::button_upper_7); + MAKE_COLOR_BUTTON_PRESS (Upper8, 109, &Push2::button_upper_8); + MAKE_COLOR_BUTTON_PRESS (Lower1, 20, &Push2::button_lower_1); + MAKE_COLOR_BUTTON_PRESS (Lower2, 21, &Push2::button_lower_2); + MAKE_COLOR_BUTTON_PRESS (Lower3, 22, &Push2::button_lower_3); + MAKE_COLOR_BUTTON_PRESS (Lower4, 23, &Push2::button_lower_4); + MAKE_COLOR_BUTTON_PRESS (Lower5, 24, &Push2::button_lower_5); + MAKE_COLOR_BUTTON_PRESS (Lower6, 25, &Push2::button_lower_6); + MAKE_COLOR_BUTTON_PRESS (Lower7, 26, &Push2::button_lower_7); + MAKE_COLOR_BUTTON_PRESS (Lower8, 27, &Push2::button_lower_8); MAKE_COLOR_BUTTON (Master, 28); MAKE_COLOR_BUTTON (Mute, 60); MAKE_COLOR_BUTTON_PRESS (Solo, 61, &Push2::button_solo); @@ -695,7 +719,8 @@ Push2::build_maps () MAKE_WHITE_BUTTON (Mix, 112); MAKE_WHITE_BUTTON (Undo, 119); MAKE_WHITE_BUTTON (AddTrack, 53); - MAKE_WHITE_BUTTON (Browse, 113); + MAKE_WHITE_BUTTON_PRESS (Browse, 111, &Push2::button_browse); + MAKE_WHITE_BUTTON_PRESS (Clip, 113, &Push2::button_clip); MAKE_WHITE_BUTTON (Convert, 35); MAKE_WHITE_BUTTON (DoubleLoop, 117); MAKE_WHITE_BUTTON (Quantize, 116); @@ -900,3 +925,154 @@ Push2::set_state (const XMLNode & node, int version) 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_nth_stripable (base+0); + + if (!stripable[0]) { + return; + } + + /* at least one stripable in this bank */ + bank_start = base; + + stripable[1] = session->get_nth_stripable (base+1); + stripable[2] = session->get_nth_stripable (base+2); + stripable[3] = session->get_nth_stripable (base+3); + stripable[4] = session->get_nth_stripable (base+4); + stripable[5] = session->get_nth_stripable (base+5); + stripable[6] = session->get_nth_stripable (base+6); + stripable[7] = session->get_nth_stripable (base+7); + + 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 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 mc = stripable[n]->mute_control(); + if (mc) { + mc->Changed.connect (stripable_connections, MISSING_INVALIDATOR, boost::bind (&Push2::mute_change, this, n), this); + } + + solo_change (n); + mute_change (n); + + } +} + +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 ac = stripable[n]->solo_control (); + if (!ac) { + return; + } + + Button* b = id_button_map[bid]; + if (ac->get_value()) { + b->set_color (LED::Red); + } else { + b->set_color (LED::Black); + } + b->set_state (LED::OneShot24th); + write (b->state_msg()); +} + +void +Push2::mute_change (int n) +{ + ButtonID bid; + + 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 ac = stripable[n]->mute_control (); + if (!ac) { + return; + } + + Button* b = id_button_map[bid]; + + if (ac->get_value ()) { + b->set_color (LED::Blue); + } else { + b->set_color (LED::Black); + } + b->set_state (LED::OneShot24th); + write (b->state_msg()); +} diff --git a/libs/surfaces/push2/push2.h b/libs/surfaces/push2/push2.h index 3eac5f8653..60bfa2b07f 100644 --- a/libs/surfaces/push2/push2.h +++ b/libs/surfaces/push2/push2.h @@ -346,6 +346,26 @@ class Push2 : public ARDOUR::ControlProtocol void button_new (); void button_shift_press (); void button_shift_release (); + void button_browse (); + void button_clip (); + void button_upper (uint32_t n); + void button_lower (uint32_t n); + void button_upper_1 () { button_upper (0); } + void button_upper_2 () { button_upper (1); } + void button_upper_3 () { button_upper (2); } + void button_upper_4 () { button_upper (3); } + void button_upper_5 () { button_upper (4); } + void button_upper_6 () { button_upper (5); } + void button_upper_7 () { button_upper (6); } + void button_upper_8 () { button_upper (7); } + void button_lower_1 () { button_lower (0); } + void button_lower_2 () { button_lower (1); } + void button_lower_3 () { button_lower (2); } + void button_lower_4 () { button_lower (3); } + void button_lower_5 () { button_lower (4); } + void button_lower_6 () { button_lower (5); } + void button_lower_7 () { button_lower (6); } + void button_lower_8 () { button_lower (7); } /* widgets */ @@ -355,6 +375,19 @@ class Push2 : public ARDOUR::ControlProtocol Glib::RefPtr upper_layout[8]; Glib::RefPtr mid_layout[8]; Glib::RefPtr lower_layout[8]; + + /* stripables */ + + int32_t bank_start; + PBD::ScopedConnectionList stripable_connections; + boost::shared_ptr stripable[8]; + boost::shared_ptr master; + boost::shared_ptr monitor; + + void solo_change (int); + void mute_change (int); + + void switch_bank (uint32_t base); };