24 #include "JackALSARawMidiPort.h"
25 #include "JackALSARawMidiUtil.h"
26 #include "JackError.h"
30 JackALSARawMidiPort::JackALSARawMidiPort(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 *alias_suffix;
40 const char *error_message;
42 const char *name_prefix;
44 if (snd_rawmidi_info_get_stream(info) == SND_RAWMIDI_STREAM_OUTPUT) {
47 name_prefix =
"system:midi_playback_";
52 name_prefix =
"system:midi_capture_";
56 int code = snd_rawmidi_open(in, out, device_id, SND_RAWMIDI_NONBLOCK);
58 error_message = snd_strerror(code);
59 func =
"snd_rawmidi_open";
62 snd_rawmidi_params_t *params;
63 code = snd_rawmidi_params_malloc(¶ms);
65 error_message = snd_strerror(code);
66 func =
"snd_rawmidi_params_malloc";
69 code = snd_rawmidi_params_current(rawmidi, params);
71 error_message = snd_strerror(code);
72 func =
"snd_rawmidi_params_current";
75 code = snd_rawmidi_params_set_avail_min(rawmidi, params, 1);
77 error_message = snd_strerror(code);
78 func =
"snd_rawmidi_params_set_avail_min";
83 code = snd_rawmidi_params_set_buffer_size(rawmidi, params, 32);
85 error_message = snd_strerror(code);
86 func =
"snd_rawmidi_params_set_buffer_size";
90 code = snd_rawmidi_params_set_no_active_sensing(rawmidi, params, 1);
92 error_message = snd_strerror(code);
93 func =
"snd_rawmidi_params_set_no_active_sensing";
96 code = snd_rawmidi_params(rawmidi, params);
98 error_message = snd_strerror(code);
99 func =
"snd_rawmidi_params";
102 snd_rawmidi_params_free(params);
103 alsa_poll_fd_count = snd_rawmidi_poll_descriptors_count(rawmidi);
104 if (! alsa_poll_fd_count) {
105 error_message =
"returned '0' count for poll descriptors";
106 func =
"snd_rawmidi_poll_descriptors_count";
110 CreateNonBlockingPipe(fds);
111 }
catch (std::exception e) {
112 error_message = e.what();
113 func =
"CreateNonBlockingPipe";
116 snprintf(alias,
sizeof(alias),
"system:%d-%d %s %d %s", card + 1,
117 device + 1, snd_rawmidi_info_get_name(info), subdevice + 1,
119 snprintf(name,
sizeof(name),
"%s%zu", name_prefix, index + 1);
120 this->io_mask = io_mask;
123 snd_rawmidi_params_free(params);
125 snd_rawmidi_close(rawmidi);
127 throw std::runtime_error(std::string(func) +
": " + error_message);
130 JackALSARawMidiPort::~JackALSARawMidiPort()
132 DestroyNonBlockingPipe(fds);
134 int code = snd_rawmidi_close(rawmidi);
136 jack_error(
"JackALSARawMidiPort::~JackALSARawMidiPort - "
137 "snd_rawmidi_close: %s", snd_strerror(code));
144 JackALSARawMidiPort::GetAlias()
150 JackALSARawMidiPort::GetIOPollEvent()
152 unsigned short events;
153 int code = snd_rawmidi_poll_descriptors_revents(rawmidi, alsa_poll_fds,
157 jack_error(
"JackALSARawMidiPort::GetIOPollEvents - "
158 "snd_rawmidi_poll_descriptors_revents: %s",
162 if (events & POLLNVAL) {
163 jack_error(
"JackALSARawMidiPort::GetIOPollEvents - the file "
164 "descriptor is invalid.");
167 if (events & POLLERR) {
168 jack_error(
"JackALSARawMidiPort::GetIOPollEvents - an error has "
169 "occurred on the device or stream.");
172 return (events & io_mask) ? 1 : 0;
176 JackALSARawMidiPort::GetName()
182 JackALSARawMidiPort::GetPollDescriptorCount()
184 return alsa_poll_fd_count + 1;
188 JackALSARawMidiPort::GetQueuePollEvent()
190 unsigned short events = queue_poll_fd->revents;
191 if (events & POLLNVAL) {
192 jack_error(
"JackALSARawMidiPort::GetQueuePollEvents - the file "
193 "descriptor is invalid.");
196 if (events & POLLERR) {
197 jack_error(
"JackALSARawMidiPort::GetQueuePollEvents - an error has "
198 "occurred on the device or stream.");
201 int event = events & POLLIN ? 1 : 0;
204 ssize_t result = read(fds[0], &c, 1);
207 jack_error(
"JackALSARawMidiPort::GetQueuePollEvents - error "
208 "reading a byte from the pipe file descriptor: %s",
217 JackALSARawMidiPort::PopulatePollDescriptors(
struct pollfd *poll_fd)
219 alsa_poll_fds = poll_fd + 1;
220 assert(snd_rawmidi_poll_descriptors(rawmidi, alsa_poll_fds,
221 alsa_poll_fd_count) ==
223 queue_poll_fd = poll_fd;
224 queue_poll_fd->events = POLLERR | POLLIN | POLLNVAL;
225 queue_poll_fd->fd = fds[0];
226 SetIOEventsEnabled(
true);
230 JackALSARawMidiPort::SetIOEventsEnabled(
bool enabled)
232 unsigned short mask = POLLNVAL | POLLERR | (enabled ? io_mask : 0);
233 for (
int i = 0; i < alsa_poll_fd_count; i++) {
234 (alsa_poll_fds + i)->events = mask;
239 JackALSARawMidiPort::TriggerQueueEvent()
242 ssize_t result = write(fds[1], &c, 1);
248 jack_error(
"JackALSARawMidiPort::TriggerQueueEvent - error writing a "
249 "byte to the pipe file descriptor: %s", strerror(errno));
252 jack_error(
"JackALSARawMidiPort::TriggerQueueEvent - couldn't write a "
253 "byte to the pipe file descriptor.");
SERVER_EXPORT void jack_error(const char *fmt,...)