diff options
| author | Carl Hetherington <cth@carlh.net> | 2012-07-25 00:28:22 +0100 |
|---|---|---|
| committer | Carl Hetherington <cth@carlh.net> | 2012-07-25 00:28:22 +0100 |
| commit | 8cb9f95ba7bc8a86236273535cd9000088a009ab (patch) | |
| tree | 03282542515812801788cbcdbccc1c6fcf52763a /src/wx | |
| parent | 80497156e0364175f9d5f8c7b14612b99dc6dc32 (diff) | |
Just move gtk -> wx.
Diffstat (limited to 'src/wx')
| -rw-r--r-- | src/wx/dvdomatic.cc | 76 | ||||
| -rw-r--r-- | src/wx/film_editor.cc | 584 | ||||
| -rw-r--r-- | src/wx/film_editor.h | 119 | ||||
| -rw-r--r-- | src/wx/film_viewer.cc | 231 | ||||
| -rw-r--r-- | src/wx/film_viewer.h | 63 | ||||
| -rw-r--r-- | src/wx/wscript | 32 |
6 files changed, 960 insertions, 145 deletions
diff --git a/src/wx/dvdomatic.cc b/src/wx/dvdomatic.cc deleted file mode 100644 index 3e1114f03..000000000 --- a/src/wx/dvdomatic.cc +++ /dev/null @@ -1,76 +0,0 @@ -#include <wx/wx.h> -#include "lib/util.h" -#include "lib/film.h" -#include "film_viewer.h" -#include "film_editor.h" - -enum { - ID_Quit = 1, -}; - -class Frame : public wxFrame -{ -public: - Frame (wxString const & title, wxPoint const & pos, wxSize const & size) - : wxFrame (NULL, -1, title, pos, size) - { - wxMenuBar* bar = new wxMenuBar; - - wxMenu *menu_file = new wxMenu; - menu_file->Append (ID_Quit, _("&Quit")); - - bar->Append (menu_file, _("&File")); - - SetMenuBar (bar); - - CreateStatusBar (); - SetStatusText (_("Welcome to DVD-o-matic!")); - } - - void OnQuit (wxCommandEvent& event) - { - Close (true); - } -}; - -class App : public wxApp -{ - bool OnInit () - { - if (!wxApp::OnInit ()) { - return false; - } - - wxInitAllImageHandlers (); - - dvdomatic_setup (); - - Film* film = new Film ("/home/carl/DCP/BitHarvest"); - - Frame* frame = new Frame (_("DVD-o-matic"), wxPoint (50, 50), wxSize(450, 350)); - frame->Show (true); - - frame->Connect ( - ID_Quit, wxEVT_COMMAND_MENU_SELECTED, - (wxObjectEventFunction) &Frame::OnQuit - ); - - FilmEditor* editor = new FilmEditor (film, frame); - editor->Show (true); - FilmViewer* viewer = new FilmViewer (film, frame); - viewer->load_thumbnail (22); - - wxBoxSizer* main_sizer = new wxBoxSizer (wxHORIZONTAL); - main_sizer->Add (editor, 0); - main_sizer->Add (viewer->get_widget (), 1, wxEXPAND); - frame->SetSizer (main_sizer); - -// frame->Add (viewer->get_widget ()); - - SetTopWindow (frame); - return true; - } -}; - -IMPLEMENT_APP (App) - diff --git a/src/wx/film_editor.cc b/src/wx/film_editor.cc index b99327879..d46244082 100644 --- a/src/wx/film_editor.cc +++ b/src/wx/film_editor.cc @@ -1,8 +1,584 @@ +/* + Copyright (C) 2012 Carl Hetherington <cth@carlh.net> + + 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., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +/** @file src/film_editor.cc + * @brief A GTK widget to edit a film's metadata, and perform various functions. + */ + +#include <iostream> +#include <gtkmm.h> +#include <boost/thread.hpp> +#include <boost/filesystem.hpp> +#include "lib/format.h" +#include "lib/film.h" +#include "lib/transcode_job.h" +#include "lib/exceptions.h" +#include "lib/ab_transcode_job.h" +#include "lib/thumbs_job.h" +#include "lib/job_manager.h" +#include "lib/filter.h" +#include "lib/screen.h" +#include "lib/config.h" +#include "filter_dialog.h" +#include "gtk_util.h" #include "film_editor.h" +#include "dcp_range_dialog.h" + +using namespace std; +using namespace boost; +using namespace Gtk; + +/** @param f Film to edit */ +FilmEditor::FilmEditor (Film* f) + : _film (f) + , _filters_button ("Edit...") + , _change_dcp_range_button ("Edit...") + , _dcp_ab ("A/B") +{ + _vbox.set_border_width (12); + _vbox.set_spacing (12); + + /* Set up our editing widgets */ + _left_crop.set_range (0, 1024); + _left_crop.set_increments (1, 16); + _top_crop.set_range (0, 1024); + _top_crop.set_increments (1, 16); + _right_crop.set_range (0, 1024); + _right_crop.set_increments (1, 16); + _bottom_crop.set_range (0, 1024); + _bottom_crop.set_increments (1, 16); + _filters.set_alignment (0, 0.5); + _audio_gain.set_range (-60, 60); + _audio_gain.set_increments (1, 3); + _audio_delay.set_range (-1000, 1000); + _audio_delay.set_increments (1, 20); + _still_duration.set_range (0, 60 * 60); + _still_duration.set_increments (1, 5); + _dcp_range.set_alignment (0, 0.5); + + vector<Format const *> fmt = Format::all (); + for (vector<Format const *>::iterator i = fmt.begin(); i != fmt.end(); ++i) { + _format.append_text ((*i)->name ()); + } + + _frames_per_second.set_increments (1, 5); + _frames_per_second.set_digits (2); + _frames_per_second.set_range (0, 60); + + vector<DCPContentType const *> const ct = DCPContentType::all (); + for (vector<DCPContentType const *>::const_iterator i = ct.begin(); i != ct.end(); ++i) { + _dcp_content_type.append_text ((*i)->pretty_name ()); + } + + vector<Scaler const *> const sc = Scaler::all (); + for (vector<Scaler const *>::const_iterator i = sc.begin(); i != sc.end(); ++i) { + _scaler.append_text ((*i)->name ()); + } + + _original_size.set_alignment (0, 0.5); + _length.set_alignment (0, 0.5); + _audio.set_alignment (0, 0.5); + + /* And set their values from the Film */ + set_film (f); + + /* Now connect to them, since initial values are safely set */ + _name.signal_changed().connect (sigc::mem_fun (*this, &FilmEditor::name_changed)); + _frames_per_second.signal_changed().connect (sigc::mem_fun (*this, &FilmEditor::frames_per_second_changed)); + _format.signal_changed().connect (sigc::mem_fun (*this, &FilmEditor::format_changed)); + _content.signal_file_set().connect (sigc::mem_fun (*this, &FilmEditor::content_changed)); + _left_crop.signal_value_changed().connect (sigc::mem_fun (*this, &FilmEditor::left_crop_changed)); + _right_crop.signal_value_changed().connect (sigc::mem_fun (*this, &FilmEditor::right_crop_changed)); + _top_crop.signal_value_changed().connect (sigc::mem_fun (*this, &FilmEditor::top_crop_changed)); + _bottom_crop.signal_value_changed().connect (sigc::mem_fun (*this, &FilmEditor::bottom_crop_changed)); + _filters_button.signal_clicked().connect (sigc::mem_fun (*this, &FilmEditor::edit_filters_clicked)); + _scaler.signal_changed().connect (sigc::mem_fun (*this, &FilmEditor::scaler_changed)); + _dcp_content_type.signal_changed().connect (sigc::mem_fun (*this, &FilmEditor::dcp_content_type_changed)); + _dcp_ab.signal_toggled().connect (sigc::mem_fun (*this, &FilmEditor::dcp_ab_toggled)); + _audio_gain.signal_value_changed().connect (sigc::mem_fun (*this, &FilmEditor::audio_gain_changed)); + _audio_delay.signal_value_changed().connect (sigc::mem_fun (*this, &FilmEditor::audio_delay_changed)); + _still_duration.signal_value_changed().connect (sigc::mem_fun (*this, &FilmEditor::still_duration_changed)); + _change_dcp_range_button.signal_clicked().connect (sigc::mem_fun (*this, &FilmEditor::change_dcp_range_clicked)); + + /* Set up the table */ + + Table* t = manage (new Table); + + t->set_row_spacings (4); + t->set_col_spacings (12); + + int n = 0; + t->attach (left_aligned_label ("Name"), 0, 1, n, n + 1); + t->attach (_name, 1, 2, n, n + 1); + ++n; + t->attach (left_aligned_label ("Content"), 0, 1, n, n + 1); + t->attach (_content, 1, 2, n, n + 1); + ++n; + t->attach (left_aligned_label ("Content Type"), 0, 1, n, n + 1); + t->attach (_dcp_content_type, 1, 2, n, n + 1); + ++n; + t->attach (video_widget (left_aligned_label ("Frames Per Second")), 0, 1, n, n + 1); + t->attach (video_widget (_frames_per_second), 1, 2, n, n + 1); + ++n; + t->attach (left_aligned_label ("Format"), 0, 1, n, n + 1); + t->attach (_format, 1, 2, n, n + 1); + ++n; + t->attach (left_aligned_label ("Crop"), 0, 1, n, n + 1); + HBox* c = manage (new HBox); + c->set_spacing (4); + c->pack_start (left_aligned_label ("L"), false, false); + c->pack_start (_left_crop, true, true); + c->pack_start (left_aligned_label ("R"), false, false); + c->pack_start (_right_crop, true, true); + c->pack_start (left_aligned_label ("T"), false, false); + c->pack_start (_top_crop, true, true); + c->pack_start (left_aligned_label ("B"), false, false); + c->pack_start (_bottom_crop, true, true); + t->attach (*c, 1, 2, n, n + 1); + ++n; + + int const special = n; + + /* VIDEO-only stuff */ + t->attach (video_widget (left_aligned_label ("Filters")), 0, 1, n, n + 1); + HBox* fb = manage (new HBox); + fb->set_spacing (4); + fb->pack_start (video_widget (_filters), true, true); + fb->pack_start (video_widget (_filters_button), false, false); + t->attach (*fb, 1, 2, n, n + 1); + ++n; + t->attach (video_widget (left_aligned_label ("Scaler")), 0, 1, n, n + 1); + t->attach (video_widget (_scaler), 1, 2, n, n + 1); + ++n; + t->attach (video_widget (left_aligned_label ("Audio Gain")), 0, 1, n, n + 1); + t->attach (video_widget (_audio_gain), 1, 2, n, n + 1); + t->attach (video_widget (left_aligned_label ("dB")), 2, 3, n, n + 1); + ++n; + t->attach (video_widget (left_aligned_label ("Audio Delay")), 0, 1, n, n + 1); + t->attach (video_widget (_audio_delay), 1, 2, n, n + 1); + t->attach (video_widget (left_aligned_label ("ms")), 2, 3, n, n + 1); + ++n; + t->attach (video_widget (left_aligned_label ("Original Size")), 0, 1, n, n + 1); + t->attach (video_widget (_original_size), 1, 2, n, n + 1); + ++n; + t->attach (video_widget (left_aligned_label ("Length")), 0, 1, n, n + 1); + t->attach (video_widget (_length), 1, 2, n, n + 1); + ++n; + t->attach (video_widget (left_aligned_label ("Audio")), 0, 1, n, n + 1); + t->attach (video_widget (_audio), 1, 2, n, n + 1); + ++n; + t->attach (video_widget (left_aligned_label ("Range")), 0, 1, n, n + 1); + Gtk::HBox* db = manage (new Gtk::HBox); + db->pack_start (_dcp_range, true, true); + video_widget (_dcp_range); + db->pack_start (_change_dcp_range_button, false, false); + video_widget (_change_dcp_range_button); + t->attach (*db, 1, 2, n, n + 1); + ++n; + t->attach (_dcp_ab, 0, 3, n, n + 1); + video_widget (_dcp_ab); + + /* STILL-only stuff */ + n = special; + t->attach (still_widget (left_aligned_label ("Duration")), 0, 1, n, n + 1); + t->attach (still_widget (_still_duration), 1, 2, n, n + 1); + t->attach (still_widget (left_aligned_label ("s")), 2, 3, n, n + 1); + ++n; + + t->show_all (); + _vbox.pack_start (*t, false, false); + + setup_visibility (); +} + +/** @return Our main widget, which contains everything else */ +Widget& +FilmEditor::widget () +{ + return _vbox; +} + +/** Called when the left crop widget has been changed */ +void +FilmEditor::left_crop_changed () +{ + if (_film) { + _film->set_left_crop (_left_crop.get_value ()); + } +} + +/** Called when the right crop widget has been changed */ +void +FilmEditor::right_crop_changed () +{ + if (_film) { + _film->set_right_crop (_right_crop.get_value ()); + } +} + +/** Called when the top crop widget has been changed */ +void +FilmEditor::top_crop_changed () +{ + if (_film) { + _film->set_top_crop (_top_crop.get_value ()); + } +} + +/** Called when the bottom crop value has been changed */ +void +FilmEditor::bottom_crop_changed () +{ + if (_film) { + _film->set_bottom_crop (_bottom_crop.get_value ()); + } +} + +/** Called when the content filename has been changed */ +void +FilmEditor::content_changed () +{ + if (!_film) { + return; + } + + try { + _film->set_content (_content.get_filename ()); + } catch (std::exception& e) { + _content.set_filename (_film->directory ()); + stringstream m; + m << "Could not set content: " << e.what() << "."; + Gtk::MessageDialog d (m.str(), false, MESSAGE_ERROR); + d.set_title ("DVD-o-matic"); + d.run (); + } +} + +/** Called when the DCP A/B switch has been toggled */ +void +FilmEditor::dcp_ab_toggled () +{ + if (_film) { + _film->set_dcp_ab (_dcp_ab.get_active ()); + } +} + +/** Called when the name widget has been changed */ +void +FilmEditor::name_changed () +{ + if (_film) { + _film->set_name (_name.get_text ()); + } +} + +/** Called when the metadata stored in the Film object has changed; + * so that we can update the GUI. + * @param p Property of the Film that has changed. + */ +void +FilmEditor::film_changed (Film::Property p) +{ + if (!_film) { + return; + } + + stringstream s; + + switch (p) { + case Film::CONTENT: + _content.set_filename (_film->content ()); + setup_visibility (); + break; + case Film::FORMAT: + _format.set_active (Format::as_index (_film->format ())); + break; + case Film::LEFT_CROP: + _left_crop.set_value (_film->left_crop ()); + break; + case Film::RIGHT_CROP: + _right_crop.set_value (_film->right_crop ()); + break; + case Film::TOP_CROP: + _top_crop.set_value (_film->top_crop ()); + break; + case Film::BOTTOM_CROP: + _bottom_crop.set_value (_film->bottom_crop ()); + break; + case Film::FILTERS: + { + pair<string, string> p = Filter::ffmpeg_strings (_film->filters ()); + _filters.set_text (p.first + " " + p.second); + break; + } + case Film::NAME: + _name.set_text (_film->name ()); + break; + case Film::FRAMES_PER_SECOND: + _frames_per_second.set_value (_film->frames_per_second ()); + break; + case Film::AUDIO_CHANNELS: + case Film::AUDIO_SAMPLE_RATE: + if (_film->audio_channels() == 0 && _film->audio_sample_rate() == 0) { + _audio.set_text (""); + } else { + s << _film->audio_channels () << " channels, " << _film->audio_sample_rate() << "Hz"; + _audio.set_text (s.str ()); + } + break; + case Film::SIZE: + if (_film->size().width == 0 && _film->size().height == 0) { + _original_size.set_text (""); + } else { + s << _film->size().width << " x " << _film->size().height; + _original_size.set_text (s.str ()); + } + break; + case Film::LENGTH: + if (_film->frames_per_second() > 0 && _film->length() > 0) { + s << _film->length() << " frames; " << seconds_to_hms (_film->length() / _film->frames_per_second()); + } else if (_film->length() > 0) { + s << _film->length() << " frames"; + } + _length.set_text (s.str ()); + break; + case Film::DCP_CONTENT_TYPE: + _dcp_content_type.set_active (DCPContentType::as_index (_film->dcp_content_type ())); + break; + case Film::THUMBS: + break; + case Film::DCP_FRAMES: + if (_film->dcp_frames() == 0) { + _dcp_range.set_text ("Whole film"); + } else { + stringstream s; + s << "First " << _film->dcp_frames() << " frames"; + _dcp_range.set_text (s.str ()); + } + break; + case Film::DCP_TRIM_ACTION: + break; + case Film::DCP_AB: + _dcp_ab.set_active (_film->dcp_ab ()); + break; + case Film::SCALER: + _scaler.set_active (Scaler::as_index (_film->scaler ())); + break; + case Film::AUDIO_GAIN: + _audio_gain.set_value (_film->audio_gain ()); + break; + case Film::AUDIO_DELAY: + _audio_delay.set_value (_film->audio_delay ()); + break; + case Film::STILL_DURATION: + _still_duration.set_value (_film->still_duration ()); + break; + } +} + +/** Called when the format widget has been changed */ +void +FilmEditor::format_changed () +{ + if (_film) { + int const n = _format.get_active_row_number (); + if (n >= 0) { + _film->set_format (Format::from_index (n)); + } + } +} + +/** Called when the DCP content type widget has been changed */ +void +FilmEditor::dcp_content_type_changed () +{ + if (_film) { + int const n = _dcp_content_type.get_active_row_number (); + if (n >= 0) { + _film->set_dcp_content_type (DCPContentType::from_index (n)); + } + } +} + +/** Sets the Film that we are editing */ +void +FilmEditor::set_film (Film* f) +{ + _film = f; + + set_things_sensitive (_film != 0); + + if (_film) { + _film->Changed.connect (sigc::mem_fun (*this, &FilmEditor::film_changed)); + } + + if (_film) { + FileChanged (_film->directory ()); + } else { + FileChanged (""); + } + + film_changed (Film::NAME); + film_changed (Film::CONTENT); + film_changed (Film::DCP_CONTENT_TYPE); + film_changed (Film::FORMAT); + film_changed (Film::LEFT_CROP); + film_changed (Film::RIGHT_CROP); + film_changed (Film::TOP_CROP); + film_changed (Film::BOTTOM_CROP); + film_changed (Film::FILTERS); + film_changed (Film::DCP_FRAMES); + film_changed (Film::DCP_TRIM_ACTION); + film_changed (Film::DCP_AB); + film_changed (Film::SIZE); + film_changed (Film::LENGTH); + film_changed (Film::FRAMES_PER_SECOND); + film_changed (Film::AUDIO_CHANNELS); + film_changed (Film::AUDIO_SAMPLE_RATE); + film_changed (Film::SCALER); + film_changed (Film::AUDIO_GAIN); + film_changed (Film::AUDIO_DELAY); + film_changed (Film::STILL_DURATION); +} + +/** Updates the sensitivity of lots of widgets to a given value. + * @param s true to make sensitive, false to make insensitive. + */ +void +FilmEditor::set_things_sensitive (bool s) +{ + _name.set_sensitive (s); + _frames_per_second.set_sensitive (s); + _format.set_sensitive (s); + _content.set_sensitive (s); + _left_crop.set_sensitive (s); + _right_crop.set_sensitive (s); + _top_crop.set_sensitive (s); + _bottom_crop.set_sensitive (s); + _filters_button.set_sensitive (s); + _scaler.set_sensitive (s); + _dcp_content_type.set_sensitive (s); + _dcp_range.set_sensitive (s); + _change_dcp_range_button.set_sensitive (s); + _dcp_ab.set_sensitive (s); + _audio_gain.set_sensitive (s); + _audio_delay.set_sensitive (s); + _still_duration.set_sensitive (s); +} + +/** Called when the `Edit filters' button has been clicked */ +void +FilmEditor::edit_filters_clicked () +{ + FilterDialog d (_film->filters ()); + d.ActiveChanged.connect (sigc::mem_fun (*_film, &Film::set_filters)); + d.run (); +} + +/** Called when the scaler widget has been changed */ +void +FilmEditor::scaler_changed () +{ + if (_film) { + int const n = _scaler.get_active_row_number (); + if (n >= 0) { + _film->set_scaler (Scaler::from_index (n)); + } + } +} + +/** Called when the frames per second widget has been changed */ +void +FilmEditor::frames_per_second_changed () +{ + if (_film) { + _film->set_frames_per_second (_frames_per_second.get_value ()); + } +} + +void +FilmEditor::audio_gain_changed () +{ + if (_film) { + _film->set_audio_gain (_audio_gain.get_value ()); + } +} + +void +FilmEditor::audio_delay_changed () +{ + if (_film) { + _film->set_audio_delay (_audio_delay.get_value ()); + } +} + +Widget& +FilmEditor::video_widget (Widget& w) +{ + _video_widgets.push_back (&w); + return w; +} + +Widget& +FilmEditor::still_widget (Widget& w) +{ + _still_widgets.push_back (&w); + return w; +} + +void +FilmEditor::setup_visibility () +{ + ContentType c = VIDEO; + + if (_film) { + c = _film->content_type (); + } + + for (list<Widget *>::iterator i = _video_widgets.begin(); i != _video_widgets.end(); ++i) { + (*i)->property_visible() = (c == VIDEO); + } + + for (list<Widget *>::iterator i = _still_widgets.begin(); i != _still_widgets.end(); ++i) { + (*i)->property_visible() = (c == STILL); + } +} + +void +FilmEditor::still_duration_changed () +{ + if (_film) { + _film->set_still_duration (_still_duration.get_value ()); + } +} + +void +FilmEditor::change_dcp_range_clicked () +{ + DCPRangeDialog d (_film); + d.Changed.connect (sigc::mem_fun (*this, &FilmEditor::dcp_range_changed)); + d.run (); +} -FilmEditor::FilmEditor (Film* f, wxFrame* p) - : wxPanel (p) - , _film (f) +void +FilmEditor::dcp_range_changed (int frames, TrimAction action) { - new wxButton (this, 0, wxT("FUCK")); + _film->set_dcp_frames (frames); + _film->set_dcp_trim_action (action); } diff --git a/src/wx/film_editor.h b/src/wx/film_editor.h index d1278b80e..9d15b436d 100644 --- a/src/wx/film_editor.h +++ b/src/wx/film_editor.h @@ -1,12 +1,125 @@ -#include <wx/wx.h> +/* + Copyright (C) 2012 Carl Hetherington <cth@carlh.net> + + 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., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +/** @file src/film_editor.h + * @brief A GTK widget to edit a film's metadata, and perform various functions. + */ + +#include <gtkmm.h> class Film; -class FilmEditor : public wxPanel +/** @class FilmEditor + * @brief A GTK widget to edit a film's metadata, and perform various functions. + */ +class FilmEditor { public: - FilmEditor (Film* f, wxFrame *); + FilmEditor (Film *); + + Gtk::Widget& widget (); + + void set_film (Film *); + void setup_visibility (); + + sigc::signal1<void, std::string> FileChanged; private: + /* Handle changes to the view */ + void name_changed (); + void left_crop_changed (); + void right_crop_changed (); + void top_crop_changed (); + void bottom_crop_changed (); + void content_changed (); + void frames_per_second_changed (); + void format_changed (); + void dcp_range_changed (int, TrimAction); + void dcp_content_type_changed (); + void dcp_ab_toggled (); + void scaler_changed (); + void audio_gain_changed (); + void audio_delay_changed (); + void still_duration_changed (); + + /* Handle changes to the model */ + void film_changed (Film::Property); + + /* Button clicks */ + void edit_filters_clicked (); + void change_dcp_range_clicked (); + + void set_things_sensitive (bool); + + Gtk::Widget & video_widget (Gtk::Widget &); + Gtk::Widget & still_widget (Gtk::Widget &); + + /** The film we are editing */ Film* _film; + /** The overall VBox containing our widget */ + Gtk::VBox _vbox; + /** The Film's name */ + Gtk::Entry _name; + /** The Film's frames per second */ + Gtk::SpinButton _frames_per_second; + /** The Film's format */ + Gtk::ComboBoxText _format; + /** The Film's content file */ + Gtk::FileChooserButton _content; + /** The Film's left crop */ + Gtk::SpinButton _left_crop; + /** The Film's right crop */ + Gtk::SpinButton _right_crop; + /** The Film's top crop */ + Gtk::SpinButton _top_crop; + /** The Film's bottom crop */ + Gtk::SpinButton _bottom_crop; + /** Currently-applied filters */ + Gtk::Label _filters; + /** Button to open the filters dialogue */ + Gtk::Button _filters_button; + /** The Film's scaler */ + Gtk::ComboBoxText _scaler; + /** The Film's audio gain */ + Gtk::SpinButton _audio_gain; + /** The Film's audio delay */ + Gtk::SpinButton _audio_delay; + /** The Film's DCP content type */ + Gtk::ComboBoxText _dcp_content_type; + /** The Film's original size */ + Gtk::Label _original_size; + /** The Film's length */ + Gtk::Label _length; + /** The Film's audio details */ + Gtk::Label _audio; + /** The Film's duration for still sources */ + Gtk::SpinButton _still_duration; + + /** Button to start making a DCP from existing J2K and WAV files */ + Gtk::Button _make_dcp_from_existing_button; + /** Display of the range of frames that will be used */ + Gtk::Label _dcp_range; + /** Button to change the range */ + Gtk::Button _change_dcp_range_button; + /** Selector to generate an A/B comparison DCP */ + Gtk::CheckButton _dcp_ab; + + std::list<Gtk::Widget*> _video_widgets; + std::list<Gtk::Widget*> _still_widgets; }; diff --git a/src/wx/film_viewer.cc b/src/wx/film_viewer.cc index c2481efb9..1d50c2f88 100644 --- a/src/wx/film_viewer.cc +++ b/src/wx/film_viewer.cc @@ -1,73 +1,218 @@ +/* + Copyright (C) 2012 Carl Hetherington <cth@carlh.net> + + 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., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +/** @file src/film_viewer.cc + * @brief A GTK widget to view `thumbnails' of a Film. + */ + #include <iostream> +#include <iomanip> #include "lib/film.h" +#include "lib/format.h" +#include "lib/util.h" +#include "lib/thumbs_job.h" +#include "lib/job_manager.h" +#include "lib/film_state.h" +#include "lib/options.h" #include "film_viewer.h" using namespace std; +using namespace boost; + +FilmViewer::FilmViewer (Film* f) + : _film (f) +{ + _scroller.add (_image); + + Gtk::HBox* controls = manage (new Gtk::HBox); + controls->set_spacing (6); + controls->pack_start (_position_slider); + + _vbox.pack_start (_scroller, true, true); + _vbox.pack_start (*controls, false, false); + _vbox.set_border_width (12); + + _position_slider.set_digits (0); + _position_slider.signal_format_value().connect (sigc::mem_fun (*this, &FilmViewer::format_position_slider_value)); + _position_slider.signal_value_changed().connect (sigc::mem_fun (*this, &FilmViewer::position_slider_changed)); + + _scroller.signal_size_allocate().connect (sigc::mem_fun (*this, &FilmViewer::scroller_size_allocate)); -class ThumbPanel : public wxPanel + set_film (_film); +} + +void +FilmViewer::load_thumbnail (int n) { -public: - ThumbPanel (wxFrame* parent) - : wxPanel (parent) - , _bitmap (0) - { + if (_film == 0 || _film->num_thumbs() <= n) { + return; } - void paint_event (wxPaintEvent& ev) - { - if (!_bitmap) { - return; - } + int const left = _film->left_crop (); + int const right = _film->right_crop (); + int const top = _film->top_crop (); + int const bottom = _film->bottom_crop (); + + _pixbuf = Gdk::Pixbuf::create_from_file (_film->thumb_file (n)); + + int const cw = _film->size().width - left - right; + int const ch = _film->size().height - top - bottom; + _cropped_pixbuf = Gdk::Pixbuf::create_subpixbuf (_pixbuf, left, top, cw, ch); + update_scaled_pixbuf (); + _image.set (_scaled_pixbuf); +} + +void +FilmViewer::reload_current_thumbnail () +{ + load_thumbnail (_position_slider.get_value ()); +} + +void +FilmViewer::position_slider_changed () +{ + reload_current_thumbnail (); +} + +string +FilmViewer::format_position_slider_value (double v) const +{ + stringstream s; - cout << "RENDER\n"; + if (_film && int (v) < _film->num_thumbs ()) { + int const f = _film->thumb_frame (int (v)); + s << f << " " << seconds_to_hms (f / _film->frames_per_second ()); + } else { + s << "-"; + } + + return s.str (); +} + +void +FilmViewer::film_changed (Film::Property p) +{ + if (p == Film::LEFT_CROP || p == Film::RIGHT_CROP || p == Film::TOP_CROP || p == Film::BOTTOM_CROP) { + reload_current_thumbnail (); + } else if (p == Film::THUMBS) { + if (_film && _film->num_thumbs() > 1) { + _position_slider.set_range (0, _film->num_thumbs () - 1); + } else { + _image.clear (); + _position_slider.set_range (0, 1); + } - wxPaintDC dc (this); - dc.DrawBitmap (*_bitmap, 0, 0, false); + _position_slider.set_value (0); + reload_current_thumbnail (); + } else if (p == Film::FORMAT) { + reload_current_thumbnail (); + } else if (p == Film::CONTENT) { + setup_visibility (); + _film->examine_content (); + update_thumbs (); } +} + +void +FilmViewer::set_film (Film* f) +{ + _film = f; - void set_bitmap (wxBitmap* bitmap) - { - _bitmap = bitmap; + if (!_film) { + _image.clear (); + return; } - DECLARE_EVENT_TABLE (); + _film->Changed.connect (sigc::mem_fun (*this, &FilmViewer::film_changed)); + + film_changed (Film::THUMBS); +} -private: - wxBitmap* _bitmap; -}; +pair<int, int> +FilmViewer::scaled_pixbuf_size () const +{ + if (_film == 0) { + return make_pair (0, 0); + } + + int const cw = _film->size().width - _film->left_crop() - _film->right_crop(); + int const ch = _film->size().height - _film->top_crop() - _film->bottom_crop(); -BEGIN_EVENT_TABLE (ThumbPanel, wxPanel) -EVT_PAINT (ThumbPanel::paint_event) -END_EVENT_TABLE () + float ratio = 1; + if (_film->format()) { + ratio = _film->format()->ratio_as_float() * ch / cw; + } -FilmViewer::FilmViewer (Film* f, wxFrame* p) - : _film (f) - , _image (0) - , _scaled_image (0) - , _bitmap (0) + Gtk::Allocation const a = _scroller.get_allocation (); + float const zoom = min (float (a.get_width()) / (cw * ratio), float (a.get_height()) / cw); + return make_pair (cw * zoom * ratio, ch * zoom); +} + +void +FilmViewer::update_scaled_pixbuf () { - _thumb_panel = new ThumbPanel (p); - _thumb_panel->Show (true); - int x, y; - _thumb_panel->GetSize (&x, &y); - cout << x << " " << y << "\n"; + pair<int, int> const s = scaled_pixbuf_size (); + + if (s.first > 0 && s.second > 0 && _cropped_pixbuf) { + _scaled_pixbuf = _cropped_pixbuf->scale_simple (s.first, s.second, Gdk::INTERP_HYPER); + _image.set (_scaled_pixbuf); + } } void -FilmViewer::load_thumbnail (int n) +FilmViewer::update_thumbs () { - if (_film == 0 && _film->num_thumbs() <= n) { + if (!_film) { return; } - _image = new wxImage (wxString (_film->thumb_file(n).c_str (), wxConvUTF8)); - _scaled_image = new wxImage (_image->Scale (512, 512)); - _bitmap = new wxBitmap (*_scaled_image); - _thumb_panel->set_bitmap (_bitmap); + _film->update_thumbs_pre_gui (); + + shared_ptr<const FilmState> s = _film->state_copy (); + shared_ptr<Options> o (new Options (s->dir ("thumbs"), ".tiff", "")); + o->out_size = _film->size (); + o->apply_crop = false; + o->decode_audio = false; + o->decode_video_frequency = 128; + + shared_ptr<Job> j (new ThumbsJob (s, o, _film->log ())); + j->Finished.connect (sigc::mem_fun (_film, &Film::update_thumbs_post_gui)); + JobManager::instance()->add (j); } -wxPanel * -FilmViewer::get_widget () +void +FilmViewer::scroller_size_allocate (Gtk::Allocation a) { - return _thumb_panel; + if (a.get_width() != _last_scroller_allocation.get_width() || a.get_height() != _last_scroller_allocation.get_height()) { + update_scaled_pixbuf (); + } + + _last_scroller_allocation = a; +} + +void +FilmViewer::setup_visibility () +{ + if (!_film) { + return; + } + + ContentType const c = _film->content_type (); + _position_slider.property_visible() = (c == VIDEO); } diff --git a/src/wx/film_viewer.h b/src/wx/film_viewer.h index b0a6aab04..ae0633cd2 100644 --- a/src/wx/film_viewer.h +++ b/src/wx/film_viewer.h @@ -1,21 +1,62 @@ -#include <wx/wx.h> +/* + Copyright (C) 2012 Carl Hetherington <cth@carlh.net> -class Film; -class ThumbPanel; + 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., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +/** @file src/film_viewer.h + * @brief A GTK widget to view `thumbnails' of a Film. + */ + +#include <gtkmm.h> +#include "lib/film.h" + +/** @class FilmViewer + * @brief A GTK widget to view `thumbnails' of a Film. + */ class FilmViewer { public: - FilmViewer (Film *, wxFrame *); + FilmViewer (Film *); - void load_thumbnail (int); - wxPanel* get_widget (); + Gtk::Widget& widget () { + return _vbox; + } + + void set_film (Film *); + void setup_visibility (); private: - Film* _film; + void position_slider_changed (); + void update_thumbs (); + std::string format_position_slider_value (double) const; + void load_thumbnail (int); + void film_changed (Film::Property); + void reload_current_thumbnail (); + void update_scaled_pixbuf (); + std::pair<int, int> scaled_pixbuf_size () const; + void scroller_size_allocate (Gtk::Allocation); - wxImage* _image; - wxImage* _scaled_image; - wxBitmap* _bitmap; - ThumbPanel* _thumb_panel; + Film* _film; + Gtk::VBox _vbox; + Gtk::ScrolledWindow _scroller; + Gtk::Image _image; + Glib::RefPtr<Gdk::Pixbuf> _pixbuf; + Glib::RefPtr<Gdk::Pixbuf> _cropped_pixbuf; + Glib::RefPtr<Gdk::Pixbuf> _scaled_pixbuf; + Gtk::HScale _position_slider; + Gtk::Allocation _last_scroller_allocation; }; diff --git a/src/wx/wscript b/src/wx/wscript index f8aa92896..8c809b675 100644 --- a/src/wx/wscript +++ b/src/wx/wscript @@ -1,16 +1,32 @@ def configure(conf): - conf.check_cfg(package = '', path = 'wx-config', args = '--cppflags --cxxflags --libs', uselib_store = 'WXWIDGETS', mandatory = True) + conf.check_cfg(package = 'glib-2.0', args = '--cflags --libs', uselib_store = 'GLIB', mandatory = True) + conf.check_cfg(package = 'gtkmm-2.4', args = '--cflags --libs', uselib_store = 'GTKMM', mandatory = True) + conf.check_cfg(package = 'cairomm-1.0', args = '--cflags --libs', uselib_store = 'CAIROMM', mandatory = True) def build(bld): - obj = bld(features = 'cxx cxxprogram') - obj.name = 'dvdomatic-wx' + obj = bld(features = 'cxx cxxshlib') + obj.name = 'libdvdomatic-gtk' obj.includes = [ '..' ] obj.export_includes = ['.'] - obj.uselib = 'WXWIDGETS' - obj.use = 'dvdomatic' + obj.uselib = 'GLIB GTKMM CAIROMM' + obj.use = 'libdvdomatic' obj.source = """ - dvdomatic.cc - film_viewer.cc + alignment.cc + config_dialog.cc + dcp_range_dialog.cc film_editor.cc + film_list.cc + film_viewer.cc + filter_dialog.cc + filter_view.cc + gpl.cc + job_manager_view.cc + gtk_util.cc + job_wrapper.cc + dvd_title_dialog.cc """ - obj.target = 'dvdomatic-wx' + + if not bld.env.DISABLE_PLAYER: + obj.source += " film_player.cc" + + obj.target = 'dvdomatic-gtk' |
