Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2271)

Unified Diff: media/midi/midi_manager_alsa.cc

Issue 264973012: Use seq instead of rawmidi for MidiManagerAlsa (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fix C++ initialization Created 6 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« media/midi/midi_manager_alsa.h ('K') | « media/midi/midi_manager_alsa.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: media/midi/midi_manager_alsa.cc
diff --git a/media/midi/midi_manager_alsa.cc b/media/midi/midi_manager_alsa.cc
index c4be32ffae29428b918cdae2707d4e92c920675d..1131d17ea641af3745b430f8b726613544f493a0 100644
--- a/media/midi/midi_manager_alsa.cc
+++ b/media/midi/midi_manager_alsa.cc
@@ -23,276 +23,316 @@ namespace media {
namespace {
-const size_t kReceiveBufferSize = 4096;
-const unsigned short kPollEventMask = POLLIN | POLLERR | POLLNVAL;
+const size_t kSendBufferSize = 64;
+const unsigned int kRequiredInputPortCaps =
+ SND_SEQ_PORT_CAP_READ | SND_SEQ_PORT_CAP_SUBS_READ;
Takashi Toyoshima 2014/05/07 04:38:28 Having a link to http://www.alsa-project.org/alsa-
Adam Goode 2014/05/08 03:00:53 Done.
+const unsigned int kRequiredOutputPortCaps =
+ SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_SUBS_WRITE;
+
+int AddrToInt(const snd_seq_addr_t* addr) {
+ return (addr->client << 8) | addr->port;
+}
} // namespace
-class MidiManagerAlsa::MidiDeviceInfo
- : public base::RefCounted<MidiDeviceInfo> {
- public:
- MidiDeviceInfo(MidiManagerAlsa* manager,
- const std::string& bus_id,
- snd_ctl_card_info_t* card,
- const snd_rawmidi_info_t* midi,
- int device) {
- opened_ = !snd_rawmidi_open(&midi_in_, &midi_out_, bus_id.c_str(), 0);
- if (!opened_)
- return;
-
- const std::string id = base::StringPrintf("%s:%d", bus_id.c_str(), device);
- const std::string name = snd_rawmidi_info_get_name(midi);
- // We assume that card longname is in the format of
- // "<manufacturer> <name> at <bus>". Otherwise, we give up to detect
- // a manufacturer name here.
- std::string manufacturer;
- const std::string card_name = snd_ctl_card_info_get_longname(card);
- size_t name_index = card_name.find(name);
- if (std::string::npos != name_index)
- manufacturer = card_name.substr(0, name_index - 1);
- const std::string version =
- base::StringPrintf("%s / ALSA library version %d.%d.%d",
- snd_ctl_card_info_get_driver(card),
- SND_LIB_MAJOR, SND_LIB_MINOR, SND_LIB_SUBMINOR);
- port_info_ = MidiPortInfo(id, manufacturer, name, version);
- }
+MidiManagerAlsa::MidiManagerAlsa()
+ : in_client_(NULL),
+ out_client_(NULL),
+ out_client_id_(-1),
+ in_port_(-1),
+ decoder_(NULL),
+ send_thread_("MidiSendThread"),
+ event_thread_("MidiEventThread"),
+ event_thread_shutdown_(false) {
+ // Initialize decoder.
+ snd_midi_event_new(0, &decoder_);
+ snd_midi_event_no_status(decoder_, 1);
+}
- void Send(MidiManagerClient* client, const std::vector<uint8>& data) {
- ssize_t result = snd_rawmidi_write(
- midi_out_, reinterpret_cast<const void*>(&data[0]), data.size());
- if (static_cast<size_t>(result) != data.size()) {
- // TODO(toyoshim): Handle device disconnection.
- VLOG(1) << "snd_rawmidi_write fails: " << strerror(-result);
- }
- base::MessageLoop::current()->PostTask(
- FROM_HERE,
- base::Bind(&MidiManagerClient::AccumulateMidiBytesSent,
- base::Unretained(client), data.size()));
+void MidiManagerAlsa::StartInitialization() {
Takashi Toyoshima 2014/05/07 04:38:28 Now that StartInitialization() can be performed as
Adam Goode 2014/05/08 03:00:53 I don't think I can do this on the event thread, s
Takashi Toyoshima 2014/05/16 19:31:52 Hum... you are right. And other MidiManager* imple
Adam Goode 2014/05/25 04:57:05 Done.
+ // Create client handles.
+ int err = snd_seq_open(&in_client_, "hw", SND_SEQ_OPEN_INPUT, 0);
+ if (err != 0) {
+ VLOG(1) << "snd_seq_open fails: " << snd_strerror(err);
+ // Nothing to close, just return failure.
+ return CompleteInitialization(MIDI_INITIALIZATION_ERROR);
}
-
- // Read input data from a MIDI input device which is ready to read through
- // the ALSA library. Called from EventLoop() and read data will be sent to
- // blink through MIDIManager base class.
- size_t Receive(uint8* data, size_t length) {
- return snd_rawmidi_read(midi_in_, reinterpret_cast<void*>(data), length);
+ int in_client_id = snd_seq_client_id(in_client_);
+ err = snd_seq_open(&out_client_, "hw", SND_SEQ_OPEN_OUTPUT, 0);
+ if (err != 0) {
+ VLOG(1) << "snd_seq_open fails: " << snd_strerror(err);
+ return CompleteInitialization(MIDI_INITIALIZATION_ERROR);
}
+ out_client_id_ = snd_seq_client_id(out_client_);
- const MidiPortInfo& GetMidiPortInfo() const { return port_info_; }
-
- // Get the number of descriptors which is required to call poll() on the
- // device. The ALSA library always returns 1 here now, but it may be changed
- // in the future.
- int GetPollDescriptorsCount() {
- return snd_rawmidi_poll_descriptors_count(midi_in_);
+ // Name the clients.
+ err = snd_seq_set_client_name(in_client_, "Google Chrome (input)");
Takashi Toyoshima 2014/05/07 04:38:28 Can you remove "Google" from the strings? _mac.cc
Adam Goode 2014/05/08 03:00:53 Done.
+ if (err != 0) {
+ VLOG(1) << "snd_seq_set_client_name fails: " << snd_strerror(err);
+ return CompleteInitialization(MIDI_INITIALIZATION_ERROR);
}
-
- // Following API initializes pollfds for polling the device, and returns the
- // number of descriptors they are initialized. It must be the same value with
- // snd_rawmidi_poll_descriptors_count().
- int SetupPollDescriptors(struct pollfd* pfds, unsigned int count) {
- return snd_rawmidi_poll_descriptors(midi_in_, pfds, count);
+ err = snd_seq_set_client_name(out_client_, "Google Chrome (output)");
Takashi Toyoshima 2014/05/07 04:38:28 ditto
Adam Goode 2014/05/08 03:00:53 Done.
+ if (err != 0) {
+ VLOG(1) << "snd_seq_set_client_name fails: " << snd_strerror(err);
+ return CompleteInitialization(MIDI_INITIALIZATION_ERROR);
}
- unsigned short GetPollDescriptorsRevents(struct pollfd* pfds) {
- unsigned short revents;
- snd_rawmidi_poll_descriptors_revents(midi_in_,
- pfds,
- GetPollDescriptorsCount(),
- &revents);
- return revents;
+ // Create input port.
+ in_port_ = snd_seq_create_simple_port(in_client_, NULL,
+ SND_SEQ_PORT_CAP_WRITE |
+ SND_SEQ_PORT_CAP_NO_EXPORT,
+ SND_SEQ_PORT_TYPE_MIDI_GENERIC |
+ SND_SEQ_PORT_TYPE_APPLICATION);
+ if (in_port_ < 0) {
+ VLOG(1) << "snd_seq_create_simple_port fails: " << snd_strerror(in_port_);
+ return CompleteInitialization(MIDI_INITIALIZATION_ERROR);
}
- bool IsOpened() const { return opened_; }
-
- private:
- friend class base::RefCounted<MidiDeviceInfo>;
- virtual ~MidiDeviceInfo() {
- if (opened_) {
- snd_rawmidi_close(midi_in_);
- snd_rawmidi_close(midi_out_);
- }
+ // Subscribe to the announce port.
+ snd_seq_port_subscribe_t* subs;
+ snd_seq_port_subscribe_alloca(&subs);
+ snd_seq_addr_t announce_sender;
+ snd_seq_addr_t announce_dest;
+ announce_sender.client = SND_SEQ_CLIENT_SYSTEM;
+ announce_sender.port = SND_SEQ_PORT_SYSTEM_ANNOUNCE;
+ announce_dest.client = in_client_id;
+ announce_dest.port = in_port_;
+ snd_seq_port_subscribe_set_sender(subs, &announce_sender);
+ snd_seq_port_subscribe_set_dest(subs, &announce_dest);
+ err = snd_seq_subscribe_port(in_client_, subs);
+ if (err != 0) {
+ VLOG(1) << "snd_seq_subscribe_port on the announce port fails: "
+ << snd_strerror(err);
+ return CompleteInitialization(MIDI_INITIALIZATION_ERROR);
}
- bool opened_;
- MidiPortInfo port_info_;
- snd_rawmidi_t* midi_in_;
- snd_rawmidi_t* midi_out_;
-
- DISALLOW_COPY_AND_ASSIGN(MidiDeviceInfo);
-};
-
-MidiManagerAlsa::MidiManagerAlsa()
- : send_thread_("MidiSendThread"),
- event_thread_("MidiEventThread") {
- for (size_t i = 0; i < arraysize(pipe_fd_); ++i)
- pipe_fd_[i] = -1;
-}
-
-void MidiManagerAlsa::StartInitialization() {
- // Enumerate only hardware MIDI devices because software MIDIs running in
- // the browser process is not secure.
- snd_ctl_card_info_t* card;
- snd_rawmidi_info_t* midi_out;
- snd_rawmidi_info_t* midi_in;
- snd_ctl_card_info_alloca(&card);
- snd_rawmidi_info_alloca(&midi_out);
- snd_rawmidi_info_alloca(&midi_in);
- for (int index = -1; !snd_card_next(&index) && index >= 0; ) {
- const std::string id = base::StringPrintf("hw:CARD=%i", index);
- snd_ctl_t* handle;
- int err = snd_ctl_open(&handle, id.c_str(), 0);
- if (err != 0) {
- VLOG(1) << "snd_ctl_open fails: " << snd_strerror(err);
- continue;
- }
- err = snd_ctl_card_info(handle, card);
- if (err != 0) {
- VLOG(1) << "snd_ctl_card_info fails: " << snd_strerror(err);
- snd_ctl_close(handle);
+ // Enumerate all ports in all clients.
+ snd_seq_client_info_t* client_info;
+ snd_seq_client_info_alloca(&client_info);
+ snd_seq_port_info_t* port_info;
+ snd_seq_port_info_alloca(&port_info);
+
+ snd_seq_client_info_set_client(client_info, -1);
+ // Enumerate clients.
+ uint32 current_input = 0;
+ while (!snd_seq_query_next_client(in_client_, client_info)) {
+ int client_id = snd_seq_client_info_get_client(client_info);
+ if ((client_id == in_client_id) || (client_id == out_client_id_)) {
+ // Skip our own clients.
continue;
}
- for (int device = -1;
- !snd_ctl_rawmidi_next_device(handle, &device) && device >= 0; ) {
- bool output;
- bool input;
- snd_rawmidi_info_set_device(midi_out, device);
- snd_rawmidi_info_set_subdevice(midi_out, 0);
- snd_rawmidi_info_set_stream(midi_out, SND_RAWMIDI_STREAM_OUTPUT);
- output = snd_ctl_rawmidi_info(handle, midi_out) == 0;
- snd_rawmidi_info_set_device(midi_in, device);
- snd_rawmidi_info_set_subdevice(midi_in, 0);
- snd_rawmidi_info_set_stream(midi_in, SND_RAWMIDI_STREAM_INPUT);
- input = snd_ctl_rawmidi_info(handle, midi_in) == 0;
- if (!output && !input)
- continue;
- scoped_refptr<MidiDeviceInfo> port = new MidiDeviceInfo(
- this, id, card, output ? midi_out : midi_in, device);
- if (!port->IsOpened()) {
- VLOG(1) << "MidiDeviceInfo open fails";
- continue;
- }
- if (input) {
- in_devices_.push_back(port);
- AddInputPort(port->GetMidiPortInfo());
- }
- if (output) {
- out_devices_.push_back(port);
- AddOutputPort(port->GetMidiPortInfo());
+ snd_seq_port_info_set_client(port_info, client_id);
+ snd_seq_port_info_set_port(port_info, -1);
+ // Enumerate ports.
+ while (!snd_seq_query_next_port(in_client_, port_info)) {
+ unsigned int port_type = snd_seq_port_info_get_type(port_info);
+ if (port_type & SND_SEQ_PORT_TYPE_MIDI_GENERIC) {
+ const snd_seq_addr_t* addr = snd_seq_port_info_get_addr(port_info);
+ const std::string name = snd_seq_port_info_get_name(port_info);
+ const std::string id = base::StringPrintf("%d:%d %s",
+ addr->client,
+ addr->port,
+ name.c_str());
+
+ unsigned int caps = snd_seq_port_info_get_capability(port_info);
+ if ((caps & kRequiredInputPortCaps) == kRequiredInputPortCaps) {
+ // Subscribe to this port.
+ const snd_seq_addr_t* sender = snd_seq_port_info_get_addr(port_info);
+ snd_seq_addr_t dest;
+ dest.client = snd_seq_client_id(in_client_);
+ dest.port = in_port_;
+ snd_seq_port_subscribe_set_sender(subs, sender);
+ snd_seq_port_subscribe_set_dest(subs, &dest);
+ err = snd_seq_subscribe_port(in_client_, subs);
+ if (err != 0) {
+ VLOG(1) << "snd_seq_subscribe_port fails: " << snd_strerror(err);
+ } else {
+ source_map_[AddrToInt(sender)] = current_input++;
+ AddInputPort(MidiPortInfo(id, "", name, ""));
+ }
+ }
+ if ((caps & kRequiredOutputPortCaps) == kRequiredOutputPortCaps) {
+ // Create a port for us to send on.
+ int out_port =
+ snd_seq_create_simple_port(out_client_, NULL,
+ SND_SEQ_PORT_CAP_READ |
+ SND_SEQ_PORT_CAP_NO_EXPORT,
+ SND_SEQ_PORT_TYPE_MIDI_GENERIC |
+ SND_SEQ_PORT_TYPE_APPLICATION);
+ if (out_port < 0) {
+ VLOG(1) << "snd_seq_create_simple_port fails: "
+ << snd_strerror(out_port);
+ // Skip this output port for now.
+ continue;
+ }
+
+ // Activate port subscription.
+ snd_seq_addr_t sender;
+ const snd_seq_addr_t* dest = snd_seq_port_info_get_addr(port_info);
+ sender.client = snd_seq_client_id(out_client_);
+ sender.port = out_port;
+ snd_seq_port_subscribe_set_sender(subs, &sender);
+ snd_seq_port_subscribe_set_dest(subs, dest);
+ err = snd_seq_subscribe_port(out_client_, subs);
+ if (err != 0) {
+ VLOG(1) << "snd_seq_subscribe_port fails: " << snd_strerror(err);
+ snd_seq_delete_simple_port(out_client_, out_port);
+ } else {
+ snd_midi_event_t* encoder;
+ snd_midi_event_new(kSendBufferSize, &encoder);
+ encoders_.push_back(encoder);
+ out_ports_.push_back(out_port);
+ AddOutputPort(MidiPortInfo(id, "", name, ""));
Takashi Toyoshima 2014/05/07 04:38:28 Can you try to get a manufacturer string and gener
Adam Goode 2014/05/08 03:00:53 I will look into this. It is complex to do. I thin
+ }
+ }
}
}
- snd_ctl_close(handle);
}
- if (pipe(pipe_fd_) < 0) {
- VPLOG(1) << "pipe() failed";
- CompleteInitialization(MIDI_INITIALIZATION_ERROR);
- } else {
- event_thread_.Start();
- event_thread_.message_loop()->PostTask(
- FROM_HERE,
- base::Bind(&MidiManagerAlsa::EventReset, base::Unretained(this)));
- CompleteInitialization(MIDI_OK);
- }
+ event_thread_.Start();
+ event_thread_.message_loop()->PostTask(
+ FROM_HERE,
+ base::Bind(&MidiManagerAlsa::EventReset, base::Unretained(this)));
+
+ CompleteInitialization(MIDI_OK);
}
MidiManagerAlsa::~MidiManagerAlsa() {
- // Send a shutdown message to awake |event_thread_| from poll().
- if (pipe_fd_[1] >= 0)
- HANDLE_EINTR(write(pipe_fd_[1], "Q", 1));
+ // Tell the event thread it will soon be time to shut down.
+ shutdown_mu_.Acquire();
Takashi Toyoshima 2014/05/07 04:38:28 option: It's up to you, but I feel using AutoLock
Adam Goode 2014/05/08 03:00:53 Done.
+ event_thread_shutdown_ = true;
+ shutdown_mu_.Release();
+
+ // Stop the send thread.
+ send_thread_.Stop();
+
+ // Close the out client. This will trigger the event thread to stop,
+ // because of SND_SEQ_EVENT_CLIENT_EXIT.
+ if (out_client_) {
+ snd_seq_close(out_client_);
+ }
- // Stop receiving messages.
+ // Wait for the event thread to stop.
event_thread_.Stop();
- for (int i = 0; i < 2; ++i) {
- if (pipe_fd_[i] >= 0)
- close(pipe_fd_[i]);
+ // Close the in client.
+ if (in_client_) {
Takashi Toyoshima 2014/05/07 04:38:28 Usually chromium style omit {} for a one line clau
Adam Goode 2014/05/08 03:00:53 Done.
+ snd_seq_close(in_client_);
+ }
+
+ // Free the decoder.
+ snd_midi_event_free(decoder_);
+
+ // Free the encoders.
+ for (EncoderList::iterator i = encoders_.begin(); i != encoders_.end(); ++i) {
+ snd_midi_event_free(*i);
Takashi Toyoshima 2014/05/07 04:38:28 ditto
Adam Goode 2014/05/08 03:00:53 Done.
+ }
+}
+
+void MidiManagerAlsa::SendMidiData(uint32 port_index,
+ const std::vector<uint8>& data) {
+ DCHECK(send_thread_.message_loop_proxy()->BelongsToCurrentThread());
+
+ snd_midi_event_t* encoder = encoders_[port_index];
+ for (unsigned int i = 0; i < data.size(); i++) {
+ snd_seq_event_t event;
+ int result = snd_midi_event_encode_byte(encoder, data[i], &event);
+ if (result == 1) {
+ // Full event, send it.
+ snd_seq_ev_set_source(&event, out_ports_[port_index]);
+ snd_seq_ev_set_subs(&event);
+ snd_seq_ev_set_direct(&event);
+ snd_seq_event_output_direct(out_client_, &event);
+ }
}
- send_thread_.Stop();
}
void MidiManagerAlsa::DispatchSendMidiData(MidiManagerClient* client,
uint32 port_index,
const std::vector<uint8>& data,
double timestamp) {
- if (out_devices_.size() <= port_index)
+ if (out_ports_.size() <= port_index)
return;
+ if (!send_thread_.IsRunning())
+ send_thread_.Start();
+
+ // Compute delay.
base::TimeDelta delay;
if (timestamp != 0.0) {
- base::TimeTicks time_to_send =
- base::TimeTicks() + base::TimeDelta::FromMicroseconds(
- timestamp * base::Time::kMicrosecondsPerSecond);
- delay = std::max(time_to_send - base::TimeTicks::Now(), base::TimeDelta());
+ delay =
+ base::TimeDelta::FromSecondsD(timestamp) -
+ (base::TimeTicks::HighResNow() - base::TimeTicks());
}
- if (!send_thread_.IsRunning())
- send_thread_.Start();
-
- scoped_refptr<MidiDeviceInfo> device = out_devices_[port_index];
send_thread_.message_loop()->PostDelayedTask(
FROM_HERE,
- base::Bind(&MidiDeviceInfo::Send, device, client, data),
- delay);
+ base::Bind(&MidiManagerAlsa::SendMidiData, base::Unretained(this),
+ port_index, data), delay);
+
+ // Acknowledge send.
+ send_thread_.message_loop()->PostTask(
+ FROM_HERE,
+ base::Bind(&MidiManagerClient::AccumulateMidiBytesSent,
+ base::Unretained(client), data.size()));
}
void MidiManagerAlsa::EventReset() {
- CHECK_GE(pipe_fd_[0], 0);
-
- // Sum up descriptors which are needed to poll input devices and a shutdown
- // message.
- // Keep the first one descriptor for a shutdown message.
- size_t poll_fds_size = 1;
- for (size_t i = 0; i < in_devices_.size(); ++i)
- poll_fds_size += in_devices_[i]->GetPollDescriptorsCount();
- poll_fds_.resize(poll_fds_size);
-
- // Setup struct pollfd to poll input MIDI devices and a shutdown message.
- // The first pollfd is for a shutdown message.
- poll_fds_[0].fd = pipe_fd_[0];
- poll_fds_[0].events = kPollEventMask;
- int fds_index = 1;
- for (size_t i = 0; i < in_devices_.size(); ++i) {
- fds_index += in_devices_[i]->SetupPollDescriptors(
- &poll_fds_[fds_index], poll_fds_.size() - fds_index);
- }
-
event_thread_.message_loop()->PostTask(
FROM_HERE,
base::Bind(&MidiManagerAlsa::EventLoop, base::Unretained(this)));
}
void MidiManagerAlsa::EventLoop() {
- if (HANDLE_EINTR(poll(&poll_fds_[0], poll_fds_.size(), -1)) < 0) {
- VPLOG(1) << "Couldn't poll(). Stop to poll input MIDI devices.";
- // TODO(toyoshim): Handle device disconnection, and try to reconnect?
- return;
- }
-
- // Check timestamp as soon as possible because the API requires accurate
- // timestamp as possible. It will be useful for recording MIDI events.
- base::TimeTicks now = base::TimeTicks::HighResNow();
-
- // Is this thread going to be shutdown?
- if (poll_fds_[0].revents & kPollEventMask)
- return;
-
// Read available incoming MIDI data.
- int fds_index = 1;
- uint8 buffer[kReceiveBufferSize];
-
- for (size_t i = 0; i < in_devices_.size(); ++i) {
- unsigned short revents =
- in_devices_[i]->GetPollDescriptorsRevents(&poll_fds_[fds_index]);
- if (revents & (POLLERR | POLLNVAL)) {
- // TODO(toyoshim): Handle device disconnection.
- VLOG(1) << "snd_rawmidi_descriptors_revents fails";
- poll_fds_[fds_index].events = 0;
+ snd_seq_event_t* event;
+ int err = snd_seq_event_input(in_client_, &event);
+ double timestamp =
+ (base::TimeTicks::HighResNow() - base::TimeTicks()).InSecondsF();
+ if (err == -ENOSPC) {
+ VLOG(1) << "snd_seq_event_input detected buffer overrun";
+
+ // We've lost events: check another way to see if we need to shut down.
Takashi Toyoshima 2014/05/07 04:38:28 Why do you check shutdown here? I mean why only fo
Adam Goode 2014/05/08 03:00:53 This is only for the case where we miss the shutdo
Takashi Toyoshima 2014/05/16 19:31:52 Ah, I see. I understand how shutdown works. Thanks
+ base::AutoLock lock(shutdown_mu_);
+ if (event_thread_shutdown_) {
+ return;
+ }
+ } else if (err < 0) {
+ VLOG(1) << "snd_seq_event_input fails: " << snd_strerror(err);
+ return;
+ } else {
+ // Check for disconnection of out client. This means "shut down".
+ if (event->source.client == SND_SEQ_CLIENT_SYSTEM &&
+ event->source.port == SND_SEQ_PORT_SYSTEM_ANNOUNCE &&
+ event->type == SND_SEQ_EVENT_CLIENT_EXIT &&
+ event->data.addr.client == out_client_id_) {
+ return;
}
- if (revents & POLLIN) {
- size_t read_size = in_devices_[i]->Receive(buffer, kReceiveBufferSize);
- ReceiveMidiData(i, buffer, read_size, now);
+
+ std::map<int, uint32>::iterator source_it =
+ source_map_.find(AddrToInt(&event->source));
+ if (source_it != source_map_.end()) {
+ uint32 source = source_it->second;
+ if (event->type == SND_SEQ_EVENT_SYSEX) {
+ // Special! Variable-length sysex.
+ ReceiveMidiData(source, static_cast<const uint8*>(event->data.ext.ptr),
+ event->data.ext.len,
+ timestamp);
+ } else {
+ // Otherwise, decode this and send that on.
+ unsigned char buf[12];
+ long count = snd_midi_event_decode(decoder_, buf, sizeof(buf), event);
+ if (count <= 0) {
+ if (count != -ENOENT) {
+ // ENOENT means that it's not a MIDI message, which is not an
+ // error, but other negative values are errors for us.
+ VLOG(1) << "snd_midi_event_decoder fails " << snd_strerror(count);
+ }
+ } else {
+ ReceiveMidiData(source, buf, count, timestamp);
+ }
+ }
}
- fds_index += in_devices_[i]->GetPollDescriptorsCount();
}
// Do again.
« media/midi/midi_manager_alsa.h ('K') | « media/midi/midi_manager_alsa.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698