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.

409 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. /*
  202. jack_nframes_t buffer_size = fEngineControl->fBufferSize;
  203. for (int i = 0; i < fPlaybackChannels; i++) {
  204. output_ports[i]->ProcessJack(GetOutputBuffer(i), buffer_size);
  205. }
  206. */
  207. return 0;
  208. }
  209. int
  210. JackWinMMEDriver::Start()
  211. {
  212. jack_info("JackWinMMEDriver::Start - Starting driver.");
  213. JackMidiDriver::Start();
  214. int input_count = 0;
  215. int output_count = 0;
  216. jack_info("JackWinMMEDriver::Start - Enabling input ports.");
  217. for (; input_count < fCaptureChannels; input_count++) {
  218. if (input_ports[input_count]->Start() < 0) {
  219. jack_error("JackWinMMEDriver::Start - Failed to enable input "
  220. "port.");
  221. goto stop_input_ports;
  222. }
  223. }
  224. jack_info("JackWinMMEDriver::Start - Enabling output ports.");
  225. for (; output_count < fPlaybackChannels; output_count++) {
  226. if (output_ports[output_count]->Start() < 0) {
  227. jack_error("JackWinMMEDriver::Start - Failed to enable output "
  228. "port.");
  229. goto stop_output_ports;
  230. }
  231. }
  232. jack_info("JackWinMMEDriver::Start - Driver started.");
  233. return 0;
  234. stop_output_ports:
  235. for (int i = 0; i < output_count; i++) {
  236. if (output_ports[i]->Stop() < 0) {
  237. jack_error("JackWinMMEDriver::Start - Failed to disable output "
  238. "port.");
  239. }
  240. }
  241. stop_input_ports:
  242. for (int i = 0; i < input_count; i++) {
  243. if (input_ports[i]->Stop() < 0) {
  244. jack_error("JackWinMMEDriver::Start - Failed to disable input "
  245. "port.");
  246. }
  247. }
  248. return -1;
  249. }
  250. int
  251. JackWinMMEDriver::Stop()
  252. {
  253. int result = 0;
  254. jack_info("JackWinMMEDriver::Stop - disabling input ports.");
  255. for (int i = 0; i < fCaptureChannels; i++) {
  256. if (input_ports[i]->Stop() < 0) {
  257. jack_error("JackWinMMEDriver::Stop - Failed to disable input "
  258. "port.");
  259. result = -1;
  260. }
  261. }
  262. jack_info("JackWinMMEDriver::Stop - disabling output ports.");
  263. for (int i = 0; i < fPlaybackChannels; i++) {
  264. if (output_ports[i]->Stop() < 0) {
  265. jack_error("JackWinMMEDriver::Stop - Failed to disable output "
  266. "port.");
  267. result = -1;
  268. }
  269. }
  270. return result;
  271. }
  272. #ifdef __cplusplus
  273. extern "C"
  274. {
  275. #endif
  276. SERVER_EXPORT jack_driver_desc_t * driver_get_descriptor()
  277. {
  278. jack_driver_desc_t * desc;
  279. //unsigned int i;
  280. desc = (jack_driver_desc_t*)calloc (1, sizeof (jack_driver_desc_t));
  281. strcpy(desc->name, "winmme"); // size MUST be less then JACK_DRIVER_NAME_MAX + 1
  282. strcpy(desc->desc, "WinMME API based MIDI backend"); // size MUST be less then JACK_DRIVER_PARAM_DESC + 1
  283. desc->nparams = 0;
  284. desc->params = (jack_driver_param_desc_t*)calloc (desc->nparams, sizeof (jack_driver_param_desc_t));
  285. return desc;
  286. }
  287. SERVER_EXPORT Jack::JackDriverClientInterface* driver_initialize(Jack::JackLockedEngine* engine, Jack::JackSynchro* table, const JSList* params)
  288. {
  289. /*
  290. unsigned int capture_ports = 2;
  291. unsigned int playback_ports = 2;
  292. unsigned long wait_time = 0;
  293. const JSList * node;
  294. const jack_driver_param_t * param;
  295. bool monitor = false;
  296. for (node = params; node; node = jack_slist_next (node)) {
  297. param = (const jack_driver_param_t *) node->data;
  298. switch (param->character) {
  299. case 'C':
  300. capture_ports = param->value.ui;
  301. break;
  302. case 'P':
  303. playback_ports = param->value.ui;
  304. break;
  305. case 'r':
  306. sample_rate = param->value.ui;
  307. break;
  308. case 'p':
  309. period_size = param->value.ui;
  310. break;
  311. case 'w':
  312. wait_time = param->value.ui;
  313. break;
  314. case 'm':
  315. monitor = param->value.i;
  316. break;
  317. }
  318. }
  319. */
  320. Jack::JackDriverClientInterface* driver = new Jack::JackWinMMEDriver("system_midi", "winmme", engine, table);
  321. if (driver->Open(1, 1, 0, 0, false, "in", "out", 0, 0) == 0) {
  322. return driver;
  323. } else {
  324. delete driver;
  325. return NULL;
  326. }
  327. }
  328. #ifdef __cplusplus
  329. }
  330. #endif
  331. /*
  332. jack_connect system:midi_capture_1 system_midi:playback_1
  333. jack_connect system:midi_capture_1 system_midi:playback_2
  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_1 system_midi:playback_1
  337. jack_connect system_midi:capture_1 system:midi_playback_1
  338. jack_connect system_midi:capture_2 system:midi_playback_1
  339. jack_connect system_midi:capture_1 system_midi:playback_1
  340. */