[vlc-commits] [Git][videolan/vlc][master] 10 commits: mmdevice: avoid using NULL as (wide) string format argument
Felix Paul Kühne (@fkuehne)
gitlab at videolan.org
Sun Dec 28 13:59:07 UTC 2025
Felix Paul Kühne pushed to branch master at VideoLAN / VLC
Commits:
8c9665b4 by Steve Lhomme at 2025-12-28T14:30:24+01:00
mmdevice: avoid using NULL as (wide) string format argument
IMMNotificationClient::OnDefaultDeviceChanged() can give a NULL pointer [^1].
[^1]: https://learn.microsoft.com/en-us/windows/win32/api/mmdeviceapi/nf-mmdeviceapi-immnotificationclient-ondefaultdevicechanged#parameters
- - - - -
f39b6c88 by Steve Lhomme at 2025-12-28T14:30:24+01:00
mmdevice: fix potential leak on exit
- - - - -
507cd9c4 by Steve Lhomme at 2025-12-28T14:30:24+01:00
mmdevice: avoid setting acquired_device to a device we can't select
Try to use the default device instead.
- - - - -
5028d30f by Steve Lhomme at 2025-12-28T14:30:24+01:00
mmdevice: set the initialisation_status to FAILED when we don't have a device
The hr error is set and MMSession() will return that value.
- - - - -
e2a874bd by Steve Lhomme at 2025-12-28T14:30:24+01:00
mmdevice: use a single string pointer for the device name
We only care about the name before getting sys->dev and we keep it
in case of restart on the same device.
We also need a way to tell if sys->dev has been acquired or if we failed
to do so. NULL alone in sys->dev can't tell that.
In OnDefaultDeviceChange() we don't care if the device was acquired or not.
We only care if we are using the default device when it changes.
- - - - -
847f7e10 by Steve Lhomme at 2025-12-28T14:30:24+01:00
mmdevice: use NULL for the default device name
That's what the core uses.
- - - - -
019cfc36 by Steve Lhomme at 2025-12-28T14:30:24+01:00
mmdevice: merge initialisation_status and device_status
The initialization fails or succeeds if the device was properly acquired.
We don't need the initialisation_status only used for initialization.
- - - - -
e197614b by Steve Lhomme at 2025-12-28T14:30:24+01:00
mmdevice: only log the device we are going to use
On error we log, which device name failed. "using default device" will be logged next.
- - - - -
61c1715d by Steve Lhomme at 2025-12-28T14:30:24+01:00
mmdevice: rename request_device_restart to default_device_changed
- - - - -
5a666ee2 by Steve Lhomme at 2025-12-28T14:30:24+01:00
mmdevice: always log the default device change
- - - - -
1 changed file:
- modules/audio_output/mmdevice.c
Changes:
=====================================
modules/audio_output/mmdevice.c
=====================================
@@ -72,13 +72,12 @@ static void LeaveMTA(void)
CoUninitialize();
}
-static wchar_t default_device[1] = L"";
static char default_device_b[1] = "";
-enum initialisation_status_t {
- INITIALISATION_PENDING,
- INITIALISATION_FAILED,
- INITIALISATION_SUCCEEDED,
+enum device_acquisition_status {
+ DEVICE_PENDING,
+ DEVICE_ACQUISITION_FAILED,
+ DEVICE_ACQUIRED,
};
typedef struct
@@ -96,13 +95,12 @@ typedef struct
unsigned ducks;
float gain; /**< Current software gain volume */
- wchar_t *requested_device; /**< Requested device identifier, NULL if none */
float requested_volume; /**< Requested volume, negative if none */
signed char requested_mute; /**< Requested mute, negative if none */
- wchar_t *acquired_device; /**< Acquired device identifier, NULL if none */
- bool request_device_restart;
+ enum device_acquisition_status device_status;
+ wchar_t *device_name; /**< device identifier to use, NULL if default */
+ bool default_device_changed;
HANDLE work_event;
- enum initialisation_status_t initialisation_status;
vlc_mutex_t lock;
vlc_cond_t ready;
vlc_thread_t thread; /**< Thread for audio session control */
@@ -579,13 +577,13 @@ vlc_MMNotificationClient_OnDefaultDeviceChange(IMMNotificationClient *this,
return S_OK;
vlc_mutex_lock(&sys->lock);
- if (sys->acquired_device == NULL || sys->acquired_device == default_device)
+ if (sys->device_name == NULL)
{
- msg_Dbg(aout, "default device changed: %ls", wid);
- sys->request_device_restart = true;
+ sys->default_device_changed = true;
aout_RestartRequest(aout, true);
}
vlc_mutex_unlock(&sys->lock);
+ msg_Dbg(aout, "default device changed: %ls", wid ? wid : L"(disabled)");
return S_OK;
}
@@ -728,12 +726,12 @@ static HRESULT DevicesEnum(IMMDeviceEnumerator *it,
static int DeviceRequestLocked(audio_output_t *aout)
{
aout_sys_t *sys = aout->sys;
- assert(sys->requested_device);
+ assert(sys->device_status == DEVICE_PENDING);
- sys->request_device_restart = false;
+ sys->default_device_changed = false;
SetEvent(sys->work_event);
- while (sys->requested_device != NULL)
+ while (sys->device_status == DEVICE_PENDING)
vlc_cond_wait(&sys->ready, &sys->lock);
if (sys->stream != NULL && sys->dev != NULL)
@@ -745,16 +743,17 @@ static int DeviceRequestLocked(audio_output_t *aout)
static int DeviceSelectLocked(audio_output_t *aout, const char *id)
{
aout_sys_t *sys = aout->sys;
- assert(sys->requested_device == NULL);
+ assert(sys->device_status != DEVICE_PENDING);
+ sys->device_status = DEVICE_PENDING;
if (id != NULL && strcmp(id, default_device_b) != 0)
{
- sys->requested_device = ToWide(id); /* FIXME leak */
- if (unlikely(sys->requested_device == NULL))
+ sys->device_name = ToWide(id); /* FIXME leak */
+ if (unlikely(sys->device_name == NULL))
return -1;
}
else
- sys->requested_device = default_device;
+ sys->device_name = NULL;
return DeviceRequestLocked(aout);
}
@@ -762,9 +761,8 @@ static int DeviceSelectLocked(audio_output_t *aout, const char *id)
static int DeviceRestartLocked(audio_output_t *aout)
{
aout_sys_t *sys = aout->sys;
- assert(sys->requested_device == NULL);
- sys->requested_device = sys->acquired_device ? sys->acquired_device
- : default_device;
+ assert(sys->device_status != DEVICE_PENDING);
+ sys->device_status = DEVICE_PENDING;
return DeviceRequestLocked(aout);
}
@@ -790,7 +788,7 @@ static void MMSessionMainloop(audio_output_t *aout, ISimpleAudioVolume *volume)
bool report_volume = true;
bool report_mute = true;
- while (sys->requested_device == NULL)
+ while (sys->device_status != DEVICE_PENDING)
{
if (volume != NULL)
{
@@ -866,7 +864,8 @@ static void MMSessionMainloop(audio_output_t *aout, ISimpleAudioVolume *volume)
if (unlikely(hr == AUDCLNT_E_DEVICE_INVALIDATED ||
hr == AUDCLNT_E_RESOURCES_INVALIDATED))
{
- sys->requested_device = default_device;
+ sys->device_name = NULL;
+ sys->device_status = DEVICE_PENDING;
/* The restart of the stream will be requested asynchronously */
}
}
@@ -895,22 +894,25 @@ static HRESULT MMSession(audio_output_t *aout, IMMDeviceEnumerator *it)
void *pv;
HRESULT hr;
- assert(sys->requested_device != NULL);
+ assert(sys->device_status == DEVICE_PENDING);
assert(sys->dev == NULL);
/* Yes, it's perfectly valid to request the same device, see Start()
* comments. */
- if (sys->acquired_device != sys->requested_device
- && sys->acquired_device != default_device)
- free(sys->acquired_device);
- if (sys->requested_device != default_device) /* Device selected explicitly */
+ if (sys->device_name != NULL) /* Device selected explicitly */
{
- msg_Dbg(aout, "using selected device %ls", sys->requested_device);
- hr = IMMDeviceEnumerator_GetDevice(it, sys->requested_device, &sys->dev);
+ hr = IMMDeviceEnumerator_GetDevice(it, sys->device_name, &sys->dev);
if (FAILED(hr))
+ {
msg_Err(aout, "cannot get selected device %ls (error 0x%lX)",
- sys->requested_device, hr);
- sys->acquired_device = sys->requested_device;
+ sys->device_name, hr);
+ hr = AUDCLNT_E_DEVICE_INVALIDATED;
+ }
+ else
+ {
+ msg_Dbg(aout, "using selected device %ls", sys->device_name);
+ sys->device_status = DEVICE_ACQUIRED;
+ }
}
else
hr = AUDCLNT_E_DEVICE_INVALIDATED;
@@ -924,21 +926,23 @@ static HRESULT MMSession(audio_output_t *aout, IMMDeviceEnumerator *it)
if (FAILED(hr))
{
msg_Err(aout, "cannot get default device (error 0x%lX)", hr);
- sys->acquired_device = NULL;
+ sys->device_status = DEVICE_ACQUISITION_FAILED;
+ sys->device_name = NULL;
}
else
- sys->acquired_device = default_device;
+ {
+ sys->device_status = DEVICE_ACQUIRED;
+ sys->device_name = NULL;
+ }
}
- sys->requested_device = NULL;
- sys->initialisation_status = INITIALISATION_SUCCEEDED;
vlc_cond_signal(&sys->ready);
if (SUCCEEDED(hr))
{ /* Report actual device */
LPWSTR wdevid;
- if (sys->acquired_device == default_device)
+ if (sys->device_name == NULL)
aout_DeviceReport(aout, default_device_b);
else
{
@@ -1132,7 +1136,7 @@ static void *MMThread(void *data)
vlc_mutex_lock(&sys->lock);
do
- if (sys->requested_device == NULL || FAILED(MMSession(aout, it)))
+ if (sys->device_status != DEVICE_PENDING || FAILED(MMSession(aout, it)))
{
vlc_mutex_unlock(&sys->lock);
WaitForSingleObject(sys->work_event, INFINITE);
@@ -1150,7 +1154,7 @@ static void *MMThread(void *data)
error:
vlc_mutex_lock(&sys->lock);
- sys->initialisation_status = INITIALISATION_FAILED;
+ sys->device_status = DEVICE_ACQUISITION_FAILED;
vlc_cond_signal(&sys->ready);
vlc_mutex_unlock(&sys->lock);
return NULL;
@@ -1212,7 +1216,7 @@ static int Start(audio_output_t *aout, audio_sample_format_t *restrict fmt)
EnterMTA();
vlc_mutex_lock(&sys->lock);
- if ((sys->request_device_restart && DeviceRestartLocked(aout) != 0)
+ if ((sys->default_device_changed && DeviceRestartLocked(aout) != 0)
|| sys->dev == NULL)
{
/* Error if the device restart failed or if a request previously
@@ -1338,8 +1342,8 @@ static int Open(vlc_object_t *obj)
sys->gain = 1.f;
sys->requested_volume = -1.f;
sys->requested_mute = -1;
- sys->acquired_device = NULL;
- sys->request_device_restart = false;
+ sys->device_name = NULL;
+ sys->default_device_changed = false;
if (!var_CreateGetBool(aout, "volume-save"))
VolumeSetLocked(aout, var_InheritFloat(aout, "mmdevice-volume"));
@@ -1356,28 +1360,28 @@ static int Open(vlc_object_t *obj)
char *saved_device_b = var_InheritString(aout, "mmdevice-audio-device");
if (saved_device_b != NULL && strcmp(saved_device_b, default_device_b) != 0)
{
- sys->requested_device = ToWide(saved_device_b); /* FIXME leak */
+ sys->device_name = ToWide(saved_device_b); /* FIXME leak */
free(saved_device_b);
- if (unlikely(sys->requested_device == NULL))
+ if (unlikely(sys->device_name == NULL))
goto error;
}
else
{
free(saved_device_b);
- sys->requested_device = default_device;
+ sys->device_name = NULL;
}
+ sys->device_status = DEVICE_PENDING;
- sys->initialisation_status = INITIALISATION_PENDING;
if (vlc_clone(&sys->thread, MMThread, aout))
goto error;
vlc_mutex_lock(&sys->lock);
- while (sys->initialisation_status == INITIALISATION_PENDING)
+ while (sys->device_status == DEVICE_PENDING)
vlc_cond_wait(&sys->ready, &sys->lock);
vlc_mutex_unlock(&sys->lock);
- if (sys->initialisation_status == INITIALISATION_FAILED)
+ if (sys->device_status == DEVICE_ACQUISITION_FAILED)
{
vlc_join(sys->thread, NULL);
goto error;
@@ -1407,10 +1411,15 @@ static void Close(vlc_object_t *obj)
aout_sys_t *sys = aout->sys;
vlc_mutex_lock(&sys->lock);
- sys->requested_device = default_device; /* break out of MMSession() loop */
+ wchar_t *previous = sys->device_name;
+ sys->device_name = NULL;
+ sys->device_status = DEVICE_PENDING; /* break out of MMSession() loop */
sys->it = NULL; /* break out of MMThread() loop */
vlc_mutex_unlock(&sys->lock);
+ if (previous != NULL)
+ free(previous);
+
SetEvent(sys->work_event);
vlc_join(sys->thread, NULL);
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/36464b937d97d49a7042889c2be3438906cd8096...5a666ee2df0070786cad7d1fdd1cd34242514c13
--
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/36464b937d97d49a7042889c2be3438906cd8096...5a666ee2df0070786cad7d1fdd1cd34242514c13
You're receiving this email because of your account on code.videolan.org.
VideoLAN code repository instance
More information about the vlc-commits
mailing list