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.

697 lines
22KB

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