24 #include "JackALSARawMidiPort.h"
25 #include "JackALSARawMidiUtil.h"
26 #include "JackError.h"
30 JackALSARawMidiPort::JackALSARawMidiPort(
const char *client_name, snd_rawmidi_info_t *info,
31 size_t index,
unsigned short io_mask)
33 int card = snd_rawmidi_info_get_card(info);
34 unsigned int device = snd_rawmidi_info_get_device(info);
35 unsigned int subdevice = snd_rawmidi_info_get_subdevice(info);
37 snprintf(device_id,
sizeof(device_id),
"hw:%d,%d,%d", card, device,
39 const char* driver_name = snd_rawmidi_info_get_name(info);
40 const char *alias_suffix;
41 const char *error_message;
43 const char *port_name;
45 if (snd_rawmidi_info_get_stream(info) == SND_RAWMIDI_STREAM_OUTPUT) {
48 port_name =
"playback_";
53 port_name =
"capture_";
57 int code = snd_rawmidi_open(in, out, device_id, SND_RAWMIDI_NONBLOCK);
59 error_message = snd_strerror(code);
60 func =
"snd_rawmidi_open";
63 snd_rawmidi_params_t *params;
64 code = snd_rawmidi_params_malloc(¶ms);
66 error_message = snd_strerror(code);
67 func =
"snd_rawmidi_params_malloc";
70 code = snd_rawmidi_params_current(rawmidi, params);
72 error_message = snd_strerror(code);
73 func =
"snd_rawmidi_params_current";
76 code = snd_rawmidi_params_set_avail_min(rawmidi, params, 1);
78 error_message = snd_strerror(code);
79 func =
"snd_rawmidi_params_set_avail_min";
84 code = snd_rawmidi_params_set_buffer_size(rawmidi, params, 32);
86 error_message = snd_strerror(code);
87 func =
"snd_rawmidi_params_set_buffer_size";
91 code = snd_rawmidi_params_set_no_active_sensing(rawmidi, params, 1);
93 error_message = snd_strerror(code);
94 func =
"snd_rawmidi_params_set_no_active_sensing";
97 code = snd_rawmidi_params(rawmidi, params);
99 error_message = snd_strerror(code);
100 func =
"snd_rawmidi_params";
103 snd_rawmidi_params_free(params);
104 alsa_poll_fd_count = snd_rawmidi_poll_descriptors_count(rawmidi);
105 if (! alsa_poll_fd_count) {
106 error_message =
"returned '0' count for poll descriptors";
107 func =
"snd_rawmidi_poll_descriptors_count";
111 CreateNonBlockingPipe(fds);
112 }
catch (std::exception e) {
113 error_message = e.what();
114 func =
"CreateNonBlockingPipe";
117 snprintf(alias,
sizeof(alias),
"system:%d-%d %s %d %s", card + 1,
118 device + 1, driver_name, subdevice + 1,
120 snprintf(name,
sizeof(name),
"%s:%s%zu", client_name, port_name, index + 1);
121 strncpy(device_name, driver_name,
sizeof(device_name) - 1);
122 this->io_mask = io_mask;
125 snd_rawmidi_params_free(params);
127 snd_rawmidi_close(rawmidi);
129 throw std::runtime_error(std::string(func) +
": " + error_message);
132 JackALSARawMidiPort::~JackALSARawMidiPort()
134 DestroyNonBlockingPipe(fds);
136 int code = snd_rawmidi_close(rawmidi);
138 jack_error(
"JackALSARawMidiPort::~JackALSARawMidiPort - "
139 "snd_rawmidi_close: %s", snd_strerror(code));
146 JackALSARawMidiPort::GetAlias()
152 JackALSARawMidiPort::GetIOPollEvent()
154 unsigned short events;
155 int code = snd_rawmidi_poll_descriptors_revents(rawmidi, alsa_poll_fds,
159 jack_error(
"JackALSARawMidiPort::GetIOPollEvents - "
160 "snd_rawmidi_poll_descriptors_revents: %s",
164 if (events & POLLNVAL) {
165 jack_error(
"JackALSARawMidiPort::GetIOPollEvents - the file "
166 "descriptor is invalid.");
169 if (events & POLLERR) {
170 jack_error(
"JackALSARawMidiPort::GetIOPollEvents - an error has "
171 "occurred on the device or stream.");
174 return (events & io_mask) ? 1 : 0;
178 JackALSARawMidiPort::GetName()
184 JackALSARawMidiPort::GetDeviceName()
190 JackALSARawMidiPort::GetPollDescriptorCount()
192 return alsa_poll_fd_count + 1;
196 JackALSARawMidiPort::GetQueuePollEvent()
198 unsigned short events = queue_poll_fd->revents;
199 if (events & POLLNVAL) {
200 jack_error(
"JackALSARawMidiPort::GetQueuePollEvents - the file "
201 "descriptor is invalid.");
204 if (events & POLLERR) {
205 jack_error(
"JackALSARawMidiPort::GetQueuePollEvents - an error has "
206 "occurred on the device or stream.");
209 int event = events & POLLIN ? 1 : 0;
212 ssize_t result = read(fds[0], &c, 1);
215 jack_error(
"JackALSARawMidiPort::GetQueuePollEvents - error "
216 "reading a byte from the pipe file descriptor: %s",
225 JackALSARawMidiPort::PopulatePollDescriptors(
struct pollfd *poll_fd)
227 alsa_poll_fds = poll_fd + 1;
228 assert(snd_rawmidi_poll_descriptors(rawmidi, alsa_poll_fds,
229 alsa_poll_fd_count) ==
231 queue_poll_fd = poll_fd;
232 queue_poll_fd->events = POLLERR | POLLIN | POLLNVAL;
233 queue_poll_fd->fd = fds[0];
234 SetIOEventsEnabled(
true);
238 JackALSARawMidiPort::SetIOEventsEnabled(
bool enabled)
240 unsigned short mask = POLLNVAL | POLLERR | (enabled ? io_mask : 0);
241 for (
int i = 0; i < alsa_poll_fd_count; i++) {
242 (alsa_poll_fds + i)->events = mask;
247 JackALSARawMidiPort::TriggerQueueEvent()
250 ssize_t result = write(fds[1], &c, 1);
256 jack_error(
"JackALSARawMidiPort::TriggerQueueEvent - error writing a "
257 "byte to the pipe file descriptor: %s", strerror(errno));
260 jack_error(
"JackALSARawMidiPort::TriggerQueueEvent - couldn't write a "
261 "byte to the pipe file descriptor.");
SERVER_EXPORT void jack_error(const char *fmt,...)