+2016-08-16 c.hetherington <cth@carlh.net>
+
+ * Simple information on mouse position in the video waveform (part of #932).
+
2016-08-15 Carl Hetherington <cth@carlh.net>
* Version 2.9.11 released.
_film = film;
_film_viewer->set_film (_film);
_film_editor->set_film (_film);
+ delete _video_waveform_dialog;
+ _video_waveform_dialog = 0;
set_menu_sensitivity ();
Config::instance()->add_to_history (_film->directory ());
}
void tools_video_waveform ()
{
if (!_video_waveform_dialog) {
- _video_waveform_dialog = new VideoWaveformDialog (this, _film_viewer);
+ _video_waveform_dialog = new VideoWaveformDialog (this, _film, _film_viewer);
}
_video_waveform_dialog->Show ();
using std::cout;
using boost::bind;
+using boost::weak_ptr;
-VideoWaveformDialog::VideoWaveformDialog (wxWindow* parent, FilmViewer* viewer)
+VideoWaveformDialog::VideoWaveformDialog (wxWindow* parent, weak_ptr<const Film> film, FilmViewer* viewer)
: wxDialog (
parent,
wxID_ANY,
overall_sizer->Add (controls, 0, wxALL | wxEXPAND, DCPOMATIC_SIZER_X_GAP);
- _plot = new VideoWaveformPlot (this, _viewer);
+ wxBoxSizer* position = new wxBoxSizer (wxHORIZONTAL);
+ add_label_to_sizer (position, this, _("Image X position"), true);
+ _x_position = new wxStaticText (this, wxID_ANY, "");
+ _x_position->SetMinSize (wxSize (64, -1));
+ position->Add (_x_position, 0, wxALL, DCPOMATIC_SIZER_X_GAP);
+ add_label_to_sizer (position, this, _("component value"), true);
+ _value = new wxStaticText (this, wxID_ANY, "");
+ _value->SetMinSize (wxSize (64, -1));
+ position->Add (_value, 0, wxALL, DCPOMATIC_SIZER_X_GAP);
+ overall_sizer->Add (position, 0, wxEXPAND | wxALL, DCPOMATIC_SIZER_Y_GAP);
+
+ _plot = new VideoWaveformPlot (this, film, _viewer);
overall_sizer->Add (_plot, 1, wxALL | wxEXPAND, 12);
#ifdef DCPOMATIC_LINUX
overall_sizer->SetSizeHints (this);
Bind (wxEVT_SHOW, bind (&VideoWaveformDialog::shown, this, _1));
- _component->Bind (wxEVT_COMMAND_CHOICE_SELECTED, bind (&VideoWaveformDialog::component_changed, this));
+ _component->Bind (wxEVT_COMMAND_CHOICE_SELECTED, bind (&VideoWaveformDialog::component_changed, this));
_contrast->Bind (wxEVT_SCROLL_THUMBTRACK, bind (&VideoWaveformDialog::contrast_changed, this));
+ _plot->MouseMoved.connect (bind (&VideoWaveformDialog::mouse_moved, this, _1, _2, _3, _4));
_component->SetSelection (0);
_contrast->SetValue (32);
{
_plot->set_contrast (_contrast->GetValue ());
}
+
+void
+VideoWaveformDialog::mouse_moved (int x1, int x2, int y1, int y2)
+{
+ if (x1 != x2) {
+ _x_position->SetLabel (wxString::Format ("%d-%d", x1, x2));
+ } else {
+ _x_position->SetLabel (wxString::Format ("%d", x1));
+ }
+
+ if (y1 != y2) {
+ _value->SetLabel (wxString::Format ("%d-%d", y1, y2));
+ } else {
+ _value->SetLabel (wxString::Format ("%d", y1));
+ }
+}
*/
#include <wx/wx.h>
+#include <boost/weak_ptr.hpp>
class VideoWaveformPlot;
class FilmViewer;
+class Film;
class VideoWaveformDialog : public wxDialog
{
public:
- VideoWaveformDialog (wxWindow* parent, FilmViewer* viewer);
+ VideoWaveformDialog (wxWindow* parent, boost::weak_ptr<const Film> film, FilmViewer* viewer);
private:
void shown (wxShowEvent &);
void component_changed ();
void contrast_changed ();
+ void mouse_moved (int x1, int x2, int y1, int y2);
FilmViewer* _viewer;
VideoWaveformPlot* _plot;
wxChoice* _component;
wxSlider* _contrast;
+ wxStaticText* _x_position;
+ wxStaticText* _value;
};
using std::cout;
using std::min;
+using std::max;
using std::string;
using boost::weak_ptr;
using boost::shared_ptr;
using dcp::locale_convert;
int const VideoWaveformPlot::_vertical_margin = 8;
+int const VideoWaveformPlot::_pixel_values = 4096;
int const VideoWaveformPlot::_x_axis_width = 52;
-VideoWaveformPlot::VideoWaveformPlot (wxWindow* parent, FilmViewer* viewer)
+VideoWaveformPlot::VideoWaveformPlot (wxWindow* parent, weak_ptr<const Film> film, FilmViewer* viewer)
: wxPanel (parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxFULL_REPAINT_ON_RESIZE)
+ , _film (film)
, _dirty (true)
, _enabled (false)
, _component (0)
Bind (wxEVT_PAINT, boost::bind (&VideoWaveformPlot::paint, this));
Bind (wxEVT_SIZE, boost::bind (&VideoWaveformPlot::sized, this, _1));
+ Bind (wxEVT_MOTION, boost::bind (&VideoWaveformPlot::mouse_moved, this, _1));
SetMinSize (wxSize (640, 512));
SetBackgroundColour (wxColour (0, 0, 0));
p.AddLineToPoint (_x_axis_width - 4, y);
gc->StrokePath (p);
int x = 4;
- int const n = i * 4096 / label_gaps;
+ int const n = i * _pixel_values / label_gaps;
if (n < 10) {
x += extra[0];
} else if (n < 100) {
int* ip = _image->data (_component) + x;
for (int y = 0; y < image_size.height; ++y) {
- strip[*ip * waveform_height / 4096]++;
+ strip[*ip * waveform_height / _pixel_values]++;
ip += image_size.width;
}
_dirty = true;
Refresh ();
}
+
+void
+VideoWaveformPlot::mouse_moved (wxMouseEvent& ev)
+{
+ if (!_image) {
+ return;
+ }
+
+ if (_dirty) {
+ create_waveform ();
+ _dirty = false;
+ }
+
+ shared_ptr<const Film> film = _film.lock ();
+ if (!film) {
+ return;
+ }
+
+ dcp::Size const full = film->frame_size ();
+
+ double const xs = static_cast<double> (full.width) / _waveform->size().width;
+ int const x1 = max (0, min (full.width - 1, int (floor (ev.GetPosition().x - _x_axis_width - 0.5) * xs)));
+ int const x2 = max (0, min (full.width - 1, int (floor (ev.GetPosition().x - _x_axis_width + 0.5) * xs)));
+
+ double const ys = static_cast<double> (_pixel_values) / _waveform->size().height;
+ int const fy = _waveform->size().height - (ev.GetPosition().y - _vertical_margin);
+ int const y1 = max (0, min (_pixel_values - 1, int (floor (fy - 0.5) * ys)));
+ int const y2 = max (0, min (_pixel_values - 1, int (floor (fy + 0.5) * ys)));
+
+ MouseMoved (x1, x2, y1, y2);
+}
class PlayerVideo;
class Image;
+class Film;
class FilmViewer;
class VideoWaveformPlot : public wxPanel
{
public:
- VideoWaveformPlot (wxWindow* parent, FilmViewer* viewer);
+ VideoWaveformPlot (wxWindow* parent, boost::weak_ptr<const Film> film, FilmViewer* viewer);
void set_enabled (bool e);
void set_component (int c);
void set_contrast (int b);
+ /** Emitted when the mouse is moved over the waveform. The parameters
+ are:
+ - (int, int): image x range
+ - (int, int): component value range
+ */
+ boost::signals2::signal<void (int, int, int, int)> MouseMoved;
+
private:
void paint ();
void sized (wxSizeEvent &);
void create_waveform ();
void set_image (boost::weak_ptr<PlayerVideo>);
+ void mouse_moved (wxMouseEvent &);
+ boost::weak_ptr<const Film> _film;
boost::shared_ptr<dcp::OpenJPEGImage> _image;
boost::shared_ptr<const Image> _waveform;
bool _dirty;
int _contrast;
static int const _vertical_margin;
+ static int const _pixel_values;
static int const _x_axis_width;
boost::signals2::connection _viewer_connection;