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

Side by Side Diff: media/midi/midi_message_queue.cc

Issue 2431393002: Web MIDI: move MIDI message validating logic into message_util.{cc|h} (Closed)
Patch Set: build fix Created 4 years, 2 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 unified diff | Download patch
« no previous file with comments | « media/midi/midi_manager_win.cc ('k') | media/midi/midi_message_util.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
15 const uint8_t kSysEx = 0xf0;
16 const uint8_t kEndOfSysEx = 0xf7;
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 13
32 MidiMessageQueue::MidiMessageQueue(bool allow_running_status) 14 MidiMessageQueue::MidiMessageQueue(bool allow_running_status)
33 : allow_running_status_(allow_running_status) {} 15 : allow_running_status_(allow_running_status) {}
34 16
35 MidiMessageQueue::~MidiMessageQueue() {} 17 MidiMessageQueue::~MidiMessageQueue() {}
36 18
37 void MidiMessageQueue::Add(const std::vector<uint8_t>& data) { 19 void MidiMessageQueue::Add(const std::vector<uint8_t>& data) {
38 queue_.insert(queue_.end(), data.begin(), data.end()); 20 queue_.insert(queue_.end(), data.begin(), data.end());
39 } 21 }
40 22
41 void MidiMessageQueue::Add(const uint8_t* data, size_t length) { 23 void MidiMessageQueue::Add(const uint8_t* data, size_t length) {
42 queue_.insert(queue_.end(), data, data + length); 24 queue_.insert(queue_.end(), data, data + length);
43 } 25 }
44 26
45 void MidiMessageQueue::Get(std::vector<uint8_t>* message) { 27 void MidiMessageQueue::Get(std::vector<uint8_t>* message) {
46 message->clear(); 28 message->clear();
47 29
48 while (true) { 30 while (true) {
49 // Check if |next_message_| is already a complete MIDI message or not. 31 // Check if |next_message_| is already a complete MIDI message or not.
50 if (!next_message_.empty()) { 32 if (!next_message_.empty()) {
51 const uint8_t status_byte = next_message_.front(); 33 const uint8_t status_byte = next_message_.front();
52 const size_t target_len = GetMidiMessageLength(status_byte); 34 const size_t target_len = GetMessageLength(status_byte);
53 if (target_len == 0) { 35 if (target_len == 0) {
54 DCHECK_EQ(kSysEx, status_byte); 36 DCHECK_EQ(kSysExByte, status_byte);
55 if (next_message_.back() == kEndOfSysEx) { 37 if (next_message_.back() == kEndOfSysExByte) {
56 // OK, this is a complete SysEx message. 38 // OK, this is a complete SysEx message.
57 std::swap(*message, next_message_); 39 std::swap(*message, next_message_);
58 DCHECK(next_message_.empty()); 40 DCHECK(next_message_.empty());
59 return; 41 return;
60 } 42 }
61 } else if (next_message_.size() == target_len) { 43 } else if (next_message_.size() == target_len) {
62 // OK, this is a complete non-SysEx message. 44 // OK, this is a complete non-SysEx message.
63 std::swap(*message, next_message_); 45 std::swap(*message, next_message_);
64 DCHECK(next_message_.empty()); 46 DCHECK(next_message_.empty());
65 if (allow_running_status_ && !IsSystemMessage(status_byte)) { 47 if (allow_running_status_ && !IsSystemMessage(status_byte)) {
66 // Speculatively keep the status byte in case of running status. 48 // Speculatively keep the status byte in case of running status.
67 // If this assumption is not true, |next_message_| will be cleared 49 // If this assumption is not true, |next_message_| will be cleared
68 // anyway. Note that system common messages should reset the 50 // anyway. Note that system common messages should reset the
(...skipping 14 matching lines...) Expand all
83 // "System Real Time Messages" prior to |next_message_| so that each message 65 // "System Real Time Messages" prior to |next_message_| so that each message
84 // can be clearly separated as a complete MIDI message. 66 // can be clearly separated as a complete MIDI message.
85 const uint8_t next = queue_.front(); 67 const uint8_t next = queue_.front();
86 if (IsSystemRealTimeMessage(next)) { 68 if (IsSystemRealTimeMessage(next)) {
87 message->push_back(next); 69 message->push_back(next);
88 queue_.pop_front(); 70 queue_.pop_front();
89 return; 71 return;
90 } 72 }
91 73
92 if (next_message_.empty()) { 74 if (next_message_.empty()) {
93 const size_t target_len = GetMidiMessageLength(next); 75 const size_t target_len = GetMessageLength(next);
94 // If |target_len| is zero, it means either |next| is not a valid status 76 // 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 77 // byte or |next| is a valid status byte but the message length is
96 // unpredictable. For the latter case, only SysEx can be accepted. 78 // unpredictable. For the latter case, only SysEx can be accepted.
97 if (target_len > 0 || next == kSysEx) { 79 if (target_len > 0 || next == kSysExByte) {
98 next_message_.push_back(next); 80 next_message_.push_back(next);
99 } 81 }
100 // Consume |next| always, since if |next| isn't status byte, which means 82 // 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 83 // that |next| is just corrupted data, or a data byte followed by
102 // reserved message, which we are unable to understand and deal with 84 // reserved message, which we are unable to understand and deal with
103 // anyway. 85 // anyway.
104 queue_.pop_front(); 86 queue_.pop_front();
105 continue; 87 continue;
106 } 88 }
107 89
108 const uint8_t status_byte = next_message_.front(); 90 const uint8_t status_byte = next_message_.front();
109 91
110 // If we receive a new non-data byte before completing the pending message, 92 // 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|. 93 // drop the pending message and respin the loop to re-evaluate |next|.
112 // This also clears the running status byte speculatively added above, as 94 // This also clears the running status byte speculatively added above, as
113 // well as any broken incomplete messages. 95 // well as any broken incomplete messages.
114 if (!IsDataByte(next) && !(status_byte == kSysEx && next == kEndOfSysEx)) { 96 if (!IsDataByte(next) &&
97 !(status_byte == kSysExByte && next == kEndOfSysExByte)) {
115 next_message_.clear(); 98 next_message_.clear();
116 continue; 99 continue;
117 } 100 }
118 101
119 // OK to consume this byte. 102 // OK to consume this byte.
120 next_message_.push_back(next); 103 next_message_.push_back(next);
121 queue_.pop_front(); 104 queue_.pop_front();
122 } 105 }
123 } 106 }
124 107
125 } // namespace midi 108 } // namespace midi
OLDNEW
« no previous file with comments | « media/midi/midi_manager_win.cc ('k') | media/midi/midi_message_util.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698