summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDiogo Franco (Kovensky) <diogomfranco@gmail.com>2014-03-11 03:46:22 -0300
committerDiogo Franco (Kovensky) <diogomfranco@gmail.com>2014-03-11 16:37:22 -0300
commitc5012946ee8273cb1c2879c9299e5959e7766ffc (patch)
tree06f934827c205888df77e82e017413f9cb3d4bd3
parentf8bdada77f992410deb4fc12652cf406d95e3657 (diff)
downloadmpv-c5012946ee8273cb1c2879c9299e5959e7766ffc.tar.bz2
mpv-c5012946ee8273cb1c2879c9299e5959e7766ffc.tar.xz
ao_wasapi: Implement AOCONTROL_UPDATE_STREAM_TITLE
-rw-r--r--audio/out/ao_wasapi.c30
-rwxr-xr-xaudio/out/ao_wasapi.h4
-rwxr-xr-xaudio/out/ao_wasapi_utils.c89
3 files changed, 89 insertions, 34 deletions
diff --git a/audio/out/ao_wasapi.c b/audio/out/ao_wasapi.c
index ec04cedcd6..2353fc4cc2 100644
--- a/audio/out/ao_wasapi.c
+++ b/audio/out/ao_wasapi.c
@@ -233,6 +233,16 @@ static int init(struct ao *ao)
return state->init_ret;
}
+static wchar_t* utf8_to_wstring(char *string) {
+ if (string) {
+ int len = MultiByteToWideChar(CP_UTF8, 0, string, -1, NULL, 0);
+ wchar_t *ret = malloc(len * sizeof(wchar_t));
+ MultiByteToWideChar(CP_UTF8, 0, string, -1, ret, len);
+ return ret;
+ }
+ return NULL;
+}
+
static int control(struct ao *ao, enum aocontrol cmd, void *arg)
{
struct wasapi_state *state = (struct wasapi_state *)ao->priv;
@@ -285,6 +295,26 @@ static int control(struct ao *ao, enum aocontrol cmd, void *arg)
ISimpleAudioVolume_SetMute(state->pAudioVolumeProxy, mute, NULL);
return CONTROL_OK;
+ case AOCONTROL_UPDATE_STREAM_TITLE: {
+ MP_VERBOSE(state, "Updating stream title to \"%s\"\n", (char*)arg);
+ wchar_t *title = utf8_to_wstring((char*)arg);
+
+ wchar_t *tmp = NULL;
+
+ /* There is a weird race condition in the IAudioSessionControl itself --
+ it seems that *sometimes* the SetDisplayName does not take effect and it still shows
+ the old title. Use this loop to insist until it works. */
+ do {
+ IAudioSessionControl_SetDisplayName(state->pSessionControlProxy, title, NULL);
+
+ SAFE_RELEASE(tmp, CoTaskMemFree(tmp));
+ IAudioSessionControl_GetDisplayName(state->pSessionControlProxy, &tmp);
+ } while (lstrcmpW(title, tmp));
+ SAFE_RELEASE(tmp, CoTaskMemFree(tmp));
+ free(title);
+
+ return CONTROL_OK;
+ }
default:
return CONTROL_UNKNOWN;
}
diff --git a/audio/out/ao_wasapi.h b/audio/out/ao_wasapi.h
index d17b2504a0..4fe80a6c8f 100755
--- a/audio/out/ao_wasapi.h
+++ b/audio/out/ao_wasapi.h
@@ -24,6 +24,7 @@
#define _WIN32_WINNT 0x600
#include <audioclient.h>
+#include <audiopolicy.h>
#include <mmdeviceapi.h>
#include <avrt.h>
@@ -58,6 +59,7 @@ typedef struct wasapi_state {
IAudioRenderClient *pRenderClient;
ISimpleAudioVolume *pAudioVolume;
IAudioEndpointVolume *pEndpointVolume;
+ IAudioSessionControl *pSessionControl;
HANDLE hFeed; /* wasapi event */
HANDLE hForceFeed; /* forces writing a buffer (e.g. before audio_resume) */
HANDLE hFeedDone; /* set only after a hForceFeed */
@@ -70,6 +72,7 @@ typedef struct wasapi_state {
IAudioClient *pAudioClientProxy;
ISimpleAudioVolume *pAudioVolumeProxy;
IAudioEndpointVolume *pEndpointVolumeProxy;
+ IAudioSessionControl *pSessionControlProxy;
/* Streams used to marshal the proxy objects. The thread owning the actual objects
needs to marshal proxy objects into these streams, and the thread that wants the
@@ -77,6 +80,7 @@ typedef struct wasapi_state {
IStream *sAudioClient;
IStream *sAudioVolume;
IStream *sEndpointVolume;
+ IStream *sSessionControl;
/* WASAPI internal clock information, for estimating delay */
IAudioClock *pAudioClock;
diff --git a/audio/out/ao_wasapi_utils.c b/audio/out/ao_wasapi_utils.c
index f5336cbebf..7baf169c32 100755
--- a/audio/out/ao_wasapi_utils.c
+++ b/audio/out/ao_wasapi_utils.c
@@ -30,6 +30,8 @@
#include "audio/format.h"
+#define MIXER_DEFAULT_LABEL L"mpv - video player"
+
#define EXIT_ON_ERROR(hres) \
do { if (FAILED(hres)) { goto exit_label; } } while(0)
#define SAFE_RELEASE(unk, release) \
@@ -464,6 +466,31 @@ exit_label:
return 1;
}
+static int init_session_display(struct wasapi_state *state) {
+ HRESULT hr;
+ wchar_t path[MAX_PATH+12] = {0};
+
+ hr = IAudioClient_GetService(state->pAudioClient,
+ &IID_IAudioSessionControl,
+ (void **) &state->pSessionControl);
+ EXIT_ON_ERROR(hr);
+
+ GetModuleFileNameW(NULL, path, MAX_PATH);
+ lstrcatW(path, L",-IDI_ICON1");
+
+ hr = IAudioSessionControl_SetDisplayName(state->pSessionControl, MIXER_DEFAULT_LABEL, NULL);
+ EXIT_ON_ERROR(hr);
+ hr = IAudioSessionControl_SetIconPath(state->pSessionControl, path, NULL);
+ EXIT_ON_ERROR(hr);
+
+ return 0;
+
+exit_label:
+ MP_ERR(state, "init_session_display failed with %s.\n",
+ wasapi_explain_err(hr));
+ return 1;
+}
+
static int fix_format(struct wasapi_state *state)
{
HRESULT hr;
@@ -524,6 +551,8 @@ reinit:
if (init_clock(state))
return 1;
+ if (init_session_display(state))
+ return 1;
state->hTask =
state->VistaBlob.pAvSetMmThreadCharacteristicsW(L"Pro Audio", &state->taskIndex);
@@ -865,23 +894,18 @@ HRESULT wasapi_setup_proxies(struct wasapi_state *state) {
CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
- hr = CoGetInterfaceAndReleaseStream(state->sAudioClient,
- &IID_IAudioClient,
- (void**) &state->pAudioClientProxy);
- state->sAudioClient = NULL;
- EXIT_ON_ERROR(hr);
+#define UNMARSHAL(type, to, from) do { \
+ hr = CoGetInterfaceAndReleaseStream((from), &(type), (void**) &(to)); \
+ (from) = NULL; \
+ EXIT_ON_ERROR(hr); \
+} while (0)
- hr = CoGetInterfaceAndReleaseStream(state->sAudioVolume,
- &IID_ISimpleAudioVolume,
- (void**) &state->pAudioVolumeProxy);
- state->sAudioVolume = NULL;
- EXIT_ON_ERROR(hr);
+ UNMARSHAL(IID_IAudioClient, state->pAudioClientProxy, state->sAudioClient);
+ UNMARSHAL(IID_ISimpleAudioVolume, state->pAudioVolumeProxy, state->sAudioVolume);
+ UNMARSHAL(IID_IAudioEndpointVolume, state->pEndpointVolumeProxy, state->sEndpointVolume);
+ UNMARSHAL(IID_IAudioSessionControl, state->pSessionControlProxy, state->sSessionControl);
- hr = CoGetInterfaceAndReleaseStream(state->sEndpointVolume,
- &IID_IAudioEndpointVolume,
- (void**) &state->pEndpointVolumeProxy);
- state->sEndpointVolume = NULL;
- EXIT_ON_ERROR(hr);
+#undef UNMARSHAL
exit_label:
if (hr != S_OK) {
@@ -891,9 +915,10 @@ exit_label:
}
void wasapi_release_proxies(wasapi_state *state) {
- SAFE_RELEASE(state->pAudioClientProxy, IUnknown_Release(state->pAudioClientProxy));
- SAFE_RELEASE(state->pAudioVolumeProxy, IUnknown_Release(state->pAudioVolumeProxy));
+ SAFE_RELEASE(state->pAudioClientProxy, IUnknown_Release(state->pAudioClientProxy));
+ SAFE_RELEASE(state->pAudioVolumeProxy, IUnknown_Release(state->pAudioVolumeProxy));
SAFE_RELEASE(state->pEndpointVolumeProxy, IUnknown_Release(state->pEndpointVolumeProxy));
+ SAFE_RELEASE(state->pSessionControlProxy, IUnknown_Release(state->pSessionControlProxy));
CoUninitialize();
}
@@ -901,25 +926,20 @@ void wasapi_release_proxies(wasapi_state *state) {
static HRESULT create_proxies(struct wasapi_state *state) {
HRESULT hr;
- hr = CreateStreamOnHGlobal(NULL, TRUE, &state->sAudioClient);
- EXIT_ON_ERROR(hr);
- hr = CoMarshalInterThreadInterfaceInStream(&IID_IAudioClient,
- (IUnknown*) state->pAudioClient,
- &state->sAudioClient);
- EXIT_ON_ERROR(hr);
+#define MARSHAL(type, to, from) do { \
+ hr = CreateStreamOnHGlobal(NULL, TRUE, &(to)); \
+ EXIT_ON_ERROR(hr); \
+ hr = CoMarshalInterThreadInterfaceInStream(&(type), \
+ (IUnknown*) (from), \
+ &(to)); \
+ EXIT_ON_ERROR(hr); \
+} while (0)
- hr = CreateStreamOnHGlobal(NULL, TRUE, &state->sAudioVolume);
- EXIT_ON_ERROR(hr);
- hr = CoMarshalInterThreadInterfaceInStream(&IID_ISimpleAudioVolume,
- (IUnknown*) state->pAudioVolume,
- &state->sAudioVolume);
- EXIT_ON_ERROR(hr);
+ MARSHAL(IID_IAudioClient, state->sAudioClient, state->pAudioClient);
+ MARSHAL(IID_ISimpleAudioVolume, state->sAudioVolume, state->pAudioVolume);
+ MARSHAL(IID_IAudioEndpointVolume, state->sEndpointVolume, state->pEndpointVolume);
+ MARSHAL(IID_IAudioSessionControl, state->sSessionControl, state->pSessionControl);
- hr = CreateStreamOnHGlobal(NULL, TRUE, &state->sEndpointVolume);
- EXIT_ON_ERROR(hr);
- hr = CoMarshalInterThreadInterfaceInStream(&IID_IAudioEndpointVolume,
- (IUnknown*) state->pEndpointVolume,
- &state->sEndpointVolume);
exit_label:
return hr;
}
@@ -1002,6 +1022,7 @@ void wasapi_thread_uninit(wasapi_state *state)
SAFE_RELEASE(state->pAudioClock, IAudioClock_Release(state->pAudioClock));
SAFE_RELEASE(state->pAudioVolume, ISimpleAudioVolume_Release(state->pAudioVolume));
SAFE_RELEASE(state->pEndpointVolume, IAudioEndpointVolume_Release(state->pEndpointVolume));
+ SAFE_RELEASE(state->pSessionControl, IAudioSessionControl_Release(state->pSessionControl));
SAFE_RELEASE(state->pAudioClient, IAudioClient_Release(state->pAudioClient));
SAFE_RELEASE(state->pDevice, IMMDevice_Release(state->pDevice));