13
0

Merge with trunk R2935.

git-svn-id: svn://localhost/ardour2/branches/3.0@2943 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
David Robillard 2008-01-19 03:49:52 +00:00
parent f80fad313a
commit 4ca1fe7993
44 changed files with 1814 additions and 525 deletions

View File

@ -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()

View File

@ -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 +

View File

@ -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;

View File

@ -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"/>

View File

@ -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);
// in 4 seconds, hide the splash screen
msg.set_position (Gtk::WIN_POS_MOUSE);
msg.present ();
msg.run ();
Glib::signal_timeout().connect (bind (sigc::ptr_fun (_hide_splash), this), 4000);
exit (1);
}
}
}
hide_splash ();
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::get_session_parameters (Glib::ustring predetermined_path, bool have_engine, bool should_be_new)
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 (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));
parse_cmdline_path (ARDOUR_COMMAND_LINE::session_name, session_name, session_path, existing_session);
/* don't ever reuse this */
ARDOUR_COMMAND_LINE::session_name = string();
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;
}
}
session_name = basename_nosuffix (string (predetermined_path));
/* make the NSD use whatever information we have */
new_session_dialog->set_session_name (session_name);
new_session_dialog->set_session_folder (session_path);
new_session_dialog->set_modal (true);
if (existing_session) {
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;
}
}
}
}
/* 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) {
session_name = new_session_dialog->session_name();
/* YES == OPEN from the session selector */
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 (Glib::file_test (session_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) {
if (load_session (session_path, session_name)) {
response = Gtk::RESPONSE_NONE;
goto try_again;
}
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 ()
{

View File

@ -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 */

View File

@ -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

View File

@ -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 */

View File

@ -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();
}
}
}

View File

@ -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,
@ -273,6 +290,13 @@ gnome_canvas_waveview_class_init (GnomeCanvasWaveViewClass *class)
FALSE,
(G_PARAM_READABLE | G_PARAM_WRITABLE)));
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,
@ -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
for (x = begin; x < end; x++) {
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 clip_max, clip_min;
clip_max = 0;
clip_min = 0;
int next_clip_max = 0;
int next_clip_min = 0;
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;
}
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;
max = waveview->cache->data[cache_index].max;
min = waveview->cache->data[cache_index].min;
next_clip_max = 0;
next_clip_min = 0;
if (max >= 1.0) {
max = 1.0;
next_clip_max = 1;
}
if (min <= -1.0) {
min = -1.0;
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);
}
/* 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);
}
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;
// for rectified, this stays constant throughout the loop
pymin = (int) rint ((item->y1 + waveview->height) * item->canvas->pixels_per_unit);
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;
}
else {
s1 -= waveview->samples_per_unit;
}
/* don't rectify at single-sample zoom */
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;
}
if (waveview->rectified && waveview->samples_per_unit > 1) {
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 (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 {
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 = 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);
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);
}
last_pymax = (int) rint ((item->y1 + waveview->height - max * waveview->height) * 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);
/*
* 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;
}
/* show clipped waveforms with small red lines */
if (clip_max || clip_min) {
clip_length = MIN(5,(waveview->height/4));
if (min <= -1.0) {
min = -1.0;
next_clip_min = 1;
}
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++;
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);
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++;
}
}
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 );

View File

@ -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;

View File

@ -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")

View File

@ -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);

View File

@ -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 */

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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

View File

@ -227,6 +227,7 @@ PluginSelector::refill ()
setup_filter_string (filterstr);
ladspa_refiller (filterstr);
lv2_refiller (filterstr);
vst_refiller (filterstr);
au_refiller (filterstr);
}
@ -280,6 +281,14 @@ PluginSelector::ladspa_refiller (const std::string& filterstr)
refiller (manager->ladspa_plugin_info(), filterstr, "LADSPA");
}
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)
{

View File

@ -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&);

View File

@ -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;

60
gtk2_ardour/splash.cc Normal file
View File

@ -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;
}

41
gtk2_ardour/splash.h Normal file
View File

@ -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__ */

View File

@ -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 ();

View File

@ -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");

View File

@ -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;

View File

@ -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'] ])

View File

@ -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;

View File

@ -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;

View File

@ -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; }

View File

@ -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__ */

View File

@ -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);

View File

@ -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;

View File

@ -350,6 +350,7 @@ namespace ARDOUR {
enum PluginType {
AudioUnit,
LADSPA,
LV2,
VST
};

View File

@ -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 {

View File

@ -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
{

547
libs/ardour/lv2_plugin.cc Normal file
View File

@ -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;
}

View File

@ -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:

View File

@ -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 {

View File

@ -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 ()

View File

@ -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") {
@ -2281,13 +2282,6 @@ Route::get_mute_config (mute_type t)
return onoff;
}
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)
{

View File

@ -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()) {

View File

@ -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

View File

@ -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
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`"
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
ps -wx -ocommand | grep -e '[X]11' > /dev/null || exit 11
fi
cd ~/
shift