/[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 2165 - (show annotations) (download)
Sun Feb 20 14:20:22 2011 UTC (13 years, 1 month ago) by persson
File size: 11983 byte(s)
* bugfix: calling SET VOICES (which Fantasia does on start and
  refresh) could cause instruments to be unloaded
* plugins: save engine type (gig, sfz or sf2) in plugin state
* VST: when opening Fantasia, look for both 32 and 64 bit Java on
  64 bit Windows

1 /***************************************************************************
2 * *
3 * Copyright (C) 2008 - 2011 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 #ifndef CHANNELS
32 #define CHANNELS 32
33 #endif
34
35 namespace {
36
37 #if defined(WIN32) && CONFIG_DEBUG_LEVEL >= 2
38 // on windows, send debug logging to a file instead of a non-existent
39 // console
40 #include <cstdarg>
41 #include "../../common/Mutex.h"
42 LinuxSampler::Mutex logmutex;
43
44 void log(const char* fmt, ...) {
45 logmutex.Lock();
46 FILE* f = fopen((String(getenv("TEMP")) + "\\linuxsamplervst.log").c_str(), "a");
47 va_list ap;
48 va_start(ap, fmt);
49 vfprintf(f, fmt, ap);
50 va_end(ap);
51 fclose(f);
52 logmutex.Unlock();
53 }
54 #undef dmsg
55 #define dmsg(debuglevel,x) log x;
56 #endif
57
58
59 // *************** LinuxSamplerVstProgram ***************
60 // *
61
62 LinuxSamplerVstProgram::LinuxSamplerVstProgram() {
63 vst_strncpy(name, "Basic", kVstMaxProgNameLen);
64 }
65
66
67 // *************** LinuxSamplerEditor ***************
68 // *
69
70 LinuxSamplerEditor::LinuxSamplerEditor(AudioEffect* effect) :
71 AEffEditor(effect) {
72 dmsg(2, ("-->LinuxSamplerEditor constructor\n"));
73 #ifdef WIN32
74 ProcessHandle = INVALID_HANDLE_VALUE;
75 #endif
76 }
77
78 LinuxSamplerEditor::~LinuxSamplerEditor() {
79 close();
80 }
81
82 bool LinuxSamplerEditor::open(void* ptr) {
83 dmsg(2, ("-->LinuxSamplerEditor::open\n"));
84 AEffEditor::open(ptr);
85
86 #ifdef WIN32
87 // try to start the JSample Fantasia GUI as a separate process
88
89 // first check if it's already running
90 if (ProcessHandle != INVALID_HANDLE_VALUE) {
91 DWORD exitCode;
92 if (GetExitCodeProcess(ProcessHandle, &exitCode)) {
93 if (exitCode == STILL_ACTIVE) return true;
94 }
95 free(Command);
96 CloseHandle(ProcessHandle);
97 ProcessHandle = INVALID_HANDLE_VALUE;
98 }
99
100 // assume Fantasia is in the same directory or one directory above
101 // the liblinuxsampler dll
102 String lspath = LinuxSampler::Sampler::GetInstallDir();
103 if (!lspath.empty()) {
104 lspath += "\\";
105 WIN32_FIND_DATA fd;
106 HANDLE hFind = FindFirstFile((lspath + "Fantasia*.jar").c_str(), &fd);
107 if (hFind == INVALID_HANDLE_VALUE) {
108 lspath += "..\\";
109 hFind = FindFirstFile((lspath + "Fantasia*.jar").c_str(), &fd);
110 }
111 if (hFind != INVALID_HANDLE_VALUE) {
112 String fantasia(fd.cFileName);
113 FindClose(hFind);
114
115 // start a java process
116 String path; // look in PATH first
117 for (int i = 0 ; i < 2 ; i++) { // two tries
118 STARTUPINFO si;
119 PROCESS_INFORMATION pi;
120 ZeroMemory(&si, sizeof(si));
121 si.cb = sizeof(si);
122 ZeroMemory(&pi, sizeof(pi));
123
124 Command = _tcsdup(TEXT((String("\"") + path + "javaw\" -jar \"" +
125 lspath + fantasia + "\"").c_str()));
126 if (CreateProcess(NULL, Command, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) {
127 ProcessHandle = pi.hProcess;
128 CloseHandle(pi.hThread);
129 break;
130 } else {
131 free(Command);
132 if (path.empty()) {
133 // java wasn't found in PATH, try again
134 // with an alternative directory
135 char* windir = getenv("windir");
136 if (!windir) break;
137 #ifdef _WIN64
138 // LS plugin is 64 bit - look for 32 bit java
139 path = String(windir) + "\\SysWOW64\\";
140 #else
141 // LS plugin is 32 bit - look for 64 bit java
142 path = String(windir) + "\\Sysnative\\";
143 #endif
144 }
145 }
146 }
147 }
148 }
149 #endif
150 dmsg(2, ("<--LinuxSamplerEditor::open\n"));
151 return true;
152 }
153
154 void LinuxSamplerEditor::close() {
155 systemWindow = 0;
156 #ifdef WIN32
157 if (ProcessHandle != INVALID_HANDLE_VALUE) {
158 TerminateProcess(ProcessHandle, 0);
159 free(Command);
160 CloseHandle(ProcessHandle);
161 ProcessHandle = INVALID_HANDLE_VALUE;
162 }
163 #endif
164 }
165
166 bool LinuxSamplerEditor::getRect(ERect** rect) {
167 ERect* r = new ERect();
168 r->top = 0;
169 r->left = 0;
170 r->bottom = 0;
171 r->right = 400;
172 *rect = r;
173 return true;
174 }
175
176
177 // *************** LinuxSamplerVst ***************
178 // *
179
180 LinuxSamplerVst::LinuxSamplerVst(audioMasterCallback audioMaster) :
181 AudioEffectX(audioMaster, NbPrograms, 0),
182 StateBuf(0)
183 {
184 dmsg(2, ("-->constructor\n"));
185
186 Programs = new LinuxSamplerVstProgram[NbPrograms];
187 setProgram(0);
188 setNumInputs(0);
189 setNumOutputs(CHANNELS);
190 canProcessReplacing();
191 isSynth();
192 programsAreChunks();
193 setUniqueID(CCONST('L', 'S', 'm', 'p')); // (registred at Steinberg)
194 setEditor(new LinuxSamplerEditor(this));
195
196 suspend();
197 dmsg(2, ("<--constructor\n"));
198 }
199
200
201 void LinuxSamplerVst::resume() {
202 dmsg(2, ("-->resume\n"));
203 if (!pAudioDevice) {
204 Init(int(sampleRate), blockSize, CHANNELS);
205
206 if (!SavedChunk.empty()) {
207 SetState(SavedChunk);
208 SavedChunk.clear();
209 } else {
210 InitState();
211 }
212 } else {
213 Init(int(sampleRate), blockSize, CHANNELS);
214 }
215 AudioEffectX::resume();
216 dmsg(2, ("<--resume\n"));
217 }
218
219 LinuxSamplerVst::~LinuxSamplerVst() {
220 dmsg(2, ("-->destructor\n"));
221 delete[] Programs;
222 if (StateBuf) free(StateBuf);
223 dmsg(2, ("<--destructor\n"));
224 }
225
226
227 void LinuxSamplerVst::setProgram(VstInt32 program) {
228 if (program < 0 || program >= NbPrograms) return;
229
230 curProgram = program;
231 }
232
233
234 void LinuxSamplerVst::setProgramName(char* name) {
235 vst_strncpy(Programs[curProgram].name, name, kVstMaxProgNameLen);
236 }
237
238
239 void LinuxSamplerVst::getProgramName(char* name) {
240 vst_strncpy(name, Programs[curProgram].name, kVstMaxProgNameLen);
241 }
242
243
244 bool LinuxSamplerVst::getOutputProperties(VstInt32 index,
245 VstPinProperties* properties) {
246 if (index < CHANNELS) {
247 sprintf(properties->label, "LS %d", index + 1);
248 properties->flags = kVstPinIsActive | kVstPinIsStereo;
249 return true;
250 }
251 return false;
252 }
253
254
255 bool LinuxSamplerVst::getProgramNameIndexed(VstInt32 category, VstInt32 index,
256 char* text) {
257 if (index < NbPrograms) {
258 vst_strncpy(text, Programs[index].name, kVstMaxProgNameLen);
259 return true;
260 }
261 return false;
262 }
263
264
265 bool LinuxSamplerVst::getEffectName(char* name) {
266 vst_strncpy(name, "LinuxSampler", kVstMaxEffectNameLen);
267 return true;
268 }
269
270
271 bool LinuxSamplerVst::getVendorString(char* text) {
272 vst_strncpy(text, "linuxsampler.org", kVstMaxVendorStrLen);
273 return true;
274 }
275
276
277 bool LinuxSamplerVst::getProductString(char* text) {
278 vst_strncpy(text, "LinuxSampler VST", kVstMaxProductStrLen);
279 return true;
280 }
281
282
283 VstInt32 LinuxSamplerVst::getVendorVersion() {
284 return 1000;
285 }
286
287
288 VstInt32 LinuxSamplerVst::canDo(char* text) {
289 dmsg(2, ("canDo %s\n", text));
290 if (strcmp(text, "receiveVstEvents") == 0 ||
291 strcmp(text, "receiveVstMidiEvent") == 0) return 1;
292 return -1;
293 }
294
295 void LinuxSamplerVst::setSampleRate(float sampleRate) {
296 dmsg(2, ("linuxsampler: setSampleRate %f\n", sampleRate));
297 AudioEffectX::setSampleRate(sampleRate);
298 }
299
300 void LinuxSamplerVst::setBlockSize(VstInt32 blockSize) {
301 dmsg(2, ("linuxsampler: setBlockSize %d\n", blockSize));
302 AudioEffectX::setBlockSize(blockSize);
303 }
304
305
306 void LinuxSamplerVst::processReplacing(float** inputs, float** outputs,
307 VstInt32 sampleFrames) {
308 if (pAudioDevice) {
309 for (int i = 0 ; i < CHANNELS ; i++) {
310 pAudioDevice->Channel(i)->SetBuffer(outputs[i]);
311 }
312 pAudioDevice->Render(sampleFrames);
313 } else {
314 for (int i = 0 ; i < CHANNELS ; i++) {
315 memset(outputs[i], 0, sampleFrames * sizeof(float));
316 }
317 }
318 }
319
320
321 VstInt32 LinuxSamplerVst::processEvents(VstEvents* ev) {
322 if (pMidiDevice) {
323 for (int i = 0; i < ev->numEvents; i++)
324 {
325 if (ev->events[i]->type == kVstMidiType) {
326 VstMidiEvent* event = reinterpret_cast<VstMidiEvent*>(ev->events[i]);
327 pMidiDevice->Port()->DispatchRaw(reinterpret_cast<uint8_t*>(event->midiData),
328 event->deltaFrames);
329 }
330 }
331 }
332 return 1;
333 }
334
335
336 VstInt32 LinuxSamplerVst::getChunk(void** data, bool isPreset) {
337 dmsg(2, ("-->getChunk\n"));
338
339 String state = GetState();
340 dmsg(2, ("state=\"%s\"\n", state.c_str()));;
341 if (StateBuf) free(StateBuf);
342 StateBuf = strdup(state.c_str());
343 *data = StateBuf;
344 dmsg(2, ("<--getChunk\n"));
345 return state.length() + 1;
346 }
347
348
349 VstInt32 LinuxSamplerVst::setChunk(void* data, VstInt32 byteSize,
350 bool isPreset) {
351 dmsg(2, ("-->setChunk byteSize=%d isPreset=%d\n", byteSize, isPreset));
352
353 const char* state = static_cast<const char*>(data);
354 VstInt32 res = 0;
355 if (byteSize > 0 && state[byteSize - 1] == '\0') {
356 dmsg(2, ("state=\"%s\"\n", state));
357 if (pAudioDevice) {
358 res = SetState(state);
359 } else {
360 SavedChunk = state;
361 }
362 }
363 dmsg(2, ("<--setChunk\n"));
364 return res;
365 }
366 }
367
368
369 // *************** VST main function ***************
370 // *
371
372 AudioEffect* createEffectInstance(audioMasterCallback audioMaster)
373 {
374 return new LinuxSamplerVst(audioMaster);
375 }

  ViewVC Help
Powered by ViewVC