X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=gtk2_ardour%2Fmeter_strip.cc;h=cd15dd5bb050332b4eda1ccada4f4fe5be5b35f8;hb=424d368614eda4b3c34d1a0962ef641d6850fb6d;hp=2de25983b0029b61f13d66bb9b4d24aa1e3a47f5;hpb=c38898f1a655901703a24be5ff7be2f2b0ad217e;p=ardour.git diff --git a/gtk2_ardour/meter_strip.cc b/gtk2_ardour/meter_strip.cc index 2de25983b0..cd15dd5bb0 100644 --- a/gtk2_ardour/meter_strip.cc +++ b/gtk2_ardour/meter_strip.cc @@ -43,6 +43,7 @@ #include "meterbridge.h" #include "meter_strip.h" +#include "meter_patterns.h" #include "i18n.h" @@ -53,13 +54,7 @@ using namespace Gtkmm2ext; using namespace std; PBD::Signal1 MeterStrip::CatchDeletion; -PBD::Signal0 MeterStrip::ResetAllPeakDisplays; -PBD::Signal1 MeterStrip::ResetGroupPeakDisplays; - - -MeterStrip::MetricPatterns MeterStrip::metric_patterns; -MeterStrip::TickPatterns MeterStrip::ticks_patterns; -int MeterStrip::max_pattern_metric_size = 1026; // +2 border +PBD::Signal0 MeterStrip::MetricChanged; MeterStrip::MeterStrip (int metricmode) : AxisView(0) @@ -71,27 +66,7 @@ MeterStrip::MeterStrip (int metricmode) btnbox.set_size_request(-1, 16); namebx.set_size_request(18, 52); - _types.clear (); - switch(metricmode) { - case 1: - meter_metric_area.set_name ("AudioBusMetrics"); - _types.push_back (DataType::AUDIO); - break; - case 2: - meter_metric_area.set_name ("AudioTrackMetrics"); - _types.push_back (DataType::AUDIO); - break; - case 3: - meter_metric_area.set_name ("MidiTrackMetrics"); - _types.push_back (DataType::MIDI); - break; - default: - meter_metric_area.set_name ("AudioMidiTrackMetrics"); - _types.push_back (DataType::AUDIO); - _types.push_back (DataType::MIDI); - break; - } - //meter_metric_area.queue_draw (); + set_metric_mode(metricmode); set_size_request_to_display_given_text (meter_metric_area, "-8888", 1, 0); meter_metric_area.signal_expose_event().connect ( @@ -124,6 +99,8 @@ MeterStrip::MeterStrip (Session* sess, boost::shared_ptr rt) set_spacing(2); RouteUI::set_route (rt); + _has_midi = false; + int meter_width = 6; if (_route->shared_peak_meter()->input_streams().n_total() == 1) { meter_width = 12; @@ -158,7 +135,7 @@ MeterStrip::MeterStrip (Session* sess, boost::shared_ptr rt) // add track-name label name_label.set_text(_route->name().c_str()); name_label.set_corner_radius(2); - name_label.set_name("solo isolate"); // XXX re-use 'very_small_text' + name_label.set_name("meterbridge label"); name_label.set_angle(-90.0); name_label.layout()->set_ellipsize (Pango::ELLIPSIZE_END); name_label.layout()->set_width(48 * PANGO_SCALE); @@ -193,6 +170,10 @@ MeterStrip::MeterStrip (Session* sess, boost::shared_ptr rt) _route->shared_peak_meter()->ConfigurationChanged.connect ( route_connections, invalidator (*this), boost::bind (&MeterStrip::meter_configuration_changed, this, _1), gui_context() ); + + ResetAllPeakDisplays.connect (sigc::mem_fun(*this, &MeterStrip::reset_peak_display)); + ResetGroupPeakDisplays.connect (sigc::mem_fun(*this, &MeterStrip::reset_group_peak_display)); + meter_configuration_changed (_route->shared_peak_meter()->input_streams ()); meter_ticks1_area.set_size_request(3,-1); @@ -267,8 +248,7 @@ MeterStrip::fast_update () void MeterStrip::on_theme_changed() { - metric_patterns.clear(); - ticks_patterns.clear(); + meter_clear_pattern_cache(); if (level_meter && _route) { int meter_width = 6; @@ -287,6 +267,7 @@ MeterStrip::meter_configuration_changed (ChanCount c) { int type = 0; _types.clear (); + bool old_has_midi = _has_midi; for (DataType::iterator i = DataType::begin(); i != DataType::end(); ++i) { if (c.get (*i) > 0) { @@ -299,37 +280,40 @@ MeterStrip::meter_configuration_changed (ChanCount c) if (boost::dynamic_pointer_cast(_route) == 0 && boost::dynamic_pointer_cast(_route) == 0 ) { - meter_ticks1_area.set_name ("AudioBusMetrics"); - meter_ticks2_area.set_name ("AudioBusMetrics"); + meter_ticks1_area.set_name ("AudioBusMetricsLeft"); + meter_ticks2_area.set_name ("AudioBusMetricsRight"); + _has_midi = false; } else if (type == (1 << DataType::AUDIO)) { - meter_ticks1_area.set_name ("AudioTrackMetrics"); - meter_ticks2_area.set_name ("AudioTrackMetrics"); + meter_ticks1_area.set_name ("AudioTrackMetricsLeft"); + meter_ticks2_area.set_name ("AudioTrackMetricsRight"); + _has_midi = false; } else if (type == (1 << DataType::MIDI)) { - meter_ticks1_area.set_name ("MidiTrackMetrics"); - meter_ticks2_area.set_name ("MidiTrackMetrics"); + meter_ticks1_area.set_name ("MidiTrackMetricsLeft"); + meter_ticks2_area.set_name ("MidiTrackMetricsRight"); + _has_midi = true; } else { - meter_ticks1_area.set_name ("AudioMidiTrackMetrics"); - meter_ticks2_area.set_name ("AudioMidiTrackMetrics"); + meter_ticks1_area.set_name ("AudioMidiTrackMetricsLeft"); + meter_ticks2_area.set_name ("AudioMidiTrackMetricsRight"); + _has_midi = true; } + if (old_has_midi != _has_midi) MetricChanged(); on_theme_changed(); } void MeterStrip::on_size_request (Gtk::Requisition* r) { - metric_patterns.clear(); - ticks_patterns.clear(); + meter_clear_pattern_cache(); VBox::on_size_request(r); } void MeterStrip::on_size_allocate (Gtk::Allocation& a) { - metric_patterns.clear(); - ticks_patterns.clear(); + meter_clear_pattern_cache(); const int wh = a.get_height(); int nh = ceilf(wh * .11f); if (nh < 52) nh = 52; @@ -342,458 +326,49 @@ MeterStrip::on_size_allocate (Gtk::Allocation& a) VBox::on_size_allocate(a); } -/* XXX code-copy from gain_meter.cc -- TODO consolidate - * - * slightly different: - * - ticks & label positions are swapped - * - more ticks for audio (longer meter by default) - * - right-aligned lables, unit-legend - * - height limitation of FastMeter::max_pattern_metric_size is included here - */ -cairo_pattern_t* -MeterStrip::render_metrics (Gtk::Widget& w, vector types) -{ - Glib::RefPtr win (w.get_window()); - - gint width, height; - win->get_size (width, height); - - cairo_surface_t* surface = cairo_image_surface_create (CAIRO_FORMAT_RGB24, width, height); - cairo_t* cr = cairo_create (surface); - Glib::RefPtr layout = Pango::Layout::create(w.get_pango_context()); - - Pango::AttrList audio_font_attributes; - Pango::AttrList midi_font_attributes; - Pango::AttrList unit_font_attributes; - - Pango::AttrFontDesc* font_attr; - Pango::FontDescription font; - - font = Pango::FontDescription (""); // use defaults - //font = get_font_for_style("gain-fader"); - //font = w.get_style()->get_font(); - - font.set_weight (Pango::WEIGHT_NORMAL); - font.set_size (9.0 * PANGO_SCALE); - font_attr = new Pango::AttrFontDesc (Pango::Attribute::create_attr_font_desc (font)); - audio_font_attributes.change (*font_attr); - delete font_attr; - - font.set_weight (Pango::WEIGHT_ULTRALIGHT); - font.set_stretch (Pango::STRETCH_ULTRA_CONDENSED); - font.set_size (7.5 * PANGO_SCALE); - font_attr = new Pango::AttrFontDesc (Pango::Attribute::create_attr_font_desc (font)); - midi_font_attributes.change (*font_attr); - delete font_attr; - - font.set_size (7.0 * PANGO_SCALE); - font_attr = new Pango::AttrFontDesc (Pango::Attribute::create_attr_font_desc (font)); - unit_font_attributes.change (*font_attr); - delete font_attr; - - cairo_move_to (cr, 0, 0); - cairo_rectangle (cr, 0, 0, width, height); - { - Gdk::Color c = w.get_style()->get_bg (Gtk::STATE_NORMAL); - cairo_set_source_rgb (cr, c.get_red_p(), c.get_green_p(), c.get_blue_p()); - } - cairo_fill (cr); - - if (height > max_pattern_metric_size) { - cairo_move_to (cr, 0, max_pattern_metric_size + 1); - cairo_rectangle (cr, 0, max_pattern_metric_size, width, height - max_pattern_metric_size); - Gdk::Color c = w.get_style()->get_bg (Gtk::STATE_ACTIVE); - cairo_set_source_rgb (cr, c.get_red_p(), c.get_green_p(), c.get_blue_p()); - cairo_fill (cr); - } - - height = min(max_pattern_metric_size, height); - uint32_t peakcolor = ARDOUR_UI::config()->color_by_name ("meterbridge peaklabel"); - - for (vector::const_iterator i = types.begin(); i != types.end(); ++i) { - - Gdk::Color c; - - if (types.size() > 1) { - /* we're overlaying more than 1 set of marks, so use different colours */ - Gdk::Color c; - switch (*i) { - case DataType::AUDIO: - c = w.get_style()->get_fg (Gtk::STATE_NORMAL); - cairo_set_source_rgb (cr, c.get_red_p(), c.get_green_p(), c.get_blue_p()); - break; - case DataType::MIDI: - c = w.get_style()->get_fg (Gtk::STATE_ACTIVE); - cairo_set_source_rgb (cr, c.get_red_p(), c.get_green_p(), c.get_blue_p()); - break; - } - } else { - c = w.get_style()->get_fg (Gtk::STATE_NORMAL); - cairo_set_source_rgb (cr, c.get_red_p(), c.get_green_p(), c.get_blue_p()); - } - - std::map points; - - switch (*i) { - case DataType::AUDIO: - layout->set_attributes (audio_font_attributes); - points.insert (std::pair(-50, 0.5)); - points.insert (std::pair(-40, 0.5)); - points.insert (std::pair(-30, 0.5)); - points.insert (std::pair(-25, 0.5)); - points.insert (std::pair(-20, 1.0)); - points.insert (std::pair(-18, 1.0)); - points.insert (std::pair(-15, 1.0)); - points.insert (std::pair(-10, 1.0)); - points.insert (std::pair( -5, 1.0)); - points.insert (std::pair( -3, 0.5)); - points.insert (std::pair( 0, 1.0)); - points.insert (std::pair( 3, 0.5)); - break; - - case DataType::MIDI: - layout->set_attributes (midi_font_attributes); - points.insert (std::pair( 0, 1.0)); - if (types.size() == 1) { - points.insert (std::pair( 16, 0.5)); - points.insert (std::pair( 32, 0.5)); - points.insert (std::pair( 48, 0.5)); - points.insert (std::pair( 64, 1.0)); - points.insert (std::pair( 80, 0.5)); - points.insert (std::pair( 96, 0.5)); - points.insert (std::pair(100, 0.5)); - points.insert (std::pair(112, 0.5)); - } else { - /* labels that don't overlay with dB */ - points.insert (std::pair( 48, 0.5)); - points.insert (std::pair( 72, 0.5)); - points.insert (std::pair( 88, 0.5)); - } - points.insert (std::pair(127, 1.0)); - break; - } - - char buf[32]; - gint pos; - - for (std::map::const_iterator j = points.begin(); j != points.end(); ++j) { - - float fraction = 0; - switch (*i) { - case DataType::AUDIO: - cairo_set_line_width (cr, (j->second)); - if (j->first >= 0) { - cairo_set_source_rgb (cr, - UINT_RGBA_R_FLT(peakcolor), - UINT_RGBA_G_FLT(peakcolor), - UINT_RGBA_B_FLT(peakcolor)); - } - fraction = log_meter (j->first); - snprintf (buf, sizeof (buf), "%+2d", j->first); - pos = height - (gint) floor (height * fraction); - cairo_move_to(cr, width-2.5, pos + .5); - cairo_line_to(cr, width, pos + .5); - cairo_stroke (cr); - break; - case DataType::MIDI: - cairo_set_line_width (cr, 1.0); - fraction = (j->first) / 127.0; - snprintf (buf, sizeof (buf), "%3d", j->first); - pos = 1 + height - (gint) rintf (height * fraction); - pos = min (pos, height); - cairo_arc(cr, 3, pos + .5, 1.0, 0, 2 * M_PI); - cairo_fill(cr); - break; - } - - layout->set_text(buf); - - /* we want logical extents, not ink extents here */ - - int tw, th; - layout->get_pixel_size(tw, th); - - int p = pos - (th / 2); - p = min (p, height - th); - p = max (p, 0); - - cairo_move_to (cr, width-4-tw, p); - pango_cairo_show_layout (cr, layout->gobj()); - } - } - - if (types.size() == 1) { - int tw, th; - layout->set_attributes (unit_font_attributes); - switch (types.at(0)) { - case DataType::AUDIO: - layout->set_text("dBFS"); - layout->get_pixel_size(tw, th); - break; - case DataType::MIDI: - layout->set_text("vel"); - layout->get_pixel_size(tw, th); - break; - } - Gdk::Color c = w.get_style()->get_fg (Gtk::STATE_ACTIVE); - cairo_set_source_rgb (cr, c.get_red_p(), c.get_green_p(), c.get_blue_p()); - cairo_move_to (cr, 1, height - th - 1.5); - pango_cairo_show_layout (cr, layout->gobj()); - } - - cairo_pattern_t* pattern = cairo_pattern_create_for_surface (surface); - MetricPatterns::iterator p; - - if ((p = metric_patterns.find (w.get_name())) != metric_patterns.end()) { - cairo_pattern_destroy (p->second); - } - - metric_patterns[w.get_name()] = pattern; - - cairo_destroy (cr); - cairo_surface_destroy (surface); - - return pattern; -} - -/* XXX code-copy from gain_meter.cc -- TODO consolidate */ gint MeterStrip::meter_metrics_expose (GdkEventExpose *ev) { - Glib::RefPtr win (meter_metric_area.get_window()); - cairo_t* cr; - - cr = gdk_cairo_create (win->gobj()); - - /* clip to expose area */ - - gdk_cairo_rectangle (cr, &ev->area); - cairo_clip (cr); - - cairo_pattern_t* pattern; - MetricPatterns::iterator i = metric_patterns.find (meter_metric_area.get_name()); - - if (i == metric_patterns.end()) { - pattern = render_metrics (meter_metric_area, _types); - } else { - pattern = i->second; - } - - cairo_move_to (cr, 0, 0); - cairo_set_source (cr, pattern); - - gint width, height; - win->get_size (width, height); - - cairo_rectangle (cr, 0, 0, width, height); - cairo_fill (cr); - - cairo_destroy (cr); - - return true; + return meter_expose_metrics(ev, _types, &meter_metric_area); } -cairo_pattern_t* -MeterStrip::render_ticks (Gtk::Widget& w, vector types) +void +MeterStrip::set_metric_mode (int metricmode) { - Glib::RefPtr win (w.get_window()); - - gint width, height; - win->get_size (width, height); - - cairo_surface_t* surface = cairo_image_surface_create (CAIRO_FORMAT_RGB24, width, height); - cairo_t* cr = cairo_create (surface); - - cairo_move_to (cr, 0, 0); - cairo_rectangle (cr, 0, 0, width, height); - { - Gdk::Color c = w.get_style()->get_bg (Gtk::STATE_NORMAL); - cairo_set_source_rgb (cr, c.get_red_p(), c.get_green_p(), c.get_blue_p()); - } - cairo_fill (cr); - - if (height > max_pattern_metric_size) { - cairo_move_to (cr, 0, max_pattern_metric_size + 1); - cairo_rectangle (cr, 0, max_pattern_metric_size, width, height - max_pattern_metric_size); - Gdk::Color c = w.get_style()->get_bg (Gtk::STATE_ACTIVE); - cairo_set_source_rgb (cr, c.get_red_p(), c.get_green_p(), c.get_blue_p()); - cairo_fill (cr); - } - - height = min(max_pattern_metric_size, height); - uint32_t peakcolor = ARDOUR_UI::config()->color_by_name ("meterbridge peaklabel"); - - for (vector::const_iterator i = types.begin(); i != types.end(); ++i) { - - Gdk::Color c; - c = w.get_style()->get_fg (Gtk::STATE_NORMAL); - - if (types.size() > 1) { - /* we're overlaying more than 1 set of marks, so use different colours */ - switch (*i) { - case DataType::AUDIO: - c = w.get_style()->get_fg (Gtk::STATE_NORMAL); - cairo_set_source_rgb (cr, c.get_red_p(), c.get_green_p(), c.get_blue_p()); - break; - case DataType::MIDI: - c = w.get_style()->get_fg (Gtk::STATE_ACTIVE); - cairo_set_source_rgb (cr, c.get_red_p(), c.get_green_p(), c.get_blue_p()); - break; - } - } else { - c = w.get_style()->get_fg (Gtk::STATE_NORMAL); - cairo_set_source_rgb (cr, c.get_red_p(), c.get_green_p(), c.get_blue_p()); - } - - std::map points; - - switch (*i) { - case DataType::AUDIO: - points.insert (std::pair(-60, 0.5)); - points.insert (std::pair(-50, 0.5)); - points.insert (std::pair(-40, 0.5)); - points.insert (std::pair(-30, 0.5)); - points.insert (std::pair(-25, 0.5)); - points.insert (std::pair(-20, 1.0)); - - points.insert (std::pair(-19, 0.5)); - points.insert (std::pair(-18, 1.0)); - points.insert (std::pair(-17, 0.5)); - points.insert (std::pair(-16, 0.5)); - points.insert (std::pair(-15, 1.0)); - - points.insert (std::pair(-14, 0.5)); - points.insert (std::pair(-13, 0.5)); - points.insert (std::pair(-12, 0.5)); - points.insert (std::pair(-11, 0.5)); - points.insert (std::pair(-10, 1.0)); - - points.insert (std::pair( -9, 0.5)); - points.insert (std::pair( -8, 0.5)); - points.insert (std::pair( -7, 0.5)); - points.insert (std::pair( -6, 0.5)); - points.insert (std::pair( -5, 1.0)); - points.insert (std::pair( -4, 0.5)); - points.insert (std::pair( -3, 0.5)); - points.insert (std::pair( -2, 0.5)); - points.insert (std::pair( -1, 0.5)); - - points.insert (std::pair( 0, 1.0)); - points.insert (std::pair( 1, 0.5)); - points.insert (std::pair( 2, 0.5)); - points.insert (std::pair( 3, 0.5)); - points.insert (std::pair( 4, 0.5)); - points.insert (std::pair( 5, 0.5)); + _types.clear (); + switch(metricmode) { + case 0: + meter_metric_area.set_name ("MidiTrackMetricsLeft"); + _types.push_back (DataType::MIDI); break; - - case DataType::MIDI: - points.insert (std::pair( 0, 1.0)); - points.insert (std::pair( 16, 0.5)); - points.insert (std::pair( 32, 0.5)); - points.insert (std::pair( 48, 0.5)); - points.insert (std::pair( 64, 1.0)); - points.insert (std::pair( 80, 0.5)); - points.insert (std::pair( 96, 0.5)); - points.insert (std::pair(100, 1.0)); - points.insert (std::pair(112, 0.5)); - points.insert (std::pair(127, 1.0)); + case 1: + meter_metric_area.set_name ("AudioTrackMetricsLeft"); + _types.push_back (DataType::AUDIO); + break; + case 2: + meter_metric_area.set_name ("MidiTrackMetricsRight"); + _types.push_back (DataType::MIDI); + break; + case 3: + default: + meter_metric_area.set_name ("AudioTrackMetricsRight"); + _types.push_back (DataType::AUDIO); break; - } - - for (std::map::const_iterator j = points.begin(); j != points.end(); ++j) { - cairo_set_line_width (cr, (j->second)); - - float fraction = 0; - gint pos; - - switch (*i) { - case DataType::AUDIO: - if (j->first >= 0 || j->first == -9) { - cairo_set_source_rgb (cr, - UINT_RGBA_R_FLT(peakcolor), - UINT_RGBA_G_FLT(peakcolor), - UINT_RGBA_B_FLT(peakcolor)); - } else { - cairo_set_source_rgb (cr, c.get_red_p(), c.get_green_p(), c.get_blue_p()); - } - fraction = log_meter (j->first); - pos = height - (gint) floor (height * fraction); - cairo_move_to(cr, 0, pos + .5); - cairo_line_to(cr, 3, pos + .5); - cairo_stroke (cr); - break; - case DataType::MIDI: - fraction = (j->first) / 127.0; - pos = 1 + height - (gint) floor (height * fraction); - pos = min (pos, height); - cairo_arc(cr, 1.5, pos + .5, 1.0, 0, 2 * M_PI); - cairo_fill(cr); - break; - } - } - } - - cairo_pattern_t* pattern = cairo_pattern_create_for_surface (surface); - TickPatterns::iterator p; - - if ((p = ticks_patterns.find (w.get_name())) != metric_patterns.end()) { - cairo_pattern_destroy (p->second); } - ticks_patterns[w.get_name()] = pattern; - - cairo_destroy (cr); - cairo_surface_destroy (surface); - - return pattern; + meter_metric_area.queue_draw (); } gint MeterStrip::meter_ticks1_expose (GdkEventExpose *ev) { - return meter_ticks_expose(ev, &meter_ticks1_area); + return meter_expose_ticks(ev, _types, &meter_ticks1_area); } gint MeterStrip::meter_ticks2_expose (GdkEventExpose *ev) { - return meter_ticks_expose(ev, &meter_ticks2_area); -} - -gint -MeterStrip::meter_ticks_expose (GdkEventExpose *ev, Gtk::DrawingArea *mta) -{ - Glib::RefPtr win (mta->get_window()); - cairo_t* cr; - - cr = gdk_cairo_create (win->gobj()); - - /* clip to expose area */ - - gdk_cairo_rectangle (cr, &ev->area); - cairo_clip (cr); - - cairo_pattern_t* pattern; - TickPatterns::iterator i = ticks_patterns.find (mta->get_name()); - - if (i == ticks_patterns.end()) { - pattern = render_ticks (*mta, _types); - } else { - pattern = i->second; - } - - cairo_move_to (cr, 0, 0); - cairo_set_source (cr, pattern); - - gint width, height; - win->get_size (width, height); - - cairo_rectangle (cr, 0, 0, width, height); - cairo_fill (cr); - - cairo_destroy (cr); - - return true; + return meter_expose_ticks(ev, _types, &meter_ticks2_area); } void