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.

179 lines
5.1KB

  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. snd_rawmidi_params_free(params);
  78. num_fds = snd_rawmidi_poll_descriptors_count(rawmidi);
  79. if (! num_fds) {
  80. error_message = "returned '0' count for poll descriptors";
  81. func = "snd_rawmidi_poll_descriptors_count";
  82. goto close;
  83. }
  84. snprintf(alias, sizeof(alias), "%s%d", alias_prefix, index);
  85. device_name = snd_rawmidi_info_get_subdevice_name(info);
  86. if (! strlen(device_name)) {
  87. device_name = snd_rawmidi_info_get_name(info);
  88. }
  89. snprintf(name, sizeof(name), "system:%s %s", device_name, name_suffix);
  90. return;
  91. free_params:
  92. snd_rawmidi_params_free(params);
  93. close:
  94. snd_rawmidi_close(rawmidi);
  95. handle_error:
  96. throw std::runtime_error(std::string(func) + ": " + error_message);
  97. }
  98. JackALSARawMidiPort::~JackALSARawMidiPort()
  99. {
  100. if (rawmidi) {
  101. int code = snd_rawmidi_close(rawmidi);
  102. if (code) {
  103. jack_error("JackALSARawMidiPort::~JackALSARawMidiPort - "
  104. "snd_rawmidi_close: %s", snd_strerror(code));
  105. }
  106. rawmidi = 0;
  107. }
  108. }
  109. const char *
  110. JackALSARawMidiPort::GetAlias()
  111. {
  112. return alias;
  113. }
  114. const char *
  115. JackALSARawMidiPort::GetName()
  116. {
  117. return name;
  118. }
  119. int
  120. JackALSARawMidiPort::GetPollDescriptorCount()
  121. {
  122. return num_fds;
  123. }
  124. bool
  125. JackALSARawMidiPort::PopulatePollDescriptors(struct pollfd *poll_fd)
  126. {
  127. bool result = snd_rawmidi_poll_descriptors(rawmidi, poll_fd, num_fds) ==
  128. num_fds;
  129. if (result) {
  130. poll_fds = poll_fd;
  131. }
  132. return result;
  133. }
  134. bool
  135. JackALSARawMidiPort::ProcessPollEvents(unsigned short *revents)
  136. {
  137. int code = snd_rawmidi_poll_descriptors_revents(rawmidi, poll_fds, num_fds,
  138. revents);
  139. if (code) {
  140. jack_error("JackALSARawMidiPort::ProcessPollEvents - "
  141. "snd_rawmidi_poll_descriptors_revents: %s",
  142. snd_strerror(code));
  143. return false;
  144. }
  145. if ((*revents) & POLLNVAL) {
  146. jack_error("JackALSARawMidiPort::ProcessPollEvents - the file "
  147. "descriptor is invalid.");
  148. return false;
  149. }
  150. if ((*revents) & POLLERR) {
  151. jack_error("JackALSARawMidiPort::ProcessPollEvents - an error has "
  152. "occurred on the device or stream.");
  153. return false;
  154. }
  155. return true;
  156. }
  157. void
  158. JackALSARawMidiPort::SetPollEventMask(unsigned short events)
  159. {
  160. for (int i = 0; i < num_fds; i++) {
  161. (poll_fds + i)->events = events;
  162. }
  163. }