Audacity 3.2.0
Classes | Public Member Functions | Static Public Member Functions | Private Member Functions | Private Attributes | List of all members
LV2Wrapper Class Referencefinal

Manager of a handle to an LV2 plug-in instantiation. More...

#include <LV2Wrapper.h>

Collaboration diagram for LV2Wrapper:
[legend]

Classes

struct  CreateToken
 To compel use of the factory. More...
 
struct  LV2Work
 

Public Member Functions

 LV2Wrapper (CreateToken &&, LV2InstanceFeaturesList &baseFeatures, const LilvPlugin &plugin, float sampleRate)
 Constructor may spawn a thread. More...
 
 ~LV2Wrapper ()
 If a thread was started, joins it. More...
 
void ConnectControlPorts (const LV2Ports &ports, const LV2EffectSettings &settings, EffectOutputs *pOutputs)
 
void ConnectPorts (const LV2Ports &ports, LV2PortStates &portStates, const LV2EffectSettings &settings, EffectOutputs *pOutputs)
 
void Activate ()
 
void Deactivate ()
 
LilvInstance & GetInstance () const
 
LV2_Handle GetHandle () const
 
float GetLatency () const
 
void SetFreeWheeling (bool enable)
 
void SendBlockSize ()
 
void ConsumeResponses ()
 
LV2_Worker_Status ScheduleWork (uint32_t size, const void *data)
 
LV2_Worker_Status Respond (uint32_t size, const void *data)
 
LV2WrapperFeaturesListGetFeatures ()
 
const LV2WrapperFeaturesListGetFeatures () const
 

Static Public Member Functions

static std::unique_ptr< LV2WrapperCreate (LV2InstanceFeaturesList &baseFeatures, const LV2Ports &ports, LV2PortStates &portStates, const LV2EffectSettings &settings, float sampleRate, EffectOutputs *pOutputs)
 Factory. More...
 
static LV2_Worker_Status schedule_work (LV2_Worker_Schedule_Handle handle, uint32_t size, const void *data)
 
static LV2_Worker_Status respond (LV2_Worker_Respond_Handle handle, uint32_t size, const void *data)
 

Private Member Functions

void ThreadFunction ()
 

Private Attributes

LV2_Worker_Schedule mWorkerSchedule { this, LV2Wrapper::schedule_work }
 
LV2WrapperFeaturesList mFeaturesList
 
const LilvInstancePtr mInstance
 
const LV2_Handle mHandle
 
const LV2_Options_Interface *const mOptionsInterface
 
const LV2_State_Interface *const mStateInterface
 
const LV2_Worker_Interface *const mWorkerInterface
 
std::thread mThread
 
wxMessageQueue< LV2WorkmRequests
 
wxMessageQueue< LV2WorkmResponses
 
float mLatency { 0.0 }
 
bool mFreeWheeling { false }
 If true, do not spawn extra worker threads. More...
 
bool mStopWorker { false }
 
bool mActivated { false }
 

Detailed Description

Manager of a handle to an LV2 plug-in instantiation.

Definition at line 44 of file LV2Wrapper.h.

Constructor & Destructor Documentation

◆ LV2Wrapper()

LV2Wrapper::LV2Wrapper ( CreateToken &&  ,
LV2InstanceFeaturesList baseFeatures,
const LilvPlugin &  plugin,
float  sampleRate 
)

Constructor may spawn a thread.

Definition at line 124 of file LV2Wrapper.cpp.

