Обработка события измененного аудиоустройства в c#

#c# #.net #events #audio #device

#c# #.net #Мероприятия #Аудио #устройство

Вопрос:

Мне интересно, как обработать событие, когда я вставляю (или извлекаю) свои наушники или другое устройство вывода в разъем звуковой карты.

Поиск здесь и в Google дает мне информацию о библиотеке «naudio», но у нее очень плохая документация для изучения, а также один из координаторов этого проекта сказал мне, что он не уверен, что это вообще возможно в их библиотеке.

Моя конечная цель — автоматическое регулирование громкости для разных устройств, например, когда наушники активны — установите 10% громкости, а когда динамики активны — установите 100%.

Ответ №1:

Вы можете сделать это с помощью MMDeviceEnumerator от NAudio и IMMNotificationClient. Однако вы добавляете реализации для обратного вызова RegisterEndpointNotificationCallback и обратного вызова UnRegisterEndpointNotificationCallback в класс MMDeviceEnumerator

Реализации следующие

  /// <summary>
       /// Registers a call back for Device Events
       /// </summary>
        /// <param name="client">Object implementing IMMNotificationClient type casted as IMMNotificationClient interface</param>
       /// <returns></returns>
        public int RegisterEndpointNotificationCallback([In] [MarshalAs(UnmanagedType.Interface)] IMMNotificationClient client)
        {
            //DeviceEnum declared below
            return deviceEnum.RegisterEndpointNotificationCallback(client);
        }

        /// <summary>
        /// UnRegisters a call back for Device Events
        /// </summary>
        /// <param name="client">Object implementing IMMNotificationClient type casted as IMMNotificationClient interface </param>
        /// <returns></returns>
        public int UnRegisterEndpointNotificationCallback([In] [MarshalAs(UnmanagedType.Interface)] IMMNotificationClient client)
        {
            //DeviceEnum declared below
            return deviceEnum.UnregisterEndpointNotificationCallback(client);
        } 
  

Затем создайте класс, который реализует IMMNotificationClient

пример:

 class NotificationClientImplementation : NAudio.CoreAudioApi.Interfaces.IMMNotificationClient
    {

        public void OnDefaultDeviceChanged(DataFlow dataFlow, Role deviceRole, string defaultDeviceId)
        {
            //Do some Work
            Console.WriteLine("OnDefaultDeviceChanged --> {0}", dataFlow.ToString());
        }

        public void OnDeviceAdded(string deviceId)
        {
             //Do some Work
            Console.WriteLine("OnDeviceAdded -->");
        }

        public void OnDeviceRemoved(string deviceId)
        {

            Console.WriteLine("OnDeviceRemoved -->");
             //Do some Work
        }

        public void OnDeviceStateChanged(string deviceId, DeviceState newState)
        {
            Console.WriteLine("OnDeviceStateChangedn Device Id -->{0} : Device State {1}", deviceId, newState);
             //Do some Work
        }

        public NotificationClientImplementation()
        {
            //_realEnumerator.RegisterEndpointNotificationCallback();
            if (System.Environment.OSVersion.Version.Major < 6)
            {
                throw new NotSupportedException("This functionality is only supported on Windows Vista or newer.");
            }
        }

        public void OnPropertyValueChanged(string deviceId, PropertyKey propertyKey)
        {
             //Do some Work
             //fmtid amp; pid are changed to formatId and propertyId in the latest version NAudio
            Console.WriteLine("OnPropertyValueChanged: formatId --> {0}  propertyId --> {1}", propertyKey.formatId.ToString(), propertyKey.propertyId.ToString());
        }

    }
  

Затем все, что вам нужно сделать, это

  1. Объявите следующие объекты NAudio и вашу реализацию IMMNotificationClient

Пример:

 private NAudio.CoreAudioApi.MMDeviceEnumerator deviceEnum = new NAudio.CoreAudioApi.MMDeviceEnumerator();
private NotificationClientImplementation notificationClient;
private NAudio.CoreAudioApi.Interfaces.IMMNotificationClient notifyClient;
  
  1. Затем введите приведенное значение notificationClient как IMMNotificationClient и передайте его в качестве параметра в MMDeviceEnumerator

Пример:

 notificationClient = new NotificationClientImplementation();
notifyClient = (NAudio.CoreAudioApi.Interfaces.IMMNotificationClient)notificationClient;
deviceEnum.RegisterEndpointNotificationCallback(notifyClient);
  

Надеюсь, это поможет какому-нибудь органу. Спасибо форумам MSDN и, в частности, Майклу Тейлору
http://msmvps.com/blogs/p3net за помощь мне в этом.

Спасибо и приветствия.

Комментарии:

1. Большое вам спасибо за ответ! К сожалению, прошло 3 года с тех пор, как я задавал этот вопрос, и я давно прекратил исследовать эту тему. Но я надеюсь, что это поможет другим решить ту же проблему.

2. @Mohtashim Огромное вам спасибо! Я часами искал пример реализации! Я бы 100 раз поднял этот вопрос за подробный ответ с примерами!!

3. Я использую тот же способ, описанный здесь, я вижу только запуск события onProperyChange, когда я подключаю разъем для наушников, я ничего не вижу, когда я отключаю его, какая-либо причина для этого?

Ответ №2:

Чтобы вы могли определить, когда устройство подключено к системе, вам нужно будет реализовать IMMNotificationClient взаимодействие через COM. В принципе, вам нужно будет определить реализации следующих методов:

Обратите внимание, что из вышеперечисленных вас больше всего интересуют:

  • OnDefaultDeviceChanged
  • OnDeviceAdded
  • OnDeviceStateChanged

Однако вы должны знать, что базовое оборудование должно поддерживать эту функциональность, и что это доступно только в Windows Vista и Windows Server 2008.

Комментарии:

1. Хорошо, мне будет достаточно получить сообщение о том, что «что-то» подключено или отключено. Как это возможно? Я также попробовал другой способ — выполнить поиск этого события в Windows event Viewer, но у меня ничего не вышло — возможно, я искал не так хорошо, или, возможно, это событие просто не записывается там.

2. @xapon: К сожалению, я сказал, что «в лучшем случае» вы сможете получить эту информацию. Если вы это сделаете, это будет зависеть от звуковой карты или материнской платы (если разъем встроен); Я не уверен, что существует стандартное событие, предоставляемое уровнем аппаратной абстракции, на которое вы можете отреагировать.

3. Я думаю, что это можно решить на низком уровне; например, вот интерфейс Windows для отслеживания звуковых событий msdn.microsoft.com/en-us/library/dd371417 (v =против 85).aspx . Итак, если я углублюсь, я найду способ сделать это. Но я надеялся, что уже существует какая-то абстракция, такая как библиотека или класс, которая могла бы мне помочь. В любом случае спасибо за объяснение.

4. @xapon — Расширил мой ответ, в конечном счете, вы должны использовать COM interop для реализации этого устройства, а затем зарегистрировать свою реализацию.

Ответ №3:

Я был почти уверен, что подключение / отсоединение наушников или чего-либо еще в audiocard не генерирует никакого системного события вообще