diff --git a/gtk2_ardour/editor.cc b/gtk2_ardour/editor.cc index fd69b6c68b..219666391a 100644 --- a/gtk2_ardour/editor.cc +++ b/gtk2_ardour/editor.cc @@ -141,6 +141,7 @@ #include "playlist_selector.h" #include "public_editor.h" #include "quantize_dialog.h" +#include "region_peak_cursor.h" #include "region_layering_order_editor.h" #include "rgb_macros.h" #include "rhythm_ferret.h" @@ -284,6 +285,7 @@ Editor::Editor () , _track_canvas_viewport (0) , within_track_canvas (false) , _verbose_cursor (0) + , _region_peak_cursor (0) , tempo_group (0) , meter_group (0) , marker_group (0) @@ -873,6 +875,7 @@ Editor::~Editor() delete _drags; delete nudge_clock; delete _verbose_cursor; + delete _region_peak_cursor; delete quantize_dialog; delete _summary; delete _group_tabs; @@ -4714,6 +4717,7 @@ Editor::visual_changer (const VisualChange& vc) update_video_timeline(); } + _region_peak_cursor->hide (); _summary->set_overlays_dirty (); } diff --git a/gtk2_ardour/editor.h b/gtk2_ardour/editor.h index 3bec5f14d0..6dc396dc35 100644 --- a/gtk2_ardour/editor.h +++ b/gtk2_ardour/editor.h @@ -140,6 +140,7 @@ class PlaylistSelector; class PluginSelector; class ProgressReporter; class QuantizeDialog; +class RegionPeakCursor; class RhythmFerret; class RulerDialog; class Selection; @@ -848,6 +849,8 @@ private: friend class VerboseCursor; VerboseCursor* _verbose_cursor; + RegionPeakCursor* _region_peak_cursor; + void parameter_changed (std::string); void ui_parameter_changed (std::string); diff --git a/gtk2_ardour/editor_canvas.cc b/gtk2_ardour/editor_canvas.cc index a72867563d..adb2c011a0 100644 --- a/gtk2_ardour/editor_canvas.cc +++ b/gtk2_ardour/editor_canvas.cc @@ -58,6 +58,7 @@ #include "editor_cursors.h" #include "mouse_cursors.h" #include "note_base.h" +#include "region_peak_cursor.h" #include "ui_config.h" #include "verbose_cursor.h" @@ -105,6 +106,7 @@ Editor::initialize_canvas () _track_canvas->add_scroller (*cg); _verbose_cursor = new VerboseCursor (this); + _region_peak_cursor = new RegionPeakCursor (get_noscroll_group ()); /*a group to hold global rects like punch/loop indicators */ global_rect_group = new ArdourCanvas::Container (hv_scroll_group); @@ -993,6 +995,7 @@ void Editor::tie_vertical_scrolling () { if (pending_visual_change.idle_handler_id < 0) { + _region_peak_cursor->hide (); _summary->set_overlays_dirty (); } } diff --git a/gtk2_ardour/editor_mouse.cc b/gtk2_ardour/editor_mouse.cc index 6be13c03a6..1e9ba3ef3e 100644 --- a/gtk2_ardour/editor_mouse.cc +++ b/gtk2_ardour/editor_mouse.cc @@ -81,6 +81,7 @@ #include "edit_note_dialog.h" #include "mouse_cursors.h" #include "editor_cursors.h" +#include "region_peak_cursor.h" #include "verbose_cursor.h" #include "note.h" @@ -2216,13 +2217,28 @@ Editor::motion_handler (ArdourCanvas::Item* /*item*/, GdkEvent* event, bool from //drags change the snapped_cursor location, because we are snapping the thing being dragged, not the actual mouse cursor return _drags->motion_handler (event, from_autoscroll); } else { - //the snapped_cursor shows where an operation (like Split) is going to occur bool ignored; + bool peaks_visible = false; MusicSample where (0, 0); if (mouse_sample (where.sample, ignored)) { + + /* display peaks */ + if (mouse_mode == MouseContent || ArdourKeyboard::indicates_snap (event->motion.state)) { + AudioRegionView* arv = dynamic_cast(entered_regionview); + if (arv) { + _region_peak_cursor->set (arv, where.sample, samples_per_pixel); + peaks_visible = true; + } + } + + /* the snapped_cursor shows where an operation (like Split) is going to occur */ snap_to_with_modifier (where, event); set_snapped_cursor_position (where.sample); } + + if (!peaks_visible) { + _region_peak_cursor->hide (); + } } return false; diff --git a/gtk2_ardour/region_peak_cursor.cc b/gtk2_ardour/region_peak_cursor.cc new file mode 100644 index 0000000000..2b42a0bb34 --- /dev/null +++ b/gtk2_ardour/region_peak_cursor.cc @@ -0,0 +1,138 @@ +/* + * Copyright (C) 2020 Robin Gareus + * + * 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., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "canvas/arrow.h" +#include "canvas/tracking_text.h" + +#include "ardour/audioregion.h" +#include "ardour/dB.h" + +#include "audio_region_view.h" +#include "region_peak_cursor.h" +#include "ui_config.h" + +#include "pbd/i18n.h" + +using namespace std; +using namespace ARDOUR; + +RegionPeakCursor::RegionPeakCursor (ArdourCanvas::Item* parent) +{ + _canvas_text = new ArdourCanvas::Text (parent); + _canvas_text->set_outline (true); + _canvas_text->set_font_description (Pango::FontDescription (UIConfiguration::instance ().get_NormalMonospaceFont ())); + _canvas_text->set_ignore_events (true); + + _canvas_line = new ArdourCanvas::Arrow (parent); + _canvas_line->set_show_head (0, true); + _canvas_line->set_show_head (1, true); + _canvas_line->set_ignore_events (true); + + color_handler (); + UIConfiguration::instance ().ColorsChanged.connect (sigc::mem_fun (*this, &RegionPeakCursor::color_handler)); +} + +RegionPeakCursor::~RegionPeakCursor () +{ +#if 0 + _canvas_text->unparent (); + delete _canvas_text; + _canvas_line->unparent (); + delete _canvas_line; +#endif +} + +void +RegionPeakCursor::color_handler () +{ + _canvas_text->set_color (UIConfiguration::instance ().color ("gtk_foreground")); +} + +void +RegionPeakCursor::show () +{ + _canvas_line->show (); + _canvas_line->raise_to_top (); + _canvas_text->show (); + _canvas_text->raise_to_top (); + _canvas_text->parent ()->raise_to_top (); +} + +void +RegionPeakCursor::hide () +{ + _canvas_text->hide (); + _canvas_line->hide (); +} + +void +RegionPeakCursor::set (AudioRegionView* arv, samplepos_t when, samplecnt_t samples_per_pixel) +{ + boost::shared_ptr ar = boost::dynamic_pointer_cast (arv->region ()); + assert (ar); + assert (ar->n_channels () > 0); + + sampleoffset_t s = when + ar->start () - ar->position (); + if (s < 0 || s > ar->length ()) { + hide (); + return; + } + + PeakData p; + for (uint32_t chn = 0; chn < ar->n_channels (); ++chn) { + PeakData pc; + ar->read_peaks (&pc, 1, s, samples_per_pixel, chn, samples_per_pixel); + if (chn == 0) { + p.min = pc.min; + p.max = pc.max; + } else { + p.min = std::min (p.min, pc.min); + p.max = std::max (p.max, pc.max); + } + } + + char tmp[128]; + sprintf (tmp, "%s %+.2f %5.1f %s\n%s %+.2f %5.1f %s\n", + _("Max:"), p.max, + accurate_coefficient_to_dB (fabsf (p.max)), _("dBFS"), + _("Min:"), p.min, + accurate_coefficient_to_dB (fabsf (p.min)), _("dBFS")); + + _canvas_text->set (tmp); + + /* position relative to editor origin */ + ArdourCanvas::Duple pos = arv->get_canvas_group ()->item_to_window (_canvas_text->parent ()->position ()); + double xpos = pos.x + floor ((when - ar->position ()) / samples_per_pixel); + + _canvas_text->set_x_position (xpos + 3); + _canvas_text->set_y_position (pos.y + 3); + + _canvas_line->set_x (xpos - 0.5); + _canvas_line->set_y0 (pos.y); + _canvas_line->set_y1 (pos.y + arv->height ()); + + if (!visible ()) { + show (); + } +} + +bool +RegionPeakCursor::visible () const +{ + return _canvas_text->visible (); +} diff --git a/gtk2_ardour/region_peak_cursor.h b/gtk2_ardour/region_peak_cursor.h new file mode 100644 index 0000000000..a7d9497479 --- /dev/null +++ b/gtk2_ardour/region_peak_cursor.h @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2020 Robin Gareus + * + * 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., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef _gtk_ardour_region_peak_cursor_h_ +#define _gtk_ardour_region_peak_cursor_h_ + +#include "ardour/types.h" +#include "canvas/canvas.h" + +namespace ArdourCanvas +{ + class Text; + class Arrow; +} + +class AudioRegionView; + +class RegionPeakCursor +{ +public: + RegionPeakCursor (ArdourCanvas::Item*); + ~RegionPeakCursor (); + + void set (AudioRegionView*, samplepos_t, samplecnt_t); + void hide (); + bool visible () const; + +private: + void color_handler (); + void show (); + + ArdourCanvas::Text* _canvas_text; + ArdourCanvas::Arrow* _canvas_line; +}; + +#endif diff --git a/gtk2_ardour/wscript b/gtk2_ardour/wscript index 912386f2eb..0d2746d550 100644 --- a/gtk2_ardour/wscript +++ b/gtk2_ardour/wscript @@ -227,6 +227,7 @@ gtk2_ardour_sources = [ 'region_editor.cc', 'region_gain_line.cc', 'region_layering_order_editor.cc', + 'region_peak_cursor.cc', 'region_selection.cc', 'region_view.cc', 'return_ui.cc',