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.

392 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. // Inputs
  46. for (int i = 0; i < fCaptureChannels; i++) {
  47. JackWinMMEInputPort *input_port = input_ports[i];
  48. name = input_port->GetName();
  49. index = fGraphManager->AllocatePort(fClientControl.fRefNum, name,
  50. JACK_DEFAULT_MIDI_TYPE,
  51. CaptureDriverFlags, buffer_size);
  52. if (index == NO_PORT) {
  53. jack_error("JackWinMMEDriver::Attach - cannot register input port "
  54. "with name '%s'.", name);
  55. // X: Do we need to deallocate ports?
  56. return -1;
  57. }
  58. port = fGraphManager->GetPort(index);
  59. port->SetAlias(input_port->GetAlias());
  60. port->SetLatencyRange(JackCaptureLatency, &latency_range);
  61. fCapturePortList[i] = index;
  62. }
  63. if (! fEngineControl->fSyncMode) {
  64. latency += buffer_size;
  65. latency_range.max = latency;
  66. latency_range.min = latency;
  67. }
  68. // Outputs
  69. for (int i = 0; i < fPlaybackChannels; i++) {
  70. JackWinMMEOutputPort *output_port = output_ports[i];
  71. name = output_port->GetName();
  72. index = fGraphManager->AllocatePort(fClientControl.fRefNum, name,
  73. JACK_DEFAULT_MIDI_TYPE,
  74. PlaybackDriverFlags, buffer_size);
  75. if (index == NO_PORT) {
  76. jack_error("JackWinMMEDriver::Attach - cannot register output "
  77. "port with name '%s'.", name);
  78. // X: Do we need to deallocate ports?
  79. return -1;
  80. }
  81. port = fGraphManager->GetPort(index);
  82. port->SetAlias(output_port->GetAlias());
  83. port->SetLatencyRange(JackPlaybackLatency, &latency_range);
  84. fPlaybackPortList[i] = index;
  85. }
  86. return 0;
  87. }
  88. int
  89. JackWinMMEDriver::Close()
  90. {
  91. int result = JackMidiDriver::Close();
  92. if (input_ports) {
  93. for (int i = 0; i < fCaptureChannels; i++) {
  94. delete input_ports[i];
  95. }
  96. delete[] input_ports;
  97. input_ports = 0;
  98. }
  99. if (output_ports) {
  100. for (int i = 0; i < fPlaybackChannels; i++) {
  101. delete output_ports[i];
  102. }
  103. delete[] output_ports;
  104. output_ports = 0;
  105. }
  106. return result;
  107. }
  108. int
  109. JackWinMMEDriver::Open(bool capturing, bool playing, int in_channels,
  110. int out_channels, bool monitor,
  111. const char* capture_driver_name,
  112. const char* playback_driver_name,
  113. jack_nframes_t capture_latency,
  114. jack_nframes_t playback_latency)
  115. {
  116. const char *client_name = fClientControl.fName;
  117. int input_count = 0;
  118. int num_potential_inputs = midiInGetNumDevs();
  119. int num_potential_outputs = midiOutGetNumDevs();
  120. int output_count = 0;
  121. if (num_potential_inputs) {
  122. try {
  123. input_ports = new JackWinMMEInputPort *[num_potential_inputs];
  124. } catch (std::exception e) {
  125. jack_error("JackWinMMEDriver::Open - while creating input port "
  126. "array: %s", e.what());
  127. return -1;
  128. }
  129. for (int i = 0; i < num_potential_inputs; i++) {
  130. try {
  131. input_ports[input_count] =
  132. new JackWinMMEInputPort(fAliasName, client_name,
  133. capture_driver_name, i);
  134. } catch (std::exception e) {
  135. jack_error("JackWinMMEDriver::Open - while creating input "
  136. "port: %s", e.what());
  137. continue;
  138. }
  139. input_count++;
  140. }
  141. }
  142. if (num_potential_outputs) {
  143. try {
  144. output_ports = new JackWinMMEOutputPort *[num_potential_outputs];
  145. } catch (std::exception e) {
  146. jack_error("JackWinMMEDriver::Open - while creating output port "
  147. "array: %s", e.what());
  148. goto destroy_input_ports;
  149. }
  150. for (int i = 0; i < num_potential_outputs; i++) {
  151. try {
  152. output_ports[output_count] =
  153. new JackWinMMEOutputPort(fAliasName, client_name,
  154. playback_driver_name, i);
  155. } catch (std::exception e) {
  156. jack_error("JackWinMMEDriver::Open - while creating output "
  157. "port: %s", e.what());
  158. continue;
  159. }
  160. output_count++;
  161. }
  162. }
  163. if (! (input_count || output_count)) {
  164. jack_error("JackWinMMEDriver::Open - no WinMME inputs or outputs "
  165. "allocated.");
  166. } else if (! JackMidiDriver::Open(capturing, playing, input_count,
  167. output_count, monitor,
  168. capture_driver_name,
  169. playback_driver_name, capture_latency,
  170. playback_latency)) {
  171. return 0;
  172. }
  173. destroy_input_ports:
  174. if (input_ports) {
  175. for (int i = 0; i < input_count; i++) {
  176. delete input_ports[i];
  177. }
  178. delete[] input_ports;
  179. input_ports = 0;
  180. }
  181. return -1;
  182. }
  183. int
  184. JackWinMMEDriver::Read()
  185. {
  186. jack_nframes_t buffer_size = fEngineControl->fBufferSize;
  187. for (int i = 0; i < fCaptureChannels; i++) {
  188. input_ports[i]->ProcessJack(GetInputBuffer(i), buffer_size);
  189. }
  190. return 0;
  191. }
  192. int
  193. JackWinMMEDriver::Start()
  194. {
  195. jack_info("JackWinMMEDriver::Start - Starting driver.");
  196. JackMidiDriver::Start();
  197. int input_count = 0;
  198. int output_count = 0;
  199. jack_info("JackWinMMEDriver::Start - Enabling input ports.");
  200. for (; input_count < fCaptureChannels; input_count++) {
  201. if (input_ports[input_count]->Start() < 0) {
  202. jack_error("JackWinMMEDriver::Start - Failed to enable input "
  203. "port.");
  204. goto stop_input_ports;
  205. }
  206. }
  207. jack_info("JackWinMMEDriver::Start - Enabling output ports.");
  208. for (; output_count < fPlaybackChannels; output_count++) {
  209. if (output_ports[output_count]->Start() < 0) {
  210. jack_error("JackWinMMEDriver::Start - Failed to enable output "
  211. "port.");
  212. goto stop_output_ports;
  213. }
  214. }
  215. jack_info("JackWinMMEDriver::Start - Driver started.");
  216. return 0;
  217. stop_output_ports:
  218. for (int i = 0; i < output_count; i++) {
  219. if (output_ports[i]->Stop() < 0) {
  220. jack_error("JackWinMMEDriver::Start - Failed to disable output "
  221. "port.");
  222. }
  223. }
  224. stop_input_ports:
  225. for (int i = 0; i < input_count; i++) {
  226. if (input_ports[i]->Stop() < 0) {
  227. jack_error("JackWinMMEDriver::Start - Failed to disable input "
  228. "port.");
  229. }
  230. }
  231. return -1;
  232. }
  233. int
  234. JackWinMMEDriver::Stop()
  235. {
  236. int result = 0;
  237. jack_info("JackWinMMEDriver::Stop - disabling input ports.");
  238. for (int i = 0; i < fCaptureChannels; i++) {
  239. if (input_ports[i]->Stop() < 0) {
  240. jack_error("JackWinMMEDriver::Stop - Failed to disable input "
  241. "port.");
  242. result = -1;
  243. }
  244. }
  245. jack_info("JackWinMMEDriver::Stop - disabling output ports.");
  246. for (int i = 0; i < fPlaybackChannels; i++) {
  247. if (output_ports[i]->Stop() < 0) {
  248. jack_error("JackWinMMEDriver::Stop - Failed to disable output "
  249. "port.");
  250. result = -1;
  251. }
  252. }
  253. return result;
  254. }
  255. int
  256. JackWinMMEDriver::Write()
  257. {
  258. jack_nframes_t buffer_size = fEngineControl->fBufferSize;
  259. for (int i = 0; i < fPlaybackChannels; i++) {
  260. output_ports[i]->ProcessJack(GetOutputBuffer(i), buffer_size);
  261. }
  262. return 0;
  263. }
  264. #ifdef __cplusplus
  265. extern "C"
  266. {
  267. #endif
  268. SERVER_EXPORT jack_driver_desc_t * driver_get_descriptor()
  269. {
  270. jack_driver_desc_t * desc;
  271. //unsigned int i;
  272. desc = (jack_driver_desc_t*)calloc (1, sizeof (jack_driver_desc_t));
  273. strcpy(desc->name, "winmme"); // size MUST be less then JACK_DRIVER_NAME_MAX + 1
  274. strcpy(desc->desc, "WinMME API based MIDI backend"); // size MUST be less then JACK_DRIVER_PARAM_DESC + 1
  275. desc->nparams = 0;
  276. desc->params = (jack_driver_param_desc_t*)calloc (desc->nparams, sizeof (jack_driver_param_desc_t));
  277. return desc;
  278. }
  279. SERVER_EXPORT Jack::JackDriverClientInterface* driver_initialize(Jack::JackLockedEngine* engine, Jack::JackSynchro* table, const JSList* params)
  280. {
  281. /*
  282. unsigned int capture_ports = 2;
  283. unsigned int playback_ports = 2;
  284. unsigned long wait_time = 0;
  285. const JSList * node;
  286. const jack_driver_param_t * param;
  287. bool monitor = false;
  288. for (node = params; node; node = jack_slist_next (node)) {
  289. param = (const jack_driver_param_t *) node->data;
  290. switch (param->character) {
  291. case 'C':
  292. capture_ports = param->value.ui;
  293. break;
  294. case 'P':
  295. playback_ports = param->value.ui;
  296. break;
  297. case 'r':
  298. sample_rate = param->value.ui;
  299. break;
  300. case 'p':
  301. period_size = param->value.ui;
  302. break;
  303. case 'w':
  304. wait_time = param->value.ui;
  305. break;
  306. case 'm':
  307. monitor = param->value.i;
  308. break;
  309. }
  310. }
  311. */
  312. Jack::JackDriverClientInterface* driver = new Jack::JackWinMMEDriver("system_midi", "winmme", engine, table);
  313. if (driver->Open(1, 1, 0, 0, false, "in", "out", 0, 0) == 0) {
  314. return driver;
  315. } else {
  316. delete driver;
  317. return NULL;
  318. }
  319. }
  320. #ifdef __cplusplus
  321. }
  322. #endif
  323. /*
  324. jack_connect system:midi_capture_1 system_midi:playback_1
  325. jack_connect system:midi_capture_1 system_midi:playback_2
  326. jack_connect system:midi_capture_1 system_midi:playback_1
  327. jack_connect system:midi_capture_1 system_midi:playback_1
  328. jack_connect system:midi_capture_1 system_midi:playback_1
  329. jack_connect system_midi:capture_1 system:midi_playback_1
  330. jack_connect system_midi:capture_2 system:midi_playback_1
  331. jack_connect system_midi:capture_1 system_midi:playback_1
  332. */