Sokonomi
Sokonomi

Reputation: 61

How to make a toggle switch in batch?

I need a batch file that will toggle between running two command lines;

One being

nircmd.exe setdefaultsounddevice "Speakers"

The other being

nircmd.exe setdefaultsounddevice "Headset"

Ive tried using the existence of a .txt file as a flag, but for some reason it just always sees it as not existing. How do you make a batch file (silently) tick/tock every time it runs?

Upvotes: 2

Views: 4242

Answers (5)

Draconic Velum
Draconic Velum

Reputation: 1

@echo off  
set _toggle=0

:Start  
CLS  
echo 1.Switch

CHOICE /C 1 /M "Enter your choice:"

IF ERRORLEVEL 1 call:Switch

:Switch  
if "%_toggle%"=="0" (goto Speakers
) else (goto Headset)

:Speakers  
echo Speakers Active  
nircmd.exe setdefaultsounddevice "Speakers"  
set /a _toggle=%_toggle%+1  
timeout /t 1 /nobreak  
goto Start

:Headset  
echo Headset Active  
nircmd.exe setdefaultsounddevice "Headset"  
set /a _toggle=%_toggle%-1  
timeout /t 1 /nobreak  
goto Start

Based of Forest bat and implemented with the choice bat option I found also on stack overflow, this should work like a charm, i use it to toggle the desktop icons visibility.

Upvotes: 0

Forest
Forest

Reputation: 21

echo off  
set _toggle=0  
Call:Process  
Call:Process  
Call:Process  
Call:Process  
Call:Process  
exit /b  

:Process
if "%_toggle%"=="0" (echo Set "Speakers"
) else (echo Set "Headset")
set /a _toggle=-1*%_toggle%+1
exit /b

Output
Set "Speakers"
Set "Headset"
Set "Speakers"
Set "Headset"
Set "Speakers"

Upvotes: 0

SachaDee
SachaDee

Reputation: 9545

A good solution is to store the switch in an ADS (alternative data stream) in the bat itself (will work only if your file system is NTFS):

You just will get a file not found warning at the first run while it can find the ADS stream but after that it will be created

@echo off

set "$activ="
set /p $activ=<%~nx0:activ

if not defined $activ (
    echo speaker>%~nx0:activ
    set "$activ=speaker"
    )

echo actual [%$activ%]

if /i "%$activ%"=="speaker" (
    nircmd.exe setdefaultsounddevice "Headset"
    echo headset>%~nx0:activ
    ) else (
    nircmd.exe setdefaultsounddevice "Speakers"
    echo speaker>%~nx0:activ
    )

EDIT : Thanks @aschipfl here is the solution to avoid the first run Warning

@echo off
set "$activ="

2> nul (set /P $activ= < "%~nx0:activ") || set "$activ=speaker"

echo actual [%$activ%]

if /i "%$activ%"=="speaker" (
    nircmd.exe setdefaultsounddevice "Headset"
    echo headset>%~nx0:activ
    ) else (
    nircmd.exe setdefaultsounddevice "Speakers"
    echo speaker>%~nx0:activ
    )

very easy and don't need any temp file and don't have call limitation

Upvotes: 2

Aacini
Aacini

Reputation: 67236

You can store the toggle value in the Batch file itself in a very simple way:

@echo off
setlocal

rem Get current value and update it
call :GetToggle
set /P "=+1" < nul >> "%~F0"
set /A "toggle%%=2"

if %toggle% equ 0 (
   echo Set "Speakers"
) else (
   echo Set "Headset"
)

goto :EOF

:GetToggle
rem Be sure that next line does NOT end in CR+LF:
set /A toggle=0

This method works correctly for a little less than 4096 times. If the Batch file run once everyday, this covers more than 11 years! If this is not enough for you, just add an if command after get the toggle value to check if it exceeds 4090, and in such a case insert a breaking CR+LF characters at end of the file followed by a new line with set /A toggle=0

Note that this method also allows to know how many times the Batch file had been used, so it may be used in other scenario...

Upvotes: 6

user6811411
user6811411

Reputation:

  • However you name the following batch, it will create an Ini file with the same name at the same location (Initially set to Speakers)
  • It uses nircmds inisetval for this and also changes the Active key to the current selection

:: ToggleSnd.cmd
@Echo off
set "NC="
::check nircmd
for /f "delims=" %%A in ("nircmd.exe") do Set "NC=%%~f$PATH:A"
if Not defined NC (Echo Can't Locate nircmd.exe&Pause&Exit /B 1)
Set "Ini=%~dpn0.Ini"

If Not Exist "%Ini%" goto :Speakers
:: get current selection
For /f %%A in ('Findstr /i "Active" %Ini%') Do Set "%%A"
if /I "%Active%"=="Headset" goto :Speakers

:: switch to Headset
%nc% setdefaultsounddevice "Headset"
%nc% inisetval "%Ini%" DefaultSoundDevice Active Headset
Echo switched to Headset
Goto :Eof

:Speakers
%nc% setDefaultSoundDevice "Speakers"
%nc% inisetval "%Ini%" DefaultSoundDevice Active Speakers
Echo switched to Speakers

Sometimes you are lucky if someone finds the task interresting.

Upvotes: 0

Related Questions