mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-18 12:46:32 +01:00
(native) Linux VST support from LinuxDSP
git-svn-id: svn://localhost/ardour2/branches/3.0@10101 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
parent
e09e0035a6
commit
d4433b9ab3
38 changed files with 4346 additions and 70 deletions
|
|
@ -76,7 +76,7 @@ ExportRangeMarkersDialog::process_range_markers_export(Locations::LocationList&
|
||||||
string filepath = get_target_filepath(
|
string filepath = get_target_filepath(
|
||||||
get_selected_file_name(),
|
get_selected_file_name(),
|
||||||
currentLocation->name(),
|
currentLocation->name(),
|
||||||
sndfile_file_ending_from_string(get_selected_header_format()));
|
get_selected_header_format());
|
||||||
|
|
||||||
initSpec(filepath);
|
initSpec(filepath);
|
||||||
|
|
||||||
|
|
|
||||||
69
gtk2_ardour/lxvst_plugin_ui.h
Executable file
69
gtk2_ardour/lxvst_plugin_ui.h
Executable file
|
|
@ -0,0 +1,69 @@
|
||||||
|
#ifndef __lxvst_plugin_ui_h__
|
||||||
|
#define __lxvst_plugin_ui_h__
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <map>
|
||||||
|
#include <list>
|
||||||
|
|
||||||
|
#include <sigc++/signal.h>
|
||||||
|
#include <gtkmm/widget.h>
|
||||||
|
|
||||||
|
#include <ardour_dialog.h>
|
||||||
|
#include <ardour/types.h>
|
||||||
|
#include "plugin_ui.h"
|
||||||
|
|
||||||
|
#ifdef LXVST_SUPPORT
|
||||||
|
|
||||||
|
namespace ARDOUR {
|
||||||
|
class PluginInsert;
|
||||||
|
class LXVSTPlugin;
|
||||||
|
}
|
||||||
|
|
||||||
|
class LXVSTPluginUI : public PlugUIBase, public Gtk::VBox
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
LXVSTPluginUI (boost::shared_ptr<ARDOUR::PluginInsert>, boost::shared_ptr<ARDOUR::LXVSTPlugin>);
|
||||||
|
~LXVSTPluginUI ();
|
||||||
|
|
||||||
|
gint get_preferred_height ();
|
||||||
|
gint get_preferred_width ();
|
||||||
|
bool start_updating(GdkEventAny*);
|
||||||
|
bool stop_updating(GdkEventAny*);
|
||||||
|
|
||||||
|
int package (Gtk::Window&);
|
||||||
|
void forward_key_event (GdkEventKey *);
|
||||||
|
bool non_gtk_gui() const { return true; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
boost::shared_ptr<ARDOUR::LXVSTPlugin> lxvst;
|
||||||
|
Gtk::Socket socket;
|
||||||
|
Gtk::HBox preset_box;
|
||||||
|
Gtk::VBox vpacker;
|
||||||
|
|
||||||
|
sigc::connection _screen_update_connection;
|
||||||
|
|
||||||
|
bool configure_handler (GdkEventConfigure*, Gtk::Socket*);
|
||||||
|
void save_plugin_setting ();
|
||||||
|
|
||||||
|
struct PresetModelColumns : public Gtk::TreeModel::ColumnRecord {
|
||||||
|
PresetModelColumns() {
|
||||||
|
add (name);
|
||||||
|
add (number);
|
||||||
|
}
|
||||||
|
Gtk::TreeModelColumn<Glib::ustring> name;
|
||||||
|
Gtk::TreeModelColumn<int> number;
|
||||||
|
};
|
||||||
|
|
||||||
|
PresetModelColumns preset_columns;
|
||||||
|
Glib::RefPtr<Gtk::ListStore> preset_model;
|
||||||
|
Gtk::ComboBox lxvst_preset_combo;
|
||||||
|
|
||||||
|
void create_preset_store ();
|
||||||
|
void preset_chosen ();
|
||||||
|
void preset_selected ();
|
||||||
|
void resize_callback();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //LXVST_SUPPORT
|
||||||
|
|
||||||
|
#endif
|
||||||
277
gtk2_ardour/lxvst_pluginui.cc
Executable file
277
gtk2_ardour/lxvst_pluginui.cc
Executable file
|
|
@ -0,0 +1,277 @@
|
||||||
|
/*
|
||||||
|
Copyright (C) 2004 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.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
/******************************************************************/
|
||||||
|
/*linuxDSP - pluginui variant for LXVST (native Linux VST) Plugins*/
|
||||||
|
/******************************************************************/
|
||||||
|
|
||||||
|
#include <ardour/vstfx.h>
|
||||||
|
#include <gtk/gtk.h>
|
||||||
|
#include <gtk/gtksocket.h>
|
||||||
|
#include <ardour/processor.h>
|
||||||
|
#include <ardour/lxvst_plugin.h>
|
||||||
|
|
||||||
|
#include "ardour_ui.h"
|
||||||
|
#include "plugin_ui.h"
|
||||||
|
#include "lxvst_plugin_ui.h"
|
||||||
|
|
||||||
|
#include <gdk/gdkx.h>
|
||||||
|
|
||||||
|
#define LXVST_H_FIDDLE 40
|
||||||
|
|
||||||
|
using namespace Gtk;
|
||||||
|
using namespace ARDOUR;
|
||||||
|
using namespace PBD;
|
||||||
|
|
||||||
|
LXVSTPluginUI::LXVSTPluginUI (boost::shared_ptr<PluginInsert> pi, boost::shared_ptr<LXVSTPlugin> lxvp)
|
||||||
|
: PlugUIBase (pi),
|
||||||
|
lxvst (lxvp)
|
||||||
|
{
|
||||||
|
create_preset_store ();
|
||||||
|
|
||||||
|
vstfx_run_editor (lxvst->vstfx());
|
||||||
|
|
||||||
|
preset_box.set_spacing (6);
|
||||||
|
preset_box.set_border_width (6);
|
||||||
|
preset_box.pack_end (bypass_button, false, false, 10);
|
||||||
|
preset_box.pack_end (save_button, false, false);
|
||||||
|
preset_box.pack_end (lxvst_preset_combo, false, false);
|
||||||
|
|
||||||
|
lxvst_preset_combo.signal_changed().connect (mem_fun (*this, &LXVSTPluginUI::preset_chosen));
|
||||||
|
|
||||||
|
bypass_button.set_active (!insert->active());
|
||||||
|
|
||||||
|
pack_start (preset_box, false, false);
|
||||||
|
pack_start (socket, true, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
LXVSTPluginUI::~LXVSTPluginUI ()
|
||||||
|
{
|
||||||
|
|
||||||
|
_screen_update_connection.disconnect();
|
||||||
|
|
||||||
|
// plugin destructor destroys the custom GUI, via the vstfx engine,
|
||||||
|
// and then our PluginUIWindow does the rest
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
LXVSTPluginUI::start_updating (GdkEventAny* ignored)
|
||||||
|
{
|
||||||
|
_screen_update_connection.disconnect();
|
||||||
|
_screen_update_connection = ARDOUR_UI::instance()->RapidScreenUpdate.connect
|
||||||
|
(mem_fun(*this, &LXVSTPluginUI::resize_callback));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
LXVSTPluginUI::stop_updating (GdkEventAny* ignored)
|
||||||
|
{
|
||||||
|
_screen_update_connection.disconnect();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
LXVSTPluginUI::resize_callback()
|
||||||
|
{
|
||||||
|
/*We could maybe use this to resize the plugin GTK parent window
|
||||||
|
if required*/
|
||||||
|
|
||||||
|
if(lxvst->vstfx()->want_resize)
|
||||||
|
{
|
||||||
|
int new_height = lxvst->vstfx()->height;
|
||||||
|
int new_width = lxvst->vstfx()->width;
|
||||||
|
|
||||||
|
void* gtk_parent_window = lxvst->vstfx()->extra_data;
|
||||||
|
|
||||||
|
if(gtk_parent_window)
|
||||||
|
((Gtk::Window*)gtk_parent_window)->resize(new_width, new_height + LXVST_H_FIDDLE);
|
||||||
|
|
||||||
|
lxvst->vstfx()->want_resize = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
LXVSTPluginUI::preset_selected ()
|
||||||
|
{
|
||||||
|
socket.grab_focus ();
|
||||||
|
PlugUIBase::preset_selected ();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
LXVSTPluginUI::preset_chosen ()
|
||||||
|
{
|
||||||
|
// we can't dispatch directly here, too many plugins only expects one GUI thread.
|
||||||
|
|
||||||
|
lxvst->vstfx()->want_program = lxvst_preset_combo.get_active_row_number ();
|
||||||
|
socket.grab_focus ();
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
LXVSTPluginUI::get_preferred_height ()
|
||||||
|
{
|
||||||
|
/*FIXME*/
|
||||||
|
|
||||||
|
/*We have to return the required height of the plugin UI window + a fiddle factor
|
||||||
|
because we can't know how big the preset menu bar is until the window is realised
|
||||||
|
and we can't realise it until we have told it how big we would like it to be
|
||||||
|
which we can't do until it is realised etc*/
|
||||||
|
|
||||||
|
return (lxvst->vstfx()->height) + LXVST_H_FIDDLE; //May not be 40 for all screen res etc
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
LXVSTPluginUI::get_preferred_width ()
|
||||||
|
{
|
||||||
|
return lxvst->vstfx()->width;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
LXVSTPluginUI::package (Gtk::Window& win)
|
||||||
|
{
|
||||||
|
/* forward configure events to plugin window */
|
||||||
|
|
||||||
|
win.signal_configure_event().connect (bind (mem_fun (*this, &LXVSTPluginUI::configure_handler), &socket), false);
|
||||||
|
|
||||||
|
/*Map the UI start and stop updating events to 'Map' events on the Window*/
|
||||||
|
|
||||||
|
win.signal_map_event().connect (mem_fun (*this, &LXVSTPluginUI::start_updating));
|
||||||
|
win.signal_unmap_event().connect (mem_fun (*this, &LXVSTPluginUI::stop_updating));
|
||||||
|
|
||||||
|
/* this assumes that the window's owner understands the XEmbed protocol. */
|
||||||
|
|
||||||
|
socket.add_id (vstfx_get_XID (lxvst->vstfx()));
|
||||||
|
|
||||||
|
vstfx_move_window_into_view (lxvst->vstfx());
|
||||||
|
|
||||||
|
lxvst->vstfx()->extra_data = (void*)(&win);
|
||||||
|
lxvst->vstfx()->want_resize = 0;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
LXVSTPluginUI::configure_handler (GdkEventConfigure* ev, Gtk::Socket *socket)
|
||||||
|
{
|
||||||
|
XEvent event;
|
||||||
|
gint x, y;
|
||||||
|
GdkWindow* w;
|
||||||
|
|
||||||
|
if (socket == 0 || ((w = socket->gobj()->plug_window) == 0)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
event.xconfigure.type = ConfigureNotify;
|
||||||
|
event.xconfigure.event = GDK_WINDOW_XWINDOW (w);
|
||||||
|
event.xconfigure.window = GDK_WINDOW_XWINDOW (w);
|
||||||
|
|
||||||
|
/* The ICCCM says that synthetic events should have root relative
|
||||||
|
* coordinates. We still aren't really ICCCM compliant, since
|
||||||
|
* we don't send events when the real toplevel is moved.
|
||||||
|
*/
|
||||||
|
gdk_error_trap_push ();
|
||||||
|
gdk_window_get_origin (w, &x, &y);
|
||||||
|
gdk_error_trap_pop ();
|
||||||
|
|
||||||
|
event.xconfigure.x = x;
|
||||||
|
event.xconfigure.y = y;
|
||||||
|
event.xconfigure.width = GTK_WIDGET(socket->gobj())->allocation.width;
|
||||||
|
event.xconfigure.height = GTK_WIDGET(socket->gobj())->allocation.height;
|
||||||
|
|
||||||
|
event.xconfigure.border_width = 0;
|
||||||
|
event.xconfigure.above = None;
|
||||||
|
event.xconfigure.override_redirect = False;
|
||||||
|
|
||||||
|
gdk_error_trap_push ();
|
||||||
|
XSendEvent (GDK_WINDOW_XDISPLAY (w), GDK_WINDOW_XWINDOW (w), False, StructureNotifyMask, &event);
|
||||||
|
gdk_error_trap_pop ();
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
LXVSTPluginUI::forward_key_event (GdkEventKey* ev)
|
||||||
|
{
|
||||||
|
std::cerr << "LXVSTPluginUI : keypress forwarding to linuxVSTs unsupported" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
LXVSTPluginUI::create_preset_store ()
|
||||||
|
{
|
||||||
|
VSTFX* vstfx = lxvst->vstfx();
|
||||||
|
|
||||||
|
int vst_version = vstfx->plugin->dispatcher (vstfx->plugin, effGetVstVersion, 0, 0, NULL, 0.0f);
|
||||||
|
|
||||||
|
preset_model = ListStore::create (preset_columns);
|
||||||
|
|
||||||
|
for (int i = 0; i < vstfx->plugin->numPrograms; ++i) {
|
||||||
|
char buf[100];
|
||||||
|
TreeModel::Row row = *(preset_model->append());
|
||||||
|
|
||||||
|
snprintf (buf, 90, "preset %d", i);
|
||||||
|
|
||||||
|
if (vst_version >= 2) {
|
||||||
|
vstfx->plugin->dispatcher (vstfx->plugin, 29, i, 0, buf, 0.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
row[preset_columns.name] = buf;
|
||||||
|
row[preset_columns.number] = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vstfx->plugin->numPrograms > 0) {
|
||||||
|
vstfx->plugin->dispatcher( vstfx->plugin, effSetProgram, 0, 0, NULL, 0.0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
lxvst_preset_combo.set_model (preset_model);
|
||||||
|
|
||||||
|
CellRenderer* renderer = manage (new CellRendererText());
|
||||||
|
lxvst_preset_combo.pack_start (*renderer, true);
|
||||||
|
lxvst_preset_combo.add_attribute (*renderer, "text", 0);
|
||||||
|
|
||||||
|
if (lxvst->vstfx()->current_program != -1) {
|
||||||
|
lxvst_preset_combo.set_active (lxvst->vstfx()->current_program);
|
||||||
|
} else {
|
||||||
|
lxvst_preset_combo.set_active (0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef int (*error_handler_t)( Display *, XErrorEvent *);
|
||||||
|
static Display *the_gtk_display;
|
||||||
|
static error_handler_t vstfx_error_handler;
|
||||||
|
static error_handler_t gtk_error_handler;
|
||||||
|
|
||||||
|
static int
|
||||||
|
gtk_xerror_handler( Display *disp, XErrorEvent *ev )
|
||||||
|
{
|
||||||
|
std::cerr << "** ERROR ** LXVSTPluginUI : Trapped an X Window System Error" << std::endl;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gui_init (int *argc, char **argv[])
|
||||||
|
{
|
||||||
|
vstfx_error_handler = XSetErrorHandler (NULL);
|
||||||
|
gtk_init (argc, argv);
|
||||||
|
the_gtk_display = gdk_x11_display_get_xdisplay (gdk_display_get_default());
|
||||||
|
gtk_error_handler = XSetErrorHandler( gtk_xerror_handler );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -1547,12 +1547,16 @@ MidiRegionView::update_note (CanvasNote* ev, bool update_ghost_regions)
|
||||||
{
|
{
|
||||||
boost::shared_ptr<NoteType> note = ev->note();
|
boost::shared_ptr<NoteType> note = ev->note();
|
||||||
|
|
||||||
|
cerr << "Note " << *note << " @ region frames " << source_beats_to_region_frames (note->time()) << endl;
|
||||||
|
|
||||||
const double x = trackview.editor().frame_to_pixel (source_beats_to_region_frames (note->time()));
|
const double x = trackview.editor().frame_to_pixel (source_beats_to_region_frames (note->time()));
|
||||||
const double y1 = midi_stream_view()->note_to_y(note->note());
|
const double y1 = midi_stream_view()->note_to_y(note->note());
|
||||||
|
|
||||||
ev->property_x1() = x;
|
ev->property_x1() = x;
|
||||||
ev->property_y1() = y1;
|
ev->property_y1() = y1;
|
||||||
|
|
||||||
|
cerr << "\t" << x << " ... ";
|
||||||
|
|
||||||
/* trim note display to not overlap the end of its region */
|
/* trim note display to not overlap the end of its region */
|
||||||
|
|
||||||
if (note->length() > 0) {
|
if (note->length() > 0) {
|
||||||
|
|
@ -1562,6 +1566,8 @@ MidiRegionView::update_note (CanvasNote* ev, bool update_ghost_regions)
|
||||||
ev->property_x2() = trackview.editor().frame_to_pixel (_region->length());
|
ev->property_x2() = trackview.editor().frame_to_pixel (_region->length());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cerr << ev->property_x2() << endl;
|
||||||
|
|
||||||
ev->property_y2() = y1 + floor(midi_stream_view()->note_height());
|
ev->property_y2() = y1 + floor(midi_stream_view()->note_height());
|
||||||
|
|
||||||
if (note->length() == 0) {
|
if (note->length() == 0) {
|
||||||
|
|
|
||||||
|
|
@ -240,6 +240,9 @@ PluginSelector::show_this_plugin (const PluginInfoPtr& info, const std::string&
|
||||||
case VST:
|
case VST:
|
||||||
compstr = X_("VST");
|
compstr = X_("VST");
|
||||||
break;
|
break;
|
||||||
|
case LXVST:
|
||||||
|
compstr = X_("LXVST");
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (mode == _("Author contains")) {
|
} else if (mode == _("Author contains")) {
|
||||||
|
|
@ -285,6 +288,7 @@ PluginSelector::refill ()
|
||||||
ladspa_refiller (filterstr);
|
ladspa_refiller (filterstr);
|
||||||
lv2_refiller (filterstr);
|
lv2_refiller (filterstr);
|
||||||
vst_refiller (filterstr);
|
vst_refiller (filterstr);
|
||||||
|
lxvst_refiller (filterstr);
|
||||||
au_refiller (filterstr);
|
au_refiller (filterstr);
|
||||||
|
|
||||||
in_row_change = false;
|
in_row_change = false;
|
||||||
|
|
@ -357,6 +361,18 @@ PluginSelector::vst_refiller (const std::string&)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
#ifdef LXVST_SUPPORT
|
||||||
|
PluginSelector::lxvst_refiller (const std::string& filterstr)
|
||||||
|
#else
|
||||||
|
PluginSelector::lxvst_refiller (const std::string&)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
#ifdef LXVST_SUPPORT
|
||||||
|
refiller (manager->lxvst_plugin_info(), filterstr, "LXVST");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
#ifdef HAVE_AUDIOUNITS
|
#ifdef HAVE_AUDIOUNITS
|
||||||
PluginSelector::au_refiller (const std::string& filterstr)
|
PluginSelector::au_refiller (const std::string& filterstr)
|
||||||
|
|
@ -585,6 +601,9 @@ PluginSelector::build_plugin_menu ()
|
||||||
#ifdef VST_SUPPORT
|
#ifdef VST_SUPPORT
|
||||||
all_plugs.insert (all_plugs.end(), manager->vst_plugin_info().begin(), manager->vst_plugin_info().end());
|
all_plugs.insert (all_plugs.end(), manager->vst_plugin_info().begin(), manager->vst_plugin_info().end());
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef LXVST_SUPPORT
|
||||||
|
all_plugs.insert (all_plugs.end(), manager->lxvst_plugin_info().begin(), manager->lxvst_plugin_info().end());
|
||||||
|
#endif
|
||||||
#ifdef HAVE_AUDIOUNITS
|
#ifdef HAVE_AUDIOUNITS
|
||||||
all_plugs.insert (all_plugs.end(), manager->au_plugin_info().begin(), manager->au_plugin_info().end());
|
all_plugs.insert (all_plugs.end(), manager->au_plugin_info().begin(), manager->au_plugin_info().end());
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -112,6 +112,7 @@ class PluginSelector : public ArdourDialog
|
||||||
void ladspa_refiller (const std::string&);
|
void ladspa_refiller (const std::string&);
|
||||||
void lv2_refiller (const std::string&);
|
void lv2_refiller (const std::string&);
|
||||||
void vst_refiller (const std::string&);
|
void vst_refiller (const std::string&);
|
||||||
|
void lxvst_refiller (const std::string&);
|
||||||
void au_refiller (const std::string&);
|
void au_refiller (const std::string&);
|
||||||
|
|
||||||
Gtk::Menu* _plugin_menu;
|
Gtk::Menu* _plugin_menu;
|
||||||
|
|
|
||||||
|
|
@ -50,6 +50,10 @@
|
||||||
#include "ardour/vst_plugin.h"
|
#include "ardour/vst_plugin.h"
|
||||||
#include "vst_pluginui.h"
|
#include "vst_pluginui.h"
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef LXVST_SUPPORT
|
||||||
|
#include "ardour/lxvst_plugin.h"
|
||||||
|
#include "lxvst_plugin_ui.h"
|
||||||
|
#endif
|
||||||
#ifdef LV2_SUPPORT
|
#ifdef LV2_SUPPORT
|
||||||
#include "ardour/lv2_plugin.h"
|
#include "ardour/lv2_plugin.h"
|
||||||
#include "lv2_plugin_ui.h"
|
#include "lv2_plugin_ui.h"
|
||||||
|
|
@ -98,6 +102,10 @@ PluginUIWindow::PluginUIWindow (
|
||||||
case ARDOUR::VST:
|
case ARDOUR::VST:
|
||||||
have_gui = create_vst_editor (insert);
|
have_gui = create_vst_editor (insert);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case ARDOUR::LXVST:
|
||||||
|
have_gui = create_lxvst_editor (insert);
|
||||||
|
break;
|
||||||
|
|
||||||
case ARDOUR::AudioUnit:
|
case ARDOUR::AudioUnit:
|
||||||
have_gui = create_audiounit_editor (insert);
|
have_gui = create_audiounit_editor (insert);
|
||||||
|
|
@ -274,6 +282,36 @@ PluginUIWindow::create_vst_editor(boost::shared_ptr<PluginInsert>)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
#ifdef LXVST_SUPPORT
|
||||||
|
PluginUIWindow::create_lxvst_editor(boost::shared_ptr<PluginInsert> insert)
|
||||||
|
#else
|
||||||
|
PluginUIWindow::create_lxvst_editor(boost::shared_ptr<PluginInsert>)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
#ifndef LXVST_SUPPORT
|
||||||
|
return false;
|
||||||
|
#else
|
||||||
|
|
||||||
|
boost::shared_ptr<LXVSTPlugin> lxvp;
|
||||||
|
|
||||||
|
if ((lxvp = boost::dynamic_pointer_cast<LXVSTPlugin> (insert->plugin())) == 0) {
|
||||||
|
error << _("unknown type of editor-supplying plugin (note: no linuxVST support in this version of ardour)")
|
||||||
|
<< endmsg;
|
||||||
|
throw failed_constructor ();
|
||||||
|
} else {
|
||||||
|
LXVSTPluginUI* lxvpu = new LXVSTPluginUI (insert, lxvp);
|
||||||
|
|
||||||
|
_pluginui = lxvpu;
|
||||||
|
_pluginui->KeyboardFocused.connect (sigc::mem_fun (*this, &PluginUIWindow::keyboard_focused));
|
||||||
|
add (*lxvpu);
|
||||||
|
lxvpu->package (*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
#ifdef GTKOSX
|
#ifdef GTKOSX
|
||||||
PluginUIWindow::create_audiounit_editor (boost::shared_ptr<PluginInsert> insert)
|
PluginUIWindow::create_audiounit_editor (boost::shared_ptr<PluginInsert> insert)
|
||||||
|
|
|
||||||
|
|
@ -53,6 +53,7 @@ namespace ARDOUR {
|
||||||
class PluginInsert;
|
class PluginInsert;
|
||||||
class Plugin;
|
class Plugin;
|
||||||
class VSTPlugin;
|
class VSTPlugin;
|
||||||
|
class LXVSTPlugin;
|
||||||
class IOProcessor;
|
class IOProcessor;
|
||||||
class AUPlugin;
|
class AUPlugin;
|
||||||
}
|
}
|
||||||
|
|
@ -298,6 +299,7 @@ class PluginUIWindow : public Gtk::Window
|
||||||
void plugin_going_away ();
|
void plugin_going_away ();
|
||||||
|
|
||||||
bool create_vst_editor (boost::shared_ptr<ARDOUR::PluginInsert>);
|
bool create_vst_editor (boost::shared_ptr<ARDOUR::PluginInsert>);
|
||||||
|
bool create_lxvst_editor(boost::shared_ptr<ARDOUR::PluginInsert>);
|
||||||
bool create_audiounit_editor (boost::shared_ptr<ARDOUR::PluginInsert>);
|
bool create_audiounit_editor (boost::shared_ptr<ARDOUR::PluginInsert>);
|
||||||
bool create_lv2_editor (boost::shared_ptr<ARDOUR::PluginInsert>);
|
bool create_lv2_editor (boost::shared_ptr<ARDOUR::PluginInsert>);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -305,6 +305,7 @@ def build(bld):
|
||||||
obj.includes = ['.']
|
obj.includes = ['.']
|
||||||
obj.source = gtk2_ardour_sources
|
obj.source = gtk2_ardour_sources
|
||||||
obj.name = 'gtk2_ardour'
|
obj.name = 'gtk2_ardour'
|
||||||
|
obj.linkflags = []
|
||||||
if bld.env['VST_SUPPORT']:
|
if bld.env['VST_SUPPORT']:
|
||||||
obj.target = 'gtk2_ardour'
|
obj.target = 'gtk2_ardour'
|
||||||
obj.includes += ['../libs/fst']
|
obj.includes += ['../libs/fst']
|
||||||
|
|
@ -343,6 +344,12 @@ def build(bld):
|
||||||
if bld.env['VST_SUPPORT']:
|
if bld.env['VST_SUPPORT']:
|
||||||
obj.source += [ 'vst_pluginui.cc' ]
|
obj.source += [ 'vst_pluginui.cc' ]
|
||||||
obj.defines += [ 'VST_SUPPORT' ]
|
obj.defines += [ 'VST_SUPPORT' ]
|
||||||
|
bld.env.append ('LINKFLAGS', '-lX11')
|
||||||
|
|
||||||
|
if bld.env['LXVST_SUPPORT']:
|
||||||
|
obj.source += [ 'lxvst_pluginui.cc' ]
|
||||||
|
obj.defines += [ 'LXVST_SUPPORT' ]
|
||||||
|
obj.linkflags += [ '-lX11' ]
|
||||||
|
|
||||||
if bld.env['PHONE_HOME']:
|
if bld.env['PHONE_HOME']:
|
||||||
obj.defines += [ 'PHONE_HOME' ]
|
obj.defines += [ 'PHONE_HOME' ]
|
||||||
|
|
@ -365,7 +372,7 @@ def build(bld):
|
||||||
'''
|
'''
|
||||||
obj.includes = '../libs/fst'
|
obj.includes = '../libs/fst'
|
||||||
obj.target = 'ardour-3.0-vst'
|
obj.target = 'ardour-3.0-vst'
|
||||||
obj.linkflags = ['-mwindows', '-Wl,--export-dynamic', '-lpthread']
|
obj.linkflags += ['-mwindows', '-Wl,--export-dynamic', '-lpthread']
|
||||||
obj.defines = ['_POSIX_SOURCE', 'USE_WS_PREFIX']
|
obj.defines = ['_POSIX_SOURCE', 'USE_WS_PREFIX']
|
||||||
obj.uselib = 'ALSA'
|
obj.uselib = 'ALSA'
|
||||||
obj.uselib_local = ['libpbd','libmidipp','libtaglib','libardour',
|
obj.uselib_local = ['libpbd','libmidipp','libtaglib','libardour',
|
||||||
|
|
|
||||||
|
|
@ -189,8 +189,6 @@ public:
|
||||||
void get_physical_outputs (DataType type, std::vector<std::string>&);
|
void get_physical_outputs (DataType type, std::vector<std::string>&);
|
||||||
void get_physical_inputs (DataType type, std::vector<std::string>&);
|
void get_physical_inputs (DataType type, std::vector<std::string>&);
|
||||||
|
|
||||||
void update_total_latencies ();
|
|
||||||
|
|
||||||
Port *get_port_by_name (const std::string &);
|
Port *get_port_by_name (const std::string &);
|
||||||
|
|
||||||
enum TransportState {
|
enum TransportState {
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@
|
||||||
#include "ardour/data_type.h"
|
#include "ardour/data_type.h"
|
||||||
#include "ardour/types.h"
|
#include "ardour/types.h"
|
||||||
|
|
||||||
#ifdef VST_SUPPORT
|
#if defined VST_SUPPORT || defined LXVST_SUPPORT
|
||||||
#include "evoral/MIDIEvent.hpp"
|
#include "evoral/MIDIEvent.hpp"
|
||||||
struct VstEvents;
|
struct VstEvents;
|
||||||
struct VstMidiEvent;
|
struct VstMidiEvent;
|
||||||
|
|
@ -118,7 +118,7 @@ public:
|
||||||
void flush_lv2_midi(bool input, size_t i);
|
void flush_lv2_midi(bool input, size_t i);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef VST_SUPPORT
|
#if defined VST_SUPPORT || defined LXVST_SUPPORT
|
||||||
VstEvents* get_vst_midi (size_t);
|
VstEvents* get_vst_midi (size_t);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
@ -176,7 +176,7 @@ private:
|
||||||
LV2Buffers _lv2_buffers;
|
LV2Buffers _lv2_buffers;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef VST_SUPPORT
|
#if defined VST_SUPPORT || defined LXVST_SUPPORT
|
||||||
class VSTBuffer {
|
class VSTBuffer {
|
||||||
public:
|
public:
|
||||||
VSTBuffer (size_t);
|
VSTBuffer (size_t);
|
||||||
|
|
|
||||||
|
|
@ -104,7 +104,6 @@ class JackPort : public virtual Port, public PortConnectableByName {
|
||||||
jack_port_t* _port;
|
jack_port_t* _port;
|
||||||
|
|
||||||
int disconnect ();
|
int disconnect ();
|
||||||
void recompute_total_latency() const;
|
|
||||||
|
|
||||||
std::set<std::string> _named_connections;
|
std::set<std::string> _named_connections;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
123
libs/ardour/ardour/lxvst_plugin.h
Executable file
123
libs/ardour/ardour/lxvst_plugin.h
Executable file
|
|
@ -0,0 +1,123 @@
|
||||||
|
/*
|
||||||
|
Copyright (C) 2004 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_lxvst_plugin_h__
|
||||||
|
#define __ardour_lxvst_plugin_h__
|
||||||
|
|
||||||
|
#include <list>
|
||||||
|
#include <map>
|
||||||
|
#include <set>
|
||||||
|
#include <vector>
|
||||||
|
#include <string>
|
||||||
|
#include <dlfcn.h>
|
||||||
|
|
||||||
|
#include "pbd/stateful.h"
|
||||||
|
#include "ardour/plugin.h"
|
||||||
|
|
||||||
|
struct _VSTFXHandle;
|
||||||
|
struct _VSTFX;
|
||||||
|
typedef struct _VSTFXHandle VSTFXHandle;
|
||||||
|
typedef struct _VSTFX VSTFX;
|
||||||
|
class AEffect;
|
||||||
|
|
||||||
|
namespace ARDOUR {
|
||||||
|
class AudioEngine;
|
||||||
|
class Session;
|
||||||
|
|
||||||
|
class LXVSTPlugin : public ARDOUR::Plugin
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
LXVSTPlugin (ARDOUR::AudioEngine&, ARDOUR::Session&, VSTFXHandle* handle);
|
||||||
|
LXVSTPlugin (const LXVSTPlugin &);
|
||||||
|
~LXVSTPlugin ();
|
||||||
|
|
||||||
|
/* Plugin interface */
|
||||||
|
|
||||||
|
std::string unique_id() const;
|
||||||
|
const char * label() const;
|
||||||
|
const char * name() const;
|
||||||
|
const char * maker() const;
|
||||||
|
uint32_t parameter_count() const;
|
||||||
|
float default_value (uint32_t port);
|
||||||
|
framecnt_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;
|
||||||
|
std::set<Evoral::Parameter> automatable() const;
|
||||||
|
uint32_t nth_parameter (uint32_t port, bool& ok) const;
|
||||||
|
void activate ();
|
||||||
|
void deactivate ();
|
||||||
|
int set_block_size (pframes_t);
|
||||||
|
|
||||||
|
int connect_and_run (BufferSet&,
|
||||||
|
ChanMapping in, ChanMapping out,
|
||||||
|
pframes_t nframes, framecnt_t offset);
|
||||||
|
|
||||||
|
std::string describe_parameter (Evoral::Parameter);
|
||||||
|
std::string state_node_name() const { return "lxvst"; }
|
||||||
|
void print_parameter (uint32_t, char*, uint32_t len) const;
|
||||||
|
|
||||||
|
bool parameter_is_audio(uint32_t i) const { return false; }
|
||||||
|
bool parameter_is_control(uint32_t i) const { return true; }
|
||||||
|
bool parameter_is_input(uint32_t i) const { return true; }
|
||||||
|
bool parameter_is_output(uint32_t i) const { return false; }
|
||||||
|
|
||||||
|
bool load_preset (PresetRecord);
|
||||||
|
int first_user_preset_index () const;
|
||||||
|
|
||||||
|
bool has_editor () const;
|
||||||
|
|
||||||
|
int set_state (XMLNode const &, int);
|
||||||
|
|
||||||
|
AEffect * plugin () const { return _plugin; }
|
||||||
|
VSTFX * vstfx () const { return _vstfx; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
void do_remove_preset (std::string name);
|
||||||
|
std::string do_save_preset (std::string name);
|
||||||
|
gchar* get_chunk (bool) const;
|
||||||
|
int set_chunk (gchar const *, bool);
|
||||||
|
XMLTree * presets_tree () const;
|
||||||
|
std::string presets_file () const;
|
||||||
|
void find_presets ();
|
||||||
|
bool load_user_preset (PresetRecord);
|
||||||
|
bool load_plugin_preset (PresetRecord);
|
||||||
|
void add_state (XMLNode *) const;
|
||||||
|
|
||||||
|
VSTFXHandle* handle;
|
||||||
|
VSTFX* _vstfx;
|
||||||
|
AEffect* _plugin;
|
||||||
|
bool been_resumed;
|
||||||
|
};
|
||||||
|
|
||||||
|
class LXVSTPluginInfo : public PluginInfo
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
LXVSTPluginInfo ();
|
||||||
|
~LXVSTPluginInfo () {}
|
||||||
|
|
||||||
|
PluginPtr load (Session& session);
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef boost::shared_ptr<LXVSTPluginInfo> LXVSTPluginInfoPtr;
|
||||||
|
|
||||||
|
} // namespace ARDOUR
|
||||||
|
|
||||||
|
#endif /* __ardour_lxvst_plugin_h__ */
|
||||||
|
|
@ -43,6 +43,7 @@ class PluginManager : public boost::noncopyable {
|
||||||
~PluginManager ();
|
~PluginManager ();
|
||||||
|
|
||||||
ARDOUR::PluginInfoList &vst_plugin_info ();
|
ARDOUR::PluginInfoList &vst_plugin_info ();
|
||||||
|
ARDOUR::PluginInfoList &lxvst_plugin_info ();
|
||||||
ARDOUR::PluginInfoList &ladspa_plugin_info ();
|
ARDOUR::PluginInfoList &ladspa_plugin_info ();
|
||||||
ARDOUR::PluginInfoList &lv2_plugin_info ();
|
ARDOUR::PluginInfoList &lv2_plugin_info ();
|
||||||
ARDOUR::PluginInfoList &au_plugin_info ();
|
ARDOUR::PluginInfoList &au_plugin_info ();
|
||||||
|
|
@ -51,6 +52,7 @@ class PluginManager : public boost::noncopyable {
|
||||||
|
|
||||||
int add_ladspa_directory (std::string dirpath);
|
int add_ladspa_directory (std::string dirpath);
|
||||||
int add_vst_directory (std::string dirpath);
|
int add_vst_directory (std::string dirpath);
|
||||||
|
int add_lxvst_directory (std::string dirpath);
|
||||||
|
|
||||||
static PluginManager* the_manager() { return _manager; }
|
static PluginManager* the_manager() { return _manager; }
|
||||||
|
|
||||||
|
|
@ -95,6 +97,7 @@ class PluginManager : public boost::noncopyable {
|
||||||
|
|
||||||
ARDOUR::PluginInfoList _empty_plugin_info;
|
ARDOUR::PluginInfoList _empty_plugin_info;
|
||||||
ARDOUR::PluginInfoList* _vst_plugin_info;
|
ARDOUR::PluginInfoList* _vst_plugin_info;
|
||||||
|
ARDOUR::PluginInfoList* _lxvst_plugin_info;
|
||||||
ARDOUR::PluginInfoList* _ladspa_plugin_info;
|
ARDOUR::PluginInfoList* _ladspa_plugin_info;
|
||||||
ARDOUR::PluginInfoList* _lv2_plugin_info;
|
ARDOUR::PluginInfoList* _lv2_plugin_info;
|
||||||
ARDOUR::PluginInfoList* _au_plugin_info;
|
ARDOUR::PluginInfoList* _au_plugin_info;
|
||||||
|
|
@ -103,13 +106,16 @@ class PluginManager : public boost::noncopyable {
|
||||||
|
|
||||||
std::string ladspa_path;
|
std::string ladspa_path;
|
||||||
std::string vst_path;
|
std::string vst_path;
|
||||||
|
std::string lxvst_path;
|
||||||
|
|
||||||
void ladspa_refresh ();
|
void ladspa_refresh ();
|
||||||
void vst_refresh ();
|
void vst_refresh ();
|
||||||
|
void lxvst_refresh ();
|
||||||
|
|
||||||
void add_lrdf_data (const std::string &path);
|
void add_lrdf_data (const std::string &path);
|
||||||
void add_ladspa_presets ();
|
void add_ladspa_presets ();
|
||||||
void add_vst_presets ();
|
void add_vst_presets ();
|
||||||
|
void add_lxvst_presets ();
|
||||||
void add_presets (std::string domain);
|
void add_presets (std::string domain);
|
||||||
|
|
||||||
void au_refresh ();
|
void au_refresh ();
|
||||||
|
|
@ -118,6 +124,9 @@ class PluginManager : public boost::noncopyable {
|
||||||
|
|
||||||
int vst_discover_from_path (std::string path);
|
int vst_discover_from_path (std::string path);
|
||||||
int vst_discover (std::string path);
|
int vst_discover (std::string path);
|
||||||
|
|
||||||
|
int lxvst_discover_from_path (std::string path);
|
||||||
|
int lxvst_discover (std::string path);
|
||||||
|
|
||||||
int ladspa_discover_from_path (std::string path);
|
int ladspa_discover_from_path (std::string path);
|
||||||
int ladspa_discover (std::string path);
|
int ladspa_discover (std::string path);
|
||||||
|
|
|
||||||
|
|
@ -140,6 +140,7 @@ CONFIG_VARIABLE (bool, hiding_groups_deactivates_groups, "hiding-groups-deactiva
|
||||||
CONFIG_VARIABLE (bool, verify_remove_last_capture, "verify-remove-last-capture", true)
|
CONFIG_VARIABLE (bool, verify_remove_last_capture, "verify-remove-last-capture", true)
|
||||||
CONFIG_VARIABLE (bool, no_new_session_dialog, "no-new-session-dialog", false)
|
CONFIG_VARIABLE (bool, no_new_session_dialog, "no-new-session-dialog", false)
|
||||||
CONFIG_VARIABLE (bool, use_vst, "use-vst", true)
|
CONFIG_VARIABLE (bool, use_vst, "use-vst", true)
|
||||||
|
CONFIG_VARIABLE (bool, use_lxvst, "use-lxvst", true)
|
||||||
CONFIG_VARIABLE (bool, save_history, "save-history", true)
|
CONFIG_VARIABLE (bool, save_history, "save-history", true)
|
||||||
CONFIG_VARIABLE (int32_t, saved_history_depth, "save-history-depth", 20)
|
CONFIG_VARIABLE (int32_t, saved_history_depth, "save-history-depth", 20)
|
||||||
CONFIG_VARIABLE (int32_t, history_depth, "history-depth", 20)
|
CONFIG_VARIABLE (int32_t, history_depth, "history-depth", 20)
|
||||||
|
|
|
||||||
|
|
@ -741,6 +741,15 @@ class Session : public PBD::StatefulDestructible, public PBD::ScopedConnectionLi
|
||||||
long value,
|
long value,
|
||||||
void* ptr,
|
void* ptr,
|
||||||
float opt);
|
float opt);
|
||||||
|
|
||||||
|
/*Native linuxVST support*/
|
||||||
|
|
||||||
|
static long lxvst_callback (AEffect* effect,
|
||||||
|
long opcode,
|
||||||
|
long index,
|
||||||
|
long value,
|
||||||
|
void* ptr,
|
||||||
|
float opt);
|
||||||
|
|
||||||
static PBD::Signal0<void> SendFeedback;
|
static PBD::Signal0<void> SendFeedback;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -42,10 +42,9 @@ extern const char * const sndfile_endian_formats_strings[SNDFILE_ENDIAN_FORMATS+
|
||||||
|
|
||||||
extern int sndfile_endian_formats[SNDFILE_ENDIAN_FORMATS];
|
extern int sndfile_endian_formats[SNDFILE_ENDIAN_FORMATS];
|
||||||
|
|
||||||
int sndfile_bitdepth_format_from_string (std::string);
|
int sndfile_bitdepth_format_by_index (int);
|
||||||
int sndfile_header_format_from_string (std::string);
|
int sndfile_header_format_by_index (int);
|
||||||
int sndfile_endian_format_from_string (std::string);
|
int sndfile_endian_format_by_index (int);
|
||||||
std::string sndfile_file_ending_from_string (std::string);
|
|
||||||
|
|
||||||
int sndfile_data_width (int format);
|
int sndfile_data_width (int format);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -449,7 +449,8 @@ namespace ARDOUR {
|
||||||
AudioUnit,
|
AudioUnit,
|
||||||
LADSPA,
|
LADSPA,
|
||||||
LV2,
|
LV2,
|
||||||
VST
|
VST,
|
||||||
|
LXVST,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum RunContext {
|
enum RunContext {
|
||||||
|
|
|
||||||
316
libs/ardour/ardour/vestige/aeffectx.h
Executable file
316
libs/ardour/ardour/vestige/aeffectx.h
Executable file
|
|
@ -0,0 +1,316 @@
|
||||||
|
/*
|
||||||
|
* aeffectx.h - simple header to allow VeSTige compilation and eventually work
|
||||||
|
*
|
||||||
|
* Copyright (c) 2006 Javier Serrano Polo <jasp00/at/users.sourceforge.net>
|
||||||
|
*
|
||||||
|
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
|
||||||
|
*
|
||||||
|
* 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 (see COPYING); if not, write to the
|
||||||
|
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||||
|
* Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef _AEFFECTX_H
|
||||||
|
#define _AEFFECTX_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#define audioMasterAutomate 0
|
||||||
|
#define audioMasterVersion 1
|
||||||
|
#define audioMasterCurrentId 2
|
||||||
|
#define audioMasterIdle 3
|
||||||
|
#define audioMasterPinConnected 4
|
||||||
|
// unsupported? 5
|
||||||
|
#define audioMasterWantMidi 6
|
||||||
|
#define audioMasterGetTime 7
|
||||||
|
#define audioMasterProcessEvents 8
|
||||||
|
#define audioMasterSetTime 9
|
||||||
|
#define audioMasterTempoAt 10
|
||||||
|
#define audioMasterGetNumAutomatableParameters 11
|
||||||
|
#define audioMasterGetParameterQuantization 12
|
||||||
|
#define audioMasterIOChanged 13
|
||||||
|
#define audioMasterNeedIdle 14
|
||||||
|
#define audioMasterSizeWindow 15
|
||||||
|
#define audioMasterGetSampleRate 16
|
||||||
|
#define audioMasterGetBlockSize 17
|
||||||
|
#define audioMasterGetInputLatency 18
|
||||||
|
#define audioMasterGetOutputLatency 19
|
||||||
|
#define audioMasterGetPreviousPlug 20
|
||||||
|
#define audioMasterGetNextPlug 21
|
||||||
|
#define audioMasterWillReplaceOrAccumulate 22
|
||||||
|
#define audioMasterGetCurrentProcessLevel 23
|
||||||
|
#define audioMasterGetAutomationState 24
|
||||||
|
#define audioMasterOfflineStart 25
|
||||||
|
#define audioMasterOfflineRead 26
|
||||||
|
#define audioMasterOfflineWrite 27
|
||||||
|
#define audioMasterOfflineGetCurrentPass 28
|
||||||
|
#define audioMasterOfflineGetCurrentMetaPass 29
|
||||||
|
#define audioMasterSetOutputSampleRate 30
|
||||||
|
// unsupported? 31
|
||||||
|
#define audioMasterGetSpeakerArrangement 31 // deprecated in 2.4?
|
||||||
|
#define audioMasterGetVendorString 32
|
||||||
|
#define audioMasterGetProductString 33
|
||||||
|
#define audioMasterGetVendorVersion 34
|
||||||
|
#define audioMasterVendorSpecific 35
|
||||||
|
#define audioMasterSetIcon 36
|
||||||
|
#define audioMasterCanDo 37
|
||||||
|
#define audioMasterGetLanguage 38
|
||||||
|
#define audioMasterOpenWindow 39
|
||||||
|
#define audioMasterCloseWindow 40
|
||||||
|
#define audioMasterGetDirectory 41
|
||||||
|
#define audioMasterUpdateDisplay 42
|
||||||
|
#define audioMasterBeginEdit 43
|
||||||
|
#define audioMasterEndEdit 44
|
||||||
|
#define audioMasterOpenFileSelector 45
|
||||||
|
#define audioMasterCloseFileSelector 46// currently unused
|
||||||
|
#define audioMasterEditFile 47// currently unused
|
||||||
|
#define audioMasterGetChunkFile 48// currently unused
|
||||||
|
#define audioMasterGetInputSpeakerArrangement 49 // currently unused
|
||||||
|
|
||||||
|
#define effFlagsHasEditor 1
|
||||||
|
// very likely
|
||||||
|
#define effFlagsCanReplacing (1 << 4)
|
||||||
|
// currently unused
|
||||||
|
#define effFlagsIsSynth (1 << 8)
|
||||||
|
|
||||||
|
#define effOpen 0
|
||||||
|
//currently unused
|
||||||
|
#define effClose 1
|
||||||
|
// currently unused
|
||||||
|
#define effSetProgram 2
|
||||||
|
// currently unused
|
||||||
|
#define effGetProgram 3
|
||||||
|
// currently unused
|
||||||
|
#define effGetProgramName 5
|
||||||
|
#define effGetParamLabel 6
|
||||||
|
// currently unused
|
||||||
|
#define effGetParamName 8
|
||||||
|
// this is a guess
|
||||||
|
#define effSetSampleRate 10
|
||||||
|
#define effSetBlockSize 11
|
||||||
|
#define effMainsChanged 12
|
||||||
|
#define effEditGetRect 13
|
||||||
|
#define effEditOpen 14
|
||||||
|
#define effEditClose 15
|
||||||
|
#define effEditIdle 19
|
||||||
|
#define effProcessEvents 25
|
||||||
|
#define effGetEffectName 45
|
||||||
|
// missing
|
||||||
|
#define effGetParameterProperties 47
|
||||||
|
#define effGetVendorString 47
|
||||||
|
#define effGetProductString 48
|
||||||
|
#define effGetVendorVersion 49
|
||||||
|
// currently unused
|
||||||
|
#define effCanDo 51
|
||||||
|
// currently unused
|
||||||
|
#define effGetVstVersion 58
|
||||||
|
|
||||||
|
#ifdef WORDS_BIGENDIAN
|
||||||
|
// "VstP"
|
||||||
|
#define kEffectMagic 0x50747356
|
||||||
|
#else
|
||||||
|
// "PtsV"
|
||||||
|
#define kEffectMagic 0x56737450
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define kVstLangEnglish 1
|
||||||
|
#define kVstMidiType 1
|
||||||
|
#define kVstTransportPlaying (1 << 1)
|
||||||
|
|
||||||
|
/* validity flags for a VstTimeINfo structure this info comes from the web */
|
||||||
|
|
||||||
|
#define kVstNanosValid (1 << 8)
|
||||||
|
#define kVstPpqPosValid (1 << 9)
|
||||||
|
#define kVstTempoValid (1 << 10)
|
||||||
|
#define kVstBarsValid (1 << 11)
|
||||||
|
#define kVstCyclePosValid (1 << 12)
|
||||||
|
#define kVstTimeSigValid (1 << 13)
|
||||||
|
#define kVstSmpteValid (1 << 14)
|
||||||
|
#define kVstClockValid (1 << 15)
|
||||||
|
|
||||||
|
#define kVstTransportChanged 1
|
||||||
|
|
||||||
|
typedef struct VstMidiEvent
|
||||||
|
{
|
||||||
|
// 00
|
||||||
|
int type;
|
||||||
|
// 04
|
||||||
|
int byteSize;
|
||||||
|
// 08
|
||||||
|
int deltaFrames;
|
||||||
|
// 0c?
|
||||||
|
int flags;
|
||||||
|
// 10?
|
||||||
|
int noteLength;
|
||||||
|
// 14?
|
||||||
|
int noteOffset;
|
||||||
|
// 18
|
||||||
|
char midiData[4];
|
||||||
|
// 1c?
|
||||||
|
char detune;
|
||||||
|
// 1d?
|
||||||
|
char noteOffVelocity;
|
||||||
|
// 1e?
|
||||||
|
char reserved1;
|
||||||
|
// 1f?
|
||||||
|
char reserved2;
|
||||||
|
|
||||||
|
} VstMidiEvent;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct VstEvent
|
||||||
|
{
|
||||||
|
char dump[sizeof( VstMidiEvent )];
|
||||||
|
|
||||||
|
} VstEvent ;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct VstEvents
|
||||||
|
{
|
||||||
|
// 00
|
||||||
|
int numEvents;
|
||||||
|
// 04
|
||||||
|
int reserved;
|
||||||
|
// 08
|
||||||
|
VstEvent * events[];
|
||||||
|
} VstEvents;
|
||||||
|
|
||||||
|
/* constants from http://www.rawmaterialsoftware.com/juceforum/viewtopic.php?t=3740&sid=183f74631fee71a493316735e2b9f28b */
|
||||||
|
|
||||||
|
enum Vestige2StringConstants
|
||||||
|
{
|
||||||
|
VestigeMaxNameLen = 64,
|
||||||
|
VestigeMaxLabelLen = 64,
|
||||||
|
VestigeMaxShortLabelLen = 8,
|
||||||
|
VestigeMaxCategLabelLen = 24,
|
||||||
|
VestigeMaxFileNameLen = 100
|
||||||
|
};
|
||||||
|
|
||||||
|
/* this struct taken from http://asseca.com/vst-24-specs/efGetParameterProperties.html */
|
||||||
|
struct VstParameterProperties
|
||||||
|
{
|
||||||
|
float stepFloat; /* float step */
|
||||||
|
float smallStepFloat; /* small float step */
|
||||||
|
float largeStepFloat; /* large float step */
|
||||||
|
char label[VestigeMaxLabelLen]; /* parameter label */
|
||||||
|
int32_t flags; /* @see VstParameterFlags */
|
||||||
|
int32_t minInteger; /* integer minimum */
|
||||||
|
int32_t maxInteger; /* integer maximum */
|
||||||
|
int32_t stepInteger; /* integer step */
|
||||||
|
int32_t largeStepInteger; /* large integer step */
|
||||||
|
char shortLabel[VestigeMaxShortLabelLen]; /* short label, recommended: 6 + delimiter */
|
||||||
|
int16_t displayIndex; /* index where this parameter should be displayed (starting with 0) */
|
||||||
|
int16_t category; /* 0: no category, else group index + 1 */
|
||||||
|
int16_t numParametersInCategory; /* number of parameters in category */
|
||||||
|
int16_t reserved; /* zero */
|
||||||
|
char categoryLabel[VestigeMaxCategLabelLen]; /* category label, e.g. "Osc 1" */
|
||||||
|
char future[16]; /* reserved for future use */
|
||||||
|
};
|
||||||
|
|
||||||
|
/* this enum taken from http://asseca.com/vst-24-specs/efGetParameterProperties.html */
|
||||||
|
enum VstParameterFlags
|
||||||
|
{
|
||||||
|
kVstParameterIsSwitch = 1 << 0, /* parameter is a switch (on/off) */
|
||||||
|
kVstParameterUsesIntegerMinMax = 1 << 1, /* minInteger, maxInteger valid */
|
||||||
|
kVstParameterUsesFloatStep = 1 << 2, /* stepFloat, smallStepFloat, largeStepFloat valid */
|
||||||
|
kVstParameterUsesIntStep = 1 << 3, /* stepInteger, largeStepInteger valid */
|
||||||
|
kVstParameterSupportsDisplayIndex = 1 << 4, /* displayIndex valid */
|
||||||
|
kVstParameterSupportsDisplayCategory = 1 << 5, /* category, etc. valid */
|
||||||
|
kVstParameterCanRamp = 1 << 6 /* set if parameter value can ramp up/down */
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct AEffect
|
||||||
|
{
|
||||||
|
// Never use c++!!!
|
||||||
|
// 00-03
|
||||||
|
int magic;
|
||||||
|
// dispatcher 04-07
|
||||||
|
int (* dispatcher)( struct AEffect * , int , int , int , void * , float );
|
||||||
|
// process, quite sure 08-0b
|
||||||
|
void (* process)( struct AEffect * , float * * , float * * , int );
|
||||||
|
// setParameter 0c-0f
|
||||||
|
void (* setParameter)( struct AEffect * , int , float );
|
||||||
|
// getParameter 10-13
|
||||||
|
float (* getParameter)( struct AEffect * , int );
|
||||||
|
// programs 14-17
|
||||||
|
int numPrograms;
|
||||||
|
// Params 18-1b
|
||||||
|
int numParams;
|
||||||
|
// Input 1c-1f
|
||||||
|
int numInputs;
|
||||||
|
// Output 20-23
|
||||||
|
int numOutputs;
|
||||||
|
// flags 24-27
|
||||||
|
int flags;
|
||||||
|
// Fill somewhere 28-2b
|
||||||
|
void * user;
|
||||||
|
// Zeroes 2c-2f 30-33 34-37 38-3b
|
||||||
|
char empty3[4 + 4 + 4 + 4];
|
||||||
|
// 1.0f 3c-3f
|
||||||
|
float unkown_float;
|
||||||
|
// An object? pointer 40-43
|
||||||
|
char empty4[4];
|
||||||
|
// Zeroes 44-47
|
||||||
|
char empty5[4];
|
||||||
|
// Id 48-4b
|
||||||
|
char unused_id[4];
|
||||||
|
// Don't know 4c-4f
|
||||||
|
char unknown1[4];
|
||||||
|
// processReplacing 50-53
|
||||||
|
void (* processReplacing)( struct AEffect * , float * * , float * * , int );
|
||||||
|
|
||||||
|
int uniqueID;
|
||||||
|
|
||||||
|
} AEffect;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct VstTimeInfo
|
||||||
|
{
|
||||||
|
/* info from online documentation of VST provided by Steinberg */
|
||||||
|
|
||||||
|
double samplePos;
|
||||||
|
double sampleRate;
|
||||||
|
double nanoSeconds;
|
||||||
|
double ppqPos;
|
||||||
|
double tempo;
|
||||||
|
double barStartPos;
|
||||||
|
double cycleStartPos;
|
||||||
|
double cycleEndPos;
|
||||||
|
double timeSigNumerator;
|
||||||
|
double timeSigDenominator;
|
||||||
|
long smpteOffset;
|
||||||
|
long smpteFrameRate;
|
||||||
|
long samplesToNextClock;
|
||||||
|
long flags;
|
||||||
|
|
||||||
|
} VstTimeInfo;
|
||||||
|
|
||||||
|
|
||||||
|
typedef long int (* audioMasterCallback)( AEffect * , long int , long int ,
|
||||||
|
long int , void * , float );
|
||||||
|
// we don't use it, may be noise
|
||||||
|
#define VSTCALLBACK
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
176
libs/ardour/ardour/vstfx.h
Executable file
176
libs/ardour/ardour/vstfx.h
Executable file
|
|
@ -0,0 +1,176 @@
|
||||||
|
#ifndef __vstfx_h__
|
||||||
|
#define __vstfx_h__
|
||||||
|
|
||||||
|
#include <setjmp.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
/******************************************************************************************/
|
||||||
|
/*VSTFX - an engine to manage native linux VST plugins - derived from FST for Windows VSTs*/
|
||||||
|
/******************************************************************************************/
|
||||||
|
|
||||||
|
extern void (*vstfx_error_callback)(const char *msg);
|
||||||
|
|
||||||
|
void vstfx_set_error_function (void (*func)(const char *));
|
||||||
|
|
||||||
|
void vstfx_error (const char *fmt, ...);
|
||||||
|
|
||||||
|
/*We will use the vestige headers*/
|
||||||
|
|
||||||
|
#define VESTIGE_HEADER
|
||||||
|
|
||||||
|
#include <ardour/vestige/aeffectx.h>
|
||||||
|
|
||||||
|
typedef struct _VSTFX VSTFX;
|
||||||
|
typedef struct _VSTFXHandle VSTFXHandle;
|
||||||
|
typedef struct _VSTFXInfo VSTFXInfo;
|
||||||
|
typedef struct _VSTFXKey VSTFXKey;
|
||||||
|
|
||||||
|
|
||||||
|
/*Struct to contain the info about a plugin*/
|
||||||
|
|
||||||
|
struct _VSTFXInfo
|
||||||
|
{
|
||||||
|
char *name;
|
||||||
|
char *creator;
|
||||||
|
int UniqueID;
|
||||||
|
char *Category;
|
||||||
|
|
||||||
|
int numInputs;
|
||||||
|
int numOutputs;
|
||||||
|
int numParams;
|
||||||
|
|
||||||
|
int wantMidi;
|
||||||
|
int wantEvents;
|
||||||
|
int hasEditor;
|
||||||
|
int canProcessReplacing;
|
||||||
|
|
||||||
|
/* i think we should save the parameter Info Stuff soon. */
|
||||||
|
// struct VstParameterInfo *infos;
|
||||||
|
char **ParamNames;
|
||||||
|
char **ParamLabels;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*The AEffect which contains the info about a plugin instance*/
|
||||||
|
|
||||||
|
typedef struct AEffect * (*main_entry_t)(audioMasterCallback);
|
||||||
|
|
||||||
|
/*A handle used to identify a plugin to vstfx*/
|
||||||
|
|
||||||
|
struct _VSTFXHandle
|
||||||
|
{
|
||||||
|
void* dll;
|
||||||
|
char* name;
|
||||||
|
char* nameptr; /* ptr returned from strdup() etc. */
|
||||||
|
|
||||||
|
//struct AEffect* (*main_entry)(audioMasterCallback);
|
||||||
|
|
||||||
|
main_entry_t main_entry;
|
||||||
|
|
||||||
|
int plugincnt;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*No key forwarding enabled in vstfx at the moment - maybe
|
||||||
|
not required*/
|
||||||
|
|
||||||
|
|
||||||
|
struct _VSTFXKey
|
||||||
|
{
|
||||||
|
/** virtual-key code, or 0 if this _VSTFXKey is a `character' key */
|
||||||
|
int special;
|
||||||
|
/** `character' key, or 0 if this _VSTFXKey is a virtual-key */
|
||||||
|
int character;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*Structure used to describe the instance of VSTFX responsible for
|
||||||
|
a particular plugin instance. These are connected together in a
|
||||||
|
linked list*/
|
||||||
|
|
||||||
|
struct _VSTFX
|
||||||
|
{
|
||||||
|
struct AEffect* plugin;
|
||||||
|
int window; /* The plugin's parent X11 XWindow */
|
||||||
|
int plugin_ui_window; /*The ID of the plugin UI window created by the plugin*/
|
||||||
|
int xid; /* X11 XWindow */
|
||||||
|
|
||||||
|
int want_resize; /*Set to signal the plugin resized its UI*/
|
||||||
|
void* extra_data; /*Pointer to any extra data*/
|
||||||
|
|
||||||
|
void* event_callback_thisptr;
|
||||||
|
void (*eventProc) (void* event);
|
||||||
|
|
||||||
|
VSTFXHandle* handle;
|
||||||
|
|
||||||
|
int width;
|
||||||
|
int height;
|
||||||
|
int wantIdle;
|
||||||
|
int destroy;
|
||||||
|
int vst_version;
|
||||||
|
int has_editor;
|
||||||
|
|
||||||
|
int program_set_without_editor;
|
||||||
|
|
||||||
|
int want_program;
|
||||||
|
int want_chunk;
|
||||||
|
int n_pending_keys;
|
||||||
|
unsigned char* wanted_chunk;
|
||||||
|
int wanted_chunk_size;
|
||||||
|
int current_program;
|
||||||
|
float *want_params;
|
||||||
|
float *set_params;
|
||||||
|
|
||||||
|
VSTFXKey pending_keys[16];
|
||||||
|
|
||||||
|
int dispatcher_wantcall;
|
||||||
|
int dispatcher_opcode;
|
||||||
|
int dispatcher_index;
|
||||||
|
int dispatcher_val;
|
||||||
|
void * dispatcher_ptr;
|
||||||
|
float dispatcher_opt;
|
||||||
|
int dispatcher_retval;
|
||||||
|
|
||||||
|
struct _VSTFX* next;
|
||||||
|
pthread_mutex_t lock;
|
||||||
|
pthread_cond_t window_status_change;
|
||||||
|
pthread_cond_t plugin_dispatcher_called;
|
||||||
|
pthread_cond_t window_created;
|
||||||
|
int been_activated;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*API to vstfx*/
|
||||||
|
|
||||||
|
extern int vstfx_launch_editor(VSTFX* vstfx);
|
||||||
|
|
||||||
|
extern int vstfx_init (void* possible_hmodule);
|
||||||
|
extern void vstfx_exit ();
|
||||||
|
|
||||||
|
extern VSTFXHandle* vstfx_load (const char*);
|
||||||
|
extern int vstfx_unload (VSTFXHandle*);
|
||||||
|
|
||||||
|
extern VSTFX* vstfx_instantiate (VSTFXHandle*, audioMasterCallback amc, void* userptr);
|
||||||
|
extern void vstfx_close (VSTFX*);
|
||||||
|
|
||||||
|
extern int vstfx_create_editor (VSTFX* vstfx);
|
||||||
|
extern int vstfx_run_editor (VSTFX*);
|
||||||
|
extern void vstfx_destroy_editor (VSTFX*);
|
||||||
|
extern int vstfx_get_XID (VSTFX*);
|
||||||
|
extern void vstfx_move_window_into_view (VSTFX*);
|
||||||
|
|
||||||
|
extern VSTFXInfo* vstfx_get_info (char *dllpathname);
|
||||||
|
extern void vstfx_free_info (VSTFXInfo *info);
|
||||||
|
extern void vstfx_event_loop_remove_plugin (VSTFX* fst);
|
||||||
|
extern int vstfx_call_dispatcher(VSTFX *vstfx, int opcode, int index, int val, void *ptr, float opt );
|
||||||
|
|
||||||
|
/** Load a plugin state from a file.**/
|
||||||
|
|
||||||
|
extern int vstfx_load_state (VSTFX* vstfx, char * filename);
|
||||||
|
|
||||||
|
/** Save a plugin state to a file.**/
|
||||||
|
|
||||||
|
extern int vstfx_save_state (VSTFX* vstfx, char * filename);
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* __vstfx_h__ */
|
||||||
|
|
@ -490,7 +490,20 @@ AudioDiskstream::process (framepos_t transport_frame, pframes_t nframes, bool ca
|
||||||
AudioPort* const ap = _io->audio (n);
|
AudioPort* const ap = _io->audio (n);
|
||||||
assert(ap);
|
assert(ap);
|
||||||
assert(rec_nframes <= (framecnt_t) ap->get_audio_buffer(nframes).capacity());
|
assert(rec_nframes <= (framecnt_t) ap->get_audio_buffer(nframes).capacity());
|
||||||
memcpy (chaninfo->current_capture_buffer, ap->get_audio_buffer (nframes).data(rec_offset), sizeof (Sample) * rec_nframes);
|
|
||||||
|
Sample *bbuf = ap->get_audio_buffer (nframes).data(rec_offset);
|
||||||
|
|
||||||
|
|
||||||
|
for (jack_nframes_t _xx = 0; _xx != rec_nframes; ++_xx) {
|
||||||
|
if (bbuf[_xx] != 0.0) {
|
||||||
|
cerr << name() << " @ " << transport_frame << " + " << _xx << " = " << bbuf[_xx]
|
||||||
|
<< endl;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
memcpy (chaninfo->current_capture_buffer, bbuf, sizeof (Sample) * rec_nframes);
|
||||||
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -1414,13 +1414,6 @@ AudioEngine::request_buffer_size (pframes_t nframes)
|
||||||
return jack_set_buffer_size (_priv_jack, nframes);
|
return jack_set_buffer_size (_priv_jack, nframes);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
AudioEngine::update_total_latencies ()
|
|
||||||
{
|
|
||||||
GET_PRIVATE_JACK_POINTER (_jack);
|
|
||||||
jack_recompute_total_latencies (_priv_jack);
|
|
||||||
}
|
|
||||||
|
|
||||||
string
|
string
|
||||||
AudioEngine::make_port_name_relative (string portname) const
|
AudioEngine::make_port_name_relative (string portname) const
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -41,6 +41,10 @@
|
||||||
#include "vestige/aeffectx.h"
|
#include "vestige/aeffectx.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef LXVST_SUPPORT
|
||||||
|
#include "ardour/vestige/aeffectx.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace ARDOUR {
|
namespace ARDOUR {
|
||||||
|
|
||||||
/** Create a new, empty BufferSet */
|
/** Create a new, empty BufferSet */
|
||||||
|
|
@ -77,13 +81,14 @@ BufferSet::clear()
|
||||||
_count.reset();
|
_count.reset();
|
||||||
_available.reset();
|
_available.reset();
|
||||||
|
|
||||||
#ifdef VST_SUPPORT
|
#if defined VST_SUPPORT || defined LXVST_SUPPORT
|
||||||
for (VSTBuffers::iterator i = _vst_buffers.begin(); i != _vst_buffers.end(); ++i) {
|
for (VSTBuffers::iterator i = _vst_buffers.begin(); i != _vst_buffers.end(); ++i) {
|
||||||
delete *i;
|
delete *i;
|
||||||
}
|
}
|
||||||
|
|
||||||
_vst_buffers.clear ();
|
_vst_buffers.clear ();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Set up this BufferSet so that its data structures mirror a PortSet's buffers.
|
/** Set up this BufferSet so that its data structures mirror a PortSet's buffers.
|
||||||
|
|
@ -192,7 +197,7 @@ BufferSet::ensure_buffers(DataType type, size_t num_buffers, size_t buffer_capac
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef VST_SUPPORT
|
#if defined VST_SUPPORT || defined LXVST_SUPPORT
|
||||||
// As above but for VST
|
// As above but for VST
|
||||||
if (type == DataType::MIDI) {
|
if (type == DataType::MIDI) {
|
||||||
while (_vst_buffers.size() < _buffers[type].size()) {
|
while (_vst_buffers.size() < _buffers[type].size()) {
|
||||||
|
|
@ -299,7 +304,7 @@ BufferSet::flush_lv2_midi(bool input, size_t i)
|
||||||
|
|
||||||
#endif /* LV2_SUPPORT */
|
#endif /* LV2_SUPPORT */
|
||||||
|
|
||||||
#ifdef VST_SUPPORT
|
#if defined VST_SUPPORT || defined LXVST_SUPPORT
|
||||||
|
|
||||||
VstEvents*
|
VstEvents*
|
||||||
BufferSet::get_vst_midi (size_t b)
|
BufferSet::get_vst_midi (size_t b)
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,10 @@
|
||||||
#include <fst.h>
|
#include <fst.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef LXVST_SUPPORT
|
||||||
|
#include "ardour/vstfx.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_AUDIOUNITS
|
#ifdef HAVE_AUDIOUNITS
|
||||||
#include "ardour/audio_unit.h"
|
#include "ardour/audio_unit.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -290,6 +294,9 @@ ARDOUR::init (bool use_vst, bool try_optimization)
|
||||||
}
|
}
|
||||||
|
|
||||||
Config->set_use_vst (use_vst);
|
Config->set_use_vst (use_vst);
|
||||||
|
#ifdef LXVST_SUPPORT
|
||||||
|
Config->set_use_lxvst(true);
|
||||||
|
#endif
|
||||||
|
|
||||||
Profile = new RuntimeProfile;
|
Profile = new RuntimeProfile;
|
||||||
|
|
||||||
|
|
@ -300,6 +307,12 @@ ARDOUR::init (bool use_vst, bool try_optimization)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef LXVST_SUPPORT
|
||||||
|
if (Config->get_use_lxvst() && vstfx_init (0)) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_AUDIOUNITS
|
#ifdef HAVE_AUDIOUNITS
|
||||||
AUPluginInfo::load_cached_info ();
|
AUPluginInfo::load_cached_info ();
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -372,6 +385,10 @@ ARDOUR::cleanup ()
|
||||||
#ifdef VST_SUPPORT
|
#ifdef VST_SUPPORT
|
||||||
fst_exit ();
|
fst_exit ();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef LXVST_SUPPOR
|
||||||
|
vstfx_exit();
|
||||||
|
#endif
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
830
libs/ardour/lxvst_plugin.cc
Executable file
830
libs/ardour/lxvst_plugin.cc
Executable file
|
|
@ -0,0 +1,830 @@
|
||||||
|
/*
|
||||||
|
Copyright (C) 2004 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.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**********************************************************************/
|
||||||
|
/*Native linuxVST (LXVST) variant of vst_plugin.cc etc */
|
||||||
|
/**********************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <vector>
|
||||||
|
#include <string>
|
||||||
|
#include <cctype>
|
||||||
|
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <cstdio> // so libraptor doesn't complain
|
||||||
|
#include <cmath>
|
||||||
|
#include <dirent.h>
|
||||||
|
#include <cstring> // for memmove
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <cerrno>
|
||||||
|
|
||||||
|
#include <glibmm/miscutils.h>
|
||||||
|
|
||||||
|
#include <lrdf.h>
|
||||||
|
|
||||||
|
/*Include for the new native vst engine - vstfx.h*/
|
||||||
|
|
||||||
|
#include <ardour/vstfx.h>
|
||||||
|
|
||||||
|
#include "pbd/compose.h"
|
||||||
|
#include "pbd/error.h"
|
||||||
|
#include "pbd/pathscanner.h"
|
||||||
|
#include "pbd/xml++.h"
|
||||||
|
|
||||||
|
#include "ardour/session.h"
|
||||||
|
#include "ardour/audioengine.h"
|
||||||
|
#include "ardour/filesystem_paths.h"
|
||||||
|
#include "ardour/lxvst_plugin.h"
|
||||||
|
#include "ardour/buffer_set.h"
|
||||||
|
#include "ardour/audio_buffer.h"
|
||||||
|
#include "ardour/midi_buffer.h"
|
||||||
|
|
||||||
|
#include "pbd/stl_delete.h"
|
||||||
|
|
||||||
|
#include "i18n.h"
|
||||||
|
#include <locale.h>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
using namespace ARDOUR;
|
||||||
|
using namespace PBD;
|
||||||
|
using std::min;
|
||||||
|
using std::max;
|
||||||
|
|
||||||
|
LXVSTPlugin::LXVSTPlugin (AudioEngine& e, Session& session, VSTFXHandle* h)
|
||||||
|
: Plugin (e, session)
|
||||||
|
{
|
||||||
|
handle = h;
|
||||||
|
|
||||||
|
/*Instantiate the plugin and return a VSTFX* */
|
||||||
|
|
||||||
|
if ((_vstfx = vstfx_instantiate (handle, Session::lxvst_callback, this)) == 0)
|
||||||
|
{
|
||||||
|
throw failed_constructor();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*Call into vstfx to get a pointer to the instance of the VST plugin*/
|
||||||
|
|
||||||
|
_plugin = _vstfx->plugin;
|
||||||
|
_plugin->user = this;
|
||||||
|
|
||||||
|
/* set rate and blocksize */
|
||||||
|
|
||||||
|
_plugin->dispatcher (_plugin, effSetSampleRate, 0, 0, NULL, (float) session.frame_rate());
|
||||||
|
|
||||||
|
_plugin->dispatcher (_plugin, effSetBlockSize, 0, session.get_block_size(), NULL, 0.0f);
|
||||||
|
|
||||||
|
/* set program to zero */
|
||||||
|
|
||||||
|
_plugin->dispatcher (_plugin, effSetProgram, 0, 0, NULL, 0.0f);
|
||||||
|
|
||||||
|
// Plugin::setup_controls ();
|
||||||
|
}
|
||||||
|
|
||||||
|
LXVSTPlugin::LXVSTPlugin (const LXVSTPlugin &other)
|
||||||
|
: Plugin (other)
|
||||||
|
{
|
||||||
|
handle = other.handle;
|
||||||
|
|
||||||
|
if ((_vstfx = vstfx_instantiate (handle, Session::lxvst_callback, this)) == 0)
|
||||||
|
{
|
||||||
|
throw failed_constructor();
|
||||||
|
}
|
||||||
|
_plugin = _vstfx->plugin;
|
||||||
|
|
||||||
|
// Plugin::setup_controls ();
|
||||||
|
}
|
||||||
|
|
||||||
|
LXVSTPlugin::~LXVSTPlugin ()
|
||||||
|
{
|
||||||
|
deactivate ();
|
||||||
|
vstfx_close (_vstfx);
|
||||||
|
}
|
||||||
|
|
||||||
|
int LXVSTPlugin::set_block_size (pframes_t nframes)
|
||||||
|
{
|
||||||
|
deactivate ();
|
||||||
|
_plugin->dispatcher (_plugin, effSetBlockSize, 0, nframes, NULL, 0.0f);
|
||||||
|
activate ();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
float LXVSTPlugin::default_value (uint32_t port)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LXVSTPlugin::set_parameter (uint32_t which, float val)
|
||||||
|
{
|
||||||
|
_plugin->setParameter (_plugin, which, val);
|
||||||
|
|
||||||
|
if (_vstfx->want_program == -1 && _vstfx->want_chunk == 0)
|
||||||
|
{
|
||||||
|
/* Heinous hack: Plugin::set_parameter below updates the `modified' status of the
|
||||||
|
current preset, but if _vstfx->want_program is not -1 then there is a preset
|
||||||
|
setup pending or in progress, which we don't want any `modified' updates
|
||||||
|
to happen for. So we only do this if _vstfx->want_program is -1.
|
||||||
|
*/
|
||||||
|
Plugin::set_parameter (which, val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
float LXVSTPlugin::get_parameter (uint32_t which) const
|
||||||
|
{
|
||||||
|
return _plugin->getParameter (_plugin, which);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t LXVSTPlugin::nth_parameter (uint32_t n, bool& ok) const
|
||||||
|
{
|
||||||
|
ok = true;
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Get VST chunk as base64-encoded data.
|
||||||
|
* @param single true for single program, false for all programs.
|
||||||
|
* @return 0-terminated base64-encoded data; must be passed to g_free () by caller.
|
||||||
|
*/
|
||||||
|
gchar *LXVSTPlugin::get_chunk (bool single) const
|
||||||
|
{
|
||||||
|
guchar* data;
|
||||||
|
int32_t data_size = _plugin->dispatcher (_plugin, 23 /* effGetChunk */, single ? 1 : 0, 0, &data, 0);
|
||||||
|
if (data_size == 0)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return g_base64_encode (data, data_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Set VST chunk from base64-encoded data.
|
||||||
|
* @param 0-terminated base64-encoded data.
|
||||||
|
* @param single true for single program, false for all programs.
|
||||||
|
* @return 0 on success, non-0 on failure
|
||||||
|
*/
|
||||||
|
int LXVSTPlugin::set_chunk (gchar const * data, bool single)
|
||||||
|
{
|
||||||
|
gsize size = 0;
|
||||||
|
guchar* raw_data = g_base64_decode (data, &size);
|
||||||
|
int const r = _plugin->dispatcher (_plugin, 24 /* effSetChunk */, single ? 1 : 0, size, raw_data, 0);
|
||||||
|
g_free (raw_data);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LXVSTPlugin::add_state (XMLNode* root) const
|
||||||
|
{
|
||||||
|
LocaleGuard lg (X_("POSIX"));
|
||||||
|
|
||||||
|
if (_vstfx->current_program != -1)
|
||||||
|
{
|
||||||
|
char buf[32];
|
||||||
|
snprintf (buf, sizeof (buf), "%d", _vstfx->current_program);
|
||||||
|
root->add_property ("current-program", buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_plugin->flags & 32 /* effFlagsProgramsChunks */)
|
||||||
|
{
|
||||||
|
gchar* data = get_chunk (false);
|
||||||
|
if (data == 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* store information */
|
||||||
|
|
||||||
|
XMLNode* chunk_node = new XMLNode (X_("chunk"));
|
||||||
|
|
||||||
|
chunk_node->add_content (data);
|
||||||
|
g_free (data);
|
||||||
|
|
||||||
|
root->add_child_nocopy (*chunk_node);
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
XMLNode* parameters = new XMLNode ("parameters");
|
||||||
|
|
||||||
|
for (int32_t n = 0; n < _plugin->numParams; ++n)
|
||||||
|
{
|
||||||
|
char index[64];
|
||||||
|
char val[32];
|
||||||
|
snprintf (index, sizeof (index), "param_%d", n);
|
||||||
|
snprintf (val, sizeof (val), "%.12g", _plugin->getParameter (_plugin, n));
|
||||||
|
parameters->add_property (index, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
root->add_child_nocopy (*parameters);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int LXVSTPlugin::set_state (const XMLNode& node, int version)
|
||||||
|
{
|
||||||
|
LocaleGuard lg (X_("POSIX"));
|
||||||
|
|
||||||
|
if (node.name() != state_node_name())
|
||||||
|
{
|
||||||
|
error << _("Bad node sent to VSTPlugin::set_state") << endmsg;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const XMLProperty* prop;
|
||||||
|
|
||||||
|
if ((prop = node.property ("current-program")) != 0)
|
||||||
|
{
|
||||||
|
_vstfx->want_program = atoi (prop->value().c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
XMLNode* child;
|
||||||
|
int ret = -1;
|
||||||
|
|
||||||
|
if ((child = find_named_node (node, X_("chunk"))) != 0)
|
||||||
|
{
|
||||||
|
XMLPropertyList::const_iterator i;
|
||||||
|
XMLNodeList::const_iterator n;
|
||||||
|
int ret = -1;
|
||||||
|
|
||||||
|
for (n = child->children ().begin (); n != child->children ().end (); ++n)
|
||||||
|
{
|
||||||
|
if ((*n)->is_content ())
|
||||||
|
{
|
||||||
|
/* XXX: this may be dubious for the same reasons that we delay
|
||||||
|
execution of load_preset.
|
||||||
|
*/
|
||||||
|
ret = set_chunk ((*n)->content().c_str(), false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
else if ((child = find_named_node (node, X_("parameters"))) != 0)
|
||||||
|
{
|
||||||
|
XMLPropertyList::const_iterator i;
|
||||||
|
|
||||||
|
for (i = child->properties().begin(); i != child->properties().end(); ++i)
|
||||||
|
{
|
||||||
|
int32_t param;
|
||||||
|
float val;
|
||||||
|
|
||||||
|
sscanf ((*i)->name().c_str(), "param-%d", ¶m); //This was param_%d (from vst_plugin) which caused all sorts of odd behaviour
|
||||||
|
sscanf ((*i)->value().c_str(), "%f", &val);
|
||||||
|
|
||||||
|
_plugin->setParameter (_plugin, param, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* program number is not knowable */
|
||||||
|
|
||||||
|
_vstfx->current_program = -1;
|
||||||
|
|
||||||
|
ret = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Plugin::set_state (node, version);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int LXVSTPlugin::get_parameter_descriptor (uint32_t which, ParameterDescriptor& desc) const
|
||||||
|
{
|
||||||
|
VstParameterProperties prop;
|
||||||
|
|
||||||
|
desc.min_unbound = false;
|
||||||
|
desc.max_unbound = false;
|
||||||
|
prop.flags = 0;
|
||||||
|
|
||||||
|
/* old style */
|
||||||
|
|
||||||
|
char label[64];
|
||||||
|
label[0] = '\0';
|
||||||
|
|
||||||
|
_plugin->dispatcher (_plugin, effGetParamName, which, 0, label, 0);
|
||||||
|
|
||||||
|
desc.label = label;
|
||||||
|
desc.integer_step = false;
|
||||||
|
desc.lower = 0.0f;
|
||||||
|
desc.upper = 1.0f;
|
||||||
|
desc.step = 0.01f;
|
||||||
|
desc.smallstep = 0.005f;
|
||||||
|
desc.largestep = 0.1f;
|
||||||
|
desc.toggled = false;
|
||||||
|
desc.logarithmic = false;
|
||||||
|
desc.sr_dependent = false;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LXVSTPlugin::load_preset (PresetRecord r)
|
||||||
|
{
|
||||||
|
bool s;
|
||||||
|
|
||||||
|
if (r.user)
|
||||||
|
{
|
||||||
|
s = load_user_preset (r);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
s = load_plugin_preset (r);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (s)
|
||||||
|
{
|
||||||
|
Plugin::load_preset (r);
|
||||||
|
}
|
||||||
|
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LXVSTPlugin::load_plugin_preset (PresetRecord r)
|
||||||
|
{
|
||||||
|
/* This is a plugin-provided preset.
|
||||||
|
We can't dispatch directly here; too many plugins expects only one GUI thread.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Extract the index of this preset from the URI */
|
||||||
|
int id;
|
||||||
|
int index;
|
||||||
|
int const p = sscanf (r.uri.c_str(), "VST:%d:%d", &id, &index);
|
||||||
|
assert (p == 2);
|
||||||
|
|
||||||
|
_vstfx->want_program = index;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LXVSTPlugin::load_user_preset (PresetRecord r)
|
||||||
|
{
|
||||||
|
/* This is a user preset; we load it, and this code also knows about the
|
||||||
|
non-direct-dispatch thing.
|
||||||
|
*/
|
||||||
|
|
||||||
|
boost::shared_ptr<XMLTree> t (presets_tree ());
|
||||||
|
if (t == 0)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
XMLNode* root = t->root ();
|
||||||
|
|
||||||
|
for (XMLNodeList::const_iterator i = root->children().begin(); i != root->children().end(); ++i)
|
||||||
|
{
|
||||||
|
XMLProperty* uri = (*i)->property (X_("uri"));
|
||||||
|
XMLProperty* label = (*i)->property (X_("label"));
|
||||||
|
|
||||||
|
assert (uri);
|
||||||
|
assert (label);
|
||||||
|
|
||||||
|
if (label->value() != r.label)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_plugin->flags & 32 /* effFlagsProgramsChunks */)
|
||||||
|
{
|
||||||
|
|
||||||
|
/* Load a user preset chunk from our XML file and send it via a circuitous route to the plugin */
|
||||||
|
|
||||||
|
if (_vstfx->wanted_chunk)
|
||||||
|
{
|
||||||
|
g_free (_vstfx->wanted_chunk);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (XMLNodeList::const_iterator j = (*i)->children().begin(); j != (*i)->children().end(); ++j)
|
||||||
|
{
|
||||||
|
if ((*j)->is_content ())
|
||||||
|
{
|
||||||
|
/* we can't dispatch directly here; too many plugins expect only one GUI thread */
|
||||||
|
gsize size = 0;
|
||||||
|
guchar* raw_data = g_base64_decode ((*j)->content().c_str(), &size);
|
||||||
|
_vstfx->wanted_chunk = raw_data;
|
||||||
|
_vstfx->wanted_chunk_size = size;
|
||||||
|
_vstfx->want_chunk = 1;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (XMLNodeList::const_iterator j = (*i)->children().begin(); j != (*i)->children().end(); ++j)
|
||||||
|
{
|
||||||
|
if ((*j)->name() == X_("Parameter"))
|
||||||
|
{
|
||||||
|
XMLProperty* index = (*j)->property (X_("index"));
|
||||||
|
XMLProperty* value = (*j)->property (X_("value"));
|
||||||
|
|
||||||
|
assert (index);
|
||||||
|
assert (value);
|
||||||
|
|
||||||
|
set_parameter (atoi (index->value().c_str()), atof (value->value().c_str ()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
string LXVSTPlugin::do_save_preset (string name)
|
||||||
|
{
|
||||||
|
boost::shared_ptr<XMLTree> t (presets_tree ());
|
||||||
|
if (t == 0)
|
||||||
|
{
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
XMLNode* p = 0;
|
||||||
|
/* XXX: use of _presets.size() + 1 for the unique ID here is dubious at best */
|
||||||
|
string const uri = string_compose (X_("VST:%1:%2"), unique_id (), _presets.size() + 1);
|
||||||
|
|
||||||
|
if (_plugin->flags & 32 /* effFlagsProgramsChunks */)
|
||||||
|
{
|
||||||
|
|
||||||
|
p = new XMLNode (X_("ChunkPreset"));
|
||||||
|
p->add_property (X_("uri"), uri);
|
||||||
|
p->add_property (X_("label"), name);
|
||||||
|
gchar* data = get_chunk (true);
|
||||||
|
p->add_content (string (data));
|
||||||
|
g_free (data);
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
|
||||||
|
p = new XMLNode (X_("Preset"));
|
||||||
|
p->add_property (X_("uri"), uri);
|
||||||
|
p->add_property (X_("label"), name);
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < parameter_count(); ++i)
|
||||||
|
{
|
||||||
|
if (parameter_is_input (i))
|
||||||
|
{
|
||||||
|
XMLNode* c = new XMLNode (X_("Parameter"));
|
||||||
|
c->add_property (X_("index"), string_compose ("%1", i));
|
||||||
|
c->add_property (X_("value"), string_compose ("%1", get_parameter (i)));
|
||||||
|
p->add_child_nocopy (*c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
t->root()->add_child_nocopy (*p);
|
||||||
|
|
||||||
|
sys::path f = ARDOUR::user_config_directory ();
|
||||||
|
f /= "presets";
|
||||||
|
f /= presets_file ();
|
||||||
|
|
||||||
|
t->write (f.to_string ());
|
||||||
|
return uri;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LXVSTPlugin::do_remove_preset (string name)
|
||||||
|
{
|
||||||
|
boost::shared_ptr<XMLTree> t (presets_tree ());
|
||||||
|
if (t == 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
t->root()->remove_nodes_and_delete (X_("label"), name);
|
||||||
|
|
||||||
|
sys::path f = ARDOUR::user_config_directory ();
|
||||||
|
f /= "presets";
|
||||||
|
f /= presets_file ();
|
||||||
|
|
||||||
|
t->write (f.to_string ());
|
||||||
|
}
|
||||||
|
|
||||||
|
string LXVSTPlugin::describe_parameter (Evoral::Parameter param)
|
||||||
|
{
|
||||||
|
char name[64] = "Unkown";
|
||||||
|
_plugin->dispatcher (_plugin, effGetParamName, param.id(), 0, name, 0);
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
framecnt_t LXVSTPlugin::signal_latency () const
|
||||||
|
{
|
||||||
|
if (_user_latency)
|
||||||
|
{
|
||||||
|
return _user_latency;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef VESTIGE_HEADER
|
||||||
|
return *((framecnt_t *) (((char *) &_plugin->flags) + 12)); /* initialDelay */
|
||||||
|
#else
|
||||||
|
return _plugin->initial_delay;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
set<Evoral::Parameter> LXVSTPlugin::automatable () const
|
||||||
|
{
|
||||||
|
set<Evoral::Parameter> ret;
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < parameter_count(); ++i)
|
||||||
|
{
|
||||||
|
ret.insert (ret.end(), Evoral::Parameter(PluginAutomation, 0, i));
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int LXVSTPlugin::connect_and_run (BufferSet& bufs,
|
||||||
|
ChanMapping in_map, ChanMapping out_map,
|
||||||
|
pframes_t nframes, framecnt_t offset)
|
||||||
|
{
|
||||||
|
Plugin::connect_and_run (bufs, in_map, out_map, nframes, offset);
|
||||||
|
|
||||||
|
float *ins[_plugin->numInputs];
|
||||||
|
float *outs[_plugin->numOutputs];
|
||||||
|
int32_t i;
|
||||||
|
|
||||||
|
const uint32_t nbufs = bufs.count().n_audio();
|
||||||
|
|
||||||
|
int in_index = 0;
|
||||||
|
for (i = 0; i < (int32_t) _plugin->numInputs; ++i)
|
||||||
|
{
|
||||||
|
ins[i] = bufs.get_audio(min((uint32_t) in_index, nbufs - 1)).data() + offset;
|
||||||
|
in_index++;
|
||||||
|
}
|
||||||
|
|
||||||
|
int out_index = 0;
|
||||||
|
for (i = 0; i < (int32_t) _plugin->numOutputs; ++i)
|
||||||
|
{
|
||||||
|
outs[i] = bufs.get_audio(min((uint32_t) out_index, nbufs - 1)).data() + offset;
|
||||||
|
out_index++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bufs.count().n_midi() > 0)
|
||||||
|
{
|
||||||
|
VstEvents* v = bufs.get_vst_midi (0);
|
||||||
|
_plugin->dispatcher (_plugin, effProcessEvents, 0, 0, v, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* we already know it can support processReplacing */
|
||||||
|
|
||||||
|
#ifdef LXVST_32BIT
|
||||||
|
_plugin->processReplacing (_plugin, ins, outs, nframes);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined LXVST_64BIT && defined VESTIGE_HEADER
|
||||||
|
|
||||||
|
/*Vestige doesn't work for 64Bit - some of the AEffect struct member types
|
||||||
|
appear not to be correct which throws the data alignment. We have two choices
|
||||||
|
|
||||||
|
1) Fix Vestige - preferable from a technical standpoint, but perhaps
|
||||||
|
not viable without affecting its 'clean room' status
|
||||||
|
|
||||||
|
2) Correct for the alignment error - a bit of a kludge, but it can work,
|
||||||
|
assuming the following data types / sizes on x86-64
|
||||||
|
|
||||||
|
char 1Byte : Byte aligned
|
||||||
|
int 4Bytes : 4Byte aligned
|
||||||
|
long 8Bytes : 8Byte aligned
|
||||||
|
pointers 8Bytes : 8Byte aligned
|
||||||
|
|
||||||
|
This gives an offset of 8 Bytes - inclusive of padding
|
||||||
|
to translate to the correct address for processReplacing*/
|
||||||
|
|
||||||
|
((AEffect*)(((char*)(_plugin)) + 8))->processReplacing(_plugin, ins, outs, nframes);
|
||||||
|
|
||||||
|
#elif defined LXVST_64BIT
|
||||||
|
|
||||||
|
_plugin->processReplacing(_plugin, ins, outs, nframes);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LXVSTPlugin::deactivate ()
|
||||||
|
{
|
||||||
|
_plugin->dispatcher (_plugin, effMainsChanged, 0, 0, NULL, 0.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LXVSTPlugin::activate ()
|
||||||
|
{
|
||||||
|
_plugin->dispatcher (_plugin, effMainsChanged, 0, 1, NULL, 0.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
string LXVSTPlugin::unique_id() const
|
||||||
|
{
|
||||||
|
char buf[32];
|
||||||
|
|
||||||
|
#if defined LXVST_64BIT && defined VESTIGE_HEADER
|
||||||
|
|
||||||
|
/*The vestige header appears not to have correct data
|
||||||
|
alignment in AEffect struct for 64Bit, possibly due
|
||||||
|
to incorrect data types - see previous comments*/
|
||||||
|
|
||||||
|
snprintf (buf, sizeof (buf), "%d", *((int32_t*) &((AEffect*)(((char*)(_plugin)) + 12))->unused_id));
|
||||||
|
|
||||||
|
#elif defined LXVST_32BIT && defined VESTIGE_HEADER
|
||||||
|
|
||||||
|
snprintf (buf, sizeof (buf), "%d", *((int32_t*) &_plugin->unused_id));
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
snprintf (buf, sizeof (buf), "%d", _plugin->uniqueID);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return string (buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const char * LXVSTPlugin::name () const
|
||||||
|
{
|
||||||
|
return handle->name;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char * LXVSTPlugin::maker () const
|
||||||
|
{
|
||||||
|
return _info->creator.c_str();
|
||||||
|
}
|
||||||
|
|
||||||
|
const char * LXVSTPlugin::label () const
|
||||||
|
{
|
||||||
|
return handle->name;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t LXVSTPlugin::parameter_count() const
|
||||||
|
{
|
||||||
|
return _plugin->numParams;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LXVSTPlugin::has_editor () const
|
||||||
|
{
|
||||||
|
return _plugin->flags & effFlagsHasEditor;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LXVSTPlugin::print_parameter (uint32_t param, char *buf, uint32_t len) const
|
||||||
|
{
|
||||||
|
char *first_nonws;
|
||||||
|
|
||||||
|
_plugin->dispatcher (_plugin, 7 /* effGetParamDisplay */, param, 0, buf, 0);
|
||||||
|
|
||||||
|
if (buf[0] == '\0')
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
first_nonws = buf;
|
||||||
|
while (*first_nonws && isspace (*first_nonws))
|
||||||
|
{
|
||||||
|
first_nonws++;
|
||||||
|
}
|
||||||
|
if (*first_nonws == '\0')
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
memmove (buf, first_nonws, strlen (buf) - (first_nonws - buf) + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
PluginPtr LXVSTPluginInfo::load (Session& session)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
PluginPtr plugin;
|
||||||
|
|
||||||
|
if (Config->get_use_lxvst())
|
||||||
|
{
|
||||||
|
VSTFXHandle* handle;
|
||||||
|
|
||||||
|
handle = vstfx_load(path.c_str());
|
||||||
|
|
||||||
|
if (handle == NULL)
|
||||||
|
{
|
||||||
|
error << string_compose(_("LXVST: cannot load module from \"%1\""), path) << endmsg;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
plugin.reset (new LXVSTPlugin (session.engine(), session, handle));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
error << _("You asked ardour to not use any LXVST plugins") << endmsg;
|
||||||
|
return PluginPtr ((Plugin*) 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
plugin->set_info(PluginInfoPtr(new LXVSTPluginInfo(*this)));
|
||||||
|
return plugin;
|
||||||
|
}
|
||||||
|
|
||||||
|
catch (failed_constructor &err)
|
||||||
|
{
|
||||||
|
return PluginPtr ((Plugin*) 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void LXVSTPlugin::find_presets ()
|
||||||
|
{
|
||||||
|
/* Built-in presets */
|
||||||
|
|
||||||
|
int const vst_version = _plugin->dispatcher (_plugin, effGetVstVersion, 0, 0, NULL, 0);
|
||||||
|
for (int i = 0; i < _plugin->numPrograms; ++i)
|
||||||
|
{
|
||||||
|
PresetRecord r (string_compose (X_("LXVST:%1:%2"), unique_id (), i), "", false);
|
||||||
|
|
||||||
|
if (vst_version >= 2)
|
||||||
|
{
|
||||||
|
char buf[256];
|
||||||
|
if (_plugin->dispatcher (_plugin, 29, i, 0, buf, 0) == 1)
|
||||||
|
{
|
||||||
|
r.label = buf;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
r.label = string_compose (_("Preset %1"), i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
r.label = string_compose (_("Preset %1"), i);
|
||||||
|
}
|
||||||
|
|
||||||
|
_presets.insert (make_pair (r.uri, r));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* User presets from our XML file */
|
||||||
|
|
||||||
|
boost::shared_ptr<XMLTree> t (presets_tree ());
|
||||||
|
|
||||||
|
if (t)
|
||||||
|
{
|
||||||
|
XMLNode* root = t->root ();
|
||||||
|
for (XMLNodeList::const_iterator i = root->children().begin(); i != root->children().end(); ++i)
|
||||||
|
{
|
||||||
|
XMLProperty* uri = (*i)->property (X_("uri"));
|
||||||
|
XMLProperty* label = (*i)->property (X_("label"));
|
||||||
|
|
||||||
|
assert (uri);
|
||||||
|
assert (label);
|
||||||
|
|
||||||
|
PresetRecord r (uri->value(), label->value(), true);
|
||||||
|
_presets.insert (make_pair (r.uri, r));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @return XMLTree with our user presets; could be a new one if no existing
|
||||||
|
* one was found, or 0 if one was present but badly-formatted.
|
||||||
|
*/
|
||||||
|
XMLTree * LXVSTPlugin::presets_tree () const
|
||||||
|
{
|
||||||
|
XMLTree* t = new XMLTree;
|
||||||
|
|
||||||
|
sys::path p = ARDOUR::user_config_directory ();
|
||||||
|
p /= "presets";
|
||||||
|
|
||||||
|
if (!is_directory (p))
|
||||||
|
{
|
||||||
|
create_directory (p);
|
||||||
|
}
|
||||||
|
|
||||||
|
p /= presets_file ();
|
||||||
|
|
||||||
|
if (!exists (p))
|
||||||
|
{
|
||||||
|
t->set_root (new XMLNode (X_("LXVSTPresets")));
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
t->set_filename (p.to_string ());
|
||||||
|
if (!t->read ())
|
||||||
|
{
|
||||||
|
delete t;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @return Index of the first user preset in our lists */
|
||||||
|
int LXVSTPlugin::first_user_preset_index () const
|
||||||
|
{
|
||||||
|
return _plugin->numPrograms;
|
||||||
|
}
|
||||||
|
|
||||||
|
string LXVSTPlugin::presets_file () const
|
||||||
|
{
|
||||||
|
return string_compose ("lxvst-%1", unique_id ());
|
||||||
|
}
|
||||||
|
|
||||||
|
LXVSTPluginInfo::LXVSTPluginInfo()
|
||||||
|
{
|
||||||
|
type = ARDOUR::LXVST;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -139,6 +139,12 @@ ARDOUR::find_plugin(Session& session, string identifier, PluginType type)
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef LXVST_SUPPORT
|
||||||
|
case ARDOUR::LXVST:
|
||||||
|
plugs = mgr->lxvst_plugin_info();
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_AUDIOUNITS
|
#ifdef HAVE_AUDIOUNITS
|
||||||
case ARDOUR::AudioUnit:
|
case ARDOUR::AudioUnit:
|
||||||
plugs = mgr->au_plugin_info();
|
plugs = mgr->au_plugin_info();
|
||||||
|
|
@ -170,6 +176,19 @@ ARDOUR::find_plugin(Session& session, string identifier, PluginType type)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef LXVST_SUPPORT
|
||||||
|
/* hmm, we didn't find it. could be because in older versions of Ardour.
|
||||||
|
we used to store the name of a VST plugin, not its unique ID. so try
|
||||||
|
again.
|
||||||
|
*/
|
||||||
|
|
||||||
|
for (i = plugs.begin(); i != plugs.end(); ++i) {
|
||||||
|
if (identifier == (*i)->name){
|
||||||
|
return (*i)->load (session);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
return PluginPtr ((Plugin*) 0);
|
return PluginPtr ((Plugin*) 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -45,6 +45,10 @@
|
||||||
#include "ardour/vst_plugin.h"
|
#include "ardour/vst_plugin.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef LXVST_SUPPORT
|
||||||
|
#include "ardour/lxvst_plugin.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_AUDIOUNITS
|
#ifdef HAVE_AUDIOUNITS
|
||||||
#include "ardour/audio_unit.h"
|
#include "ardour/audio_unit.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -570,6 +574,9 @@ PluginInsert::plugin_factory (boost::shared_ptr<Plugin> other)
|
||||||
#ifdef VST_SUPPORT
|
#ifdef VST_SUPPORT
|
||||||
boost::shared_ptr<VSTPlugin> vp;
|
boost::shared_ptr<VSTPlugin> vp;
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef LXVST_SUPPORT
|
||||||
|
boost::shared_ptr<LXVSTPlugin> lxvp;
|
||||||
|
#endif
|
||||||
#ifdef HAVE_AUDIOUNITS
|
#ifdef HAVE_AUDIOUNITS
|
||||||
boost::shared_ptr<AUPlugin> ap;
|
boost::shared_ptr<AUPlugin> ap;
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -584,6 +591,10 @@ PluginInsert::plugin_factory (boost::shared_ptr<Plugin> other)
|
||||||
} else if ((vp = boost::dynamic_pointer_cast<VSTPlugin> (other)) != 0) {
|
} else if ((vp = boost::dynamic_pointer_cast<VSTPlugin> (other)) != 0) {
|
||||||
return boost::shared_ptr<Plugin> (new VSTPlugin (*vp));
|
return boost::shared_ptr<Plugin> (new VSTPlugin (*vp));
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef LXVST_SUPPORT
|
||||||
|
} else if ((lxvp = boost::dynamic_pointer_cast<LXVSTPlugin> (other)) != 0) {
|
||||||
|
return boost::shared_ptr<Plugin> (new LXVSTPlugin (*lxvp));
|
||||||
|
#endif
|
||||||
#ifdef HAVE_AUDIOUNITS
|
#ifdef HAVE_AUDIOUNITS
|
||||||
} else if ((ap = boost::dynamic_pointer_cast<AUPlugin> (other)) != 0) {
|
} else if ((ap = boost::dynamic_pointer_cast<AUPlugin> (other)) != 0) {
|
||||||
return boost::shared_ptr<Plugin> (new AUPlugin (*ap));
|
return boost::shared_ptr<Plugin> (new AUPlugin (*ap));
|
||||||
|
|
@ -852,6 +863,8 @@ PluginInsert::set_state(const XMLNode& node, int version)
|
||||||
type = ARDOUR::LV2;
|
type = ARDOUR::LV2;
|
||||||
} else if (prop->value() == X_("vst")) {
|
} else if (prop->value() == X_("vst")) {
|
||||||
type = ARDOUR::VST;
|
type = ARDOUR::VST;
|
||||||
|
} else if (prop->value() == X_("lxvst")) {
|
||||||
|
type = ARDOUR::LXVST;
|
||||||
} else if (prop->value() == X_("audiounit")) {
|
} else if (prop->value() == X_("audiounit")) {
|
||||||
type = ARDOUR::AudioUnit;
|
type = ARDOUR::AudioUnit;
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -872,6 +885,14 @@ PluginInsert::set_state(const XMLNode& node, int version)
|
||||||
prop = node.property ("id");
|
prop = node.property ("id");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef LXVST_SUPPORT
|
||||||
|
/*There shouldn't be any older sessions with linuxVST support.. but anyway..*/
|
||||||
|
|
||||||
|
if (type == ARDOUR::LXVST) {
|
||||||
|
prop = node.property ("id");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
/* recheck */
|
/* recheck */
|
||||||
|
|
||||||
if (prop == 0) {
|
if (prop == 0) {
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,12 @@
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#endif // VST_SUPPORT
|
#endif // VST_SUPPORT
|
||||||
|
|
||||||
|
#ifdef LXVST_SUPPORT
|
||||||
|
#include <ardour/vstfx.h>
|
||||||
|
#include <pbd/basename.h>
|
||||||
|
#include <cstring>
|
||||||
|
#endif //LXVST_SUPPORT
|
||||||
|
|
||||||
#include <glibmm/miscutils.h>
|
#include <glibmm/miscutils.h>
|
||||||
|
|
||||||
#include "pbd/pathscanner.h"
|
#include "pbd/pathscanner.h"
|
||||||
|
|
@ -56,6 +62,10 @@
|
||||||
#include "ardour/vst_plugin.h"
|
#include "ardour/vst_plugin.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef LXVST_SUPPORT
|
||||||
|
#include "ardour/lxvst_plugin.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_AUDIOUNITS
|
#ifdef HAVE_AUDIOUNITS
|
||||||
#include "ardour/audio_unit.h"
|
#include "ardour/audio_unit.h"
|
||||||
#include <Carbon/Carbon.h>
|
#include <Carbon/Carbon.h>
|
||||||
|
|
@ -74,6 +84,7 @@ PluginManager* PluginManager::_manager = 0;
|
||||||
|
|
||||||
PluginManager::PluginManager ()
|
PluginManager::PluginManager ()
|
||||||
: _vst_plugin_info(0)
|
: _vst_plugin_info(0)
|
||||||
|
, _lxvst_plugin_info(0)
|
||||||
, _ladspa_plugin_info(0)
|
, _ladspa_plugin_info(0)
|
||||||
, _lv2_plugin_info(0)
|
, _lv2_plugin_info(0)
|
||||||
, _au_plugin_info(0)
|
, _au_plugin_info(0)
|
||||||
|
|
@ -107,6 +118,12 @@ PluginManager::PluginManager ()
|
||||||
}
|
}
|
||||||
#endif /* VST_SUPPORT */
|
#endif /* VST_SUPPORT */
|
||||||
|
|
||||||
|
#ifdef LXVST_SUPPORT
|
||||||
|
if (Config->get_use_lxvst()) {
|
||||||
|
add_lxvst_presets();
|
||||||
|
}
|
||||||
|
#endif /* Native LinuxVST support*/
|
||||||
|
|
||||||
if ((s = getenv ("LADSPA_PATH"))) {
|
if ((s = getenv ("LADSPA_PATH"))) {
|
||||||
ladspa_path = s;
|
ladspa_path = s;
|
||||||
}
|
}
|
||||||
|
|
@ -117,6 +134,12 @@ PluginManager::PluginManager ()
|
||||||
vst_path = s;
|
vst_path = s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((s = getenv ("LXVST_PATH"))) {
|
||||||
|
vst_path = s;
|
||||||
|
} else if ((s = getenv ("LXVST_PLUGINS"))) {
|
||||||
|
vst_path = s;
|
||||||
|
}
|
||||||
|
|
||||||
if (_manager == 0) {
|
if (_manager == 0) {
|
||||||
_manager = this;
|
_manager = this;
|
||||||
}
|
}
|
||||||
|
|
@ -154,6 +177,13 @@ PluginManager::refresh ()
|
||||||
vst_refresh ();
|
vst_refresh ();
|
||||||
}
|
}
|
||||||
#endif // VST_SUPPORT
|
#endif // VST_SUPPORT
|
||||||
|
|
||||||
|
#ifdef LXVST_SUPPORT
|
||||||
|
if(Config->get_use_lxvst()) {
|
||||||
|
lxvst_refresh();
|
||||||
|
}
|
||||||
|
#endif //Native linuxVST SUPPORT
|
||||||
|
|
||||||
#ifdef HAVE_AUDIOUNITS
|
#ifdef HAVE_AUDIOUNITS
|
||||||
au_refresh ();
|
au_refresh ();
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -268,6 +298,13 @@ PluginManager::add_vst_presets()
|
||||||
{
|
{
|
||||||
add_presets ("vst");
|
add_presets ("vst");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
PluginManager::add_lxvst_presets()
|
||||||
|
{
|
||||||
|
add_presets ("lxvst");
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
PluginManager::add_presets(string domain)
|
PluginManager::add_presets(string domain)
|
||||||
{
|
{
|
||||||
|
|
@ -586,6 +623,111 @@ PluginManager::vst_discover (string path)
|
||||||
|
|
||||||
#endif // VST_SUPPORT
|
#endif // VST_SUPPORT
|
||||||
|
|
||||||
|
#ifdef LXVST_SUPPORT
|
||||||
|
|
||||||
|
void
|
||||||
|
PluginManager::lxvst_refresh ()
|
||||||
|
{
|
||||||
|
if (_lxvst_plugin_info)
|
||||||
|
_lxvst_plugin_info->clear ();
|
||||||
|
else
|
||||||
|
_lxvst_plugin_info = new ARDOUR::PluginInfoList();
|
||||||
|
|
||||||
|
if (lxvst_path.length() == 0) {
|
||||||
|
lxvst_path = "/usr/local/lib/lxvst:/usr/lib/lxvst";
|
||||||
|
}
|
||||||
|
|
||||||
|
lxvst_discover_from_path (lxvst_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
PluginManager::add_lxvst_directory (string path)
|
||||||
|
{
|
||||||
|
if (lxvst_discover_from_path (path) == 0) {
|
||||||
|
lxvst_path += ':';
|
||||||
|
lxvst_path += path;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool lxvst_filter (const string& str, void *arg)
|
||||||
|
{
|
||||||
|
/* Not a dotfile, has a prefix before a period, suffix is "so" */
|
||||||
|
|
||||||
|
return str[0] != '.' && (str.length() > 3 && str.find (".so") == (str.length() - 3));
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
PluginManager::lxvst_discover_from_path (string path)
|
||||||
|
{
|
||||||
|
PathScanner scanner;
|
||||||
|
vector<string *> *plugin_objects;
|
||||||
|
vector<string *>::iterator x;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
info << "Discovering linuxVST plugins along " << path << endmsg;
|
||||||
|
|
||||||
|
plugin_objects = scanner (lxvst_path, lxvst_filter, 0, true, true);
|
||||||
|
|
||||||
|
if (plugin_objects) {
|
||||||
|
for (x = plugin_objects->begin(); x != plugin_objects->end (); ++x) {
|
||||||
|
lxvst_discover (**x);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
info << "Done linuxVST discover" << endmsg;
|
||||||
|
|
||||||
|
vector_delete (plugin_objects);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
PluginManager::lxvst_discover (string path)
|
||||||
|
{
|
||||||
|
VSTFXInfo* finfo;
|
||||||
|
char buf[32];
|
||||||
|
|
||||||
|
if ((finfo = vstfx_get_info (const_cast<char *> (path.c_str()))) == 0) {
|
||||||
|
warning << "Cannot get linuxVST information from " << path << endmsg;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!finfo->canProcessReplacing) {
|
||||||
|
warning << string_compose (_("linuxVST plugin %1 does not support processReplacing, and so cannot be used in ardour at this time"),
|
||||||
|
finfo->name)
|
||||||
|
<< endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
PluginInfoPtr info(new LXVSTPluginInfo);
|
||||||
|
|
||||||
|
if (!strcasecmp ("The Unnamed plugin", finfo->name)) {
|
||||||
|
info->name = PBD::basename_nosuffix (path);
|
||||||
|
} else {
|
||||||
|
info->name = finfo->name;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
snprintf (buf, sizeof (buf), "%d", finfo->UniqueID);
|
||||||
|
info->unique_id = buf;
|
||||||
|
info->category = "linuxVSTs";
|
||||||
|
info->path = path;
|
||||||
|
info->creator = finfo->creator;
|
||||||
|
info->index = 0;
|
||||||
|
info->n_inputs.set_audio (finfo->numInputs);
|
||||||
|
info->n_outputs.set_audio (finfo->numOutputs);
|
||||||
|
info->n_inputs.set_midi (finfo->wantMidi ? 1 : 0);
|
||||||
|
info->type = ARDOUR::LXVST;
|
||||||
|
|
||||||
|
_lxvst_plugin_info->push_back (info);
|
||||||
|
vstfx_free_info (finfo);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // LXVST_SUPPORT
|
||||||
|
|
||||||
|
|
||||||
PluginManager::PluginStatusType
|
PluginManager::PluginStatusType
|
||||||
PluginManager::get_status (const PluginInfoPtr& pi)
|
PluginManager::get_status (const PluginInfoPtr& pi)
|
||||||
{
|
{
|
||||||
|
|
@ -625,6 +767,9 @@ PluginManager::save_statuses ()
|
||||||
case VST:
|
case VST:
|
||||||
ofs << "VST";
|
ofs << "VST";
|
||||||
break;
|
break;
|
||||||
|
case LXVST:
|
||||||
|
ofs << "LXVST";
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
ofs << ' ';
|
ofs << ' ';
|
||||||
|
|
@ -709,6 +854,8 @@ PluginManager::load_statuses ()
|
||||||
type = LV2;
|
type = LV2;
|
||||||
} else if (stype == "VST") {
|
} else if (stype == "VST") {
|
||||||
type = VST;
|
type = VST;
|
||||||
|
} else if (stype == "LXVST") {
|
||||||
|
type = LXVST;
|
||||||
} else {
|
} else {
|
||||||
error << string_compose (_("unknown plugin type \"%1\" - ignored"), stype)
|
error << string_compose (_("unknown plugin type \"%1\" - ignored"), stype)
|
||||||
<< endmsg;
|
<< endmsg;
|
||||||
|
|
@ -748,6 +895,18 @@ PluginManager::vst_plugin_info ()
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ARDOUR::PluginInfoList&
|
||||||
|
PluginManager::lxvst_plugin_info ()
|
||||||
|
{
|
||||||
|
#ifdef LXVST_SUPPORT
|
||||||
|
if (!_lxvst_plugin_info)
|
||||||
|
lxvst_refresh();
|
||||||
|
return *_lxvst_plugin_info;
|
||||||
|
#else
|
||||||
|
return _empty_plugin_info;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
ARDOUR::PluginInfoList&
|
ARDOUR::PluginInfoList&
|
||||||
PluginManager::ladspa_plugin_info ()
|
PluginManager::ladspa_plugin_info ()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -970,6 +970,7 @@ Route::add_processor_from_xml_2X (const XMLNode& node, int version)
|
||||||
if (prop->value() == "ladspa" || prop->value() == "Ladspa" ||
|
if (prop->value() == "ladspa" || prop->value() == "Ladspa" ||
|
||||||
prop->value() == "lv2" ||
|
prop->value() == "lv2" ||
|
||||||
prop->value() == "vst" ||
|
prop->value() == "vst" ||
|
||||||
|
prop->value() == "lxvst" ||
|
||||||
prop->value() == "audiounit") {
|
prop->value() == "audiounit") {
|
||||||
|
|
||||||
processor.reset (new PluginInsert (_session));
|
processor.reset (new PluginInsert (_session));
|
||||||
|
|
@ -2382,6 +2383,7 @@ Route::set_processor_state (const XMLNode& node)
|
||||||
} else if (prop->value() == "ladspa" || prop->value() == "Ladspa" ||
|
} else if (prop->value() == "ladspa" || prop->value() == "Ladspa" ||
|
||||||
prop->value() == "lv2" ||
|
prop->value() == "lv2" ||
|
||||||
prop->value() == "vst" ||
|
prop->value() == "vst" ||
|
||||||
|
prop->value() == "lxvst" ||
|
||||||
prop->value() == "audiounit") {
|
prop->value() == "audiounit") {
|
||||||
|
|
||||||
processor.reset (new PluginInsert(_session));
|
processor.reset (new PluginInsert(_session));
|
||||||
|
|
|
||||||
|
|
@ -685,6 +685,8 @@ Session::hookup_io ()
|
||||||
|
|
||||||
/* Tell all IO objects to connect themselves together */
|
/* Tell all IO objects to connect themselves together */
|
||||||
|
|
||||||
|
cerr << "Enable IO connections, state = " << _state_of_the_state << endl;
|
||||||
|
|
||||||
IO::enable_connecting ();
|
IO::enable_connecting ();
|
||||||
MIDI::Port::MakeConnections ();
|
MIDI::Port::MakeConnections ();
|
||||||
|
|
||||||
|
|
@ -4336,6 +4338,7 @@ Session::update_latency (bool playback)
|
||||||
if (playback) {
|
if (playback) {
|
||||||
/* reverse the list so that we work backwards from the last route to run to the first */
|
/* reverse the list so that we work backwards from the last route to run to the first */
|
||||||
reverse (r->begin(), r->end());
|
reverse (r->begin(), r->end());
|
||||||
|
cerr << "\n!!! I JUST REVERSED THE ROUTE LIST (" << r->size() << ")!!!\n\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
/* compute actual latency values for the given direction and store them all in per-port
|
/* compute actual latency values for the given direction and store them all in per-port
|
||||||
|
|
@ -4378,14 +4381,15 @@ Session::post_playback_latency ()
|
||||||
set_worst_playback_latency ();
|
set_worst_playback_latency ();
|
||||||
|
|
||||||
boost::shared_ptr<RouteList> r = routes.reader ();
|
boost::shared_ptr<RouteList> r = routes.reader ();
|
||||||
|
|
||||||
for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
|
for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
|
||||||
if (!(*i)->is_hidden() && ((*i)->active())) {
|
if (!(*i)->is_hidden() && ((*i)->active())) {
|
||||||
_worst_track_latency = max (_worst_track_latency, (*i)->update_signal_latency ());
|
_worst_track_latency = max (_worst_track_latency, (*i)->update_signal_latency ());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
|
for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
|
||||||
(*i)->set_latency_compensation (_worst_track_latency);
|
(*i)->set_latency_compensation (_worst_track_latency);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -4485,15 +4489,6 @@ Session::update_latency_compensation (bool force_whole_graph)
|
||||||
DEBUG_TRACE (DEBUG::Latency, string_compose ("worst signal processing latency: %1 (changed ? %2)\n", _worst_track_latency,
|
DEBUG_TRACE (DEBUG::Latency, string_compose ("worst signal processing latency: %1 (changed ? %2)\n", _worst_track_latency,
|
||||||
(some_track_latency_changed ? "yes" : "no")));
|
(some_track_latency_changed ? "yes" : "no")));
|
||||||
|
|
||||||
if (force_whole_graph || some_track_latency_changed) {
|
|
||||||
/* trigger a full recompute of latency numbers for the graph.
|
|
||||||
everything else that we need to do will be done in the latency
|
|
||||||
callback.
|
|
||||||
*/
|
|
||||||
_engine.update_total_latencies ();
|
|
||||||
return; // everything else will be done in the latency callback
|
|
||||||
}
|
|
||||||
|
|
||||||
DEBUG_TRACE(DEBUG::Latency, "---------------------------- DONE update latency compensation\n\n")
|
DEBUG_TRACE(DEBUG::Latency, "---------------------------- DONE update latency compensation\n\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
364
libs/ardour/session_lxvst.cc
Executable file
364
libs/ardour/session_lxvst.cc
Executable file
|
|
@ -0,0 +1,364 @@
|
||||||
|
/*
|
||||||
|
Copyright (C) 2004
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
/******************************************************/
|
||||||
|
/*The big 'audio master' callback for linuxVST plugins*/
|
||||||
|
/******************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <cstdio>
|
||||||
|
|
||||||
|
#include <ardour/vstfx.h>
|
||||||
|
#include <ardour/vestige/aeffectx.h>
|
||||||
|
|
||||||
|
#include <ardour/session.h>
|
||||||
|
#include <ardour/tempo.h>
|
||||||
|
#include <ardour/lxvst_plugin.h>
|
||||||
|
|
||||||
|
#include "i18n.h"
|
||||||
|
|
||||||
|
#define DEBUG_CALLBACKS
|
||||||
|
static int debug_callbacks = -1;
|
||||||
|
|
||||||
|
#ifdef DEBUG_CALLBACKS
|
||||||
|
#define SHOW_CALLBACK if (debug_callbacks) printf
|
||||||
|
#else
|
||||||
|
#define SHOW_CALLBACK(...)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
using namespace ARDOUR;
|
||||||
|
|
||||||
|
long Session::lxvst_callback (AEffect* effect,
|
||||||
|
long opcode,
|
||||||
|
long index,
|
||||||
|
long value,
|
||||||
|
void* ptr,
|
||||||
|
float opt)
|
||||||
|
{
|
||||||
|
static VstTimeInfo _timeInfo;
|
||||||
|
LXVSTPlugin* plug;
|
||||||
|
Session* session;
|
||||||
|
|
||||||
|
if (debug_callbacks < 0)
|
||||||
|
{
|
||||||
|
debug_callbacks = (getenv ("ARDOUR_DEBUG_VST_CALLBACKS") != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (effect && effect->user)
|
||||||
|
{
|
||||||
|
plug = (LXVSTPlugin*) (effect->user);
|
||||||
|
session = &plug->session();
|
||||||
|
SHOW_CALLBACK ("am callback 0x%x, opcode = %ld, plugin = \"%s\" ", (unsigned int)pthread_self(), opcode, plug->name());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
plug = 0;
|
||||||
|
session = 0;
|
||||||
|
SHOW_CALLBACK ("am callback 0x%x, opcode = %ld", (unsigned int)pthread_self(), opcode);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(opcode){
|
||||||
|
|
||||||
|
case audioMasterAutomate:
|
||||||
|
SHOW_CALLBACK ("amc: audioMasterAutomate\n");
|
||||||
|
|
||||||
|
// index, value, returns 0
|
||||||
|
if (effect) {
|
||||||
|
effect->setParameter (effect, index, opt);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case audioMasterVersion:
|
||||||
|
SHOW_CALLBACK ("amc: audioMasterVersion\n");
|
||||||
|
// vst version, currently 2 (0 for older)
|
||||||
|
return 2;
|
||||||
|
|
||||||
|
case audioMasterCurrentId:
|
||||||
|
SHOW_CALLBACK ("amc: audioMasterCurrentId\n");
|
||||||
|
// returns the unique id of a plug that's currently
|
||||||
|
// loading
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case audioMasterIdle:
|
||||||
|
SHOW_CALLBACK ("amc: audioMasterIdle\n");
|
||||||
|
// call application idle routine (this will
|
||||||
|
// call effEditIdle for all open editors too)
|
||||||
|
if (effect) {
|
||||||
|
effect->dispatcher(effect, effEditIdle, 0, 0, NULL, 0.0f);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case audioMasterPinConnected:
|
||||||
|
SHOW_CALLBACK ("amc: audioMasterPinConnected\n");
|
||||||
|
// inquire if an input or output is beeing connected;
|
||||||
|
// index enumerates input or output counting from zero:
|
||||||
|
// value is 0 for input and != 0 otherwise. note: the
|
||||||
|
// return value is 0 for <true> such that older versions
|
||||||
|
// will always return true.
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
case audioMasterWantMidi:
|
||||||
|
SHOW_CALLBACK ("amc: audioMasterWantMidi\n");
|
||||||
|
// <value> is a filter which is currently ignored
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case audioMasterGetTime:
|
||||||
|
SHOW_CALLBACK ("amc: audioMasterGetTime\n");
|
||||||
|
// returns const VstTimeInfo* (or 0 if not supported)
|
||||||
|
// <value> should contain a mask indicating which fields are required
|
||||||
|
// (see valid masks above), as some items may require extensive
|
||||||
|
// conversions
|
||||||
|
memset(&_timeInfo, 0, sizeof(_timeInfo));
|
||||||
|
if (session) {
|
||||||
|
_timeInfo.samplePos = session->transport_frame();
|
||||||
|
_timeInfo.sampleRate = session->frame_rate();
|
||||||
|
_timeInfo.flags = 0;
|
||||||
|
|
||||||
|
if (value & (kVstTempoValid)) {
|
||||||
|
const Tempo& t (session->tempo_map().tempo_at (session->transport_frame()));
|
||||||
|
_timeInfo.tempo = t.beats_per_minute ();
|
||||||
|
_timeInfo.flags |= (kVstTempoValid);
|
||||||
|
}
|
||||||
|
if (value & (kVstBarsValid)) {
|
||||||
|
const Meter& m (session->tempo_map().meter_at (session->transport_frame()));
|
||||||
|
_timeInfo.timeSigNumerator = m.beats_per_bar ();
|
||||||
|
_timeInfo.timeSigDenominator = m.note_divisor ();
|
||||||
|
_timeInfo.flags |= (kVstBarsValid);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (session->transport_speed() != 0.0f) {
|
||||||
|
_timeInfo.flags |= kVstTransportPlaying;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (long)&_timeInfo;
|
||||||
|
|
||||||
|
case audioMasterProcessEvents:
|
||||||
|
SHOW_CALLBACK ("amc: audioMasterProcessEvents\n");
|
||||||
|
// VstEvents* in <ptr>
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case audioMasterSetTime:
|
||||||
|
SHOW_CALLBACK ("amc: audioMasterSetTime\n");
|
||||||
|
// VstTimenfo* in <ptr>, filter in <value>, not supported
|
||||||
|
|
||||||
|
case audioMasterTempoAt:
|
||||||
|
SHOW_CALLBACK ("amc: audioMasterTempoAt\n");
|
||||||
|
// returns tempo (in bpm * 10000) at sample frame location passed in <value>
|
||||||
|
if (session) {
|
||||||
|
const Tempo& t (session->tempo_map().tempo_at (value));
|
||||||
|
return t.beats_per_minute() * 1000;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case audioMasterGetNumAutomatableParameters:
|
||||||
|
SHOW_CALLBACK ("amc: audioMasterGetNumAutomatableParameters\n");
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case audioMasterGetParameterQuantization:
|
||||||
|
SHOW_CALLBACK ("amc: audioMasterGetParameterQuantization\n");
|
||||||
|
// returns the integer value for +1.0 representation,
|
||||||
|
// or 1 if full single float precision is maintained
|
||||||
|
// in automation. parameter index in <value> (-1: all, any)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case audioMasterIOChanged:
|
||||||
|
SHOW_CALLBACK ("amc: audioMasterIOChanged\n");
|
||||||
|
// numInputs and/or numOutputs has changed
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case audioMasterNeedIdle:
|
||||||
|
SHOW_CALLBACK ("amc: audioMasterNeedIdle\n");
|
||||||
|
// plug needs idle calls (outside its editor window)
|
||||||
|
if (plug) {
|
||||||
|
plug->vstfx()->wantIdle = 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case audioMasterSizeWindow:
|
||||||
|
SHOW_CALLBACK ("amc: audioMasterSizeWindow\n");
|
||||||
|
// index: width, value: height
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case audioMasterGetSampleRate:
|
||||||
|
SHOW_CALLBACK ("amc: audioMasterGetSampleRate\n");
|
||||||
|
if (session) {
|
||||||
|
return session->frame_rate();
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case audioMasterGetBlockSize:
|
||||||
|
SHOW_CALLBACK ("amc: audioMasterGetBlockSize\n");
|
||||||
|
if (session) {
|
||||||
|
return session->get_block_size();
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case audioMasterGetInputLatency:
|
||||||
|
SHOW_CALLBACK ("amc: audioMasterGetInputLatency\n");
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case audioMasterGetOutputLatency:
|
||||||
|
SHOW_CALLBACK ("amc: audioMasterGetOutputLatency\n");
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case audioMasterGetPreviousPlug:
|
||||||
|
SHOW_CALLBACK ("amc: audioMasterGetPreviousPlug\n");
|
||||||
|
// input pin in <value> (-1: first to come), returns cEffect*
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case audioMasterGetNextPlug:
|
||||||
|
SHOW_CALLBACK ("amc: audioMasterGetNextPlug\n");
|
||||||
|
// output pin in <value> (-1: first to come), returns cEffect*
|
||||||
|
|
||||||
|
case audioMasterWillReplaceOrAccumulate:
|
||||||
|
SHOW_CALLBACK ("amc: audioMasterWillReplaceOrAccumulate\n");
|
||||||
|
// returns: 0: not supported, 1: replace, 2: accumulate
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case audioMasterGetCurrentProcessLevel:
|
||||||
|
SHOW_CALLBACK ("amc: audioMasterGetCurrentProcessLevel\n");
|
||||||
|
// returns: 0: not supported,
|
||||||
|
// 1: currently in user thread (gui)
|
||||||
|
// 2: currently in audio thread (where process is called)
|
||||||
|
// 3: currently in 'sequencer' thread (midi, timer etc)
|
||||||
|
// 4: currently offline processing and thus in user thread
|
||||||
|
// other: not defined, but probably pre-empting user thread.
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case audioMasterGetAutomationState:
|
||||||
|
SHOW_CALLBACK ("amc: audioMasterGetAutomationState\n");
|
||||||
|
// returns 0: not supported, 1: off, 2:read, 3:write, 4:read/write
|
||||||
|
// offline
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case audioMasterOfflineStart:
|
||||||
|
SHOW_CALLBACK ("amc: audioMasterOfflineStart\n");
|
||||||
|
case audioMasterOfflineRead:
|
||||||
|
SHOW_CALLBACK ("amc: audioMasterOfflineRead\n");
|
||||||
|
// ptr points to offline structure, see below. return 0: error, 1 ok
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case audioMasterOfflineWrite:
|
||||||
|
SHOW_CALLBACK ("amc: audioMasterOfflineWrite\n");
|
||||||
|
// same as read
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case audioMasterOfflineGetCurrentPass:
|
||||||
|
SHOW_CALLBACK ("amc: audioMasterOfflineGetCurrentPass\n");
|
||||||
|
case audioMasterOfflineGetCurrentMetaPass:
|
||||||
|
SHOW_CALLBACK ("amc: audioMasterOfflineGetCurrentMetaPass\n");
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case audioMasterSetOutputSampleRate:
|
||||||
|
SHOW_CALLBACK ("amc: audioMasterSetOutputSampleRate\n");
|
||||||
|
// for variable i/o, sample rate in <opt>
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case audioMasterGetSpeakerArrangement:
|
||||||
|
SHOW_CALLBACK ("amc: audioMasterGetSpeakerArrangement\n");
|
||||||
|
// (long)input in <value>, output in <ptr>
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case audioMasterGetVendorString:
|
||||||
|
SHOW_CALLBACK ("amc: audioMasterGetVendorString\n");
|
||||||
|
// fills <ptr> with a string identifying the vendor (max 64 char)
|
||||||
|
strcpy ((char*) ptr, "Linux Audio Systems");
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case audioMasterGetProductString:
|
||||||
|
SHOW_CALLBACK ("amc: audioMasterGetProductString\n");
|
||||||
|
// fills <ptr> with a string with product name (max 64 char)
|
||||||
|
strcpy ((char*) ptr, "Ardour");
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case audioMasterGetVendorVersion:
|
||||||
|
SHOW_CALLBACK ("amc: audioMasterGetVendorVersion\n");
|
||||||
|
// returns vendor-specific version
|
||||||
|
return 900;
|
||||||
|
|
||||||
|
case audioMasterVendorSpecific:
|
||||||
|
SHOW_CALLBACK ("amc: audioMasterVendorSpecific\n");
|
||||||
|
// no definition, vendor specific handling
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case audioMasterSetIcon:
|
||||||
|
SHOW_CALLBACK ("amc: audioMasterSetIcon\n");
|
||||||
|
// void* in <ptr>, format not defined yet
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case audioMasterCanDo:
|
||||||
|
SHOW_CALLBACK ("amc: audioMasterCanDo\n");
|
||||||
|
// string in ptr, see below
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case audioMasterGetLanguage:
|
||||||
|
SHOW_CALLBACK ("amc: audioMasterGetLanguage\n");
|
||||||
|
// see enum
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case audioMasterOpenWindow:
|
||||||
|
SHOW_CALLBACK ("amc: audioMasterOpenWindow\n");
|
||||||
|
// returns platform specific ptr
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case audioMasterCloseWindow:
|
||||||
|
SHOW_CALLBACK ("amc: audioMasterCloseWindow\n");
|
||||||
|
// close window, platform specific handle in <ptr>
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case audioMasterGetDirectory:
|
||||||
|
SHOW_CALLBACK ("amc: audioMasterGetDirectory\n");
|
||||||
|
// get plug directory, FSSpec on MAC, else char*
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case audioMasterUpdateDisplay:
|
||||||
|
SHOW_CALLBACK ("amc: audioMasterUpdateDisplay\n");
|
||||||
|
// something has changed, update 'multi-fx' display
|
||||||
|
if (effect) {
|
||||||
|
effect->dispatcher(effect, effEditIdle, 0, 0, NULL, 0.0f);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case audioMasterBeginEdit:
|
||||||
|
SHOW_CALLBACK ("amc: audioMasterBeginEdit\n");
|
||||||
|
// begin of automation session (when mouse down), parameter index in <index>
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case audioMasterEndEdit:
|
||||||
|
SHOW_CALLBACK ("amc: audioMasterEndEdit\n");
|
||||||
|
// end of automation session (when mouse up), parameter index in <index>
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case audioMasterOpenFileSelector:
|
||||||
|
SHOW_CALLBACK ("amc: audioMasterOpenFileSelector\n");
|
||||||
|
// open a fileselector window with VstFileSelect* in <ptr>
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
default:
|
||||||
|
SHOW_CALLBACK ("LXVST master dispatcher: undefed: %d\n", (int)opcode);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -92,55 +92,32 @@ int sndfile_endian_formats[SNDFILE_ENDIAN_FORMATS] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
int
|
int
|
||||||
sndfile_header_format_from_string (string str)
|
sndfile_header_format_by_index (int index)
|
||||||
{
|
{
|
||||||
for (int n = 0; sndfile_header_formats_strings[n]; ++n) {
|
if (index >= 0 && index < SNDFILE_HEADER_FORMATS) {
|
||||||
if (str == sndfile_header_formats_strings[n]) {
|
return sndfile_header_formats[index];
|
||||||
return sndfile_header_formats[n];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
sndfile_bitdepth_format_from_string (string str)
|
sndfile_bitdepth_format_by_index (int index)
|
||||||
{
|
{
|
||||||
for (int n = 0; sndfile_bitdepth_formats_strings[n]; ++n) {
|
if (index >= 0 && index < SNDFILE_BITDEPTH_FORMATS) {
|
||||||
if (str == sndfile_bitdepth_formats_strings[n]) {
|
return sndfile_bitdepth_formats[index];
|
||||||
return sndfile_bitdepth_formats[n];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
sndfile_endian_format_from_string (string str)
|
sndfile_endian_format_by_index (int index)
|
||||||
{
|
{
|
||||||
for (int n = 0; sndfile_endian_formats_strings[n]; ++n) {
|
if (index >= 0 && index < SNDFILE_ENDIAN_FORMATS) {
|
||||||
if (str == sndfile_endian_formats_strings[n]) {
|
return sndfile_endian_formats[index];
|
||||||
return sndfile_endian_formats[n];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
string
|
|
||||||
sndfile_file_ending_from_string (string str)
|
|
||||||
{
|
|
||||||
static vector<string> file_endings;
|
|
||||||
|
|
||||||
if (file_endings.empty()) {
|
|
||||||
file_endings = I18N((const char **) sndfile_file_endings_strings);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int n = 0; sndfile_header_formats_strings[n]; ++n) {
|
|
||||||
if (str == sndfile_header_formats_strings[n]) {
|
|
||||||
return file_endings[n];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
int
|
||||||
sndfile_data_width (int format)
|
sndfile_data_width (int format)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -75,7 +75,7 @@ legalize_for_path (const string& str)
|
||||||
pos += 1;
|
pos += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return legal;
|
return string (legal);
|
||||||
}
|
}
|
||||||
|
|
||||||
string
|
string
|
||||||
|
|
|
||||||
32
libs/ardour/vstfx.cc
Executable file
32
libs/ardour/vstfx.cc
Executable file
|
|
@ -0,0 +1,32 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
#include <ardour/vstfx.h>
|
||||||
|
|
||||||
|
/***********************************************************/
|
||||||
|
/* VSTFX - A set of modules for managing linux VST plugins */
|
||||||
|
/* vstfx.cc, vstfxwin.cc and vstfxinfofile.cc */
|
||||||
|
/***********************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
/*Simple error handler stuff for VSTFX*/
|
||||||
|
|
||||||
|
void vstfx_error (const char *fmt, ...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
char buffer[512];
|
||||||
|
|
||||||
|
va_start (ap, fmt);
|
||||||
|
vsnprintf (buffer, sizeof(buffer), fmt, ap);
|
||||||
|
vstfx_error_callback (buffer);
|
||||||
|
va_end (ap);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*default error handler callback*/
|
||||||
|
|
||||||
|
void default_vstfx_error_callback (const char *desc)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "%s\n", desc);
|
||||||
|
}
|
||||||
|
|
||||||
|
void (*vstfx_error_callback)(const char *desc) = &default_vstfx_error_callback;
|
||||||
382
libs/ardour/vstfxinfofile.cc
Executable file
382
libs/ardour/vstfxinfofile.cc
Executable file
|
|
@ -0,0 +1,382 @@
|
||||||
|
/***********************************************************/
|
||||||
|
/*vstfx infofile - module to manage info files */
|
||||||
|
/*containing cached information about a plugin. e.g. its */
|
||||||
|
/*name, creator etc etc */
|
||||||
|
/***********************************************************/
|
||||||
|
|
||||||
|
/*This is largely unmodified from the original (C code) FST vstinfofile module*/
|
||||||
|
|
||||||
|
#include "ardour/vstfx.h"
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <libgen.h>
|
||||||
|
|
||||||
|
#define MAX_STRING_LEN 256
|
||||||
|
|
||||||
|
#define FALSE 0
|
||||||
|
#define TRUE !FALSE
|
||||||
|
|
||||||
|
static char* read_string(FILE *fp)
|
||||||
|
{
|
||||||
|
char buf[MAX_STRING_LEN];
|
||||||
|
|
||||||
|
fgets( buf, MAX_STRING_LEN, fp );
|
||||||
|
|
||||||
|
if(strlen(buf) < MAX_STRING_LEN)
|
||||||
|
{
|
||||||
|
if(strlen(buf))
|
||||||
|
buf[strlen(buf)-1] = 0;
|
||||||
|
|
||||||
|
return strdup(buf);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static VSTFXInfo* load_vstfx_info_file(char *filename)
|
||||||
|
{
|
||||||
|
VSTFXInfo *info = (VSTFXInfo*) malloc(sizeof(VSTFXInfo));
|
||||||
|
FILE *fp;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if(info == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
fp = fopen(filename, "r");
|
||||||
|
|
||||||
|
if(fp == NULL)
|
||||||
|
{
|
||||||
|
free( info );
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if((info->name = read_string(fp)) == NULL) goto error;
|
||||||
|
if((info->creator = read_string(fp)) == NULL) goto error;
|
||||||
|
if(1 != fscanf(fp, "%d\n", &info->UniqueID)) goto error;
|
||||||
|
if((info->Category = read_string(fp)) == NULL) goto error;
|
||||||
|
if(1 != fscanf(fp, "%d\n", &info->numInputs)) goto error;
|
||||||
|
if(1 != fscanf(fp, "%d\n", &info->numOutputs)) goto error;
|
||||||
|
if(1 != fscanf(fp, "%d\n", &info->numParams)) goto error;
|
||||||
|
if(1 != fscanf(fp, "%d\n", &info->wantMidi)) goto error;
|
||||||
|
if(1 != fscanf(fp, "%d\n", &info->hasEditor)) goto error;
|
||||||
|
if(1 != fscanf(fp, "%d\n", &info->canProcessReplacing)) goto error;
|
||||||
|
|
||||||
|
if((info->ParamNames = (char **) malloc(sizeof(char*)*info->numParams)) == NULL) goto error;
|
||||||
|
for(i=0; i<info->numParams; i++)
|
||||||
|
{
|
||||||
|
if((info->ParamNames[i] = read_string(fp)) == NULL) goto error;
|
||||||
|
}
|
||||||
|
if((info->ParamLabels = (char **) malloc(sizeof(char*)*info->numParams)) == NULL) goto error;
|
||||||
|
|
||||||
|
for(i=0; i < info->numParams; i++)
|
||||||
|
{
|
||||||
|
if((info->ParamLabels[i] = read_string(fp)) == NULL) goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose( fp );
|
||||||
|
return info;
|
||||||
|
|
||||||
|
error:
|
||||||
|
fclose( fp );
|
||||||
|
free( info );
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int save_vstfx_info_file(VSTFXInfo *info, char *filename)
|
||||||
|
{
|
||||||
|
FILE *fp;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if(info == NULL)
|
||||||
|
{
|
||||||
|
vstfx_error("** ERROR ** VSTFXinfofile : info ptr is NULL\n");
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
fp = fopen(filename, "w");
|
||||||
|
|
||||||
|
if(fp == NULL)
|
||||||
|
{
|
||||||
|
vstfx_error("** WARNING ** VSTFX : Can't write info file %s\n", filename);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf( fp, "%s\n", info->name );
|
||||||
|
fprintf( fp, "%s\n", info->creator );
|
||||||
|
fprintf( fp, "%d\n", info->UniqueID );
|
||||||
|
fprintf( fp, "%s\n", info->Category );
|
||||||
|
fprintf( fp, "%d\n", info->numInputs );
|
||||||
|
fprintf( fp, "%d\n", info->numOutputs );
|
||||||
|
fprintf( fp, "%d\n", info->numParams );
|
||||||
|
fprintf( fp, "%d\n", info->wantMidi );
|
||||||
|
fprintf( fp, "%d\n", info->hasEditor );
|
||||||
|
fprintf( fp, "%d\n", info->canProcessReplacing );
|
||||||
|
|
||||||
|
for(i=0; i < info->numParams; i++)
|
||||||
|
{
|
||||||
|
fprintf(fp, "%s\n", info->ParamNames[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(i=0; i < info->numParams; i++)
|
||||||
|
{
|
||||||
|
fprintf(fp, "%s\n", info->ParamLabels[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose( fp );
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char* vstfx_dllpath_to_infopath(char *dllpath)
|
||||||
|
{
|
||||||
|
char* retval;
|
||||||
|
char* dir_path;
|
||||||
|
char* base_name;
|
||||||
|
|
||||||
|
if(strstr(dllpath, ".so" ) == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
/*Allocate space for the filename - need strlen + 1 for the terminating'0', +1 because .so is three
|
||||||
|
chars, and .fsi is four chars and +1 because we have a '.' at the beginning*/
|
||||||
|
|
||||||
|
retval = (char*)malloc(strlen(dllpath) + 3);
|
||||||
|
|
||||||
|
dir_path = strdup(dllpath);
|
||||||
|
base_name = strdup(dllpath);
|
||||||
|
|
||||||
|
sprintf(retval, "%s/.%s", dirname(dir_path), basename(base_name));
|
||||||
|
sprintf(retval + strlen(retval) - 3, ".fsi");
|
||||||
|
|
||||||
|
free(dir_path);
|
||||||
|
free(base_name);
|
||||||
|
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int vstfx_info_file_is_valid(char *dllpath)
|
||||||
|
{
|
||||||
|
struct stat dllstat;
|
||||||
|
struct stat vstfxstat;
|
||||||
|
|
||||||
|
char *vstfxpath = vstfx_dllpath_to_infopath(dllpath);
|
||||||
|
|
||||||
|
if(!vstfxpath)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
if(stat(dllpath, &dllstat))
|
||||||
|
{
|
||||||
|
vstfx_error( "** ERROR ** VSTFXinfofile : .so path %s invalid\n", dllpath );
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(stat(vstfxpath, &vstfxstat))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
free(vstfxpath);
|
||||||
|
|
||||||
|
if(dllstat.st_mtime > vstfxstat.st_mtime)
|
||||||
|
return FALSE;
|
||||||
|
else
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int vstfx_can_midi(VSTFX *vstfx)
|
||||||
|
{
|
||||||
|
struct AEffect *plugin = vstfx->plugin;
|
||||||
|
|
||||||
|
int vst_version = plugin->dispatcher (plugin, effGetVstVersion, 0, 0, NULL, 0.0f);
|
||||||
|
|
||||||
|
if (vst_version >= 2)
|
||||||
|
{
|
||||||
|
/* should we send it VST events (i.e. MIDI) */
|
||||||
|
|
||||||
|
if ((plugin->flags & effFlagsIsSynth) || (plugin->dispatcher (plugin, effCanDo, 0, 0,(void*) "receiveVstEvents", 0.0f) > 0))
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static VSTFXInfo* vstfx_info_from_plugin(VSTFX *vstfx)
|
||||||
|
{
|
||||||
|
|
||||||
|
VSTFXInfo* info = (VSTFXInfo*) malloc(sizeof(VSTFXInfo));
|
||||||
|
|
||||||
|
struct AEffect *plugin;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/*We need to init the creator because some plugins
|
||||||
|
fail to implement getVendorString, and so won't stuff the
|
||||||
|
string with any name*/
|
||||||
|
|
||||||
|
char creator[65] = "Unknown\0";
|
||||||
|
|
||||||
|
if(!vstfx)
|
||||||
|
{
|
||||||
|
vstfx_error( "** ERROR ** VSTFXinfofile : vstfx ptr is NULL\n" );
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!info)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
plugin = vstfx->plugin;
|
||||||
|
|
||||||
|
info->name = strdup(vstfx->handle->name );
|
||||||
|
|
||||||
|
/*If the plugin doesn't bother to implement GetVendorString we will
|
||||||
|
have pre-stuffed the string with 'Unkown' */
|
||||||
|
|
||||||
|
plugin->dispatcher (plugin, effGetVendorString, 0, 0, creator, 0);
|
||||||
|
|
||||||
|
/*Some plugins DO implement GetVendorString, but DON'T put a name in it
|
||||||
|
so if its just a zero length string we replace it with 'Unknown' */
|
||||||
|
|
||||||
|
if (strlen(creator) == 0)
|
||||||
|
{
|
||||||
|
info->creator = strdup("Unknown");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
info->creator = strdup (creator);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined LXVST_64BIT && defined VESTIGE_HEADER
|
||||||
|
|
||||||
|
/*On 64Bit the data alignment in AEffect struct is
|
||||||
|
incorrect using vestige. see lxvst_plugin.cc*/
|
||||||
|
|
||||||
|
info->UniqueID = *((int32_t *) &((AEffect*)(((char*)(plugin)) + 12))->unused_id);
|
||||||
|
|
||||||
|
#elif defined LXVST_32BIT && defined VESTIGE_HEADER
|
||||||
|
|
||||||
|
info->UniqueID = *((int32_t *) &plugin->unused_id);
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
info->UniqueID = plugin->uniqueID;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
info->Category = strdup("None"); // FIXME:
|
||||||
|
info->numInputs = plugin->numInputs;
|
||||||
|
info->numOutputs = plugin->numOutputs;
|
||||||
|
info->numParams = plugin->numParams;
|
||||||
|
info->wantMidi = vstfx_can_midi(vstfx);
|
||||||
|
info->hasEditor = plugin->flags & effFlagsHasEditor ? TRUE : FALSE;
|
||||||
|
info->canProcessReplacing = plugin->flags & effFlagsCanReplacing ? TRUE : FALSE;
|
||||||
|
info->ParamNames = (char **) malloc(sizeof(char*)*info->numParams);
|
||||||
|
info->ParamLabels = (char **) malloc(sizeof(char*)*info->numParams);
|
||||||
|
for(i=0; i < info->numParams; i++)
|
||||||
|
{
|
||||||
|
char name[64];
|
||||||
|
char label[64];
|
||||||
|
|
||||||
|
/*Not all plugins give parameters labels as well as names*/
|
||||||
|
|
||||||
|
strcpy(name, "No Name");
|
||||||
|
strcpy(label, "No Label");
|
||||||
|
|
||||||
|
plugin->dispatcher (plugin, effGetParamName, i, 0, name, 0);
|
||||||
|
info->ParamNames[i] = strdup(name);
|
||||||
|
|
||||||
|
plugin->dispatcher (plugin, effGetParamLabel, i, 0, label, 0);
|
||||||
|
info->ParamLabels[i] = strdup(label);
|
||||||
|
}
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* A simple 'dummy' audiomaster callback which should be ok,
|
||||||
|
we will only be instantiating the plugin in order to get its info*/
|
||||||
|
|
||||||
|
static long simple_master_callback(struct AEffect *fx, long opcode, long index, long value, void *ptr, float opt)
|
||||||
|
{
|
||||||
|
|
||||||
|
if(opcode == audioMasterVersion)
|
||||||
|
return 2;
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*Try to get plugin info - first by looking for a .fsi cache of the
|
||||||
|
data, and if that doesn't exist, load the plugin, get its data and
|
||||||
|
then cache it for future ref*/
|
||||||
|
|
||||||
|
VSTFXInfo *vstfx_get_info(char *dllpath)
|
||||||
|
{
|
||||||
|
if( vstfx_info_file_is_valid(dllpath))
|
||||||
|
{
|
||||||
|
VSTFXInfo *info;
|
||||||
|
char *vstfxpath = vstfx_dllpath_to_infopath(dllpath);
|
||||||
|
|
||||||
|
info = load_vstfx_info_file(vstfxpath);
|
||||||
|
free(vstfxpath);
|
||||||
|
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
VSTFXHandle *h;
|
||||||
|
VSTFX *vstfx;
|
||||||
|
VSTFXInfo *info;
|
||||||
|
|
||||||
|
char *vstfxpath;
|
||||||
|
|
||||||
|
if(!(h = vstfx_load(dllpath)))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if(!(vstfx = vstfx_instantiate(h, simple_master_callback, NULL)))
|
||||||
|
{
|
||||||
|
vstfx_unload(h);
|
||||||
|
vstfx_error( "** ERROR ** VSTFXinfofile : Instantiate failed\n" );
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
vstfxpath = vstfx_dllpath_to_infopath(dllpath);
|
||||||
|
|
||||||
|
if(!vstfxpath)
|
||||||
|
{
|
||||||
|
vstfx_close(vstfx);
|
||||||
|
vstfx_unload(h);
|
||||||
|
vstfx_error( "** ERROR ** VSTFXinfofile : get vstfx filename failed\n" );
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
info = vstfx_info_from_plugin(vstfx);
|
||||||
|
|
||||||
|
save_vstfx_info_file(info, vstfxpath);
|
||||||
|
|
||||||
|
free(vstfxpath);
|
||||||
|
|
||||||
|
vstfx_close(vstfx);
|
||||||
|
vstfx_unload(h);
|
||||||
|
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void vstfx_free_info(VSTFXInfo *info )
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for(i=0; i < info->numParams; i++)
|
||||||
|
{
|
||||||
|
free(info->ParamNames[i]);
|
||||||
|
free(info->ParamLabels[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(info->name);
|
||||||
|
free(info->creator);
|
||||||
|
free(info->Category);
|
||||||
|
free(info);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
1399
libs/ardour/vstfxwin.cc
Executable file
1399
libs/ardour/vstfxwin.cc
Executable file
File diff suppressed because it is too large
Load diff
|
|
@ -396,6 +396,11 @@ def build(bld):
|
||||||
obj.source += [ 'vst_plugin.cc', 'session_vst.cc' ]
|
obj.source += [ 'vst_plugin.cc', 'session_vst.cc' ]
|
||||||
obj.includes += [ '../fst' ]
|
obj.includes += [ '../fst' ]
|
||||||
obj.defines += [ 'VST_SUPPORT' ]
|
obj.defines += [ 'VST_SUPPORT' ]
|
||||||
|
|
||||||
|
if bld.env['LXVST_SUPPORT']:
|
||||||
|
obj.source += [ 'lxvst_plugin.cc', 'session_lxvst.cc', 'vstfx.cc', 'vstfxwin.cc', 'vstfxinfofile.cc' ]
|
||||||
|
obj.defines += [ 'LXVST_SUPPORT' ]
|
||||||
|
|
||||||
|
|
||||||
if bld.env['COREAUDIO']:
|
if bld.env['COREAUDIO']:
|
||||||
obj.source += [ 'coreaudiosource.cc', 'caimportable.cc' ]
|
obj.source += [ 'coreaudiosource.cc', 'caimportable.cc' ]
|
||||||
|
|
|
||||||
15
wscript
15
wscript
|
|
@ -246,7 +246,14 @@ def set_compiler_flags (conf,opt):
|
||||||
print("\nIt is theoretically possible to build a 32 bit host on a 64 bit system.")
|
print("\nIt is theoretically possible to build a 32 bit host on a 64 bit system.")
|
||||||
print("However, this is tricky and not recommended for beginners.")
|
print("However, this is tricky and not recommended for beginners.")
|
||||||
sys.exit (-1)
|
sys.exit (-1)
|
||||||
|
|
||||||
|
if conf.env['build_target'] == 'x86_64' and opt.lxvst:
|
||||||
|
print("\n\n********************************************************")
|
||||||
|
print("* Building with 64Bit linuxVST support is experimental *")
|
||||||
|
print("********************************************************\n\n")
|
||||||
|
conf.env.append_value('CXXFLAGS', "-DLXVST_64BIT")
|
||||||
|
else:
|
||||||
|
conf.env.append_value('CXXFLAGS', "-DLXVST_32BIT")
|
||||||
#
|
#
|
||||||
# a single way to test if we're on OS X
|
# a single way to test if we're on OS X
|
||||||
#
|
#
|
||||||
|
|
@ -362,6 +369,8 @@ def set_options(opt):
|
||||||
help='Compile for use with gprofile')
|
help='Compile for use with gprofile')
|
||||||
opt.add_option('--lv2', action='store_true', default=False, dest='lv2',
|
opt.add_option('--lv2', action='store_true', default=False, dest='lv2',
|
||||||
help='Compile with support for LV2 (if SLV2 or Lilv+Suil is available)')
|
help='Compile with support for LV2 (if SLV2 or Lilv+Suil is available)')
|
||||||
|
opt.add_option('--lxvst', action='store_true', default=False, dest='lxvst',
|
||||||
|
help='Compile with support for linuxVST plugins')
|
||||||
opt.add_option('--nls', action='store_true', default=True, dest='nls',
|
opt.add_option('--nls', action='store_true', default=True, dest='nls',
|
||||||
help='Enable i18n (native language support) (default)')
|
help='Enable i18n (native language support) (default)')
|
||||||
opt.add_option('--no-nls', action='store_false', dest='nls')
|
opt.add_option('--no-nls', action='store_false', dest='nls')
|
||||||
|
|
@ -531,6 +540,9 @@ def configure(conf):
|
||||||
conf.define('VST_SUPPORT', 1)
|
conf.define('VST_SUPPORT', 1)
|
||||||
conf.env.append_value('CPPPATH', Options.options.wine_include)
|
conf.env.append_value('CPPPATH', Options.options.wine_include)
|
||||||
autowaf.check_header(conf, 'windows.h', mandatory = True)
|
autowaf.check_header(conf, 'windows.h', mandatory = True)
|
||||||
|
if opts.lxvst:
|
||||||
|
conf.define('LXVST_SUPPORT', 1)
|
||||||
|
conf.env['LXVST_SUPPORT'] = True
|
||||||
if bool(conf.env['JACK_SESSION']):
|
if bool(conf.env['JACK_SESSION']):
|
||||||
conf.define ('HAVE_JACK_SESSION', 1)
|
conf.define ('HAVE_JACK_SESSION', 1)
|
||||||
if opts.wiimote:
|
if opts.wiimote:
|
||||||
|
|
@ -572,6 +584,7 @@ const char* const ardour_config_info = "\\n\\
|
||||||
write_config_text('JACK session support', bool(conf.env['JACK_SESSION']))
|
write_config_text('JACK session support', bool(conf.env['JACK_SESSION']))
|
||||||
write_config_text('LV2 UI embedding', bool(conf.env['HAVE_SUIL']))
|
write_config_text('LV2 UI embedding', bool(conf.env['HAVE_SUIL']))
|
||||||
write_config_text('LV2 support', bool(conf.env['LV2_SUPPORT']))
|
write_config_text('LV2 support', bool(conf.env['LV2_SUPPORT']))
|
||||||
|
write_config_text('LXVST support', bool(conf.env['LXVST_SUPPORT']))
|
||||||
write_config_text('OGG', bool(conf.env['HAVE_OGG']))
|
write_config_text('OGG', bool(conf.env['HAVE_OGG']))
|
||||||
write_config_text('Phone home', bool(conf.env['PHONE_HOME']))
|
write_config_text('Phone home', bool(conf.env['PHONE_HOME']))
|
||||||
write_config_text('Program name', opts.program_name)
|
write_config_text('Program name', opts.program_name)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue