summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2008-01-19 03:49:52 +0000
committerDavid Robillard <d@drobilla.net>2008-01-19 03:49:52 +0000
commit4ca1fe7993adf63ea3f35958f63dd20ee546e7ae (patch)
treef773e6cf00e08a8260c2e2b28b8e16e28b39b887
parentf80fad313a21228f31201279cccaf555796c7eec (diff)
Merge with trunk R2935.
git-svn-id: svn://localhost/ardour2/branches/3.0@2943 d708f5d6-7413-0410-9779-e7cbd77b26cf
-rw-r--r--SConstruct16
-rw-r--r--gtk2_ardour/SConscript22
-rw-r--r--gtk2_ardour/about.cc4
-rw-r--r--gtk2_ardour/ardour3_ui_default.conf3
-rw-r--r--gtk2_ardour/ardour_ui.cc662
-rw-r--r--gtk2_ardour/ardour_ui.h13
-rw-r--r--gtk2_ardour/ardour_ui_dependents.cc3
-rw-r--r--gtk2_ardour/ardour_ui_ed.cc11
-rw-r--r--gtk2_ardour/audio_region_view.cc1
-rw-r--r--gtk2_ardour/canvas-waveview.c482
-rw-r--r--gtk2_ardour/canvas-waveview.h6
-rw-r--r--gtk2_ardour/canvas_vars.h1
-rw-r--r--gtk2_ardour/editor.cc8
-rw-r--r--gtk2_ardour/editor.h7
-rw-r--r--gtk2_ardour/editor_actions.cc8
-rw-r--r--gtk2_ardour/editor_ops.cc35
-rw-r--r--gtk2_ardour/main.cc27
-rw-r--r--gtk2_ardour/new_session_dialog.cc7
-rw-r--r--gtk2_ardour/plugin_selector.cc9
-rw-r--r--gtk2_ardour/plugin_selector.h1
-rw-r--r--gtk2_ardour/route_time_axis.cc8
-rw-r--r--gtk2_ardour/splash.cc60
-rw-r--r--gtk2_ardour/splash.h41
-rw-r--r--gtk2_ardour/time_axis_view.cc4
-rw-r--r--gtk2_ardour/waveview.cc24
-rw-r--r--gtk2_ardour/waveview.h8
-rw-r--r--libs/ardour/SConscript8
-rw-r--r--libs/ardour/ardour/audio_unit.h6
-rw-r--r--libs/ardour/ardour/io.h6
-rw-r--r--libs/ardour/ardour/ladspa_plugin.h16
-rw-r--r--libs/ardour/ardour/lv2_plugin.h138
-rw-r--r--libs/ardour/ardour/plugin_manager.h19
-rw-r--r--libs/ardour/ardour/route.h5
-rw-r--r--libs/ardour/ardour/types.h1
-rw-r--r--libs/ardour/audio_diskstream.cc10
-rw-r--r--libs/ardour/io.cc9
-rw-r--r--libs/ardour/lv2_plugin.cc547
-rw-r--r--libs/ardour/plugin.cc10
-rw-r--r--libs/ardour/plugin_insert.cc13
-rw-r--r--libs/ardour/plugin_manager.cc28
-rw-r--r--libs/ardour/route.cc8
-rw-r--r--libs/ardour/session_command.cc5
-rw-r--r--svn_revision.h2
-rwxr-xr-xtools/osx_packaging/script27
44 files changed, 1809 insertions, 520 deletions
diff --git a/SConstruct b/SConstruct
index cc21831df2..575c530300 100644
--- a/SConstruct
+++ b/SConstruct
@@ -46,6 +46,7 @@ opts.AddOptions(
BoolOption('UNIVERSAL', 'Compile as universal binary. Requires that external libraries are already universal.', 0),
BoolOption('VERSIONED', 'Add revision information to ardour/gtk executable name inside the build directory', 0),
BoolOption('VST', 'Compile with support for VST', 0),
+ BoolOption('LV2', 'Compile with support for LV2 (if slv2 is available)', 1),
BoolOption('GPROFILE', 'Compile with support for gprofile (Developers only)', 0),
BoolOption('TRANZPORT', 'Compile with support for Frontier Designs (if libusb is available)', 1)
)
@@ -403,7 +404,6 @@ else:
if os.path.isfile('.personal_use_only'):
os.remove('.personal_use_only')
-
####################
# push environment
####################
@@ -527,6 +527,18 @@ if env['FFT_ANALYSIS']:
print ('FFT Analysis cannot be compiled without the FFTW3 headers, which do not seem to be installed')
sys.exit (1)
conf.Finish()
+
+if env['LV2']:
+ conf = env.Configure(custom_tests = { 'CheckPKGExists' : CheckPKGExists })
+
+ if conf.CheckPKGExists ('\"slv2 >= 0.4.4\"'):
+ libraries['slv2'] = LibraryInfo()
+ libraries['slv2'].ParseConfig('pkg-config --cflags --libs slv2')
+ else:
+ print 'Building Ardour with LV2 support requires SLV2 >= 0.4.4'
+ print 'WARNING: SLV2 not found, or too old. Ardour will be built without LV2 support.'
+ env['LV2'] = 0
+ conf.Finish()
libraries['jack'] = LibraryInfo()
libraries['jack'].ParseConfig('pkg-config --cflags --libs jack')
@@ -942,7 +954,7 @@ if env['SYSLIBS']:
print '%s >= %s not found.' %(pkg, version)
DependenciesRequiredMessage()
Exit(1)
-
+
env = conf.Finish()
libraries['sigc2'] = LibraryInfo()
diff --git a/gtk2_ardour/SConscript b/gtk2_ardour/SConscript
index 24fd461c37..bc314f2fa4 100644
--- a/gtk2_ardour/SConscript
+++ b/gtk2_ardour/SConscript
@@ -211,6 +211,7 @@ route_ui.cc
selection.cc
sfdb_ui.cc
send_ui.cc
+splash.cc
streamview.cc
audio_streamview.cc
tempo_dialog.cc
@@ -270,24 +271,8 @@ if env['VST']:
extra_sources += vst_files
gtkardour.Append (CCFLAGS="-DVST_SUPPORT", CPPPATH="#libs/fst")
-cmt_files=Split("""
-canvas-imageframe.c
-editor_imageframe.cc
-imageframe.cc
-imageframe_socket_handler.cc
-imageframe_time_axis.cc
-imageframe_time_axis_group.cc
-imageframe_time_axis_view.cc
-imageframe_view.cc
-marker_time_axis.cc
-marker_time_axis_view.cc
-marker_view.cc
-visual_time_axis.cc
-""")
-
-#if env['CMT']:
-# extra_sources += cmt_files
-# gtkardour.Append (CCFLAGS="-DWITH_CMT")
+if env['LV2']:
+ gtkardour.Append (CCFLAGS="-DHAVE_SLV2")
if gtkardour['GTKOSX']:
extra_sources += gtkosx_files
@@ -506,7 +491,6 @@ env.Alias ('tarball', env.Distribute (env['DISTTREE'],
] +
gtkardour_files +
vst_files +
- cmt_files +
pixmap_files +
icon_files +
skipped_files +
diff --git a/gtk2_ardour/about.cc b/gtk2_ardour/about.cc
index a201a1c404..a76fc3c619 100644
--- a/gtk2_ardour/about.cc
+++ b/gtk2_ardour/about.cc
@@ -156,6 +156,8 @@ static const char* authors[] = {
N_("Nedko Arnaudov"),
N_("Carl Hetherington"),
N_("Colin Fletcher"),
+ N_("Roland Stigge"),
+ N_("Audun Halland"),
0
};
@@ -178,7 +180,7 @@ About::About ()
: paypal_pixmap (paypal_xpm)
#endif
{
- set_type_hint(Gdk::WINDOW_TYPE_HINT_SPLASHSCREEN);
+ // set_type_hint(Gdk::WINDOW_TYPE_HINT_SPLASHSCREEN);
string path;
string t;
diff --git a/gtk2_ardour/ardour3_ui_default.conf b/gtk2_ardour/ardour3_ui_default.conf
index 8525908cf0..78e40f5515 100644
--- a/gtk2_ardour/ardour3_ui_default.conf
+++ b/gtk2_ardour/ardour3_ui_default.conf
@@ -4,7 +4,8 @@
<Option name="ui-rc-file" value="ardour3_ui_dark.rc"/>
</UI>
<Canvas>
- <Option name="waveform" value="000000cc"/>
+ <Option name="waveform" value="373737a7"/>
+ <Option name="waveform fill" value="73737378"/>
<Option name="clipped waveform" value="ff0000e5"/>
<Option name="region base" value="bfbfc1aa"/>
<Option name="selected region base" value="565693a6"/>
diff --git a/gtk2_ardour/ardour_ui.cc b/gtk2_ardour/ardour_ui.cc
index 44a3d171c6..c10b0d73d0 100644
--- a/gtk2_ardour/ardour_ui.cc
+++ b/gtk2_ardour/ardour_ui.cc
@@ -84,6 +84,7 @@
#include "add_route_dialog.h"
#include "new_session_dialog.h"
#include "about.h"
+#include "splash.h"
#include "utils.h"
#include "gui_thread.h"
#include "theme_manager.h"
@@ -172,6 +173,12 @@ ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[])
_auto_display_errors = false;
#endif
about = 0;
+ splash = 0;
+
+ if (ARDOUR_COMMAND_LINE::session_name.length()) {
+ /* only show this if we're not going to post the new session dialog */
+ show_splash ();
+ }
if (theArdourUI == 0) {
theArdourUI = this;
@@ -272,6 +279,13 @@ ARDOUR_UI::create_engine ()
return 0;
}
+#ifdef __APPLE__
+ // OS X where everything is sllloooowwww
+ loading_dialog->set_message (_("Starting audio engine"));
+ loading_dialog->show_all ();
+ flush_pending ();
+#endif
+
try {
engine = new ARDOUR::AudioEngine (ARDOUR_COMMAND_LINE::jack_client_name);
@@ -602,74 +616,39 @@ Please consider the possibilities, and perhaps (re)start JACK."));
win.show_all ();
win.set_position (Gtk::WIN_POS_CENTER);
- if (!ARDOUR_COMMAND_LINE::no_splash) {
- hide_splash ();
- }
+ hide_splash ();
/* we just don't care about the result, but we want to block */
win.run ();
}
+static bool
+_hide_splash (gpointer arg)
+{
+ ((ARDOUR_UI*)arg)->hide_splash();
+ return false;
+}
+
void
ARDOUR_UI::startup ()
{
string name, path;
- bool isnew;
new_session_dialog = new NewSessionDialog();
-
- /* If no session name is given: we're not loading a session yet, nor creating a new one */
-
- if (ARDOUR_COMMAND_LINE::session_name.length()) {
-
- /* Load session or start the new session dialog */
-
- if (find_session (ARDOUR_COMMAND_LINE::session_name, path, name, isnew)) {
-
- MessageDialog msg (string_compose(_("Could not find command line session \"%1\""),
- ARDOUR_COMMAND_LINE::session_name),
- true,
- Gtk::MESSAGE_ERROR,
- Gtk::BUTTONS_OK);
-
- msg.set_position (Gtk::WIN_POS_MOUSE);
- msg.present ();
- msg.run ();
-
- exit (1);
- }
- if (!ARDOUR_COMMAND_LINE::new_session) {
-
- /* Supposed to be loading an existing session, but the session doesn't exist */
-
- if (isnew) {
- MessageDialog msg (string_compose (_("\n\nNo session named \"%1\" exists.\n"
- "To create it from the command line, start ardour as:\n ardour --new %1"), path),
- true,
- Gtk::MESSAGE_ERROR,
- Gtk::BUTTONS_OK);
-
- msg.set_position (Gtk::WIN_POS_MOUSE);
- msg.present ();
- msg.run ();
+ // in 4 seconds, hide the splash screen
- exit (1);
- }
- }
- }
-
- hide_splash ();
+ Glib::signal_timeout().connect (bind (sigc::ptr_fun (_hide_splash), this), 4000);
- bool have_backend = EngineControl::engine_running();
+ bool backend_audio_is_running = EngineControl::engine_running();
XMLNode* audio_setup = Config->extra_xml ("AudioSetup");
if (audio_setup) {
new_session_dialog->engine_control.set_state (*audio_setup);
}
- if (!get_session_parameters (ARDOUR_COMMAND_LINE::session_name, have_backend, ARDOUR_COMMAND_LINE::new_session)) {
+ if (!get_session_parameters (backend_audio_is_running, ARDOUR_COMMAND_LINE::new_session)) {
return;
}
@@ -2073,8 +2052,175 @@ ARDOUR_UI::fontconfig_dialog ()
#endif
}
+void
+ARDOUR_UI::parse_cmdline_path (const Glib::ustring& cmdline_path, Glib::ustring& session_name, Glib::ustring& session_path, bool& existing_session)
+{
+ existing_session = false;
+
+ if (Glib::file_test (cmdline_path, Glib::FILE_TEST_IS_DIR)) {
+ session_path = cmdline_path;
+ existing_session = true;
+ } else if (Glib::file_test (cmdline_path, Glib::FILE_TEST_IS_REGULAR)) {
+ session_path = Glib::path_get_dirname (string (cmdline_path));
+ existing_session = true;
+ } else {
+ /* it doesn't exist, assume the best */
+ session_path = Glib::path_get_dirname (string (cmdline_path));
+ }
+
+ session_name = basename_nosuffix (string (cmdline_path));
+}
+
+int
+ARDOUR_UI::load_cmdline_session (const Glib::ustring& session_name, const Glib::ustring& session_path, bool& existing_session)
+{
+ /* when this is called, the backend audio system must be running */
+
+ /* the main idea here is to deal with the fact that a cmdline argument for the session
+ can be interpreted in different ways - it could be a directory or a file, and before
+ we load, we need to know both the session directory and the snapshot (statefile) within it
+ that we are supposed to use.
+ */
+
+ if (session_name.length() == 0 || session_path.length() == 0) {
+ return false;
+ }
+
+ if (Glib::file_test (session_path, Glib::FILE_TEST_IS_DIR)) {
+
+ Glib::ustring predicted_session_file;
+
+ predicted_session_file = session_path;
+ predicted_session_file += '/';
+ predicted_session_file += session_name;
+ predicted_session_file += ARDOUR::statefile_suffix;
+
+ if (Glib::file_test (predicted_session_file, Glib::FILE_TEST_EXISTS)) {
+ existing_session = true;
+ }
+
+ } else if (Glib::file_test (session_path, Glib::FILE_TEST_EXISTS)) {
+
+ if (session_path.find (ARDOUR::statefile_suffix) == session_path.length() - 7) {
+ /* existing .ardour file */
+ existing_session = true;
+ }
+
+ } else {
+ existing_session = false;
+ }
+
+ /* lets just try to load it */
+
+ if (create_engine ()) {
+ hide_splash ();
+ loading_dialog->hide ();
+ backend_audio_error (false, new_session_dialog);
+ return -1;
+ }
+
+ return load_session (session_path, session_name);
+}
+
+bool
+ARDOUR_UI::ask_about_loading_existing_session (const Glib::ustring& session_path)
+{
+ Glib::ustring str = string_compose (_("This session\n%1\nalready exists. Do you want to open it?"), session_path);
+
+ MessageDialog msg (str,
+ false,
+ Gtk::MESSAGE_WARNING,
+ Gtk::BUTTONS_YES_NO,
+ true);
+
+
+ msg.set_name (X_("CleanupDialog"));
+ msg.set_wmclass (X_("existing_session"), "Ardour");
+ msg.set_position (Gtk::WIN_POS_MOUSE);
+
+ switch (msg.run()) {
+ case RESPONSE_YES:
+ return true;
+ break;
+ }
+ return false;
+}
+
+int
+ARDOUR_UI::build_session_from_nsd (const Glib::ustring& session_path, const Glib::ustring& session_name)
+{
+
+ uint32_t cchns;
+ uint32_t mchns;
+ AutoConnectOption iconnect;
+ AutoConnectOption oconnect;
+ uint32_t nphysin;
+ uint32_t nphysout;
+
+ if (Profile->get_sae()) {
+
+ cchns = 0;
+ mchns = 2;
+ iconnect = AutoConnectPhysical;
+ oconnect = AutoConnectMaster;
+ nphysin = 0; // use all available
+ nphysout = 0; // use all available
+
+ } else {
+
+ /* get settings from advanced section of NSD */
+
+ if (new_session_dialog->create_control_bus()) {
+ cchns = (uint32_t) new_session_dialog->control_channel_count();
+ } else {
+ cchns = 0;
+ }
+
+ if (new_session_dialog->create_master_bus()) {
+ mchns = (uint32_t) new_session_dialog->master_channel_count();
+ } else {
+ mchns = 0;
+ }
+
+ if (new_session_dialog->connect_inputs()) {
+ iconnect = AutoConnectPhysical;
+ } else {
+ iconnect = AutoConnectOption (0);
+ }
+
+ /// @todo some minor tweaks.
+
+ if (new_session_dialog->connect_outs_to_master()) {
+ oconnect = AutoConnectMaster;
+ } else if (new_session_dialog->connect_outs_to_physical()) {
+ oconnect = AutoConnectPhysical;
+ } else {
+ oconnect = AutoConnectOption (0);
+ }
+
+ nphysin = (uint32_t) new_session_dialog->input_limit_count();
+ nphysout = (uint32_t) new_session_dialog->output_limit_count();
+ }
+
+ if (build_session (session_path,
+ session_name,
+ cchns,
+ mchns,
+ iconnect,
+ oconnect,
+ nphysin,
+ nphysout,
+ engine->frame_rate() * 60 * 5)) {
+
+ return -1;
+ }
+
+ return 0;
+}
+
+
bool
-ARDOUR_UI::get_session_parameters (Glib::ustring predetermined_path, bool have_engine, bool should_be_new)
+ARDOUR_UI::get_session_parameters (bool backend_audio_is_running, bool should_be_new)
{
bool existing_session = false;
Glib::ustring session_name;
@@ -2089,91 +2235,45 @@ ARDOUR_UI::get_session_parameters (Glib::ustring predetermined_path, bool have_e
Gtk::BUTTONS_NONE);
}
-
int response = Gtk::RESPONSE_NONE;
- if (predetermined_path.length()) {
-
- /* before we start, lets see if the given path looks like
- an existing ardour session. if it does, skip the
- tabs that we don't need
- */
+ if (!ARDOUR_COMMAND_LINE::session_name.empty()) {
- if (Glib::file_test (predetermined_path, Glib::FILE_TEST_IS_DIR)) {
- session_path = predetermined_path;
- existing_session = true;
- } else if (Glib::file_test (predetermined_path, Glib::FILE_TEST_IS_REGULAR)) {
- session_path = Glib::path_get_dirname (string (predetermined_path));
- existing_session = true;
- } else {
- /* it doesn't exist, assume the best */
- session_path = Glib::path_get_dirname (string (predetermined_path));
- }
-
- session_name = basename_nosuffix (string (predetermined_path));
+ parse_cmdline_path (ARDOUR_COMMAND_LINE::session_name, session_name, session_path, existing_session);
- new_session_dialog->set_session_name (session_name);
- new_session_dialog->set_session_folder (session_path);
- new_session_dialog->set_modal (true);
+ /* don't ever reuse this */
- if (existing_session) {
+ ARDOUR_COMMAND_LINE::session_name = string();
- if (session_name.length() == 0 || session_path.length() == 0) {
- error << string_compose (_("Ardour cannot understand \"%1\" as a session name"), predetermined_path) << endmsg;
- return false;
- }
-
- if (Glib::file_test (predetermined_path, Glib::FILE_TEST_IS_DIR)) {
- Glib::ustring predicted_session_file;
-
- predicted_session_file = predetermined_path;
- predicted_session_file += '/';
- predicted_session_file += session_name;
- predicted_session_file += ARDOUR::statefile_suffix;
-
- if (Glib::file_test (predicted_session_file, Glib::FILE_TEST_EXISTS)) {
- existing_session = true;
- }
-
- } else if (Glib::file_test (predetermined_path, Glib::FILE_TEST_EXISTS)) {
-
- if (predetermined_path.find (ARDOUR::statefile_suffix) == predetermined_path.length() - 7) {
- /* existing .ardour file */
- existing_session = true;
- }
- } else {
- existing_session = false;
- }
-
- if (existing_session && have_engine) {
- /* lets just try to load it */
-
- loading_dialog->set_message (_("Starting audio engine"));
- loading_dialog->show_all ();
- flush_pending ();
-
- if (create_engine ()) {
- backend_audio_error (!have_engine, new_session_dialog);
- loading_dialog->hide ();
- return false;
- }
-
- if (load_session (session_path, session_name) == 0) {
- goto done;
- }
+ if (existing_session && backend_audio_is_running) {
+
+ /* just load the thing already */
+
+ if (load_cmdline_session (session_name, session_path, existing_session) == 0) {
+ return true;
}
}
+
+ /* make the NSD use whatever information we have */
+
+ new_session_dialog->set_session_name (session_name);
+ new_session_dialog->set_session_folder (session_path);
}
/* loading failed, or we need the NSD for something */
+ new_session_dialog->set_modal (false);
new_session_dialog->set_position (WIN_POS_CENTER);
new_session_dialog->set_current_page (0);
new_session_dialog->set_existing_session (existing_session);
new_session_dialog->reset_recent();
+ /* get this out of the way */
+
+ hide_splash ();
+
do {
- new_session_dialog->set_have_engine (have_engine);
+ new_session_dialog->set_have_engine (backend_audio_is_running);
new_session_dialog->present ();
response = new_session_dialog->run ();
loading_dialog->hide ();
@@ -2182,294 +2282,142 @@ ARDOUR_UI::get_session_parameters (Glib::ustring predetermined_path, bool have_e
/* handle possible negative responses */
- if (response == Gtk::RESPONSE_CANCEL || response == Gtk::RESPONSE_DELETE_EVENT) {
-
+ switch (response) {
+ case Gtk::RESPONSE_CANCEL:
+ case Gtk::RESPONSE_DELETE_EVENT:
if (!session) {
quit();
}
new_session_dialog->hide ();
return false;
- } else if (response == Gtk::RESPONSE_NONE) {
+ case Gtk::RESPONSE_NONE:
/* "Clear" was pressed */
-
goto try_again;
}
fontconfig_dialog();
- /* if we're here to help set up audio parameters this is where want to do that.
- */
-
- if (!have_engine) {
+ if (!backend_audio_is_running) {
if (new_session_dialog->engine_control.setup_engine ()) {
new_session_dialog->hide ();
return false;
}
-
- loading_dialog->set_message (_("Starting audio engine"));
- loading_dialog->show_all ();
- flush_pending ();
}
-
+
if (create_engine ()) {
- backend_audio_error (!have_engine, new_session_dialog);
+
+ backend_audio_error (!backend_audio_is_running, new_session_dialog);
loading_dialog->hide ();
flush_pending ();
- /* audio setup page */
+
new_session_dialog->set_existing_session (false);
new_session_dialog->set_current_page (2);
+
response = Gtk::RESPONSE_NONE;
goto try_again;
}
loading_dialog->hide ();
- have_engine = true;
+ backend_audio_is_running = true;
- /* now handle possible affirmative responses */
+ if (response == Gtk::RESPONSE_OK) {
- if (response == Gtk::RESPONSE_YES) {
-
- /* YES == OPEN from the session selector */
+ session_name = new_session_dialog->session_name();
- session_name = new_session_dialog->session_name();
-
if (session_name.empty()) {
response = Gtk::RESPONSE_NONE;
goto try_again;
}
+ /* if the user mistakenly typed path information into the session filename entry,
+ convert what they typed into a path & a name
+ */
+
if (session_name[0] == '/' ||
(session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
(session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
- if (load_session (Glib::path_get_dirname (session_name), session_name)) {
- response = Gtk::RESPONSE_NONE;
- goto try_again;
- }
+
+ session_path = Glib::path_get_dirname (session_name);
+ session_name = Glib::path_get_basename (session_name);
+
} else {
+
session_path = new_session_dialog->session_folder();
- if (load_session (session_path, session_name)) {
- response = Gtk::RESPONSE_NONE;
- goto try_again;
- }
}
-
- } else if (response == Gtk::RESPONSE_OK) {
-
- /* OK == OPEN button */
-
- session_name = new_session_dialog->session_name();
-
- if (session_name.empty()) {
- response = Gtk::RESPONSE_NONE;
- goto try_again;
- }
switch (new_session_dialog->which_page()) {
+
case NewSessionDialog::OpenPage:
case NewSessionDialog::EnginePage:
-
- if (session_name[0] == '/' ||
- (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
- (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
-
- if (load_session (Glib::path_get_dirname (session_name), session_name)) {
- response = Gtk::RESPONSE_NONE;
- goto try_again;
- }
-
- } else {
- session_path = new_session_dialog->session_folder();
- cerr << "there\n";
- if (load_session (session_path, session_name)) {
- response = Gtk::RESPONSE_NONE;
- goto try_again;
- }
- }
+ goto loadit;
break;
case NewSessionDialog::NewPage: /* nominally the "new" session creator, but could be in use for an old session */
-
- cerr << "on page zero\n";
-
- if (new_session_dialog->get_current_page() == 0 && ARDOUR_COMMAND_LINE::session_name.empty()) {
- should_be_new = true;
- }
-
- /* handle what appear to be paths rather than just a name */
-
- if (session_name[0] == '/' ||
- (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
- (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
-
- session_path = Glib::path_get_dirname (session_name);
- session_name = Glib::path_get_basename (session_name);
-
- } else {
-
- session_path = new_session_dialog->session_folder();
-
- }
-
+
+ should_be_new = true;
+
//XXX This is needed because session constructor wants a
//non-existant path. hopefully this will be fixed at some point.
session_path = Glib::build_filename (session_path, session_name);
- if (!should_be_new) {
-
- if (load_session (session_path, session_name)) {
- response = Gtk::RESPONSE_NONE;
- goto try_again;
- }
+ if (Glib::file_test (session_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) {
- continue; /* leaves while() loop because response != NONE */
-
- } else if (Glib::file_test (session_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) {
-
- Glib::ustring str = string_compose (_("This session\n%1\nalready exists. Do you want to open it?"), session_path);
-
- MessageDialog msg (str,
- false,
- Gtk::MESSAGE_WARNING,
- Gtk::BUTTONS_YES_NO,
- true);
-
-
- msg.set_name (X_("CleanupDialog"));
- msg.set_wmclass (X_("existing_session"), "Ardour");
- msg.set_position (Gtk::WIN_POS_MOUSE);
-
- switch (msg.run()) {
- case RESPONSE_YES:
- new_session_dialog->hide ();
- goto_editor_window ();
- flush_pending ();
- if (load_session (session_path, session_name)) {
- response = Gtk::RESPONSE_NONE;
- goto try_again;
- }
- goto done;
- break;
- default:
+ if (ask_about_loading_existing_session (session_path)) {
+ goto loadit;
+ } else {
response = RESPONSE_NONE;
- new_session_dialog->reset ();
- new_session_dialog->set_existing_session (false);
- loading_dialog->hide ();
- continue;
- }
- }
+ goto try_again;
+ }
+ }
_session_is_new = true;
if (new_session_dialog->use_session_template()) {
template_name = new_session_dialog->session_template_name();
-
- new_session_dialog->hide ();
- goto_editor_window ();
- flush_pending ();
-
- if (load_session (session_path, session_name, template_name)) {
- response = Gtk::RESPONSE_NONE;
- goto try_again;
- }
-
+ goto loadit;
} else {
-
- uint32_t cchns;
- uint32_t mchns;
- AutoConnectOption iconnect;
- AutoConnectOption oconnect;
- uint32_t nphysin;
- uint32_t nphysout;
-
- if (Profile->get_sae()) {
-
- cchns = 0;
- mchns = 2;
- iconnect = AutoConnectPhysical;
- oconnect = AutoConnectMaster;
- nphysin = 0; // use all available
- nphysout = 0; // use all available
-
- } else {
-
- /* get settings from advanced section of NSD */
-
- if (new_session_dialog->create_control_bus()) {
- cchns = (uint32_t) new_session_dialog->control_channel_count();
- } else {
- cchns = 0;
- }
-
- if (new_session_dialog->create_master_bus()) {
- mchns = (uint32_t) new_session_dialog->master_channel_count();
- } else {
- mchns = 0;
- }
-
- if (new_session_dialog->connect_inputs()) {
- iconnect = AutoConnectPhysical;
- } else {
- iconnect = AutoConnectOption (0);
- }
-
- /// @todo some minor tweaks.
-
- if (new_session_dialog->connect_outs_to_master()) {
- oconnect = AutoConnectMaster;
- } else if (new_session_dialog->connect_outs_to_physical()) {
- oconnect = AutoConnectPhysical;
- } else {
- oconnect = AutoConnectOption (0);
- }
-
- nphysin = (uint32_t) new_session_dialog->input_limit_count();
- nphysout = (uint32_t) new_session_dialog->output_limit_count();
- }
-
- if (build_session (session_path,
- session_name,
- cchns,
- mchns,
- iconnect,
- oconnect,
- nphysin,
- nphysout,
- engine->frame_rate() * 60 * 5)) {
-
- response = Gtk::RESPONSE_NONE;
+ if (build_session_from_nsd (session_path, session_name)) {
+ response = RESPONSE_NONE;
goto try_again;
}
-
- new_session_dialog->hide ();
- goto_editor_window ();
- flush_pending ();
+ goto done;
}
break;
-
+
default:
break;
}
- }
+
+ loadit:
+ new_session_dialog->hide ();
+
+ if (load_session (session_path, session_name)) {
+ /* force a retry */
+ response = Gtk::RESPONSE_NONE;
+ }
- try_again:
- if (response == Gtk::RESPONSE_NONE) {
- loading_dialog->hide ();
- new_session_dialog->set_existing_session (false);
- new_session_dialog->reset ();
+ try_again:
+ if (response == Gtk::RESPONSE_NONE) {
+ loading_dialog->hide ();
+ new_session_dialog->set_existing_session (false);
+ new_session_dialog->reset ();
+ }
}
-
+
} while (response == Gtk::RESPONSE_NONE);
done:
show();
loading_dialog->hide ();
new_session_dialog->hide();
+ new_session_dialog->reset();
+ goto_editor_window ();
return true;
-}
+}
void
ARDOUR_UI::close_session()
@@ -2480,7 +2428,7 @@ ARDOUR_UI::close_session()
unload_session (true);
- get_session_parameters ("", true, false);
+ get_session_parameters (true, false);
}
int
@@ -2514,10 +2462,13 @@ ARDOUR_UI::load_session (const Glib::ustring& path, const Glib::ustring& snap_na
goto out;
}
+#ifdef __APPLE__
+ // OS X where everything is sllloooowwww
if (loading_dialog) {
loading_dialog->set_markup (_("Please wait while Ardour loads your session"));
flush_pending ();
}
+#endif
disable_screen_updates ();
@@ -2659,28 +2610,52 @@ ARDOUR_UI::show ()
}
void
-ARDOUR_UI::show_splash ()
+ARDOUR_UI::show_about ()
{
if (about == 0) {
- about = new About();
+ about = new About;
about->signal_response().connect(mem_fun (*this, &ARDOUR_UI::about_signal_response) );
}
- about->present();
- flush_pending ();
+
+ about->show_all ();
+}
+
+void
+ARDOUR_UI::hide_about ()
+{
+ if (about) {
+ about->get_window()->set_cursor ();
+ about->hide ();
+ }
}
void
ARDOUR_UI::about_signal_response(int response)
{
- hide_splash();
+ hide_about();
+}
+
+void
+ARDOUR_UI::show_splash ()
+{
+ if (splash == 0) {
+ try {
+ splash = new Splash;
+ } catch (...) {
+ return;
+ }
+ }
+
+ splash->show ();
+ splash->get_window()->process_updates (true);
+ flush_pending ();
}
void
ARDOUR_UI::hide_splash ()
{
- if (about) {
- about->get_window()->set_cursor ();
- about->hide();
+ if (splash) {
+ splash->hide();
}
}
@@ -3110,27 +3085,6 @@ ARDOUR_UI::reconnect_to_jack ()
}
}
-int
-ARDOUR_UI::cmdline_new_session (string path)
-{
- if (path[0] != '/') {
- char buf[PATH_MAX+1];
- string str;
-
- getcwd (buf, sizeof (buf));
- str = buf;
- str += '/';
- str += path;
- path = str;
- }
-
- get_session_parameters (path, false, true);
-
- _will_create_new_session_automatically = false; /* done it */
-
- return FALSE; /* don't call it again */
-}
-
void
ARDOUR_UI::use_config ()
{
diff --git a/gtk2_ardour/ardour_ui.h b/gtk2_ardour/ardour_ui.h
index 5e43b8a64b..25abe8f14c 100644
--- a/gtk2_ardour/ardour_ui.h
+++ b/gtk2_ardour/ardour_ui.h
@@ -74,6 +74,7 @@ class Mixer_UI;
class ConnectionEditor;
class RouteParams_UI;
class About;
+class Splash;
class AddRouteDialog;
class NewSessionDialog;
class LocationUI;
@@ -111,6 +112,9 @@ class ARDOUR_UI : public Gtkmm2ext::UI
void show_splash ();
void hide_splash ();
+
+ void show_about ();
+ void hide_about ();
int load_session (const Glib::ustring & path, const Glib::ustring& snapshot, Glib::ustring mix_template = Glib::ustring());
bool session_loaded;
@@ -134,9 +138,11 @@ class ARDOUR_UI : public Gtkmm2ext::UI
_will_create_new_session_automatically = yn;
}
- bool get_session_parameters (Glib::ustring path, bool have_engine = false, bool should_be_new = false);
-
- gint cmdline_new_session (string path);
+ bool get_session_parameters (bool have_engine = false, bool should_be_new = false);
+ void parse_cmdline_path (const Glib::ustring& cmdline_path, Glib::ustring& session_name, Glib::ustring& session_path, bool& existing_session);
+ int load_cmdline_session (const Glib::ustring& session_name, const Glib::ustring& session_path, bool& existing_session);
+ int build_session_from_nsd (const Glib::ustring& session_name, const Glib::ustring& session_path);
+ bool ask_about_loading_existing_session (const Glib::ustring& session_path);
/// @return true if session was successfully unloaded.
int unload_session (bool hide_stuff = false);
@@ -653,6 +659,7 @@ class ARDOUR_UI : public Gtkmm2ext::UI
void count_recenabled_streams (ARDOUR::Route&);
About* about;
+ Splash* splash;
bool shown_flag;
/* cleanup */
diff --git a/gtk2_ardour/ardour_ui_dependents.cc b/gtk2_ardour/ardour_ui_dependents.cc
index dd0889b786..6472bc5ef4 100644
--- a/gtk2_ardour/ardour_ui_dependents.cc
+++ b/gtk2_ardour/ardour_ui_dependents.cc
@@ -111,12 +111,15 @@ ARDOUR_UI::goto_editor_window ()
{
editor->show_window ();
editor->present ();
+ flush_pending ();
}
+
void
ARDOUR_UI::goto_mixer_window ()
{
mixer->show_window ();
mixer->present ();
+ flush_pending ();
}
gint
diff --git a/gtk2_ardour/ardour_ui_ed.cc b/gtk2_ardour/ardour_ui_ed.cc
index f5e4cfa549..30b6424fb4 100644
--- a/gtk2_ardour/ardour_ui_ed.cc
+++ b/gtk2_ardour/ardour_ui_ed.cc
@@ -102,7 +102,7 @@ ARDOUR_UI::install_actions ()
/* the real actions */
- act = ActionManager::register_action (main_actions, X_("New"), _("New"), hide_return (bind (mem_fun(*this, &ARDOUR_UI::get_session_parameters), string (), true, true)));
+ act = ActionManager::register_action (main_actions, X_("New"), _("New"), hide_return (bind (mem_fun(*this, &ARDOUR_UI::get_session_parameters), true, true)));
ActionManager::register_action (main_actions, X_("Open"), _("Open"), mem_fun(*this, &ARDOUR_UI::open_session));
ActionManager::register_action (main_actions, X_("Recent"), _("Recent"), mem_fun(*this, &ARDOUR_UI::open_recent_session));
@@ -204,6 +204,11 @@ ARDOUR_UI::install_actions ()
ActionManager::session_sensitive_actions.push_back (act);
act = ActionManager::register_toggle_action (common_actions, X_("ToggleBigClock"), _("Big Clock"), mem_fun(*this, &ARDOUR_UI::toggle_big_clock_window));
ActionManager::session_sensitive_actions.push_back (act);
+ ActionManager::register_action (common_actions, X_("About"), _("About"), mem_fun(*this, &ARDOUR_UI::show_about));
+ ActionManager::register_toggle_action (common_actions, X_("ToggleThemeManager"), _("Theme Manager"), mem_fun(*this, &ARDOUR_UI::toggle_theme_manager));
+ ActionManager::register_toggle_action (common_actions, X_("ToggleKeyEditor"), _("Keybindings"), mem_fun(*this, &ARDOUR_UI::toggle_key_editor));
+ ActionManager::register_toggle_action (common_actions, X_("ToggleBundleManager"), _("Bundle Manager"), mem_fun(*this, &ARDOUR_UI::toggle_bundle_manager));
+
act = ActionManager::register_action (common_actions, X_("AddAudioTrack"), _("Add Audio Track"), bind (mem_fun(*this, &ARDOUR_UI::session_add_audio_track), 1, 1, ARDOUR::Normal, 1));
ActionManager::session_sensitive_actions.push_back (act);
act = ActionManager::register_action (common_actions, X_("AddAudioBus"), _("Add Audio Bus"), bind (mem_fun(*this, &ARDOUR_UI::session_add_audio_bus), 1, 1, 1));
@@ -218,11 +223,7 @@ ARDOUR_UI::install_actions ()
ActionManager::session_sensitive_actions.push_back (act);
ActionManager::register_action (common_actions, X_("About"), _("About"), mem_fun(*this, &ARDOUR_UI::show_splash));
- ActionManager::register_toggle_action (common_actions, X_("ToggleThemeManager"), _("Theme Manager"), mem_fun(*this, &ARDOUR_UI::toggle_theme_manager));
- ActionManager::register_toggle_action (common_actions, X_("ToggleBundleManager"), _("Bundle Manager"), mem_fun(*this, &ARDOUR_UI::toggle_bundle_manager));
- ActionManager::register_toggle_action (common_actions, X_("ToggleKeyEditor"), _("Keybindings"), mem_fun(*this, &ARDOUR_UI::toggle_key_editor));
-
Glib::RefPtr<ActionGroup> transport_actions = ActionGroup::create (X_("Transport"));
/* do-nothing action for the "transport" menu bar item */
diff --git a/gtk2_ardour/audio_region_view.cc b/gtk2_ardour/audio_region_view.cc
index 333d7ea87a..5873a71cce 100644
--- a/gtk2_ardour/audio_region_view.cc
+++ b/gtk2_ardour/audio_region_view.cc
@@ -1241,6 +1241,7 @@ AudioRegionView::set_frame_color ()
(*w)->property_wave_color() = UINT_RGBA_CHANGE_A(ARDOUR_UI::config()->canvasvar_WaveForm.get(), MUTED_ALPHA);
} else {
(*w)->property_wave_color() = ARDOUR_UI::config()->canvasvar_WaveForm.get();
+ (*w)->property_fill_color() = ARDOUR_UI::config()->canvasvar_WaveFormFill.get();
}
}
}
diff --git a/gtk2_ardour/canvas-waveview.c b/gtk2_ardour/canvas-waveview.c
index b78bf63ea7..05d5c84b32 100644
--- a/gtk2_ardour/canvas-waveview.c
+++ b/gtk2_ardour/canvas-waveview.c
@@ -52,7 +52,10 @@ enum {
PROP_WAVE_COLOR,
PROP_CLIP_COLOR,
PROP_ZERO_COLOR,
+ PROP_FILL_COLOR,
+ PROP_FILLED,
PROP_RECTIFIED,
+ PROP_ZERO_LINE,
PROP_REGION_START,
PROP_LOGSCALED,
};
@@ -265,6 +268,20 @@ gnome_canvas_waveview_class_init (GnomeCanvasWaveViewClass *class)
g_param_spec_uint ("zero_color", NULL, NULL,
0, G_MAXUINT, 0,
(G_PARAM_READABLE | G_PARAM_WRITABLE)));
+
+ g_object_class_install_property
+ (gobject_class,
+ PROP_FILL_COLOR,
+ g_param_spec_uint ("fill_color", NULL, NULL,
+ 0, G_MAXUINT, 0,
+ (G_PARAM_READABLE | G_PARAM_WRITABLE)));
+
+ g_object_class_install_property
+ (gobject_class,
+ PROP_FILLED,
+ g_param_spec_boolean ("filled", NULL, NULL,
+ FALSE,
+ (G_PARAM_READABLE | G_PARAM_WRITABLE)));
g_object_class_install_property
(gobject_class,
@@ -275,6 +292,13 @@ gnome_canvas_waveview_class_init (GnomeCanvasWaveViewClass *class)
g_object_class_install_property
(gobject_class,
+ PROP_ZERO_LINE,
+ g_param_spec_boolean ("zero_line", NULL, NULL,
+ FALSE,
+ (G_PARAM_READABLE | G_PARAM_WRITABLE)));
+
+ g_object_class_install_property
+ (gobject_class,
PROP_LOGSCALED,
g_param_spec_boolean ("logscaled", NULL, NULL,
FALSE,
@@ -335,6 +359,8 @@ gnome_canvas_waveview_init (GnomeCanvasWaveView *waveview)
waveview->gain_src = NULL;
waveview->rectified = FALSE;
waveview->logscaled = FALSE;
+ waveview->filled = TRUE;
+ waveview->zero_line = FALSE;
waveview->region_start = 0;
waveview->samples_per_unit = 1.0;
waveview->amplitude_above_axis = 1.0;
@@ -345,6 +371,7 @@ gnome_canvas_waveview_init (GnomeCanvasWaveView *waveview)
waveview->wave_color = RGBA_TO_UINT(44,35,126,255);
waveview->clip_color = RGBA_TO_UINT(44,0,0,100);
waveview->zero_color = RGBA_TO_UINT(44,0,128,100);
+ waveview->fill_color = RGBA_TO_UINT(44,35,126,128);
}
static void
@@ -830,12 +857,34 @@ gnome_canvas_waveview_set_property (GObject *object,
}
break;
+ case PROP_FILL_COLOR:
+ if (waveview->fill_color != g_value_get_uint(value)) {
+ waveview->fill_color = g_value_get_uint(value);
+ redraw = TRUE;
+ }
+ break;
+
+ case PROP_FILLED:
+ if (waveview->filled != g_value_get_boolean(value)) {
+ waveview->filled = g_value_get_boolean(value);
+ redraw = TRUE;
+ }
+ break;
+
case PROP_RECTIFIED:
if (waveview->rectified != g_value_get_boolean(value)) {
waveview->rectified = g_value_get_boolean(value);
redraw = TRUE;
}
break;
+
+ case PROP_ZERO_LINE:
+ if (waveview->zero_line != g_value_get_boolean(value)) {
+ waveview->zero_line = g_value_get_boolean(value);
+ redraw = TRUE;
+ }
+ break;
+
case PROP_LOGSCALED:
if (waveview->logscaled != g_value_get_boolean(value)) {
waveview->logscaled = g_value_get_boolean(value);
@@ -950,10 +999,22 @@ gnome_canvas_waveview_get_property (GObject *object,
g_value_set_uint (value, waveview->zero_color);
break;
+ case PROP_FILL_COLOR:
+ g_value_set_uint (value, waveview->fill_color);
+ break;
+
+ case PROP_FILLED:
+ g_value_set_boolean (value, waveview->filled);
+ break;
+
case PROP_RECTIFIED:
g_value_set_boolean (value, waveview->rectified);
break;
+ case PROP_ZERO_LINE:
+ g_value_set_boolean (value, waveview->zero_line);
+ break;
+
case PROP_LOGSCALED:
g_value_set_boolean (value, waveview->logscaled);
break;
@@ -1012,9 +1073,11 @@ gnome_canvas_waveview_update (GnomeCanvasItem *item, double *affine, ArtSVP *cli
&waveview->wave_a);
UINT_TO_RGBA (waveview->clip_color, &waveview->clip_r, &waveview->clip_g, &waveview->clip_b,
&waveview->clip_a);
+ UINT_TO_RGBA (waveview->fill_color, &waveview->fill_r, &waveview->fill_g, &waveview->fill_b,
+ &waveview->fill_a);
// check_cache (waveview, "end of update");
-}
+}
static void
gnome_canvas_waveview_render (GnomeCanvasItem *item,
@@ -1028,6 +1091,7 @@ gnome_canvas_waveview_render (GnomeCanvasItem *item,
double half_height;
int x, end, begin;
int zbegin, zend;
+ char rectify;
waveview = GNOME_CANVAS_WAVEVIEW (item);
@@ -1107,10 +1171,18 @@ gnome_canvas_waveview_render (GnomeCanvasItem *item,
waveview->reload_cache_in_render = FALSE;
}
- cache_index = gnome_canvas_waveview_ensure_cache (waveview, s1, s2);
-
// check_cache (waveview, "post-ensure");
+ /* don't rectify at single-sample zoom */
+ if(waveview->rectified && waveview->samples_per_unit > 1) {
+ rectify = TRUE;
+ }
+ else {
+ rectify = FALSE;
+ }
+
+ clip_length = MIN(5,(waveview->height/4));
+
/*
Now draw each line, clipping it appropriately. The clipping
is done by the macros PAINT_FOO().
@@ -1119,83 +1191,401 @@ gnome_canvas_waveview_render (GnomeCanvasItem *item,
half_height = waveview->half_height;
/* this makes it slightly easier to comprehend whats going on */
-
#define origin half_height
+ if(waveview->filled && !rectify) {
+ int prev_pymin = 1;
+ int prev_pymax = 0;
+ int last_pymin = 1;
+ int last_pymax = 0;
+ int next_pymin, next_pymax;
+ double max, min;
+ int next_clip_max = 0;
+ int next_clip_min = 0;
- for (x = begin; x < end; x++) {
+ if(s1 < waveview->samples_per_unit) {
+ /* we haven't got a prev vars to compare with, so outline the whole line here */
+ prev_pymax = (int) rint ((item->y1 + origin) * item->canvas->pixels_per_unit);
+ prev_pymin = prev_pymax;
+ }
+ else {
+ s1 -= waveview->samples_per_unit;
+ }
- double max, min;
- int clip_max, clip_min;
-
- clip_max = 0;
- clip_min = 0;
+ if(end == waveview->bbox_lrx) {
+ /* we don't have the NEXT vars for the last sample */
+ last_pymax = (int) rint ((item->y1 + origin) * item->canvas->pixels_per_unit);
+ last_pymin = last_pymax;
+ }
+ else {
+ s2 += waveview->samples_per_unit;
+ }
+ cache_index = gnome_canvas_waveview_ensure_cache (waveview, s1, s2);
+
+ /*
+ * Compute the variables outside the rendering rect
+ */
+ if(prev_pymax != prev_pymin) {
+ prev_pymax = (int) rint ((item->y1 + origin - MIN(waveview->cache->data[cache_index].max, 1.0) * half_height) * item->canvas->pixels_per_unit);
+ prev_pymin = (int) rint ((item->y1 + origin - MAX(waveview->cache->data[cache_index].min, -1.0) * half_height) * item->canvas->pixels_per_unit);
+ ++cache_index;
+ }
+ if(last_pymax != last_pymin) {
+ /* take the index of one sample right of what we render */
+ int index = cache_index + (end - begin);
+
+ last_pymax = (int) rint ((item->y1 + origin - MIN(waveview->cache->data[index].max, 1.0) * half_height) * item->canvas->pixels_per_unit);
+ last_pymin = (int) rint ((item->y1 + origin - MAX(waveview->cache->data[index].min, -1.0) * half_height) * item->canvas->pixels_per_unit);
+ }
+
+ /*
+ * initialize NEXT* variables for the first run, duplicated in the loop for speed
+ */
max = waveview->cache->data[cache_index].max;
min = waveview->cache->data[cache_index].min;
if (max >= 1.0) {
max = 1.0;
- clip_max = 1;
+ next_clip_max = 1;
}
-
+
if (min <= -1.0) {
min = -1.0;
- clip_min = 1;
+ next_clip_min = 1;
}
+
+ max *= half_height;
+ min *= half_height;
+
+ next_pymax = (int) rint ((item->y1 + origin - max) * item->canvas->pixels_per_unit);
+ next_pymin = (int) rint ((item->y1 + origin - min) * item->canvas->pixels_per_unit);
+
+ /*
+ * And now the loop
+ */
+ for(x = begin; x < end; ++x) {
+ int clip_max = next_clip_max;
+ int clip_min = next_clip_min;
+ int fill_max, fill_min;
+
+ pymax = next_pymax;
+ pymin = next_pymin;
+
+ /* compute next */
+ if(x == end - 1) {
+ /*next is now the last column, which is outside the rendering rect, and possibly outside the region*/
+ next_pymax = last_pymax;
+ next_pymin = last_pymin;
+ }
+ else {
+ ++cache_index;
- /* don't rectify at single-sample zoom */
-
- if (waveview->rectified && waveview->samples_per_unit > 1) {
-
- if (fabs (min) > fabs (max)) {
- max = fabs (min);
- }
+ max = waveview->cache->data[cache_index].max;
+ min = waveview->cache->data[cache_index].min;
- max = max * waveview->height;
+ next_clip_max = 0;
+ next_clip_min = 0;
- pymax = (int) rint ((item->y1 + waveview->height - max) * item->canvas->pixels_per_unit);
- pymin = (int) rint ((item->y1 + waveview->height) * item->canvas->pixels_per_unit);
+ if (max >= 1.0) {
+ max = 1.0;
+ next_clip_max = 1;
+ }
+
+ if (min <= -1.0) {
+ min = -1.0;
+ next_clip_min = 1;
+ }
- } else {
+ max *= half_height;
+ min *= half_height;
+
+ next_pymax = (int) rint ((item->y1 + origin - max) * item->canvas->pixels_per_unit);
+ next_pymin = (int) rint ((item->y1 + origin - min) * item->canvas->pixels_per_unit);
+ }
- max = max * half_height;
- min = min * half_height;
+ /* render */
+ if (pymax == pymin) {
+ PAINT_DOTA(buf, waveview->wave_r, waveview->wave_g, waveview->wave_b, waveview->wave_a, x, pymin);
+ } else {
+ if((prev_pymax < pymax && next_pymax < pymax) ||
+ (prev_pymax == pymax && next_pymax == pymax)) {
+ fill_max = pymax + 1;
+ PAINT_DOTA(buf, waveview->wave_r, waveview->wave_g, waveview->wave_b, waveview->wave_a, x, pymax);
+ }
+ else {
+ fill_max = MAX(prev_pymax, next_pymax);
+ if(pymax == fill_max) {
+ PAINT_DOTA(buf, waveview->wave_r, waveview->wave_g, waveview->wave_b, waveview->wave_a, x, pymax);
+ ++fill_max;
+ }
+ else {
+ PAINT_VERTA(buf, waveview->wave_r, waveview->wave_g, waveview->wave_b, waveview->wave_a, x, pymax, fill_max);
+ }
+ }
+
+ if((prev_pymin > pymin && next_pymin > pymin) ||
+ (prev_pymin == pymin && next_pymin == pymin)) {
+ fill_min = pymin - 1;
+ PAINT_DOTA(buf, waveview->wave_r, waveview->wave_g, waveview->wave_b, waveview->wave_a, x, pymin-1);
+ }
+ else {
+ fill_min = MIN(prev_pymin, next_pymin);
+ if(pymin == fill_min) {
+ PAINT_DOTA(buf, waveview->wave_r, waveview->wave_g, waveview->wave_b, waveview->wave_a, x, pymin);
+ }
+ else {
+ PAINT_VERTA(buf, waveview->wave_r, waveview->wave_g, waveview->wave_b, waveview->wave_a, x, fill_min, pymin);
+ }
+ }
+
+ if(fill_max < fill_min) {
+ PAINT_VERTA(buf, waveview->fill_r, waveview->fill_g, waveview->fill_b, waveview->fill_a, x, fill_max, fill_min);
+ }
+ else if(fill_max == fill_min) {
+ PAINT_DOTA(buf, waveview->fill_r, waveview->fill_g, waveview->fill_b, waveview->fill_a, x, fill_max);
+ }
+ }
+
+ if (clip_max) {
+ PAINT_VERTA(buf, waveview->clip_r, waveview->clip_g, waveview->clip_b, waveview->clip_a, x, pymax, pymax+clip_length);
+ }
- pymax = (int) rint ((item->y1 + origin - max) * item->canvas->pixels_per_unit);
- pymin = (int) rint ((item->y1 + origin - min) * item->canvas->pixels_per_unit);
+ if (clip_min) {
+ PAINT_VERTA(buf, waveview->clip_r, waveview->clip_g, waveview->clip_b, waveview->clip_a, x, pymin-clip_length, pymin);
+ }
+
+ prev_pymax = pymax;
+ prev_pymin = pymin;
}
+ }
+ else if(waveview->filled && rectify) {
+ int prev_pymax = -1;
+ int last_pymax = -1;
+ int next_pymax;
+ double max, min;
+ int next_clip_max = 0;
+ int next_clip_min = 0;
- /* OK, now fill the RGB buffer at x=i with a line between pymin and pymax,
- or, if samples_per_unit == 1, then a dot at each location.
- */
+ // for rectified, this stays constant throughout the loop
+ pymin = (int) rint ((item->y1 + waveview->height) * item->canvas->pixels_per_unit);
- if (pymax == pymin) {
- PAINT_DOTA(buf, waveview->wave_r, waveview->wave_g, waveview->wave_b, waveview->wave_a, x, pymin);
- } else {
- PAINT_VERTA(buf, waveview->wave_r, waveview->wave_g, waveview->wave_b, waveview->wave_a, x, pymax, pymin);
+ if(s1 < waveview->samples_per_unit) {
+ /* we haven't got a prev vars to compare with, so outline the whole line here */
+ prev_pymax = pymin;
}
-
- /* show clipped waveforms with small red lines */
+ else {
+ s1 -= waveview->samples_per_unit;
+ }
+
+ if(end == waveview->bbox_lrx) {
+ /* we don't have the NEXT vars for the last sample */
+ last_pymax = pymin;
+ }
+ else {
+ s2 += waveview->samples_per_unit;
+ }
+
+ cache_index = gnome_canvas_waveview_ensure_cache (waveview, s1, s2);
+
+ /*
+ * Compute the variables outside the rendering rect
+ */
+ if(prev_pymax < 0) {
+ max = MIN(waveview->cache->data[cache_index].max, 1.0);
+ min = MAX(waveview->cache->data[cache_index].min, -1.0);
- if (clip_max || clip_min) {
- clip_length = MIN(5,(waveview->height/4));
+ if (fabs (min) > fabs (max)) {
+ max = fabs (min);
+ }
+
+ prev_pymax = (int) rint ((item->y1 + waveview->height - max * waveview->height) * item->canvas->pixels_per_unit);
+ ++cache_index;
}
+ if(last_pymax < 0) {
+ /* take the index of one sample right of what we render */
+ int index = cache_index + (end - begin);
+
+ max = MIN(waveview->cache->data[index].max, 1.0);
+ min = MAX(waveview->cache->data[index].min, -1.0);
+
+ if (fabs (min) > fabs (max)) {
+ max = fabs (min);
+ }
- if (clip_max) {
- PAINT_VERTA(buf, waveview->clip_r, waveview->clip_g, waveview->clip_b, waveview->clip_a, x, pymax, pymax+clip_length);
+ last_pymax = (int) rint ((item->y1 + waveview->height - max * waveview->height) * item->canvas->pixels_per_unit);
}
- if (clip_min) {
- PAINT_VERTA(buf, waveview->clip_r, waveview->clip_g, waveview->clip_b, waveview->clip_a, x, pymin-clip_length, pymin);
+ /*
+ * initialize NEXT* variables for the first run, duplicated in the loop for speed
+ */
+ max = waveview->cache->data[cache_index].max;
+ min = waveview->cache->data[cache_index].min;
+
+ if (max >= 1.0) {
+ max = 1.0;
+ next_clip_max = 1;
+ }
+
+ if (min <= -1.0) {
+ min = -1.0;
+ next_clip_min = 1;
+ }
+
+ if (fabs (min) > fabs (max)) {
+ max = fabs (min);
+ }
+
+ next_pymax = (int) rint ((item->y1 + waveview->height - max * waveview->height) * item->canvas->pixels_per_unit);
+
+ /*
+ * And now the loop
+ */
+ for(x = begin; x < end; ++x) {
+ int clip_max = next_clip_max;
+ int clip_min = next_clip_min;
+ int fill_max;
+
+ pymax = next_pymax;
+
+ /* compute next */
+ if(x == end - 1) {
+ /*next is now the last column, which is outside the rendering rect, and possibly outside the region*/
+ next_pymax = last_pymax;
+ }
+ else {
+ ++cache_index;
+
+ max = waveview->cache->data[cache_index].max;
+ min = waveview->cache->data[cache_index].min;
+
+ if (max >= 1.0) {
+ max = 1.0;
+ next_clip_max = 1;
+ }
+
+ if (min <= -1.0) {
+ min = -1.0;
+ next_clip_min = 1;
+ }
+
+ if (fabs (min) > fabs (max)) {
+ max = fabs (min);
+ }
+
+ next_pymax = (int) rint ((item->y1 + waveview->height - max * waveview->height) * item->canvas->pixels_per_unit);
+ }
+
+ /* render */
+ if (pymax == pymin) {
+ PAINT_DOTA(buf, waveview->wave_r, waveview->wave_g, waveview->wave_b, waveview->wave_a, x, pymin);
+ } else {
+ if((prev_pymax < pymax && next_pymax < pymax) ||
+ (prev_pymax == pymax && next_pymax == pymax)) {
+ fill_max = pymax + 1;
+ PAINT_DOTA(buf, waveview->wave_r, waveview->wave_g, waveview->wave_b, waveview->wave_a, x, pymax);
+ }
+ else {
+ fill_max = MAX(prev_pymax, next_pymax);
+ if(pymax == fill_max) {
+ PAINT_DOTA(buf, waveview->wave_r, waveview->wave_g, waveview->wave_b, waveview->wave_a, x, pymax);
+ ++fill_max;
+ }
+ else {
+ PAINT_VERTA(buf, waveview->wave_r, waveview->wave_g, waveview->wave_b, waveview->wave_a, x, pymax, fill_max);
+ }
+ }
+
+ if(fill_max < pymin) {
+ PAINT_VERTA(buf, waveview->fill_r, waveview->fill_g, waveview->fill_b, waveview->fill_a, x, fill_max, pymin);
+ }
+ else if(fill_max == pymin) {
+ PAINT_DOTA(buf, waveview->fill_r, waveview->fill_g, waveview->fill_b, waveview->fill_a, x, pymin);
+ }
+ }
+
+ if (clip_max) {
+ PAINT_VERTA(buf, waveview->clip_r, waveview->clip_g, waveview->clip_b, waveview->clip_a, x, pymax, pymax+clip_length);
+ }
+
+ if (clip_min) {
+ PAINT_VERTA(buf, waveview->clip_r, waveview->clip_g, waveview->clip_b, waveview->clip_a, x, pymin-clip_length, pymin);
+ }
+
+ prev_pymax = pymax;
}
+ }
+ else {
+ cache_index = gnome_canvas_waveview_ensure_cache (waveview, s1, s2);
- /* presto, we're done */
+ for (x = begin; x < end; x++) {
+
+ double max, min;
+ int clip_max, clip_min;
+
+ clip_max = 0;
+ clip_min = 0;
+
+ max = waveview->cache->data[cache_index].max;
+ min = waveview->cache->data[cache_index].min;
+
+ if (max >= 1.0) {
+ max = 1.0;
+ clip_max = 1;
+ }
+
+ if (min <= -1.0) {
+ min = -1.0;
+ clip_min = 1;
+ }
+
+ if (rectify) {
+
+ if (fabs (min) > fabs (max)) {
+ max = fabs (min);
+ }
+
+ max = max * waveview->height;
+
+ pymax = (int) rint ((item->y1 + waveview->height - max) * item->canvas->pixels_per_unit);
+ pymin = (int) rint ((item->y1 + waveview->height) * item->canvas->pixels_per_unit);
+
+ } else {
+
+ max = max * half_height;
+ min = min * half_height;
+
+ pymax = (int) rint ((item->y1 + origin - max) * item->canvas->pixels_per_unit);
+ pymin = (int) rint ((item->y1 + origin - min) * item->canvas->pixels_per_unit);
+ }
+
+ /* OK, now fill the RGB buffer at x=i with a line between pymin and pymax,
+ or, if samples_per_unit == 1, then a dot at each location.
+ */
+
+ if (pymax == pymin) {
+ PAINT_DOTA(buf, waveview->wave_r, waveview->wave_g, waveview->wave_b, waveview->wave_a, x, pymin);
+ } else {
+ PAINT_VERTA(buf, waveview->wave_r, waveview->wave_g, waveview->wave_b, waveview->wave_a, x, pymax, pymin);
+ }
+
+ /* show clipped waveforms with small red lines */
+
+ if (clip_max) {
+ PAINT_VERTA(buf, waveview->clip_r, waveview->clip_g, waveview->clip_b, waveview->clip_a, x, pymax, pymax+clip_length);
+ }
+
+ if (clip_min) {
+ PAINT_VERTA(buf, waveview->clip_r, waveview->clip_g, waveview->clip_b, waveview->clip_a, x, pymin-clip_length, pymin);
+ }
+
+ /* presto, we're done */
- cache_index++;
+ cache_index++;
+ }
}
- if (!waveview->rectified) {
+ if (!waveview->rectified && waveview->zero_line) {
// Paint zeroline.
//PAINT_HORIZA(buf, waveview->zero_r, waveview->zero_g, waveview->zero_b, waveview->zero_a, begin, endi-1, origin );
diff --git a/gtk2_ardour/canvas-waveview.h b/gtk2_ardour/canvas-waveview.h
index 30696defd0..3d7b02946d 100644
--- a/gtk2_ardour/canvas-waveview.h
+++ b/gtk2_ardour/canvas-waveview.h
@@ -101,9 +101,12 @@ struct _GnomeCanvasWaveView
uint32_t wave_color;
uint32_t clip_color;
uint32_t zero_color;
+ uint32_t fill_color;
+ char filled;
char rectified;
- char logscaled;
+ char zero_line;
+ char logscaled;
/* These are updated by the update() routine
to optimize the render() routine, which may
@@ -116,6 +119,7 @@ struct _GnomeCanvasWaveView
int32_t bbox_lry;
unsigned char wave_r, wave_g, wave_b, wave_a;
unsigned char clip_r, clip_g, clip_b, clip_a;
+ unsigned char fill_r, fill_g, fill_b, fill_a;
uint32_t samples;
uint32_t region_start;
int32_t reload_cache_in_render;
diff --git a/gtk2_ardour/canvas_vars.h b/gtk2_ardour/canvas_vars.h
index bc17a1d988..f79515cd28 100644
--- a/gtk2_ardour/canvas_vars.h
+++ b/gtk2_ardour/canvas_vars.h
@@ -1,4 +1,5 @@
CANVAS_VARIABLE(canvasvar_WaveForm, "waveform")
+CANVAS_VARIABLE(canvasvar_WaveFormFill, "waveform fill")
CANVAS_VARIABLE(canvasvar_WaveFormClip, "clipped waveform")
CANVAS_VARIABLE(canvasvar_FrameBase, "region base")
CANVAS_VARIABLE(canvasvar_SelectedFrameBase, "selected region base")
diff --git a/gtk2_ardour/editor.cc b/gtk2_ardour/editor.cc
index 3ff52d69e7..5fe95f013b 100644
--- a/gtk2_ardour/editor.cc
+++ b/gtk2_ardour/editor.cc
@@ -1886,8 +1886,8 @@ Editor::add_region_context_items (StreamView* sv, boost::shared_ptr<Region> regi
MenuList& nudge_items = nudge_menu->items();
nudge_menu->set_name ("ArdourContextMenu");
- nudge_items.push_back (MenuElem (_("Nudge fwd"), (bind (mem_fun(*this, &Editor::nudge_forward), false))));
- nudge_items.push_back (MenuElem (_("Nudge bwd"), (bind (mem_fun(*this, &Editor::nudge_backward), false))));
+ nudge_items.push_back (MenuElem (_("Nudge fwd"), (bind (mem_fun(*this, &Editor::nudge_forward), false, false))));
+ nudge_items.push_back (MenuElem (_("Nudge bwd"), (bind (mem_fun(*this, &Editor::nudge_backward), false, false))));
nudge_items.push_back (MenuElem (_("Nudge fwd by capture offset"), (mem_fun(*this, &Editor::nudge_forward_capture_offset))));
nudge_items.push_back (MenuElem (_("Nudge bwd by capture offset"), (mem_fun(*this, &Editor::nudge_backward_capture_offset))));
@@ -2919,8 +2919,8 @@ Editor::setup_toolbar ()
nudge_box->set_spacing(1);
nudge_box->set_border_width (2);
- nudge_forward_button.signal_clicked().connect (bind (mem_fun(*this, &Editor::nudge_forward), false));
- nudge_backward_button.signal_clicked().connect (bind (mem_fun(*this, &Editor::nudge_backward), false));
+ nudge_forward_button.signal_button_release_event().connect (mem_fun(*this, &Editor::nudge_forward_release), false);
+ nudge_backward_button.signal_button_release_event().connect (mem_fun(*this, &Editor::nudge_backward_release), false);
nudge_box->pack_start (nudge_backward_button, false, false);
nudge_box->pack_start (nudge_forward_button, false, false);
diff --git a/gtk2_ardour/editor.h b/gtk2_ardour/editor.h
index bfdbcd4a6c..62031bea64 100644
--- a/gtk2_ardour/editor.h
+++ b/gtk2_ardour/editor.h
@@ -296,8 +296,8 @@ class Editor : public PublicEditor
/* nudge is initiated by transport controls owned by ARDOUR_UI */
- void nudge_forward (bool next);
- void nudge_backward (bool next);
+ void nudge_forward (bool next, bool force_playhead);
+ void nudge_backward (bool next, bool force_playhead);
/* nudge initiated from context menu */
@@ -2069,6 +2069,9 @@ class Editor : public PublicEditor
AudioClock nudge_clock;
nframes_t get_nudge_distance (nframes_t pos, nframes_t& next);
+
+ bool nudge_forward_release (GdkEventButton*);
+ bool nudge_backward_release (GdkEventButton*);
/* audio filters */
diff --git a/gtk2_ardour/editor_actions.cc b/gtk2_ardour/editor_actions.cc
index 11f56c4e94..ae576dada4 100644
--- a/gtk2_ardour/editor_actions.cc
+++ b/gtk2_ardour/editor_actions.cc
@@ -197,13 +197,13 @@ Editor::register_actions ()
act = ActionManager::register_action (editor_actions, "add-location-from-playhead", _("Add Mark from Playhead"), mem_fun(*this, &Editor::add_location_from_playhead_cursor));
ActionManager::session_sensitive_actions.push_back (act);
- act = ActionManager::register_action (editor_actions, "nudge-forward", _("Nudge Forward"), bind (mem_fun(*this, &Editor::nudge_forward), false));
+ act = ActionManager::register_action (editor_actions, "nudge-forward", _("Nudge Forward"), bind (mem_fun(*this, &Editor::nudge_forward), false, false));
ActionManager::session_sensitive_actions.push_back (act);
- act = ActionManager::register_action (editor_actions, "nudge-next-forward", _("Nudge Next Forward"), bind (mem_fun(*this, &Editor::nudge_forward), true));
+ act = ActionManager::register_action (editor_actions, "nudge-next-forward", _("Nudge Next Forward"), bind (mem_fun(*this, &Editor::nudge_forward), true, false));
ActionManager::session_sensitive_actions.push_back (act);
- act = ActionManager::register_action (editor_actions, "nudge-backward", _("Nudge Backward"), bind (mem_fun(*this, &Editor::nudge_backward), false));
+ act = ActionManager::register_action (editor_actions, "nudge-backward", _("Nudge Backward"), bind (mem_fun(*this, &Editor::nudge_backward), false, false));
ActionManager::session_sensitive_actions.push_back (act);
- act = ActionManager::register_action (editor_actions, "nudge-next-backward", _("Nudge Next Backward"), bind (mem_fun(*this, &Editor::nudge_backward), true));
+ act = ActionManager::register_action (editor_actions, "nudge-next-backward", _("Nudge Next Backward"), bind (mem_fun(*this, &Editor::nudge_backward), true, false));
ActionManager::session_sensitive_actions.push_back (act);
diff --git a/gtk2_ardour/editor_ops.cc b/gtk2_ardour/editor_ops.cc
index 9f5cb638dd..a81a6e6965 100644
--- a/gtk2_ardour/editor_ops.cc
+++ b/gtk2_ardour/editor_ops.cc
@@ -65,6 +65,7 @@
#include "editing.h"
#include "gtk-custom-hruler.h"
#include "gui_thread.h"
+#include "keyboard.h"
#include "i18n.h"
@@ -330,16 +331,38 @@ Editor::extend_selection_to_start_of_region (bool previous)
commit_reversible_command ();
}
+bool
+Editor::nudge_forward_release (GdkEventButton* ev)
+{
+ if (ev->state & Keyboard::PrimaryModifier) {
+ nudge_forward (false, true);
+ } else {
+ nudge_forward (false, false);
+ }
+ return false;
+}
+
+bool
+Editor::nudge_backward_release (GdkEventButton* ev)
+{
+ if (ev->state & Keyboard::PrimaryModifier) {
+ nudge_backward (false, true);
+ } else {
+ nudge_backward (false, false);
+ }
+ return false;
+}
+
void
-Editor::nudge_forward (bool next)
+Editor::nudge_forward (bool next, bool force_playhead)
{
nframes_t distance;
nframes_t next_distance;
if (!session) return;
- if (!selection->regions.empty()) {
+ if (!force_playhead && !selection->regions.empty()) {
begin_reversible_command (_("nudge regions forward"));
@@ -361,7 +384,7 @@ Editor::nudge_forward (bool next)
commit_reversible_command ();
- } else if (!selection->markers.empty()) {
+ } else if (!force_playhead && !selection->markers.empty()) {
bool is_start;
Location* loc = find_location_from_marker (selection->markers.front(), is_start);
@@ -405,14 +428,14 @@ Editor::nudge_forward (bool next)
}
void
-Editor::nudge_backward (bool next)
+Editor::nudge_backward (bool next, bool force_playhead)
{
nframes_t distance;
nframes_t next_distance;
if (!session) return;
- if (!selection->regions.empty()) {
+ if (!force_playhead && !selection->regions.empty()) {
begin_reversible_command (_("nudge regions backward"));
@@ -438,7 +461,7 @@ Editor::nudge_backward (bool next)
commit_reversible_command ();
- } else if (!selection->markers.empty()) {
+ } else if (!force_playhead && !selection->markers.empty()) {
bool is_start;
Location* loc = find_location_from_marker (selection->markers.front(), is_start);
diff --git a/gtk2_ardour/main.cc b/gtk2_ardour/main.cc
index e9c8613224..968ceccb3c 100644
--- a/gtk2_ardour/main.cc
+++ b/gtk2_ardour/main.cc
@@ -62,16 +62,6 @@ extern int curvetest (string);
static ARDOUR_UI *ui = 0;
static const char* localedir = LOCALEDIR;
-gint
-show_ui_callback (void *arg)
-{
- ARDOUR_UI * ui = (ARDOUR_UI *) arg;
-
- ui->hide_splash();
-
- return FALSE;
-}
-
void
gui_jack_error ()
{
@@ -166,6 +156,16 @@ fixup_bundle_environment ()
path += "/../Plugins";
setenv ("LADSPA_PATH", path.c_str(), 1);
+
+ cstr = getenv ("LV2_PATH");
+ if (cstr) {
+ path = cstr;
+ path += ':';
+ }
+ path = dir_path;
+ path += "/../Plugins";
+
+ setenv ("LV2_PATH", path.c_str(), 1);
path = dir_path;
path += "/../Frameworks/clearlooks";
@@ -363,13 +363,6 @@ int main (int argc, char *argv[])
exit (1);
}
- if (!no_splash) {
- ui->show_splash ();
- if (session_name.length()) {
- g_timeout_add (4000, show_ui_callback, ui);
- }
- }
-
setup_keybindings (ui);
ui->run (text_receiver);
diff --git a/gtk2_ardour/new_session_dialog.cc b/gtk2_ardour/new_session_dialog.cc
index db970b4d46..1b9d81df22 100644
--- a/gtk2_ardour/new_session_dialog.cc
+++ b/gtk2_ardour/new_session_dialog.cc
@@ -379,12 +379,9 @@ NewSessionDialog::NewSessionDialog()
title += _("Session Control");
set_title(title.get_string());
- //set_modal(false);
- //property_window_position().set_value(Gtk::WIN_POS_NONE);
+ set_position (Gtk::WIN_POS_MOUSE);
set_resizable(false);
- //property_destroy_with_parent().set_value(false);
set_has_separator(false);
- // add_button(Gtk::Stock::HELP, Gtk::RESPONSE_HELP);
add_button(Gtk::Stock::QUIT, Gtk::RESPONSE_CANCEL);
add_button(Gtk::Stock::CLEAR, Gtk::RESPONSE_NONE);
m_okbutton = add_button(Gtk::Stock::NEW, Gtk::RESPONSE_OK);
@@ -895,7 +892,7 @@ NewSessionDialog::template_chosen ()
void
NewSessionDialog::recent_row_activated (const Gtk::TreePath& path, Gtk::TreeViewColumn* col)
{
- response (Gtk::RESPONSE_YES);
+ response (Gtk::RESPONSE_OK);
}
void
diff --git a/gtk2_ardour/plugin_selector.cc b/gtk2_ardour/plugin_selector.cc
index 001ff370c8..d893bc5695 100644
--- a/gtk2_ardour/plugin_selector.cc
+++ b/gtk2_ardour/plugin_selector.cc
@@ -227,6 +227,7 @@ PluginSelector::refill ()
setup_filter_string (filterstr);
ladspa_refiller (filterstr);
+ lv2_refiller (filterstr);
vst_refiller (filterstr);
au_refiller (filterstr);
}
@@ -281,6 +282,14 @@ PluginSelector::ladspa_refiller (const std::string& filterstr)
}
void
+PluginSelector::lv2_refiller (const std::string& filterstr)
+{
+#ifdef HAVE_SLV2
+ refiller (manager->lv2_plugin_info(), filterstr, "LV2");
+#endif
+}
+
+void
PluginSelector::vst_refiller (const std::string& filterstr)
{
#ifdef VST_SUPPORT
diff --git a/gtk2_ardour/plugin_selector.h b/gtk2_ardour/plugin_selector.h
index ac300638d7..ea258d3be0 100644
--- a/gtk2_ardour/plugin_selector.h
+++ b/gtk2_ardour/plugin_selector.h
@@ -94,6 +94,7 @@ class PluginSelector : public ArdourDialog
void refill ();
void refiller (const ARDOUR::PluginInfoList& plugs, const::std::string& filterstr, const char* type);
void ladspa_refiller (const std::string&);
+ void lv2_refiller (const std::string&);
void vst_refiller (const std::string&);
void au_refiller (const std::string&);
diff --git a/gtk2_ardour/route_time_axis.cc b/gtk2_ardour/route_time_axis.cc
index 42b2e646ad..12a8ee67bb 100644
--- a/gtk2_ardour/route_time_axis.cc
+++ b/gtk2_ardour/route_time_axis.cc
@@ -176,7 +176,9 @@ RouteTimeAxisView::RouteTimeAxisView (PublicEditor& ed, Session& sess, boost::sh
label_view ();
- if (!Profile->get_sae()) {
+ if (0) {
+
+ /* old school - when we used to put an extra row of buttons in place */
controls_table.attach (hide_button, 0, 1, 1, 2, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
controls_table.attach (visual_button, 1, 2, 1, 2, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
@@ -185,11 +187,11 @@ RouteTimeAxisView::RouteTimeAxisView (PublicEditor& ed, Session& sess, boost::sh
} else {
- controls_table.attach (automation_button, 4, 5, 1, 2, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
+ controls_table.attach (automation_button, 5, 6, 1, 2, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
}
if (is_track() && track()->mode() == ARDOUR::Normal) {
- controls_table.attach (playlist_button, 5, 6, 1, 2, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
+ controls_table.attach (playlist_button, 4, 5, 1, 2, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
}
y_position = -1;
diff --git a/gtk2_ardour/splash.cc b/gtk2_ardour/splash.cc
new file mode 100644
index 0000000000..eee108c70b
--- /dev/null
+++ b/gtk2_ardour/splash.cc
@@ -0,0 +1,60 @@
+#include <string>
+
+#include <pbd/failed_constructor.h>
+#include <pbd/file_utils.h>
+#include <ardour/ardour.h>
+#include <ardour/filesystem_paths.h>
+
+#include "splash.h"
+
+#include "i18n.h"
+
+using namespace Gtk;
+using namespace Glib;
+using namespace std;
+using namespace ARDOUR;
+
+Splash::Splash ()
+{
+ sys::path splash_file;
+
+ if (!find_file_in_search_path (ardour_search_path(), "splash.png", splash_file)) {
+ throw failed_constructor();
+ }
+
+ try {
+ pixbuf = Gdk::Pixbuf::create_from_file (splash_file.to_string());
+ }
+
+ catch (...) {
+ throw failed_constructor();
+ }
+
+ set_size_request (pixbuf->get_width(), pixbuf->get_height());
+ set_type_hint (Gdk::WINDOW_TYPE_HINT_SPLASHSCREEN);
+ set_keep_above (true);
+ set_position (WIN_POS_CENTER);
+ add_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK);
+}
+
+bool
+Splash::on_button_release_event (GdkEventButton* ev)
+{
+ hide ();
+}
+
+bool
+Splash::on_expose_event (GdkEventExpose* ev)
+{
+ RefPtr<Gdk::Window> window = get_window();
+
+ Window::on_expose_event (ev);
+
+ window->draw_pixbuf (get_style()->get_bg_gc (STATE_NORMAL), pixbuf,
+ ev->area.x, ev->area.y,
+ ev->area.x, ev->area.y,
+ ev->area.width, ev->area.height,
+ Gdk::RGB_DITHER_NONE, 0, 0);
+
+ return true;
+}
diff --git a/gtk2_ardour/splash.h b/gtk2_ardour/splash.h
new file mode 100644
index 0000000000..3ef717d08d
--- /dev/null
+++ b/gtk2_ardour/splash.h
@@ -0,0 +1,41 @@
+/*
+ Copyright (C) 2008 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_gtk_splash_h__
+#define __ardour_gtk_splash_h__
+
+#include <gtkmm/window.h>
+#include <gdkmm/pixbuf.h>
+
+class ARDOUR_UI;
+
+class Splash : public Gtk::Window
+{
+ public:
+ Splash ();
+ ~Splash () {}
+
+ bool on_expose_event (GdkEventExpose*);
+ bool on_button_release_event (GdkEventButton*);
+
+ private:
+ Glib::RefPtr<Gdk::Pixbuf> pixbuf;
+};
+
+#endif /* __ardour_gtk_splash_h__ */
diff --git a/gtk2_ardour/time_axis_view.cc b/gtk2_ardour/time_axis_view.cc
index a707e36993..a9956f554e 100644
--- a/gtk2_ardour/time_axis_view.cc
+++ b/gtk2_ardour/time_axis_view.cc
@@ -128,7 +128,7 @@ TimeAxisView::TimeAxisView (ARDOUR::Session& sess, PublicEditor& ed, TimeAxisVie
controls_table.set_col_spacings (0);
controls_table.set_homogeneous (true);
- controls_table.attach (name_hbox, 0, 4, 0, 1, Gtk::SHRINK|Gtk::EXPAND, Gtk::SHRINK|Gtk::EXPAND);
+ controls_table.attach (name_hbox, 0, 4, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND, 3, 0);
controls_table.show_all ();
controls_table.set_no_show_all ();
@@ -143,8 +143,6 @@ TimeAxisView::TimeAxisView (ARDOUR::Session& sess, PublicEditor& ed, TimeAxisVie
controls_ebox.signal_button_release_event().connect (mem_fun (*this, &TimeAxisView::controls_ebox_button_release));
controls_ebox.signal_scroll_event().connect (mem_fun (*this, &TimeAxisView::controls_ebox_scroll), true);
- controls_lhs_pad.set_name ("TimeAxisViewControlsPadding");
- controls_hbox.pack_start (controls_lhs_pad,false,false);
controls_hbox.pack_start (controls_ebox,true,true);
controls_hbox.show ();
diff --git a/gtk2_ardour/waveview.cc b/gtk2_ardour/waveview.cc
index fef90cde22..f9f011ea41 100644
--- a/gtk2_ardour/waveview.cc
+++ b/gtk2_ardour/waveview.cc
@@ -267,6 +267,22 @@ Glib::PropertyProxy_ReadOnly<guint> WaveView::property_zero_color() const
{
return Glib::PropertyProxy_ReadOnly<guint> (this, "zero_color");
}
+Glib::PropertyProxy<guint> WaveView::property_fill_color()
+{
+ return Glib::PropertyProxy<guint> (this, "fill_color");
+}
+Glib::PropertyProxy_ReadOnly<guint> WaveView::property_fill_color() const
+{
+ return Glib::PropertyProxy_ReadOnly<guint> (this, "fill_color");
+}
+Glib::PropertyProxy<gint> WaveView::property_filled()
+{
+ return Glib::PropertyProxy<gint> (this, "filled");
+}
+Glib::PropertyProxy_ReadOnly<gint> WaveView::property_filled() const
+{
+ return Glib::PropertyProxy_ReadOnly<gint> (this, "filled");
+}
Glib::PropertyProxy<gint> WaveView::property_rectified()
{
return Glib::PropertyProxy<gint> (this, "rectified");
@@ -275,6 +291,14 @@ Glib::PropertyProxy_ReadOnly<gint> WaveView::property_rectified() const
{
return Glib::PropertyProxy_ReadOnly<gint> (this, "rectified");
}
+Glib::PropertyProxy<gint> WaveView::property_zero_line()
+{
+ return Glib::PropertyProxy<gint> (this, "zero_line");
+}
+Glib::PropertyProxy_ReadOnly<gint> WaveView::property_zero_line() const
+{
+ return Glib::PropertyProxy_ReadOnly<gint> (this, "zero_line");
+}
Glib::PropertyProxy<guint> WaveView::property_region_start()
{
return Glib::PropertyProxy<guint> (this, "region_start");
diff --git a/gtk2_ardour/waveview.h b/gtk2_ardour/waveview.h
index 99028f2519..2af3465932 100644
--- a/gtk2_ardour/waveview.h
+++ b/gtk2_ardour/waveview.h
@@ -144,9 +144,15 @@ public:
Glib::PropertyProxy_ReadOnly<guint> property_wave_color() const;
Glib::PropertyProxy<guint> property_clip_color();
Glib::PropertyProxy_ReadOnly<guint> property_clip_color() const;
- Glib::PropertyProxy<gint> property_rectified();
+ Glib::PropertyProxy<guint> property_fill_color();
+ Glib::PropertyProxy_ReadOnly<guint> property_fill_color() const;
+ Glib::PropertyProxy<gint> property_filled();
+ Glib::PropertyProxy_ReadOnly<gint> property_filled() const;
+ Glib::PropertyProxy<gint> property_zero_line();
+ Glib::PropertyProxy_ReadOnly<gint> property_zero_line() const;
Glib::PropertyProxy<guint> property_zero_color();
Glib::PropertyProxy_ReadOnly<guint> property_zero_color() const;
+ Glib::PropertyProxy<gint> property_rectified();
Glib::PropertyProxy_ReadOnly<gint> property_rectified() const;
Glib::PropertyProxy<guint> property_region_start();
Glib::PropertyProxy_ReadOnly<guint> property_region_start() const;
diff --git a/libs/ardour/SConscript b/libs/ardour/SConscript
index dce544b622..bb66118b53 100644
--- a/libs/ardour/SConscript
+++ b/libs/ardour/SConscript
@@ -142,6 +142,7 @@ arch_specific_objects = [ ]
osc_files = [ 'osc.cc' ]
vst_files = [ 'vst_plugin.cc', 'session_vst.cc' ]
+lv2_files = [ 'lv2_plugin.cc' ]
audiounit_files = [ 'audio_unit.cc' ]
coreaudio_files = [ 'coreaudiosource.cc' ]
extra_sources = [ ]
@@ -151,6 +152,10 @@ if ardour['VST']:
extra_sources += vst_files
ardour.Append(CCFLAGS="-DVST_SUPPORT", CPPPATH="#libs/fst")
+if ardour['LV2']:
+ extra_sources += lv2_files
+ ardour.Append(CCFLAGS="-DHAVE_SLV2")
+
if ardour['LIBLO']:
extra_sources += osc_files
@@ -309,6 +314,9 @@ ardour.Merge ([
ardour.Merge ([ libraries['soundtouch'] ])
timefx_sources += [ 'st_stretch.cc', 'st_pitch.cc' ]
+if ardour['LV2']:
+ ardour.Merge ([ libraries['slv2'] ])
+
if ardour['LIBLO']:
ardour.Merge ([ libraries['lo'] ])
diff --git a/libs/ardour/ardour/audio_unit.h b/libs/ardour/ardour/audio_unit.h
index 115e008a54..c781e8200d 100644
--- a/libs/ardour/ardour/audio_unit.h
+++ b/libs/ardour/ardour/audio_unit.h
@@ -144,9 +144,9 @@ class AUPluginInfo : public PluginInfo {
private:
boost::shared_ptr<CAComponentDescription> descriptor;
- static void discover_music (PluginInfoList&);
- static void discover_fx (PluginInfoList&);
- static void discover_by_description (PluginInfoList&, CAComponentDescription&);
+ static void discover_music (PluginInfoList&);
+ static void discover_fx (PluginInfoList&);
+ static void discover_by_description (PluginInfoList&, CAComponentDescription&);
};
typedef boost::shared_ptr<AUPluginInfo> AUPluginInfoPtr;
diff --git a/libs/ardour/ardour/io.h b/libs/ardour/ardour/io.h
index 0ae9cef55a..bd3cfcc30e 100644
--- a/libs/ardour/ardour/io.h
+++ b/libs/ardour/ardour/io.h
@@ -95,6 +95,9 @@ class IO : public Automatable, public Latent
void set_output_minimum (ChanCount n);
void set_output_maximum (ChanCount n);
+ bool active() const { return _active; }
+ void set_active (bool yn);
+
DataType default_type() const { return _default_type; }
void set_default_type(DataType t) { _default_type = t; }
@@ -184,6 +187,8 @@ class IO : public Automatable, public Latent
const ChanCount& n_outputs () const { return _outputs.count(); }
void attach_buffers(ChanCount ignored);
+
+ sigc::signal<void> active_changed;
sigc::signal<void,IOChange,void*> input_changed;
sigc::signal<void,IOChange,void*> output_changed;
@@ -268,6 +273,7 @@ class IO : public Automatable, public Latent
protected:
Panner* _panner;
BufferSet* _output_buffers; //< Set directly to output port buffers
+ bool _active;
gain_t _gain;
gain_t _effective_gain;
gain_t _desired_gain;
diff --git a/libs/ardour/ardour/ladspa_plugin.h b/libs/ardour/ardour/ladspa_plugin.h
index 976584b687..b26e4120b1 100644
--- a/libs/ardour/ardour/ladspa_plugin.h
+++ b/libs/ardour/ardour/ladspa_plugin.h
@@ -20,7 +20,6 @@
#ifndef __ardour_ladspa_plugin_h__
#define __ardour_ladspa_plugin_h__
-#include <list>
#include <set>
#include <vector>
#include <string>
@@ -33,11 +32,6 @@
#include <jack/types.h>
#include <ardour/ladspa.h>
#include <ardour/plugin.h>
-#include <ardour/ladspa_plugin.h>
-
-using std::string;
-using std::vector;
-using std::list;
namespace ARDOUR {
class AudioEngine;
@@ -90,10 +84,10 @@ class LadspaPlugin : public ARDOUR::Plugin
void set_block_size (nframes_t nframes) {}
- int connect_and_run (BufferSet& bufs, uint32_t& in, uint32_t& out, nframes_t nframes, nframes_t offset);
- string describe_parameter (Parameter);
- string state_node_name() const { return "ladspa"; }
- void print_parameter (uint32_t, char*, uint32_t len) const;
+ int connect_and_run (BufferSet& bufs, uint32_t& in, uint32_t& out, nframes_t nframes, nframes_t offset);
+ std::string describe_parameter (Parameter);
+ std::string state_node_name() const { return "ladspa"; }
+ void print_parameter (uint32_t, char*, uint32_t len) const;
bool parameter_is_audio(uint32_t) const;
bool parameter_is_control(uint32_t) const;
@@ -103,7 +97,7 @@ class LadspaPlugin : public ARDOUR::Plugin
XMLNode& get_state();
int set_state(const XMLNode& node);
- bool save_preset(string name);
+ bool save_preset(std::string name);
bool has_editor() const { return false; }
diff --git a/libs/ardour/ardour/lv2_plugin.h b/libs/ardour/ardour/lv2_plugin.h
new file mode 100644
index 0000000000..40b3c669fa
--- /dev/null
+++ b/libs/ardour/ardour/lv2_plugin.h
@@ -0,0 +1,138 @@
+/*
+ Copyright (C) 2008 Paul Davis
+ Author: Dave Robillard
+
+ 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_lv2_plugin_h__
+#define __ardour_lv2_plugin_h__
+
+#include <set>
+#include <vector>
+#include <string>
+#include <dlfcn.h>
+
+#include <sigc++/signal.h>
+
+#include <pbd/stateful.h>
+
+#include <jack/types.h>
+#include <slv2/slv2.h>
+#include <ardour/plugin.h>
+
+namespace ARDOUR {
+class AudioEngine;
+class Session;
+
+class LV2Plugin : public ARDOUR::Plugin
+{
+ public:
+ LV2Plugin (ARDOUR::AudioEngine&, ARDOUR::Session&, SLV2Plugin plugin, nframes_t sample_rate);
+ LV2Plugin (const LV2Plugin &);
+ ~LV2Plugin ();
+
+ /* Plugin interface */
+
+ std::string unique_id() const;
+ const char* label() const { return slv2_plugin_get_name(_plugin); }
+ const char* name() const { return slv2_plugin_get_name(_plugin); }
+ const char* maker() const { return slv2_plugin_get_author_name(_plugin); }
+ uint32_t parameter_count() const { return slv2_plugin_get_num_ports(_plugin); }
+ float default_value (uint32_t port);
+ nframes_t signal_latency() const;
+ void set_parameter (uint32_t port, float val);
+ float get_parameter (uint32_t port) const;
+ int get_parameter_descriptor (uint32_t which, ParameterDescriptor&) const;
+ uint32_t nth_parameter (uint32_t port, bool& ok) const;
+
+ std::set<Parameter> automatable() const;
+
+ void activate () {
+ if (!_was_activated) {
+ slv2_instance_activate(_instance);
+ _was_activated = true;
+ }
+ }
+
+ void deactivate () {
+ if (_was_activated) {
+ slv2_instance_deactivate(_instance);
+ _was_activated = false;
+ }
+ }
+
+ void cleanup () {
+ activate();
+ deactivate();
+ slv2_instance_free(_instance);
+ _instance = NULL;
+ }
+
+ void set_block_size (nframes_t nframes) {}
+
+ int connect_and_run (BufferSet& bufs, uint32_t& in, uint32_t& out, nframes_t nframes, nframes_t offset);
+ std::string describe_parameter (Parameter);
+ std::string state_node_name() const { return "lv2"; }
+ void print_parameter (uint32_t, char*, uint32_t len) const;
+
+ bool parameter_is_audio(uint32_t) const;
+ bool parameter_is_control(uint32_t) const;
+ bool parameter_is_input(uint32_t) const;
+ bool parameter_is_output(uint32_t) const;
+ bool parameter_is_toggled(uint32_t) const;
+
+ XMLNode& get_state();
+ int set_state(const XMLNode& node);
+ bool save_preset(std::string name);
+
+ bool has_editor() const { return false; }
+
+ int require_output_streams (uint32_t);
+
+ private:
+ void* _module;
+ SLV2Plugin _plugin;
+ SLV2Template _template;
+ SLV2Instance _instance;
+ nframes_t _sample_rate;
+ float* _control_data;
+ float* _shadow_data;
+ float* _latency_control_port;
+ bool _was_activated;
+ vector<bool> _port_is_input;
+
+ void init (SLV2Plugin plugin, nframes_t rate);
+ void run (nframes_t nsamples);
+ void latency_compute_run ();
+};
+
+class LV2PluginInfo : public PluginInfo {
+public:
+ LV2PluginInfo (void* slv2_plugin);;
+ ~LV2PluginInfo ();;
+ static PluginInfoList discover (void* slv2_world);
+
+ PluginPtr load (Session& session);
+
+ void* _slv2_plugin;
+};
+
+typedef boost::shared_ptr<LV2PluginInfo> LV2PluginInfoPtr;
+
+} // namespace ARDOUR
+
+#endif /* __ardour_lv2_plugin_h__ */
diff --git a/libs/ardour/ardour/plugin_manager.h b/libs/ardour/ardour/plugin_manager.h
index 64b871104b..dd50a079e3 100644
--- a/libs/ardour/ardour/plugin_manager.h
+++ b/libs/ardour/ardour/plugin_manager.h
@@ -27,20 +27,23 @@
#include <ardour/types.h>
#include <ardour/plugin.h>
+#ifdef HAVE_SLV2
+#include <slv2/slv2.h>
+#endif
+
namespace ARDOUR {
class Plugin;
-class Session;
-class AudioEngine;
class PluginManager {
public:
PluginManager ();
~PluginManager ();
- ARDOUR::PluginInfoList &vst_plugin_info () { return _vst_plugin_info; }
+ ARDOUR::PluginInfoList &vst_plugin_info () { return _vst_plugin_info; }
ARDOUR::PluginInfoList &ladspa_plugin_info () { return _ladspa_plugin_info; }
- ARDOUR::PluginInfoList &au_plugin_info () { return _au_plugin_info; }
+ ARDOUR::PluginInfoList &lv2_plugin_info () { return _lv2_plugin_info; }
+ ARDOUR::PluginInfoList &au_plugin_info () { return _au_plugin_info; }
void refresh ();
@@ -52,7 +55,12 @@ class PluginManager {
private:
ARDOUR::PluginInfoList _vst_plugin_info;
ARDOUR::PluginInfoList _ladspa_plugin_info;
+ ARDOUR::PluginInfoList _lv2_plugin_info;
ARDOUR::PluginInfoList _au_plugin_info;
+
+#ifdef HAVE_SLV2
+ SLV2World _lv2_world;
+#endif
std::map<uint32_t, std::string> rdf_type;
@@ -69,6 +77,9 @@ class PluginManager {
int au_discover ();
void au_refresh ();
+
+ int lv2_discover ();
+ void lv2_refresh ();
int vst_discover_from_path (std::string path);
int vst_discover (std::string path);
diff --git a/libs/ardour/ardour/route.h b/libs/ardour/ardour/route.h
index d2e40501f1..2466f37996 100644
--- a/libs/ardour/ardour/route.h
+++ b/libs/ardour/ardour/route.h
@@ -110,9 +110,6 @@ class Route : public IO
void set_gain (gain_t val, void *src);
void inc_gain (gain_t delta, void *src);
- bool active() const { return _active; }
- void set_active (bool yn);
-
void set_solo (bool yn, void *src);
bool soloed() const { return _soloed; }
@@ -203,7 +200,6 @@ class Route : public IO
sigc::signal<void,void*> record_enable_changed;
sigc::signal<void,void*> edit_group_changed;
sigc::signal<void,void*> mix_group_changed;
- sigc::signal<void> active_changed;
sigc::signal<void,void*> meter_change;
sigc::signal<void> signal_latency_changed;
sigc::signal<void> initial_delay_changed;
@@ -280,7 +276,6 @@ class Route : public IO
bool _soloed : 1;
bool _solo_safe : 1;
bool _recordable : 1;
- bool _active : 1;
bool _mute_affects_pre_fader : 1;
bool _mute_affects_post_fader : 1;
bool _mute_affects_control_outs : 1;
diff --git a/libs/ardour/ardour/types.h b/libs/ardour/ardour/types.h
index dd151abaf6..cc756b0ec6 100644
--- a/libs/ardour/ardour/types.h
+++ b/libs/ardour/ardour/types.h
@@ -350,6 +350,7 @@ namespace ARDOUR {
enum PluginType {
AudioUnit,
LADSPA,
+ LV2,
VST
};
diff --git a/libs/ardour/audio_diskstream.cc b/libs/ardour/audio_diskstream.cc
index c36c9de184..d65183a84f 100644
--- a/libs/ardour/audio_diskstream.cc
+++ b/libs/ardour/audio_diskstream.cc
@@ -523,6 +523,11 @@ AudioDiskstream::process (nframes_t transport_frame, nframes_t nframes, nframes_
commit_should_unlock = false;
+ if (!_io->active()) {
+ _processed = true;
+ return 0;
+ }
+
check_record_status (transport_frame, nframes, can_record);
nominally_recording = (can_record && re);
@@ -744,6 +749,7 @@ AudioDiskstream::process (nframes_t transport_frame, nframes_t nframes, nframes_
nframes_t total = chaninfo->playback_vector.len[0] + chaninfo->playback_vector.len[1];
if (necessary_samples > total) {
+ cerr << "underrun for " << _name << endl;
DiskUnderrun ();
goto out;
@@ -828,6 +834,10 @@ AudioDiskstream::commit (nframes_t nframes)
{
bool need_butler = false;
+ if (!_io->active()) {
+ return false;
+ }
+
if (_actual_speed < 0.0) {
playback_sample -= playback_distance;
} else {
diff --git a/libs/ardour/io.cc b/libs/ardour/io.cc
index 7a2ae2aad9..8231218e63 100644
--- a/libs/ardour/io.cc
+++ b/libs/ardour/io.cc
@@ -102,6 +102,7 @@ IO::IO (Session& s, const string& name,
DataType default_type, bool public_ports)
: Automatable (s, name),
_output_buffers (new BufferSet()),
+ _active(true),
_default_type (default_type),
_public_ports (public_ports),
_input_minimum (ChanCount::ZERO),
@@ -2350,6 +2351,14 @@ IO::find_output_port_hole ()
return n;
}
+void
+IO::set_active (bool yn)
+{
+ _active = yn;
+ active_changed(); /* EMIT SIGNAL */
+}
+
+
AudioPort*
IO::audio_input(uint32_t n) const
{
diff --git a/libs/ardour/lv2_plugin.cc b/libs/ardour/lv2_plugin.cc
new file mode 100644
index 0000000000..5df3756364
--- /dev/null
+++ b/libs/ardour/lv2_plugin.cc
@@ -0,0 +1,547 @@
+/*
+ Copyright (C) 2008 Paul Davis
+ Author: Dave Robillard
+
+ 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 <vector>
+#include <string>
+
+#include <cstdlib>
+#include <cmath>
+
+#include <pbd/compose.h>
+#include <pbd/error.h>
+#include <pbd/pathscanner.h>
+#include <pbd/xml++.h>
+
+#include <ardour/ardour.h>
+#include <ardour/session.h>
+#include <ardour/audioengine.h>
+#include <ardour/lv2_plugin.h>
+
+#include <pbd/stl_delete.h>
+
+#include "i18n.h"
+#include <locale.h>
+
+using namespace std;
+using namespace ARDOUR;
+using namespace PBD;
+
+LV2Plugin::LV2Plugin (AudioEngine& e, Session& session, SLV2Plugin plugin, nframes_t rate)
+ : Plugin (e, session)
+{
+ init (plugin, rate);
+}
+
+LV2Plugin::LV2Plugin (const LV2Plugin &other)
+ : Plugin (other)
+{
+ init (other._plugin, other._sample_rate);
+
+ for (uint32_t i = 0; i < parameter_count(); ++i) {
+ _control_data[i] = other._shadow_data[i];
+ _shadow_data[i] = other._shadow_data[i];
+ }
+}
+
+void
+LV2Plugin::init (SLV2Plugin plugin, nframes_t rate)
+{
+ _plugin = plugin;
+ _template = slv2_plugin_get_template(plugin);
+ _control_data = 0;
+ _shadow_data = 0;
+ _latency_control_port = 0;
+ _was_activated = false;
+
+ _instance = slv2_plugin_instantiate(plugin, rate, NULL);
+
+ if (_instance == 0) {
+ error << _("LV2: Failed to instantiate plugin ") << slv2_plugin_get_uri(plugin) << endl;
+ throw failed_constructor();
+ }
+
+ if (slv2_plugin_has_feature(plugin, "http://lv2plug.in/ns/lv2core#inPlaceBroken")) {
+ error << string_compose(_("LV2: \"%1\" cannot be used, since it cannot do inplace processing"), slv2_plugin_get_name(plugin)) << endmsg;
+ throw failed_constructor();
+ }
+
+ _sample_rate = rate;
+
+ const uint32_t num_ports = slv2_plugin_get_num_ports(plugin);
+
+ _control_data = new float[num_ports];
+ _shadow_data = new float[num_ports];
+
+ const bool latent = slv2_plugin_has_latency(plugin);
+ uint32_t latency_port = (latent ? slv2_plugin_get_latency_port(plugin) : 0);
+
+ for (uint32_t i = 0; i < num_ports; ++i) {
+ if (parameter_is_control(i)) {
+ slv2_instance_connect_port (_instance, i, &_control_data[i]);
+
+ if (latent && i == latency_port) {
+ _latency_control_port = &_control_data[i];
+ *_latency_control_port = 0;
+ }
+
+ if (parameter_is_input(i)) {
+ _shadow_data[i] = default_value (i);
+ }
+ }
+ }
+
+ latency_compute_run ();
+}
+
+LV2Plugin::~LV2Plugin ()
+{
+ deactivate ();
+ cleanup ();
+
+ GoingAway (); /* EMIT SIGNAL */
+
+ slv2_instance_free(_instance);
+
+ if (_control_data) {
+ delete [] _control_data;
+ }
+
+ if (_shadow_data) {
+ delete [] _shadow_data;
+ }
+}
+
+string
+LV2Plugin::unique_id() const
+{
+ return slv2_plugin_get_uri(_plugin);
+}
+
+
+float
+LV2Plugin::default_value (uint32_t port)
+{
+ return slv2_port_get_default_value(_plugin,
+ slv2_plugin_get_port_by_index(_plugin, port));
+}
+
+void
+LV2Plugin::set_parameter (uint32_t which, float val)
+{
+ if (which < slv2_plugin_get_num_ports(_plugin)) {
+ _shadow_data[which] = val;
+#if 0
+ ParameterChanged (which, val); /* EMIT SIGNAL */
+
+ if (which < parameter_count() && controls[which]) {
+ controls[which]->Changed ();
+ }
+#endif
+
+ } else {
+ warning << string_compose (_("Illegal parameter number used with plugin \"%1\"."
+ "This is a bug in either Ardour or the LV2 plugin (%2)"),
+ name(), unique_id()) << endmsg;
+ }
+}
+
+float
+LV2Plugin::get_parameter (uint32_t which) const
+{
+ if (parameter_is_input(which)) {
+ return (float) _shadow_data[which];
+ } else {
+ return (float) _control_data[which];
+ }
+ return 0.0f;
+}
+
+uint32_t
+LV2Plugin::nth_parameter (uint32_t n, bool& ok) const
+{
+ uint32_t x, c;
+
+ ok = false;
+
+ for (c = 0, x = 0; x < slv2_plugin_get_num_ports(_plugin); ++x) {
+ if (parameter_is_control (x)) {
+ if (c++ == n) {
+ ok = true;
+ return x;
+ }
+ }
+ }
+
+ return 0;
+}
+
+XMLNode&
+LV2Plugin::get_state()
+{
+ XMLNode *root = new XMLNode(state_node_name());
+ XMLNode *child;
+ char buf[16];
+ LocaleGuard lg (X_("POSIX"));
+
+ for (uint32_t i = 0; i < parameter_count(); ++i){
+
+ if (parameter_is_input(i) && parameter_is_control(i)) {
+ child = new XMLNode("port");
+ snprintf(buf, sizeof(buf), "%u", i);
+ child->add_property("number", string(buf));
+ snprintf(buf, sizeof(buf), "%+f", _shadow_data[i]);
+ child->add_property("value", string(buf));
+ root->add_child_nocopy (*child);
+
+ /*if (i < controls.size() && controls[i]) {
+ root->add_child_nocopy (controls[i]->get_state());
+ }*/
+ }
+ }
+
+ return *root;
+}
+
+bool
+LV2Plugin::save_preset (string name)
+{
+ return Plugin::save_preset (name, "lv2");
+}
+
+int
+LV2Plugin::set_state(const XMLNode& node)
+{
+ XMLNodeList nodes;
+ XMLProperty *prop;
+ XMLNodeConstIterator iter;
+ XMLNode *child;
+ const char *port;
+ const char *data;
+ uint32_t port_id;
+ LocaleGuard lg (X_("POSIX"));
+
+ if (node.name() != state_node_name()) {
+ error << _("Bad node sent to LV2Plugin::set_state") << endmsg;
+ return -1;
+ }
+
+ nodes = node.children ("port");
+
+ for(iter = nodes.begin(); iter != nodes.end(); ++iter){
+
+ child = *iter;
+
+ if ((prop = child->property("number")) != 0) {
+ port = prop->value().c_str();
+ } else {
+ warning << _("LV2: no lv2 port number") << endmsg;
+ continue;
+ }
+
+ if ((prop = child->property("value")) != 0) {
+ data = prop->value().c_str();
+ } else {
+ warning << _("LV2: no lv2 port data") << endmsg;
+ continue;
+ }
+
+ sscanf (port, "%" PRIu32, &port_id);
+ set_parameter (port_id, atof(data));
+ }
+
+ latency_compute_run ();
+
+ return 0;
+}
+
+int
+LV2Plugin::get_parameter_descriptor (uint32_t which, ParameterDescriptor& desc) const
+{
+ SLV2Port port = slv2_plugin_get_port_by_index(_plugin, which);
+
+ #define LV2_URI "http://lv2plug.in/ns/lv2core#"
+
+ desc.integer_step = slv2_port_has_property(_plugin, port, LV2_URI "integer");
+ desc.toggled = slv2_port_has_property(_plugin, port, LV2_URI "toggled");
+ desc.logarithmic = false; // TODO (LV2 extension)
+ desc.sr_dependent = slv2_port_has_property(_plugin, port, LV2_URI "sampleRate");
+ desc.label = slv2_port_get_name(_plugin, port);
+ desc.lower = slv2_port_get_minimum_value(_plugin, port);
+ desc.upper = slv2_port_get_maximum_value(_plugin, port);
+ desc.min_unbound = false; // TODO (LV2 extension)
+ desc.max_unbound = false; // TODO (LV2 extension)
+
+ if (desc.integer_step) {
+ desc.step = 1.0;
+ desc.smallstep = 0.1;
+ desc.largestep = 10.0;
+ } else {
+ const float delta = desc.upper - desc.lower;
+ desc.step = delta / 1000.0f;
+ desc.smallstep = delta / 10000.0f;
+ desc.largestep = delta/10.0f;
+ }
+
+ return 0;
+}
+
+
+string
+LV2Plugin::describe_parameter (Parameter which)
+{
+ if (which.type() == PluginAutomation && which.id() < parameter_count()) {
+ return slv2_port_get_name(_plugin,
+ slv2_plugin_get_port_by_index(_plugin, which));
+ } else {
+ return "??";
+ }
+}
+
+nframes_t
+LV2Plugin::signal_latency () const
+{
+ if (_latency_control_port) {
+ return (nframes_t) floor (*_latency_control_port);
+ } else {
+ return 0;
+ }
+}
+
+set<Parameter>
+LV2Plugin::automatable () const
+{
+ set<Parameter> ret;
+
+ for (uint32_t i = 0; i < parameter_count(); ++i){
+ if (parameter_is_input(i) && parameter_is_control(i)) {
+ ret.insert (ret.end(), Parameter(PluginAutomation, i));
+ }
+ }
+
+ return ret;
+}
+
+int
+LV2Plugin::connect_and_run (BufferSet& bufs, uint32_t& in_index, uint32_t& out_index, nframes_t nframes, nframes_t offset)
+{
+ uint32_t port_index;
+ cycles_t then, now;
+
+ port_index = 0;
+
+ then = get_cycles ();
+
+ const uint32_t nbufs = bufs.count().n_audio();
+
+ while (port_index < parameter_count()) {
+ if (parameter_is_audio(port_index)) {
+ if (parameter_is_input(port_index)) {
+ const size_t index = min(in_index, nbufs - 1);
+ slv2_instance_connect_port(_instance, port_index,
+ bufs.get_audio(index).data(nframes, offset));
+ in_index++;
+ } else if (parameter_is_output(port_index)) {
+ const size_t index = min(out_index,nbufs - 1);
+ slv2_instance_connect_port(_instance, port_index,
+ bufs.get_audio(index).data(nframes, offset));
+ out_index++;
+ }
+ }
+ port_index++;
+ }
+
+ run (nframes);
+ now = get_cycles ();
+ set_cycles ((uint32_t) (now - then));
+
+ return 0;
+}
+
+bool
+LV2Plugin::parameter_is_control (uint32_t param) const
+{
+ SLV2PortSignature sig = slv2_template_get_port(_template, param);
+ return (slv2_port_signature_get_type(sig) == SLV2_PORT_DATA_TYPE_CONTROL);
+}
+
+bool
+LV2Plugin::parameter_is_audio (uint32_t param) const
+{
+ SLV2PortSignature sig = slv2_template_get_port(_template, param);
+ return (slv2_port_signature_get_type(sig) == SLV2_PORT_DATA_TYPE_AUDIO);
+}
+
+bool
+LV2Plugin::parameter_is_output (uint32_t param) const
+{
+ SLV2PortSignature sig = slv2_template_get_port(_template, param);
+ return (slv2_port_signature_get_direction(sig) == SLV2_PORT_DIRECTION_OUTPUT);
+}
+
+bool
+LV2Plugin::parameter_is_input (uint32_t param) const
+{
+ SLV2PortSignature sig = slv2_template_get_port(_template, param);
+ return (slv2_port_signature_get_direction(sig) == SLV2_PORT_DIRECTION_INPUT);
+}
+
+void
+LV2Plugin::print_parameter (uint32_t param, char *buf, uint32_t len) const
+{
+ if (buf && len) {
+ if (param < parameter_count()) {
+ snprintf (buf, len, "%.3f", get_parameter (param));
+ } else {
+ strcat (buf, "0");
+ }
+ }
+}
+
+void
+LV2Plugin::run (nframes_t nframes)
+{
+ for (uint32_t i = 0; i < parameter_count(); ++i) {
+ SLV2PortSignature sig = slv2_template_get_port(_template, i);
+ if (slv2_port_signature_get_type(sig) == SLV2_PORT_DATA_TYPE_CONTROL
+ && slv2_port_signature_get_direction(sig) == SLV2_PORT_DIRECTION_INPUT) {
+ _control_data[i] = _shadow_data[i];
+ }
+ }
+
+ slv2_instance_run(_instance, nframes);
+}
+
+void
+LV2Plugin::latency_compute_run ()
+{
+ if (!_latency_control_port) {
+ return;
+ }
+
+ /* we need to run the plugin so that it can set its latency
+ parameter.
+ */
+
+ activate ();
+
+ uint32_t port_index = 0;
+ uint32_t in_index = 0;
+ uint32_t out_index = 0;
+ const nframes_t bufsize = 1024;
+ float buffer[bufsize];
+
+ memset(buffer,0,sizeof(float)*bufsize);
+
+ /* Note that we've already required that plugins
+ be able to handle in-place processing.
+ */
+
+ port_index = 0;
+
+ while (port_index < parameter_count()) {
+ if (parameter_is_audio (port_index)) {
+ if (parameter_is_input (port_index)) {
+ slv2_instance_connect_port (_instance, port_index, buffer);
+ in_index++;
+ } else if (parameter_is_output (port_index)) {
+ slv2_instance_connect_port (_instance, port_index, buffer);
+ out_index++;
+ }
+ }
+ port_index++;
+ }
+
+ run (bufsize);
+ deactivate ();
+}
+
+LV2PluginInfo::LV2PluginInfo (void* slv2_plugin)
+ : _slv2_plugin(slv2_plugin)
+{
+}
+
+LV2PluginInfo::~LV2PluginInfo()
+{
+}
+
+PluginPtr
+LV2PluginInfo::load (Session& session)
+{
+ SLV2Plugin p = (SLV2Plugin)_slv2_plugin;
+
+ try {
+ PluginPtr plugin;
+
+ plugin.reset (new LV2Plugin (session.engine(), session, p, session.frame_rate()));
+
+ plugin->set_info(PluginInfoPtr(new LV2PluginInfo(*this)));
+ return plugin;
+ }
+
+ catch (failed_constructor &err) {
+ return PluginPtr ((Plugin*) 0);
+ }
+
+ return PluginPtr();
+}
+
+PluginInfoList
+LV2PluginInfo::discover (void* slv2_world)
+{
+ PluginInfoList plugs;
+
+ SLV2Plugins plugins = slv2_world_get_all_plugins((SLV2World)slv2_world);
+
+ for (unsigned i=0; i < slv2_plugins_size(plugins); ++i) {
+ SLV2Plugin p = slv2_plugins_get_at(plugins, i);
+ LV2PluginInfoPtr info (new LV2PluginInfo(p));
+
+ info->name = slv2_plugin_get_name(p);
+
+ SLV2PluginClass pclass = slv2_plugin_get_class(p);
+ info->category = slv2_plugin_class_get_label(pclass);
+
+ char* author_name = slv2_plugin_get_author_name(p);
+ info->creator = author_name ? string(author_name) : "Unknown";
+ free(author_name);
+
+ info->path = "/NOPATH"; // Meaningless for LV2
+
+ SLV2Template io = slv2_plugin_get_template(p);
+
+ info->n_inputs.set_audio(slv2_template_get_num_ports_of_type(io,
+ SLV2_PORT_DIRECTION_INPUT, SLV2_PORT_DATA_TYPE_AUDIO));
+ info->n_outputs.set_audio(slv2_template_get_num_ports_of_type(io,
+ SLV2_PORT_DIRECTION_OUTPUT, SLV2_PORT_DATA_TYPE_AUDIO));
+
+ info->n_inputs.set_midi(slv2_template_get_num_ports_of_type(io,
+ SLV2_PORT_DIRECTION_INPUT, SLV2_PORT_DATA_TYPE_MIDI));
+ info->n_outputs.set_midi(slv2_template_get_num_ports_of_type(io,
+ SLV2_PORT_DIRECTION_OUTPUT, SLV2_PORT_DATA_TYPE_MIDI));
+
+ info->unique_id = slv2_plugin_get_uri(p);
+ info->index = 0; // Meaningless for LV2
+
+ plugs.push_back (info);
+ }
+
+ return plugs;
+}
+
diff --git a/libs/ardour/plugin.cc b/libs/ardour/plugin.cc
index 7f3f21b1fe..95629f2561 100644
--- a/libs/ardour/plugin.cc
+++ b/libs/ardour/plugin.cc
@@ -44,6 +44,10 @@
#include <ardour/audio_unit.h>
#endif
+#ifdef HAVE_SLV2
+#include <ardour/lv2_plugin.h>
+#endif
+
#include <pbd/stl_delete.h>
#include "i18n.h"
@@ -190,6 +194,12 @@ ARDOUR::find_plugin(Session& session, string identifier, PluginType type)
case ARDOUR::LADSPA:
plugs = mgr->ladspa_plugin_info();
break;
+
+#ifdef HAVE_SLV2
+ case ARDOUR::LV2:
+ plugs = mgr->lv2_plugin_info();
+ break;
+#endif
#ifdef VST_SUPPORT
case ARDOUR::VST:
diff --git a/libs/ardour/plugin_insert.cc b/libs/ardour/plugin_insert.cc
index 4153f26e85..26d344dee4 100644
--- a/libs/ardour/plugin_insert.cc
+++ b/libs/ardour/plugin_insert.cc
@@ -32,6 +32,10 @@
#include <ardour/buffer_set.h>
#include <ardour/automation_event.h>
+#ifdef HAVE_SLV2
+#include <ardour/lv2_plugin.h>
+#endif
+
#ifdef VST_SUPPORT
#include <ardour/vst_plugin.h>
#endif
@@ -433,6 +437,9 @@ boost::shared_ptr<Plugin>
PluginInsert::plugin_factory (boost::shared_ptr<Plugin> other)
{
boost::shared_ptr<LadspaPlugin> lp;
+#ifdef HAVE_SLV2
+ boost::shared_ptr<LV2Plugin> lv2p;
+#endif
#ifdef VST_SUPPORT
boost::shared_ptr<VSTPlugin> vp;
#endif
@@ -442,6 +449,10 @@ PluginInsert::plugin_factory (boost::shared_ptr<Plugin> other)
if ((lp = boost::dynamic_pointer_cast<LadspaPlugin> (other)) != 0) {
return boost::shared_ptr<Plugin> (new LadspaPlugin (*lp));
+#ifdef HAVE_SLV2
+ } else if ((lv2p = boost::dynamic_pointer_cast<LV2Plugin> (other)) != 0) {
+ return boost::shared_ptr<Plugin> (new LV2Plugin (*lv2p));
+#endif
#ifdef VST_SUPPORT
} else if ((vp = boost::dynamic_pointer_cast<VSTPlugin> (other)) != 0) {
return boost::shared_ptr<Plugin> (new VSTPlugin (*vp));
@@ -650,6 +661,8 @@ PluginInsert::set_state(const XMLNode& node)
if (prop->value() == X_("ladspa") || prop->value() == X_("Ladspa")) { /* handle old school sessions */
type = ARDOUR::LADSPA;
+ } else if (prop->value() == X_("lv2")) {
+ type = ARDOUR::LV2;
} else if (prop->value() == X_("vst")) {
type = ARDOUR::VST;
} else {
diff --git a/libs/ardour/plugin_manager.cc b/libs/ardour/plugin_manager.cc
index d321d6f259..ae5d6f52ee 100644
--- a/libs/ardour/plugin_manager.cc
+++ b/libs/ardour/plugin_manager.cc
@@ -39,6 +39,11 @@
#include <ardour/plugin.h>
#include <ardour/ladspa_plugin.h>
+#ifdef HAVE_SLV2
+#include <slv2/slv2.h>
+#include <ardour/lv2_plugin.h>
+#endif
+
#ifdef VST_SUPPORT
#include <ardour/vst_plugin.h>
#endif
@@ -104,6 +109,11 @@ PluginManager::PluginManager ()
ladspa_plugin_whitelist.push_back (2150); // tap pitch shifter
}
+#ifdef HAVE_SLV2
+ _lv2_world = slv2_world_new();
+ slv2_world_load_all(_lv2_world);
+#endif
+
refresh ();
}
@@ -111,6 +121,9 @@ void
PluginManager::refresh ()
{
ladspa_refresh ();
+#ifdef HAVE_SLV2
+ lv2_refresh ();
+#endif
#ifdef VST_SUPPORT
if (Config->get_use_vst()) {
vst_refresh ();
@@ -345,6 +358,21 @@ PluginManager::get_ladspa_category (uint32_t plugin_id)
return label;
}
+#ifdef HAVE_SLV2
+void
+PluginManager::lv2_refresh ()
+{
+ lv2_discover();
+}
+
+int
+PluginManager::lv2_discover ()
+{
+ _lv2_plugin_info = LV2PluginInfo::discover(_lv2_world);
+ return 0;
+}
+#endif
+
#ifdef HAVE_AUDIOUNITS
void
PluginManager::au_refresh ()
diff --git a/libs/ardour/route.cc b/libs/ardour/route.cc
index 084c4e58b5..fd0d99e87a 100644
--- a/libs/ardour/route.cc
+++ b/libs/ardour/route.cc
@@ -1666,6 +1666,7 @@ Route::add_processor_from_xml (const XMLNode& node)
bool have_insert = false;
if (prop->value() == "ladspa" || prop->value() == "Ladspa" ||
+ prop->value() == "lv2" ||
prop->value() == "vst" ||
prop->value() == "audiounit") {
@@ -2282,13 +2283,6 @@ Route::get_mute_config (mute_type t)
}
void
-Route::set_active (bool yn)
-{
- _active = yn;
- active_changed(); /* EMIT SIGNAL */
-}
-
-void
Route::handle_transport_stopped (bool abort_ignored, bool did_locate, bool can_flush_processors)
{
nframes_t now = _session.transport_frame();
diff --git a/libs/ardour/session_command.cc b/libs/ardour/session_command.cc
index 534f2ffe81..e8670e7199 100644
--- a/libs/ardour/session_command.cc
+++ b/libs/ardour/session_command.cc
@@ -90,7 +90,10 @@ Session::memento_command_factory(XMLNode *n)
if (sources.count(id))
return new MementoCommand<Source>(*sources[id], before, after);
} else if (obj_T == typeid (Location).name()) {
- return new MementoCommand<Location>(*_locations.get_location_by_id(id), before, after);
+ Location* loc = _locations.get_location_by_id(id);
+ if (loc) {
+ return new MementoCommand<Location>(*loc, before, after);
+ }
} else if (obj_T == typeid (Locations).name()) {
return new MementoCommand<Locations>(_locations, before, after);
} else if (obj_T == typeid (TempoMap).name()) {
diff --git a/svn_revision.h b/svn_revision.h
index d417a995ab..14515fb63b 100644
--- a/svn_revision.h
+++ b/svn_revision.h
@@ -1,4 +1,4 @@
#ifndef __ardour_svn_revision_h__
#define __ardour_svn_revision_h__
-static const char* ardour_svn_revision = "2914";
+static const char* ardour_svn_revision = "2918";
#endif
diff --git a/tools/osx_packaging/script b/tools/osx_packaging/script
index faf92eded8..b003337418 100755
--- a/tools/osx_packaging/script
+++ b/tools/osx_packaging/script
@@ -32,17 +32,22 @@ if [ "$?" != "0" -a ! -f ~/.xinitrc ]; then
sed 's/xterm/# xterm/' /usr/X11R6/lib/X11/xinit/xinitrc >> ~/.xinitrc
fi
-mkdir -p $TMP
-cp -f "$CWD/bin/getdisplay.sh" $TMP
-rm -f $TMP/display
-open-x11 $TMP/getdisplay.sh || \
-open -a XDarwin $TMP/getdisplay.sh || \
-echo ":0" > $TMP/display
-
-while [ "$?" == "0" -a ! -f $TMP/display ]; do sleep 1; done
-export "DISPLAY=`cat $TMP/display`"
-
-ps -wx -ocommand | grep -e '[X]11' > /dev/null || exit 11
+if uname -r | grep -sq '^9' ; then
+ # leopard will auto-start X11 for us
+ :
+else
+ mkdir -p $TMP
+ cp -f "$CWD/bin/getdisplay.sh" $TMP
+ rm -f $TMP/display
+ open-x11 $TMP/getdisplay.sh || \
+ open -a XDarwin $TMP/getdisplay.sh || \
+ echo ":0" > $TMP/display
+
+ while [ "$?" == "0" -a ! -f $TMP/display ]; do sleep 1; done
+ export "DISPLAY=`cat $TMP/display`"
+
+ ps -wx -ocommand | grep -e '[X]11' > /dev/null || exit 11
+fi
cd ~/
shift