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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2165 - (hide annotations) (download)
Sun Feb 20 14:20:22 2011 UTC (13 years, 2 months 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 persson 1777 /***************************************************************************
2     * *
3 persson 2165 * Copyright (C) 2008 - 2011 Andreas Persson *
4 persson 1777 * *
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 persson 1908 #ifndef CHANNELS
32 persson 1917 #define CHANNELS 32
33 persson 1908 #endif
34    
35 persson 1777 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 persson 2165 FILE* f = fopen((String(getenv("TEMP")) + "\\linuxsamplervst.log").c_str(), "a");
47 persson 1777 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 persson 1895 #ifdef WIN32
74     ProcessHandle = INVALID_HANDLE_VALUE;
75     #endif
76 persson 1777 }
77    
78 persson 1895 LinuxSamplerEditor::~LinuxSamplerEditor() {
79     close();
80     }
81    
82 persson 1777 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 persson 1908 // 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 persson 1777
100 schoenebeck 1928 // assume Fantasia is in the same directory or one directory above
101     // the liblinuxsampler dll
102 persson 1897 String lspath = LinuxSampler::Sampler::GetInstallDir();
103     if (!lspath.empty()) {
104     lspath += "\\";
105 persson 1777 WIN32_FIND_DATA fd;
106     HANDLE hFind = FindFirstFile((lspath + "Fantasia*.jar").c_str(), &fd);
107 schoenebeck 1928 if (hFind == INVALID_HANDLE_VALUE) {
108     lspath += "..\\";
109     hFind = FindFirstFile((lspath + "Fantasia*.jar").c_str(), &fd);
110     }
111 persson 1777 if (hFind != INVALID_HANDLE_VALUE) {
112     String fantasia(fd.cFileName);
113     FindClose(hFind);
114    
115     // start a java process
116 persson 2165 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 persson 1777
124 persson 2165 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 persson 1777 }
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 persson 1908 CloseHandle(ProcessHandle);
161 persson 1895 ProcessHandle = INVALID_HANDLE_VALUE;
162 persson 1777 }
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 persson 1908 setNumOutputs(CHANNELS);
190 persson 1777 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 persson 1908 Init(int(sampleRate), blockSize, CHANNELS);
205 persson 1777
206 persson 1895 if (!SavedChunk.empty()) {
207 persson 1777 SetState(SavedChunk);
208 persson 1895 SavedChunk.clear();
209 persson 1777 } else {
210     InitState();
211     }
212 persson 1895 } else {
213 persson 2045 Init(int(sampleRate), blockSize, CHANNELS);
214 persson 1777 }
215 senoner 1942 AudioEffectX::resume();
216 persson 1777 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 persson 1908 if (index < CHANNELS) {
247 persson 1777 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 persson 1908 for (int i = 0 ; i < CHANNELS ; i++) {
310     pAudioDevice->Channel(i)->SetBuffer(outputs[i]);
311     }
312 persson 1777 pAudioDevice->Render(sampleFrames);
313     } else {
314 persson 1908 for (int i = 0 ; i < CHANNELS ; i++) {
315     memset(outputs[i], 0, sampleFrames * sizeof(float));
316     }
317 persson 1777 }
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