**Windows: volume control** [bll] 2016-12-15 This Tcl stub might be useful to someone. [bll] 2016-12-19 Updated so that it can be built as either a stand-alone program or as a .dll. ====== load [file join [pwd] winvolume64[info sharedlibextension]] set vol [winvolume] ; # get the volume incr vol -10 set newvol [winvolume $vol] ; # set the volume, always returns the current volume. ====== '''winmkvol.sh''' ====== #!/bin/bash case $MSYSTEM in *32) g++ -m32 -static-libgcc -UWIN_TCL_INTERFACE -o winvolume32.exe \ -I$HOME/local-32/include winvolume.cpp \ -L$HOME/local-32/lib -lole32 g++ -m32 -shared -static-libgcc -DWIN_TCL_INTERFACE -o winvolume32.dll \ -I$HOME/local-32/include -DUSE_TCL_STUBS winvolume.cpp \ -L$HOME/local-32/lib -ltclstub86 -lole32 ;; *64) g++ -m64 -static-libgcc -UWIN_TCL_INTERFACE -o winvolume64.exe \ -I$HOME/local-64/include winvolume.cpp \ -L$HOME/local-64/lib -lole32 g++ -m64 -shared -static-libgcc -DWIN_TCL_INTERFACE -o winvolume64.dll \ -I$HOME/local-64/include -DUSE_TCL_STUBS winvolume.cpp \ -L$HOME/local-64/lib -ltclstub86 -lole32 ;; esac ====== '''winvolume.cpp''' ====== /* * Copyright 2016 Brad Lanam Walnut Creek, CA US * This code is in the public domain. * * much of the original volume code from: https://gist.github.com/rdp/8363580 */ #ifdef WIN_TCL_INTERFACE # include #endif #include #include #include #include #include #include #include #define EXIT_ON_ERROR(hr) \ if (FAILED(hr)) { printf ("error %d occurred\n", -hr); goto Exit; } #define SAFE_RELEASE(punk) \ if ((punk) != NULL) { (punk)->Release(); (punk) = NULL; } extern "C" { int process (int set, int vol) { IAudioEndpointVolume *g_pEndptVol = NULL; HRESULT hr = S_OK; IMMDeviceEnumerator *pEnumerator = NULL; IMMDevice *pDevice = NULL; OSVERSIONINFO VersionInfo; float currentVal; int rc; ZeroMemory(&VersionInfo, sizeof(OSVERSIONINFO)); VersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); GetVersionEx(&VersionInfo); if (VersionInfo.dwMajorVersion <= 5) { return -1; } CoInitialize(NULL); // Get enumerator for audio endpoint devices. hr = CoCreateInstance(__uuidof(MMDeviceEnumerator), NULL, CLSCTX_INPROC_SERVER, __uuidof(IMMDeviceEnumerator), (void**)&pEnumerator); EXIT_ON_ERROR(hr) // Get default audio-rendering device. hr = pEnumerator->GetDefaultAudioEndpoint(eRender, eConsole, &pDevice); EXIT_ON_ERROR(hr) hr = pDevice->Activate(__uuidof(IAudioEndpointVolume), CLSCTX_ALL, NULL, (void**)&g_pEndptVol); EXIT_ON_ERROR(hr) if (set) { float got = (float) vol / 100.0; // needs to be within 1.0 to 0.0 hr = g_pEndptVol->SetMasterVolumeLevelScalar (got, NULL); EXIT_ON_ERROR(hr) } hr = g_pEndptVol->GetMasterVolumeLevelScalar (¤tVal); EXIT_ON_ERROR(hr) vol = (int) round(100 * currentVal); Exit: SAFE_RELEASE(pEnumerator) SAFE_RELEASE(pDevice) SAFE_RELEASE(g_pEndptVol) CoUninitialize(); return vol; } #ifndef WIN_TCL_INTERFACE int main (int argc, char *argv[]) { int set; int vol; set = 0; if (argc > 1) { set = 1; vol = atoi (argv[1]); } vol = process (set, vol); printf ("%d\n", vol); fflush (stdout); return 0; } #endif #ifdef WIN_TCL_INTERFACE int winvolumeObjCmd ( ClientData cd, Tcl_Interp* interp, int objc, Tcl_Obj * const objv[] ) { int set; int vol; int rc; if (objc != 1 && objc != 2) { Tcl_WrongNumArgs (interp, 1, objv, "?volume?"); return TCL_ERROR; } set = 0; vol = -1; if (objc == 2) { rc = Tcl_GetIntFromObj (interp, objv[1], &vol); if (rc != TCL_OK) { return TCL_ERROR; } set = 1; } vol = process (set, vol); if (vol < 0) { return TCL_ERROR; } Tcl_SetObjResult (interp, Tcl_NewIntObj (vol)); return TCL_OK; } int Winvolume_Init (Tcl_Interp *interp) { Tcl_Encoding utf; #ifdef USE_TCL_STUBS if (!Tcl_InitStubs(interp,"8.3",0)) { return TCL_ERROR; } #else if (!Tcl_PkgRequire(interp,"Tcl","8.3",0)) { return TCL_ERROR; } #endif Tcl_CreateObjCommand(interp,"winvolume", winvolumeObjCmd, (ClientData) NULL, NULL); Tcl_PkgProvide(interp,"winvolume","0.1"); return TCL_OK; } #endif } /* extern C */ ====== <>Windows | Multimedia