summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gtk2_ardour/ardour_ui.cc95
-rw-r--r--gtk2_ardour/ardour_ui.h19
-rw-r--r--gtk2_ardour/ardour_ui2.cc3
-rw-r--r--gtk2_ardour/ardour_ui_dialogs.cc29
-rw-r--r--gtk2_ardour/ardour_ui_ed.cc119
-rw-r--r--gtk2_ardour/automation_time_axis.h4
-rw-r--r--gtk2_ardour/editor.cc34
-rw-r--r--gtk2_ardour/editor.h6
-rw-r--r--gtk2_ardour/editor_actions.cc4
-rw-r--r--gtk2_ardour/mixer_strip.cc13
-rw-r--r--gtk2_ardour/mixer_strip.h4
-rw-r--r--gtk2_ardour/processor_box.cc217
-rw-r--r--gtk2_ardour/processor_box.h38
-rw-r--r--gtk2_ardour/public_editor.h2
-rw-r--r--gtk2_ardour/route_time_axis.cc2
-rw-r--r--gtk2_ardour/selection.cc65
-rw-r--r--gtk2_ardour/selection.h3
-rwxr-xr-xgtk2_ardour/window_proxy.cc150
-rwxr-xr-xgtk2_ardour/window_proxy.h131
-rw-r--r--gtk2_ardour/wscript1
-rw-r--r--libs/ardour/ardour/processor.h4
-rw-r--r--libs/ardour/processor.cc1
22 files changed, 715 insertions, 229 deletions
diff --git a/gtk2_ardour/ardour_ui.cc b/gtk2_ardour/ardour_ui.cc
index f1120ccfca..837dfd9ba2 100644
--- a/gtk2_ardour/ardour_ui.cc
+++ b/gtk2_ardour/ardour_ui.cc
@@ -98,6 +98,9 @@ typedef uint64_t microseconds_t;
#include "engine_dialog.h"
#include "processor_box.h"
#include "time_axis_view_item.h"
+#include "window_proxy.h"
+#include "global_port_matrix.h"
+#include "location_ui.h"
#include "i18n.h"
@@ -164,7 +167,6 @@ ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[])
auditioning_alert_button (_("AUDITION")),
solo_alert_button (_("SOLO")),
- shown_flag (false),
error_log_button (_("Errors"))
{
@@ -290,6 +292,21 @@ ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[])
TimeAxisViewItem::set_constant_heights ();
+ /* The following must happen after ARDOUR::init() so that Config is set up */
+
+ location_ui = new ActionWindowProxy<LocationUIWindow> (X_("locations"), Config->extra_xml (X_("UI")), X_("ToggleLocations"));
+ big_clock_window = new ActionWindowProxy<Gtk::Window> (X_("bigclock"), Config->extra_xml (X_("UI")), X_("ToggleBigClock"));
+
+ for (ARDOUR::DataType::iterator i = ARDOUR::DataType::begin(); i != ARDOUR::DataType::end(); ++i) {
+ _global_port_matrix[*i] = new ActionWindowProxy<GlobalPortMatrixWindow> (
+ string_compose ("GlobalPortMatrix-%1", (*i).to_string()),
+ Config->extra_xml (X_("UI")),
+ string_compose ("toggle-%1-connection-manager", (*i).to_string())
+ );
+ }
+
+ setup_clock ();
+
starting.connect (sigc::mem_fun(*this, &ARDOUR_UI::startup));
stopping.connect (sigc::mem_fun(*this, &ARDOUR_UI::shutdown));
@@ -660,8 +677,16 @@ ARDOUR_UI::startup ()
goto_editor_window ();
+ /* Add the window proxies here; their addition may cause windows to be opened, and we want them
+ to be opened on top of the editor window that goto_editor_window() just opened.
+ */
+ add_window_proxy (location_ui);
+ add_window_proxy (big_clock_window);
+ for (ARDOUR::DataType::iterator i = ARDOUR::DataType::begin(); i != ARDOUR::DataType::end(); ++i) {
+ add_window_proxy (_global_port_matrix[*i]);
+ }
+
BootMessage (string_compose (_("%1 is ready for use"), PROGRAM_NAME));
- show ();
}
void
@@ -784,17 +809,22 @@ If you still wish to quit, please use the\n\n\
point_one_second_connection.disconnect ();
point_oh_five_second_connection.disconnect ();
point_zero_one_second_connection.disconnect();
-
- _session->set_clean ();
+ }
+
+ /* Save state before deleting the session, as that causes some
+ windows to be destroyed before their visible state can be
+ saved.
+ */
+ save_ardour_state ();
+
+ if (_session) {
// _session->set_deletion_in_progress ();
+ _session->set_clean ();
_session->remove_pending_capture_state ();
delete _session;
_session = 0;
}
- cerr << "Save before quit\n";
- save_ardour_state ();
-
ArdourDialog::close_all_dialogs ();
engine->stop (true);
quit ();
@@ -2571,7 +2601,6 @@ ARDOUR_UI::close_session()
}
goto_editor_window ();
- show ();
}
int
@@ -2726,20 +2755,6 @@ ARDOUR_UI::build_session (const Glib::ustring& path, const Glib::ustring& snap_n
}
void
-ARDOUR_UI::show ()
-{
- if (editor) {
- editor->show_window ();
-
- if (!shown_flag) {
- editor->present ();
- }
-
- shown_flag = true;
- }
-}
-
-void
ARDOUR_UI::launch_chat ()
{
#ifdef __APPLE__
@@ -3355,22 +3370,10 @@ ARDOUR_UI::reconnect_to_jack ()
void
ARDOUR_UI::use_config ()
{
-
XMLNode* node = Config->extra_xml (X_("TransportControllables"));
if (node) {
set_transport_controllable_state (*node);
}
-
- node = Config->extra_xml (X_("UI"));
-
- if (node) {
- const XMLProperty* prop = node->property (X_("show-big-clock"));
- Glib::RefPtr<Action> act = ActionManager::get_action (X_("Common"), X_("ToggleBigClock"));
- if (act) {
- Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
- tact->set_active (string_is_affirmative (prop->value()));
- }
- }
}
void
@@ -3388,7 +3391,7 @@ ARDOUR_UI::update_transport_clocks (nframes_t pos)
secondary_clock.set (pos);
}
- if (big_clock_window) {
+ if (big_clock_window->get()) {
big_clock.set (pos);
}
}
@@ -3414,7 +3417,7 @@ ARDOUR_UI::record_state_changed ()
{
ENSURE_GUI_THREAD (*this, &ARDOUR_UI::record_state_changed);
- if (!_session || !big_clock_window) {
+ if (!_session || !big_clock_window->get()) {
/* why bother - the clock isn't visible */
return;
}
@@ -3614,3 +3617,23 @@ ARDOUR_UI::toggle_translations ()
}
}
}
+
+/** Add a window proxy to our list, so that its state will be saved.
+ * This call also causes the window to be created and opened if its
+ * state was saved as `visible'.
+ */
+void
+ARDOUR_UI::add_window_proxy (WindowProxyBase* p)
+{
+ _window_proxies.push_back (p);
+ p->maybe_show ();
+}
+
+/** Remove a window proxy from our list. Must be called if a WindowProxy
+ * is deleted, to prevent hanging pointers.
+ */
+void
+ARDOUR_UI::remove_window_proxy (WindowProxyBase* p)
+{
+ _window_proxies.remove (p);
+}
diff --git a/gtk2_ardour/ardour_ui.h b/gtk2_ardour/ardour_ui.h
index cccc4ab5b0..bf9a88d29e 100644
--- a/gtk2_ardour/ardour_ui.h
+++ b/gtk2_ardour/ardour_ui.h
@@ -67,6 +67,7 @@
#include "ardour_dialog.h"
#include "editing.h"
#include "ui_config.h"
+#include "window_proxy.h"
class About;
class AddRouteDialog;
@@ -85,6 +86,8 @@ class SessionOptionEditor;
class Splash;
class ThemeManager;
class MidiTracer;
+class WindowProxyBase;
+class GlobalPortMatrixWindow;
namespace Gtkmm2ext {
class TearOff;
@@ -110,9 +113,6 @@ class ARDOUR_UI : public Gtkmm2ext::UI, public ARDOUR::SessionHandlePtr
bool run_startup (bool should_be_new, std::string load_template);
- void show ();
- bool shown() { return shown_flag; }
-
void show_splash ();
void hide_splash ();
@@ -233,6 +233,9 @@ class ARDOUR_UI : public Gtkmm2ext::UI, public ARDOUR::SessionHandlePtr
void set_shuttle_fract (double);
+ void add_window_proxy (WindowProxyBase *);
+ void remove_window_proxy (WindowProxyBase *);
+
protected:
friend class PublicEditor;
@@ -313,7 +316,7 @@ class ARDOUR_UI : public Gtkmm2ext::UI, public ARDOUR::SessionHandlePtr
void manage_window (Gtk::Window&);
AudioClock big_clock;
- Gtk::Window* big_clock_window;
+ ActionWindowProxy<Gtk::Window>* big_clock_window;
int original_big_clock_width;
int original_big_clock_height;
double original_big_clock_font_size;
@@ -588,10 +591,13 @@ class ARDOUR_UI : public Gtkmm2ext::UI, public ARDOUR::SessionHandlePtr
BundleManager *bundle_manager;
void create_bundle_manager ();
- LocationUIWindow *location_ui;
+ ActionWindowProxy<LocationUIWindow>* location_ui;
int create_location_ui ();
void handle_locations_change (ARDOUR::Location*);
+ ActionWindowProxy<GlobalPortMatrixWindow>* _global_port_matrix[ARDOUR::DataType::num_types];
+ void toggle_global_port_matrix (ARDOUR::DataType);
+
static UIConfiguration *ui_config;
ThemeManager *theme_manager;
@@ -625,7 +631,6 @@ class ARDOUR_UI : public Gtkmm2ext::UI, public ARDOUR::SessionHandlePtr
About* about;
Splash* splash;
void pop_back_splash ();
- bool shown_flag;
/* cleanup */
@@ -707,6 +712,8 @@ class ARDOUR_UI : public Gtkmm2ext::UI, public ARDOUR::SessionHandlePtr
*/
bool idle_finish ();
void queue_finish ();
+
+ std::list<WindowProxyBase*> _window_proxies;
};
#endif /* __ardour_gui_h__ */
diff --git a/gtk2_ardour/ardour_ui2.cc b/gtk2_ardour/ardour_ui2.cc
index 62b827d61a..65f165aa6e 100644
--- a/gtk2_ardour/ardour_ui2.cc
+++ b/gtk2_ardour/ardour_ui2.cc
@@ -46,6 +46,8 @@
#include "utils.h"
#include "theme_manager.h"
#include "midi_tracer.h"
+#include "global_port_matrix.h"
+#include "location_ui.h"
#include "i18n.h"
@@ -103,7 +105,6 @@ ARDOUR_UI::setup_windows ()
editor->add_toplevel_controls (top_packer);
- setup_clock ();
setup_transport();
build_menu_bar ();
diff --git a/gtk2_ardour/ardour_ui_dialogs.cc b/gtk2_ardour/ardour_ui_dialogs.cc
index 747354ca4e..6a0bbb0a7e 100644
--- a/gtk2_ardour/ardour_ui_dialogs.cc
+++ b/gtk2_ardour/ardour_ui_dialogs.cc
@@ -41,6 +41,7 @@
#include "gui_thread.h"
#include "midi_tracer.h"
#include "add_route_dialog.h"
+#include "global_port_matrix.h"
#include "i18n.h"
@@ -59,8 +60,8 @@ ARDOUR_UI::set_session (Session *s)
return;
}
- if (location_ui) {
- location_ui->set_session(s);
+ if (location_ui->get()) {
+ location_ui->get()->set_session(s);
}
if (route_params) {
@@ -75,6 +76,12 @@ ARDOUR_UI::set_session (Session *s)
session_option_editor->set_session (s);
}
+ for (ARDOUR::DataType::iterator i = ARDOUR::DataType::begin(); i != ARDOUR::DataType::end(); ++i) {
+ if (_global_port_matrix[*i]->get()) {
+ _global_port_matrix[*i]->get()->set_session (_session);
+ }
+ }
+
primary_clock.set_session (s);
secondary_clock.set_session (s);
big_clock.set_session (s);
@@ -217,10 +224,10 @@ ARDOUR_UI::toggle_big_clock_window ()
RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
if (tact->get_active()) {
- big_clock_window->show_all ();
- big_clock_window->present ();
+ big_clock_window->get()->show_all ();
+ big_clock_window->get()->present ();
} else {
- big_clock_window->hide ();
+ big_clock_window->get()->hide ();
}
}
}
@@ -297,9 +304,9 @@ int
ARDOUR_UI::create_location_ui ()
{
if (location_ui == 0) {
- location_ui = new LocationUIWindow ();
- location_ui->set_session (_session);
- location_ui->signal_unmap().connect (sigc::bind (sigc::ptr_fun(&ActionManager::uncheck_toggleaction), X_("<Actions>/Common/ToggleLocations")));
+ location_ui->set (new LocationUIWindow ());
+ location_ui->get()->set_session (_session);
+ location_ui->get()->signal_unmap().connect (sigc::bind (sigc::ptr_fun(&ActionManager::uncheck_toggleaction), X_("<Actions>/Common/ToggleLocations")));
}
return 0;
}
@@ -316,10 +323,10 @@ ARDOUR_UI::toggle_location_window ()
RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
if (tact->get_active()) {
- location_ui->show_all ();
- location_ui->present ();
+ location_ui->get()->show_all ();
+ location_ui->get()->present ();
} else {
- location_ui->hide ();
+ location_ui->get()->hide ();
}
}
}
diff --git a/gtk2_ardour/ardour_ui_ed.cc b/gtk2_ardour/ardour_ui_ed.cc
index efdbd13add..091d846c1b 100644
--- a/gtk2_ardour/ardour_ui_ed.cc
+++ b/gtk2_ardour/ardour_ui_ed.cc
@@ -47,6 +47,8 @@
#include "mixer_ui.h"
#include "startup.h"
#include "utils.h"
+#include "window_proxy.h"
+#include "global_port_matrix.h"
#include <gtkmm2ext/application.h>
@@ -68,7 +70,6 @@ using namespace Glib;
int
ARDOUR_UI::create_editor ()
-
{
try {
editor = new Editor ();
@@ -225,6 +226,10 @@ ARDOUR_UI::install_actions ()
ActionManager::session_sensitive_actions.push_back (act);
act = ActionManager::register_toggle_action (common_actions, X_("ToggleBigClock"), _("Big Clock"), sigc::mem_fun(*this, &ARDOUR_UI::toggle_big_clock_window));
ActionManager::session_sensitive_actions.push_back (act);
+ act = ActionManager::register_toggle_action (common_actions, X_("toggle-audio-connection-manager"), _("Audio Connection Manager"), sigc::bind (sigc::mem_fun(*this, &ARDOUR_UI::toggle_global_port_matrix), ARDOUR::DataType::AUDIO));
+ ActionManager::session_sensitive_actions.push_back (act);
+ act = ActionManager::register_toggle_action (common_actions, X_("toggle-midi-connection-manager"), _("MIDI Connection Manager"), sigc::bind (sigc::mem_fun(*this, &ARDOUR_UI::toggle_global_port_matrix), ARDOUR::DataType::MIDI));
+ ActionManager::session_sensitive_actions.push_back (act);
act = ActionManager::register_action (common_actions, X_("NewMIDITracer"), _("MIDI Tracer"), sigc::mem_fun(*this, &ARDOUR_UI::new_midi_tracer_window));
ActionManager::session_sensitive_actions.push_back (act);
ActionManager::register_action (common_actions, X_("About"), _("About"), sigc::mem_fun(*this, &ARDOUR_UI::show_about));
@@ -555,20 +560,20 @@ ARDOUR_UI::setup_clock ()
{
ARDOUR_UI::Clock.connect (sigc::bind (sigc::mem_fun (big_clock, &AudioClock::set), false));
- big_clock_window = new Window (WINDOW_TOPLEVEL);
+ big_clock_window->set (new Window (WINDOW_TOPLEVEL));
- big_clock_window->set_keep_above (true);
- big_clock_window->set_border_width (0);
- big_clock_window->add (big_clock);
+ big_clock_window->get()->set_keep_above (true);
+ big_clock_window->get()->set_border_width (0);
+ big_clock_window->get()->add (big_clock);
- big_clock_window->set_title (_("Big Clock"));
- big_clock_window->set_type_hint (Gdk::WINDOW_TYPE_HINT_UTILITY);
- big_clock_window->signal_realize().connect (sigc::mem_fun (*this, &ARDOUR_UI::big_clock_realized));
- big_clock_window->signal_unmap().connect (sigc::bind (sigc::ptr_fun(&ActionManager::uncheck_toggleaction), X_("<Actions>/Common/ToggleBigClock")));
- big_clock_window->signal_key_press_event().connect (sigc::bind (sigc::ptr_fun (relay_key_press), big_clock_window), false);
- big_clock_window->signal_size_allocate().connect (sigc::mem_fun (*this, &ARDOUR_UI::big_clock_size_allocate));
+ big_clock_window->get()->set_title (_("Big Clock"));
+ big_clock_window->get()->set_type_hint (Gdk::WINDOW_TYPE_HINT_UTILITY);
+ big_clock_window->get()->signal_realize().connect (sigc::mem_fun (*this, &ARDOUR_UI::big_clock_realized));
+ big_clock_window->get()->signal_unmap().connect (sigc::bind (sigc::ptr_fun(&ActionManager::uncheck_toggleaction), X_("<Actions>/Common/ToggleBigClock")));
+ big_clock_window->get()->signal_key_press_event().connect (sigc::bind (sigc::ptr_fun (relay_key_press), big_clock_window->get()), false);
+ big_clock_window->get()->signal_size_allocate().connect (sigc::mem_fun (*this, &ARDOUR_UI::big_clock_size_allocate));
- manage_window (*big_clock_window);
+ manage_window (*big_clock_window->get());
}
void
@@ -576,8 +581,8 @@ ARDOUR_UI::big_clock_realized ()
{
int x, y, w, d;
- set_decoration (big_clock_window, (Gdk::DECOR_BORDER|Gdk::DECOR_RESIZEH));
- big_clock_window->get_window()->get_geometry (x, y, w, big_clock_height, d);
+ set_decoration (big_clock_window->get(), (Gdk::DECOR_BORDER|Gdk::DECOR_RESIZEH));
+ big_clock_window->get()->get_window()->get_geometry (x, y, w, big_clock_height, d);
original_big_clock_height = big_clock_height;
original_big_clock_width = w;
@@ -588,45 +593,6 @@ ARDOUR_UI::big_clock_realized ()
if (!fd.get_size_is_absolute ()) {
original_big_clock_font_size /= PANGO_SCALE;
}
-
- /* we can't set the real size until we know the original one, with the UI rc-file-set font
- size, so do this here.
- */
-
- XMLNode* node = Config->extra_xml (X_("UI"));
-
- if (node) {
-
- const XMLProperty* prop;
- int w, h, x, y;
- int have_pos = 0;
-
- w = h = x = y = 0;
-
- if ((prop = node->property ("big-clock-x-size")) != 0) {
- w = atoi (prop->value());
- }
- if ((prop = node->property ("big-clock-y-size")) != 0) {
- h = atoi (prop->value());
- }
-
- if (w && h) {
- big_clock_window->set_default_size (w, h);
- }
-
- if ((prop = node->property ("big-clock-x-off")) != 0) {
- x = atoi (prop->value());
- have_pos++;
- }
- if ((prop = node->property ("big-clock-y-off")) != 0) {
- y = atoi (prop->value());
- have_pos++;
- }
-
- if (have_pos == 2) {
- big_clock_window->move (x, y);
- }
- }
}
void
@@ -634,9 +600,9 @@ ARDOUR_UI::float_big_clock (Gtk::Window* parent)
{
if (big_clock_window) {
if (parent) {
- big_clock_window->set_transient_for (*parent);
+ big_clock_window->get()->set_transient_for (*parent);
} else {
- gtk_window_set_transient_for (big_clock_window->gobj(), (GtkWindow*) 0);
+ gtk_window_set_transient_for (big_clock_window->get()->gobj(), (GtkWindow*) 0);
}
}
}
@@ -655,7 +621,7 @@ ARDOUR_UI::idle_big_clock_text_resizer (int win_w, int win_h)
{
big_clock_resize_in_progress = false;
- Glib::RefPtr<Gdk::Window> win = big_clock_window->get_window();
+ Glib::RefPtr<Gdk::Window> win = big_clock_window->get()->get_window();
Pango::FontDescription fd (big_clock.get_style()->get_font());
int current_size = fd.get_size ();
int x, y, w, h, d;
@@ -708,30 +674,11 @@ ARDOUR_UI::save_ardour_state ()
Config->add_extra_xml (get_transport_controllable_state());
XMLNode* window_node = new XMLNode (X_("UI"));
-
- window_node->add_property ("show-big-clock", (big_clock_window && big_clock_window->is_visible() ? "yes" : "no"));
-
- Glib::RefPtr<Gdk::Window> win;
-
- if (big_clock_window && (win = big_clock_window->get_window())) {
-
- int w, h;
- int xoff, yoff;
- char buf[32];
-
- win->get_size (w, h);
- win->get_position (xoff, yoff);
-
- snprintf (buf, sizeof (buf), "%d", w);
- window_node->add_property ("big-clock-x-size", buf);
- snprintf (buf, sizeof (buf), "%d", h);
- window_node->add_property ("big-clock-y-size", buf);
- snprintf (buf, sizeof (buf), "%d", xoff);
- window_node->add_property ("big-clock-x-off", buf);
- snprintf (buf, sizeof (buf), "%d", yoff);
- window_node->add_property ("big-clock-y-off", buf);
- }
+ for (list<WindowProxyBase*>::iterator i = _window_proxies.begin(); i != _window_proxies.end(); ++i) {
+ window_node->add_child_nocopy (*((*i)->get_state ()));
+ }
+
/* tearoffs */
XMLNode* tearoff_node = new XMLNode (X_("Tearoffs"));
@@ -778,3 +725,17 @@ ARDOUR_UI::save_ardour_state ()
Keyboard::save_keybindings ();
}
+void
+ARDOUR_UI::toggle_global_port_matrix (ARDOUR::DataType t)
+{
+ if (_global_port_matrix[t]->get() == 0) {
+ _global_port_matrix[t]->set (new GlobalPortMatrixWindow (_session, t));
+ }
+
+ if (_global_port_matrix[t]->get()->is_visible ()) {
+ _global_port_matrix[t]->get()->hide ();
+ } else {
+ _global_port_matrix[t]->get()->present ();
+ }
+}
+
diff --git a/gtk2_ardour/automation_time_axis.h b/gtk2_ardour/automation_time_axis.h
index 8daccf97eb..c4132269f1 100644
--- a/gtk2_ardour/automation_time_axis.h
+++ b/gtk2_ardour/automation_time_axis.h
@@ -107,6 +107,10 @@ class AutomationTimeAxisView : public TimeAxisView {
bool has_automation () const;
+ boost::shared_ptr<ARDOUR::Route> parent_route () {
+ return _route;
+ }
+
protected:
boost::shared_ptr<ARDOUR::Route> _route; ///< Parent route
boost::shared_ptr<ARDOUR::AutomationControl> _control; ///< Control
diff --git a/gtk2_ardour/editor.cc b/gtk2_ardour/editor.cc
index 097a7cf418..adfbf5293a 100644
--- a/gtk2_ardour/editor.cc
+++ b/gtk2_ardour/editor.cc
@@ -385,9 +385,6 @@ Editor::Editor ()
select_new_marker = false;
rhythm_ferret = 0;
_bundle_manager = 0;
- for (ARDOUR::DataType::iterator i = ARDOUR::DataType::begin(); i != ARDOUR::DataType::end(); ++i) {
- _global_port_matrix[*i] = 0;
- }
no_save_visual = false;
resize_idle_id = -1;
@@ -668,9 +665,6 @@ Editor::Editor ()
set_mouse_mode (MouseObject, true);
set_edit_point_preference (EditAtMouse, true);
- XMLNode* node = ARDOUR_UI::instance()->editor_settings();
- set_state (*node, Stateful::loading_state_version);
-
_playlist_selector = new PlaylistSelector();
_playlist_selector->signal_delete_event().connect (sigc::bind (sigc::ptr_fun (just_hide_it), static_cast<Window *> (_playlist_selector)));
@@ -1079,12 +1073,6 @@ Editor::set_session (Session *t)
sfbrowser->set_session (_session);
}
- for (ARDOUR::DataType::iterator i = ARDOUR::DataType::begin(); i != ARDOUR::DataType::end(); ++i) {
- if (_global_port_matrix[*i]) {
- _global_port_matrix[*i]->set_session (_session);
- }
- }
-
compute_fixed_ruler_scale ();
/* there are never any selected regions at startup */
@@ -2555,6 +2543,11 @@ Editor::set_state (const XMLNode& node, int /*version*/)
the_notebook.set_current_page (atoi (prop->value ()));
}
+ XMLNodeList children = node.children ();
+ for (XMLNodeList::const_iterator i = children.begin(); i != children.end(); ++i) {
+ selection->set_state (**i, Stateful::current_state_version);
+ }
+
return 0;
}
@@ -2641,6 +2634,8 @@ Editor::get_state ()
snprintf (buf, sizeof (buf), "%d", the_notebook.get_current_page ());
node->add_property (X_("editor-list-page"), buf);
+ node->add_child_nocopy (selection->get_state ());
+
return *node;
}
@@ -4906,16 +4901,6 @@ Editor::show_rhythm_ferret ()
}
void
-Editor::show_global_port_matrix (ARDOUR::DataType t)
-{
- if (_global_port_matrix[t] == 0) {
- _global_port_matrix[t] = new GlobalPortMatrixWindow (_session, t);
- }
-
- _global_port_matrix[t]->show ();
-}
-
-void
Editor::first_idle ()
{
MessageDialog* dialog = 0;
@@ -5200,12 +5185,13 @@ Editor::foreach_time_axis_view (sigc::slot<void,TimeAxisView&> theslot)
}
}
+/** Find a RouteTimeAxisView by the ID of its route */
RouteTimeAxisView*
-Editor::get_route_view_by_id (PBD::ID& id)
+Editor::get_route_view_by_route_id (PBD::ID& id) const
{
RouteTimeAxisView* v;
- for(TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
+ for (TrackViewList::const_iterator i = track_views.begin(); i != track_views.end(); ++i) {
if((v = dynamic_cast<RouteTimeAxisView*>(*i)) != 0) {
if(v->route()->id() == id) {
return v;
diff --git a/gtk2_ardour/editor.h b/gtk2_ardour/editor.h
index 45ef788d40..22f68c23ce 100644
--- a/gtk2_ardour/editor.h
+++ b/gtk2_ardour/editor.h
@@ -65,6 +65,7 @@
#include "editor_items.h"
#include "region_selection.h"
#include "canvas.h"
+#include "window_proxy.h"
namespace Gnome { namespace Canvas {
class NoEventText;
@@ -106,7 +107,6 @@ class BundleManager;
class ControlPoint;
class CrossfadeView;
class DragManager;
-class GlobalPortMatrixWindow;
class GroupedButtons;
class Marker;
class MidiRegionView;
@@ -213,7 +213,7 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD
void foreach_time_axis_view (sigc::slot<void,TimeAxisView&>);
void add_to_idle_resize (TimeAxisView*, int32_t);
- RouteTimeAxisView* get_route_view_by_id (PBD::ID& id);
+ RouteTimeAxisView* get_route_view_by_route_id (PBD::ID& id) const;
void consider_auditioning (boost::shared_ptr<ARDOUR::Region>);
void hide_a_region (boost::shared_ptr<ARDOUR::Region>);
@@ -413,7 +413,6 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD
void toggle_meter_updating();
void show_rhythm_ferret();
- void show_global_port_matrix (ARDOUR::DataType);
void goto_visual_state (uint32_t);
void save_visual_state (uint32_t);
@@ -2003,7 +2002,6 @@ public:
RhythmFerret* rhythm_ferret;
BundleManager* _bundle_manager;
- GlobalPortMatrixWindow* _global_port_matrix[ARDOUR::DataType::num_types];
void fit_tracks (TrackViewList &);
void fit_selected_tracks ();
diff --git a/gtk2_ardour/editor_actions.cc b/gtk2_ardour/editor_actions.cc
index 8c70c4d148..e8eeb4d572 100644
--- a/gtk2_ardour/editor_actions.cc
+++ b/gtk2_ardour/editor_actions.cc
@@ -542,10 +542,6 @@ Editor::register_actions ()
act = ActionManager::register_action (editor_actions, "toggle-rhythm-ferret", _("Rhythm Ferret..."), sigc::mem_fun(*this, &Editor::show_rhythm_ferret));
ActionManager::session_sensitive_actions.push_back (act);
ActionManager::region_selection_sensitive_actions.push_back (act);
- act = ActionManager::register_action (editor_actions, "toggle-audio-connection-manager", _("Audio Connection Manager"), sigc::bind (sigc::mem_fun (*this, &Editor::show_global_port_matrix), ARDOUR::DataType::AUDIO));
- ActionManager::session_sensitive_actions.push_back (act);
- act = ActionManager::register_action (editor_actions, "toggle-midi-connection-manager", _("MIDI Connection Manager"), sigc::bind (sigc::mem_fun (*this, &Editor::show_global_port_matrix), ARDOUR::DataType::MIDI));
- ActionManager::session_sensitive_actions.push_back (act);
act = ActionManager::register_action (editor_actions, "toggle-log-window", _("Log"),
sigc::mem_fun (ARDOUR_UI::instance(), &ARDOUR_UI::toggle_errors));
ActionManager::session_sensitive_actions.push_back (act);
diff --git a/gtk2_ardour/mixer_strip.cc b/gtk2_ardour/mixer_strip.cc
index ecd1b733be..4523ca524a 100644
--- a/gtk2_ardour/mixer_strip.cc
+++ b/gtk2_ardour/mixer_strip.cc
@@ -362,6 +362,8 @@ MixerStrip::set_route (boost::shared_ptr<Route> rt)
button_table.remove (*show_sends_button);
}
+ processor_box.set_route (rt);
+
RouteUI::set_route (rt);
/* map the current state */
@@ -377,8 +379,6 @@ MixerStrip::set_route (boost::shared_ptr<Route> rt)
revert_to_default_display ();
- processor_box.set_route (rt);
-
if (set_color_from_route()) {
set_color (unique_random_color());
}
@@ -1540,6 +1540,7 @@ MixerStrip::map_frozen ()
switch (at->freeze_state()) {
case AudioTrack::Frozen:
processor_box.set_sensitive (false);
+ hide_redirect_editors ();
break;
default:
processor_box.set_sensitive (true);
@@ -1547,8 +1548,6 @@ MixerStrip::map_frozen ()
break;
}
}
-
- hide_redirect_editors ();
}
void
@@ -1565,10 +1564,10 @@ MixerStrip::hide_processor_editor (boost::weak_ptr<Processor> p)
return;
}
- void* gui = processor->get_gui ();
+ Gtk::Window* w = processor_box.get_processor_ui (processor);
- if (gui) {
- static_cast<Gtk::Widget*>(gui)->hide ();
+ if (w) {
+ w->hide ();
}
}
diff --git a/gtk2_ardour/mixer_strip.h b/gtk2_ardour/mixer_strip.h
index 0d3878fc20..bbebbcaf15 100644
--- a/gtk2_ardour/mixer_strip.h
+++ b/gtk2_ardour/mixer_strip.h
@@ -99,6 +99,10 @@ class MixerStrip : public RouteUI, public Gtk::EventBox
void set_button_names ();
void show_send (boost::shared_ptr<ARDOUR::Send>);
+ bool mixer_owned () const {
+ return _mixer_owned;
+ }
+
sigc::signal<void> WidthChanged;
static sigc::signal<void,boost::shared_ptr<ARDOUR::Route> > SwitchIO;
diff --git a/gtk2_ardour/processor_box.cc b/gtk2_ardour/processor_box.cc
index cc322df13d..8840c773f9 100644
--- a/gtk2_ardour/processor_box.cc
+++ b/gtk2_ardour/processor_box.cc
@@ -393,28 +393,6 @@ ProcessorBox::set_width (Width w)
}
void
-ProcessorBox::remove_processor_gui (boost::shared_ptr<Processor> processor)
-{
- boost::shared_ptr<Send> send;
- boost::shared_ptr<Return> retrn;
- boost::shared_ptr<PortInsert> port_insert;
-
- if ((port_insert = boost::dynamic_pointer_cast<PortInsert> (processor)) != 0) {
- PortInsertUI *io_selector = reinterpret_cast<PortInsertUI *> (port_insert->get_gui());
- port_insert->set_gui (0);
- delete io_selector;
- } else if ((send = boost::dynamic_pointer_cast<Send> (processor)) != 0) {
- SendUIWindow *sui = reinterpret_cast<SendUIWindow*> (send->get_gui());
- send->set_gui (0);
- delete sui;
- } else if ((retrn = boost::dynamic_pointer_cast<Return> (processor)) != 0) {
- ReturnUIWindow *rui = reinterpret_cast<ReturnUIWindow*> (retrn->get_gui());
- retrn->set_gui (0);
- delete rui;
- }
-}
-
-void
ProcessorBox::build_send_action_menu ()
{
using namespace Menu_Helpers;
@@ -958,6 +936,73 @@ ProcessorBox::redisplay_processors ()
_route->foreach_processor (sigc::mem_fun (*this, &ProcessorBox::add_processor_to_display));
build_processor_tooltip (processor_eventbox, _("Inserts, sends & plugins:"));
+
+ _route->foreach_processor (sigc::mem_fun (*this, &ProcessorBox::maybe_add_processor_to_ui_list));
+
+ /* trim dead wood from the processor window proxy list */
+
+ list<ProcessorWindowProxy*>::iterator i = _processor_window_proxies.begin();
+ while (i != _processor_window_proxies.end()) {
+ list<ProcessorWindowProxy*>::iterator j = i;
+ ++j;
+
+ if (!(*i)->marked) {
+ ARDOUR_UI::instance()->remove_window_proxy (*i);
+ _processor_window_proxies.erase (i);
+ delete *i;
+ }
+
+ i = j;
+ }
+}
+
+/** Add a ProcessorWindowProxy for a processor to our list, if that processor does
+ * not already have one.
+ */
+void
+ProcessorBox::maybe_add_processor_to_ui_list (boost::weak_ptr<Processor> w)
+{
+ boost::shared_ptr<Processor> p = w.lock ();
+ if (!p) {
+ return;
+ }
+
+ list<ProcessorWindowProxy*>::iterator i = _processor_window_proxies.begin ();
+ while (i != _processor_window_proxies.end()) {
+
+ boost::shared_ptr<Processor> t = (*i)->processor().lock ();
+
+ if (p == t) {
+ /* this processor is already on the list; done */
+ (*i)->marked = true;
+ return;
+ }
+
+ ++i;
+ }
+
+ /* not on the list; add it */
+
+ string loc;
+ if (_parent_strip) {
+ if (_parent_strip->mixer_owned()) {
+ loc = X_("M");
+ } else {
+ loc = X_("R");
+ }
+ } else {
+ loc = X_("P");
+ }
+
+ ProcessorWindowProxy* wp = new ProcessorWindowProxy (
+ string_compose ("%1-%2-%3", loc, _route->id(), p->id()),
+ Config->extra_xml (X_("UI")),
+ this,
+ w);
+
+ wp->marked = true;
+ _processor_window_proxies.push_back (wp);
+ ARDOUR_UI::instance()->add_window_proxy (wp);
}
void
@@ -1102,10 +1147,10 @@ ProcessorBox::cut_processors (const ProcSelection& to_be_removed)
(boost::dynamic_pointer_cast<Send>((*i)) != 0) ||
(boost::dynamic_pointer_cast<Return>((*i)) != 0)) {
- void* gui = (*i)->get_gui ();
+ Window* w = get_processor_ui (*i);
- if (gui) {
- static_cast<Gtk::Widget*>(gui)->hide ();
+ if (w) {
+ w->hide ();
}
XMLNode& child ((*i)->get_state());
@@ -1174,10 +1219,10 @@ ProcessorBox::delete_processors (const ProcSelection& targets)
for (ProcSelection::const_iterator i = targets.begin(); i != targets.end(); ++i) {
- void* gui = (*i)->get_gui ();
+ Window* w = get_processor_ui (*i);
- if (gui) {
- static_cast<Gtk::Widget*>(gui)->hide ();
+ if (w) {
+ w->hide ();
}
_route->remove_processor(*i);
@@ -1195,10 +1240,10 @@ ProcessorBox::delete_dragged_processors (const list<boost::shared_ptr<Processor>
no_processor_redisplay = true;
for (x = procs.begin(); x != procs.end(); ++x) {
- void* gui = (*x)->get_gui ();
+ Window* w = get_processor_ui (*x);
- if (gui) {
- static_cast<Gtk::Widget*>(gui)->hide ();
+ if (w) {
+ w->hide ();
}
_route->remove_processor(*x);
@@ -1488,13 +1533,14 @@ ProcessorBox::edit_processor (boost::shared_ptr<Processor> processor)
#ifdef OLD_SEND_EDITING
SendUIWindow *send_ui;
- if (send->get_gui() == 0) {
+ Window* w = get_processor_ui (send);
+ if (w == 0) {
send_ui = new SendUIWindow (send, _session);
send_ui->set_title (send->name());
- send->set_gui (send_ui);
+ set_processor_ui (send, send_ui);
} else {
- send_ui = reinterpret_cast<SendUIWindow *> (send->get_gui());
+ send_ui = dynamic_cast<SendUIWindow *> (w);
}
gidget = send_ui;
@@ -1513,15 +1559,16 @@ ProcessorBox::edit_processor (boost::shared_ptr<Processor> processor)
boost::shared_ptr<Return> retrn = boost::dynamic_pointer_cast<Return> (processor);
ReturnUIWindow *return_ui;
+ Window* w = get_processor_ui (retrn);
- if (retrn->get_gui() == 0) {
+ if (w == 0) {
return_ui = new ReturnUIWindow (retrn, _session);
return_ui->set_title (retrn->name ());
- send->set_gui (return_ui);
+ set_processor_ui (send, return_ui);
} else {
- return_ui = reinterpret_cast<ReturnUIWindow *> (retrn->get_gui());
+ return_ui = dynamic_cast<ReturnUIWindow *> (w);
}
gidget = return_ui;
@@ -1535,14 +1582,16 @@ ProcessorBox::edit_processor (boost::shared_ptr<Processor> processor)
Container* toplevel = get_toplevel();
Window* win = dynamic_cast<Gtk::Window*>(toplevel);
- if (plugin_insert->get_gui() == 0) {
+ Window* w = get_processor_ui (plugin_insert);
+
+ if (w == 0) {
plugin_ui = new PluginUIWindow (win, plugin_insert);
plugin_ui->set_title (generate_processor_title (plugin_insert));
- plugin_insert->set_gui (plugin_ui);
+ set_processor_ui (plugin_insert, plugin_ui);
} else {
- plugin_ui = reinterpret_cast<PluginUIWindow *> (plugin_insert->get_gui());
+ plugin_ui = dynamic_cast<PluginUIWindow *> (w);
plugin_ui->set_parent (win);
}
@@ -1558,12 +1607,14 @@ ProcessorBox::edit_processor (boost::shared_ptr<Processor> processor)
PortInsertWindow *io_selector;
- if (port_insert->get_gui() == 0) {
+ Window* w = get_processor_ui (port_insert);
+
+ if (w == 0) {
io_selector = new PortInsertWindow (_session, port_insert);
- port_insert->set_gui (io_selector);
+ set_processor_ui (port_insert, io_selector);
} else {
- io_selector = reinterpret_cast<PortInsertWindow *> (port_insert->get_gui());
+ io_selector = dynamic_cast<PortInsertWindow *> (w);
}
gidget = io_selector;
@@ -1838,18 +1889,18 @@ ProcessorBox::route_property_changed (const PropertyChange& what_changed)
processor = (*iter)->processor ();
- void* gui = processor->get_gui();
+ Window* w = get_processor_ui (processor);
- if (!gui) {
+ if (!w) {
continue;
}
/* rename editor windows for sends and plugins */
if ((send = boost::dynamic_pointer_cast<Send> (processor)) != 0) {
- static_cast<Window*>(gui)->set_title (send->name ());
+ w->set_title (send->name ());
} else if ((plugin_insert = boost::dynamic_pointer_cast<PluginInsert> (processor)) != 0) {
- static_cast<Window*>(gui)->set_title (generate_processor_title (plugin_insert));
+ w->set_title (generate_processor_title (plugin_insert));
}
}
}
@@ -1882,3 +1933,75 @@ ProcessorBox::on_size_allocate (Allocation& a)
(*i)->set_pixel_width (a.get_width ());
}
}
+
+/** @param p Processor.
+ * @return the UI window for \a p.
+ */
+Window *
+ProcessorBox::get_processor_ui (boost::shared_ptr<Processor> p) const
+{
+ list<ProcessorWindowProxy*>::const_iterator i = _processor_window_proxies.begin ();
+ while (i != _processor_window_proxies.end()) {
+ boost::shared_ptr<Processor> t = (*i)->processor().lock ();
+ if (t && t == p) {
+ return (*i)->get ();
+ }
+
+ ++i;
+ }
+
+ /* we shouldn't get here, because the ProcessorUIList should always contain
+ an entry for each processor.
+ */
+ assert (false);
+}
+
+/** Make a note of the UI window that a processor is using.
+ * @param p Processor.
+ * @param w UI window.
+ */
+void
+ProcessorBox::set_processor_ui (boost::shared_ptr<Processor> p, Gtk::Window* w)
+{
+ list<ProcessorWindowProxy*>::iterator i = _processor_window_proxies.begin ();
+ while (i != _processor_window_proxies.end()) {
+ boost::shared_ptr<Processor> t = (*i)->processor().lock ();
+ if (t && t == p) {
+ (*i)->set (w);
+ return;
+ }
+
+ ++i;
+ }
+
+ /* we shouldn't get here, because the ProcessorUIList should always contain
+ an entry for each processor.
+ */
+ assert (false);
+}
+
+ProcessorWindowProxy::ProcessorWindowProxy (
+ string const & name,
+ XMLNode const * node,
+ ProcessorBox* box,
+ boost::weak_ptr<Processor> processor
+ )
+ : WindowProxy<Gtk::Window> (name, node)
+ , marked (false)
+ , _processor_box (box)
+ , _processor (processor)
+{
+
+}
+
+
+void
+ProcessorWindowProxy::show ()
+{
+ boost::shared_ptr<Processor> p = _processor.lock ();
+ if (!p) {
+ return;
+ }
+
+ _processor_box->edit_processor (p);
+}
diff --git a/gtk2_ardour/processor_box.h b/gtk2_ardour/processor_box.h
index 1e4257d22b..9273a75052 100644
--- a/gtk2_ardour/processor_box.h
+++ b/gtk2_ardour/processor_box.h
@@ -52,6 +52,7 @@
#include "io_selector.h"
#include "send_ui.h"
#include "enums.h"
+#include "window_proxy.h"
class MotionController;
class PluginSelector;
@@ -71,6 +72,29 @@ namespace ARDOUR {
class Session;
}
+class ProcessorBox;
+
+/** A WindowProxy for Processor UI windows; it knows how to ask a ProcessorBox
+ * to create a UI window for a particular processor.
+ */
+class ProcessorWindowProxy : public WindowProxy<Gtk::Window>
+{
+public:
+ ProcessorWindowProxy (std::string const &, XMLNode const *, ProcessorBox *, boost::weak_ptr<ARDOUR::Processor>);
+
+ void show ();
+
+ boost::weak_ptr<ARDOUR::Processor> processor () const {
+ return _processor;
+ }
+
+ bool marked;
+
+private:
+ ProcessorBox* _processor_box;
+ boost::weak_ptr<ARDOUR::Processor> _processor;
+};
+
class ProcessorEntry : public Gtkmm2ext::DnDVBoxChild, public sigc::trackable
{
public:
@@ -145,12 +169,19 @@ class ProcessorBox : public Gtk::HBox, public PluginInterestedObject, public ARD
void select_all_inserts ();
void select_all_sends ();
+ Gtk::Window* get_processor_ui (boost::shared_ptr<ARDOUR::Processor>) const;
+ void edit_processor (boost::shared_ptr<ARDOUR::Processor>);
+
sigc::signal<void,boost::shared_ptr<ARDOUR::Processor> > ProcessorSelected;
sigc::signal<void,boost::shared_ptr<ARDOUR::Processor> > ProcessorUnselected;
static void register_actions();
private:
+
+ /* prevent copy construction */
+ ProcessorBox (ProcessorBox const &);
+
boost::shared_ptr<ARDOUR::Route> _route;
MixerStrip* _parent_strip; // null if in RouteParamsUI
bool _owner_is_mixer;
@@ -212,8 +243,6 @@ class ProcessorBox : public Gtk::HBox, public PluginInterestedObject, public ARD
void reordered ();
void route_processors_changed (ARDOUR::RouteProcessorChange);
- void remove_processor_gui (boost::shared_ptr<ARDOUR::Processor>);
-
void processors_reordered (const Gtk::TreeModel::Path&, const Gtk::TreeModel::iterator&, int*);
void compute_processor_sort_keys ();
@@ -249,7 +278,6 @@ class ProcessorBox : public Gtk::HBox, public PluginInterestedObject, public ARD
void activate_processor (boost::shared_ptr<ARDOUR::Processor>);
void deactivate_processor (boost::shared_ptr<ARDOUR::Processor>);
- void edit_processor (boost::shared_ptr<ARDOUR::Processor>);
void hide_processor_editor (boost::shared_ptr<ARDOUR::Processor>);
void rename_processor (boost::shared_ptr<ARDOUR::Processor>);
@@ -281,6 +309,10 @@ class ProcessorBox : public Gtk::HBox, public PluginInterestedObject, public ARD
void route_property_changed (const PBD::PropertyChange&);
std::string generate_processor_title (boost::shared_ptr<ARDOUR::PluginInsert> pi);
+
+ std::list<ProcessorWindowProxy*> _processor_window_proxies;
+ void set_processor_ui (boost::shared_ptr<ARDOUR::Processor>, Gtk::Window *);
+ void maybe_add_processor_to_ui_list (boost::weak_ptr<ARDOUR::Processor>);
};
#endif /* __ardour_gtk_processor_box__ */
diff --git a/gtk2_ardour/public_editor.h b/gtk2_ardour/public_editor.h
index ea9ef9dfad..6bf897bcd3 100644
--- a/gtk2_ardour/public_editor.h
+++ b/gtk2_ardour/public_editor.h
@@ -274,7 +274,7 @@ class PublicEditor : public Gtk::Window, public PBD::StatefulDestructible {
virtual TimeAxisView* get_named_time_axis(const std::string & name) = 0;
#endif
- virtual RouteTimeAxisView* get_route_view_by_id (PBD::ID& id) = 0;
+ virtual RouteTimeAxisView* get_route_view_by_route_id (PBD::ID& id) const = 0;
virtual void get_equivalent_regions (RegionView* rv, std::vector<RegionView*>&, PBD::PropertyID) const = 0;
diff --git a/gtk2_ardour/route_time_axis.cc b/gtk2_ardour/route_time_axis.cc
index e44c62949b..c62ea68b2a 100644
--- a/gtk2_ardour/route_time_axis.cc
+++ b/gtk2_ardour/route_time_axis.cc
@@ -2275,7 +2275,7 @@ RouteTimeAxisView::set_underlay_state()
if (prop) {
PBD::ID id (prop->value());
- RouteTimeAxisView* v = _editor.get_route_view_by_id (id);
+ RouteTimeAxisView* v = _editor.get_route_view_by_route_id (id);
if (v) {
add_underlay(v->view(), false);
diff --git a/gtk2_ardour/selection.cc b/gtk2_ardour/selection.cc
index 786749ce72..c9d12f0694 100644
--- a/gtk2_ardour/selection.cc
+++ b/gtk2_ardour/selection.cc
@@ -1075,3 +1075,68 @@ Selection::set_point_selection_from_line (AutomationLine const & line)
PointsChanged (); /* EMIT SIGNAL */
}
+
+XMLNode&
+Selection::get_state () const
+{
+ /* XXX: not complete; just sufficient to get track selection state
+ so that re-opening plugin windows for editor mixer strips works
+ */
+
+ XMLNode* node = new XMLNode (X_("Selection"));
+
+ for (TrackSelection::const_iterator i = tracks.begin(); i != tracks.end(); ++i) {
+ RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (*i);
+ AutomationTimeAxisView* atv = dynamic_cast<AutomationTimeAxisView*> (*i);
+ if (rtv) {
+ XMLNode* t = node->add_child (X_("RouteView"));
+ t->add_property (X_("id"), atoi (rtv->route()->id().to_s().c_str()));
+ } else if (atv) {
+ XMLNode* t = node->add_child (X_("AutomationView"));
+ t->add_property (X_("id"), atoi (atv->parent_route()->id().to_s().c_str()));
+ t->add_property (X_("parameter"), EventTypeMap::instance().to_symbol (atv->control()->parameter ()));
+ }
+ }
+
+ return *node;
+}
+
+int
+Selection::set_state (XMLNode const & node, int)
+{
+ if (node.name() != X_("Selection")) {
+ return -1;
+ }
+
+ XMLNodeList children = node.children ();
+ for (XMLNodeList::const_iterator i = children.begin(); i != children.end(); ++i) {
+ if ((*i)->name() == X_("RouteView")) {
+
+ XMLProperty* prop_id = (*i)->property (X_("id"));
+ assert (prop_id);
+ PBD::ID id (prop_id->value ());
+ RouteTimeAxisView* rtv = editor->get_route_view_by_route_id (id);
+ assert (rtv);
+ add (rtv);
+
+ } else if ((*i)->name() == X_("AutomationView")) {
+
+ XMLProperty* prop_id = (*i)->property (X_("id"));
+ XMLProperty* prop_parameter = (*i)->property (X_("parameter"));
+
+ assert (prop_id);
+ assert (prop_parameter);
+
+ PBD::ID id (prop_id->value ());
+ RouteTimeAxisView* rtv = editor->get_route_view_by_route_id (id);
+ assert (rtv);
+
+ boost::shared_ptr<AutomationTimeAxisView> atv = rtv->automation_child (EventTypeMap::instance().new_parameter (prop_parameter->value ()));
+ assert (atv);
+
+ add (atv.get());
+ }
+ }
+
+ return 0;
+}
diff --git a/gtk2_ardour/selection.h b/gtk2_ardour/selection.h
index e81e1bdea8..81bb54b9df 100644
--- a/gtk2_ardour/selection.h
+++ b/gtk2_ardour/selection.h
@@ -191,6 +191,9 @@ class Selection : public sigc::trackable, public PBD::ScopedConnectionList
void foreach_midi_regionview (void (MidiRegionView::*method)(void));
template<class A> void foreach_region (void (ARDOUR::Region::*method)(A), A arg);
+ XMLNode& get_state () const;
+ int set_state (XMLNode const &, int);
+
private:
void set_point_selection_from_line (AutomationLine const &);
diff --git a/gtk2_ardour/window_proxy.cc b/gtk2_ardour/window_proxy.cc
new file mode 100755
index 0000000000..28a90215af
--- /dev/null
+++ b/gtk2_ardour/window_proxy.cc
@@ -0,0 +1,150 @@
+/*
+ Copyright (C) 2010 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include <gtkmm/window.h>
+#include "window_proxy.h"
+
+using namespace std;
+
+/** WindowProxyBase constructor.
+ * @param name Unique internal name for this window.
+ * @param node <UI> node containing <Window> children, the appropriate one of which is used
+ * to set up this object.
+ */
+WindowProxyBase::WindowProxyBase (string const & name, XMLNode const * node)
+ : _name (name)
+ , _visible (false)
+ , _x_off (-1)
+ , _y_off (-1)
+ , _width (-1)
+ , _height (-1)
+{
+ XMLNodeList children = node->children ();
+
+ XMLNodeList::const_iterator i = children.begin ();
+ while (i != children.end()) {
+ XMLProperty* prop = (*i)->property (X_("name"));
+ if ((*i)->name() == X_("Window") && prop && prop->value() == _name) {
+ break;
+ }
+
+ ++i;
+ }
+
+ if (i != children.end()) {
+
+ XMLProperty* prop;
+
+ if ((prop = (*i)->property (X_("visible"))) != 0) {
+ _visible = string_is_affirmative (prop->value ());
+ }
+
+ if ((prop = (*i)->property (X_("x-off"))) != 0) {
+ _x_off = atoi (prop->value().c_str());
+ }
+ if ((prop = (*i)->property (X_("y-off"))) != 0) {
+ _y_off = atoi (prop->value().c_str());
+ }
+ if ((prop = (*i)->property (X_("x-size"))) != 0) {
+ _width = atoi (prop->value().c_str());
+ }
+ if ((prop = (*i)->property (X_("y-size"))) != 0) {
+ _height = atoi (prop->value().c_str());
+ }
+ }
+}
+
+/** Show this window if it was configured as visible. This should
+ * be called at session startup only.
+ */
+void
+WindowProxyBase::maybe_show ()
+{
+ if (_visible) {
+ show ();
+ setup ();
+ }
+}
+
+/** Set up our window's position and size */
+void
+WindowProxyBase::setup ()
+{
+ Gtk::Window* window = get_gtk_window ();
+ if (!window) {
+ return;
+ }
+
+ if (_width != -1 && _height != -1) {
+ window->set_default_size (_width, _height);
+ }
+
+ if (_x_off != -1 && _y_off != -1) {
+ window->move (_x_off, _y_off);
+ }
+}
+
+XMLNode *
+WindowProxyBase::get_state () const
+{
+ bool v = _visible;
+ int x = _x_off;
+ int y = _y_off;
+ int w = _width;
+ int h = _height;
+
+ /* If the window has been created, get its current state; otherwise use
+ the state that we started off with.
+ */
+
+ Gtk::Window* gtk_window = get_gtk_window ();
+ if (gtk_window) {
+ v = gtk_window->is_visible ();
+
+ Glib::RefPtr<Gdk::Window> gdk_window = gtk_window->get_window ();
+ if (gdk_window) {
+ gdk_window->get_position (x, y);
+ gdk_window->get_size (w, h);
+ }
+
+ }
+
+ return state_node (v, x, y, w, h);
+}
+
+
+XMLNode *
+WindowProxyBase::state_node (bool v, int x, int y, int w, int h) const
+{
+ XMLNode* node = new XMLNode (X_("Window"));
+ node->add_property (X_("name"), _name);
+ node->add_property (X_("visible"), v ? X_("yes") : X_("no"));
+
+ char buf[32];
+ snprintf (buf, sizeof (buf), "%d", x);
+ node->add_property (X_("x-off"), buf);
+ snprintf (buf, sizeof (buf), "%d", y);
+ node->add_property (X_("y-off"), buf);
+ snprintf (buf, sizeof (buf), "%d", w);
+ node->add_property (X_("x-size"), buf);
+ snprintf (buf, sizeof (buf), "%d", h);
+ node->add_property (X_("y-size"), buf);
+
+ return node;
+}
diff --git a/gtk2_ardour/window_proxy.h b/gtk2_ardour/window_proxy.h
new file mode 100755
index 0000000000..e2b015c27b
--- /dev/null
+++ b/gtk2_ardour/window_proxy.h
@@ -0,0 +1,131 @@
+/*
+ Copyright (C) 2010 Paul Davis
+
+ 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 __ardour_window_proxy_h__
+#define __ardour_window_proxy_h__
+
+#include <gtkmm/action.h>
+#include <gtkmm/toggleaction.h>
+#include "actions.h"
+
+class XMLNode;
+
+/** A class to proxy for a window that may not have been created yet.
+ * It allows the management of visibility, position and size state
+ * so that it can be saved and restored across session loads.
+ *
+ * Subclasses of WindowProxy handle windows that are created in different
+ * ways.
+ */
+
+class WindowProxyBase
+{
+public:
+ WindowProxyBase (std::string const &, XMLNode const *);
+ virtual ~WindowProxyBase () {}
+
+ std::string name () const {
+ return _name;
+ }
+
+ void maybe_show ();
+ XMLNode* get_state () const;
+ void setup ();
+
+ /** Show this window */
+ virtual void show () = 0;
+
+ virtual Gtk::Window* get_gtk_window () const = 0;
+
+private:
+ XMLNode* state_node (bool, int, int, int, int) const;
+
+ std::string _name; ///< internal unique name for this window
+ bool _visible; ///< true if the window should be visible on startup
+ int _x_off; ///< x position
+ int _y_off; ///< y position
+ int _width; ///< width
+ int _height; ///< height
+};
+
+/** Templated WindowProxy which contains a pointer to the window that is proxying for */
+template <class T>
+class WindowProxy : public WindowProxyBase
+{
+public:
+ WindowProxy (std::string const & name, XMLNode const * node)
+ : WindowProxyBase (name, node)
+ , _window (0)
+ {
+
+ }
+
+ Gtk::Window* get_gtk_window () const {
+ return _window;
+ }
+
+ T* get () const {
+ return _window;
+ }
+
+ /** Set the window and set it up. To be used after initial window creation */
+ void set (T* w) {
+ _window = w;
+ setup ();
+ }
+
+private:
+ T* _window;
+};
+
+/** WindowProxy for windows that are created in response to a GTK Action being set active.
+ * Templated on the type of the window.
+ */
+template <class T>
+class ActionWindowProxy : public WindowProxy<T>
+{
+public:
+ /** ActionWindowProxy constructor.
+ * @param name Unique internal name for this window.
+ * @param node <UI> node containing <Window> children, the appropriate one of which is used
+ * to set up this object.
+ * @param action Name of the ToggleAction that controls this window's visibility.
+ */
+ ActionWindowProxy (std::string const & name, XMLNode const * node, std::string const & action)
+ : WindowProxy<T> (name, node)
+ , _action (action)
+ {
+
+ }
+
+ void show () {
+ /* Set the appropriate action active so that the window gets shown */
+ Glib::RefPtr<Gtk::Action> act = ActionManager::get_action ("Common", _action.c_str());
+ if (act) {
+ Glib::RefPtr<Gtk::ToggleAction> tact = Glib::RefPtr<Gtk::ToggleAction>::cast_dynamic (act);
+ assert (tact);
+ tact->set_active (true);
+ }
+ }
+
+private:
+ std::string _action;
+};
+
+#endif
diff --git a/gtk2_ardour/wscript b/gtk2_ardour/wscript
index d87e31a604..4b24082d47 100644
--- a/gtk2_ardour/wscript
+++ b/gtk2_ardour/wscript
@@ -209,6 +209,7 @@ gtk2_ardour_sources = [
'version.cc',
'volume_controller.cc',
'waveview.cc',
+ 'window_proxy.cc'
]
def set_options(opt):
diff --git a/libs/ardour/ardour/processor.h b/libs/ardour/ardour/processor.h
index e95bd57adf..1e65bc58bd 100644
--- a/libs/ardour/ardour/processor.h
+++ b/libs/ardour/ardour/processor.h
@@ -95,9 +95,6 @@ class Processor : public SessionObject, public Automatable, public Latent
XMLNode& get_state (void);
int set_state (const XMLNode&, int version);
- void *get_gui () const { return _gui; }
- void set_gui (void *p) { _gui = p; }
-
void set_pre_fader (bool);
PBD::Signal0<void> ActiveChanged;
@@ -110,7 +107,6 @@ protected:
bool _configured;
ChanCount _configured_input;
ChanCount _configured_output;
- void* _gui; /* generic, we don't know or care what this is */
bool _display_to_user;
bool _pre_fader;
diff --git a/libs/ardour/processor.cc b/libs/ardour/processor.cc
index c75a7720e0..0bea376fc9 100644
--- a/libs/ardour/processor.cc
+++ b/libs/ardour/processor.cc
@@ -66,7 +66,6 @@ Processor::Processor(Session& session, const string& name)
, _active(false)
, _next_ab_is_active(false)
, _configured(false)
- , _gui(0)
, _display_to_user (true)
, _pre_fader (false)
{