summaryrefslogtreecommitdiff
path: root/gtk2_ardour
diff options
context:
space:
mode:
authorPaul Davis <paul@linuxaudiosystems.com>2008-09-17 12:56:00 +0000
committerPaul Davis <paul@linuxaudiosystems.com>2008-09-17 12:56:00 +0000
commitb5a57cc78c92b1d887b7e8de040d8663a9ba187e (patch)
tree7facf0cfbdab8ab95dcce93034e5e59750583057 /gtk2_ardour
parent8876b57b0fda1000c63f8e1f7bb8f6d5ce53c480 (diff)
new files from sakari, missed last time
git-svn-id: svn://localhost/ardour2/branches/3.0@3738 d708f5d6-7413-0410-9779-e7cbd77b26cf
Diffstat (limited to 'gtk2_ardour')
-rw-r--r--gtk2_ardour/export_channel_selector.cc427
-rw-r--r--gtk2_ardour/export_channel_selector.h181
-rw-r--r--gtk2_ardour/export_filename_selector.cc303
-rw-r--r--gtk2_ardour/export_filename_selector.h120
-rw-r--r--gtk2_ardour/export_format_dialog.cc953
-rw-r--r--gtk2_ardour/export_format_dialog.h308
-rw-r--r--gtk2_ardour/export_format_selector.cc169
-rw-r--r--gtk2_ardour/export_format_selector.h91
-rw-r--r--gtk2_ardour/export_main_dialog.cc640
-rw-r--r--gtk2_ardour/export_main_dialog.h234
-rw-r--r--gtk2_ardour/export_multiplicator.cc330
-rw-r--r--gtk2_ardour/export_multiplicator.h121
-rw-r--r--gtk2_ardour/export_timespan_selector.cc394
-rw-r--r--gtk2_ardour/export_timespan_selector.h132
-rw-r--r--gtk2_ardour/session_metadata_dialog.cc738
-rw-r--r--gtk2_ardour/session_metadata_dialog.h276
-rw-r--r--gtk2_ardour/time_axis_view.cc11
17 files changed, 5425 insertions, 3 deletions
diff --git a/gtk2_ardour/export_channel_selector.cc b/gtk2_ardour/export_channel_selector.cc
new file mode 100644
index 0000000000..41ecec9094
--- /dev/null
+++ b/gtk2_ardour/export_channel_selector.cc
@@ -0,0 +1,427 @@
+/*
+ Copyright (C) 2008 Paul Davis
+ Author: Sakari Bergen
+
+ 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 "export_channel_selector.h"
+
+#include <algorithm>
+
+#include <pbd/convert.h>
+
+#include <ardour/audioengine.h>
+#include <ardour/export_channel_configuration.h>
+#include <ardour/export_handler.h>
+#include <ardour/io.h>
+#include <ardour/route.h>
+#include <ardour/audio_port.h>
+#include <ardour/session.h>
+
+#include <sstream>
+
+#include "i18n.h"
+
+using namespace ARDOUR;
+using namespace PBD;
+
+ExportChannelSelector::ExportChannelSelector () :
+ channels_label (_("Channels:"), Gtk::ALIGN_LEFT),
+ split_checkbox (_("Split to mono files")),
+ max_channels (20),
+ channel_view (max_channels)
+{
+
+ channels_hbox.pack_start (channels_label, false, false, 0);
+ channels_hbox.pack_end (channels_spinbutton, false, false, 0);
+
+ channels_vbox.pack_start (channels_hbox, false, false, 0);
+ channels_vbox.pack_start (split_checkbox, false, false, 6);
+
+ channel_alignment.add (channel_scroller);
+ channel_alignment.set_padding (0, 0, 12, 0);
+ channel_scroller.add (channel_view);
+ channel_scroller.set_size_request (-1, 130);
+ channel_scroller.set_policy (Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
+
+ pack_start (channels_vbox, false, false, 0);
+ pack_start (channel_alignment, true, true, 0);
+
+ /* Channels spinbutton */
+
+ channels_spinbutton.set_digits (0);
+ channels_spinbutton.set_increments (1, 2);
+ channels_spinbutton.set_range (1, max_channels);
+ channels_spinbutton.set_value (2);
+
+ channels_spinbutton.signal_value_changed().connect (sigc::mem_fun (*this, &ExportChannelSelector::update_channel_count));
+
+ /* Other signals */
+
+ split_checkbox.signal_toggled().connect (sigc::mem_fun (*this, &ExportChannelSelector::update_split_state));
+ channel_view.CriticalSelectionChanged.connect (CriticalSelectionChanged.make_slot());
+
+ /* Finalize */
+
+ show_all_children ();
+
+}
+
+ExportChannelSelector::~ExportChannelSelector ()
+{
+// if (session) {
+// session->add_instant_xml (get_state(), false);
+// }
+}
+
+void
+ExportChannelSelector::set_state (ARDOUR::ExportProfileManager::ChannelConfigStatePtr const state_, ARDOUR::Session * session_)
+{
+ state = state_;
+ session = session_;
+
+ split_checkbox.set_active (state->config->get_split());
+ channels_spinbutton.set_value (state->config->get_n_chans());
+
+ fill_route_list ();
+ channel_view.set_config (state->config);
+}
+
+void
+ExportChannelSelector::fill_route_list ()
+{
+ channel_view.clear_routes ();
+ Session::RouteList routes = *session->get_routes();
+
+ /* Add master bus and then everything else */
+
+ ARDOUR::IO * master = session->master_out().get();
+ channel_view.add_route (master);
+
+ for (Session::RouteList::iterator it = routes.begin(); it != routes.end(); ++it) {
+ if (it->get() == master) {
+ continue;
+ }
+ channel_view.add_route (it->get());
+ }
+
+ update_channel_count ();
+}
+
+void
+ExportChannelSelector::update_channel_count ()
+{
+ uint32_t chans = static_cast<uint32_t> (channels_spinbutton.get_value());
+ channel_view.set_channel_count (chans);
+ CriticalSelectionChanged();
+}
+
+void
+ExportChannelSelector::update_split_state ()
+{
+ state->config->set_split (split_checkbox.get_active());
+ CriticalSelectionChanged();
+}
+
+void
+ExportChannelSelector::RouteCols::add_channels (uint32_t chans)
+{
+ while (chans > 0) {
+ channels.push_back (Channel (*this));
+ ++n_channels;
+ --chans;
+ }
+}
+
+ExportChannelSelector::RouteCols::Channel &
+ExportChannelSelector::RouteCols::get_channel (uint32_t channel)
+{
+ if (channel > n_channels) {
+ std::cout << "Invalid channel cout for get_channel!" << std::endl;
+ }
+
+ std::list<Channel>::iterator it = channels.begin();
+
+ while (channel > 1) { // Channel count starts from one!
+ ++it;
+ --channel;
+ }
+
+ return *it;
+}
+
+ExportChannelSelector::ChannelTreeView::ChannelTreeView (uint32_t max_channels) :
+ n_channels (0)
+{
+ /* Main columns */
+
+ route_cols.add_channels (max_channels);
+
+ route_list = Gtk::ListStore::create(route_cols);
+ set_model (route_list);
+
+ /* Add column with toggle and text */
+
+ append_column_editable (_("Bus or Track"), route_cols.selected);
+
+ Gtk::CellRendererText* text_renderer = Gtk::manage (new Gtk::CellRendererText);
+ text_renderer->property_editable() = false;
+
+ Gtk::TreeView::Column* column = get_column (0);
+ column->pack_start (*text_renderer);
+ column->add_attribute (text_renderer->property_text(), route_cols.name);
+
+ Gtk::CellRendererToggle *toggle = dynamic_cast<Gtk::CellRendererToggle *>(get_column_cell_renderer (0));
+ toggle->signal_toggled().connect (mem_fun (*this, &ExportChannelSelector::ChannelTreeView::update_toggle_selection));
+
+ static_columns = get_columns().size();
+}
+
+void
+ExportChannelSelector::ChannelTreeView::set_config (ChannelConfigPtr c)
+{
+ /* TODO Without the following line, the state might get reset.
+ * Pointing to the same address does not mean the state of the configuration hasn't changed.
+ * In the current code this is safe, but the actual cause of the problem would be good to fix
+ */
+
+ if (config == c) { return; }
+ config = c;
+
+ uint32_t i = 1;
+ ExportChannelConfiguration::ChannelList chan_list = config->get_channels();
+ for (ExportChannelConfiguration::ChannelList::iterator c_it = chan_list.begin(); c_it != chan_list.end(); ++c_it) {
+
+ for (Gtk::ListStore::Children::iterator r_it = route_list->children().begin(); r_it != route_list->children().end(); ++r_it) {
+
+ Glib::RefPtr<Gtk::ListStore> port_list = r_it->get_value (route_cols.port_list_col);
+ std::set<AudioPort *> route_ports;
+ std::set<AudioPort *> intersection;
+ std::map<AudioPort *, ustring> port_labels;
+
+ for (Gtk::ListStore::Children::const_iterator p_it = port_list->children().begin(); p_it != port_list->children().end(); ++p_it) {
+ route_ports.insert ((*p_it)->get_value (route_cols.port_cols.port));
+ port_labels.insert (std::pair<AudioPort*, ustring> ((*p_it)->get_value (route_cols.port_cols.port),
+ (*p_it)->get_value (route_cols.port_cols.label)));
+ }
+
+ std::set_intersection ((*c_it)->begin(), (*c_it)->end(),
+ route_ports.begin(), route_ports.end(),
+ std::insert_iterator<std::set<AudioPort *> > (intersection, intersection.begin()));
+
+ intersection.erase (0); // Remove "none" selection
+
+ if (intersection.empty()) {
+ continue;
+ }
+
+ if (!r_it->get_value (route_cols.selected)) {
+ r_it->set_value (route_cols.selected, true);
+
+ /* Set previous channels (if any) to none */
+
+ for (uint32_t chn = 1; chn < i; ++chn) {
+ r_it->set_value (route_cols.get_channel (chn).port, (AudioPort *) 0);
+ r_it->set_value (route_cols.get_channel (chn).label, ustring ("(none)"));
+ }
+ }
+
+ AudioPort * port = *intersection.begin();
+ std::map<AudioPort *, ustring>::iterator label_it = port_labels.find (port);
+ ustring label = label_it != port_labels.end() ? label_it->second : "error";
+
+ r_it->set_value (route_cols.get_channel (i).port, port);
+ r_it->set_value (route_cols.get_channel (i).label, label);
+ }
+
+ ++i;
+ }
+}
+
+void
+ExportChannelSelector::ChannelTreeView::add_route (ARDOUR::IO * route)
+{
+ Gtk::TreeModel::iterator iter = route_list->append();
+ Gtk::TreeModel::Row row = *iter;
+
+ row[route_cols.selected] = false;
+ row[route_cols.name] = route->name();
+ row[route_cols.io] = route;
+
+ /* Initialize port list */
+
+ Glib::RefPtr<Gtk::ListStore> port_list = Gtk::ListStore::create (route_cols.port_cols);
+ row[route_cols.port_list_col] = port_list;
+
+ uint32_t outs = route->n_outputs().n_audio();
+ for (uint32_t i = 0; i < outs; ++i) {
+ iter = port_list->append();
+ row = *iter;
+
+ row[route_cols.port_cols.selected] = false;
+ row[route_cols.port_cols.port] = route->audio_output (i);
+
+ std::ostringstream oss;
+ oss << "Out-" << (i + 1);
+
+ row[route_cols.port_cols.label] = oss.str();
+ }
+
+ iter = port_list->append();
+ row = *iter;
+
+ row[route_cols.port_cols.selected] = false;
+ row[route_cols.port_cols.port] = 0;
+ row[route_cols.port_cols.label] = "(none)";
+
+}
+
+void
+ExportChannelSelector::ChannelTreeView::set_channel_count (uint32_t channels)
+{
+ int offset = channels - n_channels;
+
+ while (offset > 0) {
+ ++n_channels;
+
+ std::ostringstream oss;
+ oss << n_channels;
+
+ /* New column */
+
+ Gtk::TreeView::Column* column = Gtk::manage (new Gtk::TreeView::Column (oss.str()));
+
+ Gtk::CellRendererCombo* combo_renderer = Gtk::manage (new Gtk::CellRendererCombo);
+ combo_renderer->property_text_column() = 2;
+ column->pack_start (*combo_renderer);
+
+ append_column (*column);
+
+ column->add_attribute (combo_renderer->property_text(), route_cols.get_channel(n_channels).label);
+ column->add_attribute (combo_renderer->property_model(), route_cols.port_list_col);
+ column->add_attribute (combo_renderer->property_editable(), route_cols.selected);
+
+ combo_renderer->signal_edited().connect (sigc::bind (sigc::mem_fun (*this, &ExportChannelSelector::ChannelTreeView::update_selection_text), n_channels));
+
+ /* put data into view */
+
+ for (Gtk::ListStore::Children::iterator it = route_list->children().begin(); it != route_list->children().end(); ++it) {
+ Glib::ustring label = it->get_value(route_cols.selected) ? "(none)" : "";
+ it->set_value (route_cols.get_channel (n_channels).label, label);
+ it->set_value (route_cols.get_channel (n_channels).port, (AudioPort *) 0);
+ }
+
+ /* set column width */
+
+ get_column (static_columns + n_channels - 1)->set_min_width (80);
+
+ --offset;
+ }
+
+ while (offset < 0) {
+ --n_channels;
+
+ remove_column (*get_column (n_channels + static_columns));
+
+ ++offset;
+ }
+
+ update_config ();
+}
+
+void
+ExportChannelSelector::ChannelTreeView::update_config ()
+{
+
+ if (!config) { return; }
+
+ config->clear_channels();
+
+ for (uint32_t i = 1; i <= n_channels; ++i) {
+
+ boost::shared_ptr<ExportChannel> channel (new ExportChannel ());
+
+ for (Gtk::ListStore::Children::iterator it = route_list->children().begin(); it != route_list->children().end(); ++it) {
+ Gtk::TreeModel::Row row = *it;
+
+ if (!row[route_cols.selected]) {
+ continue;
+ }
+
+ AudioPort * port = row[route_cols.get_channel (i).port];
+ if (port) {
+ channel->add_port (port);
+ }
+ }
+
+ config->register_channel (channel);
+ }
+
+ CriticalSelectionChanged ();
+}
+
+void
+ExportChannelSelector::ChannelTreeView::update_toggle_selection (Glib::ustring const & path)
+{
+ Gtk::TreeModel::iterator iter = get_model ()->get_iter (path);
+ bool selected = iter->get_value (route_cols.selected);
+
+ for (uint32_t i = 1; i <= n_channels; ++i) {
+
+ if (!selected) {
+ iter->set_value (route_cols.get_channel (i).label, Glib::ustring (""));
+ continue;
+ }
+
+ iter->set_value (route_cols.get_channel (i).label, Glib::ustring("(none)"));
+ iter->set_value (route_cols.get_channel (i).port, (AudioPort *) 0);
+
+ Glib::RefPtr<Gtk::ListStore> port_list = iter->get_value (route_cols.port_list_col);
+ Gtk::ListStore::Children::iterator port_it;
+ uint32_t port_number = 1;
+
+ for (port_it = port_list->children().begin(); port_it != port_list->children().end(); ++port_it) {
+ if (port_number == i) {
+ iter->set_value (route_cols.get_channel (i).label, (Glib::ustring) (*port_it)->get_value (route_cols.port_cols.label));
+ iter->set_value (route_cols.get_channel (i).port, (AudioPort *) (*port_it)->get_value (route_cols.port_cols.port));
+ }
+
+ ++port_number;
+ }
+ }
+
+ update_config ();
+}
+
+void
+ExportChannelSelector::ChannelTreeView::update_selection_text (Glib::ustring const & path, Glib::ustring const & new_text, uint32_t channel)
+{
+ Gtk::TreeModel::iterator iter = get_model ()->get_iter (path);
+ iter->set_value (route_cols.get_channel (channel).label, new_text);
+
+ Glib::RefPtr<Gtk::ListStore> port_list = iter->get_value (route_cols.port_list_col);
+ Gtk::ListStore::Children::iterator port_it;
+
+ for (port_it = port_list->children().begin(); port_it != port_list->children().end(); ++port_it) {
+ Glib::ustring label = port_it->get_value (route_cols.port_cols.label);
+ if (label == new_text) {
+ iter->set_value (route_cols.get_channel (channel).port, (AudioPort *) (*port_it)[route_cols.port_cols.port]);
+ }
+ }
+
+ update_config ();
+}
diff --git a/gtk2_ardour/export_channel_selector.h b/gtk2_ardour/export_channel_selector.h
new file mode 100644
index 0000000000..0faf652bd8
--- /dev/null
+++ b/gtk2_ardour/export_channel_selector.h
@@ -0,0 +1,181 @@
+/*
+ Copyright (C) 2008 Paul Davis
+ Author: Sakari Bergen
+
+ 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.
+
+*/
+
+#ifndef __export_channel_selector_h__
+#define __export_channel_selector_h__
+
+#include <list>
+
+#include <ardour/export_profile_manager.h>
+
+#include <gtkmm.h>
+#include <sigc++/signal.h>
+#include <boost/shared_ptr.hpp>
+
+namespace ARDOUR {
+ class Session;
+ class ExportChannel;
+ class ExportChannelConfiguration;
+ class ExportHandler;
+ class AudioPort;
+ class IO;
+}
+
+class XMLNode;
+
+///
+class ExportChannelSelector : public Gtk::HBox {
+ private:
+
+ typedef boost::shared_ptr<ARDOUR::ExportChannelConfiguration> ChannelConfigPtr;
+
+ typedef boost::shared_ptr<ARDOUR::ExportHandler> HandlerPtr;
+
+ public:
+
+ ExportChannelSelector ();
+ ~ExportChannelSelector ();
+
+ void set_state (ARDOUR::ExportProfileManager::ChannelConfigStatePtr const state_, ARDOUR::Session * session_);
+
+ sigc::signal<void> CriticalSelectionChanged;
+
+ private:
+
+ void fill_route_list ();
+ void update_channel_count ();
+ void update_split_state ();
+
+ typedef boost::shared_ptr<ARDOUR::ExportChannel> ChannelPtr;
+ typedef std::list<ChannelPtr> CahnnelList;
+
+ ARDOUR::Session * session;
+ ARDOUR::ExportProfileManager::ChannelConfigStatePtr state;
+
+ /*** GUI stuff ***/
+
+ Gtk::VBox channels_vbox;
+ Gtk::HBox channels_hbox;
+
+ Gtk::Label channels_label;
+ Gtk::SpinButton channels_spinbutton;
+ Gtk::CheckButton split_checkbox;
+
+ /* Column record for channel selector view */
+
+ class RouteCols : public Gtk::TreeModelColumnRecord
+ {
+ public:
+
+ struct Channel;
+
+ RouteCols () : n_channels (0)
+ { add (selected); add (name); add (io); add (port_list_col); }
+
+ void add_channels (uint32_t chans);
+ uint32_t n_channels;
+
+ /* Channel count starts from one! */
+
+ Channel & get_channel (uint32_t channel);
+
+ /* Static columns */
+
+ Gtk::TreeModelColumn<bool> selected;
+ Gtk::TreeModelColumn<Glib::ustring> name;
+ Gtk::TreeModelColumn<ARDOUR::IO *> io;
+
+ /* Combo list column (shared by all channels) */
+
+ typedef Gtk::TreeModelColumn<Glib::RefPtr<Gtk::ListStore> > ComboCol;
+ ComboCol port_list_col;
+
+ /* Channel struct, that represents the selected port and it's name */
+
+ struct Channel {
+ public:
+ Channel (RouteCols & cols) { cols.add (port); cols.add (label); }
+
+ Gtk::TreeModelColumn<ARDOUR::AudioPort *> port;
+ Gtk::TreeModelColumn<Glib::ustring> label;
+ };
+ std::list<Channel> channels;
+
+ /* List of available ports
+ * Note: We need only one list of selectable ports per route,
+ * so the list is kept in the column record
+ */
+
+ /* Column record for selecting ports for a channel from a route */
+
+ class PortCols : public Gtk::TreeModel::ColumnRecord
+ {
+ public:
+ PortCols () { add (selected); add(port); add(label); }
+
+ Gtk::TreeModelColumn<bool> selected; // not used ATM
+ Gtk::TreeModelColumn<ARDOUR::AudioPort *> port;
+ Gtk::TreeModelColumn<Glib::ustring> label;
+ };
+ PortCols port_cols;
+ };
+
+ /* Channels view */
+
+ class ChannelTreeView : public Gtk::TreeView {
+ public:
+
+ ChannelTreeView (uint32_t max_channels);
+ void set_config (ChannelConfigPtr c);
+
+ /* Routes have to be added before adding channels */
+
+ void clear_routes () { route_list->clear (); }
+ void add_route (ARDOUR::IO * route);
+ void set_channel_count (uint32_t channels);
+
+ sigc::signal<void> CriticalSelectionChanged;
+
+ private:
+
+ ChannelConfigPtr config;
+ void update_config ();
+
+ /* Signal handlers for selections changes in the view */
+
+ void update_toggle_selection (Glib::ustring const & path);
+ void update_selection_text (Glib::ustring const & path, Glib::ustring const & new_text, uint32_t channel);
+
+ RouteCols route_cols;
+ Glib::RefPtr<Gtk::ListStore> route_list;
+
+ uint32_t static_columns;
+ uint32_t n_channels;
+ };
+
+ uint32_t max_channels;
+
+ Gtk::ScrolledWindow channel_scroller;
+ Gtk::Alignment channel_alignment;
+ ChannelTreeView channel_view;
+
+};
+
+#endif /* __export_channel_selector_h__ */
diff --git a/gtk2_ardour/export_filename_selector.cc b/gtk2_ardour/export_filename_selector.cc
new file mode 100644
index 0000000000..186ff69a80
--- /dev/null
+++ b/gtk2_ardour/export_filename_selector.cc
@@ -0,0 +1,303 @@
+/*
+ Copyright (C) 2008 Paul Davis
+ Author: Sakari Bergen
+
+ 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 "export_filename_selector.h"
+
+#include <ardour/export_handler.h>
+#include <ardour/session.h>
+#include <ardour/session_directory.h>
+
+#include "i18n.h"
+
+using namespace ARDOUR;
+
+ExportFilenameSelector::ExportFilenameSelector () :
+ session (0),
+
+ include_label (_("Include in Filename(s):"), Gtk::ALIGN_LEFT),
+
+ label_label (_("Label:"), Gtk::ALIGN_LEFT),
+ session_checkbox (_("Session Name")),
+ revision_checkbox (_("Revision:")),
+
+ path_label (_("Folder:"), Gtk::ALIGN_LEFT),
+ browse_button (_("Browse"))
+{
+ pack_start (include_label, false, false, 6);
+ pack_start (include_hbox, false, false, 0);
+ pack_start (path_hbox, false, false, 12);
+
+ include_hbox.pack_start (label_label, false, false, 3);
+ include_hbox.pack_start (label_entry, false, false, 3);
+ include_hbox.pack_start (session_checkbox, false, false, 3);
+ include_hbox.pack_start (date_format_combo, false, false, 3);
+ include_hbox.pack_start (time_format_combo, false, false, 3);
+ include_hbox.pack_start (revision_checkbox, false, false, 3);
+ include_hbox.pack_start (revision_spinbutton, false, false, 3);
+
+ path_hbox.pack_start (path_label, false, false, 3);
+ path_hbox.pack_start (path_entry, true, true, 3);
+ path_hbox.pack_start (browse_button, false, false, 3);
+
+ label_sizegroup = Gtk::SizeGroup::create (Gtk::SIZE_GROUP_HORIZONTAL);
+ label_sizegroup->add_widget (label_label);
+ label_sizegroup->add_widget (path_label);
+
+ /* Date */
+
+ date_format_list = Gtk::ListStore::create (date_format_cols);
+ date_format_combo.set_model (date_format_list);
+ date_format_combo.pack_start (date_format_cols.label);
+
+ date_format_combo.signal_changed().connect (sigc::mem_fun (*this, &ExportFilenameSelector::change_date_format));
+
+ /* Time */
+
+ time_format_list = Gtk::ListStore::create (time_format_cols);
+ time_format_combo.set_model (time_format_list);
+ time_format_combo.pack_start (time_format_cols.label);
+
+ time_format_combo.signal_changed().connect (sigc::mem_fun (*this, &ExportFilenameSelector::change_time_format));
+
+ /* Revision */
+
+ revision_spinbutton.set_digits (0);
+ revision_spinbutton.set_increments (1, 10);
+ revision_spinbutton.set_range (1, 1000);
+ revision_spinbutton.set_sensitive (false);
+
+ /* Signals */
+
+ label_entry.signal_changed().connect (sigc::mem_fun (*this, &ExportFilenameSelector::update_label));
+ path_entry.signal_changed().connect (sigc::mem_fun (*this, &ExportFilenameSelector::update_folder));
+
+ session_checkbox.signal_toggled().connect (sigc::mem_fun (*this, &ExportFilenameSelector::change_session_selection));
+
+ revision_checkbox.signal_toggled().connect (sigc::mem_fun (*this, &ExportFilenameSelector::change_revision_selection));
+ revision_spinbutton.signal_value_changed().connect (sigc::mem_fun (*this, &ExportFilenameSelector::change_revision_value));
+
+ browse_button.signal_clicked().connect (sigc::mem_fun (*this, &ExportFilenameSelector::open_browse_dialog));
+}
+
+ExportFilenameSelector::~ExportFilenameSelector ()
+{
+
+}
+
+void
+ExportFilenameSelector::load_state ()
+{
+ if (!filename) {
+ return;
+ }
+
+ label_entry.set_text (filename->include_label ? filename->get_label() : "");
+ session_checkbox.set_active (filename->include_session);
+ revision_checkbox.set_active (filename->include_revision);
+ revision_spinbutton.set_value (filename->get_revision());
+ path_entry.set_text (filename->get_folder());
+
+ Gtk::TreeModel::Children::iterator it;
+
+ for (it = date_format_list->children().begin(); it != date_format_list->children().end(); ++it) {
+ if (it->get_value (date_format_cols.format) == filename->get_date_format()) {
+ date_format_combo.set_active (it);
+ }
+ }
+
+ for (it = time_format_list->children().begin(); it != time_format_list->children().end(); ++it) {
+ if (it->get_value (time_format_cols.format) == filename->get_time_format()) {
+ time_format_combo.set_active (it);
+ }
+ }
+}
+
+void
+ExportFilenameSelector::set_state (ARDOUR::ExportProfileManager::FilenameStatePtr state_, ARDOUR::Session * session_)
+{
+ session = session_;
+
+ filename = state_->filename;
+
+ /* Fill combo boxes */
+
+ Gtk::TreeModel::iterator iter;
+ Gtk::TreeModel::Row row;
+
+ /* Dates */
+
+ date_format_list->clear();
+
+ iter = date_format_list->append();
+ row = *iter;
+ row[date_format_cols.format] = ExportFilename::D_None;
+ row[date_format_cols.label] = filename->get_date_format_str (ExportFilename::D_None);
+
+ iter = date_format_list->append();
+ row = *iter;
+ row[date_format_cols.format] = ExportFilename::D_ISO;
+ row[date_format_cols.label] = filename->get_date_format_str (ExportFilename::D_ISO);
+
+ iter = date_format_list->append();
+ row = *iter;
+ row[date_format_cols.format] = ExportFilename::D_ISOShortY;
+ row[date_format_cols.label] = filename->get_date_format_str (ExportFilename::D_ISOShortY);
+
+ iter = date_format_list->append();
+ row = *iter;
+ row[date_format_cols.format] = ExportFilename::D_BE;
+ row[date_format_cols.label] = filename->get_date_format_str (ExportFilename::D_BE);
+
+ iter = date_format_list->append();
+ row = *iter;
+ row[date_format_cols.format] = ExportFilename::D_BEShortY;
+ row[date_format_cols.label] = filename->get_date_format_str (ExportFilename::D_BEShortY);
+
+ /* Times */
+
+ time_format_list->clear();
+
+ iter = time_format_list->append();
+ row = *iter;
+ row[time_format_cols.format] = ExportFilename::T_None;
+ row[time_format_cols.label] = filename->get_time_format_str (ExportFilename::T_None);
+
+ iter = time_format_list->append();
+ row = *iter;
+ row[time_format_cols.format] = ExportFilename::T_NoDelim;
+ row[time_format_cols.label] = filename->get_time_format_str (ExportFilename::T_NoDelim);
+
+ iter = time_format_list->append();
+ row = *iter;
+ row[time_format_cols.format] = ExportFilename::T_Delim;
+ row[time_format_cols.label] = filename->get_time_format_str (ExportFilename::T_Delim);
+
+ /* Load state */
+
+ load_state();
+
+}
+
+void
+ExportFilenameSelector::update_label ()
+{
+ if (!filename) {
+ return;
+ }
+
+ filename->set_label (label_entry.get_text());
+
+ filename->include_label = !label_entry.get_text().empty();
+ CriticalSelectionChanged();
+}
+
+void
+ExportFilenameSelector::update_folder ()
+{
+ if (!filename) {
+ return;
+ }
+
+ filename->set_folder (path_entry.get_text());
+ CriticalSelectionChanged();
+}
+
+void
+ExportFilenameSelector::change_date_format ()
+{
+ if (!filename) {
+ return;
+ }
+
+ DateFormat format = date_format_combo.get_active()->get_value (date_format_cols.format);
+ filename->set_date_format (format);
+ CriticalSelectionChanged();
+}
+
+void
+ExportFilenameSelector::change_time_format ()
+{
+ if (!filename) {
+ return;
+ }
+
+ TimeFormat format = time_format_combo.get_active()->get_value (time_format_cols.format);
+ filename->set_time_format (format);
+ CriticalSelectionChanged();
+}
+
+void
+ExportFilenameSelector::change_session_selection ()
+{
+ if (!filename) {
+ return;
+ }
+
+ filename->include_session = session_checkbox.get_active();
+ CriticalSelectionChanged();
+}
+
+void
+ExportFilenameSelector::change_revision_selection ()
+{
+ if (!filename) {
+ return;
+ }
+
+ bool selected = revision_checkbox.get_active();
+ filename->include_revision = selected;
+
+ revision_spinbutton.set_sensitive (selected);
+ CriticalSelectionChanged();
+}
+
+void
+ExportFilenameSelector::change_revision_value ()
+{
+ if (!filename) {
+ return;
+ }
+
+ filename->set_revision ((uint32_t) revision_spinbutton.get_value_as_int());
+ CriticalSelectionChanged();
+}
+
+void
+ExportFilenameSelector::open_browse_dialog ()
+{
+ Gtk::FileChooserDialog dialog(_("Choose export folder"), Gtk::FILE_CHOOSER_ACTION_SELECT_FOLDER);
+ //dialog.set_transient_for(*this);
+ dialog.set_filename (path_entry.get_text());
+
+ dialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
+ dialog.add_button(Gtk::Stock::OK, Gtk::RESPONSE_OK);
+
+ int result = dialog.run();
+
+ if (result == Gtk::RESPONSE_OK) {
+ Glib::ustring filename = dialog.get_filename();
+
+ if (filename.length()) {
+ path_entry.set_text (filename);
+ }
+ }
+
+ CriticalSelectionChanged();
+}
diff --git a/gtk2_ardour/export_filename_selector.h b/gtk2_ardour/export_filename_selector.h
new file mode 100644
index 0000000000..c21435bb57
--- /dev/null
+++ b/gtk2_ardour/export_filename_selector.h
@@ -0,0 +1,120 @@
+/*
+ Copyright (C) 2008 Paul Davis
+ Author: Sakari Bergen
+
+ 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.
+
+*/
+
+#ifndef __export_filename_selector_h__
+#define __export_filename_selector_h__
+
+#include <gtkmm.h>
+
+#include <ardour/export_profile_manager.h>
+#include <ardour/export_filename.h>
+
+namespace ARDOUR {
+ class Session;
+}
+
+///
+class ExportFilenameSelector : public Gtk::VBox {
+ public:
+ typedef boost::shared_ptr<ARDOUR::ExportFilename> FilenamePtr;
+
+ ExportFilenameSelector ();
+ ~ExportFilenameSelector ();
+
+ void set_state (ARDOUR::ExportProfileManager::FilenameStatePtr state_, ARDOUR::Session * session_);
+
+ /* Compatibility with other elements */
+
+ sigc::signal<void> CriticalSelectionChanged;
+
+ private:
+
+ void load_state ();
+
+ void update_label ();
+ void update_folder ();
+
+ void change_date_format ();
+ void change_time_format ();
+
+ void change_session_selection ();
+ void change_revision_selection ();
+ void change_revision_value ();
+
+ void open_browse_dialog ();
+
+ ARDOUR::Session * session;
+ boost::shared_ptr<ARDOUR::ExportFilename> filename;
+
+ Glib::RefPtr<Gtk::SizeGroup> label_sizegroup;
+
+ Gtk::Label include_label;
+
+ Gtk::HBox include_hbox;
+
+ Gtk::Label label_label;
+ Gtk::Entry label_entry;
+
+ Gtk::CheckButton session_checkbox;
+
+ Gtk::CheckButton revision_checkbox;
+ Gtk::SpinButton revision_spinbutton;
+
+ Gtk::HBox path_hbox;
+
+ Gtk::Label path_label;
+ Gtk::Entry path_entry;
+ Gtk::Button browse_button;
+
+ /* Date combo */
+
+ typedef ARDOUR::ExportFilename::DateFormat DateFormat;
+
+ struct DateFormatCols : public Gtk::TreeModelColumnRecord
+ {
+ public:
+ Gtk::TreeModelColumn<DateFormat> format;
+ Gtk::TreeModelColumn<Glib::ustring> label;
+
+ DateFormatCols () { add(format); add(label); }
+ };
+ DateFormatCols date_format_cols;
+ Glib::RefPtr<Gtk::ListStore> date_format_list;
+ Gtk::ComboBox date_format_combo;
+
+ /* Time combo */
+
+ typedef ARDOUR::ExportFilename::TimeFormat TimeFormat;
+
+ struct TimeFormatCols : public Gtk::TreeModelColumnRecord
+ {
+ public:
+ Gtk::TreeModelColumn<TimeFormat> format;
+ Gtk::TreeModelColumn<Glib::ustring> label;
+
+ TimeFormatCols () { add(format); add(label); }
+ };
+ TimeFormatCols time_format_cols;
+ Glib::RefPtr<Gtk::ListStore> time_format_list;
+ Gtk::ComboBox time_format_combo;
+
+};
+
+#endif /* __export_filename_selector_h__ */
diff --git a/gtk2_ardour/export_format_dialog.cc b/gtk2_ardour/export_format_dialog.cc
new file mode 100644
index 0000000000..f123c9cbbb
--- /dev/null
+++ b/gtk2_ardour/export_format_dialog.cc
@@ -0,0 +1,953 @@
+/*
+ Copyright (C) 2008 Paul Davis
+ Author: Sakari Bergen
+
+ 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 "export_format_dialog.h"
+
+#include <ardour/session.h>
+#include <ardour/export_format_specification.h>
+
+#include "i18n.h"
+
+using namespace ARDOUR;
+
+ExportFormatDialog::ExportFormatDialog (FormatPtr format, bool new_dialog) :
+ ArdourDialog (new_dialog ? _("New export format profile") : _("Edit export format profile")),
+ format (format),
+ manager (format),
+ original_state (format->get_state()),
+
+ applying_changes_from_engine (0),
+
+ name_label (_("Label: "), Gtk::ALIGN_LEFT),
+
+ normalize_checkbox (_("Normalize to:")),
+ normalize_adjustment (0.00, -90.00, 0.00, 0.1, 0.2),
+ normalize_db_label (_("dBFS"), Gtk::ALIGN_LEFT),
+
+ silence_table (2, 4),
+ trim_start_checkbox (_("Trim silence at start")),
+ silence_start_checkbox (_("Add silence at start:")),
+ silence_start_clock ("silence_start", true, "PreRollClock", true, true),
+
+ trim_end_checkbox (_("Trim silence at end")),
+ silence_end_checkbox (_("Add silence at end:")),
+ silence_end_clock ("silence_end", true, "PreRollClock", true, true),
+
+ format_table (3, 4),
+ compatibility_label (_("Compatibility"), Gtk::ALIGN_LEFT),
+ quality_label (_("Quality"), Gtk::ALIGN_LEFT),
+ format_label (_("File format"), Gtk::ALIGN_LEFT),
+ sample_rate_label (_("Sample rate"), Gtk::ALIGN_LEFT),
+ src_quality_label (_("Sample rate conversion quality:"), Gtk::ALIGN_RIGHT),
+
+ encoding_options_label (_(""), Gtk::ALIGN_LEFT),
+
+ /* Changing encoding options from here on */
+
+ sample_format_label (_("Sample Format"), Gtk::ALIGN_LEFT),
+ dither_label (_("Dithering"), Gtk::ALIGN_LEFT),
+
+ tag_checkbox (_("Tag file with session's metadata"))
+{
+
+ /* Pack containers in dialog */
+
+ get_vbox()->pack_start (name_hbox, false, false, 0);
+ get_vbox()->pack_start (silence_table, false, false, 6);
+ get_vbox()->pack_start (format_table, false, false, 6);
+ get_vbox()->pack_start (encoding_options_vbox, false, false, 0);
+
+ /* Name, new and remove */
+
+ name_hbox.pack_start (name_label, false, false, 0);
+ name_hbox.pack_start (name_entry, true, true, 0);
+
+ /* Normalize */
+
+ normalize_hbox.pack_start (normalize_checkbox, false, false, 0);
+ normalize_hbox.pack_start (normalize_spinbutton, false, false, 6);
+ normalize_hbox.pack_start (normalize_db_label, false, false, 0);
+
+ normalize_spinbutton.configure (normalize_adjustment, 0.1, 2);
+
+ /* Silence */
+
+ silence_table.set_row_spacings (6);
+ silence_table.set_col_spacings (12);
+
+ silence_table.attach (normalize_hbox, 0, 3, 0, 1);
+
+ silence_table.attach (trim_start_checkbox, 0, 1, 1, 2);
+ silence_table.attach (silence_start_checkbox, 1, 2, 1, 2);
+ silence_table.attach (silence_start_clock, 2, 3, 1, 2);
+
+ silence_table.attach (trim_end_checkbox, 0, 1, 2, 3);
+ silence_table.attach (silence_end_checkbox, 1, 2, 2, 3);
+ silence_table.attach (silence_end_clock, 2, 3, 2, 3);
+
+ /* Format table */
+
+ init_format_table();
+
+ /* Encoding options */
+
+ init_encoding_option_widgets();
+
+ encoding_options_table.set_spacings (1);
+
+ encoding_options_vbox.pack_start (encoding_options_label, false, false, 0);
+ encoding_options_vbox.pack_start (encoding_options_table, false, false, 12);
+
+ Pango::AttrList bold;
+ Pango::Attribute b = Pango::Attribute::create_attr_weight (Pango::WEIGHT_BOLD);
+ bold.insert (b);
+ encoding_options_label.set_attributes (bold);
+
+ /* Buttons */
+
+ revert_button = add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
+ revert_button->signal_clicked().connect (mem_fun(*this, &ExportFormatDialog::revert));
+ close_button = add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_APPLY);
+ close_button->set_sensitive (false);
+ close_button->signal_clicked().connect (mem_fun (*this, &ExportFormatDialog::end_dialog));
+ manager.CompleteChanged.connect (mem_fun (*close_button, &Gtk::Button::set_sensitive));
+
+ /* Load state before hooking up the rest of the signals */
+
+ load_state (format);
+
+ /* Name entry */
+
+ name_entry.signal_changed().connect (mem_fun (*this, &ExportFormatDialog::update_name));
+
+ /* Normalize, silence and src_quality signals */
+
+ trim_start_checkbox.signal_toggled().connect (mem_fun (*this, &ExportFormatDialog::update_trim_start_selection));
+ trim_end_checkbox.signal_toggled().connect (mem_fun (*this, &ExportFormatDialog::update_trim_end_selection));
+
+ normalize_checkbox.signal_toggled().connect (mem_fun (*this, &ExportFormatDialog::update_normalize_selection));
+ normalize_spinbutton.signal_value_changed().connect (mem_fun (*this, &ExportFormatDialog::update_normalize_selection));
+
+ silence_start_checkbox.signal_toggled().connect (mem_fun (*this, &ExportFormatDialog::update_silence_start_selection));
+ silence_start_clock.ValueChanged.connect (mem_fun (*this, &ExportFormatDialog::update_silence_start_selection));
+
+ silence_end_checkbox.signal_toggled().connect (mem_fun (*this, &ExportFormatDialog::update_silence_end_selection));
+ silence_end_clock.ValueChanged.connect (mem_fun (*this, &ExportFormatDialog::update_silence_end_selection));
+
+ src_quality_combo.signal_changed().connect (mem_fun (*this, &ExportFormatDialog::update_src_quality_selection));
+
+ /* Format table signals */
+
+ Gtk::CellRendererToggle *toggle = dynamic_cast<Gtk::CellRendererToggle *>(compatibility_view.get_column_cell_renderer (0));
+ toggle->signal_toggled().connect (mem_fun (*this, &ExportFormatDialog::update_compatibility_selection));
+ compatibility_select_connection = compatibility_view.get_selection()->signal_changed().connect (mem_fun (*this, &ExportFormatDialog::prohibit_compatibility_selection));
+
+ quality_view.get_selection()->signal_changed().connect (mem_fun(*this, &ExportFormatDialog::update_quality_selection));
+ format_view.get_selection()->signal_changed().connect (mem_fun(*this, &ExportFormatDialog::update_format_selection));
+ sample_rate_view.get_selection()->signal_changed().connect (mem_fun(*this, &ExportFormatDialog::update_sample_rate_selection));
+
+ /* Encoding option signals */
+
+ sample_format_view.get_selection()->signal_changed().connect (mem_fun(*this, &ExportFormatDialog::update_sample_format_selection));
+ dither_type_view.get_selection()->signal_changed().connect (mem_fun(*this, &ExportFormatDialog::update_dither_type_selection));
+
+ tag_checkbox.signal_toggled().connect (mem_fun (*this, &ExportFormatDialog::update_tagging_selection));
+
+ /* Finalize */
+
+ show_all_children();
+}
+
+ExportFormatDialog::~ExportFormatDialog ()
+{
+
+}
+
+void
+ExportFormatDialog::revert ()
+{
+ ++applying_changes_from_engine;
+
+ format->set_state (original_state);
+ load_state (format);
+
+ --applying_changes_from_engine;
+}
+
+void
+ExportFormatDialog::set_session (ARDOUR::Session* s)
+{
+ session = s;
+ if (!session) {
+ return;
+ }
+
+ silence_start_clock.set_session (s);
+ silence_end_clock.set_session (s);
+
+ update_clock (silence_start_clock, silence_start);
+ update_clock (silence_end_clock, silence_end);
+
+ /* Select native samplerate if no selection is yet made */
+
+ if (sample_rate_view.get_selection()->count_selected_rows() == 0) {
+ Gtk::ListStore::Children::iterator it;
+ for (it = sample_rate_list->children().begin(); it != sample_rate_list->children().end(); ++it) {
+ if ((nframes_t) (*it)->get_value (sample_rate_cols.ptr)->rate == session->nominal_frame_rate()) {
+ sample_rate_view.get_selection()->select (it);
+ break;
+ }
+ }
+ }
+}
+
+void
+ExportFormatDialog::load_state (FormatPtr spec)
+{
+ name_entry.set_text (spec->name());
+
+ normalize_checkbox.set_active (spec->normalize());
+ normalize_spinbutton.set_value (spec->normalize_target());
+
+ trim_start_checkbox.set_active (spec->trim_beginning());
+ silence_start = spec->silence_beginning_time();
+ silence_start_checkbox.set_active (spec->silence_beginning() > 0);
+
+ trim_end_checkbox.set_active (spec->trim_end());
+ silence_end = spec->silence_end_time();
+ silence_end_checkbox.set_active (spec->silence_end() > 0);
+
+ for (Gtk::ListStore::Children::iterator it = src_quality_list->children().begin(); it != src_quality_list->children().end(); ++it) {
+ if (it->get_value (src_quality_cols.id) == spec->src_quality()) {
+ src_quality_combo.set_active (it);
+ break;
+ }
+ }
+
+ for (Gtk::ListStore::Children::iterator it = format_list->children().begin(); it != format_list->children().end(); ++it) {
+ if (it->get_value (format_cols.ptr)->get_format_id() == spec->format_id()) {
+ it->get_value (format_cols.ptr)->set_selected (true);
+ break;
+ }
+ }
+
+ for (Gtk::ListStore::Children::iterator it = sample_rate_list->children().begin(); it != sample_rate_list->children().end(); ++it) {
+ if (it->get_value (sample_rate_cols.ptr)->rate == spec->sample_rate()) {
+ it->get_value (sample_rate_cols.ptr)->set_selected (true);
+ break;
+ }
+ }
+
+ if (spec->sample_format()) {
+ for (Gtk::ListStore::Children::iterator it = sample_format_list->children().begin(); it != sample_format_list->children().end(); ++it) {
+ if (it->get_value (sample_format_cols.ptr)->format == spec->sample_format()) {
+ it->get_value (sample_format_cols.ptr)->set_selected (true);
+ break;
+ }
+ }
+
+ for (Gtk::ListStore::Children::iterator it = dither_type_list->children().begin(); it != dither_type_list->children().end(); ++it) {
+ if (it->get_value (dither_type_cols.ptr)->type == spec->dither_type()) {
+ it->get_value (dither_type_cols.ptr)->set_selected (true);
+ break;
+ }
+ }
+ }
+
+ tag_checkbox.set_active (spec->tag());
+}
+
+void
+ExportFormatDialog::init_format_table ()
+{
+
+ format_table.set_spacings (1);
+
+ format_table.attach (compatibility_label, 0, 1, 0, 1);
+ format_table.attach (quality_label, 1, 2, 0, 1);
+ format_table.attach (format_label, 2, 3, 0, 1);
+ format_table.attach (sample_rate_label, 3, 4, 0, 1);
+
+ format_table.attach (compatibility_view, 0, 1, 1, 2);
+ format_table.attach (quality_view, 1, 2, 1, 2);
+ format_table.attach (format_view, 2, 3, 1, 2);
+ format_table.attach (sample_rate_view, 3, 4, 1, 2);
+
+ format_table.attach (src_quality_label, 0, 3, 2, 3);
+ format_table.attach (src_quality_combo, 3, 4, 2, 3);
+
+ compatibility_view.set_headers_visible (false);
+ quality_view.set_headers_visible (false);
+ format_view.set_headers_visible (false);
+ sample_rate_view.set_headers_visible (false);
+
+ /*** Table entries ***/
+
+ Gtk::TreeModel::iterator iter;
+ Gtk::TreeModel::Row row;
+
+ /* Compatibilities */
+
+ compatibility_list = Gtk::ListStore::create (compatibility_cols);
+ compatibility_view.set_model (compatibility_list);
+
+ ExportFormatManager::CompatList const & compat_list = manager.get_compatibilities();
+
+ for (ExportFormatManager::CompatList::const_iterator it = compat_list.begin(); it != compat_list.end(); ++it) {
+ iter = compatibility_list->append();
+ row = *iter;
+
+ row[compatibility_cols.ptr] = *it;
+ row[compatibility_cols.selected] = false;
+ row[compatibility_cols.label] = (*it)->name();
+
+ WeakCompatPtr ptr (*it);
+ (*it)->SelectChanged.connect (sigc::bind (sigc::mem_fun (*this, &ExportFormatDialog::change_compatibility_selection), ptr));
+ }
+
+ compatibility_view.append_column_editable ("", compatibility_cols.selected);
+
+ Gtk::CellRendererText* text_renderer = Gtk::manage (new Gtk::CellRendererText);
+ text_renderer->property_editable() = false;
+
+ Gtk::TreeView::Column* column = compatibility_view.get_column (0);
+ column->pack_start (*text_renderer);
+ column->add_attribute (text_renderer->property_text(), compatibility_cols.label);
+
+ /* Qualities */
+
+ quality_list = Gtk::ListStore::create (quality_cols);
+ quality_view.set_model (quality_list);
+
+ ExportFormatManager::QualityList const & qualities = manager.get_qualities ();
+
+ for (ExportFormatManager::QualityList::const_iterator it = qualities.begin(); it != qualities.end(); ++it) {
+ iter = quality_list->append();
+ row = *iter;
+
+ row[quality_cols.ptr] = *it;
+ row[quality_cols.color] = "white";
+ row[quality_cols.label] = (*it)->name();
+
+ WeakQualityPtr ptr (*it);
+ (*it)->SelectChanged.connect (sigc::bind (sigc::mem_fun (*this, &ExportFormatDialog::change_quality_selection), ptr));
+ (*it)->CompatibleChanged.connect (sigc::bind (sigc::mem_fun (*this, &ExportFormatDialog::change_quality_compatibility), ptr));
+ }
+
+ quality_view.append_column ("", quality_cols.label);
+
+ /* Formats */
+
+ format_list = Gtk::ListStore::create (format_cols);
+ format_view.set_model (format_list);
+
+ ExportFormatManager::FormatList const & formats = manager.get_formats ();
+
+ for (ExportFormatManager::FormatList::const_iterator it = formats.begin(); it != formats.end(); ++it) {
+ iter = format_list->append();
+ row = *iter;
+
+ row[format_cols.ptr] = *it;
+ row[format_cols.color] = "white";
+ row[format_cols.label] = (*it)->name();
+
+ WeakFormatPtr ptr (*it);
+ (*it)->SelectChanged.connect (sigc::bind (sigc::mem_fun (*this, &ExportFormatDialog::change_format_selection), ptr));
+ (*it)->CompatibleChanged.connect (sigc::bind (sigc::mem_fun (*this, &ExportFormatDialog::change_format_compatibility), ptr));
+
+ /* Encoding options */
+
+ boost::shared_ptr<HasSampleFormat> hsf;
+
+ if (hsf = boost::dynamic_pointer_cast<HasSampleFormat> (*it)) {
+ hsf->SampleFormatSelectChanged.connect (sigc::mem_fun (*this, &ExportFormatDialog::change_sample_format_selection));
+ hsf->SampleFormatCompatibleChanged.connect (sigc::mem_fun (*this, &ExportFormatDialog::change_sample_format_compatibility));
+
+ hsf->DitherTypeSelectChanged.connect (sigc::mem_fun (*this, &ExportFormatDialog::change_dither_type_selection));
+ hsf->DitherTypeCompatibleChanged.connect (sigc::mem_fun (*this, &ExportFormatDialog::change_dither_type_compatibility));
+ }
+ }
+
+ format_view.append_column ("", format_cols.label);
+
+ /* Sample Rates */
+
+ sample_rate_list = Gtk::ListStore::create (sample_rate_cols);
+ sample_rate_view.set_model (sample_rate_list);
+
+ ExportFormatManager::SampleRateList const & rates = manager.get_sample_rates ();
+
+ for (ExportFormatManager::SampleRateList::const_iterator it = rates.begin(); it != rates.end(); ++it) {
+ iter = sample_rate_list->append();
+ row = *iter;
+
+ row[sample_rate_cols.ptr] = *it;
+ row[sample_rate_cols.color] = "white";
+ row[sample_rate_cols.label] = (*it)->name();
+
+ WeakSampleRatePtr ptr (*it);
+ (*it)->SelectChanged.connect (sigc::bind (sigc::mem_fun (*this, &ExportFormatDialog::change_sample_rate_selection), ptr));
+ (*it)->CompatibleChanged.connect (sigc::bind (sigc::mem_fun (*this, &ExportFormatDialog::change_sample_rate_compatibility), ptr));
+ }
+
+ sample_rate_view.append_column ("", sample_rate_cols.label);
+
+ /* Color rendering */
+
+ Gtk::TreeViewColumn * label_col;
+ Gtk::CellRendererText * renderer;
+
+ label_col = quality_view.get_column(0);
+ renderer = dynamic_cast<Gtk::CellRendererText*> (quality_view.get_column_cell_renderer (0));
+ label_col->add_attribute(renderer->property_foreground(), quality_cols.color);
+
+ label_col = format_view.get_column(0);
+ renderer = dynamic_cast<Gtk::CellRendererText*> (format_view.get_column_cell_renderer (0));
+ label_col->add_attribute(renderer->property_foreground(), format_cols.color);
+
+ label_col = sample_rate_view.get_column(0);
+ renderer = dynamic_cast<Gtk::CellRendererText*> (sample_rate_view.get_column_cell_renderer (0));
+ label_col->add_attribute(renderer->property_foreground(), sample_rate_cols.color);
+
+ /* SRC Qualities */
+
+ src_quality_list = Gtk::ListStore::create (src_quality_cols);
+ src_quality_combo.set_model (src_quality_list);
+
+ iter = src_quality_list->append();
+ row = *iter;
+ row[src_quality_cols.id] = ExportFormatBase::SRC_SincBest;
+ row[src_quality_cols.label] = _("Best (sinc)");
+
+ iter = src_quality_list->append();
+ row = *iter;
+ row[src_quality_cols.id] = ExportFormatBase::SRC_SincMedium;
+ row[src_quality_cols.label] = _("Medium (sinc)");
+
+ iter = src_quality_list->append();
+ row = *iter;
+ row[src_quality_cols.id] = ExportFormatBase::SRC_SincFast;
+ row[src_quality_cols.label] = _("Fast (sinc)");
+
+ iter = src_quality_list->append();
+ row = *iter;
+ row[src_quality_cols.id] = ExportFormatBase::SRC_Linear;
+ row[src_quality_cols.label] = _("Linear");
+
+ iter = src_quality_list->append();
+ row = *iter;
+ row[src_quality_cols.id] = ExportFormatBase::SRC_ZeroOrderHold;
+ row[src_quality_cols.label] = _("Zero order hold");
+
+ src_quality_combo.pack_start (src_quality_cols.label);
+ src_quality_combo.set_active (0);
+}
+
+void
+ExportFormatDialog::init_encoding_option_widgets ()
+{
+ Gtk::TreeViewColumn * label_col;
+ Gtk::CellRendererText * renderer;
+
+ sample_format_list = Gtk::ListStore::create (sample_format_cols);
+ sample_format_view.set_model (sample_format_list);
+ sample_format_view.set_headers_visible (false);
+ sample_format_view.append_column ("", sample_format_cols.label);
+ label_col = sample_format_view.get_column(0);
+ renderer = dynamic_cast<Gtk::CellRendererText*> (sample_format_view.get_column_cell_renderer (0));
+ label_col->add_attribute(renderer->property_foreground(), sample_format_cols.color);
+
+ dither_type_list = Gtk::ListStore::create (dither_type_cols);
+ dither_type_view.set_model (dither_type_list);
+ dither_type_view.set_headers_visible (false);
+ dither_type_view.append_column ("", dither_type_cols.label);
+ label_col = dither_type_view.get_column(0);
+ renderer = dynamic_cast<Gtk::CellRendererText*> (dither_type_view.get_column_cell_renderer (0));
+ label_col->add_attribute(renderer->property_foreground(), dither_type_cols.color);
+
+}
+
+void
+ExportFormatDialog::update_compatibility_selection (Glib::ustring const & path)
+{
+
+ Gtk::TreeModel::iterator iter = compatibility_view.get_model ()->get_iter (path);
+ ExportFormatManager::CompatPtr ptr = iter->get_value (compatibility_cols.ptr);
+ bool state = iter->get_value (compatibility_cols.selected);
+
+ iter->set_value (compatibility_cols.selected, state);
+ ptr->set_selected (state);
+
+}
+
+void
+ExportFormatDialog::update_quality_selection ()
+{
+ update_selection<QualityCols> (quality_list, quality_view, quality_cols);
+}
+
+void
+ExportFormatDialog::update_format_selection ()
+{
+ update_selection<FormatCols> (format_list, format_view, format_cols);
+}
+
+void
+ExportFormatDialog::update_sample_rate_selection ()
+{
+ update_selection<SampleRateCols> (sample_rate_list, sample_rate_view, sample_rate_cols);
+}
+
+void
+ExportFormatDialog::update_sample_format_selection ()
+{
+ update_selection<SampleFormatCols> (sample_format_list, sample_format_view, sample_format_cols);
+}
+
+void
+ExportFormatDialog::update_dither_type_selection ()
+{
+ update_selection<DitherTypeCols> (dither_type_list, dither_type_view, dither_type_cols);
+}
+
+template<typename ColsT>
+void
+ExportFormatDialog::update_selection (Glib::RefPtr<Gtk::ListStore> & list, Gtk::TreeView & view, ColsT & cols)
+{
+ if (applying_changes_from_engine) {
+ return;
+ }
+
+ Gtk::ListStore::Children::iterator it;
+ Glib::RefPtr<Gtk::TreeSelection> selection = view.get_selection();
+
+ for (it = list->children().begin(); it != list->children().end(); ++it) {
+ bool selected = selection->is_selected (it);
+ it->get_value (cols.ptr)->set_selected (selected);
+ }
+}
+
+void
+ExportFormatDialog::change_compatibility_selection (bool select, WeakCompatPtr compat)
+{
+ ++applying_changes_from_engine;
+
+ ExportFormatManager::CompatPtr ptr = compat.lock();
+
+ for (Gtk::ListStore::Children::iterator it = compatibility_list->children().begin(); it != compatibility_list->children().end(); ++it) {
+ if (it->get_value (compatibility_cols.ptr) == ptr) {
+ it->set_value (compatibility_cols.selected, select);
+ break;
+ }
+ }
+
+ --applying_changes_from_engine;
+}
+
+void
+ExportFormatDialog::change_quality_selection (bool select, WeakQualityPtr quality)
+{
+ change_selection<ExportFormatManager::QualityState, QualityCols> (select, quality, quality_list, quality_view, quality_cols);
+}
+
+void
+ExportFormatDialog::change_format_selection (bool select, WeakFormatPtr format)
+{
+ change_selection<ExportFormat, FormatCols> (select, format, format_list, format_view, format_cols);
+
+ ExportFormatManager::FormatPtr ptr = format.lock();
+
+ if (select && ptr) {
+ change_encoding_options (ptr);
+ }
+}
+
+void
+ExportFormatDialog::change_sample_rate_selection (bool select, WeakSampleRatePtr rate)
+{
+ change_selection<ExportFormatManager::SampleRateState, SampleRateCols> (select, rate, sample_rate_list, sample_rate_view, sample_rate_cols);
+
+ if (select) {
+ ExportFormatManager::SampleRatePtr ptr = rate.lock();
+ if (ptr && session) {
+ src_quality_combo.set_sensitive ((uint32_t) ptr->rate != session->frame_rate());
+ }
+ }
+}
+
+void
+ExportFormatDialog::change_sample_format_selection (bool select, WeakSampleFormatPtr format)
+{
+ change_selection<HasSampleFormat::SampleFormatState, SampleFormatCols> (select, format, sample_format_list, sample_format_view, sample_format_cols);
+}
+
+void
+ExportFormatDialog::change_dither_type_selection (bool select, WeakDitherTypePtr type)
+{
+ change_selection<HasSampleFormat::DitherTypeState, DitherTypeCols> (select, type, dither_type_list, dither_type_view, dither_type_cols);
+}
+
+template<typename T, typename ColsT>
+void
+ExportFormatDialog::change_selection (bool select, boost::weak_ptr<T> w_ptr, Glib::RefPtr<Gtk::ListStore> & list, Gtk::TreeView & view, ColsT & cols)
+{
+ ++applying_changes_from_engine;
+
+ boost::shared_ptr<T> ptr = w_ptr.lock();
+
+ Gtk::ListStore::Children::iterator it;
+ Glib::RefPtr<Gtk::TreeSelection> selection;
+
+ selection = view.get_selection();
+
+ if (!ptr) {
+ selection->unselect_all();
+ } else {
+ for (it = list->children().begin(); it != list->children().end(); ++it) {
+ if (it->get_value (cols.ptr) == ptr) {
+ if (select) {
+ selection->select (it);
+ } else {
+ selection->unselect (it);
+ }
+ break;
+ }
+ }
+ }
+
+ --applying_changes_from_engine;
+}
+
+void
+ExportFormatDialog::change_quality_compatibility (bool compatibility, WeakQualityPtr quality)
+{
+ change_compatibility<ExportFormatManager::QualityState, QualityCols> (compatibility, quality, quality_list, quality_cols);
+}
+
+void
+ExportFormatDialog::change_format_compatibility (bool compatibility, WeakFormatPtr format)
+{
+ change_compatibility<ExportFormat, FormatCols> (compatibility, format, format_list, format_cols);
+}
+
+void
+ExportFormatDialog::change_sample_rate_compatibility (bool compatibility, WeakSampleRatePtr rate)
+{
+ change_compatibility<ExportFormatManager::SampleRateState, SampleRateCols> (compatibility, rate, sample_rate_list, sample_rate_cols);
+}
+
+void
+ExportFormatDialog::change_sample_format_compatibility (bool compatibility, WeakSampleFormatPtr format)
+{
+ change_compatibility<HasSampleFormat::SampleFormatState, SampleFormatCols> (compatibility, format, sample_format_list, sample_format_cols);
+}
+
+void
+ExportFormatDialog::change_dither_type_compatibility (bool compatibility, WeakDitherTypePtr type)
+{
+ change_compatibility<HasSampleFormat::DitherTypeState, DitherTypeCols> (compatibility, type, dither_type_list, dither_type_cols, "red");
+}
+
+template<typename T, typename ColsT>
+void
+ExportFormatDialog::change_compatibility (bool compatibility, boost::weak_ptr<T> w_ptr, Glib::RefPtr<Gtk::ListStore> & list, ColsT & cols,
+ Glib::ustring const & c_incompatible, Glib::ustring const & c_compatible)
+{
+ boost::shared_ptr<T> ptr = w_ptr.lock();
+
+ Gtk::ListStore::Children::iterator it;
+ for (it = list->children().begin(); it != list->children().end(); ++it) {
+ if (it->get_value (cols.ptr) == ptr) {
+ it->set_value (cols.color, compatibility ? c_compatible : c_incompatible);
+ break;
+ }
+ }
+}
+
+void
+ExportFormatDialog::update_name ()
+{
+ manager.set_name (name_entry.get_text());
+}
+
+void
+ExportFormatDialog::update_trim_start_selection ()
+{
+ manager.select_trim_beginning (trim_start_checkbox.get_active());
+}
+
+void
+ExportFormatDialog::update_trim_end_selection ()
+{
+ manager.select_trim_end (trim_end_checkbox.get_active());
+}
+
+void
+ExportFormatDialog::update_normalize_selection ()
+{
+ manager.select_normalize (normalize_checkbox.get_active());
+ manager.select_normalize_target (normalize_spinbutton.get_value ());
+}
+
+void
+ExportFormatDialog::update_silence_start_selection ()
+{
+ update_time (silence_start, silence_start_clock);
+ AnyTime zero;
+ zero.type = AnyTime::SMPTE;
+ manager.select_silence_beginning (silence_start_checkbox.get_active() ? silence_start : zero);
+}
+
+void
+ExportFormatDialog::update_silence_end_selection ()
+{
+ update_time (silence_end, silence_end_clock);
+ AnyTime zero;
+ zero.type = AnyTime::SMPTE;
+ manager.select_silence_end (silence_end_checkbox.get_active() ? silence_end : zero);
+}
+
+void
+ExportFormatDialog::update_clock (AudioClock & clock, ARDOUR::AnyTime const & time)
+{
+ // TODO position
+ clock.set (session->convert_to_frames_at (0, time), true);
+
+ AudioClock::Mode mode;
+
+ switch (time.type) {
+ case AnyTime::SMPTE:
+ mode = AudioClock::SMPTE;
+ break;
+ case AnyTime::BBT:
+ mode = AudioClock::BBT;
+ break;
+ case AnyTime::Frames:
+ mode = AudioClock::Frames;
+ break;
+ case AnyTime::Seconds:
+ mode = AudioClock::MinSec;
+ break;
+ }
+
+ clock.set_mode (mode);
+}
+
+void
+ExportFormatDialog::update_time (AnyTime & time, AudioClock const & clock)
+{
+ if (!session) {
+ return;
+ }
+
+ nframes_t frames = clock.current_duration();
+
+ switch (clock.mode()) {
+ case AudioClock::SMPTE:
+ time.type = AnyTime::SMPTE;
+ session->smpte_time (frames, time.smpte);
+ break;
+ case AudioClock::BBT:
+ time.type = AnyTime::BBT;
+ session->bbt_time (frames, time.bbt);
+ break;
+ case AudioClock::MinSec:
+ time.type = AnyTime::Seconds;
+ time.seconds = (double) frames / session->frame_rate();
+ break;
+ case AudioClock::Frames:
+ time.type = AnyTime::Frames;
+ time.frames = frames;
+ break;
+ case AudioClock::Off:
+ silence_end_checkbox.set_active (false);
+ return;
+ }
+}
+
+void
+ExportFormatDialog::update_src_quality_selection ()
+{
+ Gtk::TreeModel::const_iterator iter = src_quality_combo.get_active();
+ ExportFormatBase::SRCQuality quality = iter->get_value (src_quality_cols.id);
+ manager.select_src_quality (quality);
+}
+
+void
+ExportFormatDialog::update_tagging_selection ()
+{
+ manager.select_tagging (tag_checkbox.get_active());
+}
+
+void
+ExportFormatDialog::change_encoding_options (ExportFormatManager::FormatPtr ptr)
+{
+ empty_encoding_option_table ();
+
+ boost::shared_ptr<ARDOUR::ExportFormatLinear> linear_ptr;
+ boost::shared_ptr<ARDOUR::ExportFormatOggVorbis> ogg_ptr;
+ boost::shared_ptr<ARDOUR::ExportFormatFLAC> flac_ptr;
+ boost::shared_ptr<ARDOUR::ExportFormatBWF> bwf_ptr;
+
+ if (linear_ptr = boost::dynamic_pointer_cast<ExportFormatLinear> (ptr)) {
+ show_linear_enconding_options (linear_ptr);
+ } else if (ogg_ptr = boost::dynamic_pointer_cast<ExportFormatOggVorbis> (ptr)) {
+ show_ogg_enconding_options (ogg_ptr);
+ } else if (flac_ptr = boost::dynamic_pointer_cast<ExportFormatFLAC> (ptr)) {
+ show_flac_enconding_options (flac_ptr);
+ } else if (bwf_ptr = boost::dynamic_pointer_cast<ExportFormatBWF> (ptr)) {
+ show_bwf_enconding_options (bwf_ptr);
+ } else {
+ std::cout << "Unrecognized format!" << std::endl;
+ }
+}
+
+void
+ExportFormatDialog::empty_encoding_option_table ()
+{
+ encoding_options_table.foreach (sigc::bind (sigc::mem_fun (*this, &ExportFormatDialog::remove_widget), &encoding_options_table));
+}
+
+void
+ExportFormatDialog::remove_widget (Gtk::Widget & to_remove, Gtk::Container * remove_from)
+{
+ remove_from->remove (to_remove);
+}
+
+void
+ExportFormatDialog::show_linear_enconding_options (boost::shared_ptr<ARDOUR::ExportFormatLinear> ptr)
+{
+ /* Set label and pack table */
+
+ encoding_options_label.set_label (_("Linear encoding options"));
+
+ encoding_options_table.resize (2, 2);
+ encoding_options_table.attach (sample_format_label, 0, 1, 0, 1);
+ encoding_options_table.attach (dither_label, 1, 2, 0, 1);
+ encoding_options_table.attach (sample_format_view, 0, 1, 1, 2);
+ encoding_options_table.attach (dither_type_view, 1, 2, 1, 2);
+
+ fill_sample_format_lists (boost::dynamic_pointer_cast<HasSampleFormat> (ptr));
+
+ show_all_children ();
+}
+
+void
+ExportFormatDialog::show_ogg_enconding_options (boost::shared_ptr<ARDOUR::ExportFormatOggVorbis> ptr)
+{
+ encoding_options_label.set_label (_("Ogg Vorbis options"));
+
+ encoding_options_table.resize (1, 1);
+ encoding_options_table.attach (tag_checkbox, 0, 1, 0, 1);
+
+ update_tagging_selection ();
+
+ show_all_children ();
+}
+
+void
+ExportFormatDialog::show_flac_enconding_options (boost::shared_ptr<ARDOUR::ExportFormatFLAC> ptr)
+{
+ encoding_options_label.set_label (_("FLAC options"));
+
+ encoding_options_table.resize (3, 2);
+ encoding_options_table.attach (sample_format_label, 0, 1, 0, 1);
+ encoding_options_table.attach (dither_label, 1, 2, 0, 1);
+ encoding_options_table.attach (sample_format_view, 0, 1, 1, 2);
+ encoding_options_table.attach (dither_type_view, 1, 2, 1, 2);
+ encoding_options_table.attach (tag_checkbox, 0, 2, 2, 3);
+
+ fill_sample_format_lists (boost::dynamic_pointer_cast<HasSampleFormat> (ptr));
+
+ show_all_children ();
+}
+
+void
+ExportFormatDialog::show_bwf_enconding_options (boost::shared_ptr<ARDOUR::ExportFormatBWF> ptr)
+{
+ encoding_options_label.set_label (_("Broadcast Wave options"));
+
+ encoding_options_table.resize (2, 2);
+ encoding_options_table.attach (sample_format_label, 0, 1, 0, 1);
+ encoding_options_table.attach (dither_label, 1, 2, 0, 1);
+ encoding_options_table.attach (sample_format_view, 0, 1, 1, 2);
+ encoding_options_table.attach (dither_type_view, 1, 2, 1, 2);
+
+ fill_sample_format_lists (boost::dynamic_pointer_cast<HasSampleFormat> (ptr));
+
+ show_all_children ();
+}
+
+void
+ExportFormatDialog::fill_sample_format_lists (boost::shared_ptr<ARDOUR::HasSampleFormat> ptr)
+{
+ /* Fill lists */
+
+ Gtk::TreeModel::iterator iter;
+ Gtk::TreeModel::Row row;
+
+ sample_format_list->clear ();
+
+ HasSampleFormat::SampleFormatList const & formats = ptr->get_sample_formats ();
+
+ for (HasSampleFormat::SampleFormatList::const_iterator it = formats.begin(); it != formats.end(); ++it) {
+ iter = sample_format_list->append();
+ row = *iter;
+
+ row[sample_format_cols.ptr] = *it;
+ row[sample_format_cols.color] = (*it)->compatible() ? "white" : "red";
+ row[sample_format_cols.label] = (*it)->name();
+
+ if ((*it)->selected()) {
+ sample_format_view.get_selection()->select (iter);
+ }
+ }
+
+ dither_type_list->clear ();
+
+ HasSampleFormat::DitherTypeList const & types = ptr->get_dither_types ();
+
+ for (HasSampleFormat::DitherTypeList::const_iterator it = types.begin(); it != types.end(); ++it) {
+ iter = dither_type_list->append();
+ row = *iter;
+
+ row[dither_type_cols.ptr] = *it;
+ row[dither_type_cols.color] = "white";
+ row[dither_type_cols.label] = (*it)->name();
+
+ if ((*it)->selected()) {
+ dither_type_view.get_selection()->select (iter);
+ }
+ }
+}
+
+void
+ExportFormatDialog::end_dialog ()
+{
+ hide_all ();
+}
+
+void
+ExportFormatDialog::prohibit_compatibility_selection ()
+{
+ compatibility_select_connection.block (true);
+ compatibility_view.get_selection()->unselect_all ();
+ compatibility_select_connection.block (false);
+}
diff --git a/gtk2_ardour/export_format_dialog.h b/gtk2_ardour/export_format_dialog.h
new file mode 100644
index 0000000000..fed081f9f0
--- /dev/null
+++ b/gtk2_ardour/export_format_dialog.h
@@ -0,0 +1,308 @@
+/*
+ Copyright (C) 2008 Paul Davis
+ Author: Sakari Bergen
+
+ 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.
+
+*/
+
+#ifndef __export_format_dialog_h__
+#define __export_format_dialog_h__
+
+#include <ardour/types.h>
+#include <ardour/export_format_manager.h>
+#include <ardour/export_format_compatibility.h>
+#include <ardour/export_formats.h>
+
+#include <pbd/xml++.h>
+
+#include "ardour_dialog.h"
+#include "audio_clock.h"
+
+#include <gtkmm.h>
+
+class ExportFormatDialog : public ArdourDialog {
+ private:
+
+ typedef ARDOUR::ExportFormatManager::WeakCompatPtr WeakCompatPtr;
+ typedef ARDOUR::ExportFormatManager::WeakQualityPtr WeakQualityPtr;
+ typedef ARDOUR::ExportFormatManager::WeakFormatPtr WeakFormatPtr;
+ typedef ARDOUR::ExportFormatManager::WeakSampleRatePtr WeakSampleRatePtr;
+ typedef ARDOUR::ExportFormatManager::WeakSampleFormatPtr WeakSampleFormatPtr;
+ typedef ARDOUR::ExportFormatManager::WeakDitherTypePtr WeakDitherTypePtr;
+
+ typedef boost::shared_ptr<ARDOUR::ExportFormatSpecification> FormatPtr;
+
+
+ public:
+
+ explicit ExportFormatDialog (FormatPtr format, bool new_dialog = false);
+ ~ExportFormatDialog ();
+
+ void set_session (ARDOUR::Session* s);
+
+ private:
+
+ FormatPtr format;
+ ARDOUR::ExportFormatManager manager;
+
+ XMLNode & original_state;
+
+ ARDOUR::AnyTime silence_start;
+ ARDOUR::AnyTime silence_end;
+
+ void end_dialog ();
+ void revert ();
+
+ /*** Init functions ***/
+
+ void load_state (FormatPtr spec);
+ void init_format_table ();
+ void init_encoding_option_widgets ();
+
+ /*** Interactive selections ***/
+
+ /* These are connected to signals from GUI components, and should change element states */
+
+ void update_compatibility_selection (Glib::ustring const & path);
+ void update_quality_selection ();
+ void update_format_selection ();
+ void update_sample_rate_selection ();
+ void update_sample_format_selection ();
+ void update_dither_type_selection ();
+
+ template<typename ColsT>
+ void update_selection (Glib::RefPtr<Gtk::ListStore> & list, Gtk::TreeView & view, ColsT & cols);
+
+ /* These are connected to signals from elements, and should only update the gui */
+
+ void change_compatibility_selection (bool select, WeakCompatPtr compat);
+
+ void change_quality_selection (bool select, WeakQualityPtr quality);
+ void change_format_selection (bool select, WeakFormatPtr format);
+ void change_sample_rate_selection (bool select, WeakSampleRatePtr rate);
+ void change_sample_format_selection (bool select, WeakSampleFormatPtr format);
+ void change_dither_type_selection (bool select, WeakDitherTypePtr type);
+
+ template<typename T, typename ColsT>
+ void change_selection (bool select, boost::weak_ptr<T> w_ptr, Glib::RefPtr<Gtk::ListStore> & list, Gtk::TreeView & view, ColsT & cols);
+
+ void change_quality_compatibility (bool compatibility, WeakQualityPtr quality);
+ void change_format_compatibility (bool compatibility, WeakFormatPtr format);
+ void change_sample_rate_compatibility (bool compatibility, WeakSampleRatePtr rate);
+ void change_sample_format_compatibility (bool compatibility, WeakSampleFormatPtr format);
+ void change_dither_type_compatibility (bool compatibility, WeakDitherTypePtr type);
+
+ template<typename T, typename ColsT>
+ void change_compatibility (bool compatibility, boost::weak_ptr<T> w_ptr, Glib::RefPtr<Gtk::ListStore> & list, ColsT & cols,
+ Glib::ustring const & c_incompatible = "red", Glib::ustring const & c_compatible = "white");
+
+ uint32_t applying_changes_from_engine;
+
+ /*** Non-interactive selections ***/
+
+ void update_name ();
+
+ void update_trim_start_selection ();
+ void update_trim_end_selection ();
+
+ void update_normalize_selection ();
+ void update_silence_start_selection ();
+ void update_silence_end_selection ();
+
+ void update_clock (AudioClock & clock, ARDOUR::AnyTime const & time);
+ void update_time (ARDOUR::AnyTime & time, AudioClock const & clock);
+
+ void update_src_quality_selection ();
+ void update_tagging_selection ();
+
+ /*** Encoding options */
+
+ void change_encoding_options (ARDOUR::ExportFormatManager::FormatPtr ptr);
+
+ void empty_encoding_option_table ();
+ void remove_widget (Gtk::Widget & to_remove, Gtk::Container * remove_from);
+
+ void show_linear_enconding_options (boost::shared_ptr<ARDOUR::ExportFormatLinear> ptr);
+ void show_ogg_enconding_options (boost::shared_ptr<ARDOUR::ExportFormatOggVorbis> ptr);
+ void show_flac_enconding_options (boost::shared_ptr<ARDOUR::ExportFormatFLAC> ptr);
+ void show_bwf_enconding_options (boost::shared_ptr<ARDOUR::ExportFormatBWF> ptr);
+
+ void fill_sample_format_lists (boost::shared_ptr<ARDOUR::HasSampleFormat> ptr);
+
+ /*** GUI components ***/
+
+ /* Name, new and remove */
+
+ Gtk::HBox name_hbox;
+
+ Gtk::Label name_label;
+ Gtk::Entry name_entry;
+
+ /* Normalize */
+
+ Gtk::HBox normalize_hbox;
+ Gtk::CheckButton normalize_checkbox;
+ Gtk::SpinButton normalize_spinbutton;
+ Gtk::Adjustment normalize_adjustment;
+ Gtk::Label normalize_db_label;
+
+ /* Silence */
+
+ Gtk::Table silence_table;
+
+ Gtk::CheckButton trim_start_checkbox;
+ Gtk::CheckButton silence_start_checkbox;
+ AudioClock silence_start_clock;
+
+ Gtk::CheckButton trim_end_checkbox;
+ Gtk::CheckButton silence_end_checkbox;
+ AudioClock silence_end_clock;
+
+ /* Format table */
+
+ struct CompatibilityCols : public Gtk::TreeModelColumnRecord
+ {
+ public:
+ Gtk::TreeModelColumn<ARDOUR::ExportFormatManager::CompatPtr> ptr;
+ Gtk::TreeModelColumn<bool> selected;
+ Gtk::TreeModelColumn<Glib::ustring> label;
+
+ CompatibilityCols () { add(ptr); add(selected); add(label); }
+ };
+ CompatibilityCols compatibility_cols;
+ Glib::RefPtr<Gtk::ListStore> compatibility_list;
+
+ /* Hack to disallow row selection in compatibilities */
+ void prohibit_compatibility_selection ();
+ sigc::connection compatibility_select_connection;
+
+ struct QualityCols : public Gtk::TreeModelColumnRecord
+ {
+ public:
+ Gtk::TreeModelColumn<ARDOUR::ExportFormatManager::QualityPtr> ptr;
+ Gtk::TreeModelColumn<Glib::ustring> color;
+ Gtk::TreeModelColumn<Glib::ustring> label;
+
+ QualityCols () { add(ptr); add(color); add(label); }
+ };
+ QualityCols quality_cols;
+ Glib::RefPtr<Gtk::ListStore> quality_list;
+
+ struct FormatCols : public Gtk::TreeModelColumnRecord
+ {
+ public:
+ Gtk::TreeModelColumn<ARDOUR::ExportFormatManager::FormatPtr> ptr;
+ Gtk::TreeModelColumn<Glib::ustring> color;
+ Gtk::TreeModelColumn<Glib::ustring> label;
+
+ FormatCols () { add(ptr); add(color); add(label); }
+ };
+ FormatCols format_cols;
+ Glib::RefPtr<Gtk::ListStore> format_list;
+
+ struct SampleRateCols : public Gtk::TreeModelColumnRecord
+ {
+ public:
+ Gtk::TreeModelColumn<ARDOUR::ExportFormatManager::SampleRatePtr> ptr;
+ Gtk::TreeModelColumn<Glib::ustring> color;
+ Gtk::TreeModelColumn<Glib::ustring> label;
+
+ SampleRateCols () { add(ptr); add(color); add(label); }
+ };
+ SampleRateCols sample_rate_cols;
+ Glib::RefPtr<Gtk::ListStore> sample_rate_list;
+
+ Gtk::Table format_table;
+
+ Gtk::Label compatibility_label;
+ Gtk::Label quality_label;
+ Gtk::Label format_label;
+ Gtk::Label sample_rate_label;
+
+ Gtk::TreeView compatibility_view;
+ Gtk::TreeView quality_view;
+ Gtk::TreeView format_view;
+ Gtk::TreeView sample_rate_view;
+
+ /* SRC quality combo */
+
+ struct SRCQualityCols : public Gtk::TreeModelColumnRecord
+ {
+ public:
+ Gtk::TreeModelColumn<ARDOUR::ExportFormatBase::SRCQuality> id;
+ Gtk::TreeModelColumn<Glib::ustring> label;
+
+ SRCQualityCols () { add(id); add(label); }
+ };
+ SRCQualityCols src_quality_cols;
+ Glib::RefPtr<Gtk::ListStore> src_quality_list;
+
+ Gtk::Label src_quality_label;
+ Gtk::ComboBox src_quality_combo;
+
+ /* Common encoding option components */
+
+ Gtk::VBox encoding_options_vbox;
+ Gtk::Label encoding_options_label;
+
+ Gtk::Table encoding_options_table;
+
+ /* Other common components */
+
+ Gtk::Button * revert_button;
+ Gtk::Button * close_button;
+
+ /*** Changing encoding option stuff ***/
+
+ /* Linear */
+
+ struct SampleFormatCols : public Gtk::TreeModelColumnRecord
+ {
+ public:
+ Gtk::TreeModelColumn<ARDOUR::HasSampleFormat::SampleFormatPtr> ptr;
+ Gtk::TreeModelColumn<Glib::ustring> color;
+ Gtk::TreeModelColumn<Glib::ustring> label;
+
+ SampleFormatCols () { add(ptr); add(color); add(label); }
+ };
+ SampleFormatCols sample_format_cols;
+ Glib::RefPtr<Gtk::ListStore> sample_format_list;
+
+ struct DitherTypeCols : public Gtk::TreeModelColumnRecord
+ {
+ public:
+ Gtk::TreeModelColumn<ARDOUR::HasSampleFormat::DitherTypePtr> ptr;
+ Gtk::TreeModelColumn<Glib::ustring> color;
+ Gtk::TreeModelColumn<Glib::ustring> label;
+
+ DitherTypeCols () { add(ptr); add (color); add(label); }
+ };
+ DitherTypeCols dither_type_cols;
+ Glib::RefPtr<Gtk::ListStore> dither_type_list;
+
+ Gtk::Label sample_format_label;
+ Gtk::Label dither_label;
+
+ Gtk::TreeView sample_format_view;
+ Gtk::TreeView dither_type_view;
+
+ /* Tagging */
+
+ Gtk::CheckButton tag_checkbox;
+
+};
+
+#endif /* __export_format_dialog_h__ */
diff --git a/gtk2_ardour/export_format_selector.cc b/gtk2_ardour/export_format_selector.cc
new file mode 100644
index 0000000000..1f1158a21f
--- /dev/null
+++ b/gtk2_ardour/export_format_selector.cc
@@ -0,0 +1,169 @@
+/*
+ Copyright (C) 2008 Paul Davis
+ Author: Sakari Bergen
+
+ 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 "export_format_selector.h"
+
+#include "export_format_dialog.h"
+
+#include <ardour/export_format_specification.h>
+#include <ardour/export_profile_manager.h>
+#include <ardour/session.h>
+
+#include "i18n.h"
+
+ExportFormatSelector::ExportFormatSelector () :
+ edit_button (Gtk::Stock::EDIT),
+ remove_button (Gtk::Stock::REMOVE),
+ new_button (Gtk::Stock::NEW)
+{
+ pack_start (format_combo, true, true, 0);
+ pack_start (edit_button, false, false, 3);
+ pack_start (remove_button, false, false, 3);
+ pack_start (new_button, false, false, 3);
+
+ edit_button.signal_clicked().connect (sigc::hide_return (sigc::bind (sigc::mem_fun (*this, &ExportFormatSelector::open_edit_dialog), false)));
+ remove_button.signal_clicked().connect (sigc::mem_fun (*this, &ExportFormatSelector::remove_format));
+ new_button.signal_clicked().connect (sigc::mem_fun (*this, &ExportFormatSelector::add_new_format));
+
+ /* Format combo */
+
+ format_list = Gtk::ListStore::create (format_cols);
+ format_combo.set_model (format_list);
+ format_combo.pack_start (format_cols.label);
+ format_combo.set_active (0);
+
+ format_combo.signal_changed().connect (sigc::mem_fun (*this, &ExportFormatSelector::update_format_combo));
+}
+
+ExportFormatSelector::~ExportFormatSelector ()
+{
+
+}
+
+void
+ExportFormatSelector::set_state (ARDOUR::ExportProfileManager::FormatStatePtr const state_, ARDOUR::Session * session_)
+{
+ session = session_;
+ state = state_;
+
+ update_format_list ();
+}
+
+void
+ExportFormatSelector::update_format_list ()
+{
+ FormatPtr format_to_select = state->format;
+ format_list->clear();
+
+ if (state->list->empty()) {
+ edit_button.set_sensitive (false);
+ remove_button.set_sensitive (false);
+ return;
+ } else {
+ edit_button.set_sensitive (true);
+ remove_button.set_sensitive (true);
+ }
+
+ Gtk::ListStore::iterator tree_it;
+
+ for (FormatList::const_iterator it = state->list->begin(); it != state->list->end(); ++it) {
+ tree_it = format_list->append();
+ tree_it->set_value (format_cols.format, *it);
+ tree_it->set_value (format_cols.label, (*it)->description());
+ }
+
+ if (format_combo.get_active_row_number() == -1) {
+ format_combo.set_active (0);
+ }
+
+ select_format (format_to_select);
+}
+
+void
+ExportFormatSelector::select_format (FormatPtr f)
+{
+ Gtk::TreeModel::Children::iterator it;
+ for (it = format_list->children().begin(); it != format_list->children().end(); ++it) {
+ if (it->get_value (format_cols.format) == f) {
+ format_combo.set_active (it);
+ break;
+ }
+ }
+
+ CriticalSelectionChanged();
+}
+
+void
+ExportFormatSelector::add_new_format ()
+{
+ FormatPtr new_format = state->format = NewFormat (state->format);
+
+ if (open_edit_dialog (true) != Gtk::RESPONSE_APPLY) {
+ remove_format();
+ if (state->list->empty()) {
+ state->format.reset ();
+ }
+ }
+}
+
+void
+ExportFormatSelector::remove_format ()
+{
+ FormatPtr remove;
+ Gtk::TreeModel::iterator it = format_combo.get_active();
+ remove = it->get_value (format_cols.format);
+ FormatRemoved (remove);
+}
+
+int
+ExportFormatSelector::open_edit_dialog (bool new_dialog)
+{
+ ExportFormatDialog dialog (state->format, new_dialog);
+ dialog.set_session (session);
+ Gtk::ResponseType response = (Gtk::ResponseType) dialog.run();
+ if (response == Gtk::RESPONSE_APPLY) {
+ update_format_description ();
+ FormatEdited (state->format);
+ CriticalSelectionChanged();
+ }
+ return response;
+}
+
+void
+ExportFormatSelector::update_format_combo ()
+{
+ Gtk::TreeModel::iterator it = format_combo.get_active();
+ if (format_list->iter_is_valid (it)) {
+ state->format = it->get_value(format_cols.format);
+ } else if (!format_list->children().empty()) {
+ format_combo.set_active (0);
+ } else {
+ edit_button.set_sensitive (false);
+ remove_button.set_sensitive (false);
+ }
+
+ CriticalSelectionChanged();
+}
+
+void
+ExportFormatSelector::update_format_description ()
+{
+ format_combo.get_active()->set_value(format_cols.label, state->format->description());
+}
diff --git a/gtk2_ardour/export_format_selector.h b/gtk2_ardour/export_format_selector.h
new file mode 100644
index 0000000000..d4e4ae0110
--- /dev/null
+++ b/gtk2_ardour/export_format_selector.h
@@ -0,0 +1,91 @@
+/*
+ Copyright (C) 2008 Paul Davis
+ Author: Sakari Bergen
+
+ 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.
+
+*/
+
+#ifndef __export_format_selector_h__
+#define __export_format_selector_h__
+
+#include <ardour/export_profile_manager.h>
+
+#include <gtkmm.h>
+#include <sigc++/signal.h>
+#include <boost/shared_ptr.hpp>
+
+namespace ARDOUR {
+ class Session;
+ class ExportFormatSpecification;
+ class ExportProfileManager;
+}
+
+///
+class ExportFormatSelector : public Gtk::HBox {
+
+ private:
+
+ typedef boost::shared_ptr<ARDOUR::ExportFormatSpecification> FormatPtr;
+ typedef std::list<FormatPtr> FormatList;
+
+ public:
+
+ ExportFormatSelector ();
+ ~ExportFormatSelector ();
+
+ void set_state (ARDOUR::ExportProfileManager::FormatStatePtr state_, ARDOUR::Session * session_);
+ void update_format_list ();
+
+ sigc::signal<void, FormatPtr> FormatEdited;
+ sigc::signal<void, FormatPtr> FormatRemoved;
+ sigc::signal<FormatPtr, FormatPtr> NewFormat;
+
+ /* Compatibility with other elements */
+
+ sigc::signal<void> CriticalSelectionChanged;
+
+ private:
+
+ void select_format (FormatPtr f);
+ void add_new_format ();
+ void remove_format ();
+ int open_edit_dialog (bool new_dialog = false);
+ void update_format_combo ();
+ void update_format_description ();
+
+ ARDOUR::ExportProfileManager::FormatStatePtr state;
+ ARDOUR::Session * session;
+
+ /*** GUI componenets ***/
+
+ struct FormatCols : public Gtk::TreeModelColumnRecord
+ {
+ public:
+ Gtk::TreeModelColumn<FormatPtr> format;
+ Gtk::TreeModelColumn<Glib::ustring> label;
+
+ FormatCols () { add (format); add (label); }
+ };
+ FormatCols format_cols;
+ Glib::RefPtr<Gtk::ListStore> format_list;
+ Gtk::ComboBox format_combo;
+
+ Gtk::Button edit_button;
+ Gtk::Button remove_button;
+ Gtk::Button new_button;
+};
+
+#endif /* __export_format_selector_h__ */
diff --git a/gtk2_ardour/export_main_dialog.cc b/gtk2_ardour/export_main_dialog.cc
new file mode 100644
index 0000000000..7a0dd8186f
--- /dev/null
+++ b/gtk2_ardour/export_main_dialog.cc
@@ -0,0 +1,640 @@
+/*
+ Copyright (C) 2008 Paul Davis
+ Author: Sakari Bergen
+
+ 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 "export_main_dialog.h"
+
+#include <sigc++/signal.h>
+
+#include <pbd/filesystem.h>
+
+#include "utils.h"
+
+#include <ardour/export_handler.h>
+#include <ardour/export_filename.h>
+#include <ardour/export_format_specification.h>
+#include <ardour/export_channel_configuration.h>
+
+#include "i18n.h"
+
+using namespace ARDOUR;
+using namespace PBD;
+
+ExportMainDialog::ExportMainDialog (PublicEditor & editor) :
+ ArdourDialog (_("Export")),
+ editor (editor),
+
+ preset_label (_("Preset:"), Gtk::ALIGN_LEFT),
+ preset_save_button (Gtk::Stock::SAVE),
+ preset_remove_button (Gtk::Stock::REMOVE),
+ preset_new_button (Gtk::Stock::NEW),
+
+ page_counter (1),
+
+ warn_label ("", Gtk::ALIGN_LEFT),
+ list_files_label (_("<span color=\"#ffa755\">Some already existing files will be overwritten.</span>"), Gtk::ALIGN_RIGHT),
+ list_files_button (_("List files")),
+
+ timespan_label (_("Time Span"), Gtk::ALIGN_LEFT),
+
+ channels_label (_("Channels"), Gtk::ALIGN_LEFT)
+{
+ /* Main packing */
+
+ get_vbox()->pack_start (preset_align, false, false, 0);
+ get_vbox()->pack_start (timespan_label, false, false, 0);
+ get_vbox()->pack_start (timespan_align, false, false, 0);
+ get_vbox()->pack_start (channels_label, false, false, 0);
+ get_vbox()->pack_start (channels_align, false, false, 0);
+ get_vbox()->pack_start (file_notebook, false, false, 0);
+ get_vbox()->pack_start (warn_container, true, true, 0);
+ get_vbox()->pack_start (progress_container, true, true, 0);
+
+ timespan_align.add (timespan_selector);
+ timespan_align.set_padding (0, 12, 18, 0);
+
+ channels_align.add (channel_selector);
+ channels_align.set_padding (0, 12, 18, 0);
+
+ /* Preset manipulation */
+
+ preset_list = Gtk::ListStore::create (preset_cols);
+ preset_entry.set_model (preset_list);
+ preset_entry.set_text_column (preset_cols.label);
+
+ preset_align.add (preset_hbox);
+ preset_align.set_padding (0, 12, 0, 0);
+
+ preset_hbox.pack_start (preset_label, false, false, 0);
+ preset_hbox.pack_start (preset_entry, true, true, 6);
+ preset_hbox.pack_start (preset_save_button, false, false, 0);
+ preset_hbox.pack_start (preset_remove_button, false, false, 6);
+ preset_hbox.pack_start (preset_new_button, false, false, 0);
+
+ preset_save_button.set_sensitive (false);
+ preset_remove_button.set_sensitive (false);
+ preset_new_button.set_sensitive (false);
+
+ preset_select_connection = preset_entry.signal_changed().connect (sigc::mem_fun (*this, &ExportMainDialog::select_preset));
+ preset_save_button.signal_clicked().connect (sigc::mem_fun (*this, &ExportMainDialog::save_current_preset));
+ preset_new_button.signal_clicked().connect (sigc::mem_fun (*this, &ExportMainDialog::save_current_preset));
+ preset_remove_button.signal_clicked().connect (sigc::mem_fun (*this, &ExportMainDialog::remove_current_preset));
+
+ /* warnings */
+
+ warn_container.pack_start (warn_hbox, true, true, 6);
+ warn_container.pack_end (list_files_hbox, false, false, 0);
+
+ warn_hbox.pack_start (warn_label, true, true, 16);
+ warn_label.set_use_markup (true);
+
+ list_files_hbox.pack_end (list_files_button, false, false, 6);
+ list_files_hbox.pack_end (list_files_label, false, false, 6);
+ list_files_label.set_use_markup (true);
+
+ list_files_button.signal_clicked().connect (sigc::mem_fun (*this, &ExportMainDialog::show_conflicting_files));
+
+ /* Progress indicators */
+
+ progress_container.pack_start (progress_label, false, false, 6);
+ progress_container.pack_start (progress_bar, false, false, 6);
+
+ /* Buttons */
+
+ cancel_button = add_button (Gtk::Stock::CANCEL, RESPONSE_CANCEL);
+ rt_export_button = add_button (_("Realtime export"), RESPONSE_RT);
+ fast_export_button = add_button (_("Fast Export"), RESPONSE_FAST);
+
+ cancel_button->signal_clicked().connect (sigc::mem_fun (*this, &ExportMainDialog::close_dialog));
+ rt_export_button->signal_clicked().connect (sigc::mem_fun (*this, &ExportMainDialog::export_rt));
+ fast_export_button->signal_clicked().connect (sigc::mem_fun (*this, &ExportMainDialog::export_fw));
+
+ /* Bolding for labels */
+
+ Pango::AttrList bold;
+ Pango::Attribute b = Pango::Attribute::create_attr_weight (Pango::WEIGHT_BOLD);
+ bold.insert (b);
+
+ timespan_label.set_attributes (bold);
+ channels_label.set_attributes (bold);
+
+ /* Done! */
+
+ show_all_children ();
+ progress_container.hide_all();
+}
+
+ExportMainDialog::~ExportMainDialog ()
+{
+ if (session) {
+ session->release_export_handler();
+ }
+}
+
+void
+ExportMainDialog::set_session (ARDOUR::Session* s)
+{
+ session = s;
+
+ /* Init handler and profile manager */
+
+ handler = session->get_export_handler ();
+ profile_manager.reset (new ExportProfileManager (*session));
+
+ /* Selection range */
+
+ TimeSelection const & time (editor.get_selection().time);
+ if (!time.empty()) {
+ profile_manager->set_selection_range (time.front().start, time.front().end);
+ } else {
+ profile_manager->set_selection_range ();
+ }
+
+ /* Last notebook page */
+
+ new_file_button.add (*Gtk::manage (new Gtk::Image (::get_icon("add"))));
+ new_file_button.set_alignment (0, 0.5);
+ new_file_button.set_relief (Gtk::RELIEF_NONE);
+
+ new_file_hbox.pack_start (new_file_button, true, true);
+ file_notebook.append_page (new_file_dummy, new_file_hbox);
+ file_notebook.set_tab_label_packing (new_file_dummy, true, true, Gtk::PACK_START);
+ new_file_hbox.show_all_children ();
+
+ file_notebook.signal_switch_page().connect (sigc::mem_fun (*this, &ExportMainDialog::handle_page_change));
+ new_file_button.signal_clicked().connect (sigc::mem_fun (*this, &ExportMainDialog::add_new_file_page));
+
+ /* Load states */
+
+ profile_manager->load_profile ();
+ sync_with_manager ();
+
+ /* Warnings */
+
+ timespan_selector.CriticalSelectionChanged.connect (sigc::mem_fun (*this, &ExportMainDialog::update_warnings));
+ channel_selector.CriticalSelectionChanged.connect (sigc::mem_fun (*this, &ExportMainDialog::update_warnings));
+
+ update_warnings ();
+}
+
+void
+ExportMainDialog::select_timespan (Glib::ustring id)
+{
+ set_title ("Export Range");
+ timespan_selector.select_one_range (id);
+}
+
+void
+ExportMainDialog::close_dialog ()
+{
+ ExportStatus & status = session->export_status;
+
+ if (status.running) {
+ status.abort();
+ }
+
+ hide_all ();
+ set_modal (false);
+
+}
+
+void
+ExportMainDialog::sync_with_manager ()
+{
+ /* Clear */
+
+ while (file_notebook.get_n_pages() > 1) {
+ file_notebook.remove_page (0);
+ }
+
+ page_counter = 1;
+ last_visible_page = 0;
+
+ /* Preset list */
+
+ preset_list->clear();
+
+ PresetList const & presets = profile_manager->get_presets();
+ Gtk::ListStore::iterator tree_it;
+
+ for (PresetList::const_iterator it = presets.begin(); it != presets.end(); ++it) {
+ tree_it = preset_list->append();
+ tree_it->set_value (preset_cols.preset, *it);
+ tree_it->set_value (preset_cols.label, Glib::ustring ((*it)->name()));
+
+ if (*it == current_preset) {
+ preset_select_connection.block (true);
+ preset_entry.set_active (tree_it);
+ preset_select_connection.block (false);
+ }
+ }
+
+ /* Timespan and channel config */
+
+ timespan_selector.set_state (profile_manager->get_timespans().front(), session);
+ channel_selector.set_state (profile_manager->get_channel_configs().front(), session);
+
+ /* File notebook */
+
+ ExportProfileManager::FormatStateList const & formats = profile_manager->get_formats ();
+ ExportProfileManager::FormatStateList::const_iterator format_it;
+ ExportProfileManager::FilenameStateList const & filenames = profile_manager->get_filenames ();
+ ExportProfileManager::FilenameStateList::const_iterator filename_it;
+ for (format_it = formats.begin(), filename_it = filenames.begin();
+ format_it != formats.end() && filename_it != filenames.end();
+ ++format_it, ++filename_it) {
+ add_file_page (*format_it, *filename_it);
+ }
+
+ file_notebook.set_current_page (0);
+ update_warnings ();
+}
+
+void
+ExportMainDialog::update_warnings ()
+{
+ /* Reset state */
+
+ warn_string = "";
+ warn_label.set_markup (warn_string);
+
+ list_files_hbox.hide ();
+ list_files_string = "";
+
+ fast_export_button->set_sensitive (true);
+ rt_export_button->set_sensitive (true);
+
+ /* Add new warnings */
+
+ boost::shared_ptr<ExportProfileManager::Warnings> warnings = profile_manager->get_warnings();
+
+ for (std::list<Glib::ustring>::iterator it = warnings->errors.begin(); it != warnings->errors.end(); ++it) {
+ add_error (*it);
+ }
+
+ for (std::list<Glib::ustring>::iterator it = warnings->warnings.begin(); it != warnings->warnings.end(); ++it) {
+ add_warning (*it);
+ }
+
+ if (!warnings->conflicting_filenames.empty()) {
+ list_files_hbox.show ();
+ for (std::list<Glib::ustring>::iterator it = warnings->conflicting_filenames.begin(); it != warnings->conflicting_filenames.end(); ++it) {
+ ustring::size_type pos = it->find_last_of ("/");
+ list_files_string += "\n" + it->substr (0, pos + 1) + "<b>" + it->substr (pos + 1) + "</b>";
+ }
+ }
+}
+
+void
+ExportMainDialog::show_conflicting_files ()
+{
+ ArdourDialog dialog (_("Files that will be overwritten"), true);
+
+ Gtk::Label label ("", Gtk::ALIGN_LEFT);
+ label.set_use_markup (true);
+ label.set_markup (list_files_string);
+
+ dialog.get_vbox()->pack_start (label);
+ dialog.add_button (Gtk::Stock::OK, 0);
+ dialog.show_all_children ();
+
+ dialog.run();
+}
+
+void
+ExportMainDialog::export_rt ()
+{
+ profile_manager->prepare_for_export ();
+ handler->do_export (true);
+ show_progress ();
+}
+
+void
+ExportMainDialog::export_fw ()
+{
+ profile_manager->prepare_for_export ();
+ handler->do_export (false);
+ show_progress ();
+}
+
+void
+ExportMainDialog::show_progress ()
+{
+ ARDOUR::ExportStatus & status = session->export_status;
+ status.running = true;
+
+ cancel_button->set_label (_("Stop Export"));
+ rt_export_button->set_sensitive (false);
+ fast_export_button->set_sensitive (false);
+
+ progress_bar.set_fraction (0.0);
+ warn_container.hide_all();
+ progress_container.show ();
+ progress_container.show_all_children ();
+ progress_connection = Glib::signal_timeout().connect (mem_fun(*this, &ExportMainDialog::progress_timeout), 100);
+
+ gtk_main_iteration ();
+ while (status.running) {
+ if (gtk_events_pending()) {
+ gtk_main_iteration ();
+ } else {
+ usleep (10000);
+ }
+ }
+}
+
+Glib::ustring
+ExportMainDialog::get_nth_format_name (uint32_t n)
+{
+ FilePage * page;
+ if ((page = dynamic_cast<FilePage *> (file_notebook.get_nth_page (n - 1)))) {
+ return page->get_format_name();
+ }
+ return "";
+}
+
+gint
+ExportMainDialog::progress_timeout ()
+{
+ ARDOUR::ExportStatus & status = session->export_status;
+
+ switch (status.stage) {
+ case export_None:
+ progress_label.set_text ("");
+ break;
+ case export_ReadTimespan:
+ progress_label.set_text (string_compose (_("Reading timespan %1 of %2"), status.timespan, status.total_timespans));
+ break;
+ case export_PostProcess:
+ progress_label.set_text (string_compose (_("Processing file %2 of %3 (%1) from timespan %4 of %5"),
+ get_nth_format_name (status.format),
+ status.format, status.total_formats,
+ status.timespan, status.total_timespans));
+ break;
+ case export_Write:
+ progress_label.set_text (string_compose (_("Encoding file %2 of %3 (%1) from timespan %4 of %5"),
+ get_nth_format_name (status.format),
+ status.format, status.total_formats,
+ status.timespan, status.total_timespans));
+ break;
+ }
+
+ progress_bar.set_fraction (status.progress);
+ return TRUE;
+}
+
+void
+ExportMainDialog::select_preset ()
+{
+ Gtk::ListStore::iterator it = preset_entry.get_active ();
+ Glib::ustring text = preset_entry.get_entry()->get_text();
+
+ if (preset_list->iter_is_valid (it)) {
+
+ previous_preset = current_preset = it->get_value (preset_cols.preset);
+ profile_manager->load_preset (current_preset);
+ sync_with_manager ();
+
+ /* Make an edit, so that signal changed will be emitted on re-selection */
+
+ preset_select_connection.block (true);
+ preset_entry.get_entry()->set_text ("");
+ preset_entry.get_entry()->set_text (text);
+ preset_select_connection.block (false);
+
+ } else { // Text has been edited
+ if (previous_preset && !text.compare (previous_preset->name())) {
+
+ current_preset = previous_preset;
+
+ } else {
+ current_preset.reset ();
+ profile_manager->load_preset (current_preset);
+ }
+ }
+
+ preset_save_button.set_sensitive (current_preset);
+ preset_remove_button.set_sensitive (current_preset);
+ preset_new_button.set_sensitive (!current_preset && !text.empty());
+}
+
+void
+ExportMainDialog::save_current_preset ()
+{
+ if (!profile_manager) { return; }
+
+ previous_preset = current_preset = profile_manager->save_preset (preset_entry.get_entry()->get_text());
+ sync_with_manager ();
+ select_preset (); // Update preset widget states
+}
+
+void
+ExportMainDialog::remove_current_preset ()
+{
+ if (!profile_manager) { return; }
+
+ profile_manager->remove_preset();
+ preset_entry.get_entry()->set_text ("");
+ sync_with_manager ();
+}
+
+ExportMainDialog::FilePage::FilePage (Session * s, ManagerPtr profile_manager, ExportMainDialog * parent, uint32_t number,
+ ExportProfileManager::FormatStatePtr format_state,
+ ExportProfileManager::FilenameStatePtr filename_state) :
+ format_state (format_state),
+ filename_state (filename_state),
+ profile_manager (profile_manager),
+
+ format_label (_("Format"), Gtk::ALIGN_LEFT),
+ filename_label (_("Location"), Gtk::ALIGN_LEFT),
+ tab_number (number)
+{
+ set_border_width (12);
+
+ pack_start (format_label, false, false, 0);
+ pack_start (format_align, false, false, 0);
+ pack_start (filename_label, false, false, 0);
+ pack_start (filename_align, false, false, 0);
+
+ format_align.add (format_selector);
+ format_align.set_padding (6, 12, 18, 0);
+
+ filename_align.add (filename_selector);
+ filename_align.set_padding (0, 12, 18, 0);
+
+ Pango::AttrList bold;
+ Pango::Attribute b = Pango::Attribute::create_attr_weight (Pango::WEIGHT_BOLD);
+ bold.insert (b);
+
+ format_label.set_attributes (bold);
+ filename_label.set_attributes (bold);
+ tab_label.set_attributes (bold);
+
+ /* Set states */
+ format_selector.set_state (format_state, s);
+ filename_selector.set_state (filename_state, s);
+
+ /* Signals */
+
+ tab_close_button.signal_clicked().connect (sigc::bind (sigc::mem_fun (*parent, &ExportMainDialog::remove_file_page), this));
+
+ profile_manager->FormatListChanged.connect (sigc::mem_fun (format_selector, &ExportFormatSelector::update_format_list));
+
+ format_selector.FormatEdited.connect (sigc::mem_fun (*this, &ExportMainDialog::FilePage::save_format_to_manager));
+ format_selector.FormatRemoved.connect (sigc::mem_fun (*profile_manager, &ExportProfileManager::remove_format_profile));
+ format_selector.NewFormat.connect (sigc::mem_fun (*profile_manager, &ExportProfileManager::get_new_format));
+
+ format_selector.CriticalSelectionChanged.connect (sigc::mem_fun (*this, &ExportMainDialog::FilePage::update_tab_label));
+ filename_selector.CriticalSelectionChanged.connect (CriticalSelectionChanged.make_slot());
+
+ /* Tab widget */
+
+ tab_close_button.add (*Gtk::manage (new Gtk::Image (::get_icon("close"))));
+ tab_close_alignment.add (tab_close_button);
+ tab_close_alignment.set (0.5, 0.5, 0, 0);
+
+ tab_widget.pack_start (tab_label, false, false, 3);
+ tab_widget.pack_end (tab_close_alignment, false, false, 0);
+ tab_widget.show_all_children ();
+ update_tab_label ();
+
+ /* Done */
+
+ show_all_children ();
+}
+
+ExportMainDialog::FilePage::~FilePage ()
+{
+}
+
+void
+ExportMainDialog::FilePage::set_remove_sensitive (bool value)
+{
+ tab_close_button.set_sensitive (value);
+}
+
+Glib::ustring
+ExportMainDialog::FilePage::get_format_name () const
+{
+ if (format_state && format_state->format) {
+ return format_state->format->name();
+ }
+ return "No format!";
+}
+
+void
+ExportMainDialog::FilePage::save_format_to_manager (FormatPtr format)
+{
+ profile_manager->save_format_to_disk (format);
+}
+
+void
+ExportMainDialog::FilePage::update_tab_label ()
+{
+ tab_label.set_text (string_compose ("%1 %2", tab_number, get_format_name()));
+ CriticalSelectionChanged();
+}
+
+void
+ExportMainDialog::add_new_file_page ()
+{
+ FilePage * page;
+ if ((page = dynamic_cast<FilePage *> (file_notebook.get_nth_page (file_notebook.get_current_page())))) {
+ add_file_page (profile_manager->duplicate_format_state (page->get_format_state()),
+ profile_manager->duplicate_filename_state (page->get_filename_state()));
+ }
+}
+
+void
+ExportMainDialog::add_file_page (ExportProfileManager::FormatStatePtr format_state, ExportProfileManager::FilenameStatePtr filename_state)
+{
+ FilePage * page = Gtk::manage (new FilePage (session, profile_manager, this, page_counter, format_state, filename_state));
+ page->CriticalSelectionChanged.connect (sigc::mem_fun (*this, &ExportMainDialog::update_warnings));
+ file_notebook.insert_page (*page, page->get_tab_widget(), file_notebook.get_n_pages() - 1);
+
+ update_remove_file_page_sensitivity ();
+ file_notebook.show_all_children();
+ ++page_counter;
+
+ update_warnings ();
+}
+
+void
+ExportMainDialog::remove_file_page (FilePage * page)
+{
+ profile_manager->remove_format_state (page->get_format_state());
+ profile_manager->remove_filename_state (page->get_filename_state());
+
+ file_notebook.remove_page (*page);
+ update_remove_file_page_sensitivity ();
+
+ update_warnings ();
+}
+
+void
+ExportMainDialog::update_remove_file_page_sensitivity ()
+{
+ FilePage * page;
+ if ((page = dynamic_cast<FilePage *> (file_notebook.get_nth_page (0)))) {
+ if (file_notebook.get_n_pages() > 2) {
+ page->set_remove_sensitive (true);
+ } else {
+ page->set_remove_sensitive (false);
+ }
+ }
+}
+
+void
+ExportMainDialog::handle_page_change (GtkNotebookPage*, uint page)
+{
+ if (file_notebook.get_n_pages() == 2 && page == 0) { return; }
+
+ if (page + 1 == (uint32_t) file_notebook.get_n_pages()) {
+ file_notebook.set_current_page (last_visible_page);
+ } else {
+ last_visible_page = page;
+ }
+}
+
+void
+ExportMainDialog::add_error (Glib::ustring const & text)
+{
+ fast_export_button->set_sensitive (false);
+ rt_export_button->set_sensitive (false);
+
+ if (warn_string.empty()) {
+ warn_string = _("<span color=\"#ffa755\">Error: ") + text + "</span>";
+ } else {
+ warn_string = _("<span color=\"#ffa755\">Error: ") + text + "</span>\n" + warn_string;
+ }
+
+ warn_label.set_markup (warn_string);
+}
+
+void
+ExportMainDialog::add_warning (Glib::ustring const & text)
+{
+ if (warn_string.empty()) {
+ warn_string = _("<span color=\"#ffa755\">Warning: ") + text + "</span>";
+ } else {
+ warn_string = warn_string + _("\n<span color=\"#ffa755\">Warning: ") + text + "</span>";
+ }
+
+ warn_label.set_markup (warn_string);
+}
diff --git a/gtk2_ardour/export_main_dialog.h b/gtk2_ardour/export_main_dialog.h
new file mode 100644
index 0000000000..af795554e1
--- /dev/null
+++ b/gtk2_ardour/export_main_dialog.h
@@ -0,0 +1,234 @@
+/*
+ Copyright (C) 2008 Paul Davis
+ Author: Sakari Bergen
+
+ 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.
+
+*/
+
+#ifndef __export_main_dialog_h__
+#define __export_main_dialog_h__
+
+#include <ardour/export_handler.h>
+#include <ardour/export_profile_manager.h>
+
+#include "public_editor.h"
+#include "export_timespan_selector.h"
+#include "export_channel_selector.h"
+#include "export_format_selector.h"
+#include "export_filename_selector.h"
+#include "ardour_dialog.h"
+
+#include <gtkmm.h>
+
+namespace ARDOUR {
+ class ExportFilename;
+ class ExportFormatSpecification;
+ class ExportChannelConfiguration;
+}
+
+class ExportTimespanSelector;
+class ExportChannelSelector;
+class ExportFormatSelector;
+class ExportFilenameSelector;
+
+class ExportMainDialog : public ArdourDialog {
+
+ public:
+
+ explicit ExportMainDialog (PublicEditor & editor);
+ ~ExportMainDialog ();
+
+ void set_session (ARDOUR::Session* s);
+
+ void select_timespan (Glib::ustring id);
+
+ /* Responses */
+
+ enum Responses {
+ RESPONSE_RT,
+ RESPONSE_FAST,
+ RESPONSE_CANCEL
+ };
+
+ private:
+
+ void close_dialog ();
+
+ void sync_with_manager ();
+ void update_warnings ();
+ void show_conflicting_files ();
+
+ typedef boost::shared_ptr<ARDOUR::ExportTimespan> TimespanPtr;
+ typedef boost::shared_ptr<std::list<TimespanPtr> > TimespanList;
+
+ typedef boost::shared_ptr<ARDOUR::ExportChannelConfiguration> ChannelConfigPtr;
+ typedef std::list<ChannelConfigPtr> ChannelConfigList;
+
+ typedef boost::shared_ptr<ARDOUR::ExportFilename> FilenamePtr;
+
+ typedef boost::shared_ptr<ARDOUR::ExportHandler> HandlerPtr;
+ typedef boost::shared_ptr<ARDOUR::ExportFormatSpecification> FormatPtr;
+ typedef boost::shared_ptr<ARDOUR::ExportProfileManager> ManagerPtr;
+
+ void export_rt ();
+ void export_fw ();
+
+ void show_progress ();
+ Glib::ustring get_nth_format_name (uint32_t n);
+ gint progress_timeout ();
+
+ /* Other stuff */
+
+ PublicEditor & editor;
+ HandlerPtr handler;
+ ManagerPtr profile_manager;
+
+ /*** GUI components ***/
+
+ Gtk::Table main_table;
+
+ /* Presets */
+
+ typedef ARDOUR::ExportProfileManager::PresetPtr PresetPtr;
+ typedef ARDOUR::ExportProfileManager::PresetList PresetList;
+
+ sigc::connection preset_select_connection;
+
+ void select_preset ();
+ void save_current_preset ();
+ void remove_current_preset ();
+
+ struct PresetCols : public Gtk::TreeModelColumnRecord
+ {
+ public:
+ Gtk::TreeModelColumn<PresetPtr> preset;
+ Gtk::TreeModelColumn<Glib::ustring> label;
+
+ PresetCols () { add (preset); add (label); }
+ };
+ PresetCols preset_cols;
+ Glib::RefPtr<Gtk::ListStore> preset_list;
+ PresetPtr current_preset;
+ PresetPtr previous_preset;
+
+ Gtk::Alignment preset_align;
+ Gtk::HBox preset_hbox;
+ Gtk::Label preset_label;
+ Gtk::ComboBoxEntry preset_entry;
+
+ Gtk::Button preset_save_button;
+ Gtk::Button preset_remove_button;
+ Gtk::Button preset_new_button;
+
+ /* File Notebook */
+
+ class FilePage : public Gtk::VBox {
+ public:
+ FilePage (ARDOUR::Session * s, ManagerPtr profile_manager, ExportMainDialog * parent, uint32_t number,
+ ARDOUR::ExportProfileManager::FormatStatePtr format_state,
+ ARDOUR::ExportProfileManager::FilenameStatePtr filename_state);
+
+ virtual ~FilePage ();
+
+ Gtk::Widget & get_tab_widget () { return tab_widget; }
+ void set_remove_sensitive (bool value);
+ Glib::ustring get_format_name () const;
+
+ ARDOUR::ExportProfileManager::FormatStatePtr get_format_state () const { return format_state; }
+ ARDOUR::ExportProfileManager::FilenameStatePtr get_filename_state () const { return filename_state; }
+
+ sigc::signal<void> CriticalSelectionChanged;
+
+ private:
+ void save_format_to_manager (FormatPtr format);
+ void update_tab_label ();
+
+ ARDOUR::ExportProfileManager::FormatStatePtr format_state;
+ ARDOUR::ExportProfileManager::FilenameStatePtr filename_state;
+ ManagerPtr profile_manager;
+
+ /* GUI components */
+
+ Gtk::Label format_label;
+ Gtk::Alignment format_align;
+ ExportFormatSelector format_selector;
+
+ Gtk::Label filename_label;
+ Gtk::Alignment filename_align;
+ ExportFilenameSelector filename_selector;
+
+ Gtk::HBox tab_widget;
+ Gtk::Label tab_label;
+ Gtk::Alignment tab_close_alignment;
+ Gtk::Button tab_close_button;
+ uint32_t tab_number;
+ };
+
+ void add_new_file_page ();
+ void add_file_page (ARDOUR::ExportProfileManager::FormatStatePtr format_state, ARDOUR::ExportProfileManager::FilenameStatePtr filename_state);
+ void remove_file_page (FilePage * page);
+ void update_remove_file_page_sensitivity ();
+ void handle_page_change (GtkNotebookPage*, uint32_t page);
+
+ uint32_t last_visible_page;
+ uint32_t page_counter;
+
+ /* Warning area */
+
+ Gtk::VBox warn_container;
+
+ Gtk::HBox warn_hbox;
+ Gtk::Label warn_label;
+ Glib::ustring warn_string;
+
+ Gtk::HBox list_files_hbox;
+ Gtk::Label list_files_label;
+ Gtk::Button list_files_button;
+ Glib::ustring list_files_string;
+
+ void add_error (Glib::ustring const & text);
+ void add_warning (Glib::ustring const & text);
+
+ /* Progress bar */
+
+ Gtk::VBox progress_container;
+ Gtk::Label progress_label;
+ Gtk::ProgressBar progress_bar;
+ sigc::connection progress_connection;
+
+ /* Everything else */
+
+ Gtk::Label timespan_label;
+ Gtk::Alignment timespan_align;
+ ExportTimespanSelector timespan_selector;
+
+ Gtk::Label channels_label;
+ Gtk::Alignment channels_align;
+ ExportChannelSelector channel_selector;
+
+ Gtk::Notebook file_notebook;
+
+ Gtk::HBox new_file_hbox;
+ Gtk::Button new_file_button;
+ Gtk::VBox new_file_dummy;
+
+ Gtk::Button * cancel_button;
+ Gtk::Button * rt_export_button;
+ Gtk::Button * fast_export_button;
+
+};
+
+#endif /* __ardour_export_main_dialog_h__ */
diff --git a/gtk2_ardour/export_multiplicator.cc b/gtk2_ardour/export_multiplicator.cc
new file mode 100644
index 0000000000..969548e273
--- /dev/null
+++ b/gtk2_ardour/export_multiplicator.cc
@@ -0,0 +1,330 @@
+/* This file is not used at the moment. It includes code related to export a
+ * multiplication graph system that can be used together with the code in
+ * libs/ardour/export_multiplication.cc and libs/ardour/ardour/export_multiplication.h
+ * - Sakari Bergen 6.8.2008 -
+ */
+
+/*
+ Copyright (C) 2008 Paul Davis
+ Author: Sakari Bergen
+
+ 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 "export_multiplicator.h"
+
+#include <cassert>
+
+#include <pbd/compose.h>
+
+#include "i18n.h"
+
+using namespace ARDOUR;
+using namespace PBD;
+
+#define CALL_MEMBER_FN(object,ptrToMember) ((object).*(ptrToMember))
+
+ExportMultiplicator::ExportMultiplicator () :
+ graph (0)
+{
+ add (table);
+}
+
+ExportMultiplicator::~ExportMultiplicator ()
+{}
+
+void
+ExportMultiplicator::set_manager (boost::shared_ptr<ARDOUR::ExportProfileManager> _manager)
+{
+ manager = _manager;
+ manager->GraphChanged.connect (sigc::mem_fun (*this, &ExportMultiplicator::redraw));
+
+ redraw();
+}
+
+void
+ExportMultiplicator::redraw ()
+{
+ if (!manager) { return; }
+
+ graph = &manager->get_graph();
+
+ /* Empty table */
+
+ table.foreach (sigc::mem_fun (table, &Gtk::Table::remove));
+ widget_map.clear();
+
+ /* Calculate table dimensions */
+
+ uint32_t max_width = 0;
+ GraphLevel max_level = NoLevel;
+
+ if (graph->timespans.size() > max_width) {
+ max_width = graph->timespans.size();
+ max_level = Timespans;
+ }
+
+ if (graph->channel_configs.size() > max_width) {
+ max_width = graph->channel_configs.size();
+ max_level = ChannelConfigs;
+ }
+
+ if (graph->formats.size() > max_width) {
+ max_width = graph->formats.size();
+ max_level = Formats;
+ }
+
+ if (graph->filenames.size() > max_width) {
+ max_width = graph->filenames.size();
+ max_level = Filenames;
+ }
+
+ table.resize (4, max_width);
+
+ std::cout << "Table width: " << max_width << std::endl;
+
+ /* Fill table */
+
+ for (list<ExportProfileManager::TimespanNodePtr>::const_iterator it = graph->timespans.begin(); it != graph->timespans.end(); ++it) {
+ draw_timespan (*it, get_bounds (it->get(), Timespans, max_level));
+ }
+
+ for (list<ExportProfileManager::ChannelConfigNodePtr>::const_iterator it = graph->channel_configs.begin(); it != graph->channel_configs.end(); ++it) {
+ draw_channel_config (*it, get_bounds (it->get(), ChannelConfigs, max_level));
+ }
+
+ for (list<ExportProfileManager::FormatNodePtr>::const_iterator it = graph->formats.begin(); it != graph->formats.end(); ++it) {
+ draw_format (*it, get_bounds (it->get(), Formats, max_level));
+ }
+
+ for (list<ExportProfileManager::FilenameNodePtr>::const_iterator it = graph->filenames.begin(); it != graph->filenames.end(); ++it) {
+ draw_filename (*it, get_bounds (it->get(), Filenames, max_level));
+ }
+
+ show_all_children ();
+}
+
+std::pair<uint32_t, uint32_t>
+ExportMultiplicator::get_bounds (ARDOUR::ExportProfileManager::GraphNode * node, GraphLevel current_level, GraphLevel max_level) const
+{
+ assert (current_level != NoLevel && max_level != NoLevel && graph);
+
+ uint32_t left_bound = 0;
+ uint32_t right_bound = 0;
+
+ bool left_bound_found = false;
+
+ bool (ExportProfileManager::GraphNode::*relation_func) (ExportProfileManager::GraphNode const *) const;
+ if (max_level < current_level) {
+ std::cout << "using 'is_ancestor_of'" << std::endl;
+ relation_func = &ExportProfileManager::GraphNode::is_ancestor_of;
+ } else if (max_level > current_level) {
+ std::cout << "using 'is_descendant_of'" << std::endl;
+ relation_func = &ExportProfileManager::GraphNode::is_descendant_of;
+ } else {
+ std::cout << "using 'equals'" << std::endl;
+ relation_func = &ExportProfileManager::GraphNode::equals;
+ }
+
+ switch (max_level) {
+ case Timespans:
+ for (list<ExportProfileManager::TimespanNodePtr>::const_iterator it = graph->timespans.begin(); it != graph->timespans.end(); ++it) {
+ if (CALL_MEMBER_FN(**it, relation_func) (node)) {
+ left_bound_found = true;
+ } else if (!left_bound_found) {
+ ++left_bound;
+ }
+
+ if (left_bound_found && !CALL_MEMBER_FN(**it, relation_func) (node)) {
+ break;
+ } else {
+ ++right_bound;
+ }
+ }
+ break;
+
+ case ChannelConfigs:
+ for (list<ExportProfileManager::ChannelConfigNodePtr>::const_iterator it = graph->channel_configs.begin(); it != graph->channel_configs.end(); ++it) {
+ if (CALL_MEMBER_FN(**it, relation_func) (node)) {
+ left_bound_found = true;
+ } else if (!left_bound_found) {
+ ++left_bound;
+ }
+
+ if (left_bound_found && !CALL_MEMBER_FN(**it, relation_func) (node)) {
+ break;
+ } else {
+ ++right_bound;
+ }
+ }
+ break;
+
+ case Formats:
+ for (list<ExportProfileManager::FormatNodePtr>::const_iterator it = graph->formats.begin(); it != graph->formats.end(); ++it) {
+ if (CALL_MEMBER_FN(**it, relation_func) (node)) {
+ left_bound_found = true;
+ } else if (!left_bound_found) {
+ ++left_bound;
+ }
+
+ if (left_bound_found && !CALL_MEMBER_FN(**it, relation_func) (node)) {
+ break;
+ } else {
+ ++right_bound;
+ }
+ }
+ break;
+
+ case Filenames:
+ for (list<ExportProfileManager::FilenameNodePtr>::const_iterator it = graph->filenames.begin(); it != graph->filenames.end(); ++it) {
+ if (CALL_MEMBER_FN(**it, relation_func) (node)) {
+ std::cout << "filename relation check returned true" << std::endl;
+ left_bound_found = true;
+ } else if (!left_bound_found) {
+ std::cout << "filename relation check returned false" << std::endl;
+ ++left_bound;
+ }
+
+ if (left_bound_found && !CALL_MEMBER_FN(**it, relation_func) (node)) {
+ break;
+ } else {
+ ++right_bound;
+ }
+ }
+ break;
+
+ case NoLevel:
+ // Not reached !
+ break;
+ }
+
+ return std::pair<uint32_t, uint32_t> (left_bound, right_bound);
+}
+
+void
+ExportMultiplicator::draw_timespan (ARDOUR::ExportProfileManager::TimespanNodePtr node, std::pair<uint32_t, uint32_t> bounds)
+{
+ ButtonWidget * button = Gtk::manage (new ButtonWidget (string_compose ("Timespan %1", node->id()), manager, node.get()));
+ get_hbox (TablePosition (bounds.first, bounds.second, Timespans))->pack_end (*button, true, true);
+}
+
+void
+ExportMultiplicator::draw_channel_config (ARDOUR::ExportProfileManager::ChannelConfigNodePtr node, std::pair<uint32_t, uint32_t> bounds)
+{
+ ButtonWidget * button = Gtk::manage (new ButtonWidget (string_compose ("Channel config %1", node->id()), manager, node.get()));
+ get_hbox (TablePosition (bounds.first, bounds.second, ChannelConfigs))->pack_end (*button, true, true);
+}
+
+void
+ExportMultiplicator::draw_format (ARDOUR::ExportProfileManager::FormatNodePtr node, std::pair<uint32_t, uint32_t> bounds)
+{
+ ButtonWidget * button = Gtk::manage (new ButtonWidget (string_compose ("Format %1", node->id()), manager, node.get()));
+ get_hbox (TablePosition (bounds.first, bounds.second, Formats))->pack_end (*button, true, true);
+}
+
+void
+ExportMultiplicator::draw_filename (ARDOUR::ExportProfileManager::FilenameNodePtr node, std::pair<uint32_t, uint32_t> bounds)
+{
+ ButtonWidget * button = Gtk::manage (new ButtonWidget (string_compose ("Filename %1", node->id()), manager, node.get()));
+ get_hbox (TablePosition (bounds.first, bounds.second, Filenames))->pack_end (*button, true, true);
+}
+
+boost::shared_ptr<Gtk::HBox>
+ExportMultiplicator::get_hbox (TablePosition position)
+{
+ WidgetMap::iterator it = widget_map.find (position);
+ if (it != widget_map.end()) { return it->second; }
+
+ boost::shared_ptr<Gtk::HBox> widget = widget_map.insert (WidgetPair (position, boost::shared_ptr<Gtk::HBox> (new Gtk::HBox ()))).first->second;
+ table.attach (*widget, position.left, position.right, position.row - 1, position.row);
+
+ return widget;
+}
+
+ExportMultiplicator::ButtonWidget::ButtonWidget (Glib::ustring name, boost::shared_ptr<ExportProfileManager> m, ExportProfileManager::GraphNode * node) :
+ label (name),
+ node (node),
+ split_position (0.5)
+{
+ manager = m;
+
+ menu_actions = Gtk::ActionGroup::create();
+ menu_actions->add (Gtk::Action::create ("Split", _("_Split here")), sigc::mem_fun (*this, &ExportMultiplicator::ButtonWidget::split));
+ menu_actions->add (Gtk::Action::create ("Remove", _("_Remove")), sigc::mem_fun (*this, &ExportMultiplicator::ButtonWidget::remove));
+
+ ui_manager = Gtk::UIManager::create();
+ ui_manager->insert_action_group (menu_actions);
+
+ Glib::ustring ui_info =
+ "<ui>"
+ " <popup name='PopupMenu'>"
+ " <menuitem action='Split'/>"
+ " <menuitem action='Remove'/>"
+ " </popup>"
+ "</ui>";
+
+ ui_manager->add_ui_from_string (ui_info);
+ menu = dynamic_cast<Gtk::Menu*> (ui_manager->get_widget ("/PopupMenu"));
+
+ add_events (Gdk::BUTTON_PRESS_MASK);
+ signal_button_press_event ().connect (sigc::mem_fun (*this, &ExportMultiplicator::ButtonWidget::on_button_press_event));
+
+ modify_bg (Gtk::STATE_NORMAL, Gdk::Color ("#0000"));
+ set_border_width (1);
+ vbox.pack_start (label, true, true, 4);
+ add (vbox);
+}
+
+bool
+ExportMultiplicator::ButtonWidget::on_button_press_event (GdkEventButton* event)
+{
+ if(event->type != GDK_BUTTON_PRESS) { return false; }
+ if (event->button == 1) {
+ node->select (!node->selected ());
+
+ if (node->selected ()) {
+ unset_bg (Gtk::STATE_NORMAL);
+ modify_bg (Gtk::STATE_NORMAL, Gdk::Color ("#194756"));
+ } else {
+ unset_bg (Gtk::STATE_NORMAL);
+ modify_bg (Gtk::STATE_NORMAL, Gdk::Color ("#0000"));
+ }
+
+ return true;
+
+ } else if (event->button == 3) {
+ int x, y;
+ get_pointer (x, y);
+ split_position = (float) x / get_width();
+
+ menu->popup (event->button, event->time);
+ return true;
+ }
+
+ return false;
+}
+
+void
+ExportMultiplicator::ButtonWidget::split ()
+{
+ manager->split_node (node, split_position);
+}
+
+void
+ExportMultiplicator::ButtonWidget::remove ()
+{
+ manager->remove_node (node);
+}
diff --git a/gtk2_ardour/export_multiplicator.h b/gtk2_ardour/export_multiplicator.h
new file mode 100644
index 0000000000..20ce96cda0
--- /dev/null
+++ b/gtk2_ardour/export_multiplicator.h
@@ -0,0 +1,121 @@
+/* This file is not used at the moment. It includes code related to export a
+ * multiplication graph system that can be used together with the code in
+ * libs/ardour/export_multiplication.cc and libs/ardour/ardour/export_multiplication.h
+ * - Sakari Bergen 6.8.2008 -
+ */
+
+/*
+ Copyright (C) 2008 Paul Davis
+ Author: Sakari Bergen
+
+ 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.
+
+*/
+
+#ifndef __export_multiplicator_h__
+#define __export_multiplicator_h__
+
+#include <utility>
+#include <map>
+
+#include <ardour/export_profile_manager.h>
+
+#include <gtkmm.h>
+#include <boost/shared_ptr.hpp>
+
+using std::list;
+using ARDOUR::ExportProfileManager;
+
+class ExportMultiplicator : public Gtk::EventBox {
+ public:
+
+ ExportMultiplicator ();
+ ~ExportMultiplicator ();
+
+ void set_manager (boost::shared_ptr<ExportProfileManager> _manager);
+
+ private:
+
+ boost::shared_ptr<ExportProfileManager> manager;
+ ExportProfileManager::MultiplicationGraph const * graph;
+
+ /* Drawing stuff */
+
+ Gtk::Table table;
+
+ void redraw ();
+
+ enum GraphLevel {
+ NoLevel = 0,
+ Timespans = 1,
+ ChannelConfigs = 2,
+ Formats = 3,
+ Filenames = 4
+ };
+
+ std::pair<uint32_t, uint32_t> get_bounds (ExportProfileManager::GraphNode * node, GraphLevel current_level, GraphLevel max_level) const;
+
+ void draw_timespan (ExportProfileManager::TimespanNodePtr node, std::pair<uint32_t, uint32_t> bounds);
+ void draw_channel_config (ExportProfileManager::ChannelConfigNodePtr node, std::pair<uint32_t, uint32_t> bounds);
+ void draw_format (ExportProfileManager::FormatNodePtr node, std::pair<uint32_t, uint32_t> bounds);
+ void draw_filename (ExportProfileManager::FilenameNodePtr node, std::pair<uint32_t, uint32_t> bounds);
+
+ struct TablePosition {
+ uint32_t left;
+ uint32_t right;
+ uint32_t row;
+
+ TablePosition (uint32_t left, uint32_t right, uint32_t row) :
+ left (left), right (right), row (row) {}
+
+ bool operator== (TablePosition const & other) const { return (row == other.row && left == other.left && right == other.right); }
+ bool operator< (TablePosition const & other) const { return (row < other.row || left < other.left || right < other.right); }
+ };
+
+ typedef std::map<TablePosition, boost::shared_ptr<Gtk::HBox> > WidgetMap;
+ typedef std::pair<TablePosition, boost::shared_ptr<Gtk::HBox> > WidgetPair;
+
+ boost::shared_ptr<Gtk::HBox> get_hbox (TablePosition position);
+ WidgetMap widget_map;
+
+ /* Button Widget */
+
+ class ButtonWidget : public Gtk::EventBox {
+ public:
+ ButtonWidget (Glib::ustring name, boost::shared_ptr<ExportProfileManager> m, ExportProfileManager::GraphNode * node);
+
+ private:
+
+ Gtk::Label label;
+ Gtk::VBox vbox;
+
+ bool on_button_press_event (GdkEventButton* event);
+
+ void split ();
+ void remove ();
+
+ boost::shared_ptr<ExportProfileManager> manager;
+ ExportProfileManager::GraphNode * node;
+ float split_position;
+
+ /* Context menu */
+
+ Glib::RefPtr<Gtk::ActionGroup> menu_actions;
+ Glib::RefPtr<Gtk::UIManager> ui_manager;
+ Gtk::Menu * menu;
+ };
+};
+
+#endif /* __export_multiplicator_h__ */
diff --git a/gtk2_ardour/export_timespan_selector.cc b/gtk2_ardour/export_timespan_selector.cc
new file mode 100644
index 0000000000..0f02a1580e
--- /dev/null
+++ b/gtk2_ardour/export_timespan_selector.cc
@@ -0,0 +1,394 @@
+/*
+ Copyright (C) 2008 Paul Davis
+ Author: Sakari Bergen
+
+ 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 "export_timespan_selector.h"
+
+#include "ardour_ui.h"
+
+#include <ardour/location.h>
+#include <ardour/types.h>
+#include <ardour/session.h>
+#include <ardour/export_handler.h>
+#include <ardour/export_timespan.h>
+
+#include <pbd/enumwriter.h>
+#include <pbd/convert.h>
+
+#include <sstream>
+#include <iomanip>
+
+#include "i18n.h"
+
+using namespace ARDOUR;
+using namespace PBD;
+
+ExportTimespanSelector::ExportTimespanSelector () :
+ time_format_label (_("Show Times as:"), Gtk::ALIGN_LEFT)
+{
+
+ option_hbox.pack_start (time_format_label, false, false, 0);
+ option_hbox.pack_start (time_format_combo, false, false, 6);
+
+ range_scroller.add (range_view);
+ range_scroller.set_policy (Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
+
+ pack_start (option_hbox, false, false, 0);
+ pack_start (range_scroller, true, true, 6);
+
+ /*** Combo boxes ***/
+
+ Gtk::TreeModel::iterator iter;
+ Gtk::TreeModel::Row row;
+
+ /* Time format combo */
+
+ time_format_list = Gtk::ListStore::create (time_format_cols);
+ time_format_combo.set_model (time_format_list);
+
+ iter = time_format_list->append();
+ row = *iter;
+ row[time_format_cols.format] = ExportProfileManager::SMPTE;
+ row[time_format_cols.label] = X_("Timecode");
+
+ iter = time_format_list->append();
+ row = *iter;
+ row[time_format_cols.format] = ExportProfileManager::MinSec;
+ row[time_format_cols.label] = _("Minutes:Seconds");
+
+ iter = time_format_list->append();
+ row = *iter;
+ row[time_format_cols.format] = ExportProfileManager::BBT;
+ row[time_format_cols.label] = _("Bars:Beats");
+
+ time_format_combo.pack_start (time_format_cols.label);
+ time_format_combo.set_active (0);
+
+ time_format_combo.signal_changed().connect (sigc::mem_fun (*this, &ExportTimespanSelector::change_time_format));
+
+ /* Range view */
+
+ range_list = Gtk::ListStore::create (range_cols);
+ range_view.set_model (range_list);
+ range_view.set_headers_visible (false);
+
+ range_view.append_column_editable ("", range_cols.selected);
+ range_view.append_column_editable ("", range_cols.name);
+
+ Gtk::CellRendererText * label_render = Gtk::manage (new Gtk::CellRendererText());
+ Gtk::TreeView::Column * label_col = Gtk::manage (new Gtk::TreeView::Column ("", *label_render));
+ label_col->add_attribute (label_render->property_markup(), range_cols.label);
+ range_view.append_column (*label_col);
+
+ if (Gtk::CellRendererToggle * renderer = dynamic_cast<Gtk::CellRendererToggle *> (range_view.get_column_cell_renderer (0))) {
+ renderer->signal_toggled().connect (sigc::hide (sigc::mem_fun (*this, &ExportTimespanSelector::update_selection)));
+ }
+ if (Gtk::CellRendererText * renderer = dynamic_cast<Gtk::CellRendererText *> (range_view.get_column_cell_renderer (1))) {
+ renderer->signal_edited().connect (sigc::mem_fun (*this, &ExportTimespanSelector::update_range_name));
+ }
+
+}
+
+ExportTimespanSelector::~ExportTimespanSelector ()
+{
+
+}
+
+void
+ExportTimespanSelector::set_state (ARDOUR::ExportProfileManager::TimespanStatePtr const state_, ARDOUR::Session * session_)
+{
+ state = state_;
+ session = session_;
+
+ fill_range_list ();
+ set_selection_from_state ();
+
+ CriticalSelectionChanged();
+}
+
+void
+ExportTimespanSelector::select_one_range (Glib::ustring id)
+{
+ if (!state) { return; }
+
+ range_view.remove_column (*range_view.get_column (0));
+
+ Glib::ustring real_id;
+
+ if (!id.compare (X_("session"))) {
+ real_id = state->session_range->id().to_s();
+ } else if (!id.compare (X_("selection"))) {
+ real_id = state->selection_range->id().to_s();
+ } else {
+ real_id = id;
+ }
+
+ for (Gtk::ListStore::Children::iterator it = range_list->children().begin(); it != range_list->children().end();) {
+ if (!it->get_value (range_cols.location)->id().to_s().compare (real_id)) {
+ it->set_value (range_cols.selected, true);
+ ++it;
+ } else {
+ Gtk::ListStore::Children::iterator temp = it++;
+ range_list->erase (temp);
+ }
+ }
+
+ int x_offset, y_offset, width, height;
+ Gtk::CellRenderer * renderer = *range_view.get_column(0)->get_cell_renderers().begin();
+ renderer->get_size (range_view, x_offset, y_offset, width, height);
+ range_scroller.set_size_request (-1, height);
+ range_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_NEVER);
+
+ update_selection();
+}
+
+void
+ExportTimespanSelector::fill_range_list ()
+{
+ range_list->clear();
+
+ Gtk::TreeModel::iterator iter;
+ Gtk::TreeModel::Row row;
+ for (LocationList::const_iterator it = state->ranges->begin(); it != state->ranges->end(); ++it) {
+ iter = range_list->append();
+ row = *iter;
+
+ row[range_cols.location] = *it;
+ row[range_cols.selected] = false;
+ row[range_cols.name] = (*it)->name();
+ row[range_cols.label] = construct_label (*it);
+ }
+}
+
+void
+ExportTimespanSelector::set_selection_from_state ()
+{
+ Gtk::TreeModel::Children::iterator tree_it;
+
+ for (TimespanList::iterator it = state->timespans->begin(); it != state->timespans->end(); ++it) {
+ ustring id = (*it)->range_id();
+ for (tree_it = range_list->children().begin(); tree_it != range_list->children().end(); ++tree_it) {
+ Location * loc = tree_it->get_value (range_cols.location);
+
+ if ((!id.compare ("session") && loc == state->session_range.get()) ||
+ (!id.compare ("selection") && loc == state->selection_range.get()) ||
+ (!id.compare (loc->id().to_s()))) {
+ tree_it->set_value (range_cols.selected, true);
+ }
+ }
+ }
+
+ for (tree_it = time_format_list->children().begin(); tree_it != time_format_list->children().end(); ++tree_it) {
+ if (tree_it->get_value (time_format_cols.format) == state->time_format) {
+ time_format_combo.set_active (tree_it);
+ }
+ }
+}
+
+void
+ExportTimespanSelector::update_selection ()
+{
+ update_timespans ();
+ CriticalSelectionChanged ();
+}
+
+void
+ExportTimespanSelector::update_timespans ()
+{
+ state->timespans->clear();
+
+ TimespanPtr span;
+ HandlerPtr handler = session->get_export_handler();
+
+ for (Gtk::TreeStore::Children::iterator it = range_list->children().begin(); it != range_list->children().end(); ++it) {
+ if (it->get_value (range_cols.selected)) {
+ span = handler->add_timespan();
+ Location * loc = it->get_value (range_cols.location);
+
+ Glib::ustring id;
+ if (loc == state->session_range.get()) {
+ id = "session";
+ } else if (loc == state->selection_range.get()) {
+ id = "selection";
+ } else {
+ id = loc->id().to_s();
+ }
+
+ span->set_range (loc->start(), loc->end());
+ span->set_name (loc->name());
+ span->set_range_id (id);
+ state->timespans->push_back (span);
+ }
+ }
+}
+
+void
+ExportTimespanSelector::change_time_format ()
+{
+ state->time_format = time_format_combo.get_active()->get_value (time_format_cols.format);
+
+ for (Gtk::ListStore::Children::iterator it = range_list->children().begin(); it != range_list->children().end(); ++it) {
+ Location * location = it->get_value (range_cols.location);
+ it->set_value (range_cols.label, construct_label (location));
+ }
+}
+
+Glib::ustring
+ExportTimespanSelector::construct_label (ARDOUR::Location const * location)
+{
+ Glib::ustring label;
+ Glib::ustring start;
+ Glib::ustring end;
+
+ nframes_t start_frame = location->start();
+ nframes_t end_frame = location->end();
+
+ switch (state->time_format) {
+ case AudioClock::BBT:
+ start = bbt_str (start_frame);
+ end = bbt_str (end_frame);
+ break;
+
+ case AudioClock::SMPTE:
+ start = smpte_str (start_frame);
+ end = smpte_str (end_frame);
+ break;
+
+ case AudioClock::MinSec:
+ start = ms_str (start_frame);
+ end = ms_str (end_frame);
+ break;
+
+ case AudioClock::Frames:
+ start = to_string (start_frame, std::dec);
+ end = to_string (end_frame, std::dec);
+ break;
+
+ case AudioClock::Off:
+ break;
+ }
+
+ // label += _("from ");
+
+ // label += "<span color=\"#7fff7f\">";
+ label += start;
+// label += "</span>";
+
+ label += _(" to ");
+
+// label += "<span color=\"#7fff7f\">";
+ label += end;
+// label += "</span>";
+
+ return label;
+}
+
+
+Glib::ustring
+ExportTimespanSelector::bbt_str (nframes_t frames)
+{
+ if (!session) {
+ return "Error!";
+ }
+
+ std::ostringstream oss;
+ BBT_Time time;
+
+ session->bbt_time (frames, time);
+
+ oss << std::setfill('0') << std::right <<
+ std::setw(3) <<
+ time.bars << "|" <<
+ std::setw(2) <<
+ time.beats << "|" <<
+ std::setw(4) <<
+ time.ticks;
+
+ return oss.str();
+}
+
+Glib::ustring
+ExportTimespanSelector::smpte_str (nframes_t frames)
+{
+ if (!session) {
+ return "Error!";
+ }
+
+ std::ostringstream oss;
+ SMPTE::Time time;
+
+ session->smpte_time (frames, time);
+
+ oss << std::setfill('0') << std::right <<
+ std::setw(2) <<
+ time.hours << ":" <<
+ std::setw(2) <<
+ time.minutes << ":" <<
+ std::setw(2) <<
+ time.seconds << ":" <<
+ std::setw(2) <<
+ time.frames;
+
+ return oss.str();
+}
+
+Glib::ustring
+ExportTimespanSelector::ms_str (nframes_t frames)
+{
+ if (!session) {
+ return "Error!";
+ }
+
+ std::ostringstream oss;
+ nframes_t left;
+ int hrs;
+ int mins;
+ int secs;
+ int sec_promilles;
+
+ left = frames;
+ hrs = (int) floor (left / (session->frame_rate() * 60.0f * 60.0f));
+ left -= (nframes_t) floor (hrs * session->frame_rate() * 60.0f * 60.0f);
+ mins = (int) floor (left / (session->frame_rate() * 60.0f));
+ left -= (nframes_t) floor (mins * session->frame_rate() * 60.0f);
+ secs = (int) floor (left / (float) session->frame_rate());
+ left -= (nframes_t) floor (secs * session->frame_rate());
+ sec_promilles = (int) (left * 1000 / (float) session->frame_rate() + 0.5);
+
+ oss << std::setfill('0') << std::right <<
+ std::setw(2) <<
+ hrs << ":" <<
+ std::setw(2) <<
+ mins << ":" <<
+ std::setw(2) <<
+ secs << "." <<
+ std::setw(3) <<
+ sec_promilles;
+
+ return oss.str();
+}
+
+void
+ExportTimespanSelector::update_range_name (Glib::ustring const & path, Glib::ustring const & new_text)
+{
+ Gtk::TreeStore::iterator it = range_list->get_iter (path);
+ it->get_value (range_cols.location)->set_name (new_text);
+
+ CriticalSelectionChanged();
+}
diff --git a/gtk2_ardour/export_timespan_selector.h b/gtk2_ardour/export_timespan_selector.h
new file mode 100644
index 0000000000..757b2caad2
--- /dev/null
+++ b/gtk2_ardour/export_timespan_selector.h
@@ -0,0 +1,132 @@
+/*
+ Copyright (C) 2008 Paul Davis
+ Author: Sakari Bergen
+
+ 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.
+
+*/
+
+#ifndef __export_timespan_selector_h__
+#define __export_timespan_selector_h__
+
+#include "public_editor.h"
+#include "audio_clock.h"
+
+#include <list>
+
+#include <gtkmm.h>
+#include <boost/shared_ptr.hpp>
+
+#include <ardour/types.h>
+#include <ardour/export_profile_manager.h>
+
+namespace ARDOUR {
+ class Location;
+ class ExportTimespan;
+ class ExportHandler;
+ class Session;
+}
+
+using ARDOUR::CDMarkerFormat;
+
+///
+class ExportTimespanSelector : public Gtk::VBox {
+ private:
+
+ typedef std::list<ARDOUR::Location *> LocationList;
+ typedef boost::shared_ptr<ARDOUR::ExportHandler> HandlerPtr;
+
+ typedef boost::shared_ptr<ARDOUR::ExportTimespan> TimespanPtr;
+ typedef std::list<TimespanPtr> TimespanList;
+ typedef boost::shared_ptr<TimespanList> TimespanListPtr;
+
+ public:
+
+ ExportTimespanSelector ();
+ ~ExportTimespanSelector ();
+
+ void set_state (ARDOUR::ExportProfileManager::TimespanStatePtr const state_, ARDOUR::Session * session_);
+
+ void select_one_range (Glib::ustring id);
+
+ /* Compatibility with other elements */
+
+ sigc::signal<void> CriticalSelectionChanged;
+
+ private:
+
+ void fill_range_list ();
+ void set_selection_from_state ();
+
+ void update_selection ();
+ void update_timespans ();
+
+ void change_time_format ();
+
+ Glib::ustring construct_label (ARDOUR::Location const * location);
+
+ Glib::ustring bbt_str (nframes_t frames);
+ Glib::ustring smpte_str (nframes_t frames);
+ Glib::ustring ms_str (nframes_t frames);
+
+ void update_range_name (Glib::ustring const & path, Glib::ustring const & new_text);
+
+ ARDOUR::Session * session;
+
+ ARDOUR::ExportProfileManager::TimespanStatePtr state;
+
+ /*** GUI components ***/
+
+ Gtk::HBox option_hbox;
+ Gtk::Label time_format_label;
+
+ /* Time format */
+
+ typedef ARDOUR::ExportProfileManager::TimeFormat TimeFormat;
+
+ struct TimeFormatCols : public Gtk::TreeModelColumnRecord
+ {
+ public:
+ Gtk::TreeModelColumn<TimeFormat> format;
+ Gtk::TreeModelColumn<Glib::ustring> label;
+
+ TimeFormatCols () { add(format); add(label); }
+ };
+ TimeFormatCols time_format_cols;
+ Glib::RefPtr<Gtk::ListStore> time_format_list;
+ Gtk::ComboBox time_format_combo;
+
+ /* View */
+
+ struct RangeCols : public Gtk::TreeModelColumnRecord
+ {
+ public:
+ Gtk::TreeModelColumn<ARDOUR::Location *> location;
+ Gtk::TreeModelColumn<Glib::ustring> label;
+ Gtk::TreeModelColumn<bool> selected;
+ Gtk::TreeModelColumn<Glib::ustring> name;
+
+ RangeCols () { add (location); add(label); add(selected); add(name); }
+ };
+ RangeCols range_cols;
+
+ Glib::RefPtr<Gtk::ListStore> range_list;
+ Gtk::TreeView range_view;
+
+ Gtk::ScrolledWindow range_scroller;
+
+};
+
+#endif /* __export_timespan_selector_h__ */
diff --git a/gtk2_ardour/session_metadata_dialog.cc b/gtk2_ardour/session_metadata_dialog.cc
new file mode 100644
index 0000000000..35920038be
--- /dev/null
+++ b/gtk2_ardour/session_metadata_dialog.cc
@@ -0,0 +1,738 @@
+/*
+ Copyright (C) 2008 Paul Davis
+ Author: Sakari Bergen
+
+ 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 "session_metadata_dialog.h"
+
+#include <sstream>
+
+#include <gtkmm2ext/utils.h>
+#include <gtkmm2ext/window_title.h>
+
+#include "i18n.h"
+#include <pbd/xml++.h>
+#include <ardour/session.h>
+#include <ardour/session_directory.h>
+#include <ardour/session_utils.h>
+
+#define CALL_MEMBER_FN(object,ptrToMember) ((object).*(ptrToMember))
+
+/*** MetadataField ***/
+
+MetadataField::MetadataField (ustring const & field_name) :
+ _name (field_name)
+{
+}
+
+MetadataField::~MetadataField() { }
+
+/* TextMetadataField */
+
+TextMetadataField::TextMetadataField (Getter getter, Setter setter, ustring const & field_name, guint width ) :
+ MetadataField (field_name),
+ getter (getter),
+ setter (setter),
+ width (width)
+{
+ entry = 0;
+ label = 0;
+ value_label = 0;
+}
+
+MetadataPtr
+TextMetadataField::copy ()
+{
+ return MetadataPtr (new TextMetadataField (getter, setter, _name, width));
+}
+
+void
+TextMetadataField::save_data (ARDOUR::SessionMetadata & data) const
+{
+ CALL_MEMBER_FN (data, setter) (_value);
+}
+
+void
+TextMetadataField::load_data (ARDOUR::SessionMetadata const & data)
+{
+ _value = CALL_MEMBER_FN (data, getter) ();
+ if (entry) {
+ entry->set_text (_value);
+ }
+}
+
+Gtk::Widget &
+TextMetadataField::name_widget ()
+{
+ label = Gtk::manage (new Gtk::Label(_name + ':', Gtk::ALIGN_LEFT));
+ return *label;
+}
+
+Gtk::Widget &
+TextMetadataField::value_widget ()
+{
+ value_label = Gtk::manage (new Gtk::Label(_value));
+ return *value_label;
+}
+
+Gtk::Widget &
+TextMetadataField::edit_widget ()
+{
+ entry = Gtk::manage (new Gtk::Entry());
+
+ entry->set_text (_value);
+ entry->set_width_chars (width);
+ entry->signal_changed().connect (sigc::mem_fun(*this, &TextMetadataField::update_value));
+
+ return *entry;
+}
+
+void
+TextMetadataField::update_value ()
+{
+ _value = entry->get_text ();
+}
+
+/* NumberMetadataField */
+
+NumberMetadataField::NumberMetadataField (Getter getter, Setter setter, ustring const & field_name, guint numbers, guint width) :
+ MetadataField (field_name),
+ getter (getter),
+ setter (setter),
+ numbers (numbers),
+ width (width)
+{
+ entry = 0;
+ label = 0;
+ value_label = 0;
+}
+
+MetadataPtr
+NumberMetadataField::copy ()
+{
+ return MetadataPtr (new NumberMetadataField (getter, setter, _name, numbers, width));
+}
+
+void
+NumberMetadataField::save_data (ARDOUR::SessionMetadata & data) const
+{
+ uint32_t number = str_to_uint (_value);
+ CALL_MEMBER_FN (data, setter) (number);
+}
+
+void
+NumberMetadataField::load_data (ARDOUR::SessionMetadata const & data)
+{
+ uint32_t number = CALL_MEMBER_FN (data, getter) ();
+ _value = uint_to_str (number);
+ if (entry) {
+ entry->set_text (_value);
+ }
+}
+
+void
+NumberMetadataField::update_value ()
+{
+ // Accpt only numbers
+ uint32_t number = str_to_uint (entry->get_text());
+ _value = uint_to_str (number);
+ entry->set_text (_value);
+}
+
+Gtk::Widget &
+NumberMetadataField::name_widget ()
+{
+ label = Gtk::manage (new Gtk::Label(_name + ':', Gtk::ALIGN_LEFT));
+ return *label;
+}
+
+Gtk::Widget &
+NumberMetadataField::value_widget ()
+{
+ value_label = Gtk::manage (new Gtk::Label(_value));
+ return *value_label;
+}
+
+Gtk::Widget &
+NumberMetadataField::edit_widget ()
+{
+ entry = Gtk::manage (new Gtk::Entry());
+
+ entry->set_text (_value);
+ entry->set_width_chars (width);
+ entry->set_max_length (numbers);
+ entry->signal_changed().connect (sigc::mem_fun(*this, &NumberMetadataField::update_value));
+
+ return *entry;
+}
+
+ustring
+NumberMetadataField::uint_to_str (uint32_t i) const
+{
+ std::ostringstream oss ("");
+ oss << i;
+ if (oss.str().compare("0")) {
+ return oss.str();
+ } else {
+ return "";
+ }
+}
+
+uint32_t
+NumberMetadataField::str_to_uint (ustring const & str) const
+{
+ ustring tmp (str);
+ ustring::size_type i;
+ while ((i = tmp.find_first_not_of("1234567890")) != ustring::npos) {
+ tmp.erase (i, 1);
+ }
+
+ std::istringstream iss(tmp);
+ uint32_t result = 0;
+ iss >> result;
+ return result;
+}
+
+
+/* SessionMetadataSet */
+
+SessionMetadataSet::SessionMetadataSet (ustring const & name) :
+ name (name)
+{
+ session = 0;
+}
+
+void
+SessionMetadataSet::add_data_field (MetadataPtr field)
+{
+ list.push_back (field);
+}
+
+/* SessionMetadataSetEditable */
+
+SessionMetadataSetEditable::SessionMetadataSetEditable (ustring const & name) :
+ SessionMetadataSet (name)
+{
+ table.set_row_spacings (6);
+ table.set_col_spacings (12);
+}
+
+Gtk::Widget &
+SessionMetadataSetEditable::get_tab_widget ()
+{
+ tab_widget.set_text (name);
+ return tab_widget;
+}
+
+void
+SessionMetadataSetEditable::set_session (ARDOUR::Session * s)
+{
+ session = s;
+
+ ARDOUR::SessionMetadata const & data = session->metadata();
+
+ table.resize (list.size(), 2);
+ uint32_t row = 0;
+ MetadataPtr field;
+ for (DataList::const_iterator it = list.begin(); it != list.end(); ++it) {
+ field = *it;
+ field->load_data (data);
+ table.attach (field->name_widget(), 0, 1, row, row + 1);
+ table.attach (field->edit_widget(), 1, 2, row, row + 1);
+ ++row;
+ }
+}
+
+void
+SessionMetadataSetEditable::save_data ()
+{
+ ARDOUR::SessionMetadata & data = session->metadata();
+ for (DataList::const_iterator it = list.begin(); it != list.end(); ++it) {
+ (*it)->save_data(data);
+ }
+}
+
+/* SessionMetadataSetImportable */
+
+SessionMetadataSetImportable::SessionMetadataSetImportable (ustring const & name) :
+ SessionMetadataSet (name),
+ session_list (list)
+{
+ tree = Gtk::ListStore::create (tree_cols);
+ tree_view.set_model (tree);
+
+ Gtk::TreeView::Column * viewcol;
+
+ // Add import column
+ Gtk::CellRendererToggle * import_render = Gtk::manage(new Gtk::CellRendererToggle());
+ import_render->signal_toggled().connect (sigc::mem_fun(*this, &SessionMetadataSetImportable::selection_changed));
+ viewcol = Gtk::manage(new Gtk::TreeView::Column (_("Import"), *import_render));
+ viewcol->add_attribute (import_render->property_active(), tree_cols.import);
+ tree_view.append_column (*viewcol);
+
+ // Add field name column
+ tree_view.append_column(_("Field"), tree_cols.field);
+
+ // Add values column with pango markup
+ Gtk::CellRendererText * values_render = Gtk::manage(new Gtk::CellRendererText());
+ viewcol = Gtk::manage(new Gtk::TreeView::Column (_("Values (current value on top)"), *values_render));
+ viewcol->add_attribute (values_render->property_markup(), tree_cols.values);
+ tree_view.append_column (*viewcol);
+
+ select_all_check.signal_toggled().connect (sigc::mem_fun(*this, &SessionMetadataSetImportable::select_all));
+
+ session = 0;
+}
+
+Gtk::Widget &
+SessionMetadataSetImportable::get_tab_widget ()
+{
+ tab_widget.set_text (name);
+ return tab_widget;
+}
+
+Gtk::Widget &
+SessionMetadataSetImportable::get_select_all_widget ()
+{
+ select_all_check.set_label (name);
+ return select_all_check;
+}
+
+void
+SessionMetadataSetImportable::load_extra_data (ARDOUR::SessionMetadata const & data)
+{
+ if (!session) {
+ std::cerr << "Programming error: no session set for SessionMetaDataSetImportable (in load_data)!" << std::endl;
+ return;
+ }
+
+ ARDOUR::SessionMetadata & session_data = session->metadata();
+
+ MetadataPtr session_field;
+ MetadataPtr import_field;
+ DataList::iterator session_it;
+ DataList::iterator import_it;
+
+ // Copy list and load data to import
+ for (session_it = session_list.begin(); session_it != session_list.end(); ++session_it) {
+ session_field = *session_it;
+ session_field->load_data(session_data);
+ import_list.push_back (session_field->copy());
+ }
+
+ // Fill widget
+ session_it = session_list.begin();
+ import_it = import_list.begin();
+ while (session_it != session_list.end() && import_it != import_list.end()) { // _should_ be the same...
+ session_field = *session_it;
+ import_field = *import_it;
+
+ import_field->load_data(data); // hasn't been done yet
+
+ // Make string for values TODO get color from somewhere?
+ ustring values = "<span weight=\"ultralight\" color=\"#777\">" + session_field->value() + "</span>\n"
+ + "<span weight=\"bold\">" + import_field->value() + "</span>";
+
+ Gtk::TreeModel::iterator row_iter = tree->append();
+ Gtk::TreeModel::Row row = *row_iter;
+
+ row[tree_cols.field] = import_field->name();
+ row[tree_cols.values] = values;
+ row[tree_cols.import] = false;
+ row[tree_cols.data] = import_field;
+
+ ++session_it;
+ ++import_it;
+ }
+}
+
+void
+SessionMetadataSetImportable::save_data ()
+{
+ if (!session) {
+ std::cerr << "Programming error: no session set for SessionMetaDataSetImportable (in import_data)!" << std::endl;
+ return;
+ }
+
+ ARDOUR::SessionMetadata & session_data = session->metadata();
+
+ Gtk::TreeModel::Children fields = tree->children();
+ Gtk::TreeModel::Children::iterator it;
+ for (it = fields.begin(); it != fields.end(); ++it) {
+ if ((*it)[tree_cols.import]) {
+ MetadataPtr field = (*it)[tree_cols.data];
+ field->save_data (session_data);
+ }
+ }
+}
+
+void
+SessionMetadataSetImportable::select_all ()
+{
+ select_all_check.set_inconsistent (false);
+ bool state = select_all_check.get_active();
+
+ Gtk::TreeModel::Children fields = tree->children();
+ Gtk::TreeModel::Children::iterator it;
+ for (it = fields.begin(); it != fields.end(); ++it) {
+ (*it)[tree_cols.import] = state;
+ }
+}
+
+void
+SessionMetadataSetImportable::selection_changed (ustring const & path)
+{
+ select_all_check.set_inconsistent (true);
+
+ Gtk::TreeModel::iterator iter = tree->get_iter (path);
+ bool value((*iter)[tree_cols.import]);
+ (*iter)[tree_cols.import] = !value;
+}
+
+/* SessionMetadataDialog */
+
+template <typename DataSet>
+SessionMetadataDialog<DataSet>::SessionMetadataDialog (ustring const & name) :
+ ArdourDialog (name, true)
+{
+ cancel_button = add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
+ cancel_button->signal_clicked().connect (mem_fun(*this, &SessionMetadataDialog::end_dialog));
+ save_button = add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
+ save_button->signal_clicked().connect (mem_fun(*this, &SessionMetadataDialog::save_and_close));
+}
+
+template <typename DataSet>
+void
+SessionMetadataDialog<DataSet>::init_data ()
+{
+ if (!session) {
+ std::cerr << "Programming error: no session set for SessionMetaDataDialog (in init_data)!" << std::endl;
+ return;
+ }
+
+ init_track_data ();
+ init_album_data ();
+ init_people_data ();
+
+ for (DataSetList::iterator it = data_list.begin(); it != data_list.end(); ++it) {
+ (*it)->set_session (session);
+
+ notebook.append_page ((*it)->get_widget(), (*it)->get_tab_widget());
+ }
+}
+
+template <typename DataSet>
+void
+SessionMetadataDialog<DataSet>::load_extra_data (ARDOUR::SessionMetadata const & data)
+{
+ for (DataSetList::iterator it = data_list.begin(); it != data_list.end(); ++it) {
+ (*it)->load_extra_data (data);
+ }
+}
+
+template <typename DataSet>
+void
+SessionMetadataDialog<DataSet>::save_data ()
+{
+ for (DataSetList::iterator it = data_list.begin(); it != data_list.end(); ++it) {
+ (*it)->save_data ();
+ }
+}
+
+template <typename DataSet>
+void
+SessionMetadataDialog<DataSet>::save_and_close ()
+{
+ save_data ();
+ end_dialog ();
+}
+
+template <typename DataSet>
+void
+SessionMetadataDialog<DataSet>::end_dialog ()
+{
+ hide_all();
+}
+
+template <typename DataSet>
+void
+SessionMetadataDialog<DataSet>::warn_user (ustring const & string)
+{
+ Gtk::MessageDialog msg (string, false, Gtk::MESSAGE_WARNING, Gtk::BUTTONS_OK, true);
+ msg.run();
+}
+
+template <typename DataSet>
+boost::shared_ptr<std::list<Gtk::Widget *> >
+SessionMetadataDialog<DataSet>::get_custom_widgets (WidgetFunc f)
+{
+ WidgetListPtr list (new WidgetList);
+ for (DataSetList::iterator it = data_list.begin(); it != data_list.end(); ++it)
+ {
+ DataSet * set = dynamic_cast<DataSet *> (it->get());
+ list->push_back (& CALL_MEMBER_FN (*set, f) ());
+ }
+
+ return list;
+}
+
+template <typename DataSet>
+void
+SessionMetadataDialog<DataSet>::add_widget (Gtk::Widget & widget)
+{
+ get_vbox()->pack_start (widget, true, true, 0);
+}
+
+template <typename DataSet>
+void
+SessionMetadataDialog<DataSet>::init_track_data ()
+{
+ DataSetPtr data_set (new DataSet (_("Track")));
+ data_list.push_back (data_set);
+
+ MetadataPtr ptr;
+
+ ptr = MetadataPtr (new TextMetadataField (&ARDOUR::SessionMetadata::title, &ARDOUR::SessionMetadata::set_title, _("Title")));
+ data_set->add_data_field (ptr);
+
+ ptr = MetadataPtr (new NumberMetadataField (&ARDOUR::SessionMetadata::track_number, &ARDOUR::SessionMetadata::set_track_number, _("Track Number"), 3));
+ data_set->add_data_field (ptr);
+
+ ptr = MetadataPtr (new TextMetadataField (&ARDOUR::SessionMetadata::subtitle, &ARDOUR::SessionMetadata::set_subtitle, _("Subtitle")));
+ data_set->add_data_field (ptr);
+
+ ptr = MetadataPtr (new TextMetadataField (&ARDOUR::SessionMetadata::grouping, &ARDOUR::SessionMetadata::set_grouping, _("Grouping")));
+ data_set->add_data_field (ptr);
+
+ ptr = MetadataPtr (new TextMetadataField (&ARDOUR::SessionMetadata::artist, &ARDOUR::SessionMetadata::set_artist, _("Artist")));
+ data_set->add_data_field (ptr);
+
+ ptr = MetadataPtr (new TextMetadataField (&ARDOUR::SessionMetadata::genre, &ARDOUR::SessionMetadata::set_genre, _("Genre")));
+ data_set->add_data_field (ptr);
+
+ ptr = MetadataPtr (new TextMetadataField (&ARDOUR::SessionMetadata::comment, &ARDOUR::SessionMetadata::set_comment, _("Comment")));
+ data_set->add_data_field (ptr);
+
+ ptr = MetadataPtr (new TextMetadataField (&ARDOUR::SessionMetadata::copyright, &ARDOUR::SessionMetadata::set_copyright, _("Copyright")));
+ data_set->add_data_field (ptr);
+}
+
+template <typename DataSet>
+void
+SessionMetadataDialog<DataSet>::init_album_data ()
+{
+ DataSetPtr data_set (new DataSet (_("Album")));
+ data_list.push_back (data_set);
+
+ MetadataPtr ptr;
+
+ ptr = MetadataPtr (new TextMetadataField (&ARDOUR::SessionMetadata::album, &ARDOUR::SessionMetadata::set_album, _("Album")));
+ data_set->add_data_field (ptr);
+
+ ptr = MetadataPtr (new NumberMetadataField (&ARDOUR::SessionMetadata::year, &ARDOUR::SessionMetadata::set_year, _("Year"), 4));
+ data_set->add_data_field (ptr);
+
+ ptr = MetadataPtr (new TextMetadataField (&ARDOUR::SessionMetadata::album_artist, &ARDOUR::SessionMetadata::set_album_artist, _("Album Artist")));
+ data_set->add_data_field (ptr);
+
+ ptr = MetadataPtr (new NumberMetadataField (&ARDOUR::SessionMetadata::total_tracks, &ARDOUR::SessionMetadata::set_total_tracks, _("Total Tracks"), 3));
+ data_set->add_data_field (ptr);
+
+ ptr = MetadataPtr (new TextMetadataField (&ARDOUR::SessionMetadata::disc_subtitle, &ARDOUR::SessionMetadata::set_disc_subtitle, _("Disc Subtitle")));
+ data_set->add_data_field (ptr);
+
+ ptr = MetadataPtr (new NumberMetadataField (&ARDOUR::SessionMetadata::disc_number, &ARDOUR::SessionMetadata::set_disc_number, _("Disc Number"), 2));
+ data_set->add_data_field (ptr);
+
+ ptr = MetadataPtr (new NumberMetadataField (&ARDOUR::SessionMetadata::total_discs, &ARDOUR::SessionMetadata::set_total_discs, _("Total Discs"), 2));
+ data_set->add_data_field (ptr);
+
+ ptr = MetadataPtr (new TextMetadataField (&ARDOUR::SessionMetadata::compilation, &ARDOUR::SessionMetadata::set_compilation, _("Compilation")));
+ data_set->add_data_field (ptr);
+
+ ptr = MetadataPtr (new TextMetadataField (&ARDOUR::SessionMetadata::isrc, &ARDOUR::SessionMetadata::set_isrc, _("ISRC")));
+ data_set->add_data_field (ptr);
+}
+
+template <typename DataSet>
+void
+SessionMetadataDialog<DataSet>::init_people_data ()
+{
+ DataSetPtr data_set (new DataSet (_("People")));
+ data_list.push_back (data_set);
+
+ MetadataPtr ptr;
+
+ ptr = MetadataPtr (new TextMetadataField (&ARDOUR::SessionMetadata::lyricist, &ARDOUR::SessionMetadata::set_lyricist, _("Lyricist")));
+ data_set->add_data_field (ptr);
+
+ ptr = MetadataPtr (new TextMetadataField (&ARDOUR::SessionMetadata::composer, &ARDOUR::SessionMetadata::set_composer, _("Composer")));
+ data_set->add_data_field (ptr);
+
+ ptr = MetadataPtr (new TextMetadataField (&ARDOUR::SessionMetadata::conductor, &ARDOUR::SessionMetadata::set_conductor, _("Conductor")));
+ data_set->add_data_field (ptr);
+
+ ptr = MetadataPtr (new TextMetadataField (&ARDOUR::SessionMetadata::remixer, &ARDOUR::SessionMetadata::set_remixer, _("Remixer")));
+ data_set->add_data_field (ptr);
+
+ ptr = MetadataPtr (new TextMetadataField (&ARDOUR::SessionMetadata::arranger, &ARDOUR::SessionMetadata::set_arranger, _("Arranger")));
+ data_set->add_data_field (ptr);
+
+ ptr = MetadataPtr (new TextMetadataField (&ARDOUR::SessionMetadata::engineer, &ARDOUR::SessionMetadata::set_engineer, _("Engineer")));
+ data_set->add_data_field (ptr);
+
+ ptr = MetadataPtr (new TextMetadataField (&ARDOUR::SessionMetadata::producer, &ARDOUR::SessionMetadata::set_producer, _("Producer")));
+ data_set->add_data_field (ptr);
+
+ ptr = MetadataPtr (new TextMetadataField (&ARDOUR::SessionMetadata::dj_mixer, &ARDOUR::SessionMetadata::set_dj_mixer, _("DJ Mixer")));
+ data_set->add_data_field (ptr);
+
+ ptr = MetadataPtr (new TextMetadataField (&ARDOUR::SessionMetadata::mixer, &ARDOUR::SessionMetadata::set_mixer, _("Mixer")));
+ data_set->add_data_field (ptr);
+}
+
+/* SessionMetadataEditor */
+
+SessionMetadataEditor::SessionMetadataEditor () :
+ SessionMetadataDialog<SessionMetadataSetEditable> (_("Edit session metadata"))
+{
+
+}
+
+SessionMetadataEditor::~SessionMetadataEditor ()
+{
+ // Remove pages from notebook to get rid of gsignal runtime warnings
+ notebook.pages().clear();
+}
+
+void
+SessionMetadataEditor::run ()
+{
+ init_data ();
+ init_gui();
+
+ ArdourDialog::run();
+}
+
+void
+SessionMetadataEditor::init_gui ()
+{
+ add_widget (notebook);
+
+ show_all();
+}
+
+/* SessionMetadataImporter */
+
+SessionMetadataImporter::SessionMetadataImporter () :
+ SessionMetadataDialog<SessionMetadataSetImportable> (_("Import session metadata"))
+{
+
+}
+
+SessionMetadataImporter::~SessionMetadataImporter ()
+{
+ // Remove pages from notebook to get rid of gsignal runtime warnings
+ notebook.pages().clear();
+}
+
+void
+SessionMetadataImporter::run ()
+{
+ if (!session) {
+ std::cerr << "Programming error: no session set for SessionMetaDataImporter (in run)!" << std::endl;
+ return;
+ }
+
+ /* Open session file selector */
+
+ Gtk::FileChooserDialog session_selector(_("Choose session to import metadata from"), Gtk::FILE_CHOOSER_ACTION_OPEN);
+ session_selector.add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
+ session_selector.add_button (Gtk::Stock::OPEN, Gtk::RESPONSE_ACCEPT);
+ session_selector.set_default_response(Gtk::RESPONSE_ACCEPT);
+
+ Gtk::FileFilter session_filter;
+ session_filter.add_pattern ("*.ardour");
+ session_filter.set_name (_("Ardour sessions"));
+ session_selector.add_filter (session_filter);
+ session_selector.set_filter (session_filter);
+
+ int response = session_selector.run();
+ session_selector.hide ();
+
+ switch (response) {
+ case Gtk::RESPONSE_ACCEPT:
+ break;
+ default:
+ return;
+ }
+
+ string session_path = session_selector.get_filename();
+ string path, name;
+ bool isnew;
+
+ if (session_path.length() > 0) {
+ if (ARDOUR::find_session (session_path, path, name, isnew) != 0) {
+ return;
+ }
+ } else {
+ return;
+ }
+
+ /* We have a session: load the data and run dialog */
+
+ string filename = Glib::build_filename (path, name + ".ardour");
+ XMLTree session_tree;
+ if (!session_tree.read (filename)) {
+ warn_user (_("A proper ardour session file was not selected!"));
+ return;
+ }
+
+ XMLNode * node = session_tree.root()->child ("Metadata");
+
+ if (!node) {
+ warn_user (_("The session file didn't contain metadata!\nMaybe this is an old session format?"));
+ return;
+ }
+
+ ARDOUR::SessionMetadata data;
+ data.set_state (*node);
+
+ init_data ();
+ load_extra_data (data);
+ init_gui();
+
+ ArdourDialog::run();
+}
+
+void
+SessionMetadataImporter::init_gui ()
+{
+ // Select all from -widget
+ add_widget (selection_hbox);
+ selection_label.set_text (_("Import all from:"));
+ selection_hbox.pack_start (selection_label, false, false);
+
+ WidgetListPtr list = get_custom_widgets (&SessionMetadataSetImportable::get_select_all_widget);
+ for (WidgetList::iterator it = list->begin(); it != list->end(); ++it) {
+ selection_hbox.pack_start (**it, false, false, 6);
+ }
+
+ add_widget (notebook);
+
+ show_all();
+}
diff --git a/gtk2_ardour/session_metadata_dialog.h b/gtk2_ardour/session_metadata_dialog.h
new file mode 100644
index 0000000000..ffbb7a0930
--- /dev/null
+++ b/gtk2_ardour/session_metadata_dialog.h
@@ -0,0 +1,276 @@
+/*
+ Copyright (C) 2008 Paul Davis
+ Author: Sakari Bergen
+
+ 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.
+*/
+
+#ifndef __session_metadata_dialog_h__
+#define __session_metadata_dialog_h__
+
+#include "ardour_dialog.h"
+
+#include <gtkmm.h>
+#include <boost/shared_ptr.hpp>
+
+#include <string>
+#include <list>
+
+#include <ardour/session_metadata.h>
+
+using std::string;
+using Glib::ustring;
+
+class MetadataField;
+typedef boost::shared_ptr<MetadataField> MetadataPtr;
+
+/// Wraps a metadata field to be used in a GUI
+class MetadataField {
+ public:
+ MetadataField (ustring const & field_name);
+ virtual ~MetadataField();
+ virtual MetadataPtr copy () = 0;
+
+ virtual void save_data (ARDOUR::SessionMetadata & data) const = 0;
+ virtual void load_data (ARDOUR::SessionMetadata const & data) = 0;
+
+ virtual ustring name() { return _name; }
+ virtual ustring value() { return _value; }
+
+ /// Get widget containing name of field
+ virtual Gtk::Widget & name_widget () = 0;
+ /// Get label containing value of field
+ virtual Gtk::Widget & value_widget () = 0;
+ /// Get widget for editing value
+ virtual Gtk::Widget & edit_widget () = 0;
+ protected:
+ ustring _name;
+ ustring _value;
+};
+
+/// MetadataField that contains text
+class TextMetadataField : public MetadataField {
+ private:
+ typedef ustring (ARDOUR::SessionMetadata::*Getter) () const;
+ typedef void (ARDOUR::SessionMetadata::*Setter) (ustring const &);
+ public:
+ TextMetadataField (Getter getter, Setter setter, ustring const & field_name, guint width = 50);
+ MetadataPtr copy ();
+
+ void save_data (ARDOUR::SessionMetadata & data) const;
+ void load_data (ARDOUR::SessionMetadata const & data);
+
+ Gtk::Widget & name_widget ();
+ Gtk::Widget & value_widget ();
+ Gtk::Widget & edit_widget ();
+ private:
+ void update_value ();
+
+ Getter getter;
+ Setter setter;
+
+ Gtk::Label* label;
+ Gtk::Label* value_label;
+ Gtk::Entry* entry;
+
+ uint width;
+};
+
+/// MetadataField that accepts only numbers
+class NumberMetadataField : public MetadataField {
+ private:
+ typedef uint32_t (ARDOUR::SessionMetadata::*Getter) () const;
+ typedef void (ARDOUR::SessionMetadata::*Setter) (uint32_t);
+ public:
+ NumberMetadataField (Getter getter, Setter setter, ustring const & field_name, guint numbers, guint width = 50);
+ MetadataPtr copy ();
+
+ void save_data (ARDOUR::SessionMetadata & data) const;
+ void load_data (ARDOUR::SessionMetadata const & data);
+
+ Gtk::Widget & name_widget ();
+ Gtk::Widget & value_widget ();
+ Gtk::Widget & edit_widget ();
+ private:
+ void update_value ();
+ ustring uint_to_str (uint32_t i) const;
+ uint32_t str_to_uint (ustring const & str) const;
+
+ Getter getter;
+ Setter setter;
+
+ Gtk::Label* label;
+ Gtk::Label* value_label;
+ Gtk::Entry* entry;
+
+ guint numbers;
+ guint width;
+};
+
+/// Interface for MetadataFields
+class SessionMetadataSet {
+ public:
+ SessionMetadataSet (ustring const & name);
+ virtual ~SessionMetadataSet () {};
+
+ void add_data_field (MetadataPtr field);
+
+ /// Sets session, into which the data is eventually saved
+ virtual void set_session (ARDOUR::Session * s) { session = s; }
+ /// allows loading extra data into data sets (for importing etc.)
+ virtual void load_extra_data (ARDOUR::SessionMetadata const & data) { }
+ /// Saves data to session
+ virtual void save_data () = 0;
+
+ virtual Gtk::Widget & get_widget () = 0;
+ virtual Gtk::Widget & get_tab_widget () = 0;
+
+ protected:
+ typedef std::list<MetadataPtr> DataList;
+ DataList list;
+ ustring name;
+ ARDOUR::Session *session;
+};
+
+/// Contains MetadataFields for editing
+class SessionMetadataSetEditable : public SessionMetadataSet {
+ public:
+ SessionMetadataSetEditable (ustring const & name);
+
+ Gtk::Widget & get_widget () { return table; }
+ Gtk::Widget & get_tab_widget ();
+
+ /// Sets session and loads data
+ void set_session (ARDOUR::Session * s);
+ /// Saves from MetadataFields into data
+ void save_data ();
+
+ private:
+ Gtk::Table table;
+ Gtk::Label tab_widget;
+};
+
+/// Contains MetadataFields for importing
+class SessionMetadataSetImportable : public SessionMetadataSet {
+ public:
+ SessionMetadataSetImportable (ustring const & name);
+
+ Gtk::Widget & get_widget () { return tree_view; }
+ Gtk::Widget & get_tab_widget ();
+ Gtk::Widget & get_select_all_widget ();
+
+ /// Loads importable data from data
+ void load_extra_data (ARDOUR::SessionMetadata const & data);
+ /// Saves from importable data (see load_data) to session_data
+ void save_data ();
+
+ private:
+ DataList & session_list; // References MetadataSet::list
+ DataList import_list;
+
+ struct Columns : public Gtk::TreeModel::ColumnRecord
+ {
+ public:
+ Gtk::TreeModelColumn<ustring> field;
+ Gtk::TreeModelColumn<ustring> values;
+ Gtk::TreeModelColumn<bool> import;
+ Gtk::TreeModelColumn<MetadataPtr> data;
+
+ Columns() { add (field); add (values); add (import); add (data); }
+ };
+
+ Glib::RefPtr<Gtk::ListStore> tree;
+ Columns tree_cols;
+ Gtk::TreeView tree_view;
+
+ Gtk::Label tab_widget;
+ Gtk::CheckButton select_all_check;
+
+ void select_all ();
+ void selection_changed (ustring const & path);
+};
+
+/// Metadata dialog interface
+/**
+ * The DataSets are initalized in this class so that all
+ * Dialogs have the same sets of data in the same order.
+ */
+template <typename DataSet>
+class SessionMetadataDialog : public ArdourDialog
+{
+ public:
+ SessionMetadataDialog (ustring const & name);
+
+ protected:
+ void init_data ();
+ void load_extra_data (ARDOUR::SessionMetadata const & data);
+ void save_data ();
+
+ virtual void init_gui () = 0;
+ virtual void save_and_close ();
+ virtual void end_dialog ();
+
+ void warn_user (ustring const & string);
+
+ typedef std::list<Gtk::Widget *> WidgetList;
+ typedef boost::shared_ptr<WidgetList> WidgetListPtr;
+ typedef Gtk::Widget & (DataSet::*WidgetFunc) ();
+
+ /// Returns list of widgets gathered by calling f for each data set
+ WidgetListPtr get_custom_widgets (WidgetFunc f);
+
+ /// Adds a widget to the table (vertical stacking) with automatic spacing
+ void add_widget (Gtk::Widget & widget);
+
+ Gtk::Notebook notebook;
+
+ private:
+ void init_track_data ();
+ void init_album_data ();
+ void init_people_data ();
+
+ typedef boost::shared_ptr<SessionMetadataSet> DataSetPtr;
+ typedef std::list<DataSetPtr> DataSetList;
+ DataSetList data_list;
+
+ Gtk::Button * save_button;
+ Gtk::Button * cancel_button;
+};
+
+class SessionMetadataEditor : public SessionMetadataDialog<SessionMetadataSetEditable> {
+ public:
+ SessionMetadataEditor ();
+ ~SessionMetadataEditor ();
+ void run ();
+ private:
+ void init_gui ();
+};
+
+class SessionMetadataImporter : public SessionMetadataDialog<SessionMetadataSetImportable> {
+ public:
+ SessionMetadataImporter ();
+ ~SessionMetadataImporter ();
+ void run ();
+
+ private:
+ void init_gui ();
+
+ // Select all from -widget
+ Gtk::HBox selection_hbox;
+ Gtk::Label selection_label;
+
+};
+
+#endif
diff --git a/gtk2_ardour/time_axis_view.cc b/gtk2_ardour/time_axis_view.cc
index 511697cf72..f1d5eb1c67 100644
--- a/gtk2_ardour/time_axis_view.cc
+++ b/gtk2_ardour/time_axis_view.cc
@@ -1046,8 +1046,9 @@ TimeAxisView::compute_controls_size_info ()
Gtk::Table one_row_table (1, 8);
Button* buttons[5];
const int border_width = 2;
- const int extra_height = (2 * border_width) + 2 // 2 pixels for the controls frame
- + 10; // resizer button
+ const int extra_height = (2 * border_width)
+ + 2 // 2 pixels for the hseparator between TimeAxisView control areas
+ + 10; // resizer button (3 x 2 pixel elements + 2 x 2 pixel gaps)
window.add (one_row_table);
@@ -1087,9 +1088,11 @@ TimeAxisView::compute_controls_size_info ()
two_row_table.show_all ();
req = two_row_table.size_request ();
+ cerr << "Normal height is " << req.height << " + " << extra_height << endl;
+
// height required to show all normal buttons
- hNormal = req.height + extra_height;
+ hNormal = /*req.height*/ 48 + extra_height;
// these heights are all just larger than normal. no more
// elements are visible (yet).
@@ -1182,6 +1185,8 @@ TimeAxisView::covers_y_position (double y)
return 0;
}
+ cerr << name() << " check for " << y << " within " << y_position << " and + " << height << endl;
+
if (y_position <= y && y < (y_position + height)) {
return this;
}