jack2 codebase
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.

406 lines
12KB

  1. /*
  2. Copyright (C) 2009 Grame
  3. Copyright (C) 2011 Devin Anderson
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  15. */
  16. #include "JackEngineControl.h"
  17. #include "JackWinMMEDriver.h"
  18. using Jack::JackWinMMEDriver;
  19. JackWinMMEDriver::JackWinMMEDriver(const char *name, const char *alias,
  20. JackLockedEngine *engine,
  21. JackSynchro *table):
  22. JackMidiDriver(name, alias, engine, table)
  23. {
  24. fCaptureChannels = 0;
  25. fPlaybackChannels = 0;
  26. input_ports = 0;
  27. output_ports = 0;
  28. }
  29. JackWinMMEDriver::~JackWinMMEDriver()
  30. {
  31. Stop();
  32. Close();
  33. }
  34. int
  35. JackWinMMEDriver::Attach()
  36. {
  37. jack_nframes_t buffer_size = fEngineControl->fBufferSize;
  38. jack_port_id_t index;
  39. jack_nframes_t latency = buffer_size;
  40. jack_latency_range_t latency_range;
  41. const char *name;
  42. JackPort *port;
  43. latency_range.max = latency;
  44. latency_range.min = latency;
  45. jack_info("JackWinMMEDriver::Attach - fCaptureChannels %d", fCaptureChannels);
  46. jack_info("JackWinMMEDriver::Attach - fPlaybackChannels %d", fPlaybackChannels);
  47. // Inputs
  48. for (int i = 0; i < fCaptureChannels; i++) {
  49. JackWinMMEInputPort *input_port = input_ports[i];
  50. name = input_port->GetName();
  51. index = fGraphManager->AllocatePort(fClientControl.fRefNum, name,
  52. JACK_DEFAULT_MIDI_TYPE,
  53. CaptureDriverFlags, buffer_size);
  54. if (index == NO_PORT) {
  55. jack_error("JackWinMMEDriver::Attach - cannot register input port "
  56. "with name '%s'.", name);
  57. // X: Do we need to deallocate ports?
  58. return -1;
  59. }
  60. port = fGraphManager->GetPort(index);
  61. port->SetAlias(input_port->GetAlias());
  62. port->SetLatencyRange(JackCaptureLatency, &latency_range);
  63. fCapturePortList[i] = index;
  64. }
  65. if (! fEngineControl->fSyncMode) {
  66. latency += buffer_size;
  67. latency_range.max = latency;
  68. latency_range.min = latency;
  69. }
  70. // Outputs
  71. for (int i = 0; i < fPlaybackChannels; i++) {
  72. JackWinMMEOutputPort *output_port = output_ports[i];
  73. name = output_port->GetName();
  74. index = fGraphManager->AllocatePort(fClientControl.fRefNum, name,
  75. JACK_DEFAULT_MIDI_TYPE,
  76. PlaybackDriverFlags, buffer_size);
  77. if (index == NO_PORT) {
  78. jack_error("JackWinMMEDriver::Attach - cannot register output "
  79. "port with name '%s'.", name);
  80. // X: Do we need to deallocate ports?
  81. return -1;
  82. }
  83. port = fGraphManager->GetPort(index);
  84. port->SetAlias(output_port->GetAlias());
  85. port->SetLatencyRange(JackPlaybackLatency, &latency_range);
  86. fPlaybackPortList[i] = index;
  87. }
  88. return 0;
  89. }
  90. int
  91. JackWinMMEDriver::Close()
  92. {
  93. int result = JackMidiDriver::Close();
  94. if (input_ports) {
  95. for (int i = 0; i < fCaptureChannels; i++) {
  96. delete input_ports[i];
  97. }
  98. delete[] input_ports;
  99. input_ports = 0;
  100. }
  101. if (output_ports) {
  102. for (int i = 0; i < fPlaybackChannels; i++) {
  103. delete output_ports[i];
  104. }
  105. delete[] output_ports;
  106. output_ports = 0;
  107. }
  108. return result;
  109. }
  110. int
  111. JackWinMMEDriver::Open(bool capturing, bool playing, int in_channels,
  112. int out_channels, bool monitor,
  113. const char* capture_driver_name,
  114. const char* playback_driver_name,
  115. jack_nframes_t capture_latency,
  116. jack_nframes_t playback_latency)
  117. {
  118. const char *client_name = fClientControl.fName;
  119. int input_count = 0;
  120. int output_count = 0;
  121. int num_potential_inputs = midiInGetNumDevs();
  122. int num_potential_outputs = midiOutGetNumDevs();
  123. jack_info("JackWinMMEDriver::Open - num_potential_inputs %d", num_potential_inputs);
  124. jack_info("JackWinMMEDriver::Open - num_potential_outputs %d", num_potential_outputs);
  125. if (num_potential_inputs) {
  126. try {
  127. input_ports = new JackWinMMEInputPort *[num_potential_inputs];
  128. } catch (std::exception e) {
  129. jack_error("JackWinMMEDriver::Open - while creating input port "
  130. "array: %s", e.what());
  131. return -1;
  132. }
  133. for (int i = 0; i < num_potential_inputs; i++) {
  134. try {
  135. input_ports[input_count] =
  136. new JackWinMMEInputPort(fAliasName, client_name,
  137. capture_driver_name, i);
  138. } catch (std::exception e) {
  139. jack_error("JackWinMMEDriver::Open - while creating input "
  140. "port: %s", e.what());
  141. continue;
  142. }
  143. input_count++;
  144. }
  145. }
  146. if (num_potential_outputs) {
  147. try {
  148. output_ports = new JackWinMMEOutputPort *[num_potential_outputs];
  149. } catch (std::exception e) {
  150. jack_error("JackWinMMEDriver::Open - while creating output port "
  151. "array: %s", e.what());
  152. goto destroy_input_ports;
  153. }
  154. for (int i = 0; i < num_potential_outputs; i++) {
  155. try {
  156. output_ports[output_count] =
  157. new JackWinMMEOutputPort(fAliasName, client_name,
  158. playback_driver_name, i);
  159. } catch (std::exception e) {
  160. jack_error("JackWinMMEDriver::Open - while creating output "
  161. "port: %s", e.what());
  162. continue;
  163. }
  164. output_count++;
  165. }
  166. }
  167. jack_info("JackWinMMEDriver::Open - input_count %d", input_count);
  168. jack_info("JackWinMMEDriver::Open - output_count %d", output_count);
  169. if (! (input_count || output_count)) {
  170. jack_error("JackWinMMEDriver::Open - no WinMME inputs or outputs "
  171. "allocated.");
  172. } else if (! JackMidiDriver::Open(capturing, playing, input_count,
  173. output_count, monitor,
  174. capture_driver_name,
  175. playback_driver_name, capture_latency,
  176. playback_latency)) {
  177. return 0;
  178. }
  179. destroy_input_ports:
  180. if (input_ports) {
  181. for (int i = 0; i < input_count; i++) {
  182. delete input_ports[i];
  183. }
  184. delete[] input_ports;
  185. input_ports = 0;
  186. }
  187. return -1;
  188. }
  189. int
  190. JackWinMMEDriver::Read()
  191. {
  192. jack_nframes_t buffer_size = fEngineControl->fBufferSize;
  193. for (int i = 0; i < fCaptureChannels; i++) {
  194. input_ports[i]->ProcessJack(GetInputBuffer(i), buffer_size);
  195. }
  196. return 0;
  197. }
  198. int
  199. JackWinMMEDriver::Write()
  200. {
  201. jack_nframes_t buffer_size = fEngineControl->fBufferSize;
  202. for (int i = 0; i < fPlaybackChannels; i++) {
  203. output_ports[i]->ProcessJack(GetOutputBuffer(i), buffer_size);
  204. }
  205. return 0;
  206. }
  207. int
  208. JackWinMMEDriver::Start()
  209. {
  210. jack_info("JackWinMMEDriver::Start - Starting driver.");
  211. JackMidiDriver::Start();
  212. int input_count = 0;
  213. int output_count = 0;
  214. jack_info("JackWinMMEDriver::Start - Enabling input ports.");
  215. for (; input_count < fCaptureChannels; input_count++) {
  216. if (input_ports[input_count]->Start() < 0) {
  217. jack_error("JackWinMMEDriver::Start - Failed to enable input "
  218. "port.");
  219. goto stop_input_ports;
  220. }
  221. }
  222. jack_info("JackWinMMEDriver::Start - Enabling output ports.");
  223. for (; output_count < fPlaybackChannels; output_count++) {
  224. if (output_ports[output_count]->Start() < 0) {
  225. jack_error("JackWinMMEDriver::Start - Failed to enable output "
  226. "port.");
  227. goto stop_output_ports;
  228. }
  229. }
  230. jack_info("JackWinMMEDriver::Start - Driver started.");
  231. return 0;
  232. stop_output_ports:
  233. for (int i = 0; i < output_count; i++) {
  234. if (output_ports[i]->Stop() < 0) {
  235. jack_error("JackWinMMEDriver::Start - Failed to disable output "
  236. "port.");
  237. }
  238. }
  239. stop_input_ports:
  240. for (int i = 0; i < input_count; i++) {
  241. if (input_ports[i]->Stop() < 0) {
  242. jack_error("JackWinMMEDriver::Start - Failed to disable input "
  243. "port.");
  244. }
  245. }
  246. return -1;
  247. }
  248. int
  249. JackWinMMEDriver::Stop()
  250. {
  251. int result = 0;
  252. jack_info("JackWinMMEDriver::Stop - disabling input ports.");
  253. for (int i = 0; i < fCaptureChannels; i++) {
  254. if (input_ports[i]->Stop() < 0) {
  255. jack_error("JackWinMMEDriver::Stop - Failed to disable input "
  256. "port.");
  257. result = -1;
  258. }
  259. }
  260. jack_info("JackWinMMEDriver::Stop - disabling output ports.");
  261. for (int i = 0; i < fPlaybackChannels; i++) {
  262. if (output_ports[i]->Stop() < 0) {
  263. jack_error("JackWinMMEDriver::Stop - Failed to disable output "
  264. "port.");
  265. result = -1;
  266. }
  267. }
  268. return result;
  269. }
  270. #ifdef __cplusplus
  271. extern "C"
  272. {
  273. #endif
  274. SERVER_EXPORT jack_driver_desc_t * driver_get_descriptor()
  275. {
  276. jack_driver_desc_t * desc;
  277. //unsigned int i;
  278. desc = (jack_driver_desc_t*)calloc (1, sizeof (jack_driver_desc_t));
  279. strcpy(desc->name, "winmme"); // size MUST be less then JACK_DRIVER_NAME_MAX + 1
  280. strcpy(desc->desc, "WinMME API based MIDI backend"); // size MUST be less then JACK_DRIVER_PARAM_DESC + 1
  281. desc->nparams = 0;
  282. desc->params = (jack_driver_param_desc_t*)calloc (desc->nparams, sizeof (jack_driver_param_desc_t));
  283. return desc;
  284. }
  285. SERVER_EXPORT Jack::JackDriverClientInterface* driver_initialize(Jack::JackLockedEngine* engine, Jack::JackSynchro* table, const JSList* params)
  286. {
  287. /*
  288. unsigned int capture_ports = 2;
  289. unsigned int playback_ports = 2;
  290. unsigned long wait_time = 0;
  291. const JSList * node;
  292. const jack_driver_param_t * param;
  293. bool monitor = false;
  294. for (node = params; node; node = jack_slist_next (node)) {
  295. param = (const jack_driver_param_t *) node->data;
  296. switch (param->character) {
  297. case 'C':
  298. capture_ports = param->value.ui;
  299. break;
  300. case 'P':
  301. playback_ports = param->value.ui;
  302. break;
  303. case 'r':
  304. sample_rate = param->value.ui;
  305. break;
  306. case 'p':
  307. period_size = param->value.ui;
  308. break;
  309. case 'w':
  310. wait_time = param->value.ui;
  311. break;
  312. case 'm':
  313. monitor = param->value.i;
  314. break;
  315. }
  316. }
  317. */
  318. Jack::JackDriverClientInterface* driver = new Jack::JackWinMMEDriver("system_midi", "winmme", engine, table);
  319. if (driver->Open(1, 1, 0, 0, false, "in", "out", 0, 0) == 0) {
  320. return driver;
  321. } else {
  322. delete driver;
  323. return NULL;
  324. }
  325. }
  326. #ifdef __cplusplus
  327. }
  328. #endif
  329. /*
  330. jack_connect system:midi_capture_1 system_midi:playback_1
  331. jack_connect system:midi_capture_1 system_midi:playback_2
  332. jack_connect system:midi_capture_1 system_midi:playback_1
  333. jack_connect system:midi_capture_1 system_midi:playback_1
  334. jack_connect system:midi_capture_1 system_midi:playback_1
  335. jack_connect system_midi:capture_1 system:midi_playback_1
  336. jack_connect system_midi:capture_2 system:midi_playback_1
  337. jack_connect system_midi:capture_1 system_midi:playback_1
  338. */