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? - ߊߚߤߘ
  • one
    Anyway, 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 1

You can use the MMDevice API added in Windows Vista. To do this, you must perform the following steps:

  1. Announce the event listener.
  2. Pass it to the RegisterEndpointNotificationCallback method of the audio device enumerator. Of course, this enumerator must first be created.
  3. 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