From 35ff516fc23f5bc90d30e9a5827ae492ca9e550a Mon Sep 17 00:00:00 2001 From: Willian Henrique Date: Mon, 8 May 2023 18:12:28 -0300 Subject: Add snd_mute_losefocus backport --- compile.bat | 4 ++- src/nomute.c | 108 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 111 insertions(+), 1 deletion(-) create mode 100644 src/nomute.c diff --git a/compile.bat b/compile.bat index f48453e..c275cb0 100644 --- a/compile.bat +++ b/compile.bat @@ -73,6 +73,7 @@ setlocal DisableDelayedExpansion :+ hook.c :+ kv.c :+ l4dwarp.c +:+ nomute.c :+ nosleep.c :+ portalcolours.c :+ rinput.c @@ -102,7 +103,8 @@ if "%dbg%"=="1" ( set clibs=-lmsvcrt -lvcruntime -lucrt ) %CC% -shared -flto %ldflags% -Wl,/IMPLIB:.build/sst.lib,/Brepro,/nodefaultlib ^ --L.build %clibs% -lkernel32 -luser32 -ladvapi32 -lshlwapi -ld3d9 -ltier0 -lvstdlib -o sst.dll%objs% .build/dll.res || exit /b +-L.build %clibs% -lkernel32 -luser32 -ladvapi32 -lshlwapi -ld3d9 -ldsound ^ +-ltier0 -lvstdlib -o sst.dll%objs% .build/dll.res || exit /b :: get rid of another useless file (can we just not create this???) del .build\sst.lib diff --git a/src/nomute.c b/src/nomute.c new file mode 100644 index 0000000..861062a --- /dev/null +++ b/src/nomute.c @@ -0,0 +1,108 @@ +/* + * Copyright © 2023 Willian Henrique + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED “AS IS” AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +// TODO(linux): this is currently only built on Windows, but a linux +// implementation would be also useful for some games e.g. L4D2 + +#include "con_.h" +#include "errmsg.h" +#include "feature.h" +#include "hook.h" +#include "intdefs.h" +#include "mem.h" +#include "os.h" +#include "sst.h" +#include "x86.h" +#include "x86util.h" + +// these have to come after Windows.h (via os.h) and in this order +#include +#include + +FEATURE("inactive window audio control") + +DEF_CVAR_UNREG(snd_mute_losefocus, + "Keep playing audio while tabbed out (SST reimplementation)", 1, + CON_ARCHIVE | CON_HIDDEN) + +static IDirectSoundVtbl *ds_vt = 0; +static typeof(ds_vt->CreateSoundBuffer) orig_CreateSoundBuffer; +static con_cmdcbv1 snd_restart_cb = 0; + +// early init (via VDF) happens before config is loaded, and audio is set up +// after that, so we don't want to run snd_restart the first time the cvar is +// set, unless we were loaded later with plugin_load, in which case audio is +// already up and running and we'll want to restart it every time +bool skiprestart; +static void losefocuscb(struct con_var *v) { + if (!skiprestart) snd_restart_cb(); + skiprestart = false; +} + +static long __stdcall hook_CreateSoundBuffer(IDirectSound *this, + const DSBUFFERDESC *desc, IDirectSoundBuffer **buff, IUnknown *unk) { + if (!con_getvari(snd_mute_losefocus)) { + ((DSBUFFERDESC *)desc)->dwFlags |= DSBCAPS_GLOBALFOCUS; + } + return orig_CreateSoundBuffer(this, desc, buff, unk); +} + +PREINIT { + if (con_findvar("snd_mute_losefocus")) return false; + con_reg(snd_mute_losefocus); + return true; +} + +INIT { + skiprestart = sst_earlyloaded; // see above + IDirectSound *ds_obj = 0; + if (DirectSoundCreate(NULL, &ds_obj, NULL) != DS_OK) { + errmsg_errorx("couldn't create IDirectSound instance"); + return false; + } + + ds_vt = ds_obj->lpVtbl; + if (!os_mprot(&ds_vt->CreateSoundBuffer, sizeof(void *), PAGE_READWRITE)) { + errmsg_errorx("couldn't make virtual table writable"); + return false; + } + + ds_obj->lpVtbl->Release(ds_obj); + + orig_CreateSoundBuffer = ds_vt->CreateSoundBuffer; + ds_vt->CreateSoundBuffer = &hook_CreateSoundBuffer; + snd_mute_losefocus->base.flags &= ~CON_HIDDEN; + + struct con_cmd *snd_restart = con_findcmd("snd_restart"); + if (snd_restart) { + snd_restart_cb = con_getcmdcbv1(snd_restart); + snd_mute_losefocus->cb = &losefocuscb; + } + else { + errmsg_warnx("couldn't find snd_restart"); + errmsg_note("changing snd_mute_losefocus will require changing other " + "audio settings or restarting the game with SST autoloaded in " + "order to have an effect"); + } + + return true; +} + +END { + ds_vt->CreateSoundBuffer = orig_CreateSoundBuffer; +} + +// vi: sw=4 ts=4 noet tw=80 cc=80 -- cgit v1.2.3