126 : mFeaturesList{ baseFeatures, sampleRate, &mWorkerSchedule }
127, mInstance{ [&instanceFeaturesList = mFeaturesList, &plugin, sampleRate](){
128 auto features = instanceFeaturesList.GetFeaturePointers();
129
130#if defined(__WXMSW__)
131 // Plugins may have dependencies that need to be loaded from the same path
132 // as the main DLL, so add this plugin's path to the DLL search order.
133 const auto libNode = lilv_plugin_get_library_uri(&plugin);
134 const auto libUri = lilv_node_as_uri(libNode);
135 LilvCharsPtr libPath{ lilv_file_uri_parse(libUri, nullptr) };
136 const auto path = wxPathOnly(libPath.get());
137 SetDllDirectory(path.c_str());
138 auto cleanup = finally([]{ SetDllDirectory(nullptr); });
139#endif
140
141 auto result = lilv_plugin_instantiate(&plugin, sampleRate, features.data());
142 return result ? result : throw std::exception{};
143}()}
144, mHandle{ lilv_instance_get_handle(mInstance.get()) }
145, mOptionsInterface{ static_cast<const LV2_Options_Interface *>(
146 lilv_instance_get_extension_data(mInstance.get(), LV2_OPTIONS__interface))
147}
148, mStateInterface{ static_cast<const LV2_State_Interface *>(
149 lilv_instance_get_extension_data(mInstance.get(), LV2_STATE__interface))
150}
151, mWorkerInterface{ static_cast<const LV2_Worker_Interface *>(
152 lilv_instance_get_extension_data(mInstance.get(), LV2_WORKER__interface))
153}
154{
156 mThread = std::thread{
157 std::mem_fn( &LV2Wrapper::ThreadFunction ), std::ref(*this)
158 };
159}
Lilv_ptr< char, free_chars > LilvCharsPtr
Definition: LV2Utils.h:29
std::thread mThread
Definition: LV2Wrapper.h:116
const LV2_Handle mHandle
Definition: LV2Wrapper.h:105
const LV2_State_Interface *const mStateInterface
Definition: LV2Wrapper.h:112
const LilvInstancePtr mInstance
Definition: LV2Wrapper.h:104
void ThreadFunction()
Definition: LV2Wrapper.cpp:212
const LV2_Options_Interface *const mOptionsInterface
Definition: LV2Wrapper.h:110
LV2_Worker_Schedule mWorkerSchedule
Definition: LV2Wrapper.h:99
LV2WrapperFeaturesList mFeaturesList
Definition: LV2Wrapper.h:101
const LV2_Worker_Interface *const mWorkerInterface
Definition: LV2Wrapper.h:114

References anonymous_namespace{ClipSegmentTest.cpp}::sampleRate.

◆ ~LV2Wrapper()

LV2Wrapper::~LV2Wrapper ( )

If a thread was started, joins it.

Definition at line 110 of file LV2Wrapper.cpp.

111{
112 if (mInstance) {
113 if (mThread.joinable()) {
114 // Even if we have been freewheeling, this unblocks the unused thread
115 // so it can be joined
116 mStopWorker = true;
117 mRequests.Post({ 0, NULL }); // Must do after writing mStopWorker
118 mThread.join();
119 }
120 Deactivate();
121 }
122}
wxMessageQueue< LV2Work > mRequests
Definition: LV2Wrapper.h:117
void Deactivate()
Definition: LV2Wrapper.cpp:169
bool mStopWorker
Definition: LV2Wrapper.h:126

References Deactivate(), mInstance, mRequests, mStopWorker, and mThread.

Here is the call graph for this function:

Member Function Documentation

◆ Activate()

void LV2Wrapper::Activate ( )

Definition at line 161 of file LV2Wrapper.cpp.

162{
163 if (!mActivated) {
164 lilv_instance_activate(&GetInstance());
165 mActivated = true;
166 }
167}
bool mActivated
Definition: LV2Wrapper.h:127
LilvInstance & GetInstance() const
Definition: LV2Wrapper.cpp:177

References GetInstance(), and mActivated.

Here is the call graph for this function:

◆ ConnectControlPorts()

void LV2Wrapper::ConnectControlPorts ( const LV2Ports ports,
const LV2EffectSettings settings,
EffectOutputs pOutputs 
)

Definition at line 64 of file LV2Wrapper.cpp.

67{
68 const auto instance = &GetInstance();
69 static float blackHole;
70 auto pValues = static_cast<LV2EffectOutputs *>(pOutputs);
71
72 // Connect all control ports
73 const auto latencyPort = ports.mLatencyPort;
74 if (latencyPort >= 0)
75 lilv_instance_connect_port(instance, latencyPort, &mLatency);
76
77 auto &values = settings.values;
78 size_t index = 0;
79 for (auto & port : ports.mControlPorts) {
80 void *const location = port->mIsInput
81 // Settings slots for input ports must pass to the library
82 // as nominal pointers to non-const
83 ? &const_cast<float&>(values[index])
84 : pValues ? &pValues->values[index]
85 : &blackHole
86 ;
87 lilv_instance_connect_port(instance, port->mIndex, location);
88 ++index;
89 }
90}
const wxChar * values
static Settings & settings()
Definition: TrackInfo.cpp:51
LV2ControlPortArray mControlPorts
Definition: LV2Ports.h:283
int mLatencyPort
Definition: LV2Ports.h:289
float mLatency
Definition: LV2Wrapper.h:119
Carry output control port information back to main thread.
Definition: LV2Ports.h:228

