Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "media/midi/midi_message_queue.h" | 5 #include "media/midi/midi_message_queue.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 | 8 |
| 9 #include "base/logging.h" | 9 #include "base/logging.h" |
| 10 #include "media/midi/midi_message_util.h" | 10 #include "media/midi/message_util.h" |
| 11 | 11 |
| 12 namespace midi { | 12 namespace midi { |
| 13 namespace { | |
| 14 | 13 |
| 15 const uint8_t kSysEx = 0xf0; | 14 using midi::kSysExByte; |
|
yukawa
2016/10/19 20:11:20
Do we need this?
Takashi Toyoshima
2016/10/20 05:18:17
Done.
| |
| 16 const uint8_t kEndOfSysEx = 0xf7; | 15 using midi::kEndOfSysExByte; |
|
yukawa
2016/10/19 20:11:20
Do we need this?
Takashi Toyoshima
2016/10/20 05:18:17
Done.
| |
| 17 | |
| 18 bool IsDataByte(uint8_t data) { | |
| 19 return (data & 0x80) == 0; | |
| 20 } | |
| 21 | |
| 22 bool IsSystemRealTimeMessage(uint8_t data) { | |
| 23 return 0xf8 <= data; | |
| 24 } | |
| 25 | |
| 26 bool IsSystemMessage(uint8_t data) { | |
| 27 return 0xf0 <= data; | |
| 28 } | |
| 29 | |
| 30 } // namespace | |
| 31 | 16 |
| 32 MidiMessageQueue::MidiMessageQueue(bool allow_running_status) | 17 MidiMessageQueue::MidiMessageQueue(bool allow_running_status) |
| 33 : allow_running_status_(allow_running_status) {} | 18 : allow_running_status_(allow_running_status) {} |
| 34 | 19 |
| 35 MidiMessageQueue::~MidiMessageQueue() {} | 20 MidiMessageQueue::~MidiMessageQueue() {} |
| 36 | 21 |
| 37 void MidiMessageQueue::Add(const std::vector<uint8_t>& data) { | 22 void MidiMessageQueue::Add(const std::vector<uint8_t>& data) { |
| 38 queue_.insert(queue_.end(), data.begin(), data.end()); | 23 queue_.insert(queue_.end(), data.begin(), data.end()); |
| 39 } | 24 } |
| 40 | 25 |
| 41 void MidiMessageQueue::Add(const uint8_t* data, size_t length) { | 26 void MidiMessageQueue::Add(const uint8_t* data, size_t length) { |
| 42 queue_.insert(queue_.end(), data, data + length); | 27 queue_.insert(queue_.end(), data, data + length); |
| 43 } | 28 } |
| 44 | 29 |
| 45 void MidiMessageQueue::Get(std::vector<uint8_t>* message) { | 30 void MidiMessageQueue::Get(std::vector<uint8_t>* message) { |
| 46 message->clear(); | 31 message->clear(); |
| 47 | 32 |
| 48 while (true) { | 33 while (true) { |
| 49 // Check if |next_message_| is already a complete MIDI message or not. | 34 // Check if |next_message_| is already a complete MIDI message or not. |
| 50 if (!next_message_.empty()) { | 35 if (!next_message_.empty()) { |
| 51 const uint8_t status_byte = next_message_.front(); | 36 const uint8_t status_byte = next_message_.front(); |
| 52 const size_t target_len = GetMidiMessageLength(status_byte); | 37 const size_t target_len = GetMessageLength(status_byte); |
| 53 if (target_len == 0) { | 38 if (target_len == 0) { |
| 54 DCHECK_EQ(kSysEx, status_byte); | 39 DCHECK_EQ(kSysExByte, status_byte); |
| 55 if (next_message_.back() == kEndOfSysEx) { | 40 if (next_message_.back() == kEndOfSysExByte) { |
| 56 // OK, this is a complete SysEx message. | 41 // OK, this is a complete SysEx message. |
| 57 std::swap(*message, next_message_); | 42 std::swap(*message, next_message_); |
| 58 DCHECK(next_message_.empty()); | 43 DCHECK(next_message_.empty()); |
| 59 return; | 44 return; |
| 60 } | 45 } |
| 61 } else if (next_message_.size() == target_len) { | 46 } else if (next_message_.size() == target_len) { |
| 62 // OK, this is a complete non-SysEx message. | 47 // OK, this is a complete non-SysEx message. |
| 63 std::swap(*message, next_message_); | 48 std::swap(*message, next_message_); |
| 64 DCHECK(next_message_.empty()); | 49 DCHECK(next_message_.empty()); |
| 65 if (allow_running_status_ && !IsSystemMessage(status_byte)) { | 50 if (allow_running_status_ && !IsSystemMessage(status_byte)) { |
| 66 // Speculatively keep the status byte in case of running status. | 51 // Speculatively keep the status byte in case of running status. |
| 67 // If this assumption is not true, |next_message_| will be cleared | 52 // If this assumption is not true, |next_message_| will be cleared |
| 68 // anyway. Note that system common messages should reset the | 53 // anyway. Note that system common messages should reset the |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 83 // "System Real Time Messages" prior to |next_message_| so that each message | 68 // "System Real Time Messages" prior to |next_message_| so that each message |
| 84 // can be clearly separated as a complete MIDI message. | 69 // can be clearly separated as a complete MIDI message. |
| 85 const uint8_t next = queue_.front(); | 70 const uint8_t next = queue_.front(); |
| 86 if (IsSystemRealTimeMessage(next)) { | 71 if (IsSystemRealTimeMessage(next)) { |
| 87 message->push_back(next); | 72 message->push_back(next); |
| 88 queue_.pop_front(); | 73 queue_.pop_front(); |
| 89 return; | 74 return; |
| 90 } | 75 } |
| 91 | 76 |
| 92 if (next_message_.empty()) { | 77 if (next_message_.empty()) { |
| 93 const size_t target_len = GetMidiMessageLength(next); | 78 const size_t target_len = GetMessageLength(next); |
| 94 // If |target_len| is zero, it means either |next| is not a valid status | 79 // If |target_len| is zero, it means either |next| is not a valid status |
| 95 // byte or |next| is a valid status byte but the message length is | 80 // byte or |next| is a valid status byte but the message length is |
| 96 // unpredictable. For the latter case, only SysEx can be accepted. | 81 // unpredictable. For the latter case, only SysEx can be accepted. |
| 97 if (target_len > 0 || next == kSysEx) { | 82 if (target_len > 0 || next == kSysExByte) { |
| 98 next_message_.push_back(next); | 83 next_message_.push_back(next); |
| 99 } | 84 } |
| 100 // Consume |next| always, since if |next| isn't status byte, which means | 85 // Consume |next| always, since if |next| isn't status byte, which means |
| 101 // that |next| is just corrupted data, or a data byte followed by | 86 // that |next| is just corrupted data, or a data byte followed by |
| 102 // reserved message, which we are unable to understand and deal with | 87 // reserved message, which we are unable to understand and deal with |
| 103 // anyway. | 88 // anyway. |
| 104 queue_.pop_front(); | 89 queue_.pop_front(); |
| 105 continue; | 90 continue; |
| 106 } | 91 } |
| 107 | 92 |
| 108 const uint8_t status_byte = next_message_.front(); | 93 const uint8_t status_byte = next_message_.front(); |
| 109 | 94 |
| 110 // If we receive a new non-data byte before completing the pending message, | 95 // If we receive a new non-data byte before completing the pending message, |
| 111 // drop the pending message and respin the loop to re-evaluate |next|. | 96 // drop the pending message and respin the loop to re-evaluate |next|. |
| 112 // This also clears the running status byte speculatively added above, as | 97 // This also clears the running status byte speculatively added above, as |
| 113 // well as any broken incomplete messages. | 98 // well as any broken incomplete messages. |
| 114 if (!IsDataByte(next) && !(status_byte == kSysEx && next == kEndOfSysEx)) { | 99 if (!IsDataByte(next) && |
| 100 !(status_byte == kSysExByte && next == kEndOfSysExByte)) { | |
| 115 next_message_.clear(); | 101 next_message_.clear(); |
| 116 continue; | 102 continue; |
| 117 } | 103 } |
| 118 | 104 |
| 119 // OK to consume this byte. | 105 // OK to consume this byte. |
| 120 next_message_.push_back(next); | 106 next_message_.push_back(next); |
| 121 queue_.pop_front(); | 107 queue_.pop_front(); |
| 122 } | 108 } |
| 123 } | 109 } |
| 124 | 110 |
| 125 } // namespace midi | 111 } // namespace midi |
| OLD | NEW |