You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

694 lines
21KB

  1. #define USE_LGLW defined
  2. #include <aeffect.h>
  3. #include <aeffectx.h>
  4. #include <stdio.h>
  5. #if defined(_WIN32) || defined(_WIN64)
  6. #include <windows.h>
  7. #include <wingdi.h>
  8. #define VST_EXPORT extern "C" __declspec(dllexport)
  9. #else
  10. #include <GL/gl.h>
  11. #include <X11/Xlib.h>
  12. #include <X11/Xutil.h>
  13. #include <X11/Xos.h>
  14. #define VST_EXPORT extern
  15. #include <dlfcn.h>
  16. #endif
  17. #include "lglw.h"
  18. #define EDITWIN_X 20
  19. #define EDITWIN_Y 20
  20. #define EDITWIN_W 640
  21. #define EDITWIN_H 480
  22. /*
  23. * I find the naming a bit confusing so I decided to use more meaningful names instead.
  24. */
  25. /**
  26. * The VSTHostCallback is a function pointer so that the plugin can communicate with the host (not used in this small example)
  27. */
  28. typedef audioMasterCallback VSTHostCallback;
  29. /**
  30. * The VSTPlugin structure (AEffect) contains information about the plugin (like version, number of inputs, ...) and
  31. * callbacks so that the host can call the plugin to do its work. The primary callback will be `processReplacing` for
  32. * single precision (float) sample processing (or `processDoubleReplacing` for double precision (double)).
  33. */
  34. typedef AEffect VSTPlugin;
  35. // Since the host is expecting a very specific API we need to make sure it has C linkage (not C++)
  36. extern "C" {
  37. /*
  38. * This is the main entry point to the VST plugin.
  39. *
  40. * The host (DAW like Maschine, Ableton Live, Reason, ...) will look for this function with this exact API.
  41. *
  42. * It is the equivalent to `int main(int argc, char *argv[])` for a C executable.
  43. *
  44. * @param vstHostCallback is a callback so that the plugin can communicate with the host (not used in this small example)
  45. * @return a pointer to the AEffect structure
  46. */
  47. VST_EXPORT VSTPlugin *VSTPluginMain(VSTHostCallback vstHostCallback);
  48. // note this looks like this without the type aliases (and is obviously 100% equivalent)
  49. // extern AEffect *VSTPluginMain(audioMasterCallback audioMaster);
  50. }
  51. /*
  52. * Constant for the version of the plugin. For example 1100 for version 1.1.0.0
  53. */
  54. const VstInt32 PLUGIN_VERSION = 1000;
  55. // extern "C" LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
  56. #ifdef USE_LGLW
  57. extern "C" {
  58. static void loc_mouse_cbk(lglw_t _lglw, int32_t _x, int32_t _y, uint32_t _buttonState, uint32_t _changedButtonState) {
  59. printf("vstgltest: lglw_mouse_cbk: lglw=%p p=(%d; %d) bt=0x%08x changedBt=0x%08x\n", _lglw, _x, _y, _buttonState, _changedButtonState);
  60. if(LGLW_IS_MOUSE_LBUTTON_DOWN())
  61. {
  62. // lglw_mouse_grab(_lglw, LGLW_MOUSE_GRAB_CAPTURE);
  63. lglw_mouse_grab(_lglw, LGLW_MOUSE_GRAB_WARP);
  64. }
  65. else if(LGLW_IS_MOUSE_LBUTTON_UP())
  66. {
  67. lglw_mouse_ungrab(_lglw);
  68. }
  69. }
  70. static void loc_focus_cbk(lglw_t _lglw, uint32_t _focusState, uint32_t _changedFocusState) {
  71. printf("vstgltest: lglw_focus_cbk: lglw=%p focusState=0x%08x changedFocusState=0x%08x\n", _lglw, _focusState, _changedFocusState);
  72. }
  73. static lglw_bool_t loc_keyboard_cbk(lglw_t _lglw, uint32_t _vkey, uint32_t _kmod, lglw_bool_t _bPressed) {
  74. printf("vstgltest: lglw_keyboard_cbk: lglw=%p vkey=0x%08x (\'%c\') kmod=0x%08x bPressed=%d\n", _lglw, _vkey, _vkey, _kmod, _bPressed);
  75. return LGLW_FALSE;
  76. }
  77. static void loc_timer_cbk(lglw_t _lglw) {
  78. printf("vstgltest: lglw_timer_cbk: tick\n");
  79. lglw_redraw(_lglw);
  80. }
  81. static void loc_redraw_cbk (lglw_t _lglw);
  82. }
  83. #endif // USE_LGLW
  84. /**
  85. * Encapsulates the plugin as a C++ class. It will keep both the host callback and the structure required by the
  86. * host (VSTPlugin). This class will be stored in the `VSTPlugin.object` field (circular reference) so that it can
  87. * be accessed when the host calls the plugin back (for example in `processDoubleReplacing`).
  88. */
  89. class VSTPluginWrapper
  90. {
  91. public:
  92. ERect editor_rect;
  93. #ifdef USE_LGLW
  94. lglw_t lglw;
  95. #endif // USE_LGLW
  96. float clear_color = 0.0f;
  97. static VSTPluginWrapper *window_to_wrapper;
  98. public:
  99. VSTPluginWrapper(VSTHostCallback vstHostCallback,
  100. VstInt32 vendorUniqueID,
  101. VstInt32 vendorVersion,
  102. VstInt32 numParams,
  103. VstInt32 numPrograms,
  104. VstInt32 numInputs,
  105. VstInt32 numOutputs);
  106. ~VSTPluginWrapper();
  107. inline VSTPlugin *getVSTPlugin()
  108. {
  109. return &_vstPlugin;
  110. }
  111. inline VstInt32 getNumInputs() const
  112. {
  113. return _vstPlugin.numInputs;
  114. }
  115. inline VstInt32 getNumOutputs() const
  116. {
  117. return _vstPlugin.numOutputs;
  118. }
  119. int openEffect(void) {
  120. printf("vstgltest: openEffect()\n");
  121. return 1;
  122. }
  123. void closeEffect(void) {
  124. closeEditor();
  125. }
  126. void openEditor(void *_hwnd) {
  127. #ifdef USE_LGLW
  128. (void)lglw_window_open(lglw, _hwnd, 0/*x*/, 0/*y*/, EDITWIN_W, EDITWIN_H);
  129. lglw_mouse_callback_set(lglw, &loc_mouse_cbk);
  130. lglw_focus_callback_set(lglw, &loc_focus_cbk);
  131. lglw_keyboard_callback_set(lglw, &loc_keyboard_cbk);
  132. lglw_timer_callback_set(lglw, &loc_timer_cbk);
  133. lglw_redraw_callback_set(lglw, &loc_redraw_cbk);
  134. lglw_timer_start(lglw, 1000/30);
  135. #endif // USE_LGLW
  136. window_to_wrapper = this;
  137. }
  138. void closeEditor(void) {
  139. if(NULL != window_to_wrapper)
  140. {
  141. #ifdef USE_LGLW
  142. lglw_window_close(lglw);
  143. #endif // USE_LGLW
  144. window_to_wrapper = NULL;
  145. }
  146. }
  147. static VSTPluginWrapper *FindWrapperByWindow(Window hwnd) {
  148. return window_to_wrapper;
  149. }
  150. void redrawWindow(void) {
  151. #if 1
  152. #ifdef USE_LGLW
  153. printf("vstgltest: redrawWindow()\n");
  154. // Save host GL context
  155. lglw_glcontext_push(lglw);
  156. // Draw something
  157. ::glClearColor(0.0, 1.0, clear_color, 1.0);
  158. clear_color += 0.05f;
  159. if(clear_color >= 1.0f)
  160. clear_color -= 1.0f;
  161. ::glClear(GL_COLOR_BUFFER_BIT);
  162. ::glFlush();
  163. lglw_swap_buffers(lglw);
  164. // Restore host GL context
  165. lglw_glcontext_pop(lglw);
  166. #endif // USE_LGLW
  167. #endif
  168. }
  169. private:
  170. // the host callback (a function pointer)
  171. VSTHostCallback _vstHostCallback;
  172. // the actual structure required by the host
  173. VSTPlugin _vstPlugin;
  174. };
  175. VSTPluginWrapper *VSTPluginWrapper::window_to_wrapper = NULL;
  176. /*******************************************
  177. * Callbacks: Host -> Plugin
  178. *
  179. * Defined here because they are used in the rest of the code later
  180. */
  181. /**
  182. * This is the callback that will be called to process the samples in the case of single precision. This is where the
  183. * meat of the logic happens!
  184. *
  185. * @param vstPlugin the object returned by VSTPluginMain
  186. * @param inputs an array of array of input samples. You read from it. First dimension is for inputs, second dimension is for samples: inputs[numInputs][sampleFrames]
  187. * @param outputs an array of array of output samples. You write to it. First dimension is for outputs, second dimension is for samples: outputs[numOuputs][sampleFrames]
  188. * @param sampleFrames the number of samples (second dimension in both arrays)
  189. */
  190. extern "C" {
  191. void VSTPluginProcessSamplesFloat32(VSTPlugin *vstPlugin, float **inputs, float **outputs, VstInt32 sampleFrames)
  192. {
  193. // we can get a hold to our C++ class since we stored it in the `object` field (see constructor)
  194. VSTPluginWrapper *wrapper = static_cast<VSTPluginWrapper *>(vstPlugin->object);
  195. // code speaks for itself: for each input (2 when stereo input), iterating over every sample and writing the
  196. // result in the outputs array after multiplying by 0.5 (which result in a 3dB attenuation of the sound)
  197. for(int i = 0; i < wrapper->getNumInputs(); i++)
  198. {
  199. auto inputSamples = inputs[i];
  200. auto outputSamples = outputs[i];
  201. for(int j = 0; j < sampleFrames; j++)
  202. {
  203. outputSamples[j] = inputSamples[j] * 0.5f;
  204. }
  205. }
  206. }
  207. }
  208. /**
  209. * This is the callback that will be called to process the samples in the case of double precision. This is where the
  210. * meat of the logic happens!
  211. *
  212. * @param vstPlugin the object returned by VSTPluginMain
  213. * @param inputs an array of array of input samples. You read from it. First dimension is for inputs, second dimension is for samples: inputs[numInputs][sampleFrames]
  214. * @param outputs an array of array of output samples. You write to it. First dimension is for outputs, second dimension is for samples: outputs[numOuputs][sampleFrames]
  215. * @param sampleFrames the number of samples (second dimension in both arrays)
  216. */
  217. extern "C" {
  218. void VSTPluginProcessSamplesFloat64(VSTPlugin *vstPlugin, double **inputs, double **outputs, VstInt32 sampleFrames)
  219. {
  220. // we can get a hold to our C++ class since we stored it in the `object` field (see constructor)
  221. VSTPluginWrapper *wrapper = static_cast<VSTPluginWrapper *>(vstPlugin->object);
  222. // code speaks for itself: for each input (2 when stereo input), iterating over every sample and writing the
  223. // result in the outputs array after multiplying by 0.5 (which result in a 3dB attenuation of the sound)
  224. for(int i = 0; i < wrapper->getNumInputs(); i++)
  225. {
  226. auto inputSamples = inputs[i];
  227. auto outputSamples = outputs[i];
  228. for(int j = 0; j < sampleFrames; j++)
  229. {
  230. outputSamples[j] = inputSamples[j] * 0.5;
  231. }
  232. }
  233. }
  234. }
  235. /**
  236. * This is the plugin called by the host to communicate with the plugin, mainly to request information (like the
  237. * vendor string, the plugin category...) or communicate state/changes (like open/close, frame rate...)
  238. *
  239. * @param vstPlugin the object returned by VSTPluginMain
  240. * @param opCode defined in aeffect.h/AEffectOpcodes and which continues in aeffectx.h/AEffectXOpcodes for a grand
  241. * total of 79 of them! Only a few of them are implemented in this small plugin.
  242. * @param index depend on the opcode
  243. * @param value depend on the opcode
  244. * @param ptr depend on the opcode
  245. * @param opt depend on the opcode
  246. * @return depend on the opcode (0 is ok when you don't implement an opcode...)
  247. */
  248. extern "C" {
  249. VstIntPtr VSTPluginDispatcher(VSTPlugin *vstPlugin, VstInt32 opCode, VstInt32 index, VstIntPtr value, void *ptr, float opt)
  250. {
  251. // printf("vstgltest: called VSTPluginDispatcher(%d)\n", opCode);
  252. VstIntPtr r = 0;
  253. // we can get a hold to our C++ class since we stored it in the `object` field (see constructor)
  254. VSTPluginWrapper *wrapper = static_cast<VSTPluginWrapper *>(vstPlugin->object);
  255. // see aeffect.h/AEffectOpcodes and aeffectx.h/AEffectXOpcodes for details on all of them
  256. switch(opCode)
  257. {
  258. default:
  259. printf("vstgltest: unhandled VSTPluginDispatcher opcode=%d\n", opCode);
  260. break;
  261. case effGetVstVersion: /*58*/
  262. r = 0;
  263. break;
  264. // request for the category of the plugin: in this case it is an effect since it is modifying the input (as opposed
  265. // to generating sound)
  266. case effGetPlugCategory:
  267. // return kPlugCategEffect;
  268. return kPlugCategSynth;
  269. case effOpen:
  270. // called by the host after it has obtained the effect instance (but _not_ during plugin scans)
  271. // (note) any heavy-lifting init code should go here
  272. printf("vstgltest: effOpen\n");
  273. r = wrapper->openEffect();
  274. break;
  275. // called by the host when the plugin was called... time to reclaim memory!
  276. case effClose:
  277. printf("vstgltest: effClose\n");
  278. wrapper->closeEffect();
  279. delete wrapper;
  280. break;
  281. case effGetEffectName:
  282. ::strncpy((char*)ptr, "VST GL Test", kVstMaxEffectNameLen);
  283. r = 1;
  284. break;
  285. case effGetProductString:
  286. ::strncpy((char*)ptr, "VST GL Test ProdStr", kVstMaxProductStrLen);
  287. r = 1;
  288. break;
  289. // request for the vendor string (usually used in the UI for plugin grouping)
  290. case effGetVendorString:
  291. strncpy(static_cast<char *>(ptr), "bsp", kVstMaxVendorStrLen);
  292. r = 1;
  293. break;
  294. // request for the version
  295. case effGetVendorVersion:
  296. return PLUGIN_VERSION;
  297. case effGetNumMidiInputChannels:
  298. r = 16;
  299. break;
  300. case effGetNumMidiOutputChannels:
  301. r = 0;
  302. break;
  303. case effCanDo:
  304. // ptr:
  305. // "sendVstEvents"
  306. // "sendVstMidiEvent"
  307. // "sendVstTimeInfo"
  308. // "receiveVstEvents"
  309. // "receiveVstMidiEvent"
  310. // "receiveVstTimeInfo"
  311. // "offline"
  312. // "plugAsChannelInsert"
  313. // "plugAsSend"
  314. // "mixDryWet"
  315. // "noRealTime"
  316. // "multipass"
  317. // "metapass"
  318. // "1in1out"
  319. // "1in2out"
  320. // "2in1out"
  321. // "2in2out"
  322. // "2in4out"
  323. // "4in2out"
  324. // "4in4out"
  325. // "4in8out"
  326. // "8in4out"
  327. // "8in8out"
  328. // "midiProgramNames"
  329. // "conformsToWindowRules"
  330. if(!strcmp((char*)ptr, "receiveVstEvents"))
  331. r = 1;
  332. else if(!strcmp((char*)ptr, "receiveVstMidiEvent")) // (note) required by Jeskola Buzz
  333. r = 1;
  334. else if(!strcmp((char*)ptr, "noRealTime"))
  335. r = 1;
  336. else
  337. r = 0;
  338. break;
  339. case effGetInputProperties:
  340. {
  341. VstPinProperties *pin = (VstPinProperties*)ptr;
  342. ::snprintf(pin->label, kVstMaxLabelLen, "Input #%d", index);
  343. pin->flags = kVstPinIsActive | ((0 == (index & 1)) ? kVstPinIsStereo : 0);
  344. pin->arrangementType = ((0 == (index & 1)) ? kSpeakerArrStereo : kSpeakerArrMono);
  345. ::snprintf(pin->shortLabel, kVstMaxShortLabelLen, "in%d", index);
  346. memset((void*)pin->future, 0, 48);
  347. r = 1;
  348. }
  349. break;
  350. case effGetOutputProperties:
  351. {
  352. VstPinProperties *pin = (VstPinProperties*)ptr;
  353. ::snprintf(pin->label, kVstMaxLabelLen, "Output #%d", index);
  354. pin->flags = kVstPinIsActive | ((0 == (index & 1)) ? kVstPinIsStereo : 0);
  355. pin->arrangementType = ((0 == (index & 1)) ? kSpeakerArrStereo : kSpeakerArrMono);
  356. ::snprintf(pin->shortLabel, kVstMaxShortLabelLen, "out%d", index);
  357. memset((void*)pin->future, 0, 48);
  358. r = 1;
  359. }
  360. break;
  361. case effSetSampleRate:
  362. printf("vstgltest: effSetSampleRate(%f)\n", opt);
  363. r = 1;////wrapper->setSampleRate(opt) ? 1 : 0;
  364. break;
  365. case effSetBlockSize:
  366. printf("vstgltest: effSetBlockSize(%u)\n", uint32_t(value));
  367. r = 1;////wrapper->setBlockSize(uint32_t(value)) ? 1 : 0;
  368. break;
  369. case effMainsChanged:
  370. printf("vstgltest: effMainsChanged(%ld)\n", value);
  371. // value = 0=suspend, 1=resume
  372. // wrapper->setEnableProcessingActive((value > 0) ? true : false);
  373. r = 1;
  374. break;
  375. case effSetProgram:
  376. r = 1;
  377. break;
  378. case effGetProgram:
  379. r = 0;
  380. break;
  381. case effGetProgramName:
  382. ::snprintf((char*)ptr, kVstMaxProgNameLen, "default");
  383. r = 1;
  384. break;
  385. case effSetProgramName:
  386. r = 1;
  387. break;
  388. case effGetProgramNameIndexed:
  389. ::sprintf((char*)ptr, "default");
  390. r = 1;
  391. break;
  392. case effGetParamName:
  393. strncpy(static_cast<char *>(ptr), "myparam", kVstMaxParamStrLen);
  394. r = 1;
  395. break;
  396. case effCanBeAutomated:
  397. // fix Propellerhead Reason VST parameter support
  398. r = 1;
  399. break;
  400. case effStartProcess:
  401. r = 1;
  402. break;
  403. case effStopProcess:
  404. r = 1;
  405. break;
  406. case effEditIdle:
  407. // printf("vstgltest: redraw window\n");
  408. // (void)::RedrawWindow(wrapper->hwnd, NULL, NULL, RDW_INTERNALPAINT);
  409. //(void)::UpdateWindow(wrapper->hwnd);
  410. #ifdef USE_LGLW
  411. if(lglw_window_is_visible(wrapper->lglw))
  412. {
  413. // lglw_events(wrapper->lglw);
  414. wrapper->redrawWindow();
  415. }
  416. #endif // USE_LGLW
  417. break;
  418. case effEditGetRect:
  419. // Query editor window geometry
  420. // ptr: ERect* (on Windows)
  421. if(NULL != ptr) // yeah, this should never be NULL
  422. {
  423. // ...
  424. wrapper->editor_rect.left = EDITWIN_X;
  425. wrapper->editor_rect.top = EDITWIN_Y;
  426. wrapper->editor_rect.right = EDITWIN_X + EDITWIN_W;
  427. wrapper->editor_rect.bottom = EDITWIN_Y + EDITWIN_H;
  428. *(void**)ptr = (void*) &wrapper->editor_rect;
  429. r = 1;
  430. }
  431. else
  432. {
  433. r = 0;
  434. }
  435. break;
  436. #if 0
  437. case effEditTop:
  438. // deprecated in vst2.4
  439. r = 0;
  440. break;
  441. #endif
  442. case effEditOpen:
  443. // Show editor window
  444. // ptr: native window handle (hWnd on Windows)
  445. wrapper->openEditor(ptr);
  446. r = 1;
  447. break;
  448. case effEditClose:
  449. // Hide editor window
  450. wrapper->closeEditor();
  451. r = 1;
  452. break;
  453. }
  454. return r;
  455. }
  456. }
  457. /**
  458. * Used for parameter setting (not used by this plugin)
  459. */
  460. extern "C" {
  461. void VSTPluginSetParameter(VSTPlugin *vstPlugin, VstInt32 index, float parameter)
  462. {
  463. printf("vstgltest: VSTPluginSetParameter(%d, %f)\n", index, parameter);
  464. // we can get a hold to our C++ class since we stored it in the `object` field (see constructor)
  465. VSTPluginWrapper *wrapper = static_cast<VSTPluginWrapper *>(vstPlugin->object);
  466. (void)wrapper;
  467. }
  468. }
  469. /**
  470. * Used for parameter (not used by this plugin)
  471. */
  472. extern "C" {
  473. float VSTPluginGetParameter(VSTPlugin *vstPlugin, VstInt32 index)
  474. {
  475. printf("vstgltest: VSTPluginGetParameter(%d)\n", index);
  476. // we can get a hold to our C++ class since we stored it in the `object` field (see constructor)
  477. VSTPluginWrapper *wrapper = static_cast<VSTPluginWrapper *>(vstPlugin->object);
  478. (void)wrapper;
  479. return 0;
  480. }
  481. }
  482. extern "C" {
  483. static void loc_redraw_cbk(lglw_t _lglw) {
  484. VSTPluginWrapper *wrapper = (VSTPluginWrapper*)lglw_userdata_get(_lglw);
  485. wrapper->redrawWindow();
  486. }
  487. }
  488. /**
  489. * Main constructor for our C++ class
  490. */
  491. VSTPluginWrapper::VSTPluginWrapper(audioMasterCallback vstHostCallback,
  492. VstInt32 vendorUniqueID,
  493. VstInt32 vendorVersion,
  494. VstInt32 numParams,
  495. VstInt32 numPrograms,
  496. VstInt32 numInputs,
  497. VstInt32 numOutputs) :
  498. _vstHostCallback(vstHostCallback)
  499. {
  500. // Make sure that the memory is properly initialized
  501. memset(&_vstPlugin, 0, sizeof(_vstPlugin));
  502. // this field must be set with this constant...
  503. _vstPlugin.magic = kEffectMagic;
  504. // storing this object into the VSTPlugin so that it can be retrieved when called back (see callbacks for use)
  505. _vstPlugin.object = this;
  506. // specifying that we handle both single and double precision (there are other flags see aeffect.h/VstAEffectFlags)
  507. _vstPlugin.flags =
  508. effFlagsIsSynth |
  509. effFlagsCanReplacing |
  510. effFlagsCanDoubleReplacing |
  511. effFlagsHasEditor
  512. ;
  513. // initializing the plugin with the various values
  514. _vstPlugin.uniqueID = vendorUniqueID;
  515. _vstPlugin.version = vendorVersion;
  516. _vstPlugin.numParams = numParams;
  517. _vstPlugin.numPrograms = numPrograms;
  518. _vstPlugin.numInputs = numInputs;
  519. _vstPlugin.numOutputs = numOutputs;
  520. // setting the callbacks to the previously defined functions
  521. _vstPlugin.dispatcher = VSTPluginDispatcher;
  522. _vstPlugin.getParameter = VSTPluginGetParameter;
  523. _vstPlugin.setParameter = VSTPluginSetParameter;
  524. _vstPlugin.processReplacing = VSTPluginProcessSamplesFloat32;
  525. _vstPlugin.processDoubleReplacing = VSTPluginProcessSamplesFloat64;
  526. #ifdef USE_LGLW
  527. printf("vstgltest: calling lglw_init()\n");
  528. lglw = lglw_init(EDITWIN_W, EDITWIN_H);
  529. lglw_userdata_set(lglw, this);
  530. printf("vstgltest: lglw_init() returned lglw=%p\n", lglw);
  531. #endif // USE_LGLW
  532. }
  533. /**
  534. * Destructor called when the plugin is closed (see VSTPluginDispatcher with effClose opCode). In this very simply plugin
  535. * there is nothing to do but in general the memory that gets allocated MUST be freed here otherwise there might be a
  536. * memory leak which may end up slowing down and/or crashing the host
  537. */
  538. VSTPluginWrapper::~VSTPluginWrapper() {
  539. #ifdef USE_LGLW
  540. lglw_exit(lglw);
  541. #endif // USE_LGLW
  542. }
  543. /**
  544. * Implementation of the main entry point of the plugin
  545. */
  546. VST_EXPORT VSTPlugin *VSTPluginMain(VSTHostCallback vstHostCallback)
  547. {
  548. printf("vstgltest: entering VSTPluginMain... \n");
  549. {
  550. FILE *fh = fopen("/tmp/debug_lglw.txt", "w");
  551. fprintf(fh, "hello\n");
  552. fflush(fh);
  553. fclose(fh);
  554. }
  555. {
  556. Dl_info dlInfo;
  557. char dllnameraw[1024];
  558. char *dllnamerawp = dllnameraw;
  559. char oldCWD[1024];
  560. getcwd(oldCWD, 1024);
  561. ::dladdr((void*)VSTPluginMain, &dlInfo);
  562. if('/' != dlInfo.dli_fname[0])
  563. {
  564. // (note) 'dli_fname' can be a relative path (e.g. when loaded from vst2_debug_host)
  565. sprintf(dllnameraw, "%s/%s", oldCWD, dlInfo.dli_fname);
  566. }
  567. else
  568. {
  569. // Absolute path (e.g. when loaded from Renoise host)
  570. dllnamerawp = (char*)dlInfo.dli_fname;
  571. }
  572. printf("vstgltest: dllname=\"%s\"\n", dllnamerawp);
  573. }
  574. // simply create our plugin C++ class
  575. VSTPluginWrapper *plugin =
  576. new VSTPluginWrapper(vstHostCallback,
  577. //CCONST('u', 's', 'a', 'ยง'), // registered with Steinberg (http://service.steinberg.de/databases/plugin.nsf/plugIn?openForm)
  578. CCONST('t', 'e', 's', 't'), // unregistered
  579. PLUGIN_VERSION, // version
  580. 0, // no params
  581. 1, // no programs
  582. 0, // 2 inputs
  583. 2); // 2 outputs
  584. // return the plugin per the contract of the API
  585. return plugin->getVSTPlugin();
  586. }