ASIO to JACK driver for WINE
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.

1634 lines
60KB

  1. /*
  2. * Copyright (C) 2006 Robert Reif
  3. * Portions copyright (C) 2007 Ralf Beck
  4. * Portions copyright (C) 2007 Johnny Petrantoni
  5. * Portions copyright (C) 2007 Stephane Letz
  6. * Portions copyright (C) 2008 William Steidtmann
  7. * Portions copyright (C) 2010 Peter L Jones
  8. * Portions copyright (C) 2010 Torben Hohn
  9. * Portions copyright (C) 2010 Nedko Arnaudov
  10. * Portions copyright (C) 2013 Joakim Hernberg
  11. *
  12. * This library is free software; you can redistribute it and/or
  13. * modify it under the terms of the GNU Lesser General Public
  14. * License as published by the Free Software Foundation; either
  15. * version 2.1 of the License, or (at your option) any later version.
  16. *
  17. * This library is distributed in the hope that it will be useful,
  18. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  19. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  20. * Lesser General Public License for more details.
  21. *
  22. * You should have received a copy of the GNU Lesser General Public
  23. * License along with this library; if not, write to the Free Software
  24. * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  25. */
  26. #include <stdbool.h>
  27. #include <stdio.h>
  28. #include <errno.h>
  29. #include <limits.h>
  30. #include <unistd.h>
  31. #include <sys/mman.h>
  32. #include <pthread.h>
  33. #ifdef DEBUG
  34. #include "wine/debug.h"
  35. #else
  36. #define TRACE(...) {}
  37. #define WARN(fmt, ...) {} fprintf(stdout, "[wineasio] " fmt, ##__VA_ARGS__)
  38. #define ERR(fmt, ...) {} fprintf(stderr, "[wineasio] " fmt, ##__VA_ARGS__)
  39. #endif
  40. #include <objbase.h>
  41. #include <mmsystem.h>
  42. #include <winreg.h>
  43. #ifdef WINE_WITH_UNICODE
  44. #include <wine/unicode.h>
  45. #endif
  46. #include "jackbridge.h"
  47. #ifdef DEBUG
  48. WINE_DEFAULT_DEBUG_CHANNEL(asio);
  49. #endif
  50. #define MAX_ENVIRONMENT_SIZE 6
  51. #define WINEASIO_MAX_NAME_LENGTH 32
  52. #define WINEASIO_MINIMUM_BUFFERSIZE 16
  53. #define WINEASIO_MAXIMUM_BUFFERSIZE 8192
  54. #define WINEASIO_PREFERRED_BUFFERSIZE 1024
  55. /* ASIO drivers (breaking the COM specification) use the Microsoft variety of
  56. * thiscall calling convention which gcc is unable to produce. These macros
  57. * add an extra layer to fixup the registers. Borrowed from config.h and the
  58. * wine source code.
  59. */
  60. /* From config.h */
  61. #define __ASM_DEFINE_FUNC(name,suffix,code) asm(".text\n\t.align 4\n\t.globl " #name suffix "\n\t.type " #name suffix ",@function\n" #name suffix ":\n\t.cfi_startproc\n\t" code "\n\t.cfi_endproc\n\t.previous");
  62. #define __ASM_GLOBAL_FUNC(name,code) __ASM_DEFINE_FUNC(name,"",code)
  63. #define __ASM_NAME(name) name
  64. #define __ASM_STDCALL(args) ""
  65. /* From wine source */
  66. #ifdef __i386__ /* thiscall functions are i386-specific */
  67. #define THISCALL(func) __thiscall_ ## func
  68. #define THISCALL_NAME(func) __ASM_NAME("__thiscall_" #func)
  69. #define __thiscall __stdcall
  70. #define DEFINE_THISCALL_WRAPPER(func,args) \
  71. extern void THISCALL(func)(void); \
  72. __ASM_GLOBAL_FUNC(__thiscall_ ## func, \
  73. "popl %eax\n\t" \
  74. "pushl %ecx\n\t" \
  75. "pushl %eax\n\t" \
  76. "jmp " __ASM_NAME(#func) __ASM_STDCALL(args) )
  77. #else /* __i386__ */
  78. #define THISCALL(func) func
  79. #define THISCALL_NAME(func) __ASM_NAME(#func)
  80. #define __thiscall __stdcall
  81. #define DEFINE_THISCALL_WRAPPER(func,args) /* nothing */
  82. #endif /* __i386__ */
  83. /* Hide ELF symbols for the COM members - No need to to export them */
  84. #define HIDDEN __attribute__ ((visibility("hidden")))
  85. #ifdef _WIN64
  86. #define WINEASIO_CALLBACK CALLBACK
  87. #else
  88. #define WINEASIO_CALLBACK
  89. #endif
  90. typedef struct w_int64_t {
  91. ULONG hi;
  92. ULONG lo;
  93. } w_int64_t;
  94. typedef struct BufferInformation
  95. {
  96. LONG isInputType;
  97. LONG channelNumber;
  98. void *audioBufferStart;
  99. void *audioBufferEnd;
  100. } BufferInformation;
  101. typedef struct TimeInformation
  102. {
  103. LONG _1[4];
  104. double _2;
  105. w_int64_t timeStamp;
  106. w_int64_t numSamples;
  107. double sampleRate;
  108. ULONG flags;
  109. char _3[12];
  110. double speedForTimeCode;
  111. w_int64_t timeStampForTimeCode;
  112. ULONG flagsForTimeCode;
  113. char _4[64];
  114. } TimeInformation;
  115. typedef struct Callbacks
  116. {
  117. void (WINEASIO_CALLBACK *swapBuffers) (LONG, LONG);
  118. void (WINEASIO_CALLBACK *sampleRateChanged) (double);
  119. LONG (WINEASIO_CALLBACK *sendNotification) (LONG, LONG, void*, double*);
  120. void* (WINEASIO_CALLBACK *swapBuffersWithTimeInfo) (TimeInformation*, LONG, LONG);
  121. } Callbacks;
  122. /*****************************************************************************
  123. * IWineAsio interface
  124. */
  125. #define INTERFACE IWineASIO
  126. DECLARE_INTERFACE_(IWineASIO,IUnknown)
  127. {
  128. STDMETHOD_(HRESULT, QueryInterface) (THIS_ IID riid, void** ppvObject) PURE;
  129. STDMETHOD_(ULONG, AddRef) (THIS) PURE;
  130. STDMETHOD_(ULONG, Release) (THIS) PURE;
  131. STDMETHOD_(LONG, Init) (THIS_ void *sysRef) PURE;
  132. STDMETHOD_(void, GetDriverName) (THIS_ char *name) PURE;
  133. STDMETHOD_(LONG, GetDriverVersion) (THIS) PURE;
  134. STDMETHOD_(void, GetErrorMessage) (THIS_ char *string) PURE;
  135. STDMETHOD_(LONG, Start) (THIS) PURE;
  136. STDMETHOD_(LONG, Stop) (THIS) PURE;
  137. STDMETHOD_(LONG, GetChannels) (THIS_ LONG *numInputChannels, LONG *numOutputChannels) PURE;
  138. STDMETHOD_(LONG, GetLatencies) (THIS_ LONG *inputLatency, LONG *outputLatency) PURE;
  139. STDMETHOD_(LONG, GetBufferSize) (THIS_ LONG *minSize, LONG *maxSize, LONG *preferredSize, LONG *granularity) PURE;
  140. STDMETHOD_(LONG, CanSampleRate) (THIS_ double sampleRate) PURE;
  141. STDMETHOD_(LONG, GetSampleRate) (THIS_ double *sampleRate) PURE;
  142. STDMETHOD_(LONG, SetSampleRate) (THIS_ double sampleRate) PURE;
  143. STDMETHOD_(LONG, GetClockSources) (THIS_ void *clocks, LONG *numSources) PURE;
  144. STDMETHOD_(LONG, SetClockSource) (THIS_ LONG index) PURE;
  145. STDMETHOD_(LONG, GetSamplePosition) (THIS_ w_int64_t *sPos, w_int64_t *tStamp) PURE;
  146. STDMETHOD_(LONG, GetChannelInfo) (THIS_ void *info) PURE;
  147. STDMETHOD_(LONG, CreateBuffers) (THIS_ BufferInformation *bufferInfo, LONG numChannels, LONG bufferSize, Callbacks *callbacks) PURE;
  148. STDMETHOD_(LONG, DisposeBuffers) (THIS) PURE;
  149. STDMETHOD_(LONG, ControlPanel) (THIS) PURE;
  150. STDMETHOD_(LONG, Future) (THIS_ LONG selector,void *opt) PURE;
  151. STDMETHOD_(LONG, OutputReady) (THIS) PURE;
  152. };
  153. #undef INTERFACE
  154. typedef struct IWineASIO *LPWINEASIO;
  155. typedef struct IOChannel
  156. {
  157. jack_default_audio_sample_t *audio_buffer;
  158. char port_name[WINEASIO_MAX_NAME_LENGTH];
  159. jack_port_t *port;
  160. bool active;
  161. } IOChannel;
  162. typedef struct IWineASIOImpl
  163. {
  164. /* COM stuff */
  165. const IWineASIOVtbl *lpVtbl;
  166. LONG ref;
  167. /* The app's main window handle on windows, 0 on OS/X */
  168. HWND sys_ref;
  169. /* Host stuff */
  170. LONG host_active_inputs;
  171. LONG host_active_outputs;
  172. BOOL host_buffer_index;
  173. Callbacks *host_callbacks;
  174. BOOL host_can_time_code;
  175. LONG host_current_buffersize;
  176. INT host_driver_state;
  177. w_int64_t host_num_samples;
  178. double host_sample_rate;
  179. TimeInformation host_time;
  180. BOOL host_time_info_mode;
  181. w_int64_t host_time_stamp;
  182. LONG host_version;
  183. /* WineASIO configuration options */
  184. int wineasio_number_inputs;
  185. int wineasio_number_outputs;
  186. BOOL wineasio_autostart_server;
  187. BOOL wineasio_connect_to_hardware;
  188. BOOL wineasio_fixed_buffersize;
  189. LONG wineasio_preferred_buffersize;
  190. /* JACK stuff */
  191. jack_client_t *jack_client;
  192. char jack_client_name[WINEASIO_MAX_NAME_LENGTH];
  193. int jack_num_input_ports;
  194. int jack_num_output_ports;
  195. const char **jack_input_ports;
  196. const char **jack_output_ports;
  197. /* jack process callback buffers */
  198. jack_default_audio_sample_t *callback_audio_buffer;
  199. IOChannel *input_channel;
  200. IOChannel *output_channel;
  201. } IWineASIOImpl;
  202. enum { Loaded, Initialized, Prepared, Running };
  203. /****************************************************************************
  204. * Interface Methods
  205. */
  206. /*
  207. * as seen from the WineASIO source
  208. */
  209. HIDDEN HRESULT STDMETHODCALLTYPE QueryInterface(LPWINEASIO iface, REFIID riid, void **ppvObject);
  210. HIDDEN ULONG STDMETHODCALLTYPE AddRef(LPWINEASIO iface);
  211. HIDDEN ULONG STDMETHODCALLTYPE Release(LPWINEASIO iface);
  212. HIDDEN LONG STDMETHODCALLTYPE Init(LPWINEASIO iface, void *sysRef);
  213. HIDDEN void STDMETHODCALLTYPE GetDriverName(LPWINEASIO iface, char *name);
  214. HIDDEN LONG STDMETHODCALLTYPE GetDriverVersion(LPWINEASIO iface);
  215. HIDDEN void STDMETHODCALLTYPE GetErrorMessage(LPWINEASIO iface, char *string);
  216. HIDDEN LONG STDMETHODCALLTYPE Start(LPWINEASIO iface);
  217. HIDDEN LONG STDMETHODCALLTYPE Stop(LPWINEASIO iface);
  218. HIDDEN LONG STDMETHODCALLTYPE GetChannels (LPWINEASIO iface, LONG *numInputChannels, LONG *numOutputChannels);
  219. HIDDEN LONG STDMETHODCALLTYPE GetLatencies(LPWINEASIO iface, LONG *inputLatency, LONG *outputLatency);
  220. HIDDEN LONG STDMETHODCALLTYPE GetBufferSize(LPWINEASIO iface, LONG *minSize, LONG *maxSize, LONG *preferredSize, LONG *granularity);
  221. HIDDEN LONG STDMETHODCALLTYPE CanSampleRate(LPWINEASIO iface, double sampleRate);
  222. HIDDEN LONG STDMETHODCALLTYPE GetSampleRate(LPWINEASIO iface, double *sampleRate);
  223. HIDDEN LONG STDMETHODCALLTYPE SetSampleRate(LPWINEASIO iface, double sampleRate);
  224. HIDDEN LONG STDMETHODCALLTYPE GetClockSources(LPWINEASIO iface, void *clocks, LONG *numSources);
  225. HIDDEN LONG STDMETHODCALLTYPE SetClockSource(LPWINEASIO iface, LONG index);
  226. HIDDEN LONG STDMETHODCALLTYPE GetSamplePosition(LPWINEASIO iface, w_int64_t *sPos, w_int64_t *tStamp);
  227. HIDDEN LONG STDMETHODCALLTYPE GetChannelInfo(LPWINEASIO iface, void *info);
  228. HIDDEN LONG STDMETHODCALLTYPE CreateBuffers(LPWINEASIO iface, BufferInformation *bufferInfo, LONG numChannels, LONG bufferSize, Callbacks *callbacks);
  229. HIDDEN LONG STDMETHODCALLTYPE DisposeBuffers(LPWINEASIO iface);
  230. HIDDEN LONG STDMETHODCALLTYPE ControlPanel(LPWINEASIO iface);
  231. HIDDEN LONG STDMETHODCALLTYPE Future(LPWINEASIO iface, LONG selector, void *opt);
  232. HIDDEN LONG STDMETHODCALLTYPE OutputReady(LPWINEASIO iface);
  233. /*
  234. * thiscall wrappers for the vtbl (as seen from app side 32bit)
  235. */
  236. HIDDEN void __thiscall_Init(void);
  237. HIDDEN void __thiscall_GetDriverName(void);
  238. HIDDEN void __thiscall_GetDriverVersion(void);
  239. HIDDEN void __thiscall_GetErrorMessage(void);
  240. HIDDEN void __thiscall_Start(void);
  241. HIDDEN void __thiscall_Stop(void);
  242. HIDDEN void __thiscall_GetChannels(void);
  243. HIDDEN void __thiscall_GetLatencies(void);
  244. HIDDEN void __thiscall_GetBufferSize(void);
  245. HIDDEN void __thiscall_CanSampleRate(void);
  246. HIDDEN void __thiscall_GetSampleRate(void);
  247. HIDDEN void __thiscall_SetSampleRate(void);
  248. HIDDEN void __thiscall_GetClockSources(void);
  249. HIDDEN void __thiscall_SetClockSource(void);
  250. HIDDEN void __thiscall_GetSamplePosition(void);
  251. HIDDEN void __thiscall_GetChannelInfo(void);
  252. HIDDEN void __thiscall_CreateBuffers(void);
  253. HIDDEN void __thiscall_DisposeBuffers(void);
  254. HIDDEN void __thiscall_ControlPanel(void);
  255. HIDDEN void __thiscall_Future(void);
  256. HIDDEN void __thiscall_OutputReady(void);
  257. /*
  258. * Jack callbacks
  259. */
  260. static inline int jack_buffer_size_callback (jack_nframes_t nframes, void *arg);
  261. static inline void jack_latency_callback(jack_latency_callback_mode_t mode, void *arg);
  262. static inline int jack_process_callback (jack_nframes_t nframes, void *arg);
  263. static inline int jack_sample_rate_callback (jack_nframes_t nframes, void *arg);
  264. /*
  265. * Support functions
  266. */
  267. HRESULT WINAPI WineASIOCreateInstance(REFIID riid, LPVOID *ppobj);
  268. static VOID configure_driver(IWineASIOImpl *This);
  269. static DWORD WINAPI jack_thread_creator_helper(LPVOID arg);
  270. static int jack_thread_creator(pthread_t* thread_id, const pthread_attr_t* attr, void *(*function)(void*), void* arg);
  271. /* {48D0C522-BFCC-45cc-8B84-17F25F33E6E8} */
  272. static GUID const CLSID_WineASIO = {
  273. 0x48d0c522, 0xbfcc, 0x45cc, { 0x8b, 0x84, 0x17, 0xf2, 0x5f, 0x33, 0xe6, 0xe8 } };
  274. static const IWineASIOVtbl WineASIO_Vtbl =
  275. {
  276. (void *) QueryInterface,
  277. (void *) AddRef,
  278. (void *) Release,
  279. (void *) THISCALL(Init),
  280. (void *) THISCALL(GetDriverName),
  281. (void *) THISCALL(GetDriverVersion),
  282. (void *) THISCALL(GetErrorMessage),
  283. (void *) THISCALL(Start),
  284. (void *) THISCALL(Stop),
  285. (void *) THISCALL(GetChannels),
  286. (void *) THISCALL(GetLatencies),
  287. (void *) THISCALL(GetBufferSize),
  288. (void *) THISCALL(CanSampleRate),
  289. (void *) THISCALL(GetSampleRate),
  290. (void *) THISCALL(SetSampleRate),
  291. (void *) THISCALL(GetClockSources),
  292. (void *) THISCALL(SetClockSource),
  293. (void *) THISCALL(GetSamplePosition),
  294. (void *) THISCALL(GetChannelInfo),
  295. (void *) THISCALL(CreateBuffers),
  296. (void *) THISCALL(DisposeBuffers),
  297. (void *) THISCALL(ControlPanel),
  298. (void *) THISCALL(Future),
  299. (void *) THISCALL(OutputReady)
  300. };
  301. /* structure needed to create the JACK callback thread in the wine process context */
  302. struct {
  303. void *(*jack_callback_thread) (void*);
  304. void *arg;
  305. pthread_t jack_callback_pthread_id;
  306. HANDLE jack_callback_thread_created;
  307. } jack_thread_creator_privates;
  308. /*****************************************************************************
  309. * Interface method definitions
  310. */
  311. HIDDEN HRESULT STDMETHODCALLTYPE QueryInterface(LPWINEASIO iface, REFIID riid, void **ppvObject)
  312. {
  313. IWineASIOImpl *This = (IWineASIOImpl *)iface;
  314. TRACE("iface: %p, riid: %s, ppvObject: %p)\n", iface, debugstr_guid(riid), ppvObject);
  315. if (ppvObject == NULL)
  316. return E_INVALIDARG;
  317. if (IsEqualIID(&CLSID_WineASIO, riid))
  318. {
  319. AddRef(iface);
  320. *ppvObject = This;
  321. return S_OK;
  322. }
  323. return E_NOINTERFACE;
  324. }
  325. /*
  326. * ULONG STDMETHODCALLTYPE AddRef(LPWINEASIO iface);
  327. * Function: Increment the reference count on the object
  328. * Returns: Ref count
  329. */
  330. HIDDEN ULONG STDMETHODCALLTYPE AddRef(LPWINEASIO iface)
  331. {
  332. IWineASIOImpl *This = (IWineASIOImpl *)iface;
  333. ULONG ref = InterlockedIncrement(&(This->ref));
  334. TRACE("iface: %p, ref count is %u\n", iface, (unsigned)ref);
  335. return ref;
  336. }
  337. /*
  338. * ULONG Release (LPWINEASIO iface);
  339. * Function: Destroy the interface
  340. * Returns: Ref count
  341. * Implies: Stop() and DisposeBuffers()
  342. */
  343. HIDDEN ULONG STDMETHODCALLTYPE Release(LPWINEASIO iface)
  344. {
  345. IWineASIOImpl *This = (IWineASIOImpl *)iface;
  346. ULONG ref = InterlockedDecrement(&This->ref);
  347. TRACE("iface: %p, ref count is %u\n", iface, (unsigned)ref);
  348. if (This->host_driver_state == Running)
  349. Stop(iface);
  350. if (This->host_driver_state == Prepared)
  351. DisposeBuffers(iface);
  352. if (This->host_driver_state == Initialized)
  353. {
  354. /* just for good measure we deinitialize IOChannel structures and unregister JACK ports */
  355. for (int i = 0; i < This->wineasio_number_inputs; i++)
  356. {
  357. jackbridge_port_unregister (This->jack_client, This->input_channel[i].port);
  358. This->input_channel[i].active = false;
  359. This->input_channel[i].port = NULL;
  360. }
  361. for (int i = 0; i < This->wineasio_number_outputs; i++)
  362. {
  363. jackbridge_port_unregister (This->jack_client, This->output_channel[i].port);
  364. This->output_channel[i].active = false;
  365. This->output_channel[i].port = NULL;
  366. }
  367. This->host_active_inputs = This->host_active_outputs = 0;
  368. TRACE("%i IOChannel structures released\n", This->wineasio_number_inputs + This->wineasio_number_outputs);
  369. jackbridge_free (This->jack_output_ports);
  370. jackbridge_free (This->jack_input_ports);
  371. jackbridge_client_close(This->jack_client);
  372. if (This->input_channel)
  373. HeapFree(GetProcessHeap(), 0, This->input_channel);
  374. }
  375. TRACE("WineASIO terminated\n\n");
  376. if (ref == 0)
  377. HeapFree(GetProcessHeap(), 0, This);
  378. return ref;
  379. }
  380. /*
  381. * LONG Init (void *sysRef);
  382. * Function: Initialize the driver
  383. * Parameters: Pointer to "This"
  384. * sysHanle is 0 on OS/X and on windows it contains the applications main window handle
  385. * Returns: 0 on error, and 1 on success
  386. */
  387. DEFINE_THISCALL_WRAPPER(Init,8)
  388. HIDDEN LONG STDMETHODCALLTYPE Init(LPWINEASIO iface, void *sysRef)
  389. {
  390. IWineASIOImpl *This = (IWineASIOImpl *)iface;
  391. jack_status_t jack_status;
  392. jack_options_t jack_options = This->wineasio_autostart_server ? JackNullOption : JackNoStartServer;
  393. int i;
  394. This->sys_ref = sysRef;
  395. mlockall(MCL_FUTURE);
  396. configure_driver(This);
  397. if (!(This->jack_client = jackbridge_client_open(This->jack_client_name, jack_options, &jack_status)))
  398. {
  399. WARN("Unable to open a JACK client as: %s\n", This->jack_client_name);
  400. return 0;
  401. }
  402. TRACE("JACK client opened as: '%s'\n", jackbridge_get_client_name(This->jack_client));
  403. This->host_sample_rate = jackbridge_get_sample_rate(This->jack_client);
  404. This->host_current_buffersize = jackbridge_get_buffer_size(This->jack_client);
  405. /* Allocate IOChannel structures */
  406. This->input_channel = HeapAlloc(GetProcessHeap(), 0, (This->wineasio_number_inputs + This->wineasio_number_outputs) * sizeof(IOChannel));
  407. if (!This->input_channel)
  408. {
  409. jackbridge_client_close(This->jack_client);
  410. ERR("Unable to allocate IOChannel structures for %i channels\n", This->wineasio_number_inputs);
  411. return 0;
  412. }
  413. This->output_channel = This->input_channel + This->wineasio_number_inputs;
  414. TRACE("%i IOChannel structures allocated\n", This->wineasio_number_inputs + This->wineasio_number_outputs);
  415. /* Get and count physical JACK ports */
  416. This->jack_input_ports = jackbridge_get_ports(This->jack_client, NULL, NULL, JackPortIsPhysical | JackPortIsOutput);
  417. for (This->jack_num_input_ports = 0; This->jack_input_ports && This->jack_input_ports[This->jack_num_input_ports]; This->jack_num_input_ports++)
  418. ;
  419. This->jack_output_ports = jackbridge_get_ports(This->jack_client, NULL, NULL, JackPortIsPhysical | JackPortIsInput);
  420. for (This->jack_num_output_ports = 0; This->jack_output_ports && This->jack_output_ports[This->jack_num_output_ports]; This->jack_num_output_ports++)
  421. ;
  422. /* Initialize IOChannel structures */
  423. for (i = 0; i < This->wineasio_number_inputs; i++)
  424. {
  425. This->input_channel[i].active = false;
  426. This->input_channel[i].port = NULL;
  427. snprintf(This->input_channel[i].port_name, WINEASIO_MAX_NAME_LENGTH, "in_%i", i + 1);
  428. This->input_channel[i].port = jackbridge_port_register(This->jack_client,
  429. This->input_channel[i].port_name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, i);
  430. /* TRACE("IOChannel structure initialized for input %d: '%s'\n", i, This->input_channel[i].port_name); */
  431. }
  432. for (i = 0; i < This->wineasio_number_outputs; i++)
  433. {
  434. This->output_channel[i].active = false;
  435. This->output_channel[i].port = NULL;
  436. snprintf(This->output_channel[i].port_name, WINEASIO_MAX_NAME_LENGTH, "out_%i", i + 1);
  437. This->output_channel[i].port = jackbridge_port_register(This->jack_client,
  438. This->output_channel[i].port_name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, i);
  439. /* TRACE("IOChannel structure initialized for output %d: '%s'\n", i, This->output_channel[i].port_name); */
  440. }
  441. TRACE("%i IOChannel structures initialized\n", This->wineasio_number_inputs + This->wineasio_number_outputs);
  442. jackbridge_set_thread_creator(jack_thread_creator);
  443. if (!jackbridge_set_buffer_size_callback(This->jack_client, jack_buffer_size_callback, This))
  444. {
  445. jackbridge_client_close(This->jack_client);
  446. HeapFree(GetProcessHeap(), 0, This->input_channel);
  447. ERR("Unable to register JACK buffer size change callback\n");
  448. return 0;
  449. }
  450. if (!jackbridge_set_latency_callback(This->jack_client, jack_latency_callback, This))
  451. {
  452. jackbridge_client_close(This->jack_client);
  453. HeapFree(GetProcessHeap(), 0, This->input_channel);
  454. ERR("Unable to register JACK latency callback\n");
  455. return 0;
  456. }
  457. if (!jackbridge_set_process_callback(This->jack_client, jack_process_callback, This))
  458. {
  459. jackbridge_client_close(This->jack_client);
  460. HeapFree(GetProcessHeap(), 0, This->input_channel);
  461. ERR("Unable to register JACK process callback\n");
  462. return 0;
  463. }
  464. if (!jackbridge_set_sample_rate_callback (This->jack_client, jack_sample_rate_callback, This))
  465. {
  466. jackbridge_client_close(This->jack_client);
  467. HeapFree(GetProcessHeap(), 0, This->input_channel);
  468. ERR("Unable to register JACK sample rate change callback\n");
  469. return 0;
  470. }
  471. This->host_driver_state = Initialized;
  472. TRACE("WineASIO 0.%.1f initialized\n",(float) This->host_version / 10);
  473. return 1;
  474. }
  475. /*
  476. * void GetDriverName(char *name);
  477. * Function: Returns the driver name in name
  478. */
  479. DEFINE_THISCALL_WRAPPER(GetDriverName,8)
  480. HIDDEN void STDMETHODCALLTYPE GetDriverName(LPWINEASIO iface, char *name)
  481. {
  482. TRACE("iface: %p, name: %p\n", iface, name);
  483. strcpy(name, "WineASIO");
  484. return;
  485. }
  486. /*
  487. * LONG GetDriverVersion (void);
  488. * Function: Returns the driver version number
  489. */
  490. DEFINE_THISCALL_WRAPPER(GetDriverVersion,4)
  491. HIDDEN LONG STDMETHODCALLTYPE GetDriverVersion(LPWINEASIO iface)
  492. {
  493. IWineASIOImpl *This = (IWineASIOImpl*)iface;
  494. TRACE("iface: %p\n", iface);
  495. return This->host_version;
  496. }
  497. /*
  498. * void GetErrorMessage(char *string);
  499. * Function: Returns an error message for the last occured error in string
  500. */
  501. DEFINE_THISCALL_WRAPPER(GetErrorMessage,8)
  502. HIDDEN void STDMETHODCALLTYPE GetErrorMessage(LPWINEASIO iface, char *string)
  503. {
  504. TRACE("iface: %p, string: %p)\n", iface, string);
  505. strcpy(string, "WineASIO does not return error messages\n");
  506. return;
  507. }
  508. /*
  509. * LONG Start(void);
  510. * Function: Start JACK IO processing and reset the sample counter to zero
  511. * Returns: -1000 if IO is missing
  512. * -999 if JACK fails to start
  513. */
  514. DEFINE_THISCALL_WRAPPER(Start,4)
  515. HIDDEN LONG STDMETHODCALLTYPE Start(LPWINEASIO iface)
  516. {
  517. IWineASIOImpl *This = (IWineASIOImpl*)iface;
  518. int i;
  519. DWORD time;
  520. TRACE("iface: %p\n", iface);
  521. if (This->host_driver_state != Prepared)
  522. return -1000;
  523. /* Zero the audio buffer */
  524. for (i = 0; i < (This->wineasio_number_inputs + This->wineasio_number_outputs) * 2 * This->host_current_buffersize; i++)
  525. This->callback_audio_buffer[i] = 0;
  526. /* prime the callback by preprocessing one outbound host bufffer */
  527. This->host_buffer_index = 0;
  528. This->host_num_samples.hi = This->host_num_samples.lo = 0;
  529. time = timeGetTime();
  530. This->host_time_stamp.lo = time * 1000000;
  531. This->host_time_stamp.hi = ((unsigned long long) time * 1000000) >> 32;
  532. if (This->host_time_info_mode) /* use the newer swapBuffersWithTimeInfo method if supported */
  533. {
  534. This->host_time.numSamples.lo = This->host_time.numSamples.hi = 0;
  535. This->host_time.timeStamp.lo = This->host_time_stamp.lo;
  536. This->host_time.timeStamp.hi = This->host_time_stamp.hi;
  537. This->host_time.sampleRate = This->host_sample_rate;
  538. This->host_time.flags = 0x7;
  539. if (This->host_can_time_code) /* addionally use time code if supported */
  540. {
  541. This->host_time.speedForTimeCode = 1; /* FIXME */
  542. This->host_time.timeStampForTimeCode.lo = This->host_time_stamp.lo;
  543. This->host_time.timeStampForTimeCode.hi = This->host_time_stamp.hi;
  544. This->host_time.flagsForTimeCode = ~(0x3);
  545. }
  546. This->host_callbacks->swapBuffersWithTimeInfo(&This->host_time, This->host_buffer_index, 1);
  547. }
  548. else
  549. { /* use the old swapBuffers method */
  550. This->host_callbacks->swapBuffers(This->host_buffer_index, 1);
  551. }
  552. /* switch host buffer */
  553. This->host_buffer_index = This->host_buffer_index ? 0 : 1;
  554. This->host_driver_state = Running;
  555. TRACE("WineASIO successfully loaded\n");
  556. return 0;
  557. }
  558. /*
  559. * LONG Stop(void);
  560. * Function: Stop JACK IO processing
  561. * Returns: -1000 on missing IO
  562. * Note: swapBuffers() must not called after returning
  563. */
  564. DEFINE_THISCALL_WRAPPER(Stop,4)
  565. HIDDEN LONG STDMETHODCALLTYPE Stop(LPWINEASIO iface)
  566. {
  567. IWineASIOImpl *This = (IWineASIOImpl*)iface;
  568. TRACE("iface: %p\n", iface);
  569. if (This->host_driver_state != Running)
  570. return -1000;
  571. This->host_driver_state = Prepared;
  572. return 0;
  573. }
  574. /*
  575. * LONG GetChannels(LONG *numInputChannels, LONG *numOutputChannels);
  576. * Function: Report number of IO channels
  577. * Parameters: numInputChannels and numOutputChannels will hold number of channels on returning
  578. * Returns: -1000 if no channels are available, otherwise AES_OK
  579. */
  580. DEFINE_THISCALL_WRAPPER(GetChannels,12)
  581. HIDDEN LONG STDMETHODCALLTYPE GetChannels (LPWINEASIO iface, LONG *numInputChannels, LONG *numOutputChannels)
  582. {
  583. IWineASIOImpl *This = (IWineASIOImpl*)iface;
  584. if (!numInputChannels || !numOutputChannels)
  585. return -998;
  586. *numInputChannels = This->wineasio_number_inputs;
  587. *numOutputChannels = This->wineasio_number_outputs;
  588. TRACE("iface: %p, inputs: %i, outputs: %i\n", iface, This->wineasio_number_inputs, This->wineasio_number_outputs);
  589. return 0;
  590. }
  591. /*
  592. * LONG GetLatencies(LONG *inputLatency, LONG *outputLatency);
  593. * Function: Return latency in frames
  594. * Returns: -1000 if no IO is available, otherwise AES_OK
  595. */
  596. DEFINE_THISCALL_WRAPPER(GetLatencies,12)
  597. HIDDEN LONG STDMETHODCALLTYPE GetLatencies(LPWINEASIO iface, LONG *inputLatency, LONG *outputLatency)
  598. {
  599. IWineASIOImpl *This = (IWineASIOImpl*)iface;
  600. jack_latency_range_t range;
  601. if (!inputLatency || !outputLatency)
  602. return -998;
  603. if (This->host_driver_state == Loaded)
  604. return -1000;
  605. jackbridge_port_get_latency_range(This->input_channel[0].port, JackCaptureLatency, &range);
  606. *inputLatency = range.max;
  607. jackbridge_port_get_latency_range(This->output_channel[0].port, JackPlaybackLatency, &range);
  608. *outputLatency = range.max;
  609. TRACE("iface: %p, input latency: %d, output latency: %d\n", iface, (int)*inputLatency, (int)*outputLatency);
  610. return 0;
  611. }
  612. /*
  613. * LONG GetBufferSize(LONG *minSize, LONG *maxSize, LONG *preferredSize, LONG *granularity);
  614. * Function: Return minimum, maximum, preferred buffer sizes, and granularity
  615. * At the moment return all the same, and granularity 0
  616. * Returns: -1000 on missing IO
  617. */
  618. DEFINE_THISCALL_WRAPPER(GetBufferSize,20)
  619. HIDDEN LONG STDMETHODCALLTYPE GetBufferSize(LPWINEASIO iface, LONG *minSize, LONG *maxSize, LONG *preferredSize, LONG *granularity)
  620. {
  621. IWineASIOImpl *This = (IWineASIOImpl*)iface;
  622. TRACE("iface: %p, minSize: %p, maxSize: %p, preferredSize: %p, granularity: %p\n", iface, minSize, maxSize, preferredSize, granularity);
  623. if (!minSize || !maxSize || !preferredSize || !granularity)
  624. return -998;
  625. if (This->wineasio_fixed_buffersize)
  626. {
  627. *minSize = *maxSize = *preferredSize = This->host_current_buffersize;
  628. *granularity = 0;
  629. TRACE("Buffersize fixed at %d\n", (int)This->host_current_buffersize);
  630. return 0;
  631. }
  632. *minSize = WINEASIO_MINIMUM_BUFFERSIZE;
  633. *maxSize = WINEASIO_MAXIMUM_BUFFERSIZE;
  634. *preferredSize = This->wineasio_preferred_buffersize;
  635. *granularity = -1;
  636. TRACE("The host can control buffersize\nMinimum: %d, maximum: %d, preferred: %d, granularity: %d, current: %d\n",
  637. (int)*minSize, (int)*maxSize, (int)*preferredSize, (int)*granularity, (int)This->host_current_buffersize);
  638. return 0;
  639. }
  640. /*
  641. * LONG CanSampleRate(double sampleRate);
  642. * Function: Ask if specific SR is available
  643. * Returns: -995 if SR isn't available, -1000 on missing IO
  644. */
  645. DEFINE_THISCALL_WRAPPER(CanSampleRate,12)
  646. HIDDEN LONG STDMETHODCALLTYPE CanSampleRate(LPWINEASIO iface, double sampleRate)
  647. {
  648. IWineASIOImpl *This = (IWineASIOImpl*)iface;
  649. TRACE("iface: %p, Samplerate = %li, requested samplerate = %li\n", iface, (long) This->host_sample_rate, (long) sampleRate);
  650. if (sampleRate != This->host_sample_rate)
  651. return -995;
  652. return 0;
  653. }
  654. /*
  655. * LONG GetSampleRate(double *currentRate);
  656. * Function: Return current SR
  657. * Parameters: currentRate will hold SR on return, 0 if unknown
  658. * Returns: -995 if SR is unknown, -1000 on missing IO
  659. */
  660. DEFINE_THISCALL_WRAPPER(GetSampleRate,8)
  661. HIDDEN LONG STDMETHODCALLTYPE GetSampleRate(LPWINEASIO iface, double *sampleRate)
  662. {
  663. IWineASIOImpl *This = (IWineASIOImpl*)iface;
  664. TRACE("iface: %p, Sample rate is %i\n", iface, (int) This->host_sample_rate);
  665. if (!sampleRate)
  666. return -998;
  667. *sampleRate = This->host_sample_rate;
  668. return 0;
  669. }
  670. /*
  671. * LONG SetSampleRate(double sampleRate);
  672. * Function: Set requested SR, enable external sync if SR == 0
  673. * Returns: -995 if unknown SR
  674. * -997 if current clock is external and SR != 0
  675. * -1000 on missing IO
  676. */
  677. DEFINE_THISCALL_WRAPPER(SetSampleRate,12)
  678. HIDDEN LONG STDMETHODCALLTYPE SetSampleRate(LPWINEASIO iface, double sampleRate)
  679. {
  680. IWineASIOImpl *This = (IWineASIOImpl*)iface;
  681. TRACE("iface: %p, Sample rate %f requested\n", iface, sampleRate);
  682. if (sampleRate != This->host_sample_rate)
  683. return -995;
  684. return 0;
  685. }
  686. /*
  687. * LONG GetClockSources(void *clocks, LONG *numSources);
  688. * Function: Return available clock sources
  689. * Parameters: clocks - a pointer to an array of clock source structures.
  690. * numSources - when called: number of allocated members
  691. * - on return: number of clock sources, the minimum is 1 - the internal clock
  692. * Returns: -1000 on missing IO
  693. */
  694. DEFINE_THISCALL_WRAPPER(GetClockSources,12)
  695. HIDDEN LONG STDMETHODCALLTYPE GetClockSources(LPWINEASIO iface, void *clocks, LONG *numSources)
  696. {
  697. LONG *lclocks = (LONG*)clocks;
  698. TRACE("iface: %p, clocks: %p, numSources: %p\n", iface, clocks, numSources);
  699. if (!clocks || !numSources)
  700. return -998;
  701. *lclocks++ = 0;
  702. *lclocks++ = -1;
  703. *lclocks++ = -1;
  704. *lclocks++ = 1;
  705. strcpy((char*)lclocks, "Internal");
  706. *numSources = 1;
  707. return 0;
  708. }
  709. /*
  710. * LONG SetClockSource(LONG index);
  711. * Function: Set clock source
  712. * Parameters: index returned by GetClockSources()
  713. * Returns: -1000 on missing IO
  714. * -997 may be returned if a clock can't be selected
  715. * -995 should not be returned
  716. */
  717. DEFINE_THISCALL_WRAPPER(SetClockSource,8)
  718. HIDDEN LONG STDMETHODCALLTYPE SetClockSource(LPWINEASIO iface, LONG index)
  719. {
  720. TRACE("iface: %p, index: %d\n", iface, (int)index);
  721. if (index != 0)
  722. return -1000;
  723. return 0;
  724. }
  725. /*
  726. * LONG GetSamplePosition (w_int64_t *sPos, w_int64_t *tStamp);
  727. * Function: Return sample position and timestamp
  728. * Parameters: sPos holds the position on return, reset to 0 on Start()
  729. * tStamp holds the system time of sPos
  730. * Return: -1000 on missing IO
  731. * -996 on missing clock
  732. */
  733. DEFINE_THISCALL_WRAPPER(GetSamplePosition,12)
  734. HIDDEN LONG STDMETHODCALLTYPE GetSamplePosition(LPWINEASIO iface, w_int64_t *sPos, w_int64_t *tStamp)
  735. {
  736. IWineASIOImpl *This = (IWineASIOImpl*)iface;
  737. TRACE("iface: %p, sPos: %p, tStamp: %p\n", iface, sPos, tStamp);
  738. if (!sPos || !tStamp)
  739. return -998;
  740. tStamp->lo = This->host_time_stamp.lo;
  741. tStamp->hi = This->host_time_stamp.hi;
  742. sPos->lo = This->host_num_samples.lo;
  743. sPos->hi = 0; /* FIXME */
  744. return 0;
  745. }
  746. /*
  747. * LONG GetChannelInfo (void *info);
  748. * Function: Retrive channel info
  749. * Returns: -1000 on missing IO
  750. */
  751. DEFINE_THISCALL_WRAPPER(GetChannelInfo,8)
  752. HIDDEN LONG STDMETHODCALLTYPE GetChannelInfo(LPWINEASIO iface, void *info)
  753. {
  754. IWineASIOImpl *This = (IWineASIOImpl*)iface;
  755. LONG *linfo = (LONG*)info;
  756. const LONG channelNumber = *linfo++;
  757. const LONG isInputType = *linfo++;
  758. /* TRACE("(iface: %p, info: %p\n", iface, info); */
  759. if (channelNumber < 0 || (isInputType ? channelNumber >= This->wineasio_number_inputs : channelNumber >= This->wineasio_number_outputs))
  760. return -998;
  761. *linfo++ = (isInputType ? This->input_channel : This->output_channel)[channelNumber].active;
  762. *linfo++ = 0;
  763. *linfo++ = 19;
  764. memcpy(linfo, (isInputType ? This->input_channel : This->output_channel)[channelNumber].port_name, WINEASIO_MAX_NAME_LENGTH);
  765. return 0;
  766. }
  767. /*
  768. * LONG CreateBuffers(BufferInformation *bufferInfo, LONG numChannels, LONG bufferSize, Callbacks *callbacks);
  769. * Function: Allocate buffers for IO channels
  770. * Parameters: bufferInfo - pointer to an array of BufferInformation structures
  771. * numChannels - the total number of IO channels to be allocated
  772. * bufferSize - one of the buffer sizes retrieved with GetBufferSize()
  773. * callbacks - pointer to a Callbacks structure
  774. * Returns: -994 if impossible to allocate enough memory
  775. * -997 on unsupported bufferSize or invalid bufferInfo data
  776. * -1000 on missing IO
  777. */
  778. DEFINE_THISCALL_WRAPPER(CreateBuffers,20)
  779. HIDDEN LONG STDMETHODCALLTYPE CreateBuffers(LPWINEASIO iface, BufferInformation *bufferInfo, LONG numChannels, LONG bufferSize, Callbacks *callbacks)
  780. {
  781. IWineASIOImpl *This = (IWineASIOImpl*)iface;
  782. BufferInformation *bufferInfoPerChannel = bufferInfo;
  783. int i, j, k;
  784. TRACE("iface: %p, bufferInfo: %p, numChannels: %d, bufferSize: %d, callbacks: %p\n", iface, bufferInfo, (int)numChannels, (int)bufferSize, callbacks);
  785. if (This->host_driver_state != Initialized)
  786. return -1000;
  787. if (!bufferInfo || !callbacks)
  788. return -997;
  789. /* Check for invalid channel numbers */
  790. for (i = j = k = 0; i < numChannels; i++, bufferInfoPerChannel++)
  791. {
  792. if (bufferInfoPerChannel->isInputType)
  793. {
  794. if (j++ >= This->wineasio_number_inputs)
  795. {
  796. WARN("Invalid input channel requested\n");
  797. return -997;
  798. }
  799. }
  800. else
  801. {
  802. if (k++ >= This->wineasio_number_outputs)
  803. {
  804. WARN("Invalid output channel requested\n");
  805. return -997;
  806. }
  807. }
  808. }
  809. /* set buf_size */
  810. if (This->wineasio_fixed_buffersize)
  811. {
  812. if (This->host_current_buffersize != bufferSize)
  813. return -997;
  814. TRACE("Buffersize fixed at %d\n", (int)This->host_current_buffersize);
  815. }
  816. else
  817. { /* fail if not a power of two and if out of range */
  818. if (!(bufferSize > 0 && !(bufferSize&(bufferSize-1))
  819. && bufferSize >= WINEASIO_MINIMUM_BUFFERSIZE
  820. && bufferSize <= WINEASIO_MAXIMUM_BUFFERSIZE))
  821. {
  822. WARN("Invalid buffersize %d requested\n", (int)bufferSize);
  823. return -997;
  824. }
  825. else
  826. {
  827. if (This->host_current_buffersize == bufferSize)
  828. {
  829. TRACE("Buffer size already set to %d\n", (int)This->host_current_buffersize);
  830. }
  831. else
  832. {
  833. This->host_current_buffersize = bufferSize;
  834. if (jackbridge_set_buffer_size(This->jack_client, This->host_current_buffersize))
  835. {
  836. WARN("JACK is unable to set buffersize to %d\n", (int)This->host_current_buffersize);
  837. return -999;
  838. }
  839. TRACE("Buffer size changed to %d\n", (int)This->host_current_buffersize);
  840. }
  841. }
  842. }
  843. This->host_callbacks = callbacks;
  844. This->host_time_info_mode = This->host_can_time_code = FALSE;
  845. if (This->host_callbacks->sendNotification(7, 0, 0, 0))
  846. {
  847. This->host_time_info_mode = TRUE;
  848. if (This->host_callbacks->sendNotification(8, 0, 0, 0))
  849. This->host_can_time_code = TRUE;
  850. }
  851. /* Allocate audio buffers */
  852. This->callback_audio_buffer = HeapAlloc(GetProcessHeap(), 0,
  853. (This->wineasio_number_inputs + This->wineasio_number_outputs) * 2 * This->host_current_buffersize * sizeof(jack_default_audio_sample_t));
  854. if (!This->callback_audio_buffer)
  855. {
  856. ERR("Unable to allocate %i audio buffers\n", This->wineasio_number_inputs + This->wineasio_number_outputs);
  857. return -994;
  858. }
  859. TRACE("%i audio buffers allocated (%i kB)\n", This->wineasio_number_inputs + This->wineasio_number_outputs,
  860. (int) ((This->wineasio_number_inputs + This->wineasio_number_outputs) * 2 * This->host_current_buffersize * sizeof(jack_default_audio_sample_t) / 1024));
  861. for (i = 0; i < This->wineasio_number_inputs; i++)
  862. This->input_channel[i].audio_buffer = This->callback_audio_buffer + (i * 2 * This->host_current_buffersize);
  863. for (i = 0; i < This->wineasio_number_outputs; i++)
  864. This->output_channel[i].audio_buffer = This->callback_audio_buffer + ((This->wineasio_number_inputs + i) * 2 * This->host_current_buffersize);
  865. /* initialize BufferInformation structures */
  866. bufferInfoPerChannel = bufferInfo;
  867. This->host_active_inputs = This->host_active_outputs = 0;
  868. for (i = 0; i < This->wineasio_number_inputs; i++) {
  869. This->input_channel[i].active = false;
  870. }
  871. for (i = 0; i < This->wineasio_number_outputs; i++) {
  872. This->output_channel[i].active = false;
  873. }
  874. for (i = 0; i < numChannels; i++, bufferInfoPerChannel++)
  875. {
  876. if (bufferInfoPerChannel->isInputType)
  877. {
  878. bufferInfoPerChannel->audioBufferStart = &This->input_channel[bufferInfoPerChannel->channelNumber].audio_buffer[0];
  879. bufferInfoPerChannel->audioBufferEnd = &This->input_channel[bufferInfoPerChannel->channelNumber].audio_buffer[This->host_current_buffersize];
  880. This->input_channel[bufferInfoPerChannel->channelNumber].active = true;
  881. This->host_active_inputs++;
  882. /* TRACE("ASIO audio buffer for channel %i as input %li created\n", i, This->host_active_inputs); */
  883. }
  884. else
  885. {
  886. bufferInfoPerChannel->audioBufferStart = &This->output_channel[bufferInfoPerChannel->channelNumber].audio_buffer[0];
  887. bufferInfoPerChannel->audioBufferEnd = &This->output_channel[bufferInfoPerChannel->channelNumber].audio_buffer[This->host_current_buffersize];
  888. This->output_channel[bufferInfoPerChannel->channelNumber].active = true;
  889. This->host_active_outputs++;
  890. /* TRACE("ASIO audio buffer for channel %i as output %li created\n", i, This->host_active_outputs); */
  891. }
  892. }
  893. TRACE("%d audio channels initialized\n", (int)(This->host_active_inputs + This->host_active_outputs));
  894. if (!jackbridge_activate(This->jack_client))
  895. return -1000;
  896. /* connect to the hardware io */
  897. if (This->wineasio_connect_to_hardware)
  898. {
  899. for (i = 0; i < This->jack_num_input_ports && i < This->wineasio_number_inputs; i++)
  900. if (strstr(jackbridge_port_type(jackbridge_port_by_name(This->jack_client, This->jack_input_ports[i])), "audio"))
  901. jackbridge_connect(This->jack_client, This->jack_input_ports[i], jackbridge_port_name(This->input_channel[i].port));
  902. for (i = 0; i < This->jack_num_output_ports && i < This->wineasio_number_outputs; i++)
  903. if (strstr(jackbridge_port_type(jackbridge_port_by_name(This->jack_client, This->jack_output_ports[i])), "audio"))
  904. jackbridge_connect(This->jack_client, jackbridge_port_name(This->output_channel[i].port), This->jack_output_ports[i]);
  905. }
  906. /* at this point all the connections are made and the jack process callback is outputting silence */
  907. This->host_driver_state = Prepared;
  908. return 0;
  909. }
  910. /*
  911. * LONG DisposeBuffers(void);
  912. * Function: Release allocated buffers
  913. * Returns: -997 if no buffers were previously allocated
  914. * -1000 on missing IO
  915. * Implies: Stop()
  916. */
  917. DEFINE_THISCALL_WRAPPER(DisposeBuffers,4)
  918. HIDDEN LONG STDMETHODCALLTYPE DisposeBuffers(LPWINEASIO iface)
  919. {
  920. IWineASIOImpl *This = (IWineASIOImpl*)iface;
  921. int i;
  922. TRACE("iface: %p\n", iface);
  923. if (This->host_driver_state == Running)
  924. Stop (iface);
  925. if (This->host_driver_state != Prepared)
  926. return -1000;
  927. if (!jackbridge_deactivate(This->jack_client))
  928. return -1000;
  929. This->host_callbacks = NULL;
  930. for (i = 0; i < This->wineasio_number_inputs; i++)
  931. {
  932. This->input_channel[i].audio_buffer = NULL;
  933. This->input_channel[i].active = false;
  934. }
  935. for (i = 0; i < This->wineasio_number_outputs; i++)
  936. {
  937. This->output_channel[i].audio_buffer = NULL;
  938. This->output_channel[i].active = false;
  939. }
  940. This->host_active_inputs = This->host_active_outputs = 0;
  941. if (This->callback_audio_buffer)
  942. HeapFree(GetProcessHeap(), 0, This->callback_audio_buffer);
  943. This->host_driver_state = Initialized;
  944. return 0;
  945. }
  946. /*
  947. * LONG ControlPanel(void);
  948. * Function: Open a control panel for driver settings
  949. * Returns: -1000 if no control panel exists. Actually return code should be ignored
  950. * Note: Call sendNotification if something has changed
  951. */
  952. DEFINE_THISCALL_WRAPPER(ControlPanel,4)
  953. HIDDEN LONG STDMETHODCALLTYPE ControlPanel(LPWINEASIO iface)
  954. {
  955. static char arg0[] = "wineasio-settings\0";
  956. static char *arg_list[] = { arg0, NULL };
  957. TRACE("iface: %p\n", iface);
  958. if (vfork() == 0)
  959. {
  960. execvp (arg0, arg_list);
  961. _exit(1);
  962. }
  963. return 0;
  964. }
  965. /*
  966. * LONG Future(LONG selector, void *opt);
  967. * Function: Various
  968. * Returns: Depends on the selector but in general -998 on invalid selector
  969. * -998 if function is unsupported to disable further calls
  970. * 0x3f4847a0 on success, do not use 0
  971. */
  972. DEFINE_THISCALL_WRAPPER(Future,12)
  973. HIDDEN LONG STDMETHODCALLTYPE Future(LPWINEASIO iface, LONG selector, void *opt)
  974. {
  975. IWineASIOImpl *This = (IWineASIOImpl *) iface;
  976. TRACE("iface: %p, selector: %d, opt: %p\n", iface, (int)selector, opt);
  977. switch (selector)
  978. {
  979. case 1:
  980. This->host_can_time_code = TRUE;
  981. TRACE("The host enabled TimeCode\n");
  982. return 0x3f4847a0;
  983. case 2:
  984. This->host_can_time_code = FALSE;
  985. TRACE("The host disabled TimeCode\n");
  986. return 0x3f4847a0;
  987. case 3:
  988. TRACE("The driver denied request to set input monitor\n");
  989. return -1000;
  990. case 4:
  991. TRACE("The driver denied request for Transport control\n");
  992. return -998;
  993. case 5:
  994. TRACE("The driver denied request to set input gain\n");
  995. return -998;
  996. case 6:
  997. TRACE("The driver denied request to get input meter \n");
  998. return -998;
  999. case 7:
  1000. TRACE("The driver denied request to set output gain\n");
  1001. return -998;
  1002. case 8:
  1003. TRACE("The driver denied request to get output meter\n");
  1004. return -998;
  1005. case 9:
  1006. TRACE("The driver does not support input monitor\n");
  1007. return -998;
  1008. case 10:
  1009. TRACE("The driver supports TimeInfo\n");
  1010. return 0x3f4847a0;
  1011. case 11:
  1012. TRACE("The driver supports TimeCode\n");
  1013. return 0x3f4847a0;
  1014. case 12:
  1015. TRACE("The driver denied request for Transport\n");
  1016. return -998;
  1017. case 13:
  1018. TRACE("The driver does not support input gain\n");
  1019. return -998;
  1020. case 14:
  1021. TRACE("The driver does not support input meter\n");
  1022. return -998;
  1023. case 15:
  1024. TRACE("The driver does not support output gain\n");
  1025. return -998;
  1026. case 16:
  1027. TRACE("The driver does not support output meter\n");
  1028. return -998;
  1029. case 0x23111961:
  1030. TRACE("The driver denied request to set DSD IO format\n");
  1031. return -1000;
  1032. case 0x23111983:
  1033. TRACE("The driver denied request to get DSD IO format\n");
  1034. return -1000;
  1035. case 0x23112004:
  1036. TRACE("The driver does not support DSD IO format\n");
  1037. return -1000;
  1038. default:
  1039. TRACE("ASIOFuture() called with undocumented selector\n");
  1040. return -998;
  1041. }
  1042. }
  1043. /*
  1044. * LONG OutputReady(void);
  1045. * Function: Tells the driver that output bufffers are ready
  1046. * Returns: 0 if supported
  1047. * -1000 to disable
  1048. */
  1049. DEFINE_THISCALL_WRAPPER(OutputReady,4)
  1050. HIDDEN LONG STDMETHODCALLTYPE OutputReady(LPWINEASIO iface)
  1051. {
  1052. /* disabled to stop stand alone NI programs from spamming the console
  1053. TRACE("iface: %p\n", iface); */
  1054. return -1000;
  1055. }
  1056. /****************************************************************************
  1057. * JACK callbacks
  1058. */
  1059. static inline int jack_buffer_size_callback(jack_nframes_t nframes, void *arg)
  1060. {
  1061. IWineASIOImpl *This = (IWineASIOImpl*)arg;
  1062. if(This->host_driver_state != Running)
  1063. return 0;
  1064. if (This->host_callbacks->sendNotification(1, 3, 0, 0))
  1065. This->host_callbacks->sendNotification(3, 0, 0, 0);
  1066. return 0;
  1067. }
  1068. static inline void jack_latency_callback(jack_latency_callback_mode_t mode, void *arg)
  1069. {
  1070. IWineASIOImpl *This = (IWineASIOImpl*)arg;
  1071. if(This->host_driver_state != Running)
  1072. return;
  1073. if (This->host_callbacks->sendNotification(1, 6, 0, 0))
  1074. This->host_callbacks->sendNotification(6, 0, 0, 0);
  1075. return;
  1076. }
  1077. static inline int jack_process_callback(jack_nframes_t nframes, void *arg)
  1078. {
  1079. IWineASIOImpl *This = (IWineASIOImpl*)arg;
  1080. int i;
  1081. jack_transport_state_t jack_transport_state;
  1082. jack_position_t jack_position;
  1083. DWORD time;
  1084. /* output silence if the host callback isn't running yet */
  1085. if (This->host_driver_state != Running)
  1086. {
  1087. for (i = 0; i < This->host_active_outputs; i++)
  1088. memset(jackbridge_port_get_buffer(This->output_channel[i].port, nframes),
  1089. 0, sizeof (jack_default_audio_sample_t) * nframes);
  1090. return 0;
  1091. }
  1092. /* copy jack to host buffers */
  1093. for (i = 0; i < This->wineasio_number_inputs; i++)
  1094. if (This->input_channel[i].active)
  1095. memcpy (&This->input_channel[i].audio_buffer[nframes * This->host_buffer_index],
  1096. jackbridge_port_get_buffer(This->input_channel[i].port, nframes),
  1097. sizeof (jack_default_audio_sample_t) * nframes);
  1098. if (This->host_num_samples.lo > ULONG_MAX - nframes)
  1099. This->host_num_samples.hi++;
  1100. This->host_num_samples.lo += nframes;
  1101. time = timeGetTime();
  1102. This->host_time_stamp.lo = time * 1000000;
  1103. This->host_time_stamp.hi = ((unsigned long long) time * 1000000) >> 32;
  1104. if (This->host_time_info_mode) /* use the newer swapBuffersWithTimeInfo method if supported */
  1105. {
  1106. This->host_time.numSamples.lo = This->host_num_samples.lo;
  1107. This->host_time.numSamples.hi = This->host_num_samples.hi;
  1108. This->host_time.timeStamp.lo = This->host_time_stamp.lo;
  1109. This->host_time.timeStamp.hi = This->host_time_stamp.hi;
  1110. This->host_time.sampleRate = This->host_sample_rate;
  1111. This->host_time.flags = 0x7;
  1112. if (This->host_can_time_code) /* FIXME addionally use time code if supported */
  1113. {
  1114. jack_transport_state = jackbridge_transport_query(This->jack_client, &jack_position);
  1115. This->host_time.flagsForTimeCode = 0x1;
  1116. if (jack_transport_state == JackTransportRolling)
  1117. This->host_time.flagsForTimeCode |= 0x2;
  1118. }
  1119. This->host_callbacks->swapBuffersWithTimeInfo(&This->host_time, This->host_buffer_index, 1);
  1120. }
  1121. else
  1122. { /* use the old swapBuffers method */
  1123. This->host_callbacks->swapBuffers(This->host_buffer_index, 1);
  1124. }
  1125. /* copy host to jack buffers */
  1126. for (i = 0; i < This->wineasio_number_outputs; i++)
  1127. if (This->output_channel[i].active)
  1128. memcpy(jackbridge_port_get_buffer(This->output_channel[i].port, nframes),
  1129. &This->output_channel[i].audio_buffer[nframes * This->host_buffer_index],
  1130. sizeof (jack_default_audio_sample_t) * nframes);
  1131. /* switch host buffer */
  1132. This->host_buffer_index = This->host_buffer_index ? 0 : 1;
  1133. return 0;
  1134. }
  1135. static inline int jack_sample_rate_callback(jack_nframes_t nframes, void *arg)
  1136. {
  1137. IWineASIOImpl *This = (IWineASIOImpl*)arg;
  1138. if(This->host_driver_state != Running)
  1139. return 0;
  1140. This->host_sample_rate = nframes;
  1141. This->host_callbacks->sampleRateChanged(nframes);
  1142. return 0;
  1143. }
  1144. /*****************************************************************************
  1145. * Support functions
  1146. */
  1147. #ifndef WINE_WITH_UNICODE
  1148. /* Funtion required as unicode.h no longer in WINE */
  1149. static WCHAR *strrchrW(const WCHAR* str, WCHAR ch)
  1150. {
  1151. WCHAR *ret = NULL;
  1152. do { if (*str == ch) ret = (WCHAR *)(ULONG_PTR)str; } while (*str++);
  1153. return ret;
  1154. }
  1155. #endif
  1156. /* Function called by JACK to create a thread in the wine process context,
  1157. * uses the global structure jack_thread_creator_privates to communicate with jack_thread_creator_helper() */
  1158. static int jack_thread_creator(pthread_t* thread_id, const pthread_attr_t* attr, void *(*function)(void*), void* arg)
  1159. {
  1160. TRACE("arg: %p, thread_id: %p, attr: %p, function: %p\n", arg, thread_id, attr, function);
  1161. jack_thread_creator_privates.jack_callback_thread = function;
  1162. jack_thread_creator_privates.arg = arg;
  1163. jack_thread_creator_privates.jack_callback_thread_created = CreateEventW(NULL, FALSE, FALSE, NULL);
  1164. CreateThread( NULL, 0, jack_thread_creator_helper, arg, 0,0 );
  1165. WaitForSingleObject(jack_thread_creator_privates.jack_callback_thread_created, INFINITE);
  1166. *thread_id = jack_thread_creator_privates.jack_callback_pthread_id;
  1167. return 0;
  1168. }
  1169. /* internal helper function for returning the posix thread_id of the newly created callback thread */
  1170. static DWORD WINAPI jack_thread_creator_helper(LPVOID arg)
  1171. {
  1172. TRACE("arg: %p\n", arg);
  1173. jack_thread_creator_privates.jack_callback_pthread_id = pthread_self();
  1174. SetEvent(jack_thread_creator_privates.jack_callback_thread_created);
  1175. jack_thread_creator_privates.jack_callback_thread(jack_thread_creator_privates.arg);
  1176. return 0;
  1177. }
  1178. static VOID configure_driver(IWineASIOImpl *This)
  1179. {
  1180. HKEY hkey;
  1181. LONG result, value;
  1182. DWORD type, size;
  1183. WCHAR application_path [MAX_PATH];
  1184. WCHAR *application_name;
  1185. char environment_variable[MAX_ENVIRONMENT_SIZE];
  1186. /* Unicode strings used for the registry */
  1187. static const WCHAR key_software_wine_wineasio[] =
  1188. { 'S','o','f','t','w','a','r','e','\\',
  1189. 'W','i','n','e','\\',
  1190. 'W','i','n','e','A','S','I','O',0 };
  1191. static const WCHAR value_wineasio_number_inputs[] =
  1192. { 'N','u','m','b','e','r',' ','o','f',' ','i','n','p','u','t','s',0 };
  1193. static const WCHAR value_wineasio_number_outputs[] =
  1194. { 'N','u','m','b','e','r',' ','o','f',' ','o','u','t','p','u','t','s',0 };
  1195. static const WCHAR value_wineasio_fixed_buffersize[] =
  1196. { 'F','i','x','e','d',' ','b','u','f','f','e','r','s','i','z','e',0 };
  1197. static const WCHAR value_wineasio_preferred_buffersize[] =
  1198. { 'P','r','e','f','e','r','r','e','d',' ','b','u','f','f','e','r','s','i','z','e',0 };
  1199. static const WCHAR wineasio_autostart_server[] =
  1200. { 'A','u','t','o','s','t','a','r','t',' ','s','e','r','v','e','r',0 };
  1201. static const WCHAR value_wineasio_connect_to_hardware[] =
  1202. { 'C','o','n','n','e','c','t',' ','t','o',' ','h','a','r','d','w','a','r','e',0 };
  1203. /* Initialise most member variables,
  1204. * host_num_samples, host_time, & host_time_stamp are initialized in Start()
  1205. * jack_num_input_ports & jack_num_output_ports are initialized in Init() */
  1206. This->host_active_inputs = 0;
  1207. This->host_active_outputs = 0;
  1208. This->host_buffer_index = 0;
  1209. This->host_callbacks = NULL;
  1210. This->host_can_time_code = FALSE;
  1211. This->host_current_buffersize = 0;
  1212. This->host_driver_state = Loaded;
  1213. This->host_sample_rate = 0;
  1214. This->host_time_info_mode = FALSE;
  1215. This->host_version = 92;
  1216. This->wineasio_number_inputs = 16;
  1217. This->wineasio_number_outputs = 16;
  1218. This->wineasio_autostart_server = FALSE;
  1219. This->wineasio_connect_to_hardware = TRUE;
  1220. This->wineasio_fixed_buffersize = TRUE;
  1221. This->wineasio_preferred_buffersize = WINEASIO_PREFERRED_BUFFERSIZE;
  1222. This->jack_client = NULL;
  1223. This->jack_client_name[0] = 0;
  1224. This->jack_input_ports = NULL;
  1225. This->jack_output_ports = NULL;
  1226. This->callback_audio_buffer = NULL;
  1227. This->input_channel = NULL;
  1228. This->output_channel = NULL;
  1229. /* create registry entries with defaults if not present */
  1230. result = RegCreateKeyExW(HKEY_CURRENT_USER, key_software_wine_wineasio, 0, NULL, 0, KEY_ALL_ACCESS, NULL, &hkey, NULL);
  1231. /* get/set number of wineasio inputs */
  1232. size = sizeof(DWORD);
  1233. if (RegQueryValueExW(hkey, value_wineasio_number_inputs, NULL, &type, (LPBYTE) &value, &size) == ERROR_SUCCESS)
  1234. {
  1235. if (type == REG_DWORD)
  1236. This->wineasio_number_inputs = value;
  1237. }
  1238. else
  1239. {
  1240. type = REG_DWORD;
  1241. size = sizeof(DWORD);
  1242. value = This->wineasio_number_inputs;
  1243. result = RegSetValueExW(hkey, value_wineasio_number_inputs, 0, REG_DWORD, (LPBYTE) &value, size);
  1244. }
  1245. /* get/set number of wineasio outputs */
  1246. size = sizeof(DWORD);
  1247. if (RegQueryValueExW(hkey, value_wineasio_number_outputs, NULL, &type, (LPBYTE) &value, &size) == ERROR_SUCCESS)
  1248. {
  1249. if (type == REG_DWORD)
  1250. This->wineasio_number_outputs = value;
  1251. }
  1252. else
  1253. {
  1254. type = REG_DWORD;
  1255. size = sizeof(DWORD);
  1256. value = This->wineasio_number_outputs;
  1257. result = RegSetValueExW(hkey, value_wineasio_number_outputs, 0, REG_DWORD, (LPBYTE) &value, size);
  1258. }
  1259. /* allow changing of wineasio buffer sizes */
  1260. size = sizeof(DWORD);
  1261. if (RegQueryValueExW(hkey, value_wineasio_fixed_buffersize, NULL, &type, (LPBYTE) &value, &size) == ERROR_SUCCESS)
  1262. {
  1263. if (type == REG_DWORD)
  1264. This->wineasio_fixed_buffersize = value;
  1265. }
  1266. else
  1267. {
  1268. type = REG_DWORD;
  1269. size = sizeof(DWORD);
  1270. value = This->wineasio_fixed_buffersize;
  1271. result = RegSetValueExW(hkey, value_wineasio_fixed_buffersize, 0, REG_DWORD, (LPBYTE) &value, size);
  1272. }
  1273. /* preferred buffer size (if changing buffersize is allowed) */
  1274. size = sizeof(DWORD);
  1275. if (RegQueryValueExW(hkey, value_wineasio_preferred_buffersize, NULL, &type, (LPBYTE) &value, &size) == ERROR_SUCCESS)
  1276. {
  1277. if (type == REG_DWORD)
  1278. This->wineasio_preferred_buffersize = value;
  1279. }
  1280. else
  1281. {
  1282. type = REG_DWORD;
  1283. size = sizeof(DWORD);
  1284. value = This->wineasio_preferred_buffersize;
  1285. result = RegSetValueExW(hkey, value_wineasio_preferred_buffersize, 0, REG_DWORD, (LPBYTE) &value, size);
  1286. }
  1287. /* get/set JACK autostart */
  1288. size = sizeof(DWORD);
  1289. if (RegQueryValueExW(hkey, wineasio_autostart_server, NULL, &type, (LPBYTE) &value, &size) == ERROR_SUCCESS)
  1290. {
  1291. if (type == REG_DWORD)
  1292. This->wineasio_autostart_server = value;
  1293. }
  1294. else
  1295. {
  1296. type = REG_DWORD;
  1297. size = sizeof(DWORD);
  1298. value = This->wineasio_autostart_server;
  1299. result = RegSetValueExW(hkey, wineasio_autostart_server, 0, REG_DWORD, (LPBYTE) &value, size);
  1300. }
  1301. /* get/set JACK connect to physical io */
  1302. size = sizeof(DWORD);
  1303. if (RegQueryValueExW(hkey, value_wineasio_connect_to_hardware, NULL, &type, (LPBYTE) &value, &size) == ERROR_SUCCESS)
  1304. {
  1305. if (type == REG_DWORD)
  1306. This->wineasio_connect_to_hardware = value;
  1307. }
  1308. else
  1309. {
  1310. type = REG_DWORD;
  1311. size = sizeof(DWORD);
  1312. value = This->wineasio_connect_to_hardware;
  1313. result = RegSetValueExW(hkey, value_wineasio_connect_to_hardware, 0, REG_DWORD, (LPBYTE) &value, size);
  1314. }
  1315. /* get client name by stripping path and extension */
  1316. GetModuleFileNameW(0, application_path, MAX_PATH);
  1317. application_name = strrchrW(application_path, L'.');
  1318. *application_name = 0;
  1319. application_name = strrchrW(application_path, L'\\');
  1320. application_name++;
  1321. WideCharToMultiByte(CP_ACP, WC_SEPCHARS, application_name, -1, This->jack_client_name, WINEASIO_MAX_NAME_LENGTH, NULL, NULL);
  1322. RegCloseKey(hkey);
  1323. /* Look for environment variables to override registry config values */
  1324. if (GetEnvironmentVariableA("WINEASIO_NUMBER_INPUTS", environment_variable, MAX_ENVIRONMENT_SIZE))
  1325. {
  1326. errno = 0;
  1327. result = strtol(environment_variable, 0, 10);
  1328. if (errno != ERANGE)
  1329. This->wineasio_number_inputs = result;
  1330. }
  1331. if (GetEnvironmentVariableA("WINEASIO_NUMBER_OUTPUTS", environment_variable, MAX_ENVIRONMENT_SIZE))
  1332. {
  1333. errno = 0;
  1334. result = strtol(environment_variable, 0, 10);
  1335. if (errno != ERANGE)
  1336. This->wineasio_number_outputs = result;
  1337. }
  1338. if (GetEnvironmentVariableA("WINEASIO_AUTOSTART_SERVER", environment_variable, MAX_ENVIRONMENT_SIZE))
  1339. {
  1340. if (!strcasecmp(environment_variable, "on"))
  1341. This->wineasio_autostart_server = TRUE;
  1342. else if (!strcasecmp(environment_variable, "off"))
  1343. This->wineasio_autostart_server = FALSE;
  1344. }
  1345. if (GetEnvironmentVariableA("WINEASIO_CONNECT_TO_HARDWARE", environment_variable, MAX_ENVIRONMENT_SIZE))
  1346. {
  1347. if (!strcasecmp(environment_variable, "on"))
  1348. This->wineasio_connect_to_hardware = TRUE;
  1349. else if (!strcasecmp(environment_variable, "off"))
  1350. This->wineasio_connect_to_hardware = FALSE;
  1351. }
  1352. if (GetEnvironmentVariableA("WINEASIO_FIXED_BUFFERSIZE", environment_variable, MAX_ENVIRONMENT_SIZE))
  1353. {
  1354. if (!strcasecmp(environment_variable, "on"))
  1355. This->wineasio_fixed_buffersize = TRUE;
  1356. else if (!strcasecmp(environment_variable, "off"))
  1357. This->wineasio_fixed_buffersize = FALSE;
  1358. }
  1359. if (GetEnvironmentVariableA("WINEASIO_PREFERRED_BUFFERSIZE", environment_variable, MAX_ENVIRONMENT_SIZE))
  1360. {
  1361. errno = 0;
  1362. result = strtol(environment_variable, 0, 10);
  1363. if (errno != ERANGE)
  1364. This->wineasio_preferred_buffersize = result;
  1365. }
  1366. /* over ride the JACK client name gotten from the application name */
  1367. size = GetEnvironmentVariableA("WINEASIO_CLIENT_NAME", environment_variable, WINEASIO_MAX_NAME_LENGTH);
  1368. if (size > 0 && size < WINEASIO_MAX_NAME_LENGTH)
  1369. strcpy(This->jack_client_name, environment_variable);
  1370. /* if wineasio_preferred_buffersize is not a power of two or if out of range, then set to WINEASIO_PREFERRED_BUFFERSIZE */
  1371. if (!(This->wineasio_preferred_buffersize > 0 && !(This->wineasio_preferred_buffersize&(This->wineasio_preferred_buffersize-1))
  1372. && This->wineasio_preferred_buffersize >= WINEASIO_MINIMUM_BUFFERSIZE
  1373. && This->wineasio_preferred_buffersize <= WINEASIO_MAXIMUM_BUFFERSIZE))
  1374. This->wineasio_preferred_buffersize = WINEASIO_PREFERRED_BUFFERSIZE;
  1375. return;
  1376. }
  1377. /* Allocate the interface pointer and associate it with the vtbl/WineASIO object */
  1378. HRESULT WINAPI WineASIOCreateInstance(REFIID riid, LPVOID *ppobj)
  1379. {
  1380. IWineASIOImpl *pobj;
  1381. /* TRACE("riid: %s, ppobj: %p\n", debugstr_guid(riid), ppobj); */
  1382. pobj = HeapAlloc(GetProcessHeap(), 0, sizeof(*pobj));
  1383. if (pobj == NULL)
  1384. {
  1385. WARN("out of memory\n");
  1386. return E_OUTOFMEMORY;
  1387. }
  1388. pobj->lpVtbl = &WineASIO_Vtbl;
  1389. pobj->ref = 1;
  1390. TRACE("pobj = %p\n", pobj);
  1391. *ppobj = pobj;
  1392. /* TRACE("return %p\n", *ppobj); */
  1393. return S_OK;
  1394. }