usb_midi_input_stream.cc 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. // Copyright 2014 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "media/midi/usb_midi_input_stream.h"
  5. #include <string.h>
  6. #include "base/logging.h"
  7. #include "media/midi/usb_midi_device.h"
  8. namespace midi {
  9. UsbMidiInputStream::JackUniqueKey::JackUniqueKey(UsbMidiDevice* device,
  10. int endpoint_number,
  11. int cable_number)
  12. : device(device),
  13. endpoint_number(endpoint_number),
  14. cable_number(cable_number) {}
  15. bool UsbMidiInputStream::JackUniqueKey::operator==(
  16. const JackUniqueKey& that) const {
  17. return device == that.device &&
  18. endpoint_number == that.endpoint_number &&
  19. cable_number == that.cable_number;
  20. }
  21. bool UsbMidiInputStream::JackUniqueKey::operator<(
  22. const JackUniqueKey& that) const {
  23. if (device != that.device)
  24. return device < that.device;
  25. if (endpoint_number != that.endpoint_number)
  26. return endpoint_number < that.endpoint_number;
  27. return cable_number < that.cable_number;
  28. }
  29. UsbMidiInputStream::UsbMidiInputStream(Delegate* delegate)
  30. : delegate_(delegate) {}
  31. UsbMidiInputStream::~UsbMidiInputStream() = default;
  32. void UsbMidiInputStream::Add(const UsbMidiJack& jack) {
  33. JackUniqueKey key(jack.device,
  34. jack.endpoint_number(),
  35. jack.cable_number);
  36. jacks_.push_back(jack);
  37. DCHECK(jack_dictionary_.end() == jack_dictionary_.find(key));
  38. jack_dictionary_.insert(std::make_pair(key, jack_dictionary_.size()));
  39. }
  40. void UsbMidiInputStream::OnReceivedData(UsbMidiDevice* device,
  41. int endpoint_number,
  42. const uint8_t* data,
  43. size_t size,
  44. base::TimeTicks time) {
  45. DCHECK_EQ(0u, size % kPacketSize);
  46. size_t current = 0;
  47. while (current + kPacketSize <= size) {
  48. ProcessOnePacket(device, endpoint_number, &data[current], time);
  49. current += kPacketSize;
  50. }
  51. }
  52. void UsbMidiInputStream::ProcessOnePacket(UsbMidiDevice* device,
  53. int endpoint_number,
  54. const uint8_t* packet,
  55. base::TimeTicks time) {
  56. // The first 4 bytes of the packet is accessible here.
  57. uint8_t code_index = packet[0] & 0x0f;
  58. uint8_t cable_number = packet[0] >> 4;
  59. const size_t packet_size_table[16] = {
  60. 0, 0, 2, 3, 3, 1, 2, 3, 3, 3, 3, 3, 2, 2, 3, 1,
  61. };
  62. size_t packet_size = packet_size_table[code_index];
  63. if (packet_size == 0) {
  64. // These CINs are reserved. Ignore them.
  65. DVLOG(1) << "code index number (" << code_index << ") arrives "
  66. << "but it is reserved.";
  67. return;
  68. }
  69. std::map<JackUniqueKey, size_t>::const_iterator it =
  70. jack_dictionary_.find(JackUniqueKey(device,
  71. endpoint_number,
  72. cable_number));
  73. if (it != jack_dictionary_.end())
  74. delegate_->OnReceivedData(it->second, &packet[1], packet_size, time);
  75. }
  76. } // namespace midi