References GetInstance(), LV2Ports::mControlPorts, mLatency, LV2Ports::mLatencyPort, settings(), and values.

Referenced by ConnectPorts().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ ConnectPorts()

void LV2Wrapper::ConnectPorts ( const LV2Ports ports,
LV2PortStates portStates,
const LV2EffectSettings settings,
EffectOutputs pOutputs 
)

Definition at line 92 of file LV2Wrapper.cpp.

94{
95 ConnectControlPorts(ports, settings, pOutputs);
96
97 const auto instance = &GetInstance();
98
99 // Connect all atom ports
100 for (auto & state : portStates.mAtomPortStates)
101 lilv_instance_connect_port(instance,
102 state->mpPort->mIndex, state->mBuffer.get());
103
104 // We don't fully support CV ports, so connect them to dummy buffers for now.
105 for (auto & state : portStates.mCVPortStates)
106 lilv_instance_connect_port(instance, state.mpPort->mIndex,
107 state.mBuffer.get());
108}
LV2CVPortStateArray mCVPortStates
Definition: LV2Ports.h:299
LV2AtomPortStateArray mAtomPortStates
Definition: LV2Ports.h:298
void ConnectControlPorts(const LV2Ports &ports, const LV2EffectSettings &settings, EffectOutputs *pOutputs)
Definition: LV2Wrapper.cpp:64

References ConnectControlPorts(), GetInstance(), LV2PortStates::mAtomPortStates, LV2PortStates::mCVPortStates, and settings().

Here is the call graph for this function:

◆ ConsumeResponses()

void LV2Wrapper::ConsumeResponses ( )

Definition at line 223 of file LV2Wrapper.cpp.

224{
225 if (mWorkerInterface) {
226 LV2Work work{};
227 while (mResponses.ReceiveTimeout(0, work) == wxMSGQUEUE_NO_ERROR)
228 // Invoke foreign instance code in main (destructive) or
229 // audio thread (real-time) processing
230 mWorkerInterface->work_response(mHandle, work.size, work.data);
231 if (mWorkerInterface->end_run)
232 // More foreign code
233 mWorkerInterface->end_run(mHandle);
234 }
235}
wxMessageQueue< LV2Work > mResponses
Definition: LV2Wrapper.h:118

References mHandle, mResponses, and mWorkerInterface.

◆ Create()

std::unique_ptr< LV2Wrapper > LV2Wrapper::Create ( LV2InstanceFeaturesList baseFeatures,
const LV2Ports ports,
LV2PortStates portStates,
const LV2EffectSettings settings,
float  sampleRate,
EffectOutputs pOutputs 
)
static

Factory.

Definition at line 32 of file LV2Wrapper.cpp.

37{
38 auto &plug = baseFeatures.mPlug;
39
40 std::unique_ptr<LV2Wrapper> wrapper;
41 try {
42 wrapper = std::make_unique<LV2Wrapper>(CreateToken{},
43 baseFeatures, plug, sampleRate);
44 } catch(const std::exception&) {
45 return nullptr;
46 }
47
48 const auto instance = &wrapper->GetInstance();
49 wrapper->SendBlockSize();
50 wrapper->ConnectPorts(ports, portStates, settings, pOutputs);
51
52 // Give plugin a chance to initialize. The SWH plugins (like AllPass) need
53 // this before it can be safely deleted.
54 lilv_instance_activate(instance);
55 lilv_instance_deactivate(instance);
56
57 // Send to the dialog whatever was the result of that "pulse"
58 for (auto & state : portStates.mAtomPortStates)
59 state->ReceiveFromInstance();
60
61 return wrapper;
62}
const LilvPlugin & mPlug

References LV2PortStates::mAtomPortStates, LV2FeaturesListBase::mPlug, anonymous_namespace{ClipSegmentTest.cpp}::sampleRate, and settings().

Referenced by LV2Instance::MakeWrapper(), LV2Instance::RealtimeAddProcessor(), and anonymous_namespace{LoadLV2.cpp}::LV2PluginValidator::Validate().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ Deactivate()

void LV2Wrapper::Deactivate ( )

Definition at line 169 of file LV2Wrapper.cpp.

170{
171 if (mActivated) {
172 lilv_instance_deactivate(&GetInstance());
173 mActivated = false;
174 }
175}

References GetInstance(), and mActivated.

