--- /dev/null
+/*
+ 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.
+
+*/
+
+#include <iostream>
+#include <gtkmm.h>
+#include <cairomm/cairomm.h>
+#include "alignment.h"
+
+using namespace std;
+
+class AlignmentWidget : public Gtk::DrawingArea
+{
+public:
+ void set_text_line (int n, string t)
+ {
+ if (int(_text.size()) < (n + 1)) {
+ _text.resize (n + 1);
+ }
+
+ _text[n] = t;
+ queue_draw ();
+ }
+
+private:
+ bool on_expose_event (GdkEventExpose* ev)
+ {
+ if (!get_window ()) {
+ return false;
+ }
+
+ Cairo::RefPtr<Cairo::Context> c = get_window()->create_cairo_context ();
+
+ Gtk::Allocation a = get_allocation ();
+ int const w = a.get_width ();
+ int const h = a.get_height ();
+
+ c->rectangle (0, 0, w, h);
+ c->set_source_rgb (0, 0, 0);
+ c->fill ();
+
+ c->set_source_rgb (1, 1, 1);
+ c->set_line_width (1);
+
+ int const arrow_size = h / 8;
+ int const head_size = h / 32;
+
+ /* arrow to left edge */
+ c->move_to (arrow_size, h / 2);
+ c->line_to (0, h / 2);
+ c->rel_line_to (head_size, head_size);
+ c->move_to (0, h / 2);
+ c->rel_line_to (head_size, -head_size);
+ c->stroke ();
+
+ /* arrow to right edge */
+ c->move_to (w - arrow_size, h / 2);
+ c->line_to (w, h / 2);
+ c->rel_line_to (-head_size, head_size);
+ c->move_to (w, h / 2);
+ c->rel_line_to (-head_size, -head_size);
+ c->stroke ();
+
+ /* arrow to top edge */
+ c->move_to (w / 2, arrow_size);
+ c->line_to (w / 2, 0);
+ c->rel_line_to (head_size, head_size);
+ c->move_to (w / 2, 0);
+ c->rel_line_to (-head_size, head_size);
+ c->stroke ();
+
+ /* arrow to bottom edge */
+ c->move_to (w / 2, h - h / 8);
+ c->line_to (w / 2, h);
+ c->rel_line_to (head_size, -head_size);
+ c->move_to (w / 2, h);
+ c->rel_line_to (-head_size, -head_size);
+ c->stroke ();
+
+ /* arrow to top-left corner */
+ c->move_to (arrow_size, arrow_size);
+ c->line_to (0, 0);
+ c->rel_line_to (head_size, 0);
+ c->move_to (0, 0);
+ c->rel_line_to (0, head_size);
+ c->stroke ();
+
+ /* arrow to top-right corner */
+ c->move_to (w - arrow_size, arrow_size);
+ c->line_to (w, 0);
+ c->rel_line_to (0, head_size);
+ c->move_to (w, 0);
+ c->rel_line_to (-head_size, 0);
+ c->stroke ();
+
+ /* arrow to bottom-left corner */
+ c->move_to (arrow_size, h - arrow_size);
+ c->line_to (0, h);
+ c->rel_line_to (head_size, 0);
+ c->move_to (0, h);
+ c->rel_line_to (0, -head_size);
+ c->stroke ();
+
+ /* arrow to bottom-right corner */
+ c->move_to (w - arrow_size, h - arrow_size);
+ c->line_to (w, h);
+ c->rel_line_to (-head_size, 0);
+ c->line_to (w, h);
+ c->rel_line_to (0, -head_size);
+ c->stroke ();
+
+ /* text */
+ int max_height = 0;
+ for (vector<string>::iterator i = _text.begin(); i != _text.end(); ++i) {
+ Cairo::TextExtents e;
+ c->get_text_extents (*i, e);
+ max_height = max (max_height, int (e.height));
+ }
+
+ int total_height = max_height * _text.size() * 2;
+
+ for (vector<string>::size_type i = 0; i < _text.size(); ++i) {
+ Cairo::TextExtents e;
+ c->get_text_extents (_text[i], e);
+ c->move_to ((w - e.width) / 2, ((h - total_height) / 2) + ((i * 2) + 1) * max_height);
+ c->text_path (_text[i]);
+ c->stroke ();
+ }
+
+ return true;
+ }
+
+ std::vector<std::string> _text;
+};
+
+Alignment::Alignment (Position p, Size s)
+{
+ _widget = Gtk::manage (new AlignmentWidget);
+ add (*_widget);
+ show_all ();
+
+ set_decorated (false);
+ set_resizable (false);
+ set_size_request (s.width, s.height);
+ move (p.x, p.y);
+}
+
+void
+Alignment::set_text_line (int n, string t)
+{
+ _widget->set_text_line (n, t);
+}
--- /dev/null
+/*
+ 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.
+
+*/
+
+#include <gtkmm.h>
+#include <string>
+#include "lib/util.h"
+
+class AlignmentWidget;
+
+class Alignment : public Gtk::Window
+{
+public:
+ Alignment (Position, Size);
+
+ void set_text_line (int, std::string);
+
+private:
+ AlignmentWidget* _widget;
+};
--- /dev/null
+/*
+ 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/config_dialog.cc
+ * @brief A dialogue to edit DVD-o-matic configuration.
+ */
+
+#include <iostream>
+#include <boost/lexical_cast.hpp>
+#include "lib/config.h"
+#include "lib/server.h"
+#include "lib/screen.h"
+#include "lib/format.h"
+#include "lib/scaler.h"
+#include "lib/filter.h"
+#include "config_dialog.h"
+#include "gtk_util.h"
+#include "filter_dialog.h"
+
+using namespace std;
+using namespace boost;
+
+ConfigDialog::ConfigDialog ()
+ : Gtk::Dialog ("DVD-o-matic Configuration")
+ , _reference_filters_button ("Edit...")
+ , _add_server ("Add Server")
+ , _remove_server ("Remove Server")
+ , _add_screen ("Add Screen")
+ , _remove_screen ("Remove Screen")
+{
+ Gtk::Table* t = manage (new Gtk::Table);
+ t->set_row_spacings (6);
+ t->set_col_spacings (6);
+ t->set_border_width (6);
+
+ Config* config = Config::instance ();
+
+ _tms_ip.set_text (config->tms_ip ());
+ _tms_ip.signal_changed().connect (sigc::mem_fun (*this, &ConfigDialog::tms_ip_changed));
+ _tms_path.set_text (config->tms_path ());
+ _tms_path.signal_changed().connect (sigc::mem_fun (*this, &ConfigDialog::tms_path_changed));
+ _tms_user.set_text (config->tms_user ());
+ _tms_user.signal_changed().connect (sigc::mem_fun (*this, &ConfigDialog::tms_user_changed));
+ _tms_password.set_text (config->tms_password ());
+ _tms_password.signal_changed().connect (sigc::mem_fun (*this, &ConfigDialog::tms_password_changed));
+
+ _num_local_encoding_threads.set_range (1, 128);
+ _num_local_encoding_threads.set_increments (1, 4);
+ _num_local_encoding_threads.set_value (config->num_local_encoding_threads ());
+ _num_local_encoding_threads.signal_changed().connect (sigc::mem_fun (*this, &ConfigDialog::num_local_encoding_threads_changed));
+
+ _colour_lut.append_text ("sRGB");
+ _colour_lut.append_text ("Rec 709");
+ _colour_lut.set_active (config->colour_lut_index ());
+ _colour_lut.signal_changed().connect (sigc::mem_fun (*this, &ConfigDialog::colour_lut_changed));
+
+ _j2k_bandwidth.set_range (50, 250);
+ _j2k_bandwidth.set_increments (10, 50);
+ _j2k_bandwidth.set_value (config->j2k_bandwidth() / 1e6);
+ _j2k_bandwidth.signal_changed().connect (sigc::mem_fun (*this, &ConfigDialog::j2k_bandwidth_changed));
+
+ vector<Scaler const *> const sc = Scaler::all ();
+ for (vector<Scaler const *>::const_iterator i = sc.begin(); i != sc.end(); ++i) {
+ _reference_scaler.append_text ((*i)->name ());
+ }
+ _reference_scaler.set_active (Scaler::as_index (config->reference_scaler ()));
+ _reference_scaler.signal_changed().connect (sigc::mem_fun (*this, &ConfigDialog::reference_scaler_changed));
+
+ _reference_filters.set_alignment (0, 0.5);
+ pair<string, string> p = Filter::ffmpeg_strings (config->reference_filters ());
+ _reference_filters.set_text (p.first + " " + p.second);
+ _reference_filters_button.signal_clicked().connect (sigc::mem_fun (*this, &ConfigDialog::edit_reference_filters_clicked));
+
+ _servers_store = Gtk::ListStore::create (_servers_columns);
+ vector<Server*> servers = config->servers ();
+ for (vector<Server*>::iterator i = servers.begin(); i != servers.end(); ++i) {
+ add_server_to_store (*i);
+ }
+
+ _servers_view.set_model (_servers_store);
+ _servers_view.append_column_editable ("Host Name", _servers_columns._host_name);
+ _servers_view.append_column_editable ("Threads", _servers_columns._threads);
+
+ _add_server.signal_clicked().connect (sigc::mem_fun (*this, &ConfigDialog::add_server_clicked));
+ _remove_server.signal_clicked().connect (sigc::mem_fun (*this, &ConfigDialog::remove_server_clicked));
+
+ _servers_view.get_selection()->signal_changed().connect (sigc::mem_fun (*this, &ConfigDialog::server_selection_changed));
+ server_selection_changed ();
+
+ _screens_store = Gtk::TreeStore::create (_screens_columns);
+ vector<shared_ptr<Screen> > screens = config->screens ();
+ for (vector<shared_ptr<Screen> >::iterator i = screens.begin(); i != screens.end(); ++i) {
+ add_screen_to_store (*i);
+ }
+
+ _screens_view.set_model (_screens_store);
+ _screens_view.append_column_editable ("Screen", _screens_columns._name);
+ _screens_view.append_column ("Format", _screens_columns._format_name);
+ _screens_view.append_column_editable ("x", _screens_columns._x);
+ _screens_view.append_column_editable ("y", _screens_columns._y);
+ _screens_view.append_column_editable ("Width", _screens_columns._width);
+ _screens_view.append_column_editable ("Height", _screens_columns._height);
+
+ _add_screen.signal_clicked().connect (sigc::mem_fun (*this, &ConfigDialog::add_screen_clicked));
+ _remove_screen.signal_clicked().connect (sigc::mem_fun (*this, &ConfigDialog::remove_screen_clicked));
+
+ _screens_view.get_selection()->signal_changed().connect (sigc::mem_fun (*this, &ConfigDialog::screen_selection_changed));
+ screen_selection_changed ();
+
+ int n = 0;
+ t->attach (left_aligned_label ("TMS IP address"), 0, 1, n, n + 1);
+ t->attach (_tms_ip, 1, 2, n, n + 1);
+ ++n;
+ t->attach (left_aligned_label ("TMS target path"), 0, 1, n, n + 1);
+ t->attach (_tms_path, 1, 2, n, n + 1);
+ ++n;
+ t->attach (left_aligned_label ("TMS user name"), 0, 1, n, n + 1);
+ t->attach (_tms_user, 1, 2, n, n + 1);
+ ++n;
+ t->attach (left_aligned_label ("TMS password"), 0, 1, n, n + 1);
+ t->attach (_tms_password, 1, 2, n, n + 1);
+ ++n;
+ t->attach (left_aligned_label ("Threads to use for encoding on this host"), 0, 1, n, n + 1);
+ t->attach (_num_local_encoding_threads, 1, 2, n, n + 1);
+ ++n;
+ t->attach (left_aligned_label ("Colour look-up table"), 0, 1, n, n + 1);
+ t->attach (_colour_lut, 1, 2, n, n + 1);
+ ++n;
+ t->attach (left_aligned_label ("JPEG2000 bandwidth"), 0, 1, n, n + 1);
+ t->attach (_j2k_bandwidth, 1, 2, n, n + 1);
+ t->attach (left_aligned_label ("MBps"), 2, 3, n, n + 1);
+ ++n;
+ t->attach (left_aligned_label ("Reference scaler for A/B"), 0, 1, n, n + 1);
+ t->attach (_reference_scaler, 1, 2, n, n + 1);
+ ++n;
+ t->attach (left_aligned_label ("Reference filters for A/B"), 0, 1, n, n + 1);
+ Gtk::HBox* fb = Gtk::manage (new Gtk::HBox);
+ fb->set_spacing (4);
+ fb->pack_start (_reference_filters, true, true);
+ fb->pack_start (_reference_filters_button, false, false);
+ t->attach (*fb, 1, 2, n, n + 1);
+ ++n;
+ t->attach (left_aligned_label ("Encoding Servers"), 0, 1, n, n + 1);
+ t->attach (_servers_view, 1, 2, n, n + 1);
+ Gtk::VBox* b = manage (new Gtk::VBox);
+ b->pack_start (_add_server, false, false);
+ b->pack_start (_remove_server, false, false);
+ t->attach (*b, 2, 3, n, n + 1);
+ ++n;
+ t->attach (left_aligned_label ("Screens"), 0, 1, n, n + 1);
+ t->attach (_screens_view, 1, 2, n, n + 1);
+ b = manage (new Gtk::VBox);
+ b->pack_start (_add_screen, false, false);
+ b->pack_start (_remove_screen, false, false);
+ t->attach (*b, 2, 3, n, n + 1);
+ ++n;
+
+ t->show_all ();
+ get_vbox()->pack_start (*t);
+
+ get_vbox()->set_border_width (24);
+
+ add_button ("Close", Gtk::RESPONSE_CLOSE);
+}
+
+void
+ConfigDialog::tms_ip_changed ()
+{
+ Config::instance()->set_tms_ip (_tms_ip.get_text ());
+}
+
+void
+ConfigDialog::tms_path_changed ()
+{
+ Config::instance()->set_tms_path (_tms_path.get_text ());
+}
+
+void
+ConfigDialog::tms_user_changed ()
+{
+ Config::instance()->set_tms_user (_tms_user.get_text ());
+}
+
+void
+ConfigDialog::tms_password_changed ()
+{
+ Config::instance()->set_tms_password (_tms_password.get_text ());
+}
+
+
+void
+ConfigDialog::num_local_encoding_threads_changed ()
+{
+ Config::instance()->set_num_local_encoding_threads (_num_local_encoding_threads.get_value ());
+}
+
+void
+ConfigDialog::colour_lut_changed ()
+{
+ Config::instance()->set_colour_lut_index (_colour_lut.get_active_row_number ());
+}
+
+void
+ConfigDialog::j2k_bandwidth_changed ()
+{
+ Config::instance()->set_j2k_bandwidth (_j2k_bandwidth.get_value() * 1e6);
+}
+
+void
+ConfigDialog::on_response (int r)
+{
+ vector<Server*> servers;
+
+ Gtk::TreeModel::Children c = _servers_store->children ();
+ for (Gtk::TreeModel::Children::iterator i = c.begin(); i != c.end(); ++i) {
+ Gtk::TreeModel::Row r = *i;
+ Server* s = new Server (r[_servers_columns._host_name], r[_servers_columns._threads]);
+ servers.push_back (s);
+ }
+
+ Config::instance()->set_servers (servers);
+
+ vector<shared_ptr<Screen> > screens;
+
+ c = _screens_store->children ();
+ for (Gtk::TreeModel::Children::iterator i = c.begin(); i != c.end(); ++i) {
+
+ Gtk::TreeModel::Row r = *i;
+ shared_ptr<Screen> s (new Screen (r[_screens_columns._name]));
+
+ Gtk::TreeModel::Children cc = r.children ();
+ for (Gtk::TreeModel::Children::iterator j = cc.begin(); j != cc.end(); ++j) {
+ Gtk::TreeModel::Row r = *j;
+ string const x_ = r[_screens_columns._x];
+ string const y_ = r[_screens_columns._y];
+ string const width_ = r[_screens_columns._width];
+ string const height_ = r[_screens_columns._height];
+ s->set_geometry (
+ Format::from_nickname (r[_screens_columns._format_nickname]),
+ Position (lexical_cast<int> (x_), lexical_cast<int> (y_)),
+ Size (lexical_cast<int> (width_), lexical_cast<int> (height_))
+ );
+ }
+
+ screens.push_back (s);
+ }
+
+ Config::instance()->set_screens (screens);
+
+ Gtk::Dialog::on_response (r);
+}
+
+void
+ConfigDialog::add_server_to_store (Server* s)
+{
+ Gtk::TreeModel::iterator i = _servers_store->append ();
+ Gtk::TreeModel::Row r = *i;
+ r[_servers_columns._host_name] = s->host_name ();
+ r[_servers_columns._threads] = s->threads ();
+}
+
+void
+ConfigDialog::add_server_clicked ()
+{
+ Server s ("localhost", 1);
+ add_server_to_store (&s);
+}
+
+void
+ConfigDialog::remove_server_clicked ()
+{
+ Gtk::TreeModel::iterator i = _servers_view.get_selection()->get_selected ();
+ if (i) {
+ _servers_store->erase (i);
+ }
+}
+
+void
+ConfigDialog::server_selection_changed ()
+{
+ Gtk::TreeModel::iterator i = _servers_view.get_selection()->get_selected ();
+ _remove_server.set_sensitive (i);
+}
+
+
+void
+ConfigDialog::add_screen_to_store (shared_ptr<Screen> s)
+{
+ Gtk::TreeModel::iterator i = _screens_store->append ();
+ Gtk::TreeModel::Row r = *i;
+ r[_screens_columns._name] = s->name ();
+
+ Screen::GeometryMap geoms = s->geometries ();
+ for (Screen::GeometryMap::const_iterator j = geoms.begin(); j != geoms.end(); ++j) {
+ i = _screens_store->append (r.children ());
+ Gtk::TreeModel::Row c = *i;
+ c[_screens_columns._format_name] = j->first->name ();
+ c[_screens_columns._format_nickname] = j->first->nickname ();
+ c[_screens_columns._x] = lexical_cast<string> (j->second.position.x);
+ c[_screens_columns._y] = lexical_cast<string> (j->second.position.y);
+ c[_screens_columns._width] = lexical_cast<string> (j->second.size.width);
+ c[_screens_columns._height] = lexical_cast<string> (j->second.size.height);
+ }
+}
+
+void
+ConfigDialog::add_screen_clicked ()
+{
+ shared_ptr<Screen> s (new Screen ("New Screen"));
+ add_screen_to_store (s);
+}
+
+void
+ConfigDialog::remove_screen_clicked ()
+{
+ Gtk::TreeModel::iterator i = _screens_view.get_selection()->get_selected ();
+ if (i) {
+ _screens_store->erase (i);
+ }
+}
+
+void
+ConfigDialog::screen_selection_changed ()
+{
+ Gtk::TreeModel::iterator i = _screens_view.get_selection()->get_selected ();
+ _remove_screen.set_sensitive (i);
+}
+
+
+void
+ConfigDialog::reference_scaler_changed ()
+{
+ int const n = _reference_scaler.get_active_row_number ();
+ if (n >= 0) {
+ Config::instance()->set_reference_scaler (Scaler::from_index (n));
+ }
+}
+
+void
+ConfigDialog::edit_reference_filters_clicked ()
+{
+ FilterDialog d (Config::instance()->reference_filters ());
+ d.ActiveChanged.connect (sigc::mem_fun (*this, &ConfigDialog::reference_filters_changed));
+ d.run ();
+}
+
+void
+ConfigDialog::reference_filters_changed (vector<Filter const *> f)
+{
+ Config::instance()->set_reference_filters (f);
+ pair<string, string> p = Filter::ffmpeg_strings (Config::instance()->reference_filters ());
+ _reference_filters.set_text (p.first + " " + p.second);
+}
--- /dev/null
+/*
+ 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/config_dialog.h
+ * @brief A dialogue to edit DVD-o-matic configuration.
+ */
+
+#include <gtkmm.h>
+
+class Screen;
+class Server;
+
+/** @class ConfigDialog
+ * @brief A dialogue to edit DVD-o-matic configuration.
+ */
+class ConfigDialog : public Gtk::Dialog
+{
+public:
+ ConfigDialog ();
+
+private:
+ void on_response (int);
+
+ void tms_ip_changed ();
+ void tms_path_changed ();
+ void tms_user_changed ();
+ void tms_password_changed ();
+ void num_local_encoding_threads_changed ();
+ void colour_lut_changed ();
+ void j2k_bandwidth_changed ();
+ void add_server_clicked ();
+ void remove_server_clicked ();
+ void server_selection_changed ();
+ void add_screen_clicked ();
+ void remove_screen_clicked ();
+ void screen_selection_changed ();
+ void reference_scaler_changed ();
+ void edit_reference_filters_clicked ();
+ void reference_filters_changed (std::vector<Filter const *>);
+
+ void add_screen_to_store (boost::shared_ptr<Screen>);
+ void add_server_to_store (Server *);
+
+ struct ServersModelColumns : public Gtk::TreeModelColumnRecord
+ {
+ ServersModelColumns () {
+ add (_host_name);
+ add (_threads);
+ }
+
+ Gtk::TreeModelColumn<std::string> _host_name;
+ Gtk::TreeModelColumn<int> _threads;
+ };
+
+ struct ScreensModelColumns : public Gtk::TreeModelColumnRecord
+ {
+ ScreensModelColumns () {
+ add (_name);
+ add (_format_name);
+ add (_format_nickname);
+ add (_x);
+ add (_y);
+ add (_width);
+ add (_height);
+ }
+
+ Gtk::TreeModelColumn<std::string> _name;
+ Gtk::TreeModelColumn<std::string> _format_name;
+ Gtk::TreeModelColumn<std::string> _format_nickname;
+ Gtk::TreeModelColumn<std::string> _x;
+ Gtk::TreeModelColumn<std::string> _y;
+ Gtk::TreeModelColumn<std::string> _width;
+ Gtk::TreeModelColumn<std::string> _height;
+ };
+
+ Gtk::Entry _tms_ip;
+ Gtk::Entry _tms_path;
+ Gtk::Entry _tms_user;
+ Gtk::Entry _tms_password;
+ Gtk::SpinButton _num_local_encoding_threads;
+ Gtk::ComboBoxText _colour_lut;
+ Gtk::SpinButton _j2k_bandwidth;
+ Gtk::ComboBoxText _reference_scaler;
+ Gtk::Label _reference_filters;
+ Gtk::Button _reference_filters_button;
+ ServersModelColumns _servers_columns;
+ Glib::RefPtr<Gtk::ListStore> _servers_store;
+ Gtk::TreeView _servers_view;
+ Gtk::Button _add_server;
+ Gtk::Button _remove_server;
+ ScreensModelColumns _screens_columns;
+ Glib::RefPtr<Gtk::TreeStore> _screens_store;
+ Gtk::TreeView _screens_view;
+ Gtk::Button _add_screen;
+ Gtk::Button _remove_screen;
+};
+
--- /dev/null
+/*
+ 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.
+
+*/
+
+#include "dcp_range_dialog.h"
+#include "lib/film.h"
+
+DCPRangeDialog::DCPRangeDialog (Film* f)
+ : _film (f)
+ , _whole ("Whole film")
+ , _first ("First")
+ , _cut ("Cut remainder")
+ , _black_out ("Black-out remainder")
+{
+ set_title ("DCP range");
+
+ Gtk::Table* table = Gtk::manage (new Gtk::Table ());
+ table->set_border_width (6);
+ table->set_row_spacings (6);
+ table->set_col_spacings (6);
+ table->attach (_whole, 0, 4, 0, 1);
+ table->attach (_first, 0, 1, 1, 2);
+ table->attach (_n_frames, 1, 2, 1, 2);
+ table->attach (*manage (new Gtk::Label ("frames")), 2, 3, 1, 2);
+ table->attach (_cut, 1, 2, 2, 3);
+ table->attach (_black_out, 1, 2, 3, 4);
+
+ Gtk::RadioButtonGroup g = _whole.get_group ();
+ _first.set_group (g);
+
+ g = _black_out.get_group ();
+ _cut.set_group (g);
+
+ _n_frames.set_range (1, INT_MAX - 1);
+ _n_frames.set_increments (24, 24 * 60);
+ if (_film->dcp_frames() > 0) {
+ _whole.set_active (false);
+ _first.set_active (true);
+ _n_frames.set_value (_film->dcp_frames ());
+ } else {
+ _whole.set_active (true);
+ _first.set_active (false);
+ _n_frames.set_value (24);
+ }
+
+ _black_out.set_active (_film->dcp_trim_action() == BLACK_OUT);
+ _cut.set_active (_film->dcp_trim_action() == CUT);
+
+ _whole.signal_toggled().connect (sigc::mem_fun (*this, &DCPRangeDialog::whole_toggled));
+ _cut.signal_toggled().connect (sigc::mem_fun (*this, &DCPRangeDialog::cut_toggled));
+ _n_frames.signal_value_changed().connect (sigc::mem_fun (*this, &DCPRangeDialog::n_frames_changed));
+
+ get_vbox()->pack_start (*table);
+
+ add_button ("Close", Gtk::RESPONSE_CLOSE);
+ show_all_children ();
+
+ set_sensitivity ();
+}
+
+void
+DCPRangeDialog::whole_toggled ()
+{
+ set_sensitivity ();
+ emit_changed ();
+}
+
+void
+DCPRangeDialog::set_sensitivity ()
+{
+ _n_frames.set_sensitive (_first.get_active ());
+ _black_out.set_sensitive (_first.get_active ());
+ _cut.set_sensitive (_first.get_active ());
+}
+
+void
+DCPRangeDialog::cut_toggled ()
+{
+ emit_changed ();
+}
+
+void
+DCPRangeDialog::n_frames_changed ()
+{
+ emit_changed ();
+}
+
+void
+DCPRangeDialog::emit_changed ()
+{
+ int frames = 0;
+ if (!_whole.get_active ()) {
+ frames = _n_frames.get_value_as_int ();
+ }
+
+ TrimAction action = CUT;
+ if (_black_out.get_active ()) {
+ action = BLACK_OUT;
+ }
+
+ Changed (frames, action);
+}
--- /dev/null
+/*
+ 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.
+
+*/
+
+#include <gtkmm.h>
+#include "lib/trim_action.h"
+
+class Film;
+
+class DCPRangeDialog : public Gtk::Dialog
+{
+public:
+ DCPRangeDialog (Film *);
+
+ sigc::signal2<void, int, TrimAction> Changed;
+
+private:
+ void whole_toggled ();
+ void cut_toggled ();
+ void n_frames_changed ();
+
+ void set_sensitivity ();
+ void emit_changed ();
+
+ Film* _film;
+ Gtk::RadioButton _whole;
+ Gtk::RadioButton _first;
+ Gtk::SpinButton _n_frames;
+ Gtk::RadioButton _cut;
+ Gtk::RadioButton _black_out;
+};
--- /dev/null
+/*
+ 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.
+
+*/
+
+#include <cassert>
+#include <iostream>
+#include "lib/exceptions.h"
+#include "dvd_title_dialog.h"
+#include "gtk_util.h"
+
+using namespace std;
+
+DVDTitleDialog::DVDTitleDialog ()
+{
+ string const dvd = find_dvd ();
+ if (dvd.empty ()) {
+ throw DVDError ("could not find DVD");
+ }
+
+ list<DVDTitle> t = dvd_titles (dvd);
+ if (t.empty ()) {
+ throw DVDError ("no titles found on DVD");
+ }
+
+ set_title ("Choose DVD title");
+ get_vbox()->set_border_width (6);
+ get_vbox()->set_spacing (3);
+
+ Gtk::RadioButtonGroup g;
+ for (list<DVDTitle>::const_iterator i = t.begin(); i != t.end(); ++i) {
+ Gtk::RadioButton* b = manage (new Gtk::RadioButton);
+ stringstream s;
+#if HAVE_G_FORMAT_SIZE
+ s << "Title " << i->number << ": " << g_format_size (i->size);
+#else
+ s << "Title " << i->number << ": " << g_format_size_for_display (i->size);
+#endif
+ b->set_label (s.str ());
+ if (i == t.begin ()) {
+ b->set_active ();
+ g = b->get_group ();
+ } else {
+ b->set_group (g);
+ }
+ get_vbox()->pack_start (*b);
+ _buttons[*i] = b;
+ }
+
+ add_button ("Cancel", Gtk::RESPONSE_CANCEL);
+ add_button ("Copy Title", Gtk::RESPONSE_OK);
+
+ show_all ();
+}
+
+DVDTitle
+DVDTitleDialog::selected ()
+{
+ std::map<DVDTitle, Gtk::RadioButton *>::const_iterator i = _buttons.begin ();
+ while (i != _buttons.end() && i->second->get_active() == false) {
+ ++i;
+ }
+
+ assert (i != _buttons.end ());
+ return i->first;
+}
--- /dev/null
+/*
+ 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.
+
+*/
+
+#include <gtkmm.h>
+#include "lib/dvd.h"
+
+class DVDTitleDialog : public Gtk::Dialog
+{
+public:
+ DVDTitleDialog ();
+
+ DVDTitle selected ();
+
+private:
+ std::map<DVDTitle, Gtk::RadioButton *> _buttons;
+};
--- /dev/null
+/*
+ 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.
+
+*/
+
+#include <boost/filesystem.hpp>
+#include "lib/film.h"
+#include "film_list.h"
+
+using namespace std;
+using namespace boost;
+
+FilmList::FilmList (string d)
+ : _directory (d)
+ , _list (1)
+{
+ for (filesystem::directory_iterator i = filesystem::directory_iterator (_directory); i != filesystem::directory_iterator(); ++i) {
+ if (is_directory (*i)) {
+ filesystem::path m = filesystem::path (*i) / filesystem::path ("metadata");
+ if (is_regular_file (m)) {
+ Film* f = new Film (i->path().string());
+ _films.push_back (f);
+ }
+ }
+ }
+
+ for (vector<Film const *>::iterator i = _films.begin(); i != _films.end(); ++i) {
+ _list.append_text ((*i)->name ());
+ }
+
+ _list.set_headers_visible (false);
+ _list.get_selection()->signal_changed().connect (sigc::mem_fun (*this, &FilmList::selection_changed));
+}
+
+Gtk::Widget&
+FilmList::widget ()
+{
+ return _list;
+}
+
+void
+FilmList::selection_changed ()
+{
+ Gtk::ListViewText::SelectionList s = _list.get_selected ();
+ if (s.empty ()) {
+ return;
+ }
+
+ assert (s[0] < int (_films.size ()));
+ SelectionChanged (_films[s[0]]);
+}
--- /dev/null
+/*
+ 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.
+
+*/
+
+#include <string>
+#include <vector>
+#include <gtkmm.h>
+
+class Film;
+
+class FilmList
+{
+public:
+ FilmList (std::string);
+
+ Gtk::Widget& widget ();
+
+ sigc::signal<void, Film const *> SelectionChanged;
+
+private:
+ void selection_changed ();
+
+ std::string _directory;
+ std::vector<Film const *> _films;
+ Gtk::ListViewText _list;
+};
--- /dev/null
+/*
+ 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.
+
+*/
+
+#include "lib/screen.h"
+#include "lib/config.h"
+#include "lib/player_manager.h"
+#include "lib/film.h"
+#include "film_player.h"
+#include "gtk_util.h"
+
+using namespace std;
+using namespace boost;
+
+FilmPlayer::FilmPlayer (Film const * f)
+ : _play ("Play")
+ , _pause ("Pause")
+ , _stop ("Stop")
+ , _ab ("A/B")
+ , _ignore_position_changed (false)
+{
+ set_film (f);
+
+ vector<shared_ptr<Screen> > const scr = Config::instance()->screens ();
+ for (vector<shared_ptr<Screen> >::const_iterator i = scr.begin(); i != scr.end(); ++i) {
+ _screen.append_text ((*i)->name ());
+ }
+
+ if (!scr.empty ()) {
+ _screen.set_active (0);
+ }
+
+ _status.set_use_markup (true);
+
+ _position.set_digits (0);
+
+ _main_vbox.set_spacing (12);
+
+ Gtk::HBox* l = manage (new Gtk::HBox);
+ l->pack_start (_play);
+ l->pack_start (_pause);
+ l->pack_start (_stop);
+
+ Gtk::VBox* r = manage (new Gtk::VBox);
+ r->pack_start (_screen, false, false);
+ r->pack_start (_ab, false, false);
+ r->pack_start (*manage (new Gtk::Label ("")), true, true);
+
+ Gtk::HBox* t = manage (new Gtk::HBox);
+ t->pack_start (*l, true, true);
+ t->pack_start (*r, false, false);
+
+ _main_vbox.pack_start (*t, true, true);
+ _main_vbox.pack_start (_position, false, false);
+ _main_vbox.pack_start (_status, false, false);
+
+ _play.signal_clicked().connect (sigc::mem_fun (*this, &FilmPlayer::play_clicked));
+ _pause.signal_clicked().connect (sigc::mem_fun (*this, &FilmPlayer::pause_clicked));
+ _stop.signal_clicked().connect (sigc::mem_fun (*this, &FilmPlayer::stop_clicked));
+ _position.signal_value_changed().connect (sigc::mem_fun (*this, &FilmPlayer::position_changed));
+ _position.signal_format_value().connect (sigc::mem_fun (*this, &FilmPlayer::format_position));
+
+ set_button_states ();
+ Glib::signal_timeout().connect (sigc::bind_return (sigc::mem_fun (*this, &FilmPlayer::update), true), 1000);
+
+ Config::instance()->Changed.connect (sigc::mem_fun (*this, &FilmPlayer::update_screens));
+}
+
+void
+FilmPlayer::set_film (Film const * f)
+{
+ _film = f;
+
+ if (_film && _film->length() != 0 && _film->frames_per_second() != 0) {
+ _position.set_range (0, _film->length() / _film->frames_per_second());
+ }
+
+ if (_film) {
+ _film->Changed.connect (sigc::mem_fun (*this, &FilmPlayer::film_changed));
+ }
+}
+
+Gtk::Widget &
+FilmPlayer::widget ()
+{
+ return _main_vbox;
+}
+
+void
+FilmPlayer::set_button_states ()
+{
+ if (_film == 0) {
+ _play.set_sensitive (false);
+ _pause.set_sensitive (false);
+ _stop.set_sensitive (false);
+ _screen.set_sensitive (false);
+ _position.set_sensitive (false);
+ _ab.set_sensitive (false);
+ return;
+ }
+
+ PlayerManager::State s = PlayerManager::instance()->state ();
+
+ switch (s) {
+ case PlayerManager::QUIESCENT:
+ _play.set_sensitive (true);
+ _pause.set_sensitive (false);
+ _stop.set_sensitive (false);
+ _screen.set_sensitive (true);
+ _position.set_sensitive (false);
+ _ab.set_sensitive (true);
+ break;
+ case PlayerManager::PLAYING:
+ _play.set_sensitive (false);
+ _pause.set_sensitive (true);
+ _stop.set_sensitive (true);
+ _screen.set_sensitive (false);
+ _position.set_sensitive (true);
+ _ab.set_sensitive (false);
+ break;
+ case PlayerManager::PAUSED:
+ _play.set_sensitive (true);
+ _pause.set_sensitive (false);
+ _stop.set_sensitive (true);
+ _screen.set_sensitive (false);
+ _position.set_sensitive (false);
+ _ab.set_sensitive (false);
+ break;
+ }
+}
+
+void
+FilmPlayer::play_clicked ()
+{
+ PlayerManager* p = PlayerManager::instance ();
+
+ switch (p->state ()) {
+ case PlayerManager::QUIESCENT:
+ _last_play_fs = _film->state_copy ();
+ if (_ab.get_active ()) {
+ shared_ptr<FilmState> fs_a = _film->state_copy ();
+ fs_a->filters.clear ();
+ /* This is somewhat arbitrary, but hey ho */
+ fs_a->scaler = Scaler::from_id ("bicubic");
+ p->setup (fs_a, _last_play_fs, screen ());
+ } else {
+ p->setup (_last_play_fs, screen ());
+ }
+ p->pause_or_unpause ();
+ break;
+ case PlayerManager::PLAYING:
+ break;
+ case PlayerManager::PAUSED:
+ p->pause_or_unpause ();
+ break;
+ }
+}
+
+void
+FilmPlayer::pause_clicked ()
+{
+ PlayerManager* p = PlayerManager::instance ();
+
+ switch (p->state ()) {
+ case PlayerManager::QUIESCENT:
+ break;
+ case PlayerManager::PLAYING:
+ p->pause_or_unpause ();
+ break;
+ case PlayerManager::PAUSED:
+ break;
+ }
+}
+
+void
+FilmPlayer::stop_clicked ()
+{
+ PlayerManager::instance()->stop ();
+}
+
+shared_ptr<Screen>
+FilmPlayer::screen () const
+{
+ vector<shared_ptr<Screen> > const s = Config::instance()->screens ();
+ if (s.empty ()) {
+ return shared_ptr<Screen> ();
+ }
+
+ int const r = _screen.get_active_row_number ();
+ if (r >= int (s.size ())) {
+ return s[0];
+ }
+
+ return s[r];
+}
+
+void
+FilmPlayer::update ()
+{
+ set_button_states ();
+ set_status ();
+}
+
+void
+FilmPlayer::set_status ()
+{
+ PlayerManager::State s = PlayerManager::instance()->state ();
+
+ stringstream m;
+ switch (s) {
+ case PlayerManager::QUIESCENT:
+ m << "Idle";
+ break;
+ case PlayerManager::PLAYING:
+ m << "<span foreground=\"red\" weight=\"bold\">PLAYING</span>";
+ break;
+ case PlayerManager::PAUSED:
+ m << "<b>Paused</b>";
+ break;
+ }
+
+ _ignore_position_changed = true;
+
+ if (s != PlayerManager::QUIESCENT) {
+ float const p = PlayerManager::instance()->position ();
+ if (_last_play_fs->frames_per_second != 0 && _last_play_fs->length != 0) {
+ m << " <i>(" << seconds_to_hms (_last_play_fs->length / _last_play_fs->frames_per_second - p) << " remaining)</i>";
+ }
+
+ _position.set_value (p);
+ } else {
+ _position.set_value (0);
+ }
+
+ _ignore_position_changed = false;
+
+ _status.set_markup (m.str ());
+}
+
+void
+FilmPlayer::position_changed ()
+{
+ if (_ignore_position_changed) {
+ return;
+ }
+
+ PlayerManager::instance()->set_position (_position.get_value ());
+}
+
+string
+FilmPlayer::format_position (double v)
+{
+ return seconds_to_hms (v);
+}
+
+void
+FilmPlayer::update_screens ()
+{
+ string const c = _screen.get_active_text ();
+
+ _screen.clear ();
+
+ vector<shared_ptr<Screen> > const scr = Config::instance()->screens ();
+ bool have_last_active_text = false;
+ for (vector<shared_ptr<Screen> >::const_iterator i = scr.begin(); i != scr.end(); ++i) {
+ _screen.append_text ((*i)->name ());
+ if ((*i)->name() == c) {
+ have_last_active_text = true;
+ }
+ }
+
+ if (have_last_active_text) {
+ _screen.set_active_text (c);
+ } else if (!scr.empty ()) {
+ _screen.set_active (0);
+ }
+}
+
+void
+FilmPlayer::film_changed (Film::Property p)
+{
+ if (p == Film::CONTENT) {
+ setup_visibility ();
+ }
+}
+
+void
+FilmPlayer::setup_visibility ()
+{
+ if (!_film) {
+ return;
+ }
+
+ widget().property_visible() = (_film->content_type() == VIDEO);
+}
--- /dev/null
+/*
+ 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.
+
+*/
+
+#include <gtkmm.h>
+#include "lib/film.h"
+
+class Film;
+class Screen;
+class FilmState;
+
+class FilmPlayer
+{
+public:
+ FilmPlayer (Film const * f = 0);
+
+ Gtk::Widget& widget ();
+
+ void set_film (Film const *);
+ void setup_visibility ();
+
+private:
+ void play_clicked ();
+ void pause_clicked ();
+ void stop_clicked ();
+ void position_changed ();
+ std::string format_position (double);
+ void film_changed (Film::Property);
+
+ void set_button_states ();
+ boost::shared_ptr<Screen> screen () const;
+ void set_status ();
+ void update ();
+ void update_screens ();
+
+ Film const * _film;
+ boost::shared_ptr<const FilmState> _last_play_fs;
+
+ Gtk::VBox _main_vbox;
+ Gtk::Button _play;
+ Gtk::Button _pause;
+ Gtk::Button _stop;
+ Gtk::Label _status;
+ Gtk::CheckButton _ab;
+ Gtk::ComboBoxText _screen;
+ Gtk::HScale _position;
+ bool _ignore_position_changed;
+};
--- /dev/null
+/*
+ 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/filter_dialog.cc
+ * @brief A dialog to select FFmpeg filters.
+ */
+
+#include "lib/film.h"
+#include "filter_dialog.h"
+
+using namespace std;
+
+FilterDialog::FilterDialog (vector<Filter const *> const & f)
+ : Gtk::Dialog ("Filters")
+ , _filters (f)
+{
+ get_vbox()->pack_start (_filters.widget ());
+
+ _filters.ActiveChanged.connect (sigc::mem_fun (*this, &FilterDialog::active_changed));
+
+ add_button ("Close", Gtk::RESPONSE_CLOSE);
+
+ show_all ();
+}
+
+
+void
+FilterDialog::active_changed ()
+{
+ ActiveChanged (_filters.active ());
+}
--- /dev/null
+/*
+ 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/filter_dialog.h
+ * @brief A dialog to select FFmpeg filters.
+ */
+
+#include <gtkmm.h>
+#include "filter_view.h"
+
+class Film;
+
+/** @class FilterDialog
+ * @brief A dialog to select FFmpeg filters.
+ */
+class FilterDialog : public Gtk::Dialog
+{
+public:
+ FilterDialog (std::vector<Filter const *> const &);
+
+ sigc::signal1<void, std::vector<Filter const *> > ActiveChanged;
+
+private:
+ void active_changed ();
+
+ FilterView _filters;
+};
--- /dev/null
+/*
+ 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/filter_view.cc
+ * @brief A widget to select FFmpeg filters.
+ */
+
+#include <iostream>
+#include "lib/filter.h"
+#include "filter_view.h"
+
+using namespace std;
+
+FilterView::FilterView (vector<Filter const *> const & active)
+{
+ _box.set_spacing (4);
+
+ vector<Filter const *> filters = Filter::all ();
+
+ for (vector<Filter const *>::iterator i = filters.begin(); i != filters.end(); ++i) {
+ Gtk::CheckButton* b = Gtk::manage (new Gtk::CheckButton ((*i)->name()));
+ bool const a = find (active.begin(), active.end(), *i) != active.end ();
+ b->set_active (a);
+ _filters[*i] = a;
+ b->signal_toggled().connect (sigc::bind (sigc::mem_fun (*this, &FilterView::filter_toggled), *i));
+ _box.pack_start (*b, false, false);
+ }
+
+ _box.show_all ();
+}
+
+Gtk::Widget &
+FilterView::widget ()
+{
+ return _box;
+}
+
+void
+FilterView::filter_toggled (Filter const * f)
+{
+ _filters[f] = !_filters[f];
+ ActiveChanged ();
+}
+
+vector<Filter const*>
+FilterView::active () const
+{
+ vector<Filter const *> active;
+ for (map<Filter const *, bool>::const_iterator i = _filters.begin(); i != _filters.end(); ++i) {
+ if (i->second) {
+ active.push_back (i->first);
+ }
+ }
+
+ return active;
+}
--- /dev/null
+/*
+ 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/filter_view.h
+ * @brief A widget to select FFmpeg filters.
+ */
+
+#include <gtkmm.h>
+#include <vector>
+
+class Filter;
+
+/** @class FilterView
+ * @brief A widget to select FFmpeg filters.
+ */
+class FilterView
+{
+public:
+ FilterView (std::vector<Filter const *> const &);
+
+ Gtk::Widget & widget ();
+ std::vector<Filter const *> active () const;
+
+ sigc::signal0<void> ActiveChanged;
+
+private:
+ void filter_toggled (Filter const *);
+
+ Gtk::VBox _box;
+ std::map<Filter const *, bool> _filters;
+};
--- /dev/null
+/*
+ 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/gpl.cc
+ * @brief The GPL.
+ */
+
+const char* gpl = "\n\
+DVD-o-matic comes with NO WARRANTY. It is free software, and you are \n\
+welcome to redistribute it under the terms of the GNU Public License,\n\
+shown below.\n \
+\n\
+ GNU GENERAL PUBLIC LICENSE\n\
+ Version 2, June 1991\n\
+\n\
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.\n\
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\n\
+ Everyone is permitted to copy and distribute verbatim copies\n\
+ of this license document, but changing it is not allowed.\n\
+\n\
+ Preamble\n\
+\n\
+ The licenses for most software are designed to take away your\n\
+freedom to share and change it. By contrast, the GNU General Public\n\
+License is intended to guarantee your freedom to share and change free\n\
+software--to make sure the software is free for all its users. This\n\
+General Public License applies to most of the Free Software\n\
+Foundation's software and to any other program whose authors commit to\n\
+using it. (Some other Free Software Foundation software is covered by\n\
+the GNU Library General Public License instead.) You can apply it to\n\
+your programs, too.\n\
+\n\
+ When we speak of free software, we are referring to freedom, not\n\
+price. Our General Public Licenses are designed to make sure that you\n\
+have the freedom to distribute copies of free software (and charge for\n\
+this service if you wish), that you receive source code or can get it\n\
+if you want it, that you can change the software or use pieces of it\n\
+in new free programs; and that you know you can do these things.\n\
+\n\
+ To protect your rights, we need to make restrictions that forbid\n\
+anyone to deny you these rights or to ask you to surrender the rights.\n\
+These restrictions translate to certain responsibilities for you if you\n\
+distribute copies of the software, or if you modify it.\n\
+\n\
+ For example, if you distribute copies of such a program, whether\n\
+gratis or for a fee, you must give the recipients all the rights that\n\
+you have. You must make sure that they, too, receive or can get the\n\
+source code. And you must show them these terms so they know their\n\
+rights.\n\
+\n\
+ We protect your rights with two steps: (1) copyright the software, and\n\
+(2) offer you this license which gives you legal permission to copy,\n\
+distribute and/or modify the software.\n\
+\n\
+ Also, for each author's protection and ours, we want to make certain\n\
+that everyone understands that there is no warranty for this free\n\
+software. If the software is modified by someone else and passed on, we\n\
+want its recipients to know that what they have is not the original, so\n\
+that any problems introduced by others will not reflect on the original\n\
+authors' reputations.\n\
+\n\
+ Finally, any free program is threatened constantly by software\n\
+patents. We wish to avoid the danger that redistributors of a free\n\
+program will individually obtain patent licenses, in effect making the\n\
+program proprietary. To prevent this, we have made it clear that any\n\
+patent must be licensed for everyone's free use or not licensed at all.\n\
+\n\
+ The precise terms and conditions for copying, distribution and\n\
+modification follow.\n\
+\n\
+ GNU GENERAL PUBLIC LICENSE\n\
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION\n\
+\n\
+ 0. This License applies to any program or other work which contains\n\
+a notice placed by the copyright holder saying it may be distributed\n\
+under the terms of this General Public License. The \"Program\", below,\n\
+refers to any such program or work, and a \"work based on the Program\"\n\
+means either the Program or any derivative work under copyright law:\n\
+that is to say, a work containing the Program or a portion of it,\n\
+either verbatim or with modifications and/or translated into another\n\
+language. (Hereinafter, translation is included without limitation in\n\
+the term \"modification\".) Each licensee is addressed as \"you\".\n\
+\n\
+Activities other than copying, distribution and modification are not\n\
+covered by this License; they are outside its scope. The act of\n\
+running the Program is not restricted, and the output from the Program\n\
+is covered only if its contents constitute a work based on the\n\
+Program (independent of having been made by running the Program).\n\
+Whether that is true depends on what the Program does.\n\
+\n\
+ 1. You may copy and distribute verbatim copies of the Program's\n\
+source code as you receive it, in any medium, provided that you\n\
+conspicuously and appropriately publish on each copy an appropriate\n\
+copyright notice and disclaimer of warranty; keep intact all the\n\
+notices that refer to this License and to the absence of any warranty;\n\
+and give any other recipients of the Program a copy of this License\n\
+along with the Program.\n\
+\n\
+You may charge a fee for the physical act of transferring a copy, and\n\
+you may at your option offer warranty protection in exchange for a fee.\n\
+\n\
+ 2. You may modify your copy or copies of the Program or any portion\n\
+of it, thus forming a work based on the Program, and copy and\n\
+distribute such modifications or work under the terms of Section 1\n\
+above, provided that you also meet all of these conditions:\n\
+\n\
+ a) You must cause the modified files to carry prominent notices\n\
+ stating that you changed the files and the date of any change.\n\
+\n\
+ b) You must cause any work that you distribute or publish, that in\n\
+ whole or in part contains or is derived from the Program or any\n\
+ part thereof, to be licensed as a whole at no charge to all third\n\
+ parties under the terms of this License.\n\
+\n\
+ c) If the modified program normally reads commands interactively\n\
+ when run, you must cause it, when started running for such\n\
+ interactive use in the most ordinary way, to print or display an\n\
+ announcement including an appropriate copyright notice and a\n\
+ notice that there is no warranty (or else, saying that you provide\n\
+ a warranty) and that users may redistribute the program under\n\
+ these conditions, and telling the user how to view a copy of this\n\
+ License. (Exception: if the Program itself is interactive but\n\
+ does not normally print such an announcement, your work based on\n\
+ the Program is not required to print an announcement.)\n\
+\n\
+These requirements apply to the modified work as a whole. If\n\
+identifiable sections of that work are not derived from the Program,\n\
+and can be reasonably considered independent and separate works in\n\
+themselves, then this License, and its terms, do not apply to those\n\
+sections when you distribute them as separate works. But when you\n\
+distribute the same sections as part of a whole which is a work based\n\
+on the Program, the distribution of the whole must be on the terms of\n\
+this License, whose permissions for other licensees extend to the\n\
+entire whole, and thus to each and every part regardless of who wrote it.\n\
+\n\
+Thus, it is not the intent of this section to claim rights or contest\n\
+your rights to work written entirely by you; rather, the intent is to\n\
+exercise the right to control the distribution of derivative or\n\
+collective works based on the Program.\n\
+\n\
+In addition, mere aggregation of another work not based on the Program\n\
+with the Program (or with a work based on the Program) on a volume of\n\
+a storage or distribution medium does not bring the other work under\n\
+the scope of this License.\n\
+\n\
+ 3. You may copy and distribute the Program (or a work based on it,\n\
+under Section 2) in object code or executable form under the terms of\n\
+Sections 1 and 2 above provided that you also do one of the following:\n\
+\n\
+ a) Accompany it with the complete corresponding machine-readable\n\
+ source code, which must be distributed under the terms of Sections\n\
+ 1 and 2 above on a medium customarily used for software interchange; or,\n\
+\n\
+ b) Accompany it with a written offer, valid for at least three\n\
+ years, to give any third party, for a charge no more than your\n\
+ cost of physically performing source distribution, a complete\n\
+ machine-readable copy of the corresponding source code, to be\n\
+ distributed under the terms of Sections 1 and 2 above on a medium\n\
+ customarily used for software interchange; or,\n\
+\n\
+ c) Accompany it with the information you received as to the offer\n\
+ to distribute corresponding source code. (This alternative is\n\
+ allowed only for noncommercial distribution and only if you\n\
+ received the program in object code or executable form with such\n\
+ an offer, in accord with Subsection b above.)\n\
+\n\
+The source code for a work means the preferred form of the work for\n\
+making modifications to it. For an executable work, complete source\n\
+code means all the source code for all modules it contains, plus any\n\
+associated interface definition files, plus the scripts used to\n\
+control compilation and installation of the executable. However, as a\n\
+special exception, the source code distributed need not include\n\
+anything that is normally distributed (in either source or binary\n\
+form) with the major components (compiler, kernel, and so on) of the\n\
+operating system on which the executable runs, unless that component\n\
+itself accompanies the executable.\n\
+\n\
+If distribution of executable or object code is made by offering\n\
+access to copy from a designated place, then offering equivalent\n\
+access to copy the source code from the same place counts as\n\
+distribution of the source code, even though third parties are not\n\
+compelled to copy the source along with the object code.\n\
+\f\n\
+ 4. You may not copy, modify, sublicense, or distribute the Program\n\
+except as expressly provided under this License. Any attempt\n\
+otherwise to copy, modify, sublicense or distribute the Program is\n\
+void, and will automatically terminate your rights under this License.\n\
+However, parties who have received copies, or rights, from you under\n\
+this License will not have their licenses terminated so long as such\n\
+parties remain in full compliance.\n\
+\n\
+ 5. You are not required to accept this License, since you have not\n\
+signed it. However, nothing else grants you permission to modify or\n\
+distribute the Program or its derivative works. These actions are\n\
+prohibited by law if you do not accept this License. Therefore, by\n\
+modifying or distributing the Program (or any work based on the\n\
+Program), you indicate your acceptance of this License to do so, and\n\
+all its terms and conditions for copying, distributing or modifying\n\
+the Program or works based on it.\n\
+\n\
+ 6. Each time you redistribute the Program (or any work based on the\n\
+Program), the recipient automatically receives a license from the\n\
+original licensor to copy, distribute or modify the Program subject to\n\
+these terms and conditions. You may not impose any further\n\
+restrictions on the recipients' exercise of the rights granted herein.\n\
+You are not responsible for enforcing compliance by third parties to\n\
+this License.\n\
+\n\
+ 7. If, as a consequence of a court judgment or allegation of patent\n\
+infringement or for any other reason (not limited to patent issues),\n\
+conditions are imposed on you (whether by court order, agreement or\n\
+otherwise) that contradict the conditions of this License, they do not\n\
+excuse you from the conditions of this License. If you cannot\n\
+distribute so as to satisfy simultaneously your obligations under this\n\
+License and any other pertinent obligations, then as a consequence you\n\
+may not distribute the Program at all. For example, if a patent\n\
+license would not permit royalty-free redistribution of the Program by\n\
+all those who receive copies directly or indirectly through you, then\n\
+the only way you could satisfy both it and this License would be to\n\
+refrain entirely from distribution of the Program.\n\
+\n\
+If any portion of this section is held invalid or unenforceable under\n\
+any particular circumstance, the balance of the section is intended to\n\
+apply and the section as a whole is intended to apply in other\n\
+circumstances.\n\
+\n\
+It is not the purpose of this section to induce you to infringe any\n\
+patents or other property right claims or to contest validity of any\n\
+such claims; this section has the sole purpose of protecting the\n\
+integrity of the free software distribution system, which is\n\
+implemented by public license practices. Many people have made\n\
+generous contributions to the wide range of software distributed\n\
+through that system in reliance on consistent application of that\n\
+system; it is up to the author/donor to decide if he or she is willing\n\
+to distribute software through any other system and a licensee cannot\n\
+impose that choice.\n\
+\n\
+This section is intended to make thoroughly clear what is believed to\n\
+be a consequence of the rest of this License.\n\
+\n\
+ 8. If the distribution and/or use of the Program is restricted in\n\
+certain countries either by patents or by copyrighted interfaces, the\n\
+original copyright holder who places the Program under this License\n\
+may add an explicit geographical distribution limitation excluding\n\
+those countries, so that distribution is permitted only in or among\n\
+countries not thus excluded. In such case, this License incorporates\n\
+the limitation as if written in the body of this License.\n\
+\n\
+ 9. The Free Software Foundation may publish revised and/or new versions\n\
+of the General Public License from time to time. Such new versions will\n\
+be similar in spirit to the present version, but may differ in detail to\n\
+address new problems or concerns.\n\
+\n\
+Each version is given a distinguishing version number. If the Program\n\
+specifies a version number of this License which applies to it and \"any\n\
+later version\", you have the option of following the terms and conditions\n\
+either of that version or of any later version published by the Free\n\
+Software Foundation. If the Program does not specify a version number of\n\
+this License, you may choose any version ever published by the Free Software\n\
+Foundation.\n\
+\n\
+ 10. If you wish to incorporate parts of the Program into other free\n\
+programs whose distribution conditions are different, write to the author\n\
+to ask for permission. For software which is copyrighted by the Free\n\
+Software Foundation, write to the Free Software Foundation; we sometimes\n\
+make exceptions for this. Our decision will be guided by the two goals\n\
+of preserving the free status of all derivatives of our free software and\n\
+of promoting the sharing and reuse of software generally.\n\
+\n\
+ NO WARRANTY\n\
+\n\
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY\n\
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN\n\
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES\n\
+PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED\n\
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\n\
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS\n\
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE\n\
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,\n\
+REPAIR OR CORRECTION.\n\
+\n\
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\n\
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR\n\
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,\n\
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING\n\
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED\n\
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY\n\
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER\n\
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE\n\
+POSSIBILITY OF SUCH DAMAGES.\n\
+\n\
+ END OF TERMS AND CONDITIONS\n\
+\n\
+ How to Apply These Terms to Your New Programs\n\
+\n\
+ If you develop a new program, and you want it to be of the greatest\n\
+possible use to the public, the best way to achieve this is to make it\n\
+free software which everyone can redistribute and change under these terms.\n\
+\n\
+ To do so, attach the following notices to the program. It is safest\n\
+to attach them to the start of each source file to most effectively\n\
+convey the exclusion of warranty; and each file should have at least\n\
+the \"copyright\" line and a pointer to where the full notice is found.\n\
+\n\
+ <one line to give the program's name and a brief idea of what it does.>\n\
+ Copyright (C) <year> <name of author>\n\
+\n\
+ This program is free software; you can redistribute it and/or modify\n\
+ it under the terms of the GNU General Public License as published by\n\
+ the Free Software Foundation; either version 2 of the License, or\n\
+ (at your option) any later version.\n\
+\n\
+ This program is distributed in the hope that it will be useful,\n\
+ but WITHOUT ANY WARRANTY; without even the implied warranty of\n\
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n\
+ GNU General Public License for more details.\n\
+\n\
+ You should have received a copy of the GNU General Public License\n\
+ along with this program; if not, write to the Free Software\n\
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\n\
+\n\
+\n\
+Also add information on how to contact you by electronic and paper mail.\n\
+\n\
+If the program is interactive, make it output a short notice like this\n\
+when it starts in an interactive mode:\n\
+\n\
+ Gnomovision version 69, Copyright (C) year name of author\n\
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.\n\
+ This is free software, and you are welcome to redistribute it\n\
+ under certain conditions; type `show c' for details.\n\
+\n\
+The hypothetical commands `show w' and `show c' should show the appropriate\n\
+parts of the General Public License. Of course, the commands you use may\n\
+be called something other than `show w' and `show c'; they could even be\n\
+mouse-clicks or menu items--whatever suits your program.\n\
+\n\
+You should also get your employer (if you work as a programmer) or your\n\
+school, if any, to sign a \"copyright disclaimer\" for the program, if\n\
+necessary. Here is a sample; alter the names:\n\
+\n\
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program\n\
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.\n\
+\n\
+ <signature of Ty Coon>, 1 April 1989\n\
+ Ty Coon, President of Vice\n\
+\n\
+This General Public License does not permit incorporating your program into\n\
+proprietary programs. If your program is a subroutine library, you may\n\
+consider it more useful to permit linking proprietary applications with the\n\
+library. If this is what you want to do, use the GNU Library General\n\
+Public License instead of this License.\n\
+";
+
--- /dev/null
+/*
+ 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/gpl.h
+ * @brief The GPL.
+ */
+
+extern const char * gpl;
--- /dev/null
+/*
+ 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/gtk/util.cc
+ * @brief Some utility functions.
+ */
+
+#include <gtkmm.h>
+
+using namespace std;
+
+/** @param t Label text.
+ * @return GTK label containing t, left-aligned (passed through Gtk::manage)
+ */
+Gtk::Label &
+left_aligned_label (string t)
+{
+ Gtk::Label* l = Gtk::manage (new Gtk::Label (t));
+ l->set_alignment (0, 0.5);
+ return *l;
+}
+
+void
+error_dialog (string m)
+{
+ Gtk::MessageDialog d (m, false, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true);
+ d.set_title ("DVD-o-matic");
+ d.run ();
+}
--- /dev/null
+/*
+ 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.
+
+*/
+
+#include <gtkmm.h>
+
+/** @file src/gtk/util.h
+ * @brief Some utility functions.
+ */
+
+extern void error_dialog (std::string);
+extern Gtk::Label & left_aligned_label (std::string);
--- /dev/null
+/*
+ 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/job_manager_view.cc
+ * @brief Class generating a GTK widget to show the progress of jobs.
+ */
+
+#include "lib/job_manager.h"
+#include "lib/job.h"
+#include "lib/util.h"
+#include "lib/exceptions.h"
+#include "job_manager_view.h"
+#include "gtk_util.h"
+
+using namespace std;
+using namespace boost;
+
+/** Must be called in the GUI thread */
+JobManagerView::JobManagerView ()
+{
+ _scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_ALWAYS);
+
+ _store = Gtk::TreeStore::create (_columns);
+ _view.set_model (_store);
+ _view.append_column ("Name", _columns.name);
+
+ Gtk::CellRendererProgress* r = Gtk::manage (new Gtk::CellRendererProgress ());
+ int const n = _view.append_column ("Progress", *r);
+ Gtk::TreeViewColumn* c = _view.get_column (n - 1);
+ c->add_attribute (r->property_value(), _columns.progress);
+ c->add_attribute (r->property_pulse(), _columns.progress_unknown);
+ c->add_attribute (r->property_text(), _columns.text);
+
+ _scroller.add (_view);
+ _scroller.set_size_request (-1, 150);
+
+ update ();
+}
+
+/** Update the view by examining the state of each jobs.
+ * Must be called in the GUI thread.
+ */
+void
+JobManagerView::update ()
+{
+ list<shared_ptr<Job> > jobs = JobManager::instance()->get ();
+
+ for (list<shared_ptr<Job> >::iterator i = jobs.begin(); i != jobs.end(); ++i) {
+ Gtk::ListStore::iterator j = _store->children().begin();
+ while (j != _store->children().end()) {
+ Gtk::TreeRow r = *j;
+ shared_ptr<Job> job = r[_columns.job];
+ if (job == *i) {
+ break;
+ }
+ ++j;
+ }
+
+ Gtk::TreeRow r;
+ if (j == _store->children().end ()) {
+ j = _store->append ();
+ r = *j;
+ r[_columns.name] = (*i)->name ();
+ r[_columns.job] = *i;
+ r[_columns.progress_unknown] = -1;
+ r[_columns.informed_of_finish] = false;
+ } else {
+ r = *j;
+ }
+
+ bool inform_of_finish = false;
+ string const st = (*i)->status ();
+
+ if (!(*i)->finished ()) {
+ float const p = (*i)->overall_progress ();
+ if (p >= 0) {
+ r[_columns.text] = st;
+ r[_columns.progress] = p * 100;
+ } else {
+ r[_columns.text] = "Running";
+ r[_columns.progress_unknown] = r[_columns.progress_unknown] + 1;
+ }
+ }
+
+ /* Hack to work around our lack of cross-thread
+ signalling; we tell the job to emit_finished()
+ from here (the GUI thread).
+ */
+
+ if ((*i)->finished_ok ()) {
+ bool i = r[_columns.informed_of_finish];
+ if (!i) {
+ r[_columns.progress_unknown] = -1;
+ r[_columns.progress] = 100;
+ r[_columns.text] = st;
+ inform_of_finish = true;
+ }
+ } else if ((*i)->finished_in_error ()) {
+ bool i = r[_columns.informed_of_finish];
+ if (!i) {
+ r[_columns.progress_unknown] = -1;
+ r[_columns.progress] = 100;
+ r[_columns.text] = st;
+ inform_of_finish = true;
+ }
+ }
+
+ if (inform_of_finish) {
+ try {
+ (*i)->emit_finished ();
+ } catch (OpenFileError& e) {
+ stringstream s;
+ s << "Error: " << e.what();
+ error_dialog (s.str ());
+ }
+ r[_columns.informed_of_finish] = true;
+ }
+ }
+}
--- /dev/null
+/*
+ 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/job_manager_view.h
+ * @brief Class generating a GTK widget to show the progress of jobs.
+ */
+
+#include <string>
+#include <boost/shared_ptr.hpp>
+#include <gtkmm.h>
+
+class Job;
+
+/** @class JobManagerView
+ * @brief Class generating a GTK widget to show the progress of jobs.
+ */
+class JobManagerView
+{
+public:
+ JobManagerView ();
+
+ /** @return Our main widget, which contains everything else */
+ Gtk::Widget& widget () {
+ return _scroller;
+ }
+
+ void update ();
+
+private:
+ /** Scroller for all our contents */
+ Gtk::ScrolledWindow _scroller;
+ /** View for the jobs */
+ Gtk::TreeView _view;
+ /** Store for the jobs */
+ Glib::RefPtr<Gtk::TreeStore> _store;
+
+ /** The TreeModelColumnRecord for the store */
+ class StoreColumns : public Gtk::TreeModelColumnRecord
+ {
+ public:
+ StoreColumns ()
+ {
+ add (name);
+ add (job);
+ add (progress);
+ add (progress_unknown);
+ add (text);
+ add (informed_of_finish);
+ }
+
+ /** Job name */
+ Gtk::TreeModelColumn<std::string> name;
+ /** Job */
+ Gtk::TreeModelColumn<boost::shared_ptr<Job> > job;
+ /** Progress */
+ Gtk::TreeModelColumn<float> progress;
+ /** An increasing integer number if the progress is unknown */
+ Gtk::TreeModelColumn<int> progress_unknown;
+ /** Text to write into the progress bar */
+ Gtk::TreeModelColumn<std::string> text;
+ /** true if the job has been informed of its finish */
+ Gtk::TreeModelColumn<bool> informed_of_finish;
+ };
+
+ /** The columns for the store */
+ StoreColumns _columns;
+};
--- /dev/null
+/*
+ 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.
+
+*/
+
+#include <sstream>
+#include "lib/film.h"
+#include "lib/exceptions.h"
+#include "job_wrapper.h"
+#include "gtk_util.h"
+
+using namespace std;
+
+void
+JobWrapper::make_dcp (Film* film, bool transcode)
+{
+ if (!film) {
+ return;
+ }
+
+ try {
+ film->make_dcp (transcode);
+ } catch (BadSettingError& e) {
+ stringstream s;
+ if (e.setting() == "dcp_long_name") {
+ s << "Could not make DCP: long name is invalid (" << e.what() << ")";
+ } else {
+ s << "Bad setting for " << e.setting() << "(" << e.what() << ")";
+ }
+ error_dialog (s.str ());
+ } catch (std::exception& e) {
+ stringstream s;
+ s << "Could not make DCP: " << e.what () << ".";
+ error_dialog (s.str ());
+ }
+}
--- /dev/null
+/*
+ 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.
+
+*/
+
+class Film;
+
+namespace JobWrapper
+{
+
+void make_dcp (Film *, bool);
+
+}