summaryrefslogtreecommitdiff
path: root/libs
diff options
context:
space:
mode:
authorPaul Davis <paul@linuxaudiosystems.com>2009-03-13 03:53:22 +0000
committerPaul Davis <paul@linuxaudiosystems.com>2009-03-13 03:53:22 +0000
commit82da4fa3ac435712831580da183b4abd1062e0ff (patch)
treee0513ac8c3563112958bd50f993a708a92cb5fc7 /libs
parent6a869dfb7a5ff2393553037e0cff31c9484403f3 (diff)
a lot of VST support odds-and-ends, including preset discovery and support, extending vestige header a bit, some new thread stuff (may break compilation against JACK, and deliver partial tempo/meter info to VST plugins
git-svn-id: svn://localhost/ardour2/branches/2.0-ongoing@4824 d708f5d6-7413-0410-9779-e7cbd77b26cf
Diffstat (limited to 'libs')
-rw-r--r--libs/ardour/session.cc2
-rw-r--r--libs/ardour/session_transport.cc55
-rw-r--r--libs/ardour/session_vst.cc39
-rw-r--r--libs/ardour/vst_plugin.cc16
-rw-r--r--libs/fst/SConscript3
-rw-r--r--libs/fst/fst.h3
-rw-r--r--libs/fst/thread.c89
-rw-r--r--libs/fst/vestige/aeffectx.h46
-rw-r--r--libs/fst/vstwin.c6
9 files changed, 221 insertions, 38 deletions
diff --git a/libs/ardour/session.cc b/libs/ardour/session.cc
index e0221b53cc..fdbe81a368 100644
--- a/libs/ardour/session.cc
+++ b/libs/ardour/session.cc
@@ -1308,6 +1308,8 @@ Session::disable_record (bool rt_context, bool force)
if ((rs = (RecordState) g_atomic_int_get (&_record_status)) != Disabled) {
+ cerr << "disable record is doing something\n";
+
if ((!Config->get_latched_record_enable () && !play_loop) || force) {
g_atomic_int_set (&_record_status, Disabled);
} else {
diff --git a/libs/ardour/session_transport.cc b/libs/ardour/session_transport.cc
index 0249350d2e..d99d184795 100644
--- a/libs/ardour/session_transport.cc
+++ b/libs/ardour/session_transport.cc
@@ -49,6 +49,8 @@ using namespace ARDOUR;
using namespace sigc;
using namespace PBD;
+#define DEBUG_TRANSPORT
+
void
Session::request_input_change_handling ()
{
@@ -77,6 +79,9 @@ void
Session::request_transport_speed (float speed)
{
Event* ev = new Event (Event::SetTransportSpeed, Event::Add, Event::Immediate, 0, speed);
+#ifdef DEBUG_TRANSPORT
+ cerr << "Queued transport speed request @ " << speed << endl;
+#endif
queue_event (ev);
}
@@ -136,11 +141,13 @@ Session::realtime_stop (bool abort)
{
/* assume that when we start, we'll be moving forwards */
+#if 1
if (_transport_speed < 0.0f) {
post_transport_work = PostTransportWork (post_transport_work | PostTransportStop | PostTransportReverse);
} else {
post_transport_work = PostTransportWork (post_transport_work | PostTransportStop);
}
+#endif
if (actively_recording()) {
@@ -162,21 +169,25 @@ Session::realtime_stop (bool abort)
post_transport_work = PostTransportWork (post_transport_work | PostTransportAbort);
}
+#if 0
+
_clear_event_type (Event::StopOnce);
_clear_event_type (Event::RangeStop);
_clear_event_type (Event::RangeLocate);
- disable_record (true);
-
- reset_slave_state ();
-
+ // disable_record (true);
+
+ // reset_slave_state ();
+#endif
_transport_speed = 0;
+#if 0
if (Config->get_use_video_sync()) {
waiting_for_sync_offset = true;
}
transport_sub_state = ((Config->get_slave_source() == None && Config->get_auto_return()) ? AutoReturning : 0);
+#endif
}
void
@@ -190,6 +201,8 @@ Session::butler_transport_work ()
int on_entry = g_atomic_int_get (&butler_should_do_transport_work);
finished = true;
+ cerr << "PTW = " << hex << post_transport_work << dec << endl;
+
if (post_transport_work & PostTransportCurveRealloc) {
for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
(*i)->curve_reallocate();
@@ -235,11 +248,12 @@ Session::butler_transport_work ()
}
if (post_transport_work & (PostTransportStop|PostTransportLocate)) {
- non_realtime_stop (post_transport_work & PostTransportAbort, on_entry, finished);
- if (!finished) {
- g_atomic_int_dec_and_test (&butler_should_do_transport_work);
- goto restart;
- }
+ // cerr << "call NRS\n";
+ // non_realtime_stop (post_transport_work & PostTransportAbort, on_entry, finished);
+ // if (!finished) {
+ // g_atomic_int_dec_and_test (&butler_should_do_transport_work);
+ // goto restart;
+ // }
}
if (post_transport_work & PostTransportOverWrite) {
@@ -294,6 +308,8 @@ Session::non_realtime_stop (bool abort, int on_entry, bool& finished)
did_record = false;
saved = false;
+ cerr << "NRS\n";
+
boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
@@ -351,6 +367,8 @@ Session::non_realtime_stop (bool abort, int on_entry, bool& finished)
_have_captured = true;
}
+ return;
+
for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
(*i)->transport_stopped (*now, xnow, abort);
}
@@ -377,6 +395,7 @@ Session::non_realtime_stop (bool abort, int on_entry, bool& finished)
synced_to_jack()) {
if (pending_locate_flush) {
+ cerr << "Flush all redirects\n";
flush_all_redirects ();
}
@@ -480,7 +499,7 @@ Session::non_realtime_stop (bool abort, int on_entry, bool& finished)
}
if (post_transport_work & PostTransportStop) {
- _play_range = false;
+ // _play_range = false;
/* do not turn off autoloop on stop */
@@ -778,6 +797,10 @@ Session::locate (nframes_t target_frame, bool with_roll, bool with_flush, bool w
void
Session::set_transport_speed (float speed, bool abort)
{
+#ifdef DEBUG_TRANSPORT
+ cerr << "Session::set_trasport_speed, new = " << speed
+ << " cur = " << _transport_speed << endl;
+#endif
if (_transport_speed == speed) {
return;
}
@@ -886,6 +909,10 @@ Session::set_transport_speed (float speed, bool abort)
void
Session::stop_transport (bool abort)
{
+#ifdef DEBUG_TRANSPORT
+ cerr << "Session::stop_transport @ " << _transport_frame << endl;
+#endif
+
if (_transport_speed == 0.0f) {
return;
}
@@ -921,12 +948,16 @@ Session::stop_transport (bool abort)
}
realtime_stop (abort);
- schedule_butler_transport_work ();
+ // schedule_butler_transport_work ();
}
void
Session::start_transport ()
{
+#ifdef DEBUG_TRANSPORT
+ cerr << "Session::start_transport @ " << _transport_frame << endl;
+#endif
+
_last_roll_location = _transport_frame;
have_looped = false;
@@ -977,7 +1008,7 @@ Session::post_transport ()
if (post_transport_work & PostTransportStop) {
- transport_sub_state = 0;
+ // transport_sub_state = 0;
}
if (post_transport_work & PostTransportLocate) {
diff --git a/libs/ardour/session_vst.cc b/libs/ardour/session_vst.cc
index 7c5daddd6f..a973ce7fa9 100644
--- a/libs/ardour/session_vst.cc
+++ b/libs/ardour/session_vst.cc
@@ -24,11 +24,12 @@
#include <fst/vestige/aeffectx.h>
#include <ardour/session.h>
+#include <ardour/tempo.h>
#include <ardour/vst_plugin.h>
#include "i18n.h"
-// #define DEBUG_CALLBACKS
+#define DEBUG_CALLBACKS
#ifdef DEBUG_CALLBACKS
#define SHOW_CALLBACK printf
@@ -49,14 +50,15 @@ long Session::vst_callback (AEffect* effect,
VSTPlugin* plug;
Session* session;
- SHOW_CALLBACK ("am callback, opcode = %d", opcode);
if (effect && effect->user) {
plug = (VSTPlugin*) (effect->user);
session = &plug->session();
+ SHOW_CALLBACK ("am callback %d, opcode = %ld, plugin = \"%s\" ", pthread_self(), opcode, plug->name());
} else {
plug = 0;
session = 0;
+ SHOW_CALLBACK ("am callback %d, opcode = %ld", pthread_self(), opcode);
}
switch(opcode){
@@ -113,7 +115,30 @@ long Session::vst_callback (AEffect* effect,
if (session) {
_timeInfo.samplePos = session->transport_frame();
_timeInfo.sampleRate = session->frame_rate();
+ _timeInfo.flags = 0;
+
+ cerr << "pos = " << _timeInfo.samplePos << " SR = " << _timeInfo.sampleRate
+ << " asked for " << std::hex << value << std::dec << endl;
+
+ if (value & (kVstTempoValid)) {
+ const Tempo& t (session->tempo_map().tempo_at (session->transport_frame()));
+ _timeInfo.tempo = t.beats_per_minute ();
+ _timeInfo.flags |= (kVstTempoValid);
+ cerr << "Tempo = " << _timeInfo.tempo << endl;
+ }
+ 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);
+ cerr << "Meter = " << _timeInfo.timeSigNumerator << '/' << _timeInfo.timeSigDenominator << endl;
+ }
+
+ if (session->transport_speed() != 0.0f) {
+ _timeInfo.flags |= kVstTransportPlaying;
+ }
}
+
return (long)&_timeInfo;
case audioMasterProcessEvents:
@@ -128,7 +153,13 @@ long Session::vst_callback (AEffect* effect,
case audioMasterTempoAt:
SHOW_CALLBACK ("amc: audioMasterTempoAt\n");
// returns tempo (in bpm * 10000) at sample frame location passed in <value>
- return 0;
+ 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");
@@ -306,7 +337,7 @@ long Session::vst_callback (AEffect* effect,
return 0;
default:
- SHOW_CALLBACK ("VST master dispatcher: undefed: %d, %d\n", opcode, effKeysRequired);
+ SHOW_CALLBACK ("VST master dispatcher: undefed: %d\n", opcode);
break;
}
diff --git a/libs/ardour/vst_plugin.cc b/libs/ardour/vst_plugin.cc
index feafb29bc9..20ba7fea24 100644
--- a/libs/ardour/vst_plugin.cc
+++ b/libs/ardour/vst_plugin.cc
@@ -70,13 +70,16 @@ VSTPlugin::VSTPlugin (AudioEngine& e, Session& session, FSTHandle* h)
/* set rate and blocksize */
+ cerr << name() << " dispatch effSetSampleRate\n";
_plugin->dispatcher (_plugin, effSetSampleRate, 0, 0, NULL,
(float) session.frame_rate());
+ cerr << name() << " dispatch effSetBlockSize\n";
_plugin->dispatcher (_plugin, effSetBlockSize, 0,
session.get_block_size(), NULL, 0.0f);
/* set program to zero */
+ cerr << name() << " dispatch effSetProgram\n";
_plugin->dispatcher (_plugin, effSetProgram, 0, 0, NULL, 0.0f);
Plugin::setup_controls ();
@@ -106,6 +109,7 @@ void
VSTPlugin::set_block_size (nframes_t nframes)
{
deactivate ();
+ cerr << name() << " dispatch effSetBlockSize\n";
_plugin->dispatcher (_plugin, effSetBlockSize, 0, nframes, NULL, 0.0f);
activate ();
}
@@ -150,6 +154,7 @@ VSTPlugin::get_state()
void* data;
long data_size;
+ cerr << name() << " dispatch = GetChunk\n";
if ((data_size = _plugin->dispatcher (_plugin, 23 /* effGetChunk */, 0, 0, &data, false)) == 0) {
return *root;
}
@@ -253,6 +258,7 @@ VSTPlugin::get_parameter_descriptor (uint32_t which, ParameterDescriptor& desc)
desc.min_unbound = false;
desc.max_unbound = false;
+ cerr << name() << " dispatch ParamProps\n";
if (_plugin->dispatcher (_plugin, effGetParameterProperties, which, 0, &prop, 0)) {
#ifdef VESTIGE_COMPLETE
@@ -300,6 +306,7 @@ VSTPlugin::get_parameter_descriptor (uint32_t which, ParameterDescriptor& desc)
char label[64];
label[0] = '\0';
+ cerr << name() << " dispatch effGetParamName\n";
_plugin->dispatcher (_plugin, effGetParamName, which, 0, label, 0);
desc.label = label;
@@ -345,6 +352,7 @@ string
VSTPlugin::describe_parameter (uint32_t param)
{
char name[64];
+ cerr << this->name() << " dispatch effGetParamName\n";
_plugin->dispatcher (_plugin, effGetParamName, param, 0, name, 0);
return name;
}
@@ -378,6 +386,7 @@ VSTPlugin::connect_and_run (vector<Sample*>& bufs, uint32_t maxbuf, int32_t& in_
float *outs[_plugin->numOutputs];
int32_t i;
+
for (i = 0; i < (int32_t) _plugin->numInputs; ++i) {
ins[i] = bufs[min((uint32_t) in_index,maxbuf - 1)] + offset;
in_index++;
@@ -398,20 +407,24 @@ VSTPlugin::connect_and_run (vector<Sample*>& bufs, uint32_t maxbuf, int32_t& in_
/* we already know it can support processReplacing */
+ cerr << "++++++++++ " << name() << " RUN in " << pthread_self() << endl;
_plugin->processReplacing (_plugin, ins, outs, nframes);
-
+ cerr << "\tdone\n";
+
return 0;
}
void
VSTPlugin::deactivate ()
{
+ cerr << "\n\n\n ************ " << name() << " DEACTIVATE in " << pthread_self() << endl;
_plugin->dispatcher (_plugin, effMainsChanged, 0, 0, NULL, 0.0f);
}
void
VSTPlugin::activate ()
{
+ cerr << "\n\n\n ************ " << name() << " ACTIVATE in " << pthread_self() << endl;
_plugin->dispatcher (_plugin, effMainsChanged, 0, 1, NULL, 0.0f);
}
@@ -463,6 +476,7 @@ VSTPlugin::print_parameter (uint32_t param, char *buf, uint32_t len) const
{
char *first_nonws;
+ cerr << name() << " dispatch paramDisplay\n";
_plugin->dispatcher (_plugin, 7 /* effGetParamDisplay */, param, 0, buf, 0);
if (buf[0] == '\0') {
diff --git a/libs/fst/SConscript b/libs/fst/SConscript
index 92c7504257..0980dd6ca0 100644
--- a/libs/fst/SConscript
+++ b/libs/fst/SConscript
@@ -17,8 +17,9 @@ if fst['VST']:
b = fst.Object ('fstinfofile', 'fstinfofile.c')
c = fst.Object ('vstwin', 'vstwin.c')
d = fst.Object ('vsti', 'vsti.c')
+ e = fst.Object ('thread', 'thread.c')
- Default([a,b,c,d])
+ Default([a,b,c,d,e])
env.Alias('tarball', env.Distribute (env['DISTTREE'],
fst_src + ['SConscript',
diff --git a/libs/fst/fst.h b/libs/fst/fst.h
index 2a0130667a..463d022640 100644
--- a/libs/fst/fst.h
+++ b/libs/fst/fst.h
@@ -133,6 +133,9 @@ extern int fst_load_state (FST * fst, char * filename);
*/
extern int fst_save_state (FST * fst, char * filename);
+extern int wine_pthread_create (pthread_t* thread_id, const pthread_attr_t* attr, void *(*function)(void*), void* arg);
+
+
#ifdef __cplusplus
}
#endif
diff --git a/libs/fst/thread.c b/libs/fst/thread.c
new file mode 100644
index 0000000000..2c1fa2e9ec
--- /dev/null
+++ b/libs/fst/thread.c
@@ -0,0 +1,89 @@
+#include <stdio.h>
+#include <sys/types.h>
+#include <pthread.h>
+#include <windows.h>
+
+typedef struct {
+ void* (*thread_function)(void*);
+ void* thread_arg;
+ pthread_t thread_id;
+ pthread_mutex_t init_lock;
+ pthread_cond_t init_cond;
+ pthread_attr_t attr;
+} real_thread_info_t;
+
+static DWORD WINAPI
+fake_thread_proxy (LPVOID parameter)
+{
+ real_thread_info_t* rti = (real_thread_info_t*) parameter;
+
+ fprintf (stderr, "WINDOWS THREAD, @ pthread = %p\n", pthread_self());
+
+ pthread_mutex_lock (&rti->init_lock);
+ rti->thread_id = pthread_self();
+ pthread_cond_signal (&rti->init_cond);
+ pthread_mutex_unlock (&rti->init_lock);
+
+#if 0
+ if (pthread_attr_get_schedparam (&rti->attr)) {
+ pthread_set_schedparam (pthread_self(), policy, sched_param);
+ }
+#endif
+ /* XXX no way to use pthread API to set contention scope,
+ because that has to be done before a thread is created.
+ But ... its only meaningful for an M:N thread implemenation
+ so its not important for the only platform where
+ this code matters (Linux running Wine) because Linux
+ uses a 1:1 thread design.
+ */
+
+ return (DWORD) rti->thread_function (rti->thread_arg);
+}
+
+int
+wine_pthread_create (pthread_t* thread_id, const pthread_attr_t* attr, void *(*function)(void*), void* arg)
+{
+ DWORD tid;
+ size_t stack_size;
+
+ fprintf (stderr, "****** Lets make a windows pthread\n");
+
+ real_thread_info_t* rti = (real_thread_info_t*) malloc (sizeof (real_thread_info_t));
+
+ rti->thread_function = function;
+ rti->thread_arg = arg;
+ if (attr) {
+ rti->attr = *attr;
+ }
+
+ fprintf (stderr, "\tset up the locks\n");
+
+ pthread_mutex_init (&rti->init_lock, NULL);
+ pthread_cond_init (&rti->init_cond, NULL);
+
+ pthread_mutex_lock (&rti->init_lock);
+
+ fprintf (stderr, "\tget the stacksize\n");
+
+ if (attr) {
+ if (pthread_attr_getstacksize (attr, &stack_size) != 0) {
+ stack_size = 0;
+ }
+ } else {
+ stack_size = 0;
+ }
+
+ fprintf (stderr, "\tget that sucker started in the proxy, stacksize = %u\n", stack_size);
+
+ if (CreateThread (0, stack_size, fake_thread_proxy, rti, 0, &tid) == NULL) {
+ return -1;
+ }
+
+ pthread_cond_wait (&rti->init_cond, &rti->init_lock);
+ pthread_mutex_unlock (&rti->init_lock);
+ fprintf (stderr, "\tlet it run\n");
+
+ *thread_id = rti->thread_id;
+
+ return 0;
+}
diff --git a/libs/fst/vestige/aeffectx.h b/libs/fst/vestige/aeffectx.h
index 790c93e6dc..4389ce70ec 100644
--- a/libs/fst/vestige/aeffectx.h
+++ b/libs/fst/vestige/aeffectx.h
@@ -129,8 +129,18 @@
#define kVstMidiType 1
#define kVstTransportPlaying (1 << 1)
#define kVstParameterUsesFloatStep (1 << 2)
+
+/* 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
@@ -253,30 +263,26 @@ typedef struct AEffect
typedef struct VstTimeInfo
{
- // 00
- double samplePos;
- // 08
- double sampleRate;
- // unconfirmed 10 18
- char empty1[8 + 8];
- // 20?
- double tempo;
- // unconfirmed 28 30 38
- char empty2[8 + 8 + 8];
- // 40?
- int timeSigNumerator;
- // 44?
- int timeSigDenominator;
- // unconfirmed 48 4c 50
- char empty3[4 + 4 + 4];
- // 54
- int flags;
+ /* 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
diff --git a/libs/fst/vstwin.c b/libs/fst/vstwin.c
index fc9ac0c999..2fce334f0a 100644
--- a/libs/fst/vstwin.c
+++ b/libs/fst/vstwin.c
@@ -1,4 +1,6 @@
#include <stdio.h>
+#include <jack/jack.h>
+#include <jack/thread.h>
#include <libgen.h>
#include <windows.h>
#include <winnt.h>
@@ -182,6 +184,7 @@ again:
/* condition/unlock: it was signalled & unlocked in fst_create_editor() */
}
if(fst->want_program != -1 ) {
+ fprintf (stderr, "switching to program %d\n", fst->want_program);
fst->plugin->dispatcher (fst->plugin, effSetProgram, 0, fst->want_program, NULL, 0);
fst->want_program = -1;
}
@@ -263,6 +266,9 @@ fst_init (void* possible_hmodule)
fst_error ("could not create new thread proxy");
return -1;
}
+
+ jack_set_thread_creator (wine_pthread_create);
+
return 0;
}