Referenced by ~LV2Wrapper().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ GetFeatures() [1/2]

LV2WrapperFeaturesList & LV2Wrapper::GetFeatures ( )
inline

Definition at line 92 of file LV2Wrapper.h.

92{ return mFeaturesList; }

◆ GetFeatures() [2/2]

const LV2WrapperFeaturesList & LV2Wrapper::GetFeatures ( ) const
inline

Definition at line 93 of file LV2Wrapper.h.

93{ return mFeaturesList; }

◆ GetHandle()

LV2_Handle LV2Wrapper::GetHandle ( ) const

Definition at line 182 of file LV2Wrapper.cpp.

183{
184 return mHandle;
185}

References mHandle.

◆ GetInstance()

LilvInstance & LV2Wrapper::GetInstance ( ) const

Definition at line 177 of file LV2Wrapper.cpp.

178{
179 return *mInstance;
180}

References mInstance.

Referenced by Activate(), ConnectControlPorts(), ConnectPorts(), and Deactivate().

Here is the caller graph for this function:

◆ GetLatency()

float LV2Wrapper::GetLatency ( ) const

Definition at line 187 of file LV2Wrapper.cpp.

188{
189 return mLatency;
190}

References mLatency.

◆ respond()

LV2_Worker_Status LV2Wrapper::respond ( LV2_Worker_Respond_Handle  handle,
uint32_t  size,
const void *  data 
)
static

Definition at line 260 of file LV2Wrapper.cpp.

262{
263 return static_cast<LV2Wrapper*>(handle)->Respond(size, data);
264}
Manager of a handle to an LV2 plug-in instantiation.
Definition: LV2Wrapper.h:45
LV2_Worker_Status Respond(uint32_t size, const void *data)
Definition: LV2Wrapper.cpp:266

References Respond(), and size.

Referenced by ScheduleWork(), and ThreadFunction().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ Respond()

LV2_Worker_Status LV2Wrapper::Respond ( uint32_t  size,
const void *  data 
)

Definition at line 266 of file LV2Wrapper.cpp.

267{
268 // Put in the queue, for another thread -- when not "freewheeling."
269 // Otherwise it is just roundabout communication within a thread
270 const auto err = mResponses.Post({ size, data });
271 return (err == wxMSGQUEUE_NO_ERROR)
272 ? LV2_WORKER_SUCCESS : LV2_WORKER_ERR_UNKNOWN;
273}

References mResponses, and size.

Referenced by respond().

Here is the caller graph for this function:

◆ schedule_work()

LV2_Worker_Status LV2Wrapper::schedule_work ( LV2_Worker_Schedule_Handle  handle,
uint32_t  size,
const void *  data 
)
static

Definition at line 238 of file LV2Wrapper.cpp.

240{
241 return static_cast<LV2Wrapper *>(handle)->ScheduleWork(size, data);
242}
LV2_Worker_Status ScheduleWork(uint32_t size, const void *data)
Definition: LV2Wrapper.cpp:244

References ScheduleWork(), and size.

Here is the call graph for this function:

◆ ScheduleWork()

LV2_Worker_Status LV2Wrapper::ScheduleWork ( uint32_t  size,
const void *  data 
)

Definition at line 244 of file LV2Wrapper.cpp.

245{
246 if (mFreeWheeling)
247 // Not using another thread
248 return mWorkerInterface->work(mHandle, respond, this, size, data);
249 else {
250 // Put in the queue for the worker thread
251 // which will then do mWorkerInterface->work
252 const auto err = mRequests.Post({ size, data });
253 return (err == wxMSGQUEUE_NO_ERROR)
254 ? LV2_WORKER_SUCCESS : LV2_WORKER_ERR_UNKNOWN;
255 }
256}
static LV2_Worker_Status respond(LV2_Worker_Respond_Handle handle, uint32_t size, const void *data)
Definition: LV2Wrapper.cpp:260
bool mFreeWheeling
If true, do not spawn extra worker threads.
Definition: LV2Wrapper.h:122

References mFreeWheeling, mHandle, mRequests, mWorkerInterface, respond(), and size.

Referenced by schedule_work().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ SendBlockSize()

void LV2Wrapper::SendBlockSize ( )

Definition at line 198 of file LV2Wrapper.cpp.

