| 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 |