-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathvstnode.h
197 lines (139 loc) · 5.79 KB
/
vstnode.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
#pragma once
#include "node.h"
#include "nodewindow.h"
#include "vstmodule.h"
#include "mididevice.hh"
#include "en.h"
#include <QtCore>
// TODO: change this so that the vst module instantiates this node?
namespace En
{
class VstNode : public Node
{
Q_OBJECT
AEffect* m_vstInstance;
QMutex m_eventQueueMutex;
QVector<VstEvent*> m_eventQueue[2];// 'double buffered' to mitigate lock contention.
int m_eventQueueWriteIndex; // 0 or 1 depending on which of m_eventQueue is for writing.
Node* m_input;
QString m_productName;
NodeWindow* m_editorWindow; // move this to Node eventually
public:
class Factory : public Node::Factory
{
QString m_vstName;
public:
Factory(const QString& vstName) : m_vstName(vstName) {}
virtual Node* create(Host*);
};
VstNode(Host* /*host*/, VstModule* vstModule) :
m_vstInstance(vstModule->createVstInstance()),
m_eventQueueWriteIndex(0),
m_input(0),
m_editorWindow(0)
{
//this->setParent(vstModule); // hm, this causes a crash on the VstModule QObject children cleanup.
qDebug() << "opening instance";
m_vstInstance->dispatcher (m_vstInstance, effOpen, 0, 0, 0, 0);
qDebug() << "getting product string";
int ret = 0;
char charBuffer[64] = {0};
ret = m_vstInstance->dispatcher (m_vstInstance, effGetProductString, 0, 0, &charBuffer, 0);
if (ret) {
m_productName = QString(charBuffer);
} else {
m_productName = tr("Untitled");
}
qDebug() << "vst product string is" << m_productName;
VstPinProperties pinProps;
qDebug() << "output props";
int pin;
const int maxPins = 128;
for (pin = 0; pin < maxPins; ++pin) {
int ret = m_vstInstance->dispatcher (m_vstInstance, effGetInputProperties, pin, 0, &pinProps, 0);
if (ret == 1) {
qDebug() << "Input pin" << pin << pinProps.label << pinProps.flags;
m_inputChannelData << ChannelData(pinProps.label, blockSize());
} else {
break;
}
}
for (pin = 0; pin < maxPins; ++pin) {
int ret = m_vstInstance->dispatcher (m_vstInstance, effGetOutputProperties, pin, 0, &pinProps, 0);
if (ret == 1) {
qDebug() << "Output pin" << pin << pinProps.label << pinProps.flags;
m_outputChannelData << ChannelData(pinProps.label, blockSize());
} else {
break;
}
}
// the AEffect::numInputs / numOutputs fields are the final word on IO config. Make sure we're set up right,
// even if the effGetOutputProperties opcode lied to us.
if (m_vstInstance->numInputs != numInputChannels() || m_vstInstance->numOutputs != numOutputChannels()) {
if (numInputChannels() != 0 || numOutputChannels() != 0) {
qDebug() << "WARNING: plugins input/output properties don't match actual number of inputs/outputs!";
}
m_inputChannelData.clear();
for (int c = 0; c < m_vstInstance->numInputs; ++c) {
m_inputChannelData << ChannelData(QString("In %2").arg(QString::number(c)), blockSize());
}
m_outputChannelData.clear();
for (int c = 0; c < m_vstInstance->numOutputs; ++c) {
m_outputChannelData << ChannelData(QString("Out %2").arg(QString::number(c)), blockSize());
}
}
qDebug() << "inputs:" << numInputChannels();
qDebug() << "outputs:" << numOutputChannels();
// VstSpeakerArrangement inputSpeakerArr = {kSpeakerArrStereo, 2};
// VstSpeakerArrangement outputSpeakerArr = {kSpeakerArrStereo, 2};
// VstSpeakerArrangement *in = 0, *out = 0;
// qDebug() << "Setting speaker arrangements and shit";
// int ret = m_vstInstance->dispatcher (m_vstInstance, effGetSpeakerArrangement, 0, (VstIntPtr)&in, &out, 0);
// if (in) {
// qDebug() << "initial speaker arrangement: ret" << ret << "inputs" << in->numChannels << "outputs" << out->numChannels;
// }
// ret = m_vstInstance->dispatcher (m_vstInstance, effSetSpeakerArrangement, 0, (VstIntPtr)&inputSpeakerArr, &outputSpeakerArr, 0);
// ret = m_vstInstance->dispatcher (m_vstInstance, effGetSpeakerArrangement, 0, (VstIntPtr)&in, &out, 0);
// if (in) {
// qDebug() << "new speaker arrangement: ret" << ret << "inputs" << in->numChannels << "outputs" << out->numChannels;
// }
qDebug() << "setSampleRate";
m_vstInstance->dispatcher (m_vstInstance, effSetSampleRate, 0, 0, 0, 44100);
qDebug() << "setBlockSize";
m_vstInstance->dispatcher (m_vstInstance, effSetBlockSize, 0, blockSize(), 0, 0);
qDebug() << "mainsChanged";
m_vstInstance->dispatcher (m_vstInstance, effMainsChanged, 0, 1, 0, 0);
}
AEffect* vstInstance() const {
return m_vstInstance;
}
virtual ~VstNode();
const QString& productName() const {
return m_productName;
}
virtual QString displayLabel() const {
return tr("%1 (VST)").arg(productName());
}
virtual void accept(Visitor& visitor) {
visitor.visit(this);
}
void queueEvent(VstEvent* event) {
QMutexLocker locker(&m_eventQueueMutex);
Q_UNUSED(locker);
m_eventQueue[m_eventQueueWriteIndex].push_back(event);
}
void queueMidiEvent(const QByteArray &midiEvent);
void processAudio();
void setInput(Node* node);
Node* input() const {
return m_input;
}
QList<Node*> inputs() const {
QList<Node*> ret;
ret << m_input;
return ret;
}
void removeInput(Node* node);
virtual void openEditorWindow();
};
}