From 33015a7173ef790746a340cc39a1242a03dc015b Mon Sep 17 00:00:00 2001 From: Paul Davis Date: Sun, 25 Sep 2016 18:29:30 -0500 Subject: [PATCH] push2: many improvements to track mix and mix layouts Including meters and clocks --- libs/surfaces/push2/layout.h | 1 + libs/surfaces/push2/mix.cc | 105 +++++++++++++++-------- libs/surfaces/push2/mix.h | 13 ++- libs/surfaces/push2/push2.cc | 5 +- libs/surfaces/push2/track_mix.cc | 141 ++++++++++++++++++++++++++----- libs/surfaces/push2/track_mix.h | 6 +- 6 files changed, 215 insertions(+), 56 deletions(-) diff --git a/libs/surfaces/push2/layout.h b/libs/surfaces/push2/layout.h index eb0a467e35..e655a6de8f 100644 --- a/libs/surfaces/push2/layout.h +++ b/libs/surfaces/push2/layout.h @@ -69,6 +69,7 @@ class Push2Layout : public sigc::trackable, public ArdourCanvas::Container virtual void strip_vpot_touch (int, bool) = 0; virtual void update_meters () {} + virtual void update_clocks () {} protected: Push2& p2; diff --git a/libs/surfaces/push2/mix.cc b/libs/surfaces/push2/mix.cc index c61ee45008..847586f0e5 100644 --- a/libs/surfaces/push2/mix.cc +++ b/libs/surfaces/push2/mix.cc @@ -51,8 +51,9 @@ #include "gtkmm2ext/gui_thread.h" #include "canvas.h" -#include "mix.h" #include "knob.h" +#include "level_meter.h" +#include "mix.h" #include "push2.h" #include "utils.h" @@ -83,6 +84,7 @@ MixLayout::MixLayout (Push2& p, Session& s) upper_line->set_outline_color (p2.get_color (Push2::LightBackground)); Pango::FontDescription fd2 ("Sans 10"); + for (int n = 0; n < 8; ++n) { /* background for text labels for knob function */ @@ -133,11 +135,10 @@ MixLayout::MixLayout (Push2& p, Session& s) t->set (txt); upper_text.push_back (t); - /* knobs */ + /* GainMeters */ - knobs[n] = new Push2Knob (p2, this); - knobs[n]->set_position (Duple (60 + (n*Push2Canvas::inter_button_spacing()), 95)); - knobs[n]->set_radius (25); + gain_meter[n] = new GainMeter (this, p2); + gain_meter[n]->set_position (Duple (40 + (n * Push2Canvas::inter_button_spacing()), 95)); /* stripable names */ @@ -259,95 +260,110 @@ MixLayout::show_vpot_mode () case Volume: for (int s = 0; s < 8; ++s) { if (stripable[s]) { - knobs[s]->set_controllable (stripable[s]->gain_control()); + gain_meter[s]->knob->set_controllable (stripable[s]->gain_control()); + boost::shared_ptr pm = stripable[s]->peak_meter(); + if (pm) { + gain_meter[s]->meter->set_meter (pm.get()); + } else { + gain_meter[s]->meter->set_meter (0); + } } else { - knobs[s]->set_controllable (boost::shared_ptr()); + gain_meter[s]->knob->set_controllable (boost::shared_ptr()); + gain_meter[s]->meter->set_meter (0); } - knobs[s]->remove_flag (Push2Knob::ArcToZero); + gain_meter[s]->knob->remove_flag (Push2Knob::ArcToZero); + gain_meter[s]->meter->show (); } n = 0; break; case PanAzimuth: for (int s = 0; s < 8; ++s) { if (stripable[s]) { - knobs[s]->set_controllable (stripable[s]->pan_azimuth_control()); - knobs[s]->add_flag (Push2Knob::ArcToZero); + gain_meter[s]->knob->set_controllable (stripable[s]->pan_azimuth_control()); + gain_meter[s]->knob->add_flag (Push2Knob::ArcToZero); } else { - knobs[s]->set_controllable (boost::shared_ptr()); + gain_meter[s]->knob->set_controllable (boost::shared_ptr()); } + gain_meter[s]->meter->hide (); } n = 1; break; case PanWidth: for (int s = 0; s < 8; ++s) { if (stripable[s]) { - knobs[s]->set_controllable (stripable[s]->pan_width_control()); + gain_meter[s]->knob->set_controllable (stripable[s]->pan_width_control()); } else { - knobs[s]->set_controllable (boost::shared_ptr()); + gain_meter[s]->knob->set_controllable (boost::shared_ptr()); } - knobs[s]->remove_flag (Push2Knob::ArcToZero); + gain_meter[s]->knob->remove_flag (Push2Knob::ArcToZero); + gain_meter[s]->meter->hide (); } n = 2; break; case Send1: for (int s = 0; s < 8; ++s) { if (stripable[s]) { - knobs[s]->set_controllable (stripable[s]->send_level_controllable (0)); + gain_meter[s]->knob->set_controllable (stripable[s]->send_level_controllable (0)); } else { - knobs[s]->set_controllable (boost::shared_ptr()); + gain_meter[s]->knob->set_controllable (boost::shared_ptr()); } - knobs[s]->remove_flag (Push2Knob::ArcToZero); + gain_meter[s]->knob->remove_flag (Push2Knob::ArcToZero); + gain_meter[s]->meter->hide (); } n = 3; break; case Send2: for (int s = 0; s < 8; ++s) { if (stripable[s]) { - knobs[s]->set_controllable (stripable[s]->send_level_controllable (1)); + gain_meter[s]->knob->set_controllable (stripable[s]->send_level_controllable (1)); } else { - knobs[s]->set_controllable (boost::shared_ptr()); + gain_meter[s]->knob->set_controllable (boost::shared_ptr()); } - knobs[s]->remove_flag (Push2Knob::ArcToZero); + gain_meter[s]->knob->remove_flag (Push2Knob::ArcToZero); + gain_meter[s]->meter->hide (); } n = 4; break; case Send3: for (int s = 0; s < 8; ++s) { if (stripable[s]) { - knobs[s]->set_controllable (stripable[s]->send_level_controllable (2)); + gain_meter[s]->knob->set_controllable (stripable[s]->send_level_controllable (2)); } else { - knobs[s]->set_controllable (boost::shared_ptr()); + gain_meter[s]->knob->set_controllable (boost::shared_ptr()); } - knobs[s]->remove_flag (Push2Knob::ArcToZero); + gain_meter[s]->knob->remove_flag (Push2Knob::ArcToZero); + gain_meter[s]->meter->hide (); } n = 5; break; case Send4: for (int s = 0; s < 8; ++s) { if (stripable[s]) { - knobs[s]->set_controllable (stripable[s]->send_level_controllable (3)); + gain_meter[s]->knob->set_controllable (stripable[s]->send_level_controllable (3)); } else { - knobs[s]->set_controllable (boost::shared_ptr()); + gain_meter[s]->knob->set_controllable (boost::shared_ptr()); } - knobs[s]->remove_flag (Push2Knob::ArcToZero); + gain_meter[s]->knob->remove_flag (Push2Knob::ArcToZero); + gain_meter[s]->meter->hide (); } n = 6; break; case Send5: for (int s = 0; s < 8; ++s) { if (stripable[s]) { - knobs[s]->set_controllable (stripable[s]->send_level_controllable (4)); + gain_meter[s]->knob->set_controllable (stripable[s]->send_level_controllable (4)); } else { - knobs[s]->set_controllable (boost::shared_ptr()); + gain_meter[s]->knob->set_controllable (boost::shared_ptr()); } - knobs[s]->remove_flag (Push2Knob::ArcToZero); + gain_meter[s]->knob->remove_flag (Push2Knob::ArcToZero); + gain_meter[s]->meter->hide (); } n = 7; break; @@ -398,7 +414,7 @@ MixLayout::button_lower (uint32_t n) void MixLayout::strip_vpot (int n, int delta) { - boost::shared_ptr ac = knobs[n]->controllable(); + boost::shared_ptr ac = gain_meter[n]->knob->controllable(); if (ac) { ac->set_value (ac->interface_to_internal ( @@ -566,9 +582,9 @@ MixLayout::switch_bank (uint32_t base) solo_mute_changed (n); - knobs[n]->set_text_color (stripable[n]->presentation_info().color()); - knobs[n]->set_arc_start_color (stripable[n]->presentation_info().color()); - knobs[n]->set_arc_end_color (stripable[n]->presentation_info().color()); + gain_meter[n]->knob->set_text_color (stripable[n]->presentation_info().color()); + gain_meter[n]->knob->set_arc_start_color (stripable[n]->presentation_info().color()); + gain_meter[n]->knob->set_arc_end_color (stripable[n]->presentation_info().color()); } @@ -732,3 +748,26 @@ MixLayout::button_up () { p2.scroll_up_1_track (); } + +void +MixLayout::update_meters () +{ + if (vpot_mode != Volume) { + return; + } + + for (uint32_t n = 0; n < 8; ++n) { + gain_meter[n]->meter->update_meters (); + } +} + +MixLayout::GainMeter::GainMeter (Item* parent, Push2& p2) + : Container (parent) +{ + knob = new Push2Knob (p2, this); + knob->set_radius (25); + /* leave position at (0,0) */ + + meter = new LevelMeter (p2, this, 90, ArdourCanvas::Meter::Vertical); + meter->set_position (Duple (40, -60)); +} diff --git a/libs/surfaces/push2/mix.h b/libs/surfaces/push2/mix.h index fdad06bf29..836709d929 100644 --- a/libs/surfaces/push2/mix.h +++ b/libs/surfaces/push2/mix.h @@ -35,6 +35,7 @@ namespace ArdourCanvas { namespace ArdourSurface { class Push2Knob; +class LevelMeter; class MixLayout : public Push2Layout { @@ -59,6 +60,8 @@ class MixLayout : public Push2Layout void strip_vpot (int, int); void strip_vpot_touch (int, bool); + void update_meters (); + private: ArdourCanvas::Rectangle* bg; ArdourCanvas::Line* upper_line; @@ -66,7 +69,15 @@ class MixLayout : public Push2Layout std::vector lower_text; std::vector upper_backgrounds; std::vector lower_backgrounds; - Push2Knob* knobs[8]; + + struct GainMeter : public ArdourCanvas::Container { + GainMeter (Item* parent, Push2&); + + Push2Knob* knob; + LevelMeter* meter; + }; + + GainMeter* gain_meter[8]; /* stripables */ diff --git a/libs/surfaces/push2/push2.cc b/libs/surfaces/push2/push2.cc index 339eadd500..3fb5b6c372 100644 --- a/libs/surfaces/push2/push2.cc +++ b/libs/surfaces/push2/push2.cc @@ -480,7 +480,10 @@ Push2::vblank () } } - track_mix_layout->update_meters (); + if (_current_layout) { + _current_layout->update_meters (); + _current_layout->update_clocks (); + } _canvas->vblank(); diff --git a/libs/surfaces/push2/track_mix.cc b/libs/surfaces/push2/track_mix.cc index 6bfd3c5f04..67602a809a 100644 --- a/libs/surfaces/push2/track_mix.cc +++ b/libs/surfaces/push2/track_mix.cc @@ -142,8 +142,19 @@ TrackMixLayout::TrackMixLayout (Push2& p, Session& s) name_text->set_font_description (fd); name_text->set_position (Duple (10 + (4*Push2Canvas::inter_button_spacing()), 2)); - meter = new LevelMeter (p2, this, 200, ArdourCanvas::Meter::Horizontal); - meter->set_position (Duple (10 + (4 * Push2Canvas::inter_button_spacing()), 50)); + meter = new LevelMeter (p2, this, 300, ArdourCanvas::Meter::Horizontal); + meter->set_position (Duple (10 + (4 * Push2Canvas::inter_button_spacing()), 30)); + + Pango::FontDescription fd2 ("Sans 18"); + bbt_text = new Text (this); + bbt_text->set_font_description (fd2); + bbt_text->set_color (p2.get_color (Push2::LightBackground)); + bbt_text->set_position (Duple (10 + (4 * Push2Canvas::inter_button_spacing()), 60)); + + minsec_text = new Text (this); + minsec_text->set_font_description (fd2); + minsec_text->set_color (p2.get_color (Push2::LightBackground)); + minsec_text->set_position (Duple (10 + (4 * Push2Canvas::inter_button_spacing()), 90)); ControlProtocol::StripableSelectionChanged.connect (selection_connection, invalidator (*this), boost::bind (&TrackMixLayout::selection_changed, this), &p2); } @@ -158,6 +169,10 @@ TrackMixLayout::~TrackMixLayout () void TrackMixLayout::selection_changed () { + if (!parent()) { + return; + } + boost::shared_ptr s = ControlProtocol::first_selected_stripable(); if (s) { set_stripable (s); @@ -267,17 +282,16 @@ TrackMixLayout::button_right () void TrackMixLayout::simple_control_change (boost::shared_ptr ac, Push2::ButtonID bid) { - if (!ac) { + if (!ac || !parent()) { return; } Push2::Button* b = p2.button_by_id (bid); - if (!bid) { + if (!b) { return; } - if (ac->get_value()) { b->set_color (selection_color); } else { @@ -288,23 +302,61 @@ TrackMixLayout::simple_control_change (boost::shared_ptr ac, } void -TrackMixLayout::solo_change () +TrackMixLayout::solo_mute_change () { if (!stripable) { return; } - simple_control_change (stripable->solo_control(), Push2::Lower2); -} + Push2::Button* b = p2.button_by_id (Push2::Lower2); + + if (b) { + boost::shared_ptr sc = stripable->solo_control(); + + if (sc) { + if (sc->soloed_by_self_or_masters()) { + b->set_color (selection_color); + b->set_state (Push2::LED::OneShot24th); + } else if (sc->soloed_by_others_upstream() || sc->soloed_by_others_downstream()) { + b->set_color (selection_color); + b->set_state (Push2::LED::Blinking8th); + } else { + b->set_color (Push2::LED::DarkGray); + b->set_state (Push2::LED::OneShot24th); + } + } else { + b->set_color (Push2::LED::DarkGray); + b->set_state (Push2::LED::OneShot24th); + } -void -TrackMixLayout::mute_change () -{ - if (!stripable) { - return; + p2.write (b->state_msg()); + } + + b = p2.button_by_id (Push2::Lower1); + + if (b) { + boost::shared_ptr mc = stripable->mute_control(); + + if (mc) { + if (mc->muted_by_self_or_masters()) { + b->set_color (selection_color); + b->set_state (Push2::LED::OneShot24th); + } else if (mc->muted_by_others_soloing()) { + b->set_color (selection_color); + b->set_state (Push2::LED::Blinking8th); + } else { + b->set_color (Push2::LED::DarkGray); + b->set_state (Push2::LED::OneShot24th); + } + + } else { + b->set_color (Push2::LED::DarkGray); + b->set_state (Push2::LED::OneShot24th); + } + + p2.write (b->state_msg()); } - simple_control_change (stripable->mute_control(), Push2::Lower1); } void @@ -396,8 +448,8 @@ TrackMixLayout::set_stripable (boost::shared_ptr s) stripable->PropertyChanged.connect (stripable_connections, invalidator (*this), boost::bind (&TrackMixLayout::stripable_property_change, this, _1), &p2); stripable->presentation_info().PropertyChanged.connect (stripable_connections, invalidator (*this), boost::bind (&TrackMixLayout::stripable_property_change, this, _1), &p2); - stripable->solo_control()->Changed.connect (stripable_connections, invalidator (*this), boost::bind (&TrackMixLayout::solo_change, this), &p2); - stripable->mute_control()->Changed.connect (stripable_connections, invalidator (*this), boost::bind (&TrackMixLayout::mute_change, this), &p2); + stripable->solo_control()->Changed.connect (stripable_connections, invalidator (*this), boost::bind (&TrackMixLayout::solo_mute_change, this), &p2); + stripable->mute_control()->Changed.connect (stripable_connections, invalidator (*this), boost::bind (&TrackMixLayout::solo_mute_change, this), &p2); stripable->solo_isolate_control()->Changed.connect (stripable_connections, invalidator (*this), boost::bind (&TrackMixLayout::solo_iso_change, this), &p2); stripable->solo_safe_control()->Changed.connect (stripable_connections, invalidator (*this), boost::bind (&TrackMixLayout::solo_safe_change, this), &p2); @@ -422,8 +474,7 @@ TrackMixLayout::set_stripable (boost::shared_ptr s) name_changed (); color_changed (); - solo_change (); - mute_change (); + solo_mute_change (); rec_enable_change (); solo_iso_change (); solo_safe_change (); @@ -447,7 +498,7 @@ TrackMixLayout::name_changed () { if (stripable) { /* poor-man's right justification */ - char buf[96]; + char buf[92]; snprintf (buf, sizeof (buf), "%*s", (int) sizeof (buf) - 1, stripable->name().c_str()); name_text->set (buf); } @@ -515,3 +566,55 @@ TrackMixLayout::update_meters () meter->update_meters (); } + +void +TrackMixLayout::update_clocks () +{ + framepos_t pos = session.audible_frame(); + bool negative = false; + + if (pos < 0) { + pos = -pos; + negative = true; + } + + char buf[16]; + Timecode::BBT_Time BBT = session.tempo_map().bbt_at_frame (pos); + +#define BBT_BAR_CHAR "|" + + if (negative) { + snprintf (buf, sizeof (buf), "-%03" PRIu32 BBT_BAR_CHAR "%02" PRIu32 BBT_BAR_CHAR "%04" PRIu32, + BBT.bars, BBT.beats, BBT.ticks); + } else { + snprintf (buf, sizeof (buf), " %03" PRIu32 BBT_BAR_CHAR "%02" PRIu32 BBT_BAR_CHAR "%04" PRIu32, + BBT.bars, BBT.beats, BBT.ticks); + } + + bbt_text->set (buf); + + framecnt_t left; + int hrs; + int mins; + int secs; + int millisecs; + + const double frame_rate = session.frame_rate (); + + left = pos; + hrs = (int) floor (left / (frame_rate * 60.0f * 60.0f)); + left -= (framecnt_t) floor (hrs * frame_rate * 60.0f * 60.0f); + mins = (int) floor (left / (frame_rate * 60.0f)); + left -= (framecnt_t) floor (mins * frame_rate * 60.0f); + secs = (int) floor (left / (float) frame_rate); + left -= (framecnt_t) floor ((double)(secs * frame_rate)); + millisecs = floor (left * 1000.0 / (float) frame_rate); + + if (negative) { + snprintf (buf, sizeof (buf), "-%02" PRId32 ":%02" PRId32 ":%02" PRId32 ".%03" PRId32, hrs, mins, secs, millisecs); + } else { + snprintf (buf, sizeof (buf), " %02" PRId32 ":%02" PRId32 ":%02" PRId32 ".%03" PRId32, hrs, mins, secs, millisecs); + } + + minsec_text->set (buf); +} diff --git a/libs/surfaces/push2/track_mix.h b/libs/surfaces/push2/track_mix.h index 8ba95344b0..417c394f95 100644 --- a/libs/surfaces/push2/track_mix.h +++ b/libs/surfaces/push2/track_mix.h @@ -61,6 +61,7 @@ class TrackMixLayout : public Push2Layout void strip_vpot_touch (int, bool); void update_meters (); + void update_clocks (); private: boost::shared_ptr stripable; @@ -71,6 +72,8 @@ class TrackMixLayout : public Push2Layout std::vector upper_text; std::vector lower_text; ArdourCanvas::Text* name_text; + ArdourCanvas::Text* bbt_text; + ArdourCanvas::Text* minsec_text; uint8_t selection_color; Push2Knob* knobs[8]; @@ -86,8 +89,7 @@ class TrackMixLayout : public Push2Layout void name_changed (); void color_changed (); - void solo_change (); - void mute_change (); + void solo_mute_change (); void rec_enable_change (); void solo_iso_change (); void solo_safe_change (); -- 2.30.2