/[svn]/linuxsampler/trunk/src/hostplugins/vst/PluginVst.cpp
ViewVC logotype

Contents of /linuxsampler/trunk/src/hostplugins/vst/PluginVst.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1895 - (show annotations) (download)
Sun May 3 12:15:40 2009 UTC (10 years, 5 months ago) by persson
File size: 10218 byte(s)
* fixes for using large audio device buffers
* VST: added support for sample rate and buffer size changes
* VST: close editor (Fantasia) when the VST is removed
* minor fix in configure for mmsystem.h detection on MinGW
* removed warnings from gcc 4.4 and valgrind

1 /***************************************************************************
2 * *
3 * Copyright (C) 2008 Andreas Persson *
4 * *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
9 * *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
14 * *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the Free Software *
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, *
18 * MA 02110-1301 USA *
19 ***************************************************************************/
20
21 #include <cstdio>
22 #include <cstdlib>
23 #include <cstring>
24
25 #ifdef WIN32
26 #include <tchar.h>
27 #endif
28
29 #include "PluginVst.h"
30
31 namespace {
32
33 #if defined(WIN32) && CONFIG_DEBUG_LEVEL >= 2
34 // on windows, send debug logging to a file instead of a non-existent
35 // console
36 #include <cstdarg>
37 #include "../../common/Mutex.h"
38 LinuxSampler::Mutex logmutex;
39
40 void log(const char* fmt, ...) {
41 logmutex.Lock();
42 FILE* f = fopen("C:\\linuxsamplervst.log", "a");
43 va_list ap;
44 va_start(ap, fmt);
45 vfprintf(f, fmt, ap);
46 va_end(ap);
47 fclose(f);
48 logmutex.Unlock();
49 }
50 #undef dmsg
51 #define dmsg(debuglevel,x) log x;
52 #endif
53
54
55 // *************** LinuxSamplerVstProgram ***************
56 // *
57
58 LinuxSamplerVstProgram::LinuxSamplerVstProgram() {
59 vst_strncpy(name, "Basic", kVstMaxProgNameLen);
60 }
61
62
63 // *************** LinuxSamplerEditor ***************
64 // *
65
66 LinuxSamplerEditor::LinuxSamplerEditor(AudioEffect* effect) :
67 AEffEditor(effect) {
68 dmsg(2, ("-->LinuxSamplerEditor constructor\n"));
69 #ifdef WIN32
70 ProcessHandle = INVALID_HANDLE_VALUE;
71 #endif
72 }
73
74 LinuxSamplerEditor::~LinuxSamplerEditor() {
75 close();
76 }
77
78 bool LinuxSamplerEditor::open(void* ptr) {
79 dmsg(2, ("-->LinuxSamplerEditor::open\n"));
80 AEffEditor::open(ptr);
81
82 #ifdef WIN32
83 // try to start the JSample Fantasia GUI as a separate process
84
85 ProcessHandle = INVALID_HANDLE_VALUE;
86
87 // look for a Fantasia jar file in %programfiles%\LinuxSampler
88 if (const char* programfiles = getenv("PROGRAMFILES")) {
89 String lspath = String(programfiles) + "\\LinuxSampler\\";
90 WIN32_FIND_DATA fd;
91 HANDLE hFind = FindFirstFile((lspath + "Fantasia*.jar").c_str(), &fd);
92 if (hFind != INVALID_HANDLE_VALUE) {
93 String fantasia(fd.cFileName);
94 FindClose(hFind);
95
96 // start a java process
97 STARTUPINFO si;
98 PROCESS_INFORMATION pi;
99 ZeroMemory(&si, sizeof(si));
100 si.cb = sizeof(si);
101 ZeroMemory(&pi, sizeof(pi));
102
103 Command = _tcsdup(TEXT((String("javaw -jar \"") + lspath + fantasia + "\" &").c_str()));
104 CreateProcess(NULL, Command, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
105 ProcessHandle = pi.hProcess;
106 }
107 }
108 #endif
109 dmsg(2, ("<--LinuxSamplerEditor::open\n"));
110 return true;
111 }
112
113 void LinuxSamplerEditor::close() {
114 systemWindow = 0;
115 #ifdef WIN32
116 if (ProcessHandle != INVALID_HANDLE_VALUE) {
117 TerminateProcess(ProcessHandle, 0);
118 free(Command);
119 ProcessHandle = INVALID_HANDLE_VALUE;
120 }
121 #endif
122 }
123
124 bool LinuxSamplerEditor::getRect(ERect** rect) {
125 ERect* r = new ERect();
126 r->top = 0;
127 r->left = 0;
128 r->bottom = 0;
129 r->right = 400;
130 *rect = r;
131 return true;
132 }
133
134
135 // *************** LinuxSamplerVst ***************
136 // *
137
138 LinuxSamplerVst::LinuxSamplerVst(audioMasterCallback audioMaster) :
139 AudioEffectX(audioMaster, NbPrograms, 0),
140 StateBuf(0)
141 {
142 dmsg(2, ("-->constructor\n"));
143
144 Programs = new LinuxSamplerVstProgram[NbPrograms];
145 setProgram(0);
146 setNumInputs(0);
147 setNumOutputs(2);
148 canProcessReplacing();
149 isSynth();
150 programsAreChunks();
151 setUniqueID(CCONST('L', 'S', 'm', 'p')); // (registred at Steinberg)
152 setEditor(new LinuxSamplerEditor(this));
153
154 suspend();
155 dmsg(2, ("<--constructor\n"));
156 }
157
158
159 void LinuxSamplerVst::resume() {
160 dmsg(2, ("-->resume\n"));
161 if (!pAudioDevice) {
162 Init(int(sampleRate), blockSize);
163
164 if (!SavedChunk.empty()) {
165 SetState(SavedChunk);
166 SavedChunk.clear();
167 } else {
168 InitState();
169 }
170 } else {
171 Init(int(sampleRate), blockSize);
172 }
173 dmsg(2, ("<--resume\n"));
174 }
175
176 LinuxSamplerVst::~LinuxSamplerVst() {
177 dmsg(2, ("-->destructor\n"));
178 delete[] Programs;
179 if (StateBuf) free(StateBuf);
180 dmsg(2, ("<--destructor\n"));
181 }
182
183
184 void LinuxSamplerVst::setProgram(VstInt32 program) {
185 if (program < 0 || program >= NbPrograms) return;
186
187 curProgram = program;
188 }
189
190
191 void LinuxSamplerVst::setProgramName(char* name) {
192 vst_strncpy(Programs[curProgram].name, name, kVstMaxProgNameLen);
193 }
194
195
196 void LinuxSamplerVst::getProgramName(char* name) {
197 vst_strncpy(name, Programs[curProgram].name, kVstMaxProgNameLen);
198 }
199
200
201 bool LinuxSamplerVst::getOutputProperties(VstInt32 index,
202 VstPinProperties* properties) {
203 if (index < 2) {
204 sprintf(properties->label, "LS %d", index + 1);
205 properties->flags = kVstPinIsActive | kVstPinIsStereo;
206 return true;
207 }
208 return false;
209 }
210
211
212 bool LinuxSamplerVst::getProgramNameIndexed(VstInt32 category, VstInt32 index,
213 char* text) {
214 if (index < NbPrograms) {
215 vst_strncpy(text, Programs[index].name, kVstMaxProgNameLen);
216 return true;
217 }
218 return false;
219 }
220
221
222 bool LinuxSamplerVst::getEffectName(char* name) {
223 vst_strncpy(name, "LinuxSampler", kVstMaxEffectNameLen);
224 return true;
225 }
226
227
228 bool LinuxSamplerVst::getVendorString(char* text) {
229 vst_strncpy(text, "linuxsampler.org", kVstMaxVendorStrLen);
230 return true;
231 }
232
233
234 bool LinuxSamplerVst::getProductString(char* text) {
235 vst_strncpy(text, "LinuxSampler VST", kVstMaxProductStrLen);
236 return true;
237 }
238
239
240 VstInt32 LinuxSamplerVst::getVendorVersion() {
241 return 1000;
242 }
243
244
245 VstInt32 LinuxSamplerVst::canDo(char* text) {
246 dmsg(2, ("canDo %s\n", text));
247 if (strcmp(text, "receiveVstEvents") == 0 ||
248 strcmp(text, "receiveVstMidiEvent") == 0) return 1;
249 return -1;
250 }
251
252 void LinuxSamplerVst::setSampleRate(float sampleRate) {
253 dmsg(2, ("linuxsampler: setSampleRate %f\n", sampleRate));
254 AudioEffectX::setSampleRate(sampleRate);
255 }
256
257 void LinuxSamplerVst::setBlockSize(VstInt32 blockSize) {
258 dmsg(2, ("linuxsampler: setBlockSize %d\n", blockSize));
259 AudioEffectX::setBlockSize(blockSize);
260 }
261
262
263 void LinuxSamplerVst::processReplacing(float** inputs, float** outputs,
264 VstInt32 sampleFrames) {
265 if (pAudioDevice) {
266 pAudioDevice->Channel(0)->SetBuffer(outputs[0]);
267 pAudioDevice->Channel(1)->SetBuffer(outputs[1]);
268 pAudioDevice->Render(sampleFrames);
269 } else {
270 memset(outputs[0], 0, sampleFrames * sizeof(float));
271 memset(outputs[1], 0, sampleFrames * sizeof(float));
272 }
273 }
274
275
276 VstInt32 LinuxSamplerVst::processEvents(VstEvents* ev) {
277 if (pMidiDevice) {
278 for (int i = 0; i < ev->numEvents; i++)
279 {
280 if (ev->events[i]->type == kVstMidiType) {
281 VstMidiEvent* event = reinterpret_cast<VstMidiEvent*>(ev->events[i]);
282 pMidiDevice->Port()->DispatchRaw(reinterpret_cast<uint8_t*>(event->midiData),
283 event->deltaFrames);
284 }
285 }
286 }
287 return 1;
288 }
289
290
291 VstInt32 LinuxSamplerVst::getChunk(void** data, bool isPreset) {
292 dmsg(2, ("-->getChunk\n"));
293
294 String state = GetState();
295 dmsg(2, ("state=\"%s\"\n", state.c_str()));;
296 if (StateBuf) free(StateBuf);
297 StateBuf = strdup(state.c_str());
298 *data = StateBuf;
299 dmsg(2, ("<--getChunk\n"));
300 return state.length() + 1;
301 }
302
303
304 VstInt32 LinuxSamplerVst::setChunk(void* data, VstInt32 byteSize,
305 bool isPreset) {
306 dmsg(2, ("-->setChunk byteSize=%d isPreset=%d\n", byteSize, isPreset));
307
308 const char* state = static_cast<const char*>(data);
309 VstInt32 res = 0;
310 if (byteSize > 0 && state[byteSize - 1] == '\0') {
311 dmsg(2, ("state=\"%s\"\n", state));
312 if (pAudioDevice) {
313 res = SetState(state);
314 } else {
315 SavedChunk = state;
316 }
317 }
318 dmsg(2, ("<--setChunk\n"));
319 return res;
320 }
321 }
322
323
324 // *************** VST main function ***************
325 // *
326
327 AudioEffect* createEffectInstance(audioMasterCallback audioMaster)
328 {
329 return new LinuxSamplerVst(audioMaster);
330 }

  ViewVC Help
Powered by ViewVC