diff options
Diffstat (limited to 'media/midi/usb_midi_input_stream.cc')
-rw-r--r-- | media/midi/usb_midi_input_stream.cc | 92 |
1 files changed, 92 insertions, 0 deletions
diff --git a/media/midi/usb_midi_input_stream.cc b/media/midi/usb_midi_input_stream.cc new file mode 100644 index 0000000..f68436c --- /dev/null +++ b/media/midi/usb_midi_input_stream.cc @@ -0,0 +1,92 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "media/midi/usb_midi_input_stream.h" + +#include <string.h> +#include <map> +#include <vector> + +#include "base/logging.h" +#include "media/midi/usb_midi_device.h" +#include "media/midi/usb_midi_jack.h" + +namespace media { + +UsbMidiInputStream::JackUniqueKey::JackUniqueKey(UsbMidiDevice* device, + int endpoint_number, + int cable_number) + : device(device), + endpoint_number(endpoint_number), + cable_number(cable_number) {} + +bool UsbMidiInputStream::JackUniqueKey::operator==( + const JackUniqueKey& that) const { + return device == that.device && + endpoint_number == that.endpoint_number && + cable_number == that.cable_number; +} + +bool UsbMidiInputStream::JackUniqueKey::operator<( + const JackUniqueKey& that) const { + if (device != that.device) + return device < that.device; + if (endpoint_number != that.endpoint_number) + return endpoint_number < that.endpoint_number; + return cable_number < that.cable_number; +} + +UsbMidiInputStream::UsbMidiInputStream(const std::vector<UsbMidiJack>& jacks, + Delegate* delegate) + : delegate_(delegate) { + for (size_t i = 0; i < jacks.size(); ++i) { + jack_dictionary_.insert( + std::make_pair(JackUniqueKey(jacks[i].device, + jacks[i].endpoint_number(), + jacks[i].cable_number), + i)); + } +} + +UsbMidiInputStream::~UsbMidiInputStream() {} + +void UsbMidiInputStream::OnReceivedData(UsbMidiDevice* device, + int endpoint_number, + const uint8* data, + size_t size, + double timestamp) { + DCHECK_EQ(0u, size % kPacketSize); + size_t current = 0; + while (current + kPacketSize <= size) { + ProcessOnePacket(device, endpoint_number, &data[current], timestamp); + current += kPacketSize; + } +} + +void UsbMidiInputStream::ProcessOnePacket(UsbMidiDevice* device, + int endpoint_number, + const uint8* packet, + double timestamp) { + // The first 4 bytes of the packet is accessible here. + uint8 code_index = packet[0] & 0x0f; + uint8 cable_number = packet[0] >> 4; + const size_t packet_size_table[16] = { + 0, 0, 2, 3, 3, 1, 2, 3, 3, 3, 3, 3, 2, 2, 3, 1, + }; + size_t packet_size = packet_size_table[code_index]; + if (packet_size == 0) { + // These CINs are reserved. Ignore them. + DVLOG(1) << "code index number (" << code_index << ") arrives " + << "but it is reserved."; + return; + } + std::map<JackUniqueKey, size_t>::const_iterator it = + jack_dictionary_.find(JackUniqueKey(device, + endpoint_number, + cable_number)); + if (it != jack_dictionary_.end()) + delegate_->OnReceivedData(it->second, &packet[1], packet_size, timestamp); +} + +} // namespace media |