Audacity 3.2.0
ComponentHandler.cpp
Go to the documentation of this file.
1/**********************************************************************
2
3 Audacity: A Digital Audio Editor
4
5 @file ComponentHandler.cpp
6
7 @author Vitaly Sverchinsky
8
9 @brief Part of Audacity VST3 module
10
11**********************************************************************/
12
13#include "ComponentHandler.h"
14
15#include <pluginterfaces/vst/ivstparameterchanges.h>
16
17#include "ParameterChanges.h"
18
20{
21 //We use two instances of ParameterChanges to ensure
22 //that read/write is lock and wait free.
23 //Once parameter value change is requested, they are
24 //written either to the pending outgoing parameters,
25 //if they are not yet requested, or to any of those
26 //two instances whichever of them is available.
27 //When done writing, parameter changes become pending.
28
29 using namespace Steinberg;
30
31 FUNKNOWN_CTOR
32 auto first = owned(safenew internal::ParameterChanges);
33 auto second = owned(safenew internal::ParameterChanges);
34 if(first && second)
35 {
36 mFirst = first.take();
37 mSecond = second.take();
38 }
39}
40
42{
43 Steinberg::Vst::IParameterChanges* ptr { nullptr };
44 if(ptr = mFirst.load())
45 ptr->release();
46 if(ptr = mSecond.load())
47 ptr->release();
48 if(ptr = mPendingChanges.load())
49 ptr->release();
50
51 FUNKNOWN_DTOR;
52}
53
54Steinberg::tresult internal::ComponentHandler::beginEdit(Steinberg::Vst::ParamID)
55{
56 return Steinberg::kResultOk;
57}
58
59Steinberg::tresult internal::ComponentHandler::performEdit(Steinberg::Vst::ParamID id,
60 Steinberg::Vst::ParamValue valueNormalized)
61{
62 using namespace Steinberg;
63
64 //Try grab pending changes first (processing thread will not
65 //see them until they are applied)
66 auto lock = mPendingChanges.exchange(nullptr);
67 if(lock == nullptr)
68 {
69 //There is no pending changes, then try grab
70 //any of the containers. At least one of them always should be
71 //available, but another one may be grabbed by the processing thread
72 lock = mFirst.exchange(nullptr);
73 if(lock == nullptr)
74 lock = mSecond.exchange(nullptr);
75
76 //Grabbed object may contain some old data, clean it.
77 //We surely don't want to delay the processing thread with cleanup
78 //routines
79 static_cast<ParameterChanges*>(lock)->clear();
80 }
81
82 int32 index;
83 tresult result = kInternalError;
84
85 if(const auto queue = lock->addParameterData(id, index))
86 //Since we don't yet have a support for automation,
87 //sampleOffset is always 0
88 result = queue->addPoint(0, valueNormalized, index);
89 //else
90 // for some unknown reason we have failed to
91 // find/create appropriate queue for this parameter
92
93 //now processing thread can see changes
94 mPendingChanges.exchange(lock);
95
96 return result;
97}
98
99Steinberg::tresult internal::ComponentHandler::endEdit(Steinberg::Vst::ParamID)
100{
101 return Steinberg::kResultOk;
102}
103
104Steinberg::tresult internal::ComponentHandler::restartComponent(Steinberg::int32 flags)
105{
106 return Steinberg::kNotImplemented;
107}
108
110{
111 using namespace Steinberg;
112
113 const auto pendingChanges = mPendingChanges.exchange(nullptr);
114 if(pendingChanges != nullptr)
115 {
116 return PendingChangesPtr { pendingChanges, [handler = IPtr { this }](Vst::IParameterChanges* ptr)
117 {
118 //once the processing thread done reading changes
119 //pointer is moved back
120 ptr = handler->mFirst.exchange(ptr);
121 if(ptr != nullptr)
122 handler->mSecond.exchange(ptr);
123 }};
124 }
125 return { nullptr };
126}
127
128IMPLEMENT_FUNKNOWN_METHODS(internal::ComponentHandler, Steinberg::Vst::IComponentHandler, Steinberg::Vst::IComponentHandler::iid)
IMPLEMENT_FUNKNOWN_METHODS(internal::ConnectionProxy, Steinberg::Vst::IConnectionPoint, Steinberg::Vst::IConnectionPoint::iid)
#define safenew
Definition: MemoryX.h:10
std::atomic< Steinberg::Vst::IParameterChanges * > mSecond
Steinberg::tresult PLUGIN_API performEdit(Steinberg::Vst::ParamID id, Steinberg::Vst::ParamValue valueNormalized) override
Steinberg::tresult PLUGIN_API beginEdit(Steinberg::Vst::ParamID id) override
Steinberg::tresult PLUGIN_API restartComponent(Steinberg::int32 flags) override
std::unique_ptr< Steinberg::Vst::IParameterChanges, std::function< void(Steinberg::Vst::IParameterChanges *)> > PendingChangesPtr
PendingChangesPtr getPendingChanges()
std::atomic< Steinberg::Vst::IParameterChanges * > mFirst
Steinberg::tresult PLUGIN_API endEdit(Steinberg::Vst::ParamID id) override