diff options
author | toyoshim <toyoshim@chromium.org> | 2015-02-18 23:28:09 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-02-19 07:28:38 +0000 |
commit | 40405201282bde7546763d2402d31104cc991ba0 (patch) | |
tree | ab8b4ee7689d688974ce19d7f647a276d29bc9a9 | |
parent | f3a85349d2da16aa306f1fdc43ea3b5d21a9f956 (diff) | |
download | chromium_src-40405201282bde7546763d2402d31104cc991ba0.zip chromium_src-40405201282bde7546763d2402d31104cc991ba0.tar.gz chromium_src-40405201282bde7546763d2402d31104cc991ba0.tar.bz2 |
Web MIDI: make MidiManagerMac notify device connection status
To handle device connection status, MidiManager and MidiMessageFilter
hold all devices as a list. These lists are modified by event
notifications that are delivered asynchronously.
They do not remove disconnected devices, but just mark as disconnected.
This is useful when JavaScript has a reference to a device
that got disconnected. The reference can be availalbe if the device
gets connected again.
BUG=422333
TEST=media_unittests
Review URL: https://codereview.chromium.org/662233002
Cr-Commit-Position: refs/heads/master@{#317000}
-rw-r--r-- | content/browser/media/midi_host.cc | 8 | ||||
-rw-r--r-- | content/browser/media/midi_host.h | 3 | ||||
-rw-r--r-- | content/common/media/midi_messages.h | 12 | ||||
-rw-r--r-- | content/renderer/media/midi_message_filter.cc | 34 | ||||
-rw-r--r-- | content/renderer/media/midi_message_filter.h | 8 | ||||
-rw-r--r-- | media/midi/midi_manager.cc | 16 | ||||
-rw-r--r-- | media/midi/midi_manager.h | 10 | ||||
-rw-r--r-- | media/midi/midi_manager_alsa.cc | 6 | ||||
-rw-r--r-- | media/midi/midi_manager_mac.cc | 65 | ||||
-rw-r--r-- | media/midi/midi_manager_mac.h | 19 | ||||
-rw-r--r-- | media/midi/midi_manager_unittest.cc | 2 | ||||
-rw-r--r-- | media/midi/midi_manager_usb.cc | 2 | ||||
-rw-r--r-- | media/midi/midi_manager_usb_unittest.cc | 4 | ||||
-rw-r--r-- | media/midi/midi_manager_win.cc | 6 | ||||
-rw-r--r-- | media/midi/midi_port_info.cc | 9 | ||||
-rw-r--r-- | media/midi/midi_port_info.h | 11 |
16 files changed, 192 insertions, 23 deletions
diff --git a/content/browser/media/midi_host.cc b/content/browser/media/midi_host.cc index 37e5411..b8fcdd0 100644 --- a/content/browser/media/midi_host.cc +++ b/content/browser/media/midi_host.cc @@ -145,6 +145,14 @@ void MidiHost::AddOutputPort(const media::MidiPortInfo& info) { Send(new MidiMsg_AddOutputPort(info)); } +void MidiHost::SetInputPortState(uint32 port, media::MidiPortState state) { + Send(new MidiMsg_SetInputPortState(port, state)); +} + +void MidiHost::SetOutputPortState(uint32 port, media::MidiPortState state) { + Send(new MidiMsg_SetOutputPortState(port, state)); +} + void MidiHost::ReceiveMidiData( uint32 port, const uint8* data, diff --git a/content/browser/media/midi_host.h b/content/browser/media/midi_host.h index 3a469bf..9d9c01f 100644 --- a/content/browser/media/midi_host.h +++ b/content/browser/media/midi_host.h @@ -16,6 +16,7 @@ #include "content/public/browser/browser_message_filter.h" #include "content/public/browser/browser_thread.h" #include "media/midi/midi_manager.h" +#include "media/midi/midi_port_info.h" namespace media { class MidiManager; @@ -39,6 +40,8 @@ class CONTENT_EXPORT MidiHost void CompleteStartSession(media::MidiResult result) override; void AddInputPort(const media::MidiPortInfo& info) override; void AddOutputPort(const media::MidiPortInfo& info) override; + void SetInputPortState(uint32 port, media::MidiPortState state) override; + void SetOutputPortState(uint32 port, media::MidiPortState state) override; void ReceiveMidiData(uint32 port, const uint8* data, size_t length, diff --git a/content/common/media/midi_messages.h b/content/common/media/midi_messages.h index 6f314b6..6147c8a 100644 --- a/content/common/media/midi_messages.h +++ b/content/common/media/midi_messages.h @@ -17,11 +17,15 @@ #define IPC_MESSAGE_EXPORT CONTENT_EXPORT #define IPC_MESSAGE_START MidiMsgStart +IPC_ENUM_TRAITS_MAX_VALUE(media::MidiPortState, + media::MIDI_PORT_STATE_LAST) + IPC_STRUCT_TRAITS_BEGIN(media::MidiPortInfo) IPC_STRUCT_TRAITS_MEMBER(id) IPC_STRUCT_TRAITS_MEMBER(manufacturer) IPC_STRUCT_TRAITS_MEMBER(name) IPC_STRUCT_TRAITS_MEMBER(version) + IPC_STRUCT_TRAITS_MEMBER(state) IPC_STRUCT_TRAITS_END() IPC_ENUM_TRAITS_MAX_VALUE(media::MidiResult, media::MIDI_RESULT_LAST) @@ -46,6 +50,14 @@ IPC_MESSAGE_CONTROL1(MidiMsg_AddInputPort, IPC_MESSAGE_CONTROL1(MidiMsg_AddOutputPort, media::MidiPortInfo /* output port */) +IPC_MESSAGE_CONTROL2(MidiMsg_SetInputPortState, + uint32 /* port */, + media::MidiPortState /* state */) + +IPC_MESSAGE_CONTROL2(MidiMsg_SetOutputPortState, + uint32 /* port */, + media::MidiPortState /* state */) + IPC_MESSAGE_CONTROL1(MidiMsg_SessionStarted, media::MidiResult /* result */) diff --git a/content/renderer/media/midi_message_filter.cc b/content/renderer/media/midi_message_filter.cc index 03a9d00..258d04d 100644 --- a/content/renderer/media/midi_message_filter.cc +++ b/content/renderer/media/midi_message_filter.cc @@ -116,6 +116,8 @@ bool MidiMessageFilter::OnMessageReceived(const IPC::Message& message) { IPC_MESSAGE_HANDLER(MidiMsg_SessionStarted, OnSessionStarted) IPC_MESSAGE_HANDLER(MidiMsg_AddInputPort, OnAddInputPort) IPC_MESSAGE_HANDLER(MidiMsg_AddOutputPort, OnAddOutputPort) + IPC_MESSAGE_HANDLER(MidiMsg_SetInputPortState, OnSetInputPortState) + IPC_MESSAGE_HANDLER(MidiMsg_SetOutputPortState, OnSetOutputPortState) IPC_MESSAGE_HANDLER(MidiMsg_DataReceived, OnDataReceived) IPC_MESSAGE_HANDLER(MidiMsg_AcknowledgeSentData, OnAcknowledgeSentData) IPC_MESSAGE_UNHANDLED(handled = false) @@ -163,6 +165,24 @@ void MidiMessageFilter::OnAddOutputPort(media::MidiPortInfo info) { base::Bind(&MidiMessageFilter::HandleAddOutputPort, this, info)); } +void MidiMessageFilter::OnSetInputPortState(uint32 port, + media::MidiPortState state) { + DCHECK(io_message_loop_->BelongsToCurrentThread()); + main_message_loop_->PostTask( + FROM_HERE, + base::Bind(&MidiMessageFilter::HandleSetInputPortState, + this, port, state)); +} + +void MidiMessageFilter::OnSetOutputPortState(uint32 port, + media::MidiPortState state) { + DCHECK(io_message_loop_->BelongsToCurrentThread()); + main_message_loop_->PostTask( + FROM_HERE, + base::Bind(&MidiMessageFilter::HandleSetOutputPortState, + this, port, state)); +} + void MidiMessageFilter::OnDataReceived(uint32 port, const std::vector<uint8>& data, double timestamp) { @@ -265,4 +285,18 @@ void MidiMessageFilter::HandleAckknowledgeSentData(size_t bytes_sent) { unacknowledged_bytes_sent_ -= bytes_sent; } +void MidiMessageFilter::HandleSetInputPortState(uint32 port, + media::MidiPortState state) { + DCHECK(main_message_loop_->BelongsToCurrentThread()); + inputs_[port].state = state; + // TODO(toyoshim): Notify to all clients. +} + +void MidiMessageFilter::HandleSetOutputPortState(uint32 port, + media::MidiPortState state) { + DCHECK(main_message_loop_->BelongsToCurrentThread()); + outputs_[port].state = state; + // TODO(toyoshim): Notify to all clients. +} + } // namespace content diff --git a/content/renderer/media/midi_message_filter.h b/content/renderer/media/midi_message_filter.h index f7e1a84..83e760a 100644 --- a/content/renderer/media/midi_message_filter.h +++ b/content/renderer/media/midi_message_filter.h @@ -77,6 +77,12 @@ class CONTENT_EXPORT MidiMessageFilter : public IPC::MessageFilter { void OnAddInputPort(media::MidiPortInfo info); void OnAddOutputPort(media::MidiPortInfo info); + // These functions are called to notify the recipient that a device that is + // notified via OnAddInputPort() or OnAddOutputPort() gets disconnected, or + // connected again. + void OnSetInputPortState(uint32 port, media::MidiPortState state); + void OnSetOutputPortState(uint32 port, media::MidiPortState state); + // Called when the browser process has sent MIDI data containing one or // more messages. void OnDataReceived(uint32 port, @@ -93,6 +99,8 @@ class CONTENT_EXPORT MidiMessageFilter : public IPC::MessageFilter { void HandleAddInputPort(media::MidiPortInfo info); void HandleAddOutputPort(media::MidiPortInfo info); + void HandleSetInputPortState(uint32 port, media::MidiPortState state); + void HandleSetOutputPortState(uint32 port, media::MidiPortState state); void HandleDataReceived(uint32 port, const std::vector<uint8>& data, diff --git a/media/midi/midi_manager.cc b/media/midi/midi_manager.cc index 9e1f1e2..f7de36f 100644 --- a/media/midi/midi_manager.cc +++ b/media/midi/midi_manager.cc @@ -130,6 +130,22 @@ void MidiManager::AddOutputPort(const MidiPortInfo& info) { client->AddOutputPort(info); } +void MidiManager::SetInputPortState(uint32 port_index, MidiPortState state) { + base::AutoLock auto_lock(lock_); + DCHECK_LT(port_index, input_ports_.size()); + input_ports_[port_index].state = state; + for (auto client : clients_) + client->SetInputPortState(port_index, state); +} + +void MidiManager::SetOutputPortState(uint32 port_index, MidiPortState state) { + base::AutoLock auto_lock(lock_); + DCHECK_LT(port_index, output_ports_.size()); + output_ports_[port_index].state = state; + for (auto client : clients_) + client->SetOutputPortState(port_index, state); +} + void MidiManager::ReceiveMidiData( uint32 port_index, const uint8* data, diff --git a/media/midi/midi_manager.h b/media/midi/midi_manager.h index d7e7e47..a7c5262 100644 --- a/media/midi/midi_manager.h +++ b/media/midi/midi_manager.h @@ -35,10 +35,10 @@ class MEDIA_EXPORT MidiManagerClient { virtual void AddInputPort(const MidiPortInfo& info) = 0; virtual void AddOutputPort(const MidiPortInfo& info) = 0; - // TODO(toyoshim): DisableInputPort(const MidiPortInfo& info) and - // DisableOutputPort(const MidiPortInfo& info) should be added. - // On DisableInputPort(), internal states, e.g. received_messages_queues in - // MidiHost, should be reset. + // SetInputPortState() and SetOutputPortState() are called to notify a known + // device gets disconnected, or connected again. + virtual void SetInputPortState(uint32 port_index, MidiPortState state) = 0; + virtual void SetOutputPortState(uint32 port_index, MidiPortState state) = 0; // CompleteStartSession() is called when platform dependent preparation is // finished. @@ -122,6 +122,8 @@ class MEDIA_EXPORT MidiManager { void AddInputPort(const MidiPortInfo& info); void AddOutputPort(const MidiPortInfo& info); + void SetInputPortState(uint32 port_index, MidiPortState state); + void SetOutputPortState(uint32 port_index, MidiPortState state); // Dispatches to all clients. // TODO(toyoshim): Fix the mac implementation to use diff --git a/media/midi/midi_manager_alsa.cc b/media/midi/midi_manager_alsa.cc index e4cadfb..9043f1f 100644 --- a/media/midi/midi_manager_alsa.cc +++ b/media/midi/midi_manager_alsa.cc @@ -252,7 +252,8 @@ void MidiManagerAlsa::StartInitialization() { VLOG(1) << "snd_seq_subscribe_port fails: " << snd_strerror(err); } else { source_map_[AddrToInt(sender)] = current_input++; - AddInputPort(MidiPortInfo(id, manufacturer, name, version)); + AddInputPort(MidiPortInfo( + id, manufacturer, name, version, MIDI_PORT_OPENED)); } } if ((caps & kRequiredOutputPortCaps) == kRequiredOutputPortCaps) { @@ -286,7 +287,8 @@ void MidiManagerAlsa::StartInitialization() { snd_midi_event_new(kSendBufferSize, &encoder); encoders_.push_back(encoder); out_ports_.push_back(out_port); - AddOutputPort(MidiPortInfo(id, manufacturer, name, version)); + AddOutputPort(MidiPortInfo( + id, manufacturer, name, version, MIDI_PORT_OPENED)); } } } diff --git a/media/midi/midi_manager_mac.cc b/media/midi/midi_manager_mac.cc index e9d56fb..8a9e0607 100644 --- a/media/midi/midi_manager_mac.cc +++ b/media/midi/midi_manager_mac.cc @@ -4,6 +4,7 @@ #include "media/midi/midi_manager_mac.h" +#include <algorithm> #include <string> #include "base/bind.h" @@ -25,8 +26,7 @@ namespace media { namespace { -MidiPortInfo GetPortInfoFromEndpoint( - MIDIEndpointRef endpoint) { +MidiPortInfo GetPortInfoFromEndpoint(MIDIEndpointRef endpoint) { SInt32 id_number = 0; MIDIObjectGetIntegerProperty(endpoint, kMIDIPropertyUniqueID, &id_number); string id = IntToString(id_number); @@ -65,7 +65,8 @@ MidiPortInfo GetPortInfoFromEndpoint( << result; } - return MidiPortInfo(id, manufacturer, name, version); + const MidiPortState state = MIDI_PORT_OPENED; + return MidiPortInfo(id, manufacturer, name, version, state); } double MIDITimeStampToSeconds(MIDITimeStamp timestamp) { @@ -140,7 +141,8 @@ void MidiManagerMac::InitializeCoreMIDI() { // TODO(toyoshim): Set MIDINotifyProc to receive CoreMIDI event notifications. midi_client_ = 0; OSStatus result = - MIDIClientCreate(CFSTR("Chrome"), NULL, NULL, &midi_client_); + MIDIClientCreate(CFSTR("Chrome"), ReceiveMidiNotifyDispatch, this, + &midi_client_); if (result != noErr) return CompleteInitialization(MIDI_INITIALIZATION_ERROR); @@ -200,6 +202,61 @@ void MidiManagerMac::InitializeCoreMIDI() { } // static +void MidiManagerMac::ReceiveMidiNotifyDispatch(const MIDINotification* message, + void* refcon) { + MidiManagerMac* manager = static_cast<MidiManagerMac*>(refcon); + manager->ReceiveMidiNotify(message); +} + +void MidiManagerMac::ReceiveMidiNotify(const MIDINotification* message) { + DCHECK(client_thread_.message_loop_proxy()->BelongsToCurrentThread()); + + if (kMIDIMsgObjectAdded == message->messageID) { + const MIDIObjectAddRemoveNotification* notification = + reinterpret_cast<const MIDIObjectAddRemoveNotification*>(message); + MIDIEndpointRef endpoint = + static_cast<MIDIEndpointRef>(notification->child); + if (notification->childType == kMIDIObjectType_Source) { + SourceMap::iterator it = source_map_.find(endpoint); + if (it == source_map_.end()) { + uint32 index = source_map_.size(); + source_map_[endpoint] = index; + MidiPortInfo info = GetPortInfoFromEndpoint(endpoint); + AddInputPort(info); + } else { + uint32 index = it->second; + SetInputPortState(index, MIDI_PORT_OPENED); + } + } else if (notification->childType == kMIDIObjectType_Destination) { + auto i = std::find(destinations_.begin(), destinations_.end(), endpoint); + if (i != destinations_.end()) { + SetOutputPortState(i - destinations_.begin(), MIDI_PORT_OPENED); + } else { + destinations_.push_back(endpoint); + MidiPortInfo info = GetPortInfoFromEndpoint(endpoint); + AddOutputPort(info); + } + } + } else if (kMIDIMsgObjectRemoved == message->messageID) { + const MIDIObjectAddRemoveNotification* notification = + reinterpret_cast<const MIDIObjectAddRemoveNotification*>(message); + MIDIEndpointRef endpoint = + static_cast<MIDIEndpointRef>(notification->child); + if (notification->childType == kMIDIObjectType_Source) { + SourceMap::iterator it = source_map_.find(endpoint); + if (it != source_map_.end()) { + uint32 index = it->second; + SetInputPortState(index, MIDI_PORT_DISCONNECTED); + } + } else if (notification->childType == kMIDIObjectType_Destination) { + auto i = std::find(destinations_.begin(), destinations_.end(), endpoint); + if (i != destinations_.end()) + SetOutputPortState(i - destinations_.begin(), MIDI_PORT_DISCONNECTED); + } + } +} + +// static void MidiManagerMac::ReadMidiDispatch(const MIDIPacketList* packet_list, void* read_proc_refcon, void* src_conn_refcon) { diff --git a/media/midi/midi_manager_mac.h b/media/midi/midi_manager_mac.h index f7179ec..e8e4474 100644 --- a/media/midi/midi_manager_mac.h +++ b/media/midi/midi_manager_mac.h @@ -42,13 +42,18 @@ class MEDIA_EXPORT MidiManagerMac : public MidiManager { // StartInitialization(). void InitializeCoreMIDI(); + // CoreMIDI callback for MIDI notification. + // Receives MIDI related event notifications from CoreMIDI. + static void ReceiveMidiNotifyDispatch(const MIDINotification* message, + void* refcon); + void ReceiveMidiNotify(const MIDINotification* message); + // CoreMIDI callback for MIDI data. // Each callback can contain multiple packets, each of which can contain // multiple MIDI messages. - static void ReadMidiDispatch( - const MIDIPacketList *pktlist, - void *read_proc_refcon, - void *src_conn_refcon); + static void ReadMidiDispatch(const MIDIPacketList* packet_list, + void* read_proc_refcon, + void* src_conn_refcon); virtual void ReadMidi(MIDIEndpointRef source, const MIDIPacketList *pktlist); // An internal callback that runs on MidiSendThread. @@ -67,13 +72,13 @@ class MEDIA_EXPORT MidiManagerMac : public MidiManager { MIDIPacketList* packet_list_; MIDIPacket* midi_packet_; - typedef std::map<MIDIEndpointRef, uint32> SourceMap; - // Keeps track of the index (0-based) for each of our sources. + typedef std::map<MIDIEndpointRef, uint32> SourceMap; SourceMap source_map_; // Keeps track of all destinations. - std::vector<MIDIEndpointRef> destinations_; + typedef std::vector<MIDIEndpointRef> DestinationVector; + DestinationVector destinations_; // |client_thread_| is used to handle platform dependent operations. base::Thread client_thread_; diff --git a/media/midi/midi_manager_unittest.cc b/media/midi/midi_manager_unittest.cc index 40d9152..680f9db 100644 --- a/media/midi/midi_manager_unittest.cc +++ b/media/midi/midi_manager_unittest.cc @@ -62,6 +62,8 @@ class FakeMidiManagerClient : public MidiManagerClient { // MidiManagerClient implementation. void AddInputPort(const MidiPortInfo& info) override {} void AddOutputPort(const MidiPortInfo& info) override {} + void SetInputPortState(uint32 port_index, MidiPortState state) override {} + void SetOutputPortState(uint32 port_index, MidiPortState state) override {} void CompleteStartSession(MidiResult result) override { EXPECT_TRUE(wait_for_result_); diff --git a/media/midi/midi_manager_usb.cc b/media/midi/midi_manager_usb.cc index 63c241b..67953e4 100644 --- a/media/midi/midi_manager_usb.cc +++ b/media/midi/midi_manager_usb.cc @@ -106,6 +106,7 @@ void MidiManagerUsb::OnEnumerateDevicesDone(bool result, // setting is sufficiently unique although there is no user-friendly // meaning. MidiPortInfo port; + port.state = MIDI_PORT_OPENED; port.id = base::StringPrintf("port-%ld-%ld", static_cast<long>(i), static_cast<long>(j)); @@ -115,6 +116,7 @@ void MidiManagerUsb::OnEnumerateDevicesDone(bool result, input_jacks.push_back(jacks[j]); // TODO(yhirano): Set appropriate properties. MidiPortInfo port; + port.state = MIDI_PORT_OPENED; port.id = base::StringPrintf("port-%ld-%ld", static_cast<long>(i), static_cast<long>(j)); diff --git a/media/midi/midi_manager_usb_unittest.cc b/media/midi/midi_manager_usb_unittest.cc index 8552403..d59f857 100644 --- a/media/midi/midi_manager_usb_unittest.cc +++ b/media/midi/midi_manager_usb_unittest.cc @@ -86,6 +86,10 @@ class FakeMidiManagerClient : public MidiManagerClient { output_ports_.push_back(info); } + void SetInputPortState(uint32 port_index, MidiPortState state) override {} + + void SetOutputPortState(uint32 port_index, MidiPortState state) override {} + void CompleteStartSession(MidiResult result) override { complete_start_session_ = true; result_ = result; diff --git a/media/midi/midi_manager_win.cc b/media/midi/midi_manager_win.cc index bc4b15d..26657d6 100644 --- a/media/midi/midi_manager_win.cc +++ b/media/midi/midi_manager_win.cc @@ -515,7 +515,8 @@ void MidiManagerWin::StartInitialization() { base::IntToString(static_cast<int>(device_id)), "", base::WideToUTF8(caps.szPname), - base::IntToString(static_cast<int>(caps.vDriverVersion))); + base::IntToString(static_cast<int>(caps.vDriverVersion)), + MIDI_PORT_OPENED); AddInputPort(info); in_device->set_port_index(inport_index++); in_devices_.push_back(in_device.release()); @@ -538,7 +539,8 @@ void MidiManagerWin::StartInitialization() { base::IntToString(static_cast<int>(device_id)), "", base::WideToUTF8(caps.szPname), - base::IntToString(static_cast<int>(caps.vDriverVersion))); + base::IntToString(static_cast<int>(caps.vDriverVersion)), + MIDI_PORT_OPENED); AddOutputPort(info); out_devices_.push_back(out_port.release()); } diff --git a/media/midi/midi_port_info.cc b/media/midi/midi_port_info.cc index 02b4aa9..020394e 100644 --- a/media/midi/midi_port_info.cc +++ b/media/midi/midi_port_info.cc @@ -11,11 +11,13 @@ MidiPortInfo::MidiPortInfo() {} MidiPortInfo::MidiPortInfo(const std::string& in_id, const std::string& in_manufacturer, const std::string& in_name, - const std::string& in_version) + const std::string& in_version, + MidiPortState in_state) : id(in_id), manufacturer(in_manufacturer), name(in_name), - version(in_version) {} + version(in_version), + state(in_state) {} MidiPortInfo::~MidiPortInfo() {} @@ -23,6 +25,7 @@ MidiPortInfo::MidiPortInfo(const MidiPortInfo& info) : id(info.id), manufacturer(info.manufacturer), name(info.name), - version(info.version) {} + version(info.version), + state(info.state) {} } // namespace media diff --git a/media/midi/midi_port_info.h b/media/midi/midi_port_info.h index 1fe3bca..32b94b4 100644 --- a/media/midi/midi_port_info.h +++ b/media/midi/midi_port_info.h @@ -13,12 +13,20 @@ namespace media { +enum MidiPortState { + MIDI_PORT_DISCONNECTED, + MIDI_PORT_CONNECTED, + MIDI_PORT_OPENED, + MIDI_PORT_STATE_LAST = MIDI_PORT_OPENED, +}; + struct MEDIA_EXPORT MidiPortInfo { MidiPortInfo(); MidiPortInfo(const std::string& in_id, const std::string& in_manufacturer, const std::string& in_name, - const std::string& in_version); + const std::string& in_version, + MidiPortState in_state); MidiPortInfo(const MidiPortInfo& info); ~MidiPortInfo(); @@ -27,6 +35,7 @@ struct MEDIA_EXPORT MidiPortInfo { std::string manufacturer; std::string name; std::string version; + MidiPortState state; }; typedef std::vector<MidiPortInfo> MidiPortInfoList; |