| Index: media/midi/midi_manager_winrt.cc
|
| diff --git a/media/midi/midi_manager_winrt.cc b/media/midi/midi_manager_winrt.cc
|
| index a5141a6ce4d00681f98c1479ff5c25480f69b860..22cdcd0f6c4c2dc3249015bfe32e8768e4247c4c 100644
|
| --- a/media/midi/midi_manager_winrt.cc
|
| +++ b/media/midi/midi_manager_winrt.cc
|
| @@ -18,6 +18,7 @@ struct __declspec(uuid("905a0fef-bc53-11df-8c49-001e4fc686da"))
|
|
|
| #include <comdef.h>
|
| #include <robuffer.h>
|
| +#include <setupapi.h>
|
| #include <windows.devices.enumeration.h>
|
| #include <windows.devices.midi.h>
|
| #include <wrl/event.h>
|
| @@ -29,6 +30,7 @@ struct __declspec(uuid("905a0fef-bc53-11df-8c49-001e4fc686da"))
|
| #include "base/bind.h"
|
| #include "base/lazy_instance.h"
|
| #include "base/scoped_generic.h"
|
| +#include "base/strings/string_util.h"
|
| #include "base/strings/utf_string_conversions.h"
|
| #include "base/threading/thread_checker.h"
|
| #include "base/threading/thread_task_runner_handle.h"
|
| @@ -261,6 +263,84 @@ bool IsMicrosoftSynthesizer(IDeviceInformation* info) {
|
| return result != FALSE;
|
| }
|
|
|
| +class ScopedDeviceInfoListTraits {
|
| + public:
|
| + static HDEVINFO InvalidValue() { return INVALID_HANDLE_VALUE; }
|
| +
|
| + static void Free(HDEVINFO devinfo_set) {
|
| + SetupDiDestroyDeviceInfoList(devinfo_set);
|
| + }
|
| +};
|
| +
|
| +using ScopedDeviceInfoList =
|
| + base::ScopedGeneric<HDEVINFO, ScopedDeviceInfoListTraits>;
|
| +
|
| +// Retrieves manufacturer (provider) and version information of underlying
|
| +// device driver using Setup API, given device (interface) ID provided by WinRT.
|
| +// |out_manufacturer| and |out_driver_version| won't be modified if retrieval
|
| +// fails. Note that SetupDiBuildDriverInfoList() would block for a few hundred
|
| +// milliseconds so consider calling this function in an asynchronous manner.
|
| +//
|
| +// Device instance ID is extracted from device (interface) ID provided by WinRT
|
| +// APIs, for example from the following interface ID:
|
| +// \\?\SWD#MMDEVAPI#MIDII_60F39FCA.P_0002#{504be32c-ccf6-4d2c-b73f-6f8b3747e22b}
|
| +// we extract the device instance ID: SWD\MMDEVAPI\MIDII_60F39FCA.P_0002
|
| +void GetDriverInfoFromDeviceId(const std::string& dev_id,
|
| + std::string* out_manufacturer,
|
| + std::string* out_driver_version) {
|
| + base::string16 dev_instance_id =
|
| + base::UTF8ToWide(dev_id.substr(4, dev_id.size() - 43));
|
| + base::ReplaceChars(dev_instance_id, L"#", L"\\", &dev_instance_id);
|
| +
|
| + ScopedDeviceInfoList devinfo_list(
|
| + SetupDiCreateDeviceInfoList(nullptr, nullptr));
|
| + if (!devinfo_list.is_valid()) {
|
| + VLOG(1) << "SetupDiCreateDeviceInfoList failed: "
|
| + << PrintHr(HRESULT_FROM_WIN32(GetLastError()));
|
| + return;
|
| + }
|
| +
|
| + SP_DEVINFO_DATA devinfo_data = {0};
|
| + devinfo_data.cbSize = sizeof(SP_DEVINFO_DATA);
|
| + SP_DRVINFO_DATA drvinfo_data = {0};
|
| + drvinfo_data.cbSize = sizeof(SP_DRVINFO_DATA);
|
| +
|
| + if (!SetupDiOpenDeviceInfo(devinfo_list.get(), dev_instance_id.c_str(),
|
| + nullptr, 0, &devinfo_data)) {
|
| + VLOG(1) << "SetupDiOpenDeviceInfo failed: "
|
| + << PrintHr(HRESULT_FROM_WIN32(GetLastError()));
|
| + return;
|
| + }
|
| +
|
| + if (!SetupDiBuildDriverInfoList(devinfo_list.get(), &devinfo_data,
|
| + SPDIT_COMPATDRIVER)) {
|
| + VLOG(1) << "SetupDiBuildDriverInfoList failed: "
|
| + << PrintHr(HRESULT_FROM_WIN32(GetLastError()));
|
| + return;
|
| + }
|
| +
|
| + // Assume only one entry in driver info list.
|
| + if (SetupDiEnumDriverInfo(devinfo_list.get(), &devinfo_data,
|
| + SPDIT_COMPATDRIVER, 0, &drvinfo_data)) {
|
| + *out_manufacturer = base::WideToUTF8(drvinfo_data.ProviderName);
|
| +
|
| + std::stringstream ss;
|
| + ss << (drvinfo_data.DriverVersion >> 48) << "."
|
| + << (drvinfo_data.DriverVersion >> 32 & 0xffff) << "."
|
| + << (drvinfo_data.DriverVersion >> 16 & 0xffff) << "."
|
| + << (drvinfo_data.DriverVersion & 0xffff);
|
| + *out_driver_version = ss.str();
|
| + } else {
|
| + VLOG(1) << "SetupDiEnumDriverInfo failed: "
|
| + << PrintHr(HRESULT_FROM_WIN32(GetLastError()));
|
| + }
|
| +
|
| + if (!SetupDiDestroyDriverInfoList(devinfo_list.get(), &devinfo_data,
|
| + SPDIT_COMPATDRIVER))
|
| + VLOG(1) << "SetupDiDestroyDriverInfoList failed: "
|
| + << PrintHr(HRESULT_FROM_WIN32(GetLastError()));
|
| +}
|
| +
|
| // Tokens with value = 0 are considered invalid (as in <wrl/event.h>).
|
| const int64_t kInvalidTokenValue = 0;
|
|
|
| @@ -594,10 +674,11 @@ class MidiManagerWinrt::MidiPortManager {
|
| MidiPort<InterfaceType>* port = GetPortByDeviceId(dev_id);
|
|
|
| if (port == nullptr) {
|
| - // TODO(crbug.com/642604): Fill in manufacturer and driver version.
|
| - AddPort(MidiPortInfo(dev_id, std::string("Manufacturer"),
|
| - port_names_[dev_id], std::string("DriverVersion"),
|
| - MIDI_PORT_OPENED));
|
| + std::string manufacturer = "Unknown", driver_version = "Unknown";
|
| + GetDriverInfoFromDeviceId(dev_id, &manufacturer, &driver_version);
|
| +
|
| + AddPort(MidiPortInfo(dev_id, manufacturer, port_names_[dev_id],
|
| + driver_version, MIDI_PORT_OPENED));
|
|
|
| port = new MidiPort<InterfaceType>;
|
| port->index = static_cast<uint32_t>(port_ids_.size());
|
|
|