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.

185 lines
5.3KB

  1. /*
  2. Copyright (C) 2011 Devin Anderson
  3. This program is free software; you can redistribute it and/or modify
  4. it under the terms of the GNU General Public License as published by
  5. the Free Software Foundation; either version 2 of the License, or
  6. (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with this program; if not, write to the Free Software
  13. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  14. */
  15. #include <stdexcept>
  16. #include <string>
  17. #include "JackALSARawMidiPort.h"
  18. #include "JackError.h"
  19. using Jack::JackALSARawMidiPort;
  20. JackALSARawMidiPort::JackALSARawMidiPort(snd_rawmidi_info_t *info,
  21. size_t index)
  22. {
  23. char device_id[32];
  24. snprintf(device_id, sizeof(device_id), "hw:%d,%d,%d",
  25. snd_rawmidi_info_get_card(info),
  26. snd_rawmidi_info_get_device(info),
  27. snd_rawmidi_info_get_subdevice(info));
  28. const char *alias_prefix;
  29. const char *error_message;
  30. snd_rawmidi_t **in;
  31. snd_rawmidi_t **out;
  32. const char *name_suffix;
  33. if (snd_rawmidi_info_get_stream(info) == SND_RAWMIDI_STREAM_OUTPUT) {
  34. alias_prefix = "system:midi_playback_";
  35. in = 0;
  36. name_suffix = "out";
  37. out = &rawmidi;
  38. } else {
  39. alias_prefix = "system:midi_capture_";
  40. in = &rawmidi;
  41. name_suffix = "in";
  42. out = 0;
  43. }
  44. const char *device_name;
  45. const char *func;
  46. int code = snd_rawmidi_open(in, out, device_id, SND_RAWMIDI_NONBLOCK);
  47. if (code) {
  48. error_message = snd_strerror(code);
  49. func = "snd_rawmidi_open";
  50. goto handle_error;
  51. }
  52. snd_rawmidi_params_t *params;
  53. code = snd_rawmidi_params_malloc(&params);
  54. if (code) {
  55. error_message = snd_strerror(code);
  56. func = "snd_rawmidi_params_malloc";
  57. goto close;
  58. }
  59. code = snd_rawmidi_params_current(rawmidi, params);
  60. if (code) {
  61. error_message = snd_strerror(code);
  62. func = "snd_rawmidi_params_current";
  63. goto free_params;
  64. }
  65. code = snd_rawmidi_params_set_avail_min(rawmidi, params, 1);
  66. if (code) {
  67. error_message = snd_strerror(code);
  68. func = "snd_rawmidi_params_set_avail_min";
  69. goto free_params;
  70. }
  71. code = snd_rawmidi_params_set_no_active_sensing(rawmidi, params, 1);
  72. if (code) {
  73. error_message = snd_strerror(code);
  74. func = "snd_rawmidi_params_set_no_active_sensing";
  75. goto free_params;
  76. }
  77. code = snd_rawmidi_params(rawmidi, params);
  78. if (code) {
  79. error_message = snd_strerror(code);
  80. func = "snd_rawmidi_params";
  81. goto free_params;
  82. }
  83. snd_rawmidi_params_free(params);
  84. num_fds = snd_rawmidi_poll_descriptors_count(rawmidi);
  85. if (! num_fds) {
  86. error_message = "returned '0' count for poll descriptors";
  87. func = "snd_rawmidi_poll_descriptors_count";
  88. goto close;
  89. }
  90. snprintf(alias, sizeof(alias), "%s%d", alias_prefix, index);
  91. device_name = snd_rawmidi_info_get_subdevice_name(info);
  92. if (! strlen(device_name)) {
  93. device_name = snd_rawmidi_info_get_name(info);
  94. }
  95. snprintf(name, sizeof(name), "system:%s %s", device_name, name_suffix);
  96. return;
  97. free_params:
  98. snd_rawmidi_params_free(params);
  99. close:
  100. snd_rawmidi_close(rawmidi);
  101. handle_error:
  102. throw std::runtime_error(std::string(func) + ": " + error_message);
  103. }
  104. JackALSARawMidiPort::~JackALSARawMidiPort()
  105. {
  106. if (rawmidi) {
  107. int code = snd_rawmidi_close(rawmidi);
  108. if (code) {
  109. jack_error("JackALSARawMidiPort::~JackALSARawMidiPort - "
  110. "snd_rawmidi_close: %s", snd_strerror(code));
  111. }
  112. rawmidi = 0;
  113. }
  114. }
  115. const char *
  116. JackALSARawMidiPort::GetAlias()
  117. {
  118. return alias;
  119. }
  120. const char *
  121. JackALSARawMidiPort::GetName()
  122. {
  123. return name;
  124. }
  125. int
  126. JackALSARawMidiPort::GetPollDescriptorCount()
  127. {
  128. return num_fds;
  129. }
  130. bool
  131. JackALSARawMidiPort::PopulatePollDescriptors(struct pollfd *poll_fd)
  132. {
  133. bool result = snd_rawmidi_poll_descriptors(rawmidi, poll_fd, num_fds) ==
  134. num_fds;
  135. if (result) {
  136. poll_fds = poll_fd;
  137. }
  138. return result;
  139. }
  140. bool
  141. JackALSARawMidiPort::ProcessPollEvents(unsigned short *revents)
  142. {
  143. int code = snd_rawmidi_poll_descriptors_revents(rawmidi, poll_fds, num_fds,
  144. revents);
  145. if (code) {
  146. jack_error("JackALSARawMidiPort::ProcessPollEvents - "
  147. "snd_rawmidi_poll_descriptors_revents: %s",
  148. snd_strerror(code));
  149. return false;
  150. }
  151. if ((*revents) & POLLNVAL) {
  152. jack_error("JackALSARawMidiPort::ProcessPollEvents - the file "
  153. "descriptor is invalid.");
  154. return false;
  155. }
  156. if ((*revents) & POLLERR) {
  157. jack_error("JackALSARawMidiPort::ProcessPollEvents - an error has "
  158. "occurred on the device or stream.");
  159. return false;
  160. }
  161. return true;
  162. }
  163. void
  164. JackALSARawMidiPort::SetPollEventMask(unsigned short events)
  165. {
  166. for (int i = 0; i < num_fds; i++) {
  167. (poll_fds + i)->events = events;
  168. }
  169. }