OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 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_manager_alsa.h" | 5 #include "media/midi/midi_manager_alsa.h" |
6 | 6 |
7 #include <errno.h> | 7 #include <errno.h> |
8 #include <poll.h> | 8 #include <poll.h> |
9 #include <stdlib.h> | 9 #include <stdlib.h> |
10 #include <algorithm> | 10 #include <algorithm> |
(...skipping 260 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
271 // Close the out client. This will trigger the event thread to stop, | 271 // Close the out client. This will trigger the event thread to stop, |
272 // because of SND_SEQ_EVENT_CLIENT_EXIT. | 272 // because of SND_SEQ_EVENT_CLIENT_EXIT. |
273 if (out_client_.get()) | 273 if (out_client_.get()) |
274 snd_seq_close(out_client_.release()); | 274 snd_seq_close(out_client_.release()); |
275 | 275 |
276 // Wait for the event thread to stop. | 276 // Wait for the event thread to stop. |
277 event_thread_.Stop(); | 277 event_thread_.Stop(); |
278 } | 278 } |
279 | 279 |
280 void MidiManagerAlsa::DispatchSendMidiData(MidiManagerClient* client, | 280 void MidiManagerAlsa::DispatchSendMidiData(MidiManagerClient* client, |
281 uint32 port_index, | 281 uint32_t port_index, |
282 const std::vector<uint8>& data, | 282 const std::vector<uint8_t>& data, |
283 double timestamp) { | 283 double timestamp) { |
284 if (!send_thread_.IsRunning()) | 284 if (!send_thread_.IsRunning()) |
285 send_thread_.Start(); | 285 send_thread_.Start(); |
286 | 286 |
287 base::TimeDelta delay; | 287 base::TimeDelta delay; |
288 if (timestamp != 0.0) { | 288 if (timestamp != 0.0) { |
289 base::TimeTicks time_to_send = | 289 base::TimeTicks time_to_send = |
290 base::TimeTicks() + base::TimeDelta::FromMicroseconds( | 290 base::TimeTicks() + base::TimeDelta::FromMicroseconds( |
291 timestamp * base::Time::kMicrosecondsPerSecond); | 291 timestamp * base::Time::kMicrosecondsPerSecond); |
292 delay = std::max(time_to_send - base::TimeTicks::Now(), base::TimeDelta()); | 292 delay = std::max(time_to_send - base::TimeTicks::Now(), base::TimeDelta()); |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
392 std::string json; | 392 std::string json; |
393 JSONStringValueSerializer serializer(&json); | 393 JSONStringValueSerializer serializer(&json); |
394 serializer.Serialize(*Value().get()); | 394 serializer.Serialize(*Value().get()); |
395 return json; | 395 return json; |
396 } | 396 } |
397 | 397 |
398 // TODO(agoode): Do not use SHA256 here. Instead store a persistent | 398 // TODO(agoode): Do not use SHA256 here. Instead store a persistent |
399 // mapping and just use a UUID or other random string. | 399 // mapping and just use a UUID or other random string. |
400 // http://crbug.com/465320 | 400 // http://crbug.com/465320 |
401 std::string MidiManagerAlsa::MidiPort::OpaqueKey() const { | 401 std::string MidiManagerAlsa::MidiPort::OpaqueKey() const { |
402 uint8 hash[crypto::kSHA256Length]; | 402 uint8_t hash[crypto::kSHA256Length]; |
403 crypto::SHA256HashString(JSONValue(), &hash, sizeof(hash)); | 403 crypto::SHA256HashString(JSONValue(), &hash, sizeof(hash)); |
404 return base::HexEncode(&hash, sizeof(hash)); | 404 return base::HexEncode(&hash, sizeof(hash)); |
405 } | 405 } |
406 | 406 |
407 bool MidiManagerAlsa::MidiPort::MatchConnected(const MidiPort& query) const { | 407 bool MidiManagerAlsa::MidiPort::MatchConnected(const MidiPort& query) const { |
408 // Matches on: | 408 // Matches on: |
409 // connected == true | 409 // connected == true |
410 // type | 410 // type |
411 // path | 411 // path |
412 // id | 412 // id |
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
557 } | 557 } |
558 | 558 |
559 // No match. | 559 // No match. |
560 return ports_.end(); | 560 return ports_.end(); |
561 } | 561 } |
562 | 562 |
563 MidiManagerAlsa::MidiPortStateBase::MidiPortStateBase() = default; | 563 MidiManagerAlsa::MidiPortStateBase::MidiPortStateBase() = default; |
564 | 564 |
565 MidiManagerAlsa::MidiPortState::MidiPortState() = default; | 565 MidiManagerAlsa::MidiPortState::MidiPortState() = default; |
566 | 566 |
567 uint32 MidiManagerAlsa::MidiPortState::push_back(scoped_ptr<MidiPort> port) { | 567 uint32_t MidiManagerAlsa::MidiPortState::push_back(scoped_ptr<MidiPort> port) { |
568 // Add the web midi index. | 568 // Add the web midi index. |
569 uint32 web_port_index = 0; | 569 uint32_t web_port_index = 0; |
570 switch (port->type()) { | 570 switch (port->type()) { |
571 case MidiPort::Type::kInput: | 571 case MidiPort::Type::kInput: |
572 web_port_index = num_input_ports_++; | 572 web_port_index = num_input_ports_++; |
573 break; | 573 break; |
574 case MidiPort::Type::kOutput: | 574 case MidiPort::Type::kOutput: |
575 web_port_index = num_output_ports_++; | 575 web_port_index = num_output_ports_++; |
576 break; | 576 break; |
577 } | 577 } |
578 port->set_web_port_index(web_port_index); | 578 port->set_web_port_index(web_port_index); |
579 MidiPortStateBase::push_back(port.Pass()); | 579 MidiPortStateBase::push_back(port.Pass()); |
(...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
803 if (at_index && at_index != std::string::npos) { | 803 if (at_index && at_index != std::string::npos) { |
804 size_t name_index = alsa_longname.rfind(alsa_name, at_index - 1); | 804 size_t name_index = alsa_longname.rfind(alsa_name, at_index - 1); |
805 if (name_index && name_index != std::string::npos) | 805 if (name_index && name_index != std::string::npos) |
806 return alsa_longname.substr(0, name_index - 1); | 806 return alsa_longname.substr(0, name_index - 1); |
807 } | 807 } |
808 | 808 |
809 // Failure. | 809 // Failure. |
810 return ""; | 810 return ""; |
811 } | 811 } |
812 | 812 |
813 void MidiManagerAlsa::SendMidiData(uint32 port_index, | 813 void MidiManagerAlsa::SendMidiData(uint32_t port_index, |
814 const std::vector<uint8>& data) { | 814 const std::vector<uint8_t>& data) { |
815 DCHECK(send_thread_.task_runner()->BelongsToCurrentThread()); | 815 DCHECK(send_thread_.task_runner()->BelongsToCurrentThread()); |
816 | 816 |
817 snd_midi_event_t* encoder; | 817 snd_midi_event_t* encoder; |
818 snd_midi_event_new(kSendBufferSize, &encoder); | 818 snd_midi_event_new(kSendBufferSize, &encoder); |
819 for (const auto datum : data) { | 819 for (const auto datum : data) { |
820 snd_seq_event_t event; | 820 snd_seq_event_t event; |
821 int result = snd_midi_event_encode_byte(encoder, datum, &event); | 821 int result = snd_midi_event_encode_byte(encoder, datum, &event); |
822 if (result == 1) { | 822 if (result == 1) { |
823 // Full event, send it. | 823 // Full event, send it. |
824 base::AutoLock lock(out_ports_lock_); | 824 base::AutoLock lock(out_ports_lock_); |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
921 // Do again. | 921 // Do again. |
922 if (loop_again) | 922 if (loop_again) |
923 ScheduleEventLoop(); | 923 ScheduleEventLoop(); |
924 } | 924 } |
925 | 925 |
926 void MidiManagerAlsa::ProcessSingleEvent(snd_seq_event_t* event, | 926 void MidiManagerAlsa::ProcessSingleEvent(snd_seq_event_t* event, |
927 double timestamp) { | 927 double timestamp) { |
928 auto source_it = | 928 auto source_it = |
929 source_map_.find(AddrToInt(event->source.client, event->source.port)); | 929 source_map_.find(AddrToInt(event->source.client, event->source.port)); |
930 if (source_it != source_map_.end()) { | 930 if (source_it != source_map_.end()) { |
931 uint32 source = source_it->second; | 931 uint32_t source = source_it->second; |
932 if (event->type == SND_SEQ_EVENT_SYSEX) { | 932 if (event->type == SND_SEQ_EVENT_SYSEX) { |
933 // Special! Variable-length sysex. | 933 // Special! Variable-length sysex. |
934 ReceiveMidiData(source, static_cast<const uint8*>(event->data.ext.ptr), | 934 ReceiveMidiData(source, static_cast<const uint8_t*>(event->data.ext.ptr), |
935 event->data.ext.len, timestamp); | 935 event->data.ext.len, timestamp); |
936 } else { | 936 } else { |
937 // Otherwise, decode this and send that on. | 937 // Otherwise, decode this and send that on. |
938 unsigned char buf[12]; | 938 unsigned char buf[12]; |
939 long count = | 939 long count = |
940 snd_midi_event_decode(decoder_.get(), buf, sizeof(buf), event); | 940 snd_midi_event_decode(decoder_.get(), buf, sizeof(buf), event); |
941 if (count <= 0) { | 941 if (count <= 0) { |
942 if (count != -ENOENT) { | 942 if (count != -ENOENT) { |
943 // ENOENT means that it's not a MIDI message, which is not an | 943 // ENOENT means that it's not a MIDI message, which is not an |
944 // error, but other negative values are errors for us. | 944 // error, but other negative values are errors for us. |
(...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1137 return; | 1137 return; |
1138 | 1138 |
1139 // Generate new port state. | 1139 // Generate new port state. |
1140 auto new_port_state = alsa_seq_state_.ToMidiPortState(alsa_cards_); | 1140 auto new_port_state = alsa_seq_state_.ToMidiPortState(alsa_cards_); |
1141 | 1141 |
1142 // Disconnect any connected old ports that are now missing. | 1142 // Disconnect any connected old ports that are now missing. |
1143 for (auto& old_port : port_state_) { | 1143 for (auto& old_port : port_state_) { |
1144 if (old_port->connected() && | 1144 if (old_port->connected() && |
1145 (new_port_state->FindConnected(*old_port) == new_port_state->end())) { | 1145 (new_port_state->FindConnected(*old_port) == new_port_state->end())) { |
1146 old_port->set_connected(false); | 1146 old_port->set_connected(false); |
1147 uint32 web_port_index = old_port->web_port_index(); | 1147 uint32_t web_port_index = old_port->web_port_index(); |
1148 switch (old_port->type()) { | 1148 switch (old_port->type()) { |
1149 case MidiPort::Type::kInput: | 1149 case MidiPort::Type::kInput: |
1150 source_map_.erase( | 1150 source_map_.erase( |
1151 AddrToInt(old_port->client_id(), old_port->port_id())); | 1151 AddrToInt(old_port->client_id(), old_port->port_id())); |
1152 SetInputPortState(web_port_index, MIDI_PORT_DISCONNECTED); | 1152 SetInputPortState(web_port_index, MIDI_PORT_DISCONNECTED); |
1153 break; | 1153 break; |
1154 case MidiPort::Type::kOutput: | 1154 case MidiPort::Type::kOutput: |
1155 DeleteAlsaOutputPort(web_port_index); | 1155 DeleteAlsaOutputPort(web_port_index); |
1156 SetOutputPortState(web_port_index, MIDI_PORT_DISCONNECTED); | 1156 SetOutputPortState(web_port_index, MIDI_PORT_DISCONNECTED); |
1157 break; | 1157 break; |
1158 } | 1158 } |
1159 } | 1159 } |
1160 } | 1160 } |
1161 | 1161 |
1162 // Reconnect or add new ports. | 1162 // Reconnect or add new ports. |
1163 auto it = new_port_state->begin(); | 1163 auto it = new_port_state->begin(); |
1164 while (it != new_port_state->end()) { | 1164 while (it != new_port_state->end()) { |
1165 auto& new_port = *it; | 1165 auto& new_port = *it; |
1166 auto old_port = port_state_.Find(*new_port); | 1166 auto old_port = port_state_.Find(*new_port); |
1167 if (old_port == port_state_.end()) { | 1167 if (old_port == port_state_.end()) { |
1168 // Add new port. | 1168 // Add new port. |
1169 const auto& opaque_key = new_port->OpaqueKey(); | 1169 const auto& opaque_key = new_port->OpaqueKey(); |
1170 const auto& manufacturer = new_port->manufacturer(); | 1170 const auto& manufacturer = new_port->manufacturer(); |
1171 const auto& port_name = new_port->port_name(); | 1171 const auto& port_name = new_port->port_name(); |
1172 const auto& version = new_port->version(); | 1172 const auto& version = new_port->version(); |
1173 const auto& type = new_port->type(); | 1173 const auto& type = new_port->type(); |
1174 const auto& client_id = new_port->client_id(); | 1174 const auto& client_id = new_port->client_id(); |
1175 const auto& port_id = new_port->port_id(); | 1175 const auto& port_id = new_port->port_id(); |
1176 | 1176 |
1177 uint32 web_port_index = port_state_.push_back(new_port.Pass()); | 1177 uint32_t web_port_index = port_state_.push_back(new_port.Pass()); |
1178 it = new_port_state->erase(it); | 1178 it = new_port_state->erase(it); |
1179 | 1179 |
1180 MidiPortInfo info(opaque_key, manufacturer, port_name, version, | 1180 MidiPortInfo info(opaque_key, manufacturer, port_name, version, |
1181 MIDI_PORT_OPENED); | 1181 MIDI_PORT_OPENED); |
1182 switch (type) { | 1182 switch (type) { |
1183 case MidiPort::Type::kInput: | 1183 case MidiPort::Type::kInput: |
1184 if (Subscribe(web_port_index, client_id, port_id)) | 1184 if (Subscribe(web_port_index, client_id, port_id)) |
1185 AddInputPort(info); | 1185 AddInputPort(info); |
1186 break; | 1186 break; |
1187 case MidiPort::Type::kOutput: | 1187 case MidiPort::Type::kOutput: |
1188 if (CreateAlsaOutputPort(web_port_index, client_id, port_id)) | 1188 if (CreateAlsaOutputPort(web_port_index, client_id, port_id)) |
1189 AddOutputPort(info); | 1189 AddOutputPort(info); |
1190 break; | 1190 break; |
1191 } | 1191 } |
1192 } else if (!(*old_port)->connected()) { | 1192 } else if (!(*old_port)->connected()) { |
1193 // Reconnect. | 1193 // Reconnect. |
1194 uint32 web_port_index = (*old_port)->web_port_index(); | 1194 uint32_t web_port_index = (*old_port)->web_port_index(); |
1195 (*old_port)->Update(new_port->path(), new_port->client_id(), | 1195 (*old_port)->Update(new_port->path(), new_port->client_id(), |
1196 new_port->port_id(), new_port->client_name(), | 1196 new_port->port_id(), new_port->client_name(), |
1197 new_port->port_name(), new_port->manufacturer(), | 1197 new_port->port_name(), new_port->manufacturer(), |
1198 new_port->version()); | 1198 new_port->version()); |
1199 switch ((*old_port)->type()) { | 1199 switch ((*old_port)->type()) { |
1200 case MidiPort::Type::kInput: | 1200 case MidiPort::Type::kInput: |
1201 if (Subscribe(web_port_index, (*old_port)->client_id(), | 1201 if (Subscribe(web_port_index, (*old_port)->client_id(), |
1202 (*old_port)->port_id())) | 1202 (*old_port)->port_id())) |
1203 SetInputPortState(web_port_index, MIDI_PORT_OPENED); | 1203 SetInputPortState(web_port_index, MIDI_PORT_OPENED); |
1204 break; | 1204 break; |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1270 const char* path = device::udev_list_entry_get_name(list_entry); | 1270 const char* path = device::udev_list_entry_get_name(list_entry); |
1271 device::ScopedUdevDevicePtr dev( | 1271 device::ScopedUdevDevicePtr dev( |
1272 device::udev_device_new_from_syspath(udev_.get(), path)); | 1272 device::udev_device_new_from_syspath(udev_.get(), path)); |
1273 if (dev.get()) | 1273 if (dev.get()) |
1274 ProcessUdevEvent(dev.get()); | 1274 ProcessUdevEvent(dev.get()); |
1275 } | 1275 } |
1276 | 1276 |
1277 return true; | 1277 return true; |
1278 } | 1278 } |
1279 | 1279 |
1280 bool MidiManagerAlsa::CreateAlsaOutputPort(uint32 port_index, | 1280 bool MidiManagerAlsa::CreateAlsaOutputPort(uint32_t port_index, |
1281 int client_id, | 1281 int client_id, |
1282 int port_id) { | 1282 int port_id) { |
1283 // Create the port. | 1283 // Create the port. |
1284 int out_port = snd_seq_create_simple_port( | 1284 int out_port = snd_seq_create_simple_port( |
1285 out_client_.get(), NULL, kCreateOutputPortCaps, kCreatePortType); | 1285 out_client_.get(), NULL, kCreateOutputPortCaps, kCreatePortType); |
1286 if (out_port < 0) { | 1286 if (out_port < 0) { |
1287 VLOG(1) << "snd_seq_create_simple_port fails: " << snd_strerror(out_port); | 1287 VLOG(1) << "snd_seq_create_simple_port fails: " << snd_strerror(out_port); |
1288 return false; | 1288 return false; |
1289 } | 1289 } |
1290 // Activate port subscription. | 1290 // Activate port subscription. |
(...skipping 13 matching lines...) Expand all Loading... |
1304 snd_seq_delete_simple_port(out_client_.get(), out_port); | 1304 snd_seq_delete_simple_port(out_client_.get(), out_port); |
1305 return false; | 1305 return false; |
1306 } | 1306 } |
1307 | 1307 |
1308 // Update our map. | 1308 // Update our map. |
1309 base::AutoLock lock(out_ports_lock_); | 1309 base::AutoLock lock(out_ports_lock_); |
1310 out_ports_[port_index] = out_port; | 1310 out_ports_[port_index] = out_port; |
1311 return true; | 1311 return true; |
1312 } | 1312 } |
1313 | 1313 |
1314 void MidiManagerAlsa::DeleteAlsaOutputPort(uint32 port_index) { | 1314 void MidiManagerAlsa::DeleteAlsaOutputPort(uint32_t port_index) { |
1315 base::AutoLock lock(out_ports_lock_); | 1315 base::AutoLock lock(out_ports_lock_); |
1316 auto it = out_ports_.find(port_index); | 1316 auto it = out_ports_.find(port_index); |
1317 if (it == out_ports_.end()) | 1317 if (it == out_ports_.end()) |
1318 return; | 1318 return; |
1319 | 1319 |
1320 int alsa_port = it->second; | 1320 int alsa_port = it->second; |
1321 snd_seq_delete_simple_port(out_client_.get(), alsa_port); | 1321 snd_seq_delete_simple_port(out_client_.get(), alsa_port); |
1322 out_ports_.erase(it); | 1322 out_ports_.erase(it); |
1323 } | 1323 } |
1324 | 1324 |
1325 bool MidiManagerAlsa::Subscribe(uint32 port_index, int client_id, int port_id) { | 1325 bool MidiManagerAlsa::Subscribe(uint32_t port_index, |
| 1326 int client_id, |
| 1327 int port_id) { |
1326 // Activate port subscription. | 1328 // Activate port subscription. |
1327 snd_seq_port_subscribe_t* subs; | 1329 snd_seq_port_subscribe_t* subs; |
1328 snd_seq_port_subscribe_alloca(&subs); | 1330 snd_seq_port_subscribe_alloca(&subs); |
1329 snd_seq_addr_t sender; | 1331 snd_seq_addr_t sender; |
1330 sender.client = client_id; | 1332 sender.client = client_id; |
1331 sender.port = port_id; | 1333 sender.port = port_id; |
1332 snd_seq_port_subscribe_set_sender(subs, &sender); | 1334 snd_seq_port_subscribe_set_sender(subs, &sender); |
1333 snd_seq_addr_t dest; | 1335 snd_seq_addr_t dest; |
1334 dest.client = in_client_id_; | 1336 dest.client = in_client_id_; |
1335 dest.port = in_port_id_; | 1337 dest.port = in_port_id_; |
1336 snd_seq_port_subscribe_set_dest(subs, &dest); | 1338 snd_seq_port_subscribe_set_dest(subs, &dest); |
1337 int err = snd_seq_subscribe_port(in_client_.get(), subs); | 1339 int err = snd_seq_subscribe_port(in_client_.get(), subs); |
1338 if (err != 0) { | 1340 if (err != 0) { |
1339 VLOG(1) << "snd_seq_subscribe_port fails: " << snd_strerror(err); | 1341 VLOG(1) << "snd_seq_subscribe_port fails: " << snd_strerror(err); |
1340 return false; | 1342 return false; |
1341 } | 1343 } |
1342 | 1344 |
1343 // Update our map. | 1345 // Update our map. |
1344 source_map_[AddrToInt(client_id, port_id)] = port_index; | 1346 source_map_[AddrToInt(client_id, port_id)] = port_index; |
1345 return true; | 1347 return true; |
1346 } | 1348 } |
1347 | 1349 |
1348 MidiManager* MidiManager::Create() { | 1350 MidiManager* MidiManager::Create() { |
1349 return new MidiManagerAlsa(); | 1351 return new MidiManagerAlsa(); |
1350 } | 1352 } |
1351 | 1353 |
1352 } // namespace midi | 1354 } // namespace midi |
1353 } // namespace media | 1355 } // namespace media |
OLD | NEW |