OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2013 Google Inc. All rights reserved. | 2 * Copyright (C) 2013 Google Inc. All rights reserved. |
3 * | 3 * |
4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are |
6 * met: | 6 * met: |
7 * | 7 * |
8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright |
9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
10 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
44 | 44 |
45 double now(ExecutionContext* context) | 45 double now(ExecutionContext* context) |
46 { | 46 { |
47 DOMWindow* window = context ? context->executingWindow() : 0; | 47 DOMWindow* window = context ? context->executingWindow() : 0; |
48 Performance* performance = window ? &window->performance() : 0; | 48 Performance* performance = window ? &window->performance() : 0; |
49 return performance ? performance->now() : 0.0; | 49 return performance ? performance->now() : 0.0; |
50 } | 50 } |
51 | 51 |
52 class MessageValidator { | 52 class MessageValidator { |
53 public: | 53 public: |
54 static bool validate(Uint8Array* array, ExceptionState& exceptionState, bool
sysExEnabled) | 54 static bool validate(Uint8Array* array, ExceptionState& exceptionState, bool
sysexEnabled) |
55 { | 55 { |
56 MessageValidator validator(array); | 56 MessageValidator validator(array); |
57 return validator.process(exceptionState, sysExEnabled); | 57 return validator.process(exceptionState, sysexEnabled); |
58 } | 58 } |
59 private: | 59 private: |
60 MessageValidator(Uint8Array* array) | 60 MessageValidator(Uint8Array* array) |
61 : m_data(array->data()) | 61 : m_data(array->data()) |
62 , m_length(array->length()) | 62 , m_length(array->length()) |
63 , m_offset(0) { } | 63 , m_offset(0) { } |
64 | 64 |
65 bool process(ExceptionState& exceptionState, bool sysExEnabled) | 65 bool process(ExceptionState& exceptionState, bool sysexEnabled) |
66 { | 66 { |
67 while (!isEndOfData() && acceptRealTimeMessages()) { | 67 while (!isEndOfData() && acceptRealTimeMessages()) { |
68 if (!isStatusByte()) { | 68 if (!isStatusByte()) { |
69 exceptionState.throwTypeError("Running status is not allowed " +
getPositionString()); | 69 exceptionState.throwTypeError("Running status is not allowed " +
getPositionString()); |
70 return false; | 70 return false; |
71 } | 71 } |
72 if (isEndOfSysEx()) { | 72 if (isEndOfSysex()) { |
73 exceptionState.throwTypeError("Unexpected end of system exclusiv
e message " + getPositionString()); | 73 exceptionState.throwTypeError("Unexpected end of system exclusiv
e message " + getPositionString()); |
74 return false; | 74 return false; |
75 } | 75 } |
76 if (isReservedStatusByte()) { | 76 if (isReservedStatusByte()) { |
77 exceptionState.throwTypeError("Reserved status is not allowed "
+ getPositionString()); | 77 exceptionState.throwTypeError("Reserved status is not allowed "
+ getPositionString()); |
78 return false; | 78 return false; |
79 } | 79 } |
80 if (isSysEx()) { | 80 if (isSysex()) { |
81 if (!sysExEnabled) { | 81 if (!sysexEnabled) { |
82 exceptionState.throwDOMException(InvalidAccessError, "System
exclusive message is not allowed " + getPositionString()); | 82 exceptionState.throwDOMException(InvalidAccessError, "System
exclusive message is not allowed " + getPositionString()); |
83 return false; | 83 return false; |
84 } | 84 } |
85 if (!acceptCurrentSysEx()) { | 85 if (!acceptCurrentSysex()) { |
86 if (isEndOfData()) | 86 if (isEndOfData()) |
87 exceptionState.throwTypeError("System exclusive message
is not ended by end of system exclusive message."); | 87 exceptionState.throwTypeError("System exclusive message
is not ended by end of system exclusive message."); |
88 else | 88 else |
89 exceptionState.throwTypeError("System exclusive message
contains a status byte " + getPositionString()); | 89 exceptionState.throwTypeError("System exclusive message
contains a status byte " + getPositionString()); |
90 return false; | 90 return false; |
91 } | 91 } |
92 } else { | 92 } else { |
93 if (!acceptCurrentMessage()) { | 93 if (!acceptCurrentMessage()) { |
94 if (isEndOfData()) | 94 if (isEndOfData()) |
95 exceptionState.throwTypeError("Message is incomplete."); | 95 exceptionState.throwTypeError("Message is incomplete."); |
96 else | 96 else |
97 exceptionState.throwTypeError("Unexpected status byte at
index " + getPositionString()); | 97 exceptionState.throwTypeError("Unexpected status byte at
index " + getPositionString()); |
98 return false; | 98 return false; |
99 } | 99 } |
100 } | 100 } |
101 } | 101 } |
102 return true; | 102 return true; |
103 } | 103 } |
104 | 104 |
105 private: | 105 private: |
106 bool isEndOfData() { return m_offset >= m_length; } | 106 bool isEndOfData() { return m_offset >= m_length; } |
107 bool isSysEx() { return m_data[m_offset] == 0xf0; } | 107 bool isSysex() { return m_data[m_offset] == 0xf0; } |
108 bool isSystemMessage() { return m_data[m_offset] >= 0xf0; } | 108 bool isSystemMessage() { return m_data[m_offset] >= 0xf0; } |
109 bool isEndOfSysEx() { return m_data[m_offset] == 0xf7; } | 109 bool isEndOfSysex() { return m_data[m_offset] == 0xf7; } |
110 bool isRealTimeMessage() { return m_data[m_offset] >= 0xf8; } | 110 bool isRealTimeMessage() { return m_data[m_offset] >= 0xf8; } |
111 bool isStatusByte() { return m_data[m_offset] & 0x80; } | 111 bool isStatusByte() { return m_data[m_offset] & 0x80; } |
112 bool isReservedStatusByte() { return m_data[m_offset] == 0xf4 || m_data[m_of
fset] == 0xf5 || m_data[m_offset] == 0xf9 || m_data[m_offset] == 0xfd; } | 112 bool isReservedStatusByte() { return m_data[m_offset] == 0xf4 || m_data[m_of
fset] == 0xf5 || m_data[m_offset] == 0xf9 || m_data[m_offset] == 0xfd; } |
113 | 113 |
114 bool acceptRealTimeMessages() | 114 bool acceptRealTimeMessages() |
115 { | 115 { |
116 for (; !isEndOfData(); m_offset++) { | 116 for (; !isEndOfData(); m_offset++) { |
117 if (isRealTimeMessage() && !isReservedStatusByte()) | 117 if (isRealTimeMessage() && !isReservedStatusByte()) |
118 continue; | 118 continue; |
119 return true; | 119 return true; |
120 } | 120 } |
121 return false; | 121 return false; |
122 } | 122 } |
123 | 123 |
124 bool acceptCurrentSysEx() | 124 bool acceptCurrentSysex() |
125 { | 125 { |
126 ASSERT(isSysEx()); | 126 ASSERT(isSysex()); |
127 for (m_offset++; !isEndOfData(); m_offset++) { | 127 for (m_offset++; !isEndOfData(); m_offset++) { |
128 if (isReservedStatusByte()) | 128 if (isReservedStatusByte()) |
129 return false; | 129 return false; |
130 if (isRealTimeMessage()) | 130 if (isRealTimeMessage()) |
131 continue; | 131 continue; |
132 if (isEndOfSysEx()) { | 132 if (isEndOfSysex()) { |
133 m_offset++; | 133 m_offset++; |
134 return true; | 134 return true; |
135 } | 135 } |
136 if (isStatusByte()) | 136 if (isStatusByte()) |
137 return false; | 137 return false; |
138 } | 138 } |
139 return false; | 139 return false; |
140 } | 140 } |
141 | 141 |
142 bool acceptCurrentMessage() | 142 bool acceptCurrentMessage() |
143 { | 143 { |
144 ASSERT(isStatusByte()); | 144 ASSERT(isStatusByte()); |
145 ASSERT(!isSysEx()); | 145 ASSERT(!isSysex()); |
146 ASSERT(!isReservedStatusByte()); | 146 ASSERT(!isReservedStatusByte()); |
147 ASSERT(!isRealTimeMessage()); | 147 ASSERT(!isRealTimeMessage()); |
148 static const int channelMessageLength[7] = { 3, 3, 3, 3, 2, 2, 3 }; // f
or 0x8*, 0x9*, ..., 0xe* | 148 static const int channelMessageLength[7] = { 3, 3, 3, 3, 2, 2, 3 }; // f
or 0x8*, 0x9*, ..., 0xe* |
149 static const int systemMessageLength[7] = { 2, 3, 2, 0, 0, 1, 0 }; // fo
r 0xf1, 0xf2, ..., 0xf7 | 149 static const int systemMessageLength[7] = { 2, 3, 2, 0, 0, 1, 0 }; // fo
r 0xf1, 0xf2, ..., 0xf7 |
150 size_t length = isSystemMessage() ? systemMessageLength[m_data[m_offset]
- 0xf1] : channelMessageLength[(m_data[m_offset] >> 4) - 8]; | 150 size_t length = isSystemMessage() ? systemMessageLength[m_data[m_offset]
- 0xf1] : channelMessageLength[(m_data[m_offset] >> 4) - 8]; |
151 size_t count = 1; | 151 size_t count = 1; |
152 for (m_offset++; !isEndOfData(); m_offset++) { | 152 for (m_offset++; !isEndOfData(); m_offset++) { |
153 if (isReservedStatusByte()) | 153 if (isReservedStatusByte()) |
154 return false; | 154 return false; |
155 if (isRealTimeMessage()) | 155 if (isRealTimeMessage()) |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
191 } | 191 } |
192 | 192 |
193 void MIDIOutput::send(Uint8Array* array, double timestamp, ExceptionState& excep
tionState) | 193 void MIDIOutput::send(Uint8Array* array, double timestamp, ExceptionState& excep
tionState) |
194 { | 194 { |
195 if (timestamp == 0.0) | 195 if (timestamp == 0.0) |
196 timestamp = now(executionContext()); | 196 timestamp = now(executionContext()); |
197 | 197 |
198 if (!array) | 198 if (!array) |
199 return; | 199 return; |
200 | 200 |
201 if (MessageValidator::validate(array, exceptionState, midiAccess()->sysExEna
bled())) | 201 if (MessageValidator::validate(array, exceptionState, midiAccess()->sysexEna
bled())) |
202 midiAccess()->sendMIDIData(m_portIndex, array->data(), array->length(),
timestamp); | 202 midiAccess()->sendMIDIData(m_portIndex, array->data(), array->length(),
timestamp); |
203 } | 203 } |
204 | 204 |
205 void MIDIOutput::send(Vector<unsigned> unsignedData, double timestamp, Exception
State& exceptionState) | 205 void MIDIOutput::send(Vector<unsigned> unsignedData, double timestamp, Exception
State& exceptionState) |
206 { | 206 { |
207 if (timestamp == 0.0) | 207 if (timestamp == 0.0) |
208 timestamp = now(executionContext()); | 208 timestamp = now(executionContext()); |
209 | 209 |
210 RefPtr<Uint8Array> array = Uint8Array::create(unsignedData.size()); | 210 RefPtr<Uint8Array> array = Uint8Array::create(unsignedData.size()); |
211 | 211 |
(...skipping 18 matching lines...) Expand all Loading... |
230 { | 230 { |
231 send(unsignedData, 0.0, exceptionState); | 231 send(unsignedData, 0.0, exceptionState); |
232 } | 232 } |
233 | 233 |
234 void MIDIOutput::trace(Visitor* visitor) | 234 void MIDIOutput::trace(Visitor* visitor) |
235 { | 235 { |
236 MIDIPort::trace(visitor); | 236 MIDIPort::trace(visitor); |
237 } | 237 } |
238 | 238 |
239 } // namespace WebCore | 239 } // namespace WebCore |
OLD | NEW |