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.

160 lines
4.4KB

  1. #include <stdexcept>
  2. #include <string>
  3. #include "JackALSARawMidiPort.h"
  4. #include "JackError.h"
  5. using Jack::JackALSARawMidiPort;
  6. JackALSARawMidiPort::JackALSARawMidiPort(snd_rawmidi_info_t *info,
  7. size_t index)
  8. {
  9. char device_id[32];
  10. snprintf(device_id, sizeof(device_id), "hw:%d,%d,%d",
  11. snd_rawmidi_info_get_card(info),
  12. snd_rawmidi_info_get_device(info),
  13. snd_rawmidi_info_get_subdevice(info));
  14. const char *alias_prefix;
  15. const char *error_message;
  16. snd_rawmidi_t **in;
  17. snd_rawmidi_t **out;
  18. const char *name_suffix;
  19. if (snd_rawmidi_info_get_stream(info) == SND_RAWMIDI_STREAM_OUTPUT) {
  20. alias_prefix = "system:midi_playback_";
  21. in = 0;
  22. name_suffix = "out";
  23. out = &rawmidi;
  24. } else {
  25. alias_prefix = "system:midi_capture_";
  26. in = &rawmidi;
  27. name_suffix = "in";
  28. out = 0;
  29. }
  30. const char *device_name;
  31. const char *func;
  32. int code = snd_rawmidi_open(in, out, device_id, SND_RAWMIDI_NONBLOCK);
  33. if (code) {
  34. error_message = snd_strerror(code);
  35. func = "snd_rawmidi_open";
  36. goto handle_error;
  37. }
  38. snd_rawmidi_params_t *params;
  39. code = snd_rawmidi_params_malloc(&params);
  40. if (code) {
  41. error_message = snd_strerror(code);
  42. func = "snd_rawmidi_params_malloc";
  43. goto close;
  44. }
  45. code = snd_rawmidi_params_current(rawmidi, params);
  46. if (code) {
  47. error_message = snd_strerror(code);
  48. func = "snd_rawmidi_params_current";
  49. goto free_params;
  50. }
  51. code = snd_rawmidi_params_set_avail_min(rawmidi, params, 1);
  52. if (code) {
  53. error_message = snd_strerror(code);
  54. func = "snd_rawmidi_params_set_avail_min";
  55. goto free_params;
  56. }
  57. code = snd_rawmidi_params_set_no_active_sensing(rawmidi, params, 1);
  58. if (code) {
  59. error_message = snd_strerror(code);
  60. func = "snd_rawmidi_params_set_no_active_sensing";
  61. goto free_params;
  62. }
  63. snd_rawmidi_params_free(params);
  64. num_fds = snd_rawmidi_poll_descriptors_count(rawmidi);
  65. if (! num_fds) {
  66. error_message = "returned '0' count for poll descriptors";
  67. func = "snd_rawmidi_poll_descriptors_count";
  68. goto close;
  69. }
  70. snprintf(alias, sizeof(alias), "%s%d", alias_prefix, index);
  71. device_name = snd_rawmidi_info_get_subdevice_name(info);
  72. if (! strlen(device_name)) {
  73. device_name = snd_rawmidi_info_get_name(info);
  74. }
  75. snprintf(name, sizeof(name), "system:%s %s", device_name, name_suffix);
  76. return;
  77. free_params:
  78. snd_rawmidi_params_free(params);
  79. close:
  80. snd_rawmidi_close(rawmidi);
  81. handle_error:
  82. throw std::runtime_error(std::string(func) + ": " + error_message);
  83. }
  84. JackALSARawMidiPort::~JackALSARawMidiPort()
  85. {
  86. if (rawmidi) {
  87. int code = snd_rawmidi_close(rawmidi);
  88. if (code) {
  89. jack_error("JackALSARawMidiPort::~JackALSARawMidiPort - "
  90. "snd_rawmidi_close: %s", snd_strerror(code));
  91. }
  92. rawmidi = 0;
  93. }
  94. }
  95. const char *
  96. JackALSARawMidiPort::GetAlias()
  97. {
  98. return alias;
  99. }
  100. const char *
  101. JackALSARawMidiPort::GetName()
  102. {
  103. return name;
  104. }
  105. int
  106. JackALSARawMidiPort::GetPollDescriptorCount()
  107. {
  108. return num_fds;
  109. }
  110. bool
  111. JackALSARawMidiPort::PopulatePollDescriptors(struct pollfd *poll_fd)
  112. {
  113. bool result = snd_rawmidi_poll_descriptors(rawmidi, poll_fd, num_fds) ==
  114. num_fds;
  115. if (result) {
  116. poll_fds = poll_fd;
  117. }
  118. return result;
  119. }
  120. bool
  121. JackALSARawMidiPort::ProcessPollEvents(unsigned short *revents)
  122. {
  123. int code = snd_rawmidi_poll_descriptors_revents(rawmidi, poll_fds, num_fds,
  124. revents);
  125. if (code) {
  126. jack_error("JackALSARawMidiPort::ProcessPollEvents - "
  127. "snd_rawmidi_poll_descriptors_revents: %s",
  128. snd_strerror(code));
  129. return false;
  130. }
  131. if ((*revents) & POLLNVAL) {
  132. jack_error("JackALSARawMidiPort::ProcessPollEvents - the file "
  133. "descriptor is invalid.");
  134. return false;
  135. }
  136. if ((*revents) & POLLERR) {
  137. jack_error("JackALSARawMidiPort::ProcessPollEvents - an error has "
  138. "occurred on the device or stream.");
  139. return false;
  140. }
  141. return true;
  142. }
  143. void
  144. JackALSARawMidiPort::SetPollEventMask(unsigned short events)
  145. {
  146. for (int i = 0; i < num_fds; i++) {
  147. (poll_fds + i)->events = events;
  148. }
  149. }