summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarl Hetherington <cth@carlh.net>2025-04-17 02:09:09 +0200
committerCarl Hetherington <cth@carlh.net>2025-04-20 21:18:05 +0200
commit2136a540da3f2fe55966db8f30a05193bcb83484 (patch)
tree30f7371c4e2e1d59a875f2f0276d9a017bbfe4e7
parent9323d3ec1e168a7003b5c0515247129c2fb3d1e7 (diff)
wip: audio meters.
-rw-r--r--src/lib/butler.cc13
-rw-r--r--src/lib/butler.h5
-rw-r--r--src/lib/level_calculator.cc127
-rw-r--r--src/lib/level_calculator.h74
-rw-r--r--src/lib/wscript1
-rw-r--r--src/tools/dcpomatic_player.cc8
-rw-r--r--src/wx/film_viewer.cc19
-rw-r--r--src/wx/film_viewer.h3
-rw-r--r--src/wx/meters_dialog.cc44
-rw-r--r--src/wx/meters_dialog.h40
-rw-r--r--src/wx/simple_meters.cc103
-rw-r--r--src/wx/simple_meters.h63
-rw-r--r--src/wx/simple_video_view.cc5
-rw-r--r--src/wx/simple_video_view.h7
-rw-r--r--src/wx/wscript2
15 files changed, 512 insertions, 2 deletions
diff --git a/src/lib/butler.cc b/src/lib/butler.cc
index 14f342045..57c891404 100644
--- a/src/lib/butler.cc
+++ b/src/lib/butler.cc
@@ -24,6 +24,7 @@
#include "cross.h"
#include "dcpomatic_log.h"
#include "exceptions.h"
+#include "level_calculator.h"
#include "log.h"
#include "player.h"
#include "util.h"
@@ -33,6 +34,7 @@
using std::cout;
using std::function;
using std::make_pair;
+using std::make_shared;
using std::pair;
using std::shared_ptr;
using std::string;
@@ -88,6 +90,7 @@ Butler::Butler(
, _alignment(alignment)
, _fast(fast)
, _prepare_only_proxy(prepare_only_proxy)
+ , _level_calculator(make_shared<LevelCalculator>())
{
_player_video_connection = _player.Video.connect(bind(&Butler::video, this, _1, _2));
_player_audio_connection = _player.Audio.connect(bind(&Butler::audio, this, _1, _2, _3));
@@ -312,6 +315,7 @@ Butler::seek_unlocked(DCPTime position, bool accurate)
_video.clear();
_audio.clear();
+ _level_calculator->clear();
_closed_caption.clear();
_summon.notify_all();
@@ -370,6 +374,8 @@ Butler::audio(shared_ptr<AudioBuffers> audio, DCPTime time, int frame_rate)
return;
}
+ _level_calculator->put(audio, time, frame_rate);
+
_audio.put(remap(audio, _audio_channels, _audio_mapping), time, frame_rate);
}
@@ -481,3 +487,10 @@ Butler::Error::summary() const
return "";
}
+
+shared_ptr<LevelCalculator>
+Butler::level_calculator() const
+{
+ return _level_calculator;
+}
+
diff --git a/src/lib/butler.h b/src/lib/butler.h
index ad2552769..dd04e7b86 100644
--- a/src/lib/butler.h
+++ b/src/lib/butler.h
@@ -37,6 +37,7 @@
#include <boost/thread/condition.hpp>
+class LevelCalculator;
class Player;
class PlayerVideo;
@@ -94,6 +95,8 @@ public:
boost::optional<dcpomatic::DCPTime> get_audio(Behaviour behaviour, float* out, Frame frames);
boost::optional<TextRingBuffers::Data> get_closed_caption();
+ std::shared_ptr<LevelCalculator> level_calculator() const;
+
std::pair<size_t, std::string> memory_used() const;
private:
@@ -154,6 +157,8 @@ private:
*/
boost::optional<dcpomatic::DCPTime> _awaiting;
+ std::shared_ptr<LevelCalculator> _level_calculator;
+
boost::signals2::scoped_connection _player_video_connection;
boost::signals2::scoped_connection _player_audio_connection;
boost::signals2::scoped_connection _player_text_connection;
diff --git a/src/lib/level_calculator.cc b/src/lib/level_calculator.cc
new file mode 100644
index 000000000..0563d4ed8
--- /dev/null
+++ b/src/lib/level_calculator.cc
@@ -0,0 +1,127 @@
+/*
+ Copyright (C) 2025 Carl Hetherington <cth@carlh.net>
+
+ This file is part of DCP-o-matic.
+
+ DCP-o-matic 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.
+
+ DCP-o-matic 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 DCP-o-matic. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+
+#include "audio_buffers.h"
+#include "level_calculator.h"
+
+
+using std::make_pair;
+using std::shared_ptr;
+using boost::optional;
+
+
+constexpr int frames_per_measurement = 48000 / 30;
+
+
+LevelCalculator::LevelCalculator()
+ : _enabled(false)
+{
+
+}
+
+
+void
+LevelCalculator::put(shared_ptr<const AudioBuffers> audio, dcpomatic::DCPTime time, int frame_rate)
+{
+ if (!_enabled) {
+ std::cout << "no calcs for me.\n";
+ return;
+ }
+
+ boost::mutex::scoped_lock lm(_current_mutex);
+
+ auto const channels = audio->channels();
+
+ if (static_cast<int>(_current_peaks.size()) != channels) {
+ _current_peaks.resize(channels);
+ }
+
+ auto const data = audio->data();
+ auto const frames = audio->frames();
+ for (auto frame = 0; frame < frames; ++frame) {
+ for (auto channel = 0; channel < channels; ++channel) {
+ _current_peaks[channel] = std::max(std::abs(data[channel][frame]), _current_peaks[channel]);
+ }
+
+ ++_current_frames;
+ if (_current_frames == frames_per_measurement) {
+ {
+ boost::mutex::scoped_lock lm(_store_mutex);
+ _peaks.emplace_back(time + dcpomatic::DCPTime::from_frames(frame, frame_rate), _current_peaks);
+ }
+ std::fill(_current_peaks.begin(), _current_peaks.end(), 0.0f);
+ _current_frames = 0;
+ }
+ }
+
+}
+
+
+void
+LevelCalculator::clear()
+{
+ boost::mutex::scoped_lock slm(_store_mutex);
+ _peaks.clear();
+
+ boost::mutex::scoped_lock clm(_current_mutex);
+ std::fill(_current_peaks.begin(), _current_peaks.end(), 0.0f);
+ _current_frames = 0;
+}
+
+
+std::vector<float>
+LevelCalculator::get(dcpomatic::DCPTime time)
+{
+ boost::mutex::scoped_lock slm(_store_mutex);
+
+ auto iter = _peaks.begin();
+ optional<dcpomatic::DCPTime> last_delta;
+ std::list<Measurement>::iterator last_iter;
+ while (iter != _peaks.end()) {
+ auto const delta = dcpomatic::DCPTime(time - iter->time).abs();
+ if (last_delta) {
+ if (delta > *last_delta) {
+ /* This is worse than the last - use the last one */
+ return last_iter->value;
+ } else {
+ /* This is better - keep looking */
+ _peaks.erase(last_iter);
+ }
+ }
+ last_delta = delta;
+ last_iter = iter;
+ ++iter;
+ }
+
+ if (iter == _peaks.end()) {
+ return {};
+ }
+
+ return iter->value;
+}
+
+
+void
+LevelCalculator::enable(bool e)
+{
+ _enabled = e;
+}
+
diff --git a/src/lib/level_calculator.h b/src/lib/level_calculator.h
new file mode 100644
index 000000000..9eeb5b9b8
--- /dev/null
+++ b/src/lib/level_calculator.h
@@ -0,0 +1,74 @@
+/*
+ Copyright (C) 2025 Carl Hetherington <cth@carlh.net>
+
+ This file is part of DCP-o-matic.
+
+ DCP-o-matic 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.
+
+ DCP-o-matic 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 DCP-o-matic. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+
+#ifndef DCPOMATIC_LEVEL_CALCULATOR_H
+#define DCPOMATIC_LEVEL_CALCULATOR_H
+
+
+#include "dcpomatic_time.h"
+#include <boost/thread.hpp>
+#include <memory>
+
+
+class AudioBuffers;
+
+
+class LevelCalculator
+{
+public:
+ LevelCalculator();
+
+ LevelCalculator(LevelCalculator const&) = delete;
+ LevelCalculator& operator=(LevelCalculator const&) = delete;
+
+ void put(std::shared_ptr<const AudioBuffers> audio, dcpomatic::DCPTime time, int frame_rate);
+ void clear();
+ std::vector<float> get(dcpomatic::DCPTime time);
+
+ void enable(bool e);
+
+private:
+ boost::mutex _current_mutex;
+ std::vector<float> _current_peaks;
+ int _current_frames = 0;
+
+ struct Measurement
+ {
+ Measurement(dcpomatic::DCPTime t, std::vector<float> v)
+ : time(t)
+ , value(std::move(v))
+ {
+
+ }
+
+ dcpomatic::DCPTime time;
+ std::vector<float> value;
+ };
+
+ mutable boost::mutex _store_mutex;
+ std::list<Measurement> _peaks;
+
+ boost::atomic<bool> _enabled;
+};
+
+
+#endif
+
diff --git a/src/lib/wscript b/src/lib/wscript
index dafd655fe..4b0002f04 100644
--- a/src/lib/wscript
+++ b/src/lib/wscript
@@ -156,6 +156,7 @@ sources = """
kdm_recipient.cc
kdm_with_metadata.cc
kdm_util.cc
+ level_calculator.cc
log.cc
log_entry.cc
make_dcp.cc
diff --git a/src/tools/dcpomatic_player.cc b/src/tools/dcpomatic_player.cc
index c5242c310..98fa6517a 100644
--- a/src/tools/dcpomatic_player.cc
+++ b/src/tools/dcpomatic_player.cc
@@ -133,6 +133,7 @@ enum {
ID_view_full_screen = DCPOMATIC_MAIN_MENU + 200,
ID_view_dual_screen,
ID_view_closed_captions,
+ ID_view_meters,
ID_view_eye,
ID_view_eye_left,
ID_view_eye_right,
@@ -241,6 +242,7 @@ public:
Bind (wxEVT_MENU, boost::bind (&DOMFrame::view_full_screen, this), ID_view_full_screen);
Bind (wxEVT_MENU, boost::bind (&DOMFrame::view_dual_screen, this), ID_view_dual_screen);
Bind (wxEVT_MENU, boost::bind (&DOMFrame::view_closed_captions, this), ID_view_closed_captions);
+ Bind (wxEVT_MENU, boost::bind (&DOMFrame::view_meters, this), ID_view_meters);
Bind (wxEVT_MENU, boost::bind (&DOMFrame::view_cpl, this, _1), ID_view_cpl, ID_view_cpl + MAX_CPLS);
Bind (wxEVT_MENU, boost::bind (&DOMFrame::view_eye_changed, this, _1), ID_view_eye_left);
Bind (wxEVT_MENU, boost::bind (&DOMFrame::view_eye_changed, this, _1), ID_view_eye_right);
@@ -644,6 +646,7 @@ private:
setup_menu ();
view->AppendSeparator();
view->Append(ID_view_closed_captions, _("Closed captions..."));
+ view->Append(ID_view_meters, _("Audio meters..."));
_view_eye_menu = new wxMenu;
_view_eye_left = _view_eye_menu->AppendRadioItem(ID_view_eye_left, _("Left"));
_view_eye_menu->AppendRadioItem(ID_view_eye_right, _("Right"));
@@ -989,6 +992,11 @@ private:
_viewer.show_closed_captions();
}
+ void view_meters ()
+ {
+ _viewer.show_meters();
+ }
+
void tools_verify ()
{
DCPOMATIC_ASSERT(!_film->content().empty());
diff --git a/src/wx/film_viewer.cc b/src/wx/film_viewer.cc
index b77ff987c..5e1caa1bf 100644
--- a/src/wx/film_viewer.cc
+++ b/src/wx/film_viewer.cc
@@ -28,6 +28,7 @@
#include "closed_captions_dialog.h"
#include "film_viewer.h"
#include "gl_video_view.h"
+#include "meters_dialog.h"
#include "nag_dialog.h"
#include "playhead_to_frame_dialog.h"
#include "playhead_to_timecode_dialog.h"
@@ -89,6 +90,7 @@ rtaudio_callback(void* out, void *, unsigned int frames, double, RtAudioStreamSt
FilmViewer::FilmViewer(wxWindow* p)
: _closed_captions_dialog(new ClosedCaptionsDialog(p, this))
+ , _meters_dialog(new MetersDialog(p))
{
#if wxCHECK_VERSION(3, 1, 0)
switch (Config::instance()->video_view_type()) {
@@ -96,11 +98,17 @@ FilmViewer::FilmViewer(wxWindow* p)
_video_view = std::make_shared<GLVideoView>(this, p);
break;
case Config::VIDEO_VIEW_SIMPLE:
- _video_view = std::make_shared<SimpleVideoView>(this, p);
+ {
+ auto simple = std::make_shared<SimpleVideoView>(this, p);
+ _meters_dialog->set_meters(simple->get_meters());
+ _video_view = simple;
+ }
break;
}
#else
- _video_view = std::make_shared<SimpleVideoView>(this, p);
+ auto simple = std::make_shared<SimpleVideoView>(this, p);
+ _meters_dialog->set_meters(simple->get_meters());
+ _video_view = simple;
#endif
_video_view->Sized.connect(boost::bind(&FilmViewer::video_view_sized, this));
@@ -808,6 +816,13 @@ FilmViewer::show_closed_captions()
void
+FilmViewer::show_meters()
+{
+ _meters_dialog->Show();
+}
+
+
+void
FilmViewer::seek_by(DCPTime by, bool accurate)
{
seek(_video_view->position() + by, accurate);
diff --git a/src/wx/film_viewer.h b/src/wx/film_viewer.h
index 2a6239d7d..31fdbe0c7 100644
--- a/src/wx/film_viewer.h
+++ b/src/wx/film_viewer.h
@@ -48,6 +48,7 @@ class FFmpegPlayer;
class Image;
class Player;
class PlayerVideo;
+class MetersDialog;
class RGBPlusAlphaImage;
class wxToggleButton;
@@ -71,6 +72,7 @@ public:
}
void show_closed_captions();
+ void show_meters();
void set_film(std::shared_ptr<Film>);
std::shared_ptr<Film> film() const {
@@ -212,6 +214,7 @@ private:
Optimisation _optimisation = Optimisation::NONE;
ClosedCaptionsDialog* _closed_captions_dialog = nullptr;
+ MetersDialog* _meters_dialog = nullptr;
bool _outline_content = false;
boost::optional<dcpomatic::Rect<double>> _outline_subtitles;
diff --git a/src/wx/meters_dialog.cc b/src/wx/meters_dialog.cc
new file mode 100644
index 000000000..e95fb65f2
--- /dev/null
+++ b/src/wx/meters_dialog.cc
@@ -0,0 +1,44 @@
+/*
+ Copyright (C) 2019-2021 Carl Hetherington <cth@carlh.net>
+
+ This file is part of DCP-o-matic.
+
+ DCP-o-matic 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.
+
+ DCP-o-matic 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 DCP-o-matic. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+
+#include "meters_dialog.h"
+#include <wx/wx.h>
+
+
+MetersDialog::MetersDialog(wxWindow* parent)
+ : wxDialog(parent, wxID_ANY, _("Meters"))
+{
+
+}
+
+void
+MetersDialog::set_meters(wxWindow* meters)
+{
+ meters->Reparent(this);
+
+ auto sizer = new wxBoxSizer(wxVERTICAL);
+ sizer->Add(meters, 1, wxEXPAND);
+ SetSizer(sizer);
+
+ SetSize({640, 480});
+ sizer->Layout();
+}
+
diff --git a/src/wx/meters_dialog.h b/src/wx/meters_dialog.h
new file mode 100644
index 000000000..84e2f0504
--- /dev/null
+++ b/src/wx/meters_dialog.h
@@ -0,0 +1,40 @@
+/*
+ Copyright (C) 2019-2021 Carl Hetherington <cth@carlh.net>
+
+ This file is part of DCP-o-matic.
+
+ DCP-o-matic 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.
+
+ DCP-o-matic 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 DCP-o-matic. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+
+#include "simple_meters.h"
+#include "lib/dcpomatic_time.h"
+#include <wx/wx.h>
+#include <memory>
+
+
+class Butler;
+class LevelCalculator;
+class wxWindow;
+
+
+class MetersDialog : public wxDialog
+{
+public:
+ MetersDialog(wxWindow* parent);
+
+ void set_meters(wxWindow* meters);
+};
+
diff --git a/src/wx/simple_meters.cc b/src/wx/simple_meters.cc
new file mode 100644
index 000000000..b719f93f9
--- /dev/null
+++ b/src/wx/simple_meters.cc
@@ -0,0 +1,103 @@
+/*
+ Copyright (C) 2025 Carl Hetherington <cth@carlh.net>
+
+ This file is part of DCP-o-matic.
+
+ DCP-o-matic 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.
+
+ DCP-o-matic 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 DCP-o-matic. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+
+#include "simple_meters.h"
+#include "wx_util.h"
+#include "lib/level_calculator.h"
+#include <dcp/types.h>
+#include <wx/wx.h>
+#include <algorithm>
+
+
+static auto constexpr min_db = -70.0f;
+
+
+using std::shared_ptr;
+#if BOOST_VERSION >= 106100
+using namespace boost::placeholders;
+#endif
+
+
+SimpleMeters::SimpleMeters(wxWindow* parent)
+ : _panel(new wxPanel(parent, wxID_ANY))
+{
+ _panel->Bind(wxEVT_PAINT, boost::bind(&SimpleMeters::paint, this));
+}
+
+
+wxWindow*
+SimpleMeters::get() const
+{
+ return _panel;
+}
+
+
+void
+SimpleMeters::paint()
+{
+ wxPaintDC dc(_panel);
+
+ dc.SetBackground(*wxBLACK_BRUSH);
+ dc.Clear();
+
+ if (_peaks.empty()) {
+ return;
+ }
+
+ auto const scale = 1 / dpi_scale_factor(_panel);
+ dc.SetLogicalScale(scale, scale);
+
+ auto const panel_size = dcp::Size(_panel->GetSize().GetWidth() / scale, _panel->GetSize().GetHeight() / scale);
+
+ auto const channel_width = panel_size.width / _peaks.size();
+
+ int x = 0;
+ dc.SetBrush(*wxGREEN_BRUSH);
+ for (auto peak: _peaks) {
+ auto const peak_db = std::max(min_db, 20 * log10(peak));
+ dc.DrawRectangle(x, panel_size.height, channel_width, (1 - (peak_db - min_db)) * panel_size.height / (-min_db));
+ x += channel_width;
+ }
+}
+
+
+bool
+SimpleMeters::update(shared_ptr<LevelCalculator> calculator, dcpomatic::DCPTime time)
+{
+ if (!_panel->GetParent()->IsShown()) {
+ return false;
+ }
+
+ _peaks = calculator->get(time);
+ _panel->Refresh();
+ _panel->Update();
+
+ return true;
+}
+
+
+void
+SimpleMeters::clear()
+{
+ _peaks.clear();
+ _panel->Refresh();
+ _panel->Update();
+}
diff --git a/src/wx/simple_meters.h b/src/wx/simple_meters.h
new file mode 100644
index 000000000..6b3843f3c
--- /dev/null
+++ b/src/wx/simple_meters.h
@@ -0,0 +1,63 @@
+/*
+ Copyright (C) 2025 Carl Hetherington <cth@carlh.net>
+
+ This file is part of DCP-o-matic.
+
+ DCP-o-matic 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.
+
+ DCP-o-matic 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 DCP-o-matic. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+
+#ifndef DCPOMATIC_SIMPLE_METERS_H
+#define DCPOMATIC_SIMPLE_METERS_H
+
+
+#include "lib/dcpomatic_time.h"
+#include <memory>
+#include <vector>
+
+
+class Butler;
+class LevelCalculator;
+class wxPanel;
+class wxShowEvent;
+class wxWindow;
+
+
+class SimpleMeters
+{
+public:
+ SimpleMeters(wxWindow* parent);
+
+ SimpleMeters(SimpleMeters const&) = delete;
+ SimpleMeters& operator=(SimpleMeters const&) = delete;
+
+ wxWindow* get() const;
+
+ bool update(std::shared_ptr<LevelCalculator> calculator, dcpomatic::DCPTime time);
+ void clear();
+
+private:
+ void paint();
+ void shown(wxShowEvent& ev);
+
+ wxPanel* _panel;
+ std::vector<float> _peaks;
+
+ std::weak_ptr<LevelCalculator> _level_calculator;
+};
+
+
+#endif
+
diff --git a/src/wx/simple_video_view.cc b/src/wx/simple_video_view.cc
index 665cee117..fe0ea42e0 100644
--- a/src/wx/simple_video_view.cc
+++ b/src/wx/simple_video_view.cc
@@ -26,6 +26,7 @@
#include "lib/butler.h"
#include "lib/dcpomatic_log.h"
#include "lib/image.h"
+#include "lib/level_calculator.h"
#include "lib/video_filter_graph.h"
#include "lib/video_filter_graph_set.h"
#include <dcp/util.h>
@@ -50,6 +51,7 @@ SimpleVideoView::SimpleVideoView (FilmViewer* viewer, wxWindow* parent)
: VideoView (viewer)
, _rec2020_filter("convert", "convert", "", "colorspace=all=bt709:iall=bt2020")
, _rec2020_filter_graph({ _rec2020_filter }, dcp::Fraction(24, 1))
+ , _meters(parent)
{
_panel = new wxPanel (parent);
@@ -265,4 +267,7 @@ SimpleVideoView::update ()
_inter_size = player_video().first->inter_size ();
refresh_panel ();
+
+ auto calculator = _viewer->butler()->level_calculator();
+ calculator->enable(_meters.update(calculator, _viewer->time()));
}
diff --git a/src/wx/simple_video_view.h b/src/wx/simple_video_view.h
index e19068979..2c6ce7965 100644
--- a/src/wx/simple_video_view.h
+++ b/src/wx/simple_video_view.h
@@ -19,6 +19,7 @@
*/
+#include "simple_meters.h"
#include "video_view.h"
#include "lib/filter.h"
#include "lib/position.h"
@@ -43,6 +44,10 @@ public:
return _panel;
}
+ wxWindow* get_meters() {
+ return _meters.get();
+ }
+
void update () override;
void start () override;
NextFrameResult display_next_frame (bool non_blocking) override;
@@ -60,4 +65,6 @@ private:
Filter _rec2020_filter;
VideoFilterGraphSet _rec2020_filter_graph;
+
+ SimpleMeters _meters;
};
diff --git a/src/wx/wscript b/src/wx/wscript
index 6bb10511b..9a9a79d9c 100644
--- a/src/wx/wscript
+++ b/src/wx/wscript
@@ -125,6 +125,7 @@ sources = """
markers_panel.cc
message_dialog.cc
metadata_dialog.cc
+ meters_dialog.cc
move_to_dialog.cc
nag_dialog.cc
name_format_editor.cc
@@ -160,6 +161,7 @@ sources = """
server_dialog.cc
servers_list_dialog.cc
short_kdm_output_panel.cc
+ simple_meters.cc
simple_video_view.cc
smpte_metadata_dialog.cc
sound_preferences_page.cc