События сеанса звука
Приложение, управляющее аудиопотоками в общем режиме, может регистрироваться для получения уведомлений при возникновении событий сеанса. Как описано ранее, каждый поток принадлежит звуковому сеансу. Событие сеанса инициируется изменением состояния звукового сеанса.
Клиентское приложение может зарегистрировать для получения уведомлений о следующих типах событий сеанса:
- Изменился уровень основного тома или состояние отключения подмиксов сеанса.
- Уровень тома одного или нескольких каналов подмиксов сеанса изменился.
- Сеанс отключен.
- Состояние действия сеанса изменилось на активное, неактивное или истекло.
- Сеанс был назначен новым параметром группировки.
- Изменено свойство пользовательского интерфейса сеанса (значок или отображаемое имя).
Клиент получает уведомления об этих событиях с помощью методов в реализации интерфейса IAudioSessionEvents. В отличие от других интерфейсов в WASAPI, реализованных системным модулем WASAPI, клиент реализует IAudioSessionEvents. Методы в этом интерфейсе получают обратные вызовы из системного модуля WASAPI при возникновении событий сеанса.
Чтобы начать получение уведомлений, клиент вызывает метод IAudioSessionControl::RegisterAudioSessionNotification для регистрации своего интерфейса IAudioSessionEvents. Если клиент больше не требует уведомлений, он вызывает метод IAudioSessionControl::UnregisterAudioSessionNotification для удаления регистрации.
В следующем примере кода показана возможная реализация интерфейса IAudioSessionEvents:
//-----------------------------------------------------------
// Client implementation of IAudioSessionEvents interface.
// WASAPI calls these methods to notify the application when
// a parameter or property of the audio session changes.
//-----------------------------------------------------------
class CAudioSessionEvents : public IAudioSessionEvents
{
LONG _cRef;
public:
CAudioSessionEvents() :
_cRef(1)
{
}
~CAudioSessionEvents()
{
}
// IUnknown methods -- AddRef, Release, and QueryInterface
ULONG STDMETHODCALLTYPE AddRef()
{
return InterlockedIncrement(&_cRef);
}
ULONG STDMETHODCALLTYPE Release()
{
ULONG ulRef = InterlockedDecrement(&_cRef);
if (0 == ulRef)
{
delete this;
}
return ulRef;
}
HRESULT STDMETHODCALLTYPE QueryInterface(
REFIID riid,
VOID **ppvInterface)
{
if (IID_IUnknown == riid)
{
AddRef();
*ppvInterface = (IUnknown*)this;
}
else if (__uuidof(IAudioSessionEvents) == riid)
{
AddRef();
*ppvInterface = (IAudioSessionEvents*)this;
}
else
{
*ppvInterface = NULL;
return E_NOINTERFACE;
}
return S_OK;
}
// Notification methods for audio session events
HRESULT STDMETHODCALLTYPE OnDisplayNameChanged(
LPCWSTR NewDisplayName,
LPCGUID EventContext)
{
return S_OK;
}
HRESULT STDMETHODCALLTYPE OnIconPathChanged(
LPCWSTR NewIconPath,
LPCGUID EventContext)
{
return S_OK;
}
HRESULT STDMETHODCALLTYPE OnSimpleVolumeChanged(
float NewVolume,
BOOL NewMute,
LPCGUID EventContext)
{
if (NewMute)
{
printf("MUTE\n");
}
else
{
printf("Volume = %d percent\n",
(UINT32)(100*NewVolume + 0.5));
}
return S_OK;
}
HRESULT STDMETHODCALLTYPE OnChannelVolumeChanged(
DWORD ChannelCount,
float NewChannelVolumeArray[],
DWORD ChangedChannel,
LPCGUID EventContext)
{
return S_OK;
}
HRESULT STDMETHODCALLTYPE OnGroupingParamChanged(
LPCGUID NewGroupingParam,
LPCGUID EventContext)
{
return S_OK;
}
HRESULT STDMETHODCALLTYPE OnStateChanged(
AudioSessionState NewState)
{
char *pszState = "?????";
switch (NewState)
{
case AudioSessionStateActive:
pszState = "active";
break;
case AudioSessionStateInactive:
pszState = "inactive";
break;
}
printf("New session state = %s\n", pszState);
return S_OK;
}
HRESULT STDMETHODCALLTYPE OnSessionDisconnected(
AudioSessionDisconnectReason DisconnectReason)
{
char *pszReason = "?????";
switch (DisconnectReason)
{
case DisconnectReasonDeviceRemoval:
pszReason = "device removed";
break;
case DisconnectReasonServerShutdown:
pszReason = "server shut down";
break;
case DisconnectReasonFormatChanged:
pszReason = "format changed";
break;
case DisconnectReasonSessionLogoff:
pszReason = "user logged off";
break;
case DisconnectReasonSessionDisconnected:
pszReason = "session disconnected";
break;
case DisconnectReasonExclusiveModeOverride:
pszReason = "exclusive-mode override";
break;
}
printf("Audio session disconnected (reason: %s)\n",
pszReason);
return S_OK;
}
};
Класс CAudioSessionEvents в предыдущем примере кода является реализацией интерфейса IAudioSessionEvents . Эта конкретная реализация может быть частью консольного приложения, которое выводит сведения о событиях сеанса в окно командной строки. Так как IAudioSessionEvents наследует от IUnknown, определение класса содержит реализации методов IUnknown AddRef, Release и QueryInterface. Остальные открытые методы в определении класса относятся к интерфейсу IAudioSessionEvents .
Некоторые клиенты могут не быть заинтересованы в мониторинге всех типов событий сеанса. В приведенном выше примере кода несколько методов уведомлений в классе CAudioSessionEvents ничего не делают. Например, метод OnChannelVolumeChanged ничего не делает, кроме возврата кода состояния S_OK. Это приложение не отслеживает тома каналов, так как оно не изменяет тома канала (вызывая методы в интерфейсе IChannelAudioVolume ), и не предоставляет общий доступ к сеансу с другими приложениями, которые могут изменить тома канала.
Единственными тремя методами в классе CAudioSessionEvents, которые уведомляют пользователя о событиях сеанса: OnSimpleVolumeChanged, OnStateChanged и OnSessionDisconnected. Например, если пользователь запускает программу управления системным томом, Sndvol и использует элемент управления томом в Sndvol для изменения уровня тома приложения, OnSimpleVolumeChanged
немедленно выводит новый уровень тома.
Пример кода, который регистрирует и отменяет регистрацию интерфейса IAudioSessionEvents клиента, см. в разделе "Звуковые события" для устаревших звуковых приложений.
См. также