Actually..Is it really winapi? Or maybe something in the registry is changing, so compare, for example.
- Device Events . However, this only works in Vista and above. What is your OS version? - ߊߚߤߘ
- oneAnyway, now I will write a working example for this technology. - ߊߚߤߘ
- win 7, 8.1 and 10 Three home PCs But priority - 10 - Range
- one@Arhad solved the problem like this: const CLSID CLSID_MMDeviceEnumerator = __uuidof (MMDeviceEnumerator); const IID IID_IMMDeviceEnumerator = __uuidof (IMMDeviceEnumerator); Determined before calling CoCreateInstance But, having started, the program just goes on hold, not responding to connecting / disconnecting the headphones. I’ll also check on another system of course ... - Range
- one@Arhad I inform you: the connection of headphones is perfectly caught by another computer. Advise where you can still dig? PS: a computer where the connection is not caught - a laptop, and there is a combined connector. Maybe it plays a role - Range
|
1 answer
You can use the MMDevice API added in Windows Vista. To do this, you must perform the following steps:
- Announce the event listener.
- Pass it to the
RegisterEndpointNotificationCallbackmethod of the audio device enumerator. Of course, this enumerator must first be created. - Handle incoming events so that the listener’s methods will be invoked in a separate thread.
Pay attention: if earlier the subscription to events consisted in processing window messages, now, in the COM world, it is necessary to pass a pointer to an instance of the class-listener.
Here is a sample code that handles activation / deactivation, enable / disable events. Unfortunately, the Windows API does not provide the ability to distinguish between connection and activation, reporting only the readiness of the device.
#define WIN32_LEAN_AND_MEAN #include <windows.h> #include <initguid.h> #include <Mmdeviceapi.h> #include <Objbase.h> #include <cstdlib> #include <iostream> // Базовая реализация, выводящая в консоль уведомления о втыкании/вытаскивании джека. class JackStateNotificationClient : public IMMNotificationClient { public: virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppvObject); virtual ULONG STDMETHODCALLTYPE AddRef(); virtual ULONG STDMETHODCALLTYPE Release(); virtual HRESULT STDMETHODCALLTYPE OnDefaultDeviceChanged (EDataFlow flow, ERole role, LPCWSTR pwstrDefaultDevice); virtual HRESULT STDMETHODCALLTYPE OnDeviceAdded(LPCWSTR pwstrDeviceId); virtual HRESULT STDMETHODCALLTYPE OnDeviceRemoved(LPCWSTR pwstrDeviceId); virtual HRESULT STDMETHODCALLTYPE OnDeviceStateChanged (LPCWSTR pwstrDeviceId, DWORD dwNewState); virtual HRESULT STDMETHODCALLTYPE OnPropertyValueChanged (LPCWSTR pwstrDeviceId, const PROPERTYKEY key); }; HRESULT JackStateNotificationClient::OnDefaultDeviceChanged( EDataFlow flow, ERole role, LPCWSTR pwstrDefaultDevice ) { UNREFERENCED_PARAMETER(flow); UNREFERENCED_PARAMETER(role); UNREFERENCED_PARAMETER(pwstrDefaultDevice); // Смена устройства по умолчанию нам неинтересна return S_OK; } HRESULT JackStateNotificationClient::QueryInterface(REFIID riid, void** ppvObject) { // Наш объект не является полиморфным, это простой одноразовый перечислитель return ppvObject ? E_NOINTERFACE : E_POINTER; } ULONG JackStateNotificationClient::AddRef() { // Наш объект статичен, а потому не нуждается в COM-овском методе подсчёта ссылок return 1; } ULONG JackStateNotificationClient::Release() { // Наш объект статичен, а потому не нуждается в COM-овском методе подсчёта ссылок return 1; } HRESULT JackStateNotificationClient::OnDeviceAdded(LPCWSTR pwstrDeviceId) { // Устройство зарегистрировано std::wcout << pwstrDeviceId << L" was registered\n"; return S_OK; } HRESULT JackStateNotificationClient::OnDeviceRemoved(LPCWSTR pwstrDeviceId) { // Устройство разрегистрировано std::wcout << pwstrDeviceId <<L" was unregistered\n"; return S_OK; } HRESULT JackStateNotificationClient::OnDeviceStateChanged( LPCWSTR pwstrDeviceId, DWORD dwNewState ) { switch(dwNewState) { case DEVICE_STATE_ACTIVE: // Устройство активировано через панель управления, либо подключен джек std::wcout << pwstrDeviceId << L" was enabled or plugged\n"; break; case DEVICE_STATE_DISABLED: // Устройство деактивировано через панель управления std::wcout << pwstrDeviceId << L" was disabled\n"; break; case DEVICE_STATE_UNPLUGGED: std::wcout << pwstrDeviceId << L" was unplugged\n"; break; } return S_OK; } HRESULT JackStateNotificationClient::OnPropertyValueChanged( LPCWSTR pwstrDeviceId, const PROPERTYKEY key ) { UNREFERENCED_PARAMETER(pwstrDeviceId); //UNREFERENCED_PARAMETER(key); // Настройка устройства нас не интересует return S_OK; } int main() { ::CoInitialize(NULL); IMMDeviceEnumerator* enumerator; HRESULT result = ::CoCreateInstance( /* rclsid */ CLSID_MMDeviceEnumerator, /* pUnkOuter */ NULL, /* dwClsContext */ CLSCTX_ALL, /* riid */ IID_IMMDeviceEnumerator, /* ppv */ (void**)&enumerator ); if(result == S_OK) { JackStateNotificationClient listener; enumerator->RegisterEndpointNotificationCallback(&listener); // ========================= // События будут приходить в другом потоке, так что можем спокойно делать // свои дела. Например, разбирать оконные сообщения. Ну или просто ждать, // как в этом примере. const HANDLE hFreezingEvent = CreateEvent( /* lpEventAttributes */ NULL, /* bManualReset */ FALSE, /* bInitialState */ FALSE, /* lpName */ NULL ); ::WaitForSingleObject(hFreezingEvent, INFINITE); // ========================= enumerator->UnregisterEndpointNotificationCallback(&listener); enumerator->Release(); ::CoUninitialize(); return EXIT_SUCCESS; } else { std::wcout << (result == REGDB_E_CLASSNOTREG ? "You need Windows Vista or newer\n" : "Unknown error\n"); ::CoUninitialize(); return EXIT_FAILURE; } } - Thank you so much! In the evening I will understand and try. PS: and yet, how huge is the winapi library ... - Range
|