I have this code in my .bat
script.
( echo Set Sound = CreateObject("WMPlayer.OCX.7"^)
echo Sound.URL = "music\sia.mp3"
echo Sound.settings.volume = %volume%
echo Sound.settings.setMode "loop", True
echo Sound.Controls.play
echo While Sound.playState ^<^> 1
echo WScript.Sleep 100
echo Wend
)>sound22.vbs
start /min sound22.vbs
del *.vbs
It simply plays music\sia.mp3
in an infinite loop in the background.
Sometimes it fails to execute the sound22.vbs
because it deletes it before the poor code could even execute it.
However, here are my main issues:
( echo Set Sound = CreateObject("WMPlayer.OCX.7"^)
echo Sound.settings.volume = %volume2%
echo While Sound.playState ^<^> 1
echo WScript.Sleep 100
echo Wend
)>sound22.vbs
start /min sound22.vbs
del *.vbs
This code was supposed to, but doesn't, change the current volume to %volume2%
without replaying the music.
WMPlayer
object I created before?sound.controls.pause
the same way and continue to play it again?You can not control the previously created WMPlayer
object by creating a new one, but you can control it by incorporating a mechanism which communicates with the created object.
Since batch scripts have no standard means for interprocess communication, the only option will be left, is to use an intermediate file as the communication medium.
Following is an standalone example code which demonstrate one way of doing it through batch script.
It could be written differently but I've followed you design path for writing the code.
It plays the specified music/sound file and prompts the user to enter a command to send to the player to control it.
Implemented control command are: [0-100] for volume, mute, unmute, play, pause, replay, stop, open, quit
:: MusicPlayerAndController.bat
@echo off
setlocal DisableDelayedExpansion
set "PlayerMutex=BatchVbsSoundPlayer.mutex"
if "%~1"=="/LaunchAsyncPipedVbsPlayer" (
%= Asynchronous Background Player =%
%= Invoking only one instance of background player in the current directory =%
9>&2 2>nul ( 8>"%PlayerMutex%" 2>&9 (
call :LaunchAsyncPipedVbsPlayer
(call,) %= Masks all other errors except than failure to hold PlayerMutex =%
)) && del "%PlayerMutex%" >nul 2>&1 || echo WARNING: Another instance of player is already running.
exit /b
)
%= Asynchronous Controller =%
cls
title Batch/VBS Music Player And Controller
set "PlayerCommandFile=VBSPlayerCommand.txt"
set "VBScriptPlayerApp=MediaPlayer.vbs"
:: Sample Music from Windows 7
set "SoundFile=%PUBLIC%\Music\Sample Music\Sleep Away.mp3"
if not exist "%SoundFile%" (
set "SoundFile="
echo Open a media file to start playing.
)
set "InitialVolume=30"
set "PingPipe=pingpipe"
(
echo Dim Input : Dim Open
echo Open = False
echo Set Sound = CreateObject("WMPlayer.OCX.7"^)
echo Sound.URL = "%SoundFile%"
echo Sound.settings.volume = %InitialVolume%
echo Sound.settings.setMode "loop", True
echo Sound.Controls.play
echo 'Give enough time for preparing new media, not relying on 'pingpipe' intervals
echo WScript.Sleep 1000
echo Do Until WScript.StdIn.AtEndOfStream
echo Input = WScript.StdIn.ReadLine^(^)
echo If IsNumeric^(Input^) Then
echo Sound.settings.volume = Input
echo ElseIf Open = True Then
echo Open = False
echo Sound.Controls.stop
echo Sound.URL = Input
echo Sound.Controls.play
echo 'Give enough time for preparing new media, not relying on 'pingpipe' intervals
echo WScript.Sleep 1000
echo Else
echo Select Case Trim^(LCase^(Input^)^)
echo Case "quit"
echo Exit Do
echo Case "stop"
echo Sound.Controls.stop
echo Case "pause"
echo Sound.Controls.pause
echo Case "play"
echo Sound.Controls.play
echo Case "replay"
echo Sound.Controls.stop
echo Sound.Controls.play
echo Case "mute"
echo Sound.settings.mute = True
echo Case "unmute"
echo Sound.settings.mute = False
echo Case "open"
echo Open = True
echo Case "%PingPipe%"
echo 'Workaround for StdIn blokcing player from looping media
echo WScript.Sleep 1
echo End Select
echo End If
echo Loop
echo Sound.Controls.stop
echo Sound.close
)>"%VBScriptPlayerApp%"
:: Workaround for CMD %~0 bug
call :getBatFullPath @f0
:: Starting player
start "" /B "%COMSPEC%" /D /C "%@f0%" /LaunchAsyncPipedVbsPlayer
:: Give the player enough time to start
timeout /t 1 /nobreak >nul
del "%VBScriptPlayerApp%" >nul 2>&1
set "PlayerCommand=NONE"
set "QuitMsg=Player Closed."
:: Controller Command Loop
:PlayerCommandPrompt
set "LastCommand=%PlayerCommand%"
:PromptPreserveLastCommand
:: Making sure player is alive
del "%PlayerMutex%" >nul 2>&1
if not exist "%PlayerMutex%" (
set "QuitMsg=Player Closed unexpectedly."
goto :Quit
)
echo,
echo VbsPlayer Command Prompt
echo Valid Commands:
echo [0-100] for volume, mute, unmute, play, pause, replay, stop, open, quit, cls (Clears Screen)
echo,
echo Last Command Sent: %LastCommand%
echo,
set "PlayerCommand="
set /p "PlayerCommand=Enter Command to send to VBS Player>"
if not defined PlayerCommand goto :PromptPreserveLastCommand
if /i "%PlayerCommand%"=="cls" cls & goto :PromptPreserveLastCommand
if /i "%PlayerCommand%"=="open" (
setlocal EnableDelayedExpansion
set "OK="
set "NewMedia="
set /p "NewMedia=Media File (Drag'n'Drop): "
if defined NewMedia (
set ^"NewMedia=!NewMedia:^"=!^"
if exist "!NewMedia!" (
(echo open&echo !NewMedia!)>"!PlayerCommandFile!"
set "OK=1"
)
)
if defined OK (
endlocal
goto :PlayerCommandPrompt
) else (
endlocal
goto :PromptPreserveLastCommand
)
)
(echo %PlayerCommand%)>"%PlayerCommandFile%"
if /i "%PlayerCommand%"=="quit" goto :Quit
goto :PlayerCommandPrompt
:Quit
echo,
echo %QuitMsg%
pause
exit /b
:LaunchAsyncPipedVbsPlayer
del /f "%PlayerCommandFile%" >nul 2>&1
(
(
for /L %%# in (0,0,1) do @(
type "%PlayerCommandFile%" && del "%PlayerCommandFile%" >&2
timeout /t 1 /nobreak >&2
%= This guarantees we will not loop infinitely when the player is closed =%
%= Also used as a workaround for player 'loop music' to function correctly =%
echo %PingPipe% 2>&1
)
)2>nul
)|cscript //nologo "%VBScriptPlayerApp%"
exit /b
:getBatFullPath
set "%~1=%~f0" & exit /b
It reads the file by batch code and sends the data though an established pipe to the VBS
code.
The VBS
code could simply read the file by itself without the need to use pipe, but then I had to embed a larger and more complex VBS
code into the batch file with the echo
commands which would be somewhat counterintuitive unless you decide to keep the VBS
code separate from the batch code.
Or alternatively the VBS
portion can be converted to JS
which enables you to use true BAT/JS
hybrid code without the need to write the JS
part to a separate file each time the script is executed.