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.

1633 lines
59KB

  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. #include <jack/jack.h>
  34. #include <jack/thread.h>
  35. #ifdef DEBUG
  36. #include "wine/debug.h"
  37. #else
  38. #define TRACE(...) {}
  39. #define WARN(fmt, ...) {} fprintf(stdout, fmt, ##__VA_ARGS__)
  40. #define ERR(fmt, ...) {} fprintf(stderr, fmt, ##__VA_ARGS__)
  41. #endif
  42. #include "objbase.h"
  43. #include "mmsystem.h"
  44. #include "winreg.h"
  45. #ifdef WINE_WITH_UNICODE
  46. #include "wine/unicode.h"
  47. #endif
  48. #ifdef DEBUG
  49. WINE_DEFAULT_DEBUG_CHANNEL(asio);
  50. #endif
  51. #define MAX_ENVIRONMENT_SIZE 6
  52. #define WINEASIO_MAX_NAME_LENGTH 32
  53. #define WINEASIO_MINIMUM_BUFFERSIZE 16
  54. #define WINEASIO_MAXIMUM_BUFFERSIZE 8192
  55. #define WINEASIO_PREFERRED_BUFFERSIZE 1024
  56. /* ASIO drivers (breaking the COM specification) use the Microsoft variety of
  57. * thiscall calling convention which gcc is unable to produce. These macros
  58. * add an extra layer to fixup the registers. Borrowed from config.h and the
  59. * wine source code.
  60. */
  61. /* From config.h */
  62. #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");
  63. #define __ASM_GLOBAL_FUNC(name,code) __ASM_DEFINE_FUNC(name,"",code)
  64. #define __ASM_NAME(name) name
  65. #define __ASM_STDCALL(args) ""
  66. /* From wine source */
  67. #ifdef __i386__ /* thiscall functions are i386-specific */
  68. #define THISCALL(func) __thiscall_ ## func
  69. #define THISCALL_NAME(func) __ASM_NAME("__thiscall_" #func)
  70. #define __thiscall __stdcall
  71. #define DEFINE_THISCALL_WRAPPER(func,args) \
  72. extern void THISCALL(func)(void); \
  73. __ASM_GLOBAL_FUNC(__thiscall_ ## func, \
  74. "popl %eax\n\t" \
  75. "pushl %ecx\n\t" \
  76. "pushl %eax\n\t" \
  77. "jmp " __ASM_NAME(#func) __ASM_STDCALL(args) )
  78. #else /* __i386__ */
  79. #define THISCALL(func) func
  80. #define THISCALL_NAME(func) __ASM_NAME(#func)
  81. #define __thiscall __stdcall
  82. #define DEFINE_THISCALL_WRAPPER(func,args) /* nothing */
  83. #endif /* __i386__ */
  84. /* Hide ELF symbols for the COM members - No need to to export them */
  85. #define HIDDEN __attribute__ ((visibility("hidden")))
  86. #ifdef _WIN64
  87. #define WINEASIO_CALLBACK CALLBACK
  88. #else
  89. #define WINEASIO_CALLBACK
  90. #endif
  91. typedef struct w_int64_t {
  92. ULONG hi;
  93. ULONG lo;
  94. } w_int64_t;
  95. typedef struct BufferInformation
  96. {
  97. LONG isInputType;
  98. LONG channelNumber;
  99. void *audioBufferStart;
  100. void *audioBufferEnd;
  101. } BufferInformation;
  102. typedef struct TimeInformation
  103. {
  104. LONG _1[4];
  105. double _2;
  106. w_int64_t timeStamp;
  107. w_int64_t numSamples;
  108. double sampleRate;
  109. ULONG flags;
  110. char _3[12];
  111. double speedForTimeCode;
  112. w_int64_t timeStampForTimeCode;
  113. ULONG flagsForTimeCode;
  114. char _4[64];
  115. } TimeInformation;
  116. typedef struct Callbacks
  117. {
  118. void (WINEASIO_CALLBACK *swapBuffers) (LONG, LONG);
  119. void (WINEASIO_CALLBACK *sampleRateChanged) (double);
  120. LONG (WINEASIO_CALLBACK *sendNotification) (LONG, LONG, void*, double*);
  121. void* (WINEASIO_CALLBACK *swapBuffersWithTimeInfo) (TimeInformation*, LONG, LONG);
  122. } Callbacks;
  123. /*****************************************************************************
  124. * IWineAsio interface
  125. */
  126. #define INTERFACE IWineASIO
  127. DECLARE_INTERFACE_(IWineASIO,IUnknown)
  128. {
  129. STDMETHOD_(HRESULT, QueryInterface) (THIS_ IID riid, void** ppvObject) PURE;
  130. STDMETHOD_(ULONG, AddRef) (THIS) PURE;
  131. STDMETHOD_(ULONG, Release) (THIS) PURE;
  132. STDMETHOD_(LONG, Init) (THIS_ void *sysRef) PURE;
  133. STDMETHOD_(void, GetDriverName) (THIS_ char *name) PURE;
  134. STDMETHOD_(LONG, GetDriverVersion) (THIS) PURE;
  135. STDMETHOD_(void, GetErrorMessage) (THIS_ char *string) PURE;
  136. STDMETHOD_(LONG, Start) (THIS) PURE;
  137. STDMETHOD_(LONG, Stop) (THIS) PURE;
  138. STDMETHOD_(LONG, GetChannels) (THIS_ LONG *numInputChannels, LONG *numOutputChannels) PURE;
  139. STDMETHOD_(LONG, GetLatencies) (THIS_ LONG *inputLatency, LONG *outputLatency) PURE;
  140. STDMETHOD_(LONG, GetBufferSize) (THIS_ LONG *minSize, LONG *maxSize, LONG *preferredSize, LONG *granularity) PURE;
  141. STDMETHOD_(LONG, CanSampleRate) (THIS_ double sampleRate) PURE;
  142. STDMETHOD_(LONG, GetSampleRate) (THIS_ double *sampleRate) PURE;
  143. STDMETHOD_(LONG, SetSampleRate) (THIS_ double sampleRate) PURE;
  144. STDMETHOD_(LONG, GetClockSources) (THIS_ void *clocks, LONG *numSources) PURE;
  145. STDMETHOD_(LONG, SetClockSource) (THIS_ LONG index) PURE;
  146. STDMETHOD_(LONG, GetSamplePosition) (THIS_ w_int64_t *sPos, w_int64_t *tStamp) PURE;
  147. STDMETHOD_(LONG, GetChannelInfo) (THIS_ void *info) PURE;
  148. STDMETHOD_(LONG, CreateBuffers) (THIS_ BufferInformation *bufferInfo, LONG numChannels, LONG bufferSize, Callbacks *callbacks) PURE;
  149. STDMETHOD_(LONG, DisposeBuffers) (THIS) PURE;
  150. STDMETHOD_(LONG, ControlPanel) (THIS) PURE;
  151. STDMETHOD_(LONG, Future) (THIS_ LONG selector,void *opt) PURE;
  152. STDMETHOD_(LONG, OutputReady) (THIS) PURE;
  153. };
  154. #undef INTERFACE
  155. typedef struct IWineASIO *LPWINEASIO;
  156. typedef struct IOChannel
  157. {
  158. jack_default_audio_sample_t *audio_buffer;
  159. char port_name[WINEASIO_MAX_NAME_LENGTH];
  160. jack_port_t *port;
  161. bool active;
  162. } IOChannel;
  163. typedef struct IWineASIOImpl
  164. {
  165. /* COM stuff */
  166. const IWineASIOVtbl *lpVtbl;
  167. LONG ref;
  168. /* The app's main window handle on windows, 0 on OS/X */
  169. HWND sys_ref;
  170. /* Host stuff */
  171. LONG host_active_inputs;
  172. LONG host_active_outputs;
  173. BOOL host_buffer_index;
  174. Callbacks *host_callbacks;
  175. BOOL host_can_time_code;
  176. LONG host_current_buffersize;
  177. INT host_driver_state;
  178. w_int64_t host_num_samples;
  179. double host_sample_rate;
  180. TimeInformation host_time;
  181. BOOL host_time_info_mode;
  182. w_int64_t host_time_stamp;
  183. LONG host_version;
  184. /* WineASIO configuration options */
  185. int wineasio_number_inputs;
  186. int wineasio_number_outputs;
  187. BOOL wineasio_autostart_server;
  188. BOOL wineasio_connect_to_hardware;
  189. BOOL wineasio_fixed_buffersize;
  190. LONG wineasio_preferred_buffersize;
  191. /* JACK stuff */
  192. jack_client_t *jack_client;
  193. char jack_client_name[WINEASIO_MAX_NAME_LENGTH];
  194. int jack_num_input_ports;
  195. int jack_num_output_ports;
  196. const char **jack_input_ports;
  197. const char **jack_output_ports;
  198. /* jack process callback buffers */
  199. jack_default_audio_sample_t *callback_audio_buffer;
  200. IOChannel *input_channel;
  201. IOChannel *output_channel;
  202. } IWineASIOImpl;
  203. enum { Loaded, Initialized, Prepared, Running };
  204. /****************************************************************************
  205. * Interface Methods
  206. */
  207. /*
  208. * as seen from the WineASIO source
  209. */
  210. HIDDEN HRESULT STDMETHODCALLTYPE QueryInterface(LPWINEASIO iface, REFIID riid, void **ppvObject);
  211. HIDDEN ULONG STDMETHODCALLTYPE AddRef(LPWINEASIO iface);
  212. HIDDEN ULONG STDMETHODCALLTYPE Release(LPWINEASIO iface);
  213. HIDDEN LONG STDMETHODCALLTYPE Init(LPWINEASIO iface, void *sysRef);
  214. HIDDEN void STDMETHODCALLTYPE GetDriverName(LPWINEASIO iface, char *name);
  215. HIDDEN LONG STDMETHODCALLTYPE GetDriverVersion(LPWINEASIO iface);
  216. HIDDEN void STDMETHODCALLTYPE GetErrorMessage(LPWINEASIO iface, char *string);
  217. HIDDEN LONG STDMETHODCALLTYPE Start(LPWINEASIO iface);
  218. HIDDEN LONG STDMETHODCALLTYPE Stop(LPWINEASIO iface);
  219. HIDDEN LONG STDMETHODCALLTYPE GetChannels (LPWINEASIO iface, LONG *numInputChannels, LONG *numOutputChannels);
  220. HIDDEN LONG STDMETHODCALLTYPE GetLatencies(LPWINEASIO iface, LONG *inputLatency, LONG *outputLatency);
  221. HIDDEN LONG STDMETHODCALLTYPE GetBufferSize(LPWINEASIO iface, LONG *minSize, LONG *maxSize, LONG *preferredSize, LONG *granularity);
  222. HIDDEN LONG STDMETHODCALLTYPE CanSampleRate(LPWINEASIO iface, double sampleRate);
  223. HIDDEN LONG STDMETHODCALLTYPE GetSampleRate(LPWINEASIO iface, double *sampleRate);
  224. HIDDEN LONG STDMETHODCALLTYPE SetSampleRate(LPWINEASIO iface, double sampleRate);
  225. HIDDEN LONG STDMETHODCALLTYPE GetClockSources(LPWINEASIO iface, void *clocks, LONG *numSources);
  226. HIDDEN LONG STDMETHODCALLTYPE SetClockSource(LPWINEASIO iface, LONG index);
  227. HIDDEN LONG STDMETHODCALLTYPE GetSamplePosition(LPWINEASIO iface, w_int64_t *sPos, w_int64_t *tStamp);
  228. HIDDEN LONG STDMETHODCALLTYPE GetChannelInfo(LPWINEASIO iface, void *info);
  229. HIDDEN LONG STDMETHODCALLTYPE CreateBuffers(LPWINEASIO iface, BufferInformation *bufferInfo, LONG numChannels, LONG bufferSize, Callbacks *callbacks);
  230. HIDDEN LONG STDMETHODCALLTYPE DisposeBuffers(LPWINEASIO iface);
  231. HIDDEN LONG STDMETHODCALLTYPE ControlPanel(LPWINEASIO iface);
  232. HIDDEN LONG STDMETHODCALLTYPE Future(LPWINEASIO iface, LONG selector, void *opt);
  233. HIDDEN LONG STDMETHODCALLTYPE OutputReady(LPWINEASIO iface);
  234. /*
  235. * thiscall wrappers for the vtbl (as seen from app side 32bit)
  236. */
  237. HIDDEN void __thiscall_Init(void);
  238. HIDDEN void __thiscall_GetDriverName(void);
  239. HIDDEN void __thiscall_GetDriverVersion(void);
  240. HIDDEN void __thiscall_GetErrorMessage(void);
  241. HIDDEN void __thiscall_Start(void);
  242. HIDDEN void __thiscall_Stop(void);
  243. HIDDEN void __thiscall_GetChannels(void);
  244. HIDDEN void __thiscall_GetLatencies(void);
  245. HIDDEN void __thiscall_GetBufferSize(void);
  246. HIDDEN void __thiscall_CanSampleRate(void);
  247. HIDDEN void __thiscall_GetSampleRate(void);
  248. HIDDEN void __thiscall_SetSampleRate(void);
  249. HIDDEN void __thiscall_GetClockSources(void);
  250. HIDDEN void __thiscall_SetClockSource(void);
  251. HIDDEN void __thiscall_GetSamplePosition(void);
  252. HIDDEN void __thiscall_GetChannelInfo(void);
  253. HIDDEN void __thiscall_CreateBuffers(void);
  254. HIDDEN void __thiscall_DisposeBuffers(void);
  255. HIDDEN void __thiscall_ControlPanel(void);
  256. HIDDEN void __thiscall_Future(void);
  257. HIDDEN void __thiscall_OutputReady(void);
  258. /*
  259. * Jack callbacks
  260. */
  261. static inline int jack_buffer_size_callback (jack_nframes_t nframes, void *arg);
  262. static inline void jack_latency_callback(jack_latency_callback_mode_t mode, void *arg);
  263. static inline int jack_process_callback (jack_nframes_t nframes, void *arg);
  264. static inline int jack_sample_rate_callback (jack_nframes_t nframes, void *arg);
  265. /*
  266. * Support functions
  267. */
  268. HRESULT WINAPI WineASIOCreateInstance(REFIID riid, LPVOID *ppobj);
  269. static VOID configure_driver(IWineASIOImpl *This);
  270. static DWORD WINAPI jack_thread_creator_helper(LPVOID arg);
  271. static int jack_thread_creator(pthread_t* thread_id, const pthread_attr_t* attr, void *(*function)(void*), void* arg);
  272. /* {48D0C522-BFCC-45cc-8B84-17F25F33E6E8} */
  273. static GUID const CLSID_WineASIO = {
  274. 0x48d0c522, 0xbfcc, 0x45cc, { 0x8b, 0x84, 0x17, 0xf2, 0x5f, 0x33, 0xe6, 0xe8 } };
  275. static const IWineASIOVtbl WineASIO_Vtbl =
  276. {
  277. (void *) QueryInterface,
  278. (void *) AddRef,
  279. (void *) Release,
  280. (void *) THISCALL(Init),
  281. (void *) THISCALL(GetDriverName),
  282. (void *) THISCALL(GetDriverVersion),
  283. (void *) THISCALL(GetErrorMessage),
  284. (void *) THISCALL(Start),
  285. (void *) THISCALL(Stop),
  286. (void *) THISCALL(GetChannels),
  287. (void *) THISCALL(GetLatencies),
  288. (void *) THISCALL(GetBufferSize),
  289. (void *) THISCALL(CanSampleRate),
  290. (void *) THISCALL(GetSampleRate),
  291. (void *) THISCALL(SetSampleRate),
  292. (void *) THISCALL(GetClockSources),
  293. (void *) THISCALL(SetClockSource),
  294. (void *) THISCALL(GetSamplePosition),
  295. (void *) THISCALL(GetChannelInfo),
  296. (void *) THISCALL(CreateBuffers),
  297. (void *) THISCALL(DisposeBuffers),
  298. (void *) THISCALL(ControlPanel),
  299. (void *) THISCALL(Future),
  300. (void *) THISCALL(OutputReady)
  301. };
  302. /* structure needed to create the JACK callback thread in the wine process context */
  303. struct {
  304. void *(*jack_callback_thread) (void*);
  305. void *arg;
  306. pthread_t jack_callback_pthread_id;
  307. HANDLE jack_callback_thread_created;
  308. } jack_thread_creator_privates;
  309. /*****************************************************************************
  310. * Interface method definitions
  311. */
  312. HIDDEN HRESULT STDMETHODCALLTYPE QueryInterface(LPWINEASIO iface, REFIID riid, void **ppvObject)
  313. {
  314. IWineASIOImpl *This = (IWineASIOImpl *)iface;
  315. TRACE("iface: %p, riid: %s, ppvObject: %p)\n", iface, debugstr_guid(riid), ppvObject);
  316. if (ppvObject == NULL)
  317. return E_INVALIDARG;
  318. if (IsEqualIID(&CLSID_WineASIO, riid))
  319. {
  320. AddRef(iface);
  321. *ppvObject = This;
  322. return S_OK;
  323. }
  324. return E_NOINTERFACE;
  325. }
  326. /*
  327. * ULONG STDMETHODCALLTYPE AddRef(LPWINEASIO iface);
  328. * Function: Increment the reference count on the object
  329. * Returns: Ref count
  330. */
  331. HIDDEN ULONG STDMETHODCALLTYPE AddRef(LPWINEASIO iface)
  332. {
  333. IWineASIOImpl *This = (IWineASIOImpl *)iface;
  334. ULONG ref = InterlockedIncrement(&(This->ref));
  335. TRACE("iface: %p, ref count is %d\n", iface, ref);
  336. return ref;
  337. }
  338. /*
  339. * ULONG Release (LPWINEASIO iface);
  340. * Function: Destroy the interface
  341. * Returns: Ref count
  342. * Implies: Stop() and DisposeBuffers()
  343. */
  344. HIDDEN ULONG STDMETHODCALLTYPE Release(LPWINEASIO iface)
  345. {
  346. IWineASIOImpl *This = (IWineASIOImpl *)iface;
  347. ULONG ref = InterlockedDecrement(&This->ref);
  348. TRACE("iface: %p, ref count is %d\n", iface, ref);
  349. if (This->host_driver_state == Running)
  350. Stop(iface);
  351. if (This->host_driver_state == Prepared)
  352. DisposeBuffers(iface);
  353. if (This->host_driver_state == Initialized)
  354. {
  355. /* just for good measure we deinitialize IOChannel structures and unregister JACK ports */
  356. for (int i = 0; i < This->wineasio_number_inputs; i++)
  357. {
  358. jack_port_unregister (This->jack_client, This->input_channel[i].port);
  359. This->input_channel[i].active = false;
  360. This->input_channel[i].port = NULL;
  361. }
  362. for (int i = 0; i < This->wineasio_number_outputs; i++)
  363. {
  364. jack_port_unregister (This->jack_client, This->output_channel[i].port);
  365. This->output_channel[i].active = false;
  366. This->output_channel[i].port = NULL;
  367. }
  368. This->host_active_inputs = This->host_active_outputs = 0;
  369. TRACE("%i IOChannel structures released\n", This->wineasio_number_inputs + This->wineasio_number_outputs);
  370. jack_free (This->jack_output_ports);
  371. jack_free (This->jack_input_ports);
  372. jack_client_close(This->jack_client);
  373. if (This->input_channel)
  374. HeapFree(GetProcessHeap(), 0, This->input_channel);
  375. }
  376. TRACE("WineASIO terminated\n\n");
  377. if (ref == 0)
  378. HeapFree(GetProcessHeap(), 0, This);
  379. return ref;
  380. }
  381. /*
  382. * LONG Init (void *sysRef);
  383. * Function: Initialize the driver
  384. * Parameters: Pointer to "This"
  385. * sysHanle is 0 on OS/X and on windows it contains the applications main window handle
  386. * Returns: 0 on error, and 1 on success
  387. */
  388. DEFINE_THISCALL_WRAPPER(Init,8)
  389. HIDDEN LONG STDMETHODCALLTYPE Init(LPWINEASIO iface, void *sysRef)
  390. {
  391. IWineASIOImpl *This = (IWineASIOImpl *)iface;
  392. jack_status_t jack_status;
  393. jack_options_t jack_options = This->wineasio_autostart_server ? JackNullOption : JackNoStartServer;
  394. int i;
  395. This->sys_ref = sysRef;
  396. mlockall(MCL_FUTURE);
  397. configure_driver(This);
  398. if (!(This->jack_client = jack_client_open(This->jack_client_name, jack_options, &jack_status)))
  399. {
  400. WARN("Unable to open a JACK client as: %s\n", This->jack_client_name);
  401. return 0;
  402. }
  403. TRACE("JACK client opened as: '%s'\n", jack_get_client_name(This->jack_client));
  404. This->host_sample_rate = jack_get_sample_rate(This->jack_client);
  405. This->host_current_buffersize = jack_get_buffer_size(This->jack_client);
  406. /* Allocate IOChannel structures */
  407. This->input_channel = HeapAlloc(GetProcessHeap(), 0, (This->wineasio_number_inputs + This->wineasio_number_outputs) * sizeof(IOChannel));
  408. if (!This->input_channel)
  409. {
  410. jack_client_close(This->jack_client);
  411. ERR("Unable to allocate IOChannel structures for %i channels\n", This->wineasio_number_inputs);
  412. return 0;
  413. }
  414. This->output_channel = This->input_channel + This->wineasio_number_inputs;
  415. TRACE("%i IOChannel structures allocated\n", This->wineasio_number_inputs + This->wineasio_number_outputs);
  416. /* Get and count physical JACK ports */
  417. This->jack_input_ports = jack_get_ports(This->jack_client, NULL, NULL, JackPortIsPhysical | JackPortIsOutput);
  418. 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++)
  419. ;
  420. This->jack_output_ports = jack_get_ports(This->jack_client, NULL, NULL, JackPortIsPhysical | JackPortIsInput);
  421. 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++)
  422. ;
  423. /* Initialize IOChannel structures */
  424. for (i = 0; i < This->wineasio_number_inputs; i++)
  425. {
  426. This->input_channel[i].active = false;
  427. This->input_channel[i].port = NULL;
  428. snprintf(This->input_channel[i].port_name, WINEASIO_MAX_NAME_LENGTH, "in_%i", i + 1);
  429. This->input_channel[i].port = jack_port_register(This->jack_client,
  430. This->input_channel[i].port_name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, i);
  431. /* TRACE("IOChannel structure initialized for input %d: '%s'\n", i, This->input_channel[i].port_name); */
  432. }
  433. for (i = 0; i < This->wineasio_number_outputs; i++)
  434. {
  435. This->output_channel[i].active = false;
  436. This->output_channel[i].port = NULL;
  437. snprintf(This->output_channel[i].port_name, WINEASIO_MAX_NAME_LENGTH, "out_%i", i + 1);
  438. This->output_channel[i].port = jack_port_register(This->jack_client,
  439. This->output_channel[i].port_name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, i);
  440. /* TRACE("IOChannel structure initialized for output %d: '%s'\n", i, This->output_channel[i].port_name); */
  441. }
  442. TRACE("%i IOChannel structures initialized\n", This->wineasio_number_inputs + This->wineasio_number_outputs);
  443. jack_set_thread_creator(jack_thread_creator);
  444. if (jack_set_buffer_size_callback(This->jack_client, jack_buffer_size_callback, This))
  445. {
  446. jack_client_close(This->jack_client);
  447. HeapFree(GetProcessHeap(), 0, This->input_channel);
  448. ERR("Unable to register JACK buffer size change callback\n");
  449. return 0;
  450. }
  451. if (jack_set_latency_callback(This->jack_client, jack_latency_callback, This))
  452. {
  453. jack_client_close(This->jack_client);
  454. HeapFree(GetProcessHeap(), 0, This->input_channel);
  455. ERR("Unable to register JACK latency callback\n");
  456. return 0;
  457. }
  458. if (jack_set_process_callback(This->jack_client, jack_process_callback, This))
  459. {
  460. jack_client_close(This->jack_client);
  461. HeapFree(GetProcessHeap(), 0, This->input_channel);
  462. ERR("Unable to register JACK process callback\n");
  463. return 0;
  464. }
  465. if (jack_set_sample_rate_callback (This->jack_client, jack_sample_rate_callback, This))
  466. {
  467. jack_client_close(This->jack_client);
  468. HeapFree(GetProcessHeap(), 0, This->input_channel);
  469. ERR("Unable to register JACK sample rate change callback\n");
  470. return 0;
  471. }
  472. This->host_driver_state = Initialized;
  473. TRACE("WineASIO 0.%.1f initialized\n",(float) This->host_version / 10);
  474. return 1;
  475. }
  476. /*
  477. * void GetDriverName(char *name);
  478. * Function: Returns the driver name in name
  479. */
  480. DEFINE_THISCALL_WRAPPER(GetDriverName,8)
  481. HIDDEN void STDMETHODCALLTYPE GetDriverName(LPWINEASIO iface, char *name)
  482. {
  483. TRACE("iface: %p, name: %p\n", iface, name);
  484. strcpy(name, "WineASIO");
  485. return;
  486. }
  487. /*
  488. * LONG GetDriverVersion (void);
  489. * Function: Returns the driver version number
  490. */
  491. DEFINE_THISCALL_WRAPPER(GetDriverVersion,4)
  492. HIDDEN LONG STDMETHODCALLTYPE GetDriverVersion(LPWINEASIO iface)
  493. {
  494. IWineASIOImpl *This = (IWineASIOImpl*)iface;
  495. TRACE("iface: %p\n", iface);
  496. return This->host_version;
  497. }
  498. /*
  499. * void GetErrorMessage(char *string);
  500. * Function: Returns an error message for the last occured error in string
  501. */
  502. DEFINE_THISCALL_WRAPPER(GetErrorMessage,8)
  503. HIDDEN void STDMETHODCALLTYPE GetErrorMessage(LPWINEASIO iface, char *string)
  504. {
  505. TRACE("iface: %p, string: %p)\n", iface, string);
  506. strcpy(string, "WineASIO does not return error messages\n");
  507. return;
  508. }
  509. /*
  510. * LONG Start(void);
  511. * Function: Start JACK IO processing and reset the sample counter to zero
  512. * Returns: -1000 if IO is missing
  513. * -999 if JACK fails to start
  514. */
  515. DEFINE_THISCALL_WRAPPER(Start,4)
  516. HIDDEN LONG STDMETHODCALLTYPE Start(LPWINEASIO iface)
  517. {
  518. IWineASIOImpl *This = (IWineASIOImpl*)iface;
  519. int i;
  520. DWORD time;
  521. TRACE("iface: %p\n", iface);
  522. if (This->host_driver_state != Prepared)
  523. return -1000;
  524. /* Zero the audio buffer */
  525. for (i = 0; i < (This->wineasio_number_inputs + This->wineasio_number_outputs) * 2 * This->host_current_buffersize; i++)
  526. This->callback_audio_buffer[i] = 0;
  527. /* prime the callback by preprocessing one outbound host bufffer */
  528. This->host_buffer_index = 0;
  529. This->host_num_samples.hi = This->host_num_samples.lo = 0;
  530. time = timeGetTime();
  531. This->host_time_stamp.lo = time * 1000000;
  532. This->host_time_stamp.hi = ((unsigned long long) time * 1000000) >> 32;
  533. if (This->host_time_info_mode) /* use the newer swapBuffersWithTimeInfo method if supported */
  534. {
  535. This->host_time.numSamples.lo = This->host_time.numSamples.hi = 0;
  536. This->host_time.timeStamp.lo = This->host_time_stamp.lo;
  537. This->host_time.timeStamp.hi = This->host_time_stamp.hi;
  538. This->host_time.sampleRate = This->host_sample_rate;
  539. This->host_time.flags = 0x7;
  540. if (This->host_can_time_code) /* addionally use time code if supported */
  541. {
  542. This->host_time.speedForTimeCode = 1; /* FIXME */
  543. This->host_time.timeStampForTimeCode.lo = This->host_time_stamp.lo;
  544. This->host_time.timeStampForTimeCode.hi = This->host_time_stamp.hi;
  545. This->host_time.flagsForTimeCode = ~(0x3);
  546. }
  547. This->host_callbacks->swapBuffersWithTimeInfo(&This->host_time, This->host_buffer_index, 1);
  548. }
  549. else
  550. { /* use the old swapBuffers method */
  551. This->host_callbacks->swapBuffers(This->host_buffer_index, 1);
  552. }
  553. /* switch host buffer */
  554. This->host_buffer_index = This->host_buffer_index ? 0 : 1;
  555. This->host_driver_state = Running;
  556. TRACE("WineASIO successfully loaded\n");
  557. return 0;
  558. }
  559. /*
  560. * LONG Stop(void);
  561. * Function: Stop JACK IO processing
  562. * Returns: -1000 on missing IO
  563. * Note: swapBuffers() must not called after returning
  564. */
  565. DEFINE_THISCALL_WRAPPER(Stop,4)
  566. HIDDEN LONG STDMETHODCALLTYPE Stop(LPWINEASIO iface)
  567. {
  568. IWineASIOImpl *This = (IWineASIOImpl*)iface;
  569. TRACE("iface: %p\n", iface);
  570. if (This->host_driver_state != Running)
  571. return -1000;
  572. This->host_driver_state = Prepared;
  573. return 0;
  574. }
  575. /*
  576. * LONG GetChannels(LONG *numInputChannels, LONG *numOutputChannels);
  577. * Function: Report number of IO channels
  578. * Parameters: numInputChannels and numOutputChannels will hold number of channels on returning
  579. * Returns: -1000 if no channels are available, otherwise AES_OK
  580. */
  581. DEFINE_THISCALL_WRAPPER(GetChannels,12)
  582. HIDDEN LONG STDMETHODCALLTYPE GetChannels (LPWINEASIO iface, LONG *numInputChannels, LONG *numOutputChannels)
  583. {
  584. IWineASIOImpl *This = (IWineASIOImpl*)iface;
  585. if (!numInputChannels || !numOutputChannels)
  586. return -998;
  587. *numInputChannels = This->wineasio_number_inputs;
  588. *numOutputChannels = This->wineasio_number_outputs;
  589. TRACE("iface: %p, inputs: %i, outputs: %i\n", iface, This->wineasio_number_inputs, This->wineasio_number_outputs);
  590. return 0;
  591. }
  592. /*
  593. * LONG GetLatencies(LONG *inputLatency, LONG *outputLatency);
  594. * Function: Return latency in frames
  595. * Returns: -1000 if no IO is available, otherwise AES_OK
  596. */
  597. DEFINE_THISCALL_WRAPPER(GetLatencies,12)
  598. HIDDEN LONG STDMETHODCALLTYPE GetLatencies(LPWINEASIO iface, LONG *inputLatency, LONG *outputLatency)
  599. {
  600. IWineASIOImpl *This = (IWineASIOImpl*)iface;
  601. jack_latency_range_t range;
  602. if (!inputLatency || !outputLatency)
  603. return -998;
  604. if (This->host_driver_state == Loaded)
  605. return -1000;
  606. jack_port_get_latency_range(This->input_channel[0].port, JackCaptureLatency, &range);
  607. *inputLatency = range.max;
  608. jack_port_get_latency_range(This->output_channel[0].port, JackPlaybackLatency, &range);
  609. *outputLatency = range.max;
  610. TRACE("iface: %p, input latency: %d, output latency: %d\n", iface, *inputLatency, *outputLatency);
  611. return 0;
  612. }
  613. /*
  614. * LONG GetBufferSize(LONG *minSize, LONG *maxSize, LONG *preferredSize, LONG *granularity);
  615. * Function: Return minimum, maximum, preferred buffer sizes, and granularity
  616. * At the moment return all the same, and granularity 0
  617. * Returns: -1000 on missing IO
  618. */
  619. DEFINE_THISCALL_WRAPPER(GetBufferSize,20)
  620. HIDDEN LONG STDMETHODCALLTYPE GetBufferSize(LPWINEASIO iface, LONG *minSize, LONG *maxSize, LONG *preferredSize, LONG *granularity)
  621. {
  622. IWineASIOImpl *This = (IWineASIOImpl*)iface;
  623. TRACE("iface: %p, minSize: %p, maxSize: %p, preferredSize: %p, granularity: %p\n", iface, minSize, maxSize, preferredSize, granularity);
  624. if (!minSize || !maxSize || !preferredSize || !granularity)
  625. return -998;
  626. if (This->wineasio_fixed_buffersize)
  627. {
  628. *minSize = *maxSize = *preferredSize = This->host_current_buffersize;
  629. *granularity = 0;
  630. TRACE("Buffersize fixed at %i\n", This->host_current_buffersize);
  631. return 0;
  632. }
  633. *minSize = WINEASIO_MINIMUM_BUFFERSIZE;
  634. *maxSize = WINEASIO_MAXIMUM_BUFFERSIZE;
  635. *preferredSize = This->wineasio_preferred_buffersize;
  636. *granularity = -1;
  637. TRACE("The host can control buffersize\nMinimum: %i, maximum: %i, preferred: %i, granularity: %i, current: %i\n",
  638. *minSize, *maxSize, *preferredSize, *granularity, This->host_current_buffersize);
  639. return 0;
  640. }
  641. /*
  642. * LONG CanSampleRate(double sampleRate);
  643. * Function: Ask if specific SR is available
  644. * Returns: -995 if SR isn't available, -1000 on missing IO
  645. */
  646. DEFINE_THISCALL_WRAPPER(CanSampleRate,12)
  647. HIDDEN LONG STDMETHODCALLTYPE CanSampleRate(LPWINEASIO iface, double sampleRate)
  648. {
  649. IWineASIOImpl *This = (IWineASIOImpl*)iface;
  650. TRACE("iface: %p, Samplerate = %li, requested samplerate = %li\n", iface, (long) This->host_sample_rate, (long) sampleRate);
  651. if (sampleRate != This->host_sample_rate)
  652. return -995;
  653. return 0;
  654. }
  655. /*
  656. * LONG GetSampleRate(double *currentRate);
  657. * Function: Return current SR
  658. * Parameters: currentRate will hold SR on return, 0 if unknown
  659. * Returns: -995 if SR is unknown, -1000 on missing IO
  660. */
  661. DEFINE_THISCALL_WRAPPER(GetSampleRate,8)
  662. HIDDEN LONG STDMETHODCALLTYPE GetSampleRate(LPWINEASIO iface, double *sampleRate)
  663. {
  664. IWineASIOImpl *This = (IWineASIOImpl*)iface;
  665. TRACE("iface: %p, Sample rate is %i\n", iface, (int) This->host_sample_rate);
  666. if (!sampleRate)
  667. return -998;
  668. *sampleRate = This->host_sample_rate;
  669. return 0;
  670. }
  671. /*
  672. * LONG SetSampleRate(double sampleRate);
  673. * Function: Set requested SR, enable external sync if SR == 0
  674. * Returns: -995 if unknown SR
  675. * -997 if current clock is external and SR != 0
  676. * -1000 on missing IO
  677. */
  678. DEFINE_THISCALL_WRAPPER(SetSampleRate,12)
  679. HIDDEN LONG STDMETHODCALLTYPE SetSampleRate(LPWINEASIO iface, double sampleRate)
  680. {
  681. IWineASIOImpl *This = (IWineASIOImpl*)iface;
  682. TRACE("iface: %p, Sample rate %f requested\n", iface, sampleRate);
  683. if (sampleRate != This->host_sample_rate)
  684. return -995;
  685. return 0;
  686. }
  687. /*
  688. * LONG GetClockSources(void *clocks, LONG *numSources);
  689. * Function: Return available clock sources
  690. * Parameters: clocks - a pointer to an array of clock source structures.
  691. * numSources - when called: number of allocated members
  692. * - on return: number of clock sources, the minimum is 1 - the internal clock
  693. * Returns: -1000 on missing IO
  694. */
  695. DEFINE_THISCALL_WRAPPER(GetClockSources,12)
  696. HIDDEN LONG STDMETHODCALLTYPE GetClockSources(LPWINEASIO iface, void *clocks, LONG *numSources)
  697. {
  698. LONG *lclocks = (LONG*)clocks;
  699. TRACE("iface: %p, clocks: %p, numSources: %p\n", iface, clocks, numSources);
  700. if (!clocks || !numSources)
  701. return -998;
  702. *lclocks++ = 0;
  703. *lclocks++ = -1;
  704. *lclocks++ = -1;
  705. *lclocks++ = 1;
  706. strcpy((char*)lclocks, "Internal");
  707. *numSources = 1;
  708. return 0;
  709. }
  710. /*
  711. * LONG SetClockSource(LONG index);
  712. * Function: Set clock source
  713. * Parameters: index returned by GetClockSources()
  714. * Returns: -1000 on missing IO
  715. * -997 may be returned if a clock can't be selected
  716. * -995 should not be returned
  717. */
  718. DEFINE_THISCALL_WRAPPER(SetClockSource,8)
  719. HIDDEN LONG STDMETHODCALLTYPE SetClockSource(LPWINEASIO iface, LONG index)
  720. {
  721. TRACE("iface: %p, index: %i\n", iface, index);
  722. if (index != 0)
  723. return -1000;
  724. return 0;
  725. }
  726. /*
  727. * LONG GetSamplePosition (w_int64_t *sPos, w_int64_t *tStamp);
  728. * Function: Return sample position and timestamp
  729. * Parameters: sPos holds the position on return, reset to 0 on Start()
  730. * tStamp holds the system time of sPos
  731. * Return: -1000 on missing IO
  732. * -996 on missing clock
  733. */
  734. DEFINE_THISCALL_WRAPPER(GetSamplePosition,12)
  735. HIDDEN LONG STDMETHODCALLTYPE GetSamplePosition(LPWINEASIO iface, w_int64_t *sPos, w_int64_t *tStamp)
  736. {
  737. IWineASIOImpl *This = (IWineASIOImpl*)iface;
  738. TRACE("iface: %p, sPos: %p, tStamp: %p\n", iface, sPos, tStamp);
  739. if (!sPos || !tStamp)
  740. return -998;
  741. tStamp->lo = This->host_time_stamp.lo;
  742. tStamp->hi = This->host_time_stamp.hi;
  743. sPos->lo = This->host_num_samples.lo;
  744. sPos->hi = 0; /* FIXME */
  745. return 0;
  746. }
  747. /*
  748. * LONG GetChannelInfo (void *info);
  749. * Function: Retrive channel info
  750. * Returns: -1000 on missing IO
  751. */
  752. DEFINE_THISCALL_WRAPPER(GetChannelInfo,8)
  753. HIDDEN LONG STDMETHODCALLTYPE GetChannelInfo(LPWINEASIO iface, void *info)
  754. {
  755. IWineASIOImpl *This = (IWineASIOImpl*)iface;
  756. LONG *linfo = (LONG*)info;
  757. const LONG channelNumber = *linfo++;
  758. const LONG isInputType = *linfo++;
  759. /* TRACE("(iface: %p, info: %p\n", iface, info); */
  760. if (channelNumber < 0 || (isInputType ? channelNumber >= This->wineasio_number_inputs : channelNumber >= This->wineasio_number_outputs))
  761. return -998;
  762. *linfo++ = (isInputType ? This->input_channel : This->output_channel)[channelNumber].active;
  763. *linfo++ = 0;
  764. *linfo++ = 19;
  765. memcpy(linfo, (isInputType ? This->input_channel : This->output_channel)[channelNumber].port_name, WINEASIO_MAX_NAME_LENGTH);
  766. return 0;
  767. }
  768. /*
  769. * LONG CreateBuffers(BufferInformation *bufferInfo, LONG numChannels, LONG bufferSize, Callbacks *callbacks);
  770. * Function: Allocate buffers for IO channels
  771. * Parameters: bufferInfo - pointer to an array of BufferInformation structures
  772. * numChannels - the total number of IO channels to be allocated
  773. * bufferSize - one of the buffer sizes retrieved with GetBufferSize()
  774. * callbacks - pointer to a Callbacks structure
  775. * Returns: -994 if impossible to allocate enough memory
  776. * -997 on unsupported bufferSize or invalid bufferInfo data
  777. * -1000 on missing IO
  778. */
  779. DEFINE_THISCALL_WRAPPER(CreateBuffers,20)
  780. HIDDEN LONG STDMETHODCALLTYPE CreateBuffers(LPWINEASIO iface, BufferInformation *bufferInfo, LONG numChannels, LONG bufferSize, Callbacks *callbacks)
  781. {
  782. IWineASIOImpl *This = (IWineASIOImpl*)iface;
  783. BufferInformation *bufferInfoPerChannel = bufferInfo;
  784. int i, j, k;
  785. TRACE("iface: %p, bufferInfo: %p, numChannels: %i, bufferSize: %i, callbacks: %p\n", iface, bufferInfo, (int)numChannels, (int)bufferSize, callbacks);
  786. if (This->host_driver_state != Initialized)
  787. return -1000;
  788. if (!bufferInfo || !callbacks)
  789. return -997;
  790. /* Check for invalid channel numbers */
  791. for (i = j = k = 0; i < numChannels; i++, bufferInfoPerChannel++)
  792. {
  793. if (bufferInfoPerChannel->isInputType)
  794. {
  795. if (j++ >= This->wineasio_number_inputs)
  796. {
  797. WARN("Invalid input channel requested\n");
  798. return -997;
  799. }
  800. }
  801. else
  802. {
  803. if (k++ >= This->wineasio_number_outputs)
  804. {
  805. WARN("Invalid output channel requested\n");
  806. return -997;
  807. }
  808. }
  809. }
  810. /* set buf_size */
  811. if (This->wineasio_fixed_buffersize)
  812. {
  813. if (This->host_current_buffersize != bufferSize)
  814. return -997;
  815. TRACE("Buffersize fixed at %i\n", (int)This->host_current_buffersize);
  816. }
  817. else
  818. { /* fail if not a power of two and if out of range */
  819. if (!(bufferSize > 0 && !(bufferSize&(bufferSize-1))
  820. && bufferSize >= WINEASIO_MINIMUM_BUFFERSIZE
  821. && bufferSize <= WINEASIO_MAXIMUM_BUFFERSIZE))
  822. {
  823. WARN("Invalid buffersize %i requested\n", (int)bufferSize);
  824. return -997;
  825. }
  826. else
  827. {
  828. if (This->host_current_buffersize == bufferSize)
  829. {
  830. TRACE("Buffer size already set to %i\n", (int)This->host_current_buffersize);
  831. }
  832. else
  833. {
  834. This->host_current_buffersize = bufferSize;
  835. if (jack_set_buffer_size(This->jack_client, This->host_current_buffersize))
  836. {
  837. WARN("JACK is unable to set buffersize to %i\n", (int)This->host_current_buffersize);
  838. return -999;
  839. }
  840. TRACE("Buffer size changed to %i\n", (int)This->host_current_buffersize);
  841. }
  842. }
  843. }
  844. This->host_callbacks = callbacks;
  845. This->host_time_info_mode = This->host_can_time_code = FALSE;
  846. if (This->host_callbacks->sendNotification(7, 0, 0, 0))
  847. {
  848. This->host_time_info_mode = TRUE;
  849. if (This->host_callbacks->sendNotification(8, 0, 0, 0))
  850. This->host_can_time_code = TRUE;
  851. }
  852. /* Allocate audio buffers */
  853. This->callback_audio_buffer = HeapAlloc(GetProcessHeap(), 0,
  854. (This->wineasio_number_inputs + This->wineasio_number_outputs) * 2 * This->host_current_buffersize * sizeof(jack_default_audio_sample_t));
  855. if (!This->callback_audio_buffer)
  856. {
  857. ERR("Unable to allocate %i audio buffers\n", This->wineasio_number_inputs + This->wineasio_number_outputs);
  858. return -994;
  859. }
  860. TRACE("%i audio buffers allocated (%i kB)\n", This->wineasio_number_inputs + This->wineasio_number_outputs,
  861. (int) ((This->wineasio_number_inputs + This->wineasio_number_outputs) * 2 * This->host_current_buffersize * sizeof(jack_default_audio_sample_t) / 1024));
  862. for (i = 0; i < This->wineasio_number_inputs; i++)
  863. This->input_channel[i].audio_buffer = This->callback_audio_buffer + (i * 2 * This->host_current_buffersize);
  864. for (i = 0; i < This->wineasio_number_outputs; i++)
  865. This->output_channel[i].audio_buffer = This->callback_audio_buffer + ((This->wineasio_number_inputs + i) * 2 * This->host_current_buffersize);
  866. /* initialize BufferInformation structures */
  867. bufferInfoPerChannel = bufferInfo;
  868. This->host_active_inputs = This->host_active_outputs = 0;
  869. for (i = 0; i < This->wineasio_number_inputs; i++) {
  870. This->input_channel[i].active = false;
  871. }
  872. for (i = 0; i < This->wineasio_number_outputs; i++) {
  873. This->output_channel[i].active = false;
  874. }
  875. for (i = 0; i < numChannels; i++, bufferInfoPerChannel++)
  876. {
  877. if (bufferInfoPerChannel->isInputType)
  878. {
  879. bufferInfoPerChannel->audioBufferStart = &This->input_channel[bufferInfoPerChannel->channelNumber].audio_buffer[0];
  880. bufferInfoPerChannel->audioBufferEnd = &This->input_channel[bufferInfoPerChannel->channelNumber].audio_buffer[This->host_current_buffersize];
  881. This->input_channel[bufferInfoPerChannel->channelNumber].active = true;
  882. This->host_active_inputs++;
  883. /* TRACE("ASIO audio buffer for channel %i as input %li created\n", i, This->host_active_inputs); */
  884. }
  885. else
  886. {
  887. bufferInfoPerChannel->audioBufferStart = &This->output_channel[bufferInfoPerChannel->channelNumber].audio_buffer[0];
  888. bufferInfoPerChannel->audioBufferEnd = &This->output_channel[bufferInfoPerChannel->channelNumber].audio_buffer[This->host_current_buffersize];
  889. This->output_channel[bufferInfoPerChannel->channelNumber].active = true;
  890. This->host_active_outputs++;
  891. /* TRACE("ASIO audio buffer for channel %i as output %li created\n", i, This->host_active_outputs); */
  892. }
  893. }
  894. TRACE("%i audio channels initialized\n", This->host_active_inputs + This->host_active_outputs);
  895. if (jack_activate(This->jack_client))
  896. return -1000;
  897. /* connect to the hardware io */
  898. if (This->wineasio_connect_to_hardware)
  899. {
  900. for (i = 0; i < This->jack_num_input_ports && i < This->wineasio_number_inputs; i++)
  901. if (strstr(jack_port_type(jack_port_by_name(This->jack_client, This->jack_input_ports[i])), "audio"))
  902. jack_connect(This->jack_client, This->jack_input_ports[i], jack_port_name(This->input_channel[i].port));
  903. for (i = 0; i < This->jack_num_output_ports && i < This->wineasio_number_outputs; i++)
  904. if (strstr(jack_port_type(jack_port_by_name(This->jack_client, This->jack_output_ports[i])), "audio"))
  905. jack_connect(This->jack_client, jack_port_name(This->output_channel[i].port), This->jack_output_ports[i]);
  906. }
  907. /* at this point all the connections are made and the jack process callback is outputting silence */
  908. This->host_driver_state = Prepared;
  909. return 0;
  910. }
  911. /*
  912. * LONG DisposeBuffers(void);
  913. * Function: Release allocated buffers
  914. * Returns: -997 if no buffers were previously allocated
  915. * -1000 on missing IO
  916. * Implies: Stop()
  917. */
  918. DEFINE_THISCALL_WRAPPER(DisposeBuffers,4)
  919. HIDDEN LONG STDMETHODCALLTYPE DisposeBuffers(LPWINEASIO iface)
  920. {
  921. IWineASIOImpl *This = (IWineASIOImpl*)iface;
  922. int i;
  923. TRACE("iface: %p\n", iface);
  924. if (This->host_driver_state == Running)
  925. Stop (iface);
  926. if (This->host_driver_state != Prepared)
  927. return -1000;
  928. if (jack_deactivate(This->jack_client))
  929. return -1000;
  930. This->host_callbacks = NULL;
  931. for (i = 0; i < This->wineasio_number_inputs; i++)
  932. {
  933. This->input_channel[i].audio_buffer = NULL;
  934. This->input_channel[i].active = false;
  935. }
  936. for (i = 0; i < This->wineasio_number_outputs; i++)
  937. {
  938. This->output_channel[i].audio_buffer = NULL;
  939. This->output_channel[i].active = false;
  940. }
  941. This->host_active_inputs = This->host_active_outputs = 0;
  942. if (This->callback_audio_buffer)
  943. HeapFree(GetProcessHeap(), 0, This->callback_audio_buffer);
  944. This->host_driver_state = Initialized;
  945. return 0;
  946. }
  947. /*
  948. * LONG ControlPanel(void);
  949. * Function: Open a control panel for driver settings
  950. * Returns: -1000 if no control panel exists. Actually return code should be ignored
  951. * Note: Call sendNotification if something has changed
  952. */
  953. DEFINE_THISCALL_WRAPPER(ControlPanel,4)
  954. HIDDEN LONG STDMETHODCALLTYPE ControlPanel(LPWINEASIO iface)
  955. {
  956. static char arg0[] = "wineasio-settings\0";
  957. static char *arg_list[] = { arg0, NULL };
  958. TRACE("iface: %p\n", iface);
  959. if (vfork() == 0)
  960. {
  961. execvp (arg0, arg_list);
  962. _exit(1);
  963. }
  964. return 0;
  965. }
  966. /*
  967. * LONG Future(LONG selector, void *opt);
  968. * Function: Various
  969. * Returns: Depends on the selector but in general -998 on invalid selector
  970. * -998 if function is unsupported to disable further calls
  971. * 0x3f4847a0 on success, do not use 0
  972. */
  973. DEFINE_THISCALL_WRAPPER(Future,12)
  974. HIDDEN LONG STDMETHODCALLTYPE Future(LPWINEASIO iface, LONG selector, void *opt)
  975. {
  976. IWineASIOImpl *This = (IWineASIOImpl *) iface;
  977. TRACE("iface: %p, selector: %i, opt: %p\n", iface, selector, opt);
  978. switch (selector)
  979. {
  980. case 1:
  981. This->host_can_time_code = TRUE;
  982. TRACE("The host enabled TimeCode\n");
  983. return 0x3f4847a0;
  984. case 2:
  985. This->host_can_time_code = FALSE;
  986. TRACE("The host disabled TimeCode\n");
  987. return 0x3f4847a0;
  988. case 3:
  989. TRACE("The driver denied request to set input monitor\n");
  990. return -1000;
  991. case 4:
  992. TRACE("The driver denied request for Transport control\n");
  993. return -998;
  994. case 5:
  995. TRACE("The driver denied request to set input gain\n");
  996. return -998;
  997. case 6:
  998. TRACE("The driver denied request to get input meter \n");
  999. return -998;
  1000. case 7:
  1001. TRACE("The driver denied request to set output gain\n");
  1002. return -998;
  1003. case 8:
  1004. TRACE("The driver denied request to get output meter\n");
  1005. return -998;
  1006. case 9:
  1007. TRACE("The driver does not support input monitor\n");
  1008. return -998;
  1009. case 10:
  1010. TRACE("The driver supports TimeInfo\n");
  1011. return 0x3f4847a0;
  1012. case 11:
  1013. TRACE("The driver supports TimeCode\n");
  1014. return 0x3f4847a0;
  1015. case 12:
  1016. TRACE("The driver denied request for Transport\n");
  1017. return -998;
  1018. case 13:
  1019. TRACE("The driver does not support input gain\n");
  1020. return -998;
  1021. case 14:
  1022. TRACE("The driver does not support input meter\n");
  1023. return -998;
  1024. case 15:
  1025. TRACE("The driver does not support output gain\n");
  1026. return -998;
  1027. case 16:
  1028. TRACE("The driver does not support output meter\n");
  1029. return -998;
  1030. case 0x23111961:
  1031. TRACE("The driver denied request to set DSD IO format\n");
  1032. return -1000;
  1033. case 0x23111983:
  1034. TRACE("The driver denied request to get DSD IO format\n");
  1035. return -1000;
  1036. case 0x23112004:
  1037. TRACE("The driver does not support DSD IO format\n");
  1038. return -1000;
  1039. default:
  1040. TRACE("ASIOFuture() called with undocumented selector\n");
  1041. return -998;
  1042. }
  1043. }
  1044. /*
  1045. * LONG OutputReady(void);
  1046. * Function: Tells the driver that output bufffers are ready
  1047. * Returns: 0 if supported
  1048. * -1000 to disable
  1049. */
  1050. DEFINE_THISCALL_WRAPPER(OutputReady,4)
  1051. HIDDEN LONG STDMETHODCALLTYPE OutputReady(LPWINEASIO iface)
  1052. {
  1053. /* disabled to stop stand alone NI programs from spamming the console
  1054. TRACE("iface: %p\n", iface); */
  1055. return -1000;
  1056. }
  1057. /****************************************************************************
  1058. * JACK callbacks
  1059. */
  1060. static inline int jack_buffer_size_callback(jack_nframes_t nframes, void *arg)
  1061. {
  1062. IWineASIOImpl *This = (IWineASIOImpl*)arg;
  1063. if(This->host_driver_state != Running)
  1064. return 0;
  1065. if (This->host_callbacks->sendNotification(1, 3, 0, 0))
  1066. This->host_callbacks->sendNotification(3, 0, 0, 0);
  1067. return 0;
  1068. }
  1069. static inline void jack_latency_callback(jack_latency_callback_mode_t mode, void *arg)
  1070. {
  1071. IWineASIOImpl *This = (IWineASIOImpl*)arg;
  1072. if(This->host_driver_state != Running)
  1073. return;
  1074. if (This->host_callbacks->sendNotification(1, 6, 0, 0))
  1075. This->host_callbacks->sendNotification(6, 0, 0, 0);
  1076. return;
  1077. }
  1078. static inline int jack_process_callback(jack_nframes_t nframes, void *arg)
  1079. {
  1080. IWineASIOImpl *This = (IWineASIOImpl*)arg;
  1081. int i;
  1082. jack_transport_state_t jack_transport_state;
  1083. jack_position_t jack_position;
  1084. DWORD time;
  1085. /* output silence if the host callback isn't running yet */
  1086. if (This->host_driver_state != Running)
  1087. {
  1088. for (i = 0; i < This->host_active_outputs; i++)
  1089. bzero(jack_port_get_buffer(This->output_channel[i].port, nframes), 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. jack_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 = jack_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(jack_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. }