199{
200 if (auto pOption = mFeaturesList.Base().NominalBlockLengthOption()
201 ; pOption && mOptionsInterface && mOptionsInterface->set
202 ){
203 LV2_Options_Option options[2]{ *pOption, {} };
204 // I assume the pointer to temporary options is not retained by
205 // well written plug-ins, but they may watch the location at the pointer
206 // that is in the option structure.
207 mOptionsInterface->set(mHandle, options);
208 }
209}
const LV2_Options_Option * NominalBlockLengthOption() const
const LV2InstanceFeaturesList & Base() const

References LV2WrapperFeaturesList::Base(), mFeaturesList, mHandle, mOptionsInterface, and LV2InstanceFeaturesList::NominalBlockLengthOption().

Here is the call graph for this function:

◆ SetFreeWheeling()

void LV2Wrapper::SetFreeWheeling ( bool  enable)

Definition at line 193 of file LV2Wrapper.cpp.

194{
195 mFreeWheeling = enable;
196}

References mFreeWheeling.

◆ ThreadFunction()

void LV2Wrapper::ThreadFunction ( )
private

Definition at line 212 of file LV2Wrapper.cpp.

213{
214 for (LV2Work work{};
215 // Must test mStopWorker only after reading mRequests
216 mRequests.Receive(work) == wxMSGQUEUE_NO_ERROR && !mStopWorker;
217 )
218 // Call foreign instance code in this thread, which is neither the
219 // main nor the audio thread
220 mWorkerInterface->work(mHandle, respond, this, work.size, work.data);
221}

References mHandle, mRequests, mStopWorker, mWorkerInterface, and respond().

Here is the call graph for this function:

Member Data Documentation

◆ mActivated

bool LV2Wrapper::mActivated { false }
private

Definition at line 127 of file LV2Wrapper.h.

Referenced by Activate(), and Deactivate().

◆ mFeaturesList

LV2WrapperFeaturesList LV2Wrapper::mFeaturesList
private

Definition at line 101 of file LV2Wrapper.h.

Referenced by SendBlockSize().

◆ mFreeWheeling

bool LV2Wrapper::mFreeWheeling { false }
private

If true, do not spawn extra worker threads.

Definition at line 122 of file LV2Wrapper.h.

Referenced by ScheduleWork(), and SetFreeWheeling().

◆ mHandle

const LV2_Handle LV2Wrapper::mHandle
private

◆ mInstance

const LilvInstancePtr LV2Wrapper::mInstance
private
Invariant
not null

Definition at line 104 of file LV2Wrapper.h.

Referenced by GetInstance(), and ~LV2Wrapper().

◆ mLatency

float LV2Wrapper::mLatency { 0.0 }
private

Definition at line 119 of file LV2Wrapper.h.

Referenced by ConnectControlPorts(), and GetLatency().

◆ mOptionsInterface

const LV2_Options_Interface* const LV2Wrapper::mOptionsInterface
private

Definition at line 110 of file LV2Wrapper.h.

Referenced by SendBlockSize().

◆ mRequests

wxMessageQueue<LV2Work> LV2Wrapper::mRequests
private

Definition at line 117 of file LV2Wrapper.h.

Referenced by ScheduleWork(), ThreadFunction(), and ~LV2Wrapper().

◆ mResponses

wxMessageQueue<LV2Work> LV2Wrapper::mResponses
private

Definition at line 118 of file LV2Wrapper.h.

Referenced by ConsumeResponses(), and Respond().

◆ mStateInterface

const LV2_State_Interface* const LV2Wrapper::mStateInterface
private

Definition at line 112 of file LV2Wrapper.h.

◆ mStopWorker

bool LV2Wrapper::mStopWorker { false }
private

Written by main thread, read by worker, but atomic isn't needed because mRequests provides synchronization

Definition at line 126 of file LV2Wrapper.h.

Referenced by ThreadFunction(), and ~LV2Wrapper().

◆ mThread

std::thread LV2Wrapper::mThread
private

Definition at line 116 of file LV2Wrapper.h.

Referenced by ~LV2Wrapper().

◆ mWorkerInterface

const LV2_Worker_Interface* const LV2Wrapper::mWorkerInterface
private

Definition at line 114 of file LV2Wrapper.h.

Referenced by ConsumeResponses(), ScheduleWork(), and ThreadFunction().

◆ mWorkerSchedule

LV2_Worker_Schedule LV2Wrapper::mWorkerSchedule { this, LV2Wrapper::schedule_work }
private

Definition at line 99 of file LV2Wrapper.h.


The documentation for this class was generated from the following files: