diff options
author | Paul Davis <paul@linuxaudiosystems.com> | 2009-03-13 03:53:22 +0000 |
---|---|---|
committer | Paul Davis <paul@linuxaudiosystems.com> | 2009-03-13 03:53:22 +0000 |
commit | 82da4fa3ac435712831580da183b4abd1062e0ff (patch) | |
tree | e0513ac8c3563112958bd50f993a708a92cb5fc7 /libs | |
parent | 6a869dfb7a5ff2393553037e0cff31c9484403f3 (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.cc | 2 | ||||
-rw-r--r-- | libs/ardour/session_transport.cc | 55 | ||||
-rw-r--r-- | libs/ardour/session_vst.cc | 39 | ||||
-rw-r--r-- | libs/ardour/vst_plugin.cc | 16 | ||||
-rw-r--r-- | libs/fst/SConscript | 3 | ||||
-rw-r--r-- | libs/fst/fst.h | 3 | ||||
-rw-r--r-- | libs/fst/thread.c | 89 | ||||
-rw-r--r-- | libs/fst/vestige/aeffectx.h | 46 | ||||
-rw-r--r-- | libs/fst/vstwin.c | 6 |
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; } |