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.

395 lines
12KB

  1. // vst_eureka_standalone_test.cpp : Defines the entry point for the console application.
  2. //
  3. #define DLL_PATH "../../vst2_bin/veeseevstrack_effect.dll"
  4. #define SO_PATH "../../vst2_bin/veeseevstrack_effect.so"
  5. // #define SO_PATH "../vst2_lglw_debug_plugin/debug_lglw.so"
  6. // #define SO_PATH "/usr/local/lib/vst/debug_lglw.so"
  7. // #define SO_PATH "../../vst2_bin/debug_lglw.so"
  8. // #define SO_PATH "/home/bsp/.vst/DiscoveryPro68DemoLinux/64-bit/DiscoveryPro64.so"
  9. // #define SO_PATH "/home/bsp/.vst/AcidBoxDEMO-Linux/AcidBoxDEMOVST-x64.so"
  10. // #define SO_PATH "/home/bsp/.vst/DigitsLinux_2_1/DigitsVST_64.so"
  11. // #define SO_PATH "/usr/lib/lxvst/helm.so"
  12. // #define SO_PATH "/home/bsp/.vst/oxevst134/oxevst64.so" // crashes VirtualBox (!)
  13. // #define SO_PATH "/home/bsp/.vst/tunefish-v4.2.0-linux64-vst24.tar/Tunefish4.so" // does not load (GLIBC error)
  14. // #define SO_PATH "/home/bsp/.vst/zyn-fusion/ZynAddSubFX.so"
  15. #define Dprintf_verbose if(1);else printf
  16. // #define Dprintf_verbose if(0);else printf
  17. #include <yac.h>
  18. #ifdef YAC_WIN32
  19. #include "stdafx.h"
  20. #include <windows.h>
  21. #else
  22. #include <dlfcn.h>
  23. #include <unistd.h>
  24. #include <X11/Xlib.h>
  25. #include <X11/Xutil.h>
  26. #include <X11/Xos.h>
  27. #include <X11/Xatom.h>
  28. #endif
  29. #include <aeffect.h>
  30. #include <aeffectx.h>
  31. typedef AEffect* (*PluginEntryProc) (audioMasterCallback audioMaster);
  32. #ifndef YAC_WIN32
  33. static void *loc_getProperty(Display *_display, Window _window, const char *_name) {
  34. int userSize;
  35. unsigned long bytes;
  36. unsigned long userCount;
  37. unsigned char *data;
  38. Atom userType;
  39. Atom atom = XInternAtom(_display, _name, False);
  40. // (note) 64bit properties need to be read with two XGetWindowProperty() calls.
  41. // When using just one call and setting the 'length' to 2, the upper 32bit (second array element) will be 0xFFFFffff.
  42. XGetWindowProperty(_display,
  43. _window,
  44. atom,
  45. 0/*offset*/,
  46. 1/*length*/,
  47. False/*delete*/,
  48. AnyPropertyType,
  49. &userType/*actual_type_return*/,
  50. &userSize/*actual_format_return*/,
  51. &userCount/*nitems_return*/,
  52. &bytes/*bytes_after_return / partial reads*/,
  53. &data);
  54. union {
  55. uint32_t ui[2];
  56. void *any;
  57. } uptr;
  58. uptr.any = 0;
  59. Dprintf_verbose("xxx debug_host: loc_getProperty: LOWER userSize=%d userCount=%lu bytes=%lu data=%p\n", userSize, userCount, bytes, data);
  60. if(NULL != data)
  61. {
  62. if(userCount >= 1)
  63. {
  64. // lower 32-bit
  65. uptr.ui[0] = *(long*)data;
  66. uptr.ui[1] = 0;
  67. Dprintf_verbose("xxx lower=0x%08x\n", uptr.ui[0]);
  68. XFree(data);
  69. XGetWindowProperty(_display,
  70. _window,
  71. atom,
  72. 1/*offset*/,
  73. 1/*length*/,
  74. False/*delete*/,
  75. AnyPropertyType,
  76. &userType/*actual_type_return*/,
  77. &userSize/*actual_format_return*/,
  78. &userCount/*nitems_return*/,
  79. &bytes/*bytes_after_return / partial reads*/,
  80. &data);
  81. // printf("xxx debug_host: loc_getProperty: UPPER userSize=%d userCount=%lu bytes=%lu data=%p\n", userSize, userCount, bytes, data);
  82. if(NULL != data)
  83. {
  84. // upper 32-bit
  85. uptr.ui[1] = *(long*)data;
  86. Dprintf_verbose("xxx upper=0x%08x\n", uptr.ui[1]);
  87. XFree(data);
  88. }
  89. }
  90. }
  91. Dprintf_verbose("xxx debug_host: loc_getProperty: return value=%p\n", uptr.any);
  92. return uptr.any;
  93. }
  94. #endif // !YAC_WIN32
  95. static VstIntPtr VSTCALLBACK HostCallback(AEffect* effect, VstInt32 opcode, VstInt32 index, VstIntPtr value, void* ptr, float opt) {
  96. static VstInt32 lastOpcode = -1;
  97. static VstIntPtr lastTimeMask = ~0;
  98. VstIntPtr result = 0;
  99. lastOpcode = opcode;
  100. (void)lastOpcode;
  101. (void)lastTimeMask;
  102. switch(opcode)
  103. {
  104. default:
  105. printf("xxx debug_host: HostCallback: unhandled opcode=%d index=%d value=%ld ptr=%p opt=%f\n", opcode, index, value, ptr, opt);
  106. break;
  107. case audioMasterVersion:
  108. result = 2400;
  109. break;
  110. }
  111. return result;
  112. }
  113. float *inputBuffers[48];
  114. float *outputBuffers[48];
  115. void open_and_close(void) {
  116. #ifdef YAC_WIN32
  117. HINSTANCE dllHandle = ::LoadLibraryA(DLL_PATH);
  118. #else
  119. void *dllHandle = ::dlopen(SO_PATH, RTLD_NOW);
  120. if(NULL == dllHandle)
  121. {
  122. printf("Failed to load library %s: %s", SO_PATH, dlerror());
  123. return;
  124. }
  125. #endif
  126. #ifndef YAC_WIN32
  127. Display *d;
  128. Window w;
  129. int s;
  130. d = XOpenDisplay(NULL);
  131. s = DefaultScreen(d);
  132. #endif
  133. for(int i = 0; i < 48; i++)
  134. {
  135. inputBuffers[i] = new float[4096];
  136. outputBuffers[i] = new float[4096];
  137. }
  138. if(NULL != dllHandle)
  139. {
  140. #ifdef YAC_WIN32
  141. PluginEntryProc mainProc = (PluginEntryProc) ::GetProcAddress((HMODULE)dllHandle, "VSTPluginMain");
  142. if(NULL == mainProc)
  143. {
  144. mainProc = (PluginEntryProc) ::GetProcAddress((HMODULE)dllHandle, "main");
  145. }
  146. #else
  147. PluginEntryProc mainProc = (PluginEntryProc) ::dlsym(dllHandle, "VSTPluginMain");
  148. if(NULL == mainProc)
  149. {
  150. mainProc = (PluginEntryProc) ::dlsym(dllHandle, "main");
  151. }
  152. #endif
  153. if(NULL != mainProc)
  154. {
  155. AEffect *effect;
  156. printf("xxx calling mainProc\n");
  157. effect = mainProc(HostCallback);
  158. printf("xxx mainProc returned effect=%p\n", effect);
  159. if(NULL != effect)
  160. {
  161. printf("xxx calling effect->dispatcher<effOpen>\n");
  162. effect->dispatcher(effect, effOpen, 0, 0, NULL, 0.0f);
  163. printf("xxx effect->dispatcher<effOpen> returned\n");
  164. ERect *rectp = 0;
  165. ERect rect;
  166. effect->dispatcher(effect, effEditGetRect, 0, 0, (void*)&rectp, 0.0f);
  167. if(NULL != rectp)
  168. {
  169. rect = *rectp;
  170. }
  171. else
  172. {
  173. rect.top = 0;
  174. rect.left = 0;
  175. rect.right = 640;
  176. rect.bottom = 480;
  177. }
  178. printf("xxx effEditGetRect returned left=%d top=%d right=%d bottom=%d\n", rect.left, rect.top, rect.right, rect.bottom);
  179. #ifndef YAC_WIN32
  180. w = XCreateSimpleWindow(d, RootWindow(d, s), rect.left, rect.top, (rect.right - rect.left), (rect.bottom - rect.top), 1,
  181. BlackPixel(d, s), WhitePixel(d, s)
  182. );
  183. XSelectInput(d, w, ExposureMask | KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | EnterWindowMask | LeaveWindowMask | PointerMotionMask | ButtonMotionMask | FocusChangeMask);
  184. // see <https://stackoverflow.com/questions/1157364/intercept-wm-delete-window-on-x11>
  185. Atom wm_delete_window;
  186. {
  187. wm_delete_window = XInternAtom(d, "WM_DELETE_WINDOW", False);
  188. XSetWMProtocols(d, w, &wm_delete_window, 1);
  189. }
  190. XMapRaised(d, w);
  191. XFlush(d);
  192. #endif
  193. #if 0
  194. // Event test (=> keyboard events are working)
  195. {
  196. int evIdx = 0;
  197. for(;;)
  198. {
  199. XEvent xev;
  200. XNextEvent(d, &xev);
  201. printf("xxx XNextEvent[%d]\n", evIdx++);
  202. }
  203. }
  204. #endif
  205. #ifdef YAC_WIN32
  206. VstIntPtr ip = effect->dispatcher(effect, effEditOpen, 0, 0, NULL/*hWnd*/, 0.0f);
  207. #else
  208. VstIntPtr ip = effect->dispatcher(effect, effEditOpen, 0, 0, (void*)(w)/*hWnd*/, 0.0f);
  209. effect->dispatcher(effect, effEditIdle, 0, 0, NULL, 0.0f); // test feedback loop
  210. #endif
  211. (void)ip;
  212. sleep(2);
  213. #ifndef YAC_WIN32
  214. void *result = loc_getProperty(d, w, "_XEventProc");
  215. if(result == 0)
  216. {
  217. printf("xxx no XEventProc found, running effEditIdle instead\n");
  218. bool bRunning = true;
  219. while(bRunning)
  220. {
  221. XEvent xev;
  222. int queued = XPending(d);
  223. // printf("xxx =====================================================\n");
  224. // printf("xxx checking host queue before effEditIdle (events: %i)\n", queued);
  225. while(queued)
  226. {
  227. XNextEvent(d, &xev);
  228. // printf("xxx event type: %i\n", xev.type);
  229. queued--;
  230. }
  231. // printf("xxx calling effect->dispatcher<effEditIdle>\n");
  232. effect->dispatcher(effect, effEditIdle, 0, 0, NULL, 0.0f);
  233. queued = XPending(d);
  234. // printf("xxx checking host queue after effEditIdle (events: %i)\n", queued);
  235. while((queued > 0) && bRunning)
  236. {
  237. XNextEvent(d, &xev);
  238. // printf("xxx debug_host: xev.type=%d\n", xev.type);
  239. if(ClientMessage == xev.type)
  240. {
  241. printf("xxx debug_host: ClientMessage\n");
  242. if((Atom)xev.xclient.data.l[0] == wm_delete_window)
  243. {
  244. printf("xxx debug_host: ClientMessage<wm_delete_window>\n");
  245. bRunning = false;
  246. }
  247. }
  248. // if(MotionNotify != xev.type)
  249. // printf("xxx event type: %i\n", xev.type);
  250. queued--;
  251. }
  252. // sleep(1); // can be helpful when viewing print statements
  253. }
  254. }
  255. else
  256. {
  257. void (* eventProc) (void * event);
  258. int evIdx = 0;
  259. eventProc = (void (*) (void* event))result;
  260. printf("xxx XEventProc found\n");
  261. for(;;)
  262. {
  263. XEvent xev;
  264. XNextEvent(d, &xev);
  265. Dprintf_verbose("xxx call XEventProc[%d]\n", evIdx++);
  266. eventProc(&xev);
  267. // Dprintf_verbose("xxx calling effect->dispatcher<effEditIdle>\n");
  268. // effect->dispatcher(effect, effEditIdle, 0, 0, NULL, 0.0f);
  269. }
  270. }
  271. #endif
  272. sleep(1);
  273. printf("xxx calling effect->dispatcher<effEditClose>\n");
  274. effect->dispatcher(effect, effEditClose, 0, 0, NULL, 0.0f);
  275. #if 0
  276. sleep(1);
  277. printf("xxx calling effect->dispatcher<effEditOpen> again\n");
  278. #ifdef YAC_WIN32
  279. effect->dispatcher(effect, effEditOpen, 0, 0, NULL/*hWnd*/, 0.0f);
  280. #else
  281. effect->dispatcher(effect, effEditOpen, 0, 0, (void*)(w)/*hWnd*/, 0.0f);
  282. #endif
  283. sleep(1);
  284. printf("xxx calling effect->dispatcher<effEditIdle>\n");
  285. effect->dispatcher(effect, effEditIdle, 0, 0, NULL, 0.0f);
  286. sleep(1);
  287. #endif
  288. printf("xxx call processreplacing\n");
  289. for(int i = 0; i < 1024; i++)
  290. {
  291. effect->processReplacing(effect, inputBuffers, outputBuffers, (VstInt32)64);
  292. }
  293. #if 0
  294. printf("xxx calling effect->dispatcher<effEditClose>\n");
  295. effect->dispatcher(effect, effEditClose, 0, 0, NULL, 0.0f);
  296. sleep(1);
  297. #endif
  298. printf("xxx calling effect->dispatcher<effClose>\n");
  299. effect->dispatcher(effect, effClose, 0, 0, NULL, 0.0f);
  300. sleep(1);
  301. #ifndef YAC_WIN32
  302. XDestroyWindow(d, w);
  303. #endif
  304. }
  305. }
  306. else
  307. {
  308. printf("[---] failed to find mainProc\n");
  309. }
  310. printf("xxx debug_host: closing library\n");
  311. #ifdef YAC_WIN32
  312. ::FreeLibrary(dllHandle);
  313. #else
  314. ::dlclose(dllHandle);
  315. #endif
  316. printf("xxx debug_host: library closed\n");
  317. }
  318. for(int i = 0; i < 48; i++)
  319. {
  320. delete [] inputBuffers[i];
  321. delete [] outputBuffers[i];
  322. }
  323. #ifndef YAC_WIN32
  324. XCloseDisplay(d);
  325. #endif
  326. }
  327. int main() {
  328. for(int i = 0; i < 2; i++)
  329. {
  330. open_and_close();
  331. }
  332. printf("xxx debug_host: exiting\n");
  333. return 0;
  334. }