Merge with trunk R2935.
git-svn-id: svn://localhost/ardour2/branches/3.0@2943 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
parent
f80fad313a
commit
4ca1fe7993
16
SConstruct
16
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()
|
||||
|
|
|
@ -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 +
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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"/>
|
||||
|
|
|
@ -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 ()
|
||||
{
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 );
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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&);
|
||||
|
||||
|
|
|
@ -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
60
gtk2_ardour/splash.cc
Normal 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
41
gtk2_ardour/splash.h
Normal 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__ */
|
|
@ -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 ();
|
||||
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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'] ])
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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; }
|
||||
|
||||
|
|
138
libs/ardour/ardour/lv2_plugin.h
Normal file
138
libs/ardour/ardour/lv2_plugin.h
Normal 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__ */
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -350,6 +350,7 @@ namespace ARDOUR {
|
|||
enum PluginType {
|
||||
AudioUnit,
|
||||
LADSPA,
|
||||
LV2,
|
||||
VST
|
||||
};
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
547
libs/ardour/lv2_plugin.cc
Normal 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;
|
||||
}
|
||||
|
|
@ -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:
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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 ()
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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()) {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue
Block a user