; This program requires libmpv-2.dll file in the script directory ; libmpv-2.dll can be downloaded at: https://github.com/shinchiro/mpv-winbuild-cmake/releases ; File name: mpv-dev-x86_64-YYYYMMDD-git-f9190e5.7z ; Reference Manual: https://mpv.io/manual/ Global $hMpvDLL = DllOpen(@ScriptDir & "\libmpv-2.dll") If $hMpvDLL = -1 Then ; Thanks to @Dan_555 for the web-link suggestion Global $iRet = MsgBox(270660, "Welcome to zPlayer", "" & _ "This program requires libmpv-2.dll in the script directory." & @CRLF & _ "Do you want to open the download page in your web browser?" & @CRLF & @CRLF & _ "Download mpv-dev-x86_64-YYYYMMDD-git-f9190e5.7z file, " & @CRLF & _ "extract the .dll and copy it into the script folder." & @CRLF & _ "Then restart this program.") if $iRet = 6 Then ShellExecute ("https://github.com/shinchiro/mpv-winbuild-cmake/releases") EndIf Exit EndIf #Region ;**** Directives created by AutoIt3Wrapper_GUI **** #AutoIt3Wrapper_UseX64=Y #AutoIt3Wrapper_Icon=zPlayer.ico #AutoIt3Wrapper_OutFile=zPlayer-mpv.exe #AutoIt3Wrapper_Res_Fileversion=7.0.0.0 #AutoIt3Wrapper_Res_Description=zPlayer by CYCho #AutoIt3Wrapper_AU3Check_Parameters=-d -w 1 -w 2 -w 3 -w- 4 -w 5 -w 6 -w 7 #EndRegion ;**** Directives created by AutoIt3Wrapper_GUI **** #include #include #include #include #include #include #include #include #include Global $sIconFile = @ScriptDir & "\zPlayer.ico" If @Compiled = 0 And FileExists($sIconFile) = 0 Then zPlayerIcon() HotKeySet("^!{right}", _PlayNext) ; Play next file HotKeySet("^!{left}", _PlayPrevious) ; Play previous file HotKeySet("^!{up}", _VolumeUp) ; Increase application volume level by 5/100 HotKeySet("^!{down}", _VolumeDown) ; Decrease application volume level by 5/100 ; Alternate hotkeys for Ctrl+Alt+Arrows in case they are used by Windows for changing screen orientation HotKeySet("^!{.}", _PlayNext) ; Play next file HotKeySet("^!{,}", _PlayPrevious) ; Play previous file HotKeySet("^!{=}", _VolumeUp) ; Increase application volume level by 5/100 HotKeySet("^!{-}", _VolumeDown) ; Decrease application volume level by 5/100 HotKeySet("^!{END}", _Exit) ; Terminate the program HotKeySet("^!l", _PlaylistDisplay) ; Display playlist HotKeySet("^!{]}", _SpeedUp) ; Increase play speed by 1/10 HotKeySet("^!{[}", _SpeedDown) ; Decrease play speed by 1/10 HotKeySet("^!{BS}", _SpeedRevert) ; Revert speed to 1 HotKeySet("^!p", _PlayPause) ; Toggle play and pause Global $aPos = WinGetPos("[Class:Shell_TrayWnd]") ; 0, 1032, 1920, 48 Global $iClientHeight = $aPos[1] Global $iClientWidth = $aPos[2] Global $sIniFile = @ScriptDir & "\zPlayer-mpv.ini" Global $sFolder = IniRead($sIniFile, "Player", "Folder", @ScriptDir) If StringRight($sFolder, 1) <> "\" Then $sFolder &= "\" Global $sFileTypes = IniRead($sIniFile, "Player", "File Types", "mp3 wav wma ogg ape flac asf mp4 wmv avi mkv flv webM cda") $sFileTypes = "*." & StringReplace($sFileTypes, " ", ";*.") Global $iVolume = IniRead($sIniFile, "Player", "Volume Level", 100) If $iVolume > 100 Then $iVolume = 100 If $iVolume < 20 Then $iVolume = 20 Global $sColorScheme = IniRead($sIniFile, "Player", "Color scheme", "Lavender") Global $iMainIsOnTop = IniRead($sIniFile, "Player", "Always On Top", "Yes") If $iMainIsOnTop = "No" Then $iMainIsOnTop = 0 Else $iMainIsOnTop = 1 EndIf Global $aCoverPos = IniRead($sIniFile, "Player", "Position", "1,0") Global $sKeepAspect = IniRead($sIniFile, "Player", "Keep Aspect", "Yes") Global $sDisplayAlbumArt = IniRead($sIniFile, "Player", "Display Album Art", "Yes") Global $iAudioMode = IniRead($sIconFile, "Player", "Audio Mode", "1") Global $sResumeMode = IniRead($sIniFile, "Resume Playback", "Mode", "Always") Global $iMinTotalLength = IniRead($sIniFile, "Resume Playback", "Minimum Total Length", 300) Global $iMinPlaybackLength = _Max(Number(IniRead($sIniFile, "Resume Playback", "Minimum Playback Length", 100)), 0) ; Variables for main GUI Global $sMainGuiTitle = "zPlayer" Global $iMainGuiWidth = 320 Global $iMainGuiHeight = 73 Global $iTitlePosX = 5 Global $iTitlePosY = 5 Global $iSliderPosX = 40 Global $iProgBarWidth = 10 Global $iSliderLength = $iMainGuiWidth-$iSliderPosX*2-$iProgBarWidth Global $sFontName = "Arial" Global $hMain = GUICreate($sMainGuiTitle, $iMainGuiWidth, $iMainGuiHeight, -2, 0) ; Main GUI GUISetIcon($sIconFile) GUISetFont(10, 400, 0, $sFontName, $hMain) Global $idCurrentPos = GUICtrlCreateLabel("00.00", 0, 25, 39, 15, $SS_RIGHT) ; Current media position GUICtrlSetTip(-1, "Open/Close A-B Repeat Settings", "", 1, 1) Global $idSlider = GUICtrlCreateLabel("", $iSliderPosX, 27, $iSliderLength+$iProgBarWidth, 12) ; Slider GUICtrlSetBkColor(-1, 0xD0D0D0) Global $idRepeatAB = GUICtrlCreateLabel("", $iSliderPosX, 27, 10, 12) ; Pink bar to indicate A-B repeat position in slider GUICtrlSetBkColor(-1, 0xFFB3E6) GUICtrlSetState(-1, $GUI_HIDE) Global $idProgBar = GUICtrlCreateLabel("", $iSliderPosX, 27, $iProgBarWidth, 12) ; Progress bar GUICtrlSetBkColor(-1, 0x656565) Global $idLength = GUICtrlCreateLabel("00.00", $iMainGuiWidth-39, 25, 39, 15, $SS_LEFT) ; Media length GUICtrlSetTip(-1, "Open/Close File Repeat Settings", "", 1, 1) Global $idPlay = GUICtrlCreateLabel("β–Ά", 68, 47, 16, 18, BitOR($SS_CENTER, $SS_CENTERIMAGE)) ; Pause/Play GUICtrlSetFont($idPlay, 17) GUICtrlSetColor(-1, 0x656565) Global $idPrevious = GUICtrlCreateLabel("β—€", 87, 48, 14, 18, BitOR($SS_CENTER, $SS_CENTERIMAGE)) ; Play previous file GUICtrlSetFont(-1, 13) GUICtrlSetColor(-1, 0x656565) Global $idRepeat = GUICtrlCreateLabel("U", 101, 48, 14, 20, BitOR($SS_CENTER, $SS_CENTERIMAGE)) ; Repeat(0)/No repeat(U) GUICtrlSetFont(-1, 10, 900) GUICtrlSetColor(-1, 0x656565) Global $idNext = GUICtrlCreateLabel("β–Ά", 115, 48, 14, 18, BitOR($SS_CENTER, $SS_CENTERIMAGE)) ; Play next file GUICtrlSetFont(-1, 13) GUICtrlSetColor(-1, 0x656565) Global $idSpeaker = GUICtrlCreateLabel("πŸ”Š", 132, 47, 16, 18, BitOR($SS_CENTER, $SS_CENTERIMAGE)) ; Audio on/off GUICtrlSetFont(-1, 15, 400) GUICtrlSetColor(-1, 0x656565) Global $idUp = GUICtrlCreateLabel("β–²", 147, 42, 15, 15, BitOR($SS_CENTER, $SS_CENTERIMAGE)) ; Volume up GUICtrlSetFont(-1, 10) GUICtrlSetColor(-1, 0x656565) GUICtrlSetTip(-1, $iVolume) Global $idDown = GUICtrlCreateLabel("β–Ό", 147, 56, 15, 15, BitOR($SS_CENTER, $SS_CENTERIMAGE)) ; Volume down GUICtrlSetFont(-1, 10) GUICtrlSetColor(-1, 0x656565) GUICtrlSetTip(-1, $iVolume) Global $idShuffle = GUICtrlCreateButton("Shuffle", 5, 45, 50, 24) ; Play at shuffled/sorted order GUICtrlSetData(-1, "Shuffle") Global $idFile = GUICtrlCreateButton("Load Files", 172, 45, 69, 24) ; Load files Global $idFolder = GUICtrlCreateButton("Load Folder", 241, 45, 75, 24) ; Load/Change folder Global $idVolume = GUICtrlCreateButton($iVolume, 163, 33, 25, 25) GUICtrlSetState(-1, $GUI_HIDE) #Region ; Cover the title bar of $hMain with $hCover $aPos = WinGetPos($hMain) Global $iMainBorderWidth = ($aPos[2]-$iMainGuiWidth)/2 ; 3 in Win 10/11 Global $iMainBarHeight = $aPos[3] - $iMainBorderWidth - $iMainGuiHeight ; 26 Global $hCover = GUICreate("", $iMainGuiWidth, $iMainBarHeight+1, 1, 0, $WS_POPUP, -1, $hMain) ; When the parent($hMain) is minimized/restored, the popup child(hCover) gets hidden/shown GUICtrlCreateLabel("", 0, 0, $iMainGuiWidth, 1) ; Cover the top border of $hMain GUICtrlSetBkColor(-1, 0xB6B6B6) GUICtrlCreateIcon($sIconFile, -1, 5, 6, 16, 16) GUICtrlCreateLabel($sMainGuiTitle, 25, 6, 60, 20) GUICtrlSetFont(-1, 10, 400, 0, $sFontName) Global $idCloseX = GUICtrlCreateLabel("X", $iMainGuiWidth-35, 1, 35, $iMainBarHeight, BitOR($SS_CENTER, $SS_CENTERIMAGE)) ; _Exit() GUICtrlSetFont(-1, 14, 600, 0, $sFontName) GUICtrlSetColor(-1, 0x404040) Global $idMinimize = GUICtrlCreateLabel("―", $iMainGuiWidth-65, 3, 30, $iMainBarHeight-5, BitOR($SS_CENTER, $SS_CENTERIMAGE)); Minimize - ChrW(8213) GUICtrlSetFont(-1, 11, 900, 0, $sFontName) Global $idOptions = GUICtrlCreateButton(ChrW(9881), $iMainGuiWidth-96, 1, 29, $iMainBarHeight-1) ; _Options() "βš™" GUICtrlSetFont(-1, 14, 400, 0, $sFontName) Global $idSetOnTop = GUICtrlCreateButton("πŸ”", $iMainGuiWidth-125, 1, 29, $iMainBarHeight-1) ; _SetMainOnTop() "πŸ”πŸ”™" GUICtrlSetFont(-1, 14, 400, 0, $sFontName) Global $idQuestion = GUICtrlCreateButton("?", $iMainGuiWidth-154, 1, 29, $iMainBarHeight-1) ; _Help() GUICtrlSetFont(-1, 14, 400, 0, $sFontName) If @OSVersion = "WIN_11" Then ; Create round corners for $hCover Global $hRgn = _WinAPI_CreateRoundRectRgn(0, 0, $iMainGuiWidth+1, 40, 13, 13) _WinAPI_SetWindowRgn($hCover, $hRgn) _WinAPI_DeleteObject($hRgn) EndIf #EndRegion ; Cover the title bar of $hMain with $hCover ; The main window inherits its position and 'Always On Top' attribute from the last session $aCoverPos = StringSplit($aCoverPos, ",", 2) If UBound($aCoverPos) = 2 Then If $aCoverPos[0] < 1 Then $aCoverPos[0] = 1 ElseIf $aCoverPos[0] > $iClientWidth - $iMainGuiWidth -1 Then $aCoverPos[0] = $iClientWidth - $iMainGuiWidth - 1 EndIf If $aCoverPos[1] < 0 Then $aCoverPos[1] = 0 ElseIf $aCoverPos[1] > $iClientHeight - $iMainGuiHeight - $iMainBarHeight Then $aCoverPos[1] = $iClientHeight - $iMainGuiHeight - $iMainBarHeight EndIf Else ReDim $aCoverPos[2] $aCoverPos[0] = 1 $aCoverPos[1] = 0 EndIf ; Create GUI to parent video Global $iVideoWidth = Int($iClientWidth/3*2) Global $iVideoHeight = Int($iVideoWidth*9/16) Global $aVideoDefPos[4] Global $hVideoGUI = GUICreate("AutoIt 4K MPV Player", $iVideoWidth, $iVideoHeight, -1, -1, $WS_OVERLAPPEDWINDOW) GUISetIcon($sIconFile) Global $idAspect_Hotkey = GUICtrlCreateDummy() ; Press "a" key to keep aspect on or off Global $idShot_Hotkey = GUICtrlCreateDummy() ; Press "s" key to take screenshot Global $idF11_Hotkey = GUICtrlCreateDummy() ; Press "F11" key to turn full screen mode on or off Global $idEsc_Hotkey = GUICtrlCreateDummy() ; Press "Esc" key to turn full screen mode off Global $aAccel[4][2] = [["a", $idAspect_Hotkey], ["s", $idShot_Hotkey], ["{F11}", $idF11_Hotkey], ["{ESC}", $idEsc_Hotkey]] GUISetAccelerators($aAccel, $hVideoGUI) ; These hotkeys work only when $hVideoGUI is active ; Global variables for window metrics $aPos = WinGetPos($hVideoGUI) Global $iBorderWidth = ($aPos[2]-$iVideoWidth)/2 ; 8 Global $iTitleHeight = $aPos[3]-$iVideoHeight-$iBorderWidth ; 31 Global $iMaximizedTitleHeight ; 23 ; Create video controls at the bottom of $hVideoGUI Global $iVCHeight = 60 Global $iSliderLength2, $iVCLeft, $iVCRight, $iVCBottom, $iVCTop Global $hVCGui, $idSlider2, $idProgBar2, $idRepeatAB2, $idCurrentPos2, $idLength2, $idExit, $idPlay2 Global $idPrevious2, $idRepeat2, $idNext2, $idSpeaker2, $idUp2, $idDown2, $idVolume2, $idFullScreen, $idSetDefault Global $iRepeatCurrentFile, $iMute, $iMediaLength, $iFullScreen, $iMaximized _VCCreate() Global $hLoading = GUICreate("", 600, 50, -1, -1, $WS_POPUPWINDOW, $WS_EX_TOPMOST) GUISetFont(10, 0, 0, "Arial Bold", $hLoading) Global $idLoading = GUICtrlCreateLabel("", 10, 18, 580, 18, BitOR($SS_NOPREFIX, $SS_CENTER)) ; Create a child GUI for scrolling the media title. Earlier creation may cause scrolling malfunction in high-speed computers. Global $hChildGUI = GUICreate("", $iMainGuiWidth-$iTitlePosX*2, 18, $iTitlePosX, $iTitlePosY, $WS_CHILD, $WS_EX_COMPOSITED, $hMain) GUISetFont(10, 400, 0, $sFontName, $hChildGUI) Global $idTitle = GUICtrlCreateLabel("Media title", 0, 0, 2000, 18, BitOR($SS_NOPREFIX, $SS_LEFTNOWORDWRAP)) ; Media title GUICtrlSetTip(-1, "Open/Close Playlist", "", 1, 1) If $iMainIsOnTop = 1 Then WinSetOnTop($hMain, "", 1) GUICtrlSetData($idSetOnTop, "πŸ”™") EndIf ; Global variables for playback Global $aGUIMsg Global $sGUIMsg Global $aFiles Global $aItems[1][3] Global $aColors[1][3] Global $bNextAppended Global $sCurrentFile Global $sFile Global $sPath Global $sTitle Global $iExecute Global $iFolderLoaded Global $iIndex Global $iMainIsMinimized Global $iOptions Global $iPaused Global $iPlaying Global $iPlaylist Global $iProperties Global $iResumePosition Global $iShuffled Global $iVolumeStep Global $hTopWnd Global $tText = DllStructCreate( "wchar[256]" ) ; To be used by WM_NOTIFY() for virtual listview Global $hUser32DLL = DllOpen("user32.dll") ; _IsPressed(), SendMessageW, GetDoubleClickTime If $hUser32DLL = -1 Then MsgBox($MB_OK, "DLL Open Failure", "user32.dll could not be opened!") _Exit() EndIf Global $hWinmmDLL ; winmm.dll to be opened in _PlayCD() Global $oShellApp = ObjCreate("shell.application") ; GetDetailsOf() ; global variables for marquee effect Global $iTitleWidth Global $iMarqueeInterval = 40 Global $iMarquee Global $iTitlePosX2 Global $sGap = " " ; Global variables for audio CD Global $sCDLabel, $aTracks, $iTrack, $iTrackPos ; Global variables for file properties Global $iLenColNumber ; Coulmn number for media length property (27 for Windows 10/11) Global $aFileInfo[12][2] Global $sFileName, $sDir, $oDir, $oFile Global $sCurrentFileProperties Global $i4K, $h4KApp ; Global variables for _GetLength() adlib function Global $iAllDone = -1 Global $iDoing Global $iTitleColored Global $iItemNo ; Global variables to differentiate function calls by control clicks from those by hotkeys Global $iFilePropertiesFrom Global $iInternetSearchFrom Global $sLoadFolderFrom Global $sPlaylistShowFrom ; Create Help window in zPlayerHelp() Global $hHelp, $helpEdit WinMove($hCover, "", $aCoverPos[0], $aCoverPos[1]) WinMove($hMain, "", $aCoverPos[0]-$iMainBorderWidth, $aCoverPos[1]) GUISetState(@SW_SHOW, $hCover) GUISetState(@SW_SHOW, $hMain) GUISetState(@SW_SHOW, $hChildGUI) Global $aPlaylist, $hStartLoading, $bIsLoading ; Create playlist window Global $iListWidth = 485 ; initial width of listview window Global $iListHeight = @DesktopHeight/2 ; initial height of listview window Global $iListMinimumWidth = $iListWidth ; minimum width of listview window Global $iViewHeight = $iListHeight-35 ; initial height of listview control, to be defined in _PlaylistCreate() Global $iCharacterWidth = 6 ; average character width in listview window Global $iHeaderHeight ; heights of listview header and items to be defined in _PlaylistLoad_1() Global $iItemHeight ; height of a listview item Global $iColumn1Width ; width of the 1st column Global $iDoubleClicked ; 1 if a playlist item is double-clicked Global $iRescanned ; 1 if the folder is rescanned to update the playlist ; Controls in $hPlaylist Global $hPlaylist, $ctrlView, $ctrlSearchBox, $ctrlFind, $ctrlNext, $ctrlRevert, $ctrlRescan, $ctrlReshuffle Global $idContextmenu, $idSubmenuPlay, $idSubmenuFileInfo, $idSubmenuSearch, $idSubmenuFolder, $idSubmenuRemove, $idSubmenuMove Global $iStartPos, $iAspect Global $iPlayPrevious, $iCurrentPos, $iClickCount, $isAudio, $isVideo Global $iVideoRefresh, $iCycleMute Global $iLastTime, $sNewTime, $tDouble, $tSeconds, $iMinutes, $iSeconds, $iLastX, $iLastX2, $iNewX, $iNewX2, $iSlider Global $iProgressWaitTime = 100 ; a shorter time may result in program crash due to command overlaps Global $iDoubleclickTime = DllCall($hUser32DLL, 'uint', 'GetDoubleClickTime')[0] Global $pHandle, $sVideoCardSpec, $iTrackCount _mpv_InitializeEngine() If $iStartPos > 0 Then ; when resuming playback from preious session's last position _mpv_set_option_string($pHandle, "start", String($iStartPos)) _AudioModeSet($iAudioMode, True) ; fade-in ; This will be reset to normal in main loop when the first file is finished EndIf GUIRegisterMsg($WM_WINDOWPOSCHANGED, "WM_WINDOWPOSCHANGED") ; To sync movements of $hVideoGUI and $hVCGui Global $bIsFirstFile = True _PlaylistCreate() While 1 ; Main loop $aGUIMsg = GUIGetMsg(1) $sGUIMsg = $aGUIMsg[0] Switch $aGUIMsg[1] Case $hCover Switch $sGUIMsg Case $idCloseX _Exit() Case $idMinimize AdlibUnRegister("_SaveCoverPos") GUISetState(@SW_MINIMIZE, $hMain) $iMainIsMinimized = 1 While _IsPressed("01", $hUser32DLL) Sleep(10) WEnd Case $idOptions ; _Options() Case $idSetOnTop _SetMainOnTop() Case $idQuestion ; _Help() Case $GUI_EVENT_PRIMARYDOWN ; Click and drag $hCover. WM_WINDOWPOSCHANGED() will move $hMain in sync with $hCover. DllCall($hUser32DLL, "int", "SendMessageW", "hwnd", $hCover, "uint", $WM_NCLBUTTONDOWN, "wparam", $HTCAPTION, "lparam", 0) EndSwitch Case $hVideoGUI Switch $sGuiMsg Case $GUI_EVENT_CLOSE _PlayNext() Case $GUI_EVENT_MAXIMIZE $iMaximized = 1 If $iMaximizedTitleHeight = 0 Then Local $aPos1 = WinGetClientSize($hVideoGUI) $iMaximizedTitleHeight = $iClientHeight-$aPos1[1] EndIf Case $GUI_EVENT_RESTORE $iMaximized = 0 Case $GUI_EVENT_RESIZED If $iFullScreen+$iMaximized = 0 And $sKeepAspect = "Yes" Then _VideoResize() EndIf Case $GUI_EVENT_PRIMARYDOWN _VideoClicked() Case $idAspect_Hotkey _AspectToggler() Case $idShot_Hotkey Local $sTimestamp = @YEAR & @MON & @MDAY & "_" & @HOUR & @MIN & @SEC Local $sFilePath = @ScriptDir & "\Shot_" & $sTimestamp & ".jpg" _mpv_command($pHandle, "screenshot-to-file", $sFilePath) _mpv_command($pHandle, "show-text", "Screenshot Saved", "2000") Case $idF11_Hotkey _FullScreen() Case $idEsc_Hotkey If $iFullScreen = 1 Then _FullScreen() EndIf EndSwitch Case $hMain, $hCover, $hVCGui, $hChildGUI Switch $sGuiMsg Case $idDown, $idDown2 _VolumeDown() Case $idUp, $idUp2 _VolumeUp() Case $idPlay, $idPlay2 _PlayPause() Case $idPrevious, $idPrevious2 _PlayPrevious() Case $idNext, $idNext2 _PlayNext() Case $idExit _Exit() Case $idSpeaker, $idSpeaker2 _mpv_command($pHandle, "cycle", "mute") If $iMute = 0 Then GUICtrlSetData($idSpeaker, "πŸ”‡") GUICtrlSetData($idSpeaker2, "πŸ”‡") _Audio_Action("SetMute", True) $iMute = 1 Else GUICtrlSetData($idSpeaker, "πŸ”Š") GUICtrlSetData($idSpeaker2, "πŸ”Š") _Audio_MasterVolume("UnMute") _Audio_Action("SetMute", False) $iMute = 0 EndIf Case $idRepeat, $idRepeat2 _RepeatCurrentFile() Case $idFullScreen _FullScreen() Case $idSetDefault If $iFullScreen+$iMaximized = 0 Then If $aVideoDefPos[2] = 0 Then GUICtrlSetColor($idSetDefault, 0xFF0055) $aVideoDefPos = WinGetPos($hVideoGUI) GUICtrlSetTip($idSetDefault, "Unset your default size and position") Else GUICtrlSetColor($idSetDefault, 0x000000) Local $w, $h, $x, $y $w = ($isVideo = 1) ? $iVideoWidth : 500 If $sKeepAspect = "Yes" Then $h = Round($w/$iAspect) If $h > $iClientHeight-$iTitleHeight Then $h = $iClientHeight-$iTitleHeight $w = Round($h*$iAspect) EndIf EndIf If $isVideo <> 1 Or $sKeepAspect = "No" Then $h = 500 EndIf $w += $iBorderWidth*2 $h += $iTitleHeight+$iBorderWidth $x = ($iClientWidth-$w)/2 $y = ($iClientHeight-$h)/2 WinMove($hVideoGUI, "", $x, $y, $w, $h) $aVideoDefPos[0] = 0 $aVideoDefPos[1] = 0 $aVideoDefPos[2] = 0 $aVideoDefPos[3] = 0 GUICtrlSetTip($idSetDefault, "Set this size and position as your default") EndIf EndIf While _IsPressed("01", $hUser32DLL) Sleep(10) WEnd Case $idSlider, $idSlider2 _Slider($sGuiMsg) Case $idTitle _PlaylistDisplay() Case $idShuffle _Shuffle_MPV() Case $idFile If Not $bIsLoading Then Local $iOldFolder, $aOldList, $iOldIndex If IsArray($aPlaylist) Then $iOldFolder = $sFolder $aOldList = $aPlaylist $iOldIndex = $iIndex EndIf $aPlaylist = 0 _PlaylistCreate() If IsArray($aPlaylist) Then _mpv_command($pHandle, "stop") ElseIf IsArray($aOldList) Then $sFolder = $iOldFolder $aPlaylist = $aOldList $iIndex = $iOldIndex EndIf EndIf EndSwitch EndSwitch If IsArray($aPlaylist) And $aPlaylist[0] > 0 Then _mpv_EventHandler() ; includes _mpv_EndOfFile(), which includes _PlayFile() EndIf WEnd ; end of main loop Func _ActivateSpeakers() ; Adlib function to keep the speakers continuously active during pause Beep(1, 1) ; once in 30 seconds EndFunc ; _ActivatSpeakers Func _AspectToggler() ; Called by "a" hotkey Local $sMsg If $sKeepAspect = "Yes" Then $sKeepAspect = "No" $sMsg = "Keep aspect: No" Else $sKeepAspect = "Yes" _VideoResize() $sMsg = "Keep aspect: Yes" EndIf _mpv_set_property($pHandle, "keepaspect", StringLower($sKeepAspect), "string") _mpv_command($pHandle, "show-text", $sMsg) EndFunc ; _AspectToggler Func _Audio_Action($action, $value) ; Each action takes about 6 milliseconds ; https://www.autoitscript.com/forum/topic/211638-how-can-i-getset-mute-state-of-windows-volume-mixer/?do=findComment&comment=1531412 Local $oIAudioSessionManager2 = _Audio_GetIAudioSessionManager2() If Not IsObj($oIAudioSessionManager2) Then Return Local Const $sIID_IAudioSessionEnumerator = "{e2f5bb11-0570-40ca-acdd-3aa01277dee8}" Local Const $sTagIAudioSessionEnumerator = "GetCount hresult(int*);GetSession hresult(int;ptr*)" ;Local Const $sIID_IAudioSessionControl = "{f4b1a599-7266-4319-a8ca-e70acb11e8cd}" Local Const $sTagIAudioSessionControl = "GetState hresult(int*);GetDisplayName hresult(ptr);" & _ "SetDisplayName hresult(wstr);GetIconPath hresult(ptr);" & _ "SetIconPath hresult(wstr;ptr);GetGroupingParam hresult(ptr*);" & _ "SetGroupingParam hresult(ptr;ptr);RegisterAudioSessionNotification hresult(ptr);" & _ "UnregisterAudioSessionNotification hresult(ptr);" Local Const $sIID_IAudioSessionControl2 = "{bfb7ff88-7239-4fc9-8fa2-07c950be9c6d}" Local Const $sTagIAudioSessionControl2 = $sTagIAudioSessionControl & "GetSessionIdentifier hresult(ptr)" & _ "GetSessionInstanceIdentifier hresult(ptr);" & _ "GetProcessId hresult(dword*);IsSystemSoundsSession hresult();" & _ "SetDuckingPreferences hresult(bool);" ; http://answers.awesomium.com/questions/3398/controlling-the-sound-using-pinvoke-the-volume-mix.html Local Const $sIID_ISimpleAudioVolume = "{87CE5498-68D6-44E5-9215-6DA47EF883D8}" Local Const $sTagISimpleAudioVolume = _ "SetMasterVolume hresult(float;ptr);" & _ "GetMasterVolume hresult(float*);" & _ "SetMute hresult(int;ptr);" & _ "GetMute hresult(int*)" Local $pIAudioSessionEnumerator, $oIAudioSessionEnumerator If $oIAudioSessionManager2.GetSessionEnumerator($pIAudioSessionEnumerator) < 0 Then Return $oIAudioSessionEnumerator = ObjCreateInterface($pIAudioSessionEnumerator, $sIID_IAudioSessionEnumerator, $sTagIAudioSessionEnumerator) If Not IsObj($oIAudioSessionEnumerator) Then Return SetError(1) Local $i, $nSessions, $pIAudioSessionControl2, $oIAudioSessionControl2 Local $ProcessID, $oISimpleAudioVolume Local $error = 1 If $oIAudioSessionEnumerator.GetCount($nSessions) >= 0 Then For $i = 0 To $nSessions - 1 If $oIAudioSessionEnumerator.GetSession($i, $pIAudioSessionControl2) >= 0 Then $oIAudioSessionControl2 = ObjCreateInterface($pIAudioSessionControl2, $sIID_IAudioSessionControl2, $sTagIAudioSessionControl2) If @error Then ContinueLoop $oIAudioSessionControl2.GetProcessId($ProcessID) If $ProcessID = @AutoItPID Then $oISimpleAudioVolume = ObjCreateInterface($pIAudioSessionControl2, $sIID_ISimpleAudioVolume, $sTagISimpleAudioVolume) If @error Then ContinueLoop $oIAudioSessionControl2.AddRef() ;stabilize Switch $action Case "SetMute" ; Run(@SystemDir & "\sndvol.exe") ; https://learn.microsoft.com/en-us/windows/win32/api/audioclient/nf-audioclient-isimpleaudiovolume-setmute If $oISimpleAudioVolume.SetMute($value, Null) >= 0 Then $error = 0 ExitLoop EndIf Case "GetMute" ; https://learn.microsoft.com/en-us/windows/win32/api/audioclient/nf-audioclient-isimpleaudiovolume-getmute If $oISimpleAudioVolume.GetMute($value) >= 0 Then $error = 0 ExitLoop EndIf Case "SetVolume" If $oISimpleAudioVolume.SetMasterVolume($value, 0) >= 0 Then $error = 0 ExitLoop EndIf Case "GetVolume" If $oISimpleAudioVolume.GetMasterVolume($value) >= 0 Then $error = 0 ExitLoop EndIf EndSwitch EndIf EndIf Next EndIf $oISimpleAudioVolume = 0 $oIAudioSessionControl2 = 0 $oIAudioSessionEnumerator = 0 Return SetError($error, 0, $value) EndFunc ; _Audio_Action Func _Audio_GetIAudioSessionManager2() ; Used in _Audio_Action() Local Const $sCLSID_MMDeviceEnumerator = "{BCDE0395-E52F-467C-8E3D-C4579291692E}" Local Const $sIID_IMMDeviceEnumerator = "{A95664D2-9614-4F35-A746-DE8DB63617E6}" Local Const $sTagIMMDeviceEnumerator = _ "EnumAudioEndpoints hresult(int;dword;ptr*);" & _ "GetDefaultAudioEndpoint hresult(int;int;ptr*);" & _ "GetDevice hresult(wstr;ptr*);" & _ "RegisterEndpointNotificationCallback hresult(ptr);" & _ "UnregisterEndpointNotificationCallback hresult(ptr)" Local Const $sIID_IMMDevice = "{D666063F-1587-4E43-81F1-B948E807363F}" Local Const $sTagIMMDevice = _ "Activate hresult(struct*;dword;ptr;ptr*);" & _ "OpenPropertyStore hresult(dword;ptr*);" & _ "GetId hresult(wstr*);" & _ "GetState hresult(dword*)" Local Const $sIID_IAudioSessionManager2 = "{77aa99a0-1bd6-484f-8bc7-2c654c9a9b6f}" Local Const $sTagIAudioSessionManager = "GetAudioSessionControl hresult(ptr;dword;ptr*);" & _ "GetSimpleAudioVolume hresult(ptr;dword;ptr*);" Local Const $sTagIAudioSessionManager2 = $sTagIAudioSessionManager & "GetSessionEnumerator hresult(ptr*);" & _ "RegisterSessionNotification hresult(ptr);" & _ "UnregisterSessionNotification hresult(ptr);" & _ "RegisterDuckNotification hresult(wstr;ptr);" & _ "UnregisterDuckNotification hresult(ptr)" Local $_oIAudioSessionManager2 = 0 Local Const $eMultimedia = 1, $CLSCTX_INPROC_SERVER = 0x01 Local $pIMMDevice, $oMMDevice, $pIAudioSessionManager2 Local $oMMDeviceEnumerator = ObjCreateInterface($sCLSID_MMDeviceEnumerator, $sIID_IMMDeviceEnumerator, $sTagIMMDeviceEnumerator) If IsObj($oMMDeviceEnumerator) Then If $oMMDeviceEnumerator.GetDefaultAudioEndpoint(0, $eMultimedia, $pIMMDevice) >= 0 Then $oMMDevice = ObjCreateInterface($pIMMDevice, $sIID_IMMDevice, $sTagIMMDevice) If IsObj($oMMDevice) Then Local $tGUID = DllStructCreate("ulong Data1;ushort Data2;ushort Data3;byte Data4[8]") DllCall("ole32.dll", "long", "CLSIDFromString", "wstr", $sIID_IAudioSessionManager2, "struct*", $tGUID) If $oMMDevice.Activate($tGUID, $CLSCTX_INPROC_SERVER, 0, $pIAudioSessionManager2) >= 0 Then $_oIAudioSessionManager2 = ObjCreateInterface($pIAudioSessionManager2, $sIID_IAudioSessionManager2, $sTagIAudioSessionManager2) EndIf $oMMDevice = 0 EndIf EndIf $oMMDeviceEnumerator = 0 EndIf If IsObj($_oIAudioSessionManager2) Then Return $_oIAudioSessionManager2 EndIf EndFunc ; _Audio_GetIAudioSessionManager2 Func _Audio_MasterVolume($action) ; To sync zPlayer's mute state with the audio device's mute state ; https://www.autoitscript.com/forum/topic/84834-control-vista-master-volume/ Local Const $CLSID_MMDeviceEnumerator = "{BCDE0395-E52F-467C-8E3D-C4579291692E}" Local Const $IID_IMMDeviceEnumerator = "{A95664D2-9614-4F35-A746-DE8DB63617E6}" Local Const $tagIMMDeviceEnumerator = _ "EnumAudioEndpoints hresult(int;dword;ptr*);" & _ "GetDefaultAudioEndpoint hresult(int;int;ptr*);" & _ "GetDevice hresult(wstr;ptr*);" & _ "RegisterEndpointNotificationCallback hresult(ptr);" & _ "UnregisterEndpointNotificationCallback hresult(ptr)" Local Const $IID_IMMDevice = "{D666063F-1587-4E43-81F1-B948E807363F}" Local Const $tagIMMDevice = _ "Activate hresult(struct*;dword;ptr;ptr*);" & _ "OpenPropertyStore hresult(dword;ptr*);" & _ "GetId hresult(wstr*);" & _ "GetState hresult(dword*)" Local Const $eRender = 0, $eConsole = 0 Local Const $IID_IAudioEndpointVolume = "{5CDF2C82-841E-4546-9722-0CF74078229A}" Local Const $tagIAudioEndpointVolume = _ "RegisterControlChangeNotify hresult(ptr);" & _ "UnregisterControlChangeNotify hresult(ptr);" & _ "GetChannelCount hresult(uint*);" & _ "SetMasterVolumeLevel hresult(float;ptr);" & _ "SetMasterVolumeLevelScalar hresult(float;ptr);" & _ "GetMasterVolumeLevel hresult(float*);" & _ "GetMasterVolumeLevelScalar hresult(float*);" & _ "SetChannelVolumeLevel hresult(uint;float;ptr);" & _ "SetChannelVolumeLevelScalar hresult(uint;float;ptr);" & _ "GetChannelVolumeLevel hresult(uint;float*);" & _ "GetChannelVolumeLevelScalar hresult(uint;float*);" & _ "SetMute hresult(int;ptr);" & _ "GetMute hresult(int*);" & _ "GetVolumeStepInfo hresult(uint*;uint*);" & _ "VolumeStepUp hresult(ptr);" & _ "VolumeStepDown hresult(ptr);" & _ "QueryHardwareSupport hresult(dword*);" & _ "GetVolumeRange hresult(float*;float*;float*)" Local $oIAudioEndpointVolume = 0;, $err = 1 ; create device enumerator interface Local $oDevEnum = ObjCreateInterface($CLSID_MMDeviceEnumerator, $IID_IMMDeviceEnumerator, $tagIMMDeviceEnumerator) If IsObj($oDevEnum) Then ; get default audio endpoint interface pointer Local $pDefaultDevice = 0 If $oDevEnum.GetDefaultAudioEndpoint($eRender, $eConsole, $pDefaultDevice) >= 0 Then ; create default audio endpoint interface Local $oIMMDevice = ObjCreateInterface($pDefaultDevice, $IID_IMMDevice, $tagIMMDevice) If IsObj($oIMMDevice) Then ; get endpoint volume interface pointer Local $pEndpointVolume = 0 Local $tGUID = DllStructCreate("ulong Data1;ushort Data2;ushort Data3;byte Data4[8]") DllCall("ole32.dll", "long", "CLSIDFromString", "wstr", $IID_IAudioEndpointVolume, "struct*", $tGUID) If $oIMMDevice.Activate($tGUID, 1, 0, $pEndpointVolume) >= 0 Then ; create endpoint volume interface $oIAudioEndpointVolume = ObjCreateInterface($pEndpointVolume, $IID_IAudioEndpointVolume, $tagIAudioEndpointVolume) EndIf $oIMMDevice = 0 EndIf EndIf $oDevEnum = 0 EndIf If $action = "GetMute" Then ; Get mute state of the audio device Local $bMute = 0 $oIAudioEndpointVolume.GetMute($bMute) Return $bMute ; 0 - not muted, 1 - muted ElseIf $action = "UnMute" Then ; Set mute state of the audio device $oIAudioEndpointVolume.SetMute(0, 0) ; 1st parameter: 1 to mute, 0 to unmute EndIf EndFunc ; _Audio_MasterVolume Func _AudioModeSet($iModeIndex, $bFadeIn = False) Local $sAF = "" Switch $iModeIndex Case 1 ; Normal $sAF = "" Case 2 ; Deep Bass $sAF = "lowshelf=f=150:g=12" Case 3 ; Crystal Clear $sAF = "highshelf=f=3000:g=10" Case 4 ; Pop/Rock $sAF = "lowshelf=f=100:g=6,highshelf=f=8000:g=6" Case 5 ; Cinema Voice $sAF = "lowshelf=f=150:g=8,loudnorm=I=-12" Case 6 ; Midnight $sAF = "loudnorm=I=-12,dynaudnorm=f=150:g=10" Case 7 ; Speech/Podcast $sAF = "highpass=f=200,equalizer=f=2000:width_type=h:width=1000:g=5" Case Else $sAF = "" EndSwitch ; For fade-in of 4 seconds when resuming playback from previous session If $bFadeIn Then If $sAF <> "" Then $sAF &= "," $sAF &= "afade=t=in:ss=0:d=5" EndIf ;~ ; When changing the mode, you can reduce sound level by 3 dB ;~ If $iModeIndex > 1 Then ;~ $sAF &= ",volume=-3dB" ;~ EndIf _mpv_set_property($pHandle, "af", $sAF, "str") EndFunc ; _AudioModeSet Func _Exit() ; Terminates the program (Click "🞭" in $hVCGui or pres Ctrl+Alt+End) GUIRegisterMsg($WM_WINDOWPOSCHANGED, "") If IsDeclared("pHandle") Then _mpv_command($pHandle, "stop") DllCall($hMpvDLL, "void:cdecl", "mpv_terminate_destroy", "ptr", $pHandle) EndIf If StringInStr(".cda .mid", StringRight($sFile, 4)) Then _mciSendString("close myMedia") EndIf DllClose($hMpvDLL) DllClose($hWinmmDLL) DllClose($hUser32DLL) GUIDelete($hMain) GUIDelete($hVideoGUI) GUIDelete($hLoading) Exit EndFunc ; _Exit Func _FullScreen() ; Video in full screen mode on/off (Click ⇔/⇙ $hVCGui) While _IsPressed("01", $hUser32DLL) Sleep(50) WEnd GUISetState(@SW_HIDE, $hVCGui) If $iFullScreen = 0 Then $iFullScreen = 1 GUICtrlSetData($idFullScreen, "⇙") GUISetStyle($WS_POPUP, -1, $hVideoGUI) WinMove($hVideoGUI, "", 0, 0, @DesktopWidth, @DesktopHeight) WinSetOnTop($hVideoGUI, "", 1) GUICtrlSetData($idSlider2, " " & $sTitle) Else $iFullScreen = 0 $iMaximized = 0 GUICtrlSetData($idFullScreen, "⇔") GUISetStyle($WS_OVERLAPPEDWINDOW, -1, $hVideoGUI) WinSetOnTop($hVideoGUI, "", 0) GUICtrlSetData($idSlider2, "") If $isVideo = 1 Or $isAudio = 2 Then ; $isVideo, $isAudio, $iVideoWidth and $iAspect defined in _PlayMPV() Local $x, $y, $w, $h If $isVideo = 1 Then $w = $iVideoWidth Else $w = 500 EndIf If $aVideoDefPos[2] > 0 Then $w = $aVideoDefPos[2] - $iBorderWidth * 2 EndIf If $sKeepAspect = "Yes" Then $h = Int($w/$iAspect) If $h > $iClientHeight-$iTitleHeight-$iBorderWidth Then $h = $iClientHeight-$iTitleHeight-$iBorderWidth $w = Int($h*$iAspect) EndIf Else $h = _Min($w, $iClientHeight) EndIf If $aVideoDefPos[2] = 0 Then $x = ($iClientWidth-$w-$iBorderWidth*2)/2 $y = ($iClientHeight-$h-$iTitleHeight-$iBorderWidth)/2 Else $x = $aVideoDefPos[0] $y = $aVideoDefPos[1] EndIf $w += $iBorderWidth*2 $h += $iTitleHeight+$iBorderWidth WinMove($hVideoGUI, "", $x, $y, $w, $h) EndIf EndIf EndFunc ; _FullScreen Func _GetVideoCardSpec() ; Get video card spec, to be used for setting hardware acceleration options Local $oWMIService = ObjGet("winmgmts:\\.\root\cimv2") Local $colItems = $oWMIService.ExecQuery("SELECT Name, AdapterRAM FROM Win32_VideoController") Local $hasExternalGPU = False Local $gpuName = "" If IsObj($colItems) Then For $oItem In $colItems $gpuName = $oItem.Name If StringInStr($gpuName, "NVIDIA") Or StringInStr($gpuName, "Radeon") Or StringInStr($gpuName, "RTX") Or StringInStr($gpuName, "GTX") Then ; Embedded GPU may require other method to check its availability $hasExternalGPU = True EndIf If $oItem.AdapterRAM >= 2147483648 Then ; Embedded GPU may show lower RAM size $hasExternalGPU = True EndIf Next EndIf If $hasExternalGPU Then Return "high" Else Return "low" EndIf EndFunc ; _GetVideoCardSpec Func _Marquee() ; Adlib function to implement marquee, 40ms, called in _Play() $iMarquee += 1 If $iMarquee < 3000/$iMarqueeInterval Then Return ; 3 seconds of halt when the $idTitle reaches $iTitlePosX $iTitlePosX2 -= 1 If -($iTitlePosX2) = $iTitleWidth + StringLen($sGap) * 4 Then ; Each space is 4 pixels wide $iTitlePosX2 = 0 $iMarquee = 0 EndIf ControlMove($hChildGUI, "", $idTitle, $iTitlePosX2, 0) EndFunc ; _Marquee Func _mciSendString($string) ; Send command string to winmm.dll - https://learn.microsoft.com/en-us/windows/win32/multimedia/multimedia-command-strings Local $aRet = DllCall($hWinmmDLL, "int", "mciSendStringW", "wstr", $string, "wstr", "", "int", 65534, "hwnd", 0) If Not @error Then Return $aRet[2] EndFunc ; _mciSendString Func _mpv_command($ptr, $p1, $p2 = "", $p3 = "", $p4 = "") ; Call mpv_command with variable number of parameters Local $aParams = [$p1, $p2, $p3, $p4] Local $iCount = 0 For $i = 0 To 3 If $aParams[$i] <> "" Then $iCount += 1 Next ; Create pointer array (number of parameters + NULL end pointer) Local $tPtrArray = DllStructCreate("ptr[" & ($iCount + 1) & "]") ; Convert strings to UTF-8 binary strings and assign to memory Local $aStrStructs[$iCount] For $i = 0 To $iCount - 1 Local $bUTF8 = StringToBinary($aParams[$i], 4) ; UTF-8 Local $iLen = BinaryLen($bUTF8) ; Create "byte" structure instead of "char" to prevent converting to ANSI $aStrStructs[$i] = DllStructCreate("byte[" & ($iLen + 1) & "]") DllStructSetData($aStrStructs[$i], 1, $bUTF8) DllStructSetData($tPtrArray, 1, DllStructGetPtr($aStrStructs[$i]), $i + 1) Next ; The ending pointer must be NULL DllStructSetData($tPtrArray, 1, 0, $iCount + 1) Local $aRet = DllCall($hMpvDLL, "int:cdecl", "mpv_command", "ptr", $ptr, "ptr", DllStructGetPtr($tPtrArray)) Return $aRet EndFunc ; _mpv_command Func _mpv_EndOfFile() ; End of File routine, called by main loop for non-appended file AdlibUnRegister("_VCShow") AdlibUnRegister("_VideoRefresh") AdlibUnRegister("_VolumeSync") AdlibUnRegister("_Marquee") ControlMove($hChildGUI, "", $idTitle, 0, 0) If $isVideo = 1 Or $isAudio = 2 Then GUISetState(@SW_HIDE, $hVCGui) If $iMaximized + $iFullScreen = 0 Then GUISetState(@SW_HIDE, $hVideoGUI) EndIf EndIf If $iPlayPrevious = 0 Then $iIndex += 1 If $iIndex > $aPlaylist[0] Then $iIndex = 1 Else $iIndex -= 1 If $iIndex = 0 Then $iIndex = $aPlaylist[0] $iPlayPrevious = 0 EndIf $iPlayPrevious = 0 If $iStartPos > 0 Then $iStartPos = 0 _mpv_set_option_string($pHandle, "start", "0") _AudioModeSet($iAudioMode, False) ; No fade-in EndIf _PlayFile() EndFunc ; _mpv_EndOfFile() Func _mpv_EventHandler() ; receive mpv event ID and take relevant actions ; --- Receive mpv event --- Local $pEvent = _mpv_wait_event($pHandle, 0) If $pEvent = 0 Then Return Local $tEvent = DllStructCreate("int event_id;int error;uint64 reply_userdata;ptr data", $pEvent) Local $iEventId = DllStructGetData($tEvent, "event_id") If $iEventId = 22 Then ; MPV_EVENT_PROPERTY_CHANGE Local $pPropData = DllStructGetData($tEvent, "data") ; mpv_event_property structure: name(ptr), format(int), data(ptr) Local $tProp = DllStructCreate("ptr name;int format;ptr val", $pPropData) ; 1. read property string from pointer Local $pName = DllStructGetData($tProp, "name") Local $sName = _PtrToStringAnsi($pName) ; convert a pointer to string, like "time-pos" Local $iFormat = DllStructGetData($tProp, "format") Local $pVal = DllStructGetData($tProp, "val") If $pVal = 0 Then Return ; 2. extract data for each property Switch $sName Case "time-pos" ; current playback position has changed If $iFormat = 5 Then ; MPV_FORMAT_DOUBLE $tDouble = DllStructCreate("double", $pVal) $iCurrentPos = DllStructGetData($tDouble, 1) ; in seconds If $iSlider = 0 Then ; update progress bar and current media position in MMM:SS format $iNewX = $iSliderPosX+$iCurrentPos/$iMediaLength*$iSliderLength If $iLastX <> $iNewX Then ; update progress bar of $hMain GUICtrlSetPos($idProgBar, $iNewX) $iLastX = $iSliderPosX+$iNewX EndIf If $isVideo = 1 Or $isAudio = 2 Then $iNewX2 = $iCurrentPos/$iMediaLength*$iSliderLength2 If $iLastX2 <> $iNewX2 Then ; update progress bar of $hVideoGUI GUICtrlSetPos($idProgBar2, $iNewX2) $iLastX2 = $iNewX2 EndIf EndIf $tSeconds = Int($iCurrentPos) If $iLastTime <> $tSeconds Then ; update $idCurrentPos and $idCurrentPos2 $sNewTime = _SecondsToTime(Int($tSeconds), $hMain) GUICtrlSetData($idCurrentPos, $sNewTime) If $isVideo = 1 Or $isAudio = 2 Then $sNewTime = _SecondsToTime($tSeconds, $hVCGui) GUICtrlSetData($idCurrentPos2, $sNewTime) EndIf $iLastTime = $tSeconds EndIf EndIf If $bIsLoading = False And $iCurrentPos < 5 Then $bIsLoading = True ElseIf $bIsLoading = True And $iCurrentPos >= 5 Then $bIsLoading = False EndIf ; $bIsLoading was set to True in the beginning of _PlayFile() ; _PlayNext(), _PlayPrevious() and some adlibs do not function while $bIsLoading is True If $iVideoRefresh = 1 Then ; _VideoRefresh() $iVideoRefresh = 0 _mpv_command($pHandle, "seek", -0.05, "relative") _mpv_command($pHandle, "seek", +0.05, "relative") EndIf If $iCycleMute = 1 Then ; _VolumeSync() $iCycleMute = 0 _mpv_command($pHandle, "cycle", "mute") EndIf EndIf Case "duration" ; a new file has been loaded If $iFormat = 5 Then ; MPV_FORMAT_DOUBLE $tDouble = DllStructCreate("double", $pVal) $iMediaLength = DllStructGetData($tDouble, 1) ; in seconds $iMinutes = Int($iMediaLength/60) If $iMinutes < 100 Then GUICtrlSetPos($idLength, 284) Else GUICtrlSetPos($idLength, 278) EndIf $sNewTime = _SecondsToTime(Int($iMediaLength), $hMain) GUICtrlSetData($idLength, $sNewTime) $sNewTime = _SecondsToTime(Int($iMediaLength), $hVCGui) GUICtrlSetData($idLength2, $sNewTime) ; If $iMediaLength > 9 Then ; for test runs to check proper transition to next file ; _mpv_command($pHandle, "seek", $iMediaLength-8, "absolute") ; EndIf EndIf Case "idle-active" ; the playback has stopped If $iFormat = 3 Then ; MPV_FORMAT_FLAG Local $tBool = DllStructCreate("int", $pVal) ; MPV_FORMAT_FLAG is internally a 4-byte integer If DllStructGetData($tBool, 1) <> 0 Then ;ConsoleWrite(_mpv_get_property($pHandle, "idle-active", "string") & @CRLF) _mpv_EndOfFile() EndIf EndIf EndSwitch ; ElseIf $iEventId = 6 Then ; MPV_EVENT_START_FILE ; ConsoleWrite("Event ID - 6" & @CRLF) ; ElseIf $iEventId = 7 Then ; MPV_EVENT_END_FILE - Do not use this event ID ;Local $pData = DllStructGetData($tEvent, "data") ;Local $tEndFileData = DllStructCreate("int reason", $pData) ;Local $iReason = DllStructGetData($tEndFileData, "reason") ;0 (MPV_END_FILE_REASON_EOF) ;2 (MPV_END_FILE_REASON_STOP) ;3 (MPV_END_FILE_REASON_QUIT) ;4 (MPV_END_FILE_REASON_ERROR) ;5 (MPV_END_FILE_REASON_REDIRECT) ElseIf $iEventId = 8 Then ; MPV_EVENT_FILE_LOADED _mpv_set_property($pHandle, "pause", "no", "string") Local $sCurrentPath = _mpv_get_property($pHandle, "path", "string") If StringInStr($sCurrentPath, $sFolder) Then $sFile = StringReplace($sCurrentPath, $sFolder, "") Else $sFile = $sCurrentPath EndIf For $i = 1 To $aPlaylist[0] ; _ArraySearch() cannot search certain UTF characters like "dΓ©ploration" If $aPlaylist[$i] = $sFile Then $iIndex = $i ExitLoop EndIf Next If StringInStr($sFile, ":\") Then $sPath = $sFile Else $sPath = $sFolder & $sFile EndIf _PlayMPV() Local $nextIndex = $iIndex + 1, $nextPath, $nextFile If $nextIndex > $aPlaylist[0] Then $nextIndex = 1 $nextFile = $aPlaylist[$nextIndex] If StringInStr($nextFile, ":\") Then $nextPath = $nextFile Else $nextPath = $sFolder & $nextFile EndIf If Not StringInStr(".cda .mid", StringRight($nextFile, 4)) And FileExists($nextPath) Then _mpv_command($pHandle, "loadfile", $nextPath, "append-play") EndIf EndIf EndFunc ; _mpv_EventHandler Func _mpv_free($pAddr) ; Prevent memory leak ; Omitting :cdecl in an AutoIt DllCall leads to stack corruption, which can cause ignored commands or program termination DllCall($hMpvDLL, "void:cdecl", "mpv_free", "ptr", $pAddr) EndFunc ; _mpv_free Func _mpv_get_property($hMpv, $sProperty, $sType = "string") ; Get MPV properties, string or double Local $aRet, $iLen, $vResult = "", $tDouble Switch StringLower($sType) Case "string", "str" $aRet = DllCall($hMpvDLL, "ptr:cdecl", "mpv_get_property_string", "ptr", $hMpv, "str", $sProperty) If Not @error And $aRet[0] <> 0 Then $iLen = _mpv_get_strlen($aRet[0]) $vResult = DllStructGetData(DllStructCreate("char[" & $iLen & "]", $aRet[0]), 1) DllCall($hMpvDLL, "none:cdecl", "mpv_free", "ptr", $aRet[0]) EndIf Case "double", "num", "number" $tDouble = DllStructCreate("double") $aRet = DllCall($hMpvDLL, "int:cdecl", "mpv_get_property", "ptr", $hMpv, "str", $sProperty, "int", 5, "ptr", DllStructGetPtr($tDouble)) If $aRet[0] < 0 Then Return 0 ; Error Return DllStructGetData($tDouble, 1) Case Else Return SetError(1, 0, "Unknown Type") EndSwitch Return $vResult EndFunc ; _mpv_get_property Func _mpv_get_strlen($pPtr) ; get string length, called by _mpv_get_property() Local $aRet = DllCall("kernel32.dll", "int", "lstrlenA", "ptr", $pPtr) Return $aRet[0] EndFunc ; _mpv_get_strlen Func _mpv_InitializeEngine() ; initialize mpv engine $pHandle = DllCall($hMpvDLL, "ptr:cdecl", "mpv_create")[0] If Not $pHandle Then _Exit() _mpv_set_options() DllCall($hMpvDLL, "int:cdecl", "mpv_initialize", "ptr", $pHandle) _mpv_set_option_string($pHandle, "wid", String(Ptr($hVideoGUI))) Sleep(50) _mpv_set_property($pHandle, "keepaspect", $sKeepAspect, "string") _mpv_set_property($pHandle, "volume", 100, "double") _mpv_command($pHandle, "set", "ao-volume", $iVolume) ; _mpv_observe_property($pHandle, 100, "osd-dimensions", 1) ; string - to get position of video image _mpv_observe_property($pHandle, 100, "track-list", 4) ; MPV_FORMAT_NODE _mpv_observe_property($pHandle, 101, "duration", 5) ; double _mpv_observe_property($pHandle, 102, "time-pos", 5) ; double _mpv_observe_property($pHandle, 103, "idle-active", 3) ; flag (boolean) EndFunc ; _mpv_InitializeEngine Func _mpv_observe_property($pHandle, $iReplyId, $sName, $iFormat) ; DllCall for mpv_observe_property function in libmpv-2.dll ; $pHandle: mpv handle ; $iReplyId: arbitrary number to identify an event (e.g. 100) ; $sName: name of property to observe (e.g. "ao-volume", "time-pos") ; $iFormat: data format (e.g. "double", "flag") Local $aResult = DllCall($hMpvDLL, "int", "mpv_observe_property", "ptr", $pHandle, "uint64", $iReplyId, "str", $sName, "int", $iFormat) If @error Then Return SetError(1, 0, 0) Return $aResult[0] ; return 0 or a positive number when successful EndFunc ; _mpv_observe_property Func _mpv_set_options() ; set initial options for smooth operation ; Set hardware acceleration options (Based on Media Foundation) $sVideoCardSpec = _GetVideoCardSpec() If $sVideoCardSpec = "low" Then _mpv_set_option_string($pHandle, "profile", "fast") _mpv_set_option_string($pHandle, "vo", "direct3d") _mpv_set_option_string($pHandle, "dither", "no") _mpv_set_option_string($pHandle, "framedrop", "vo") Else _mpv_set_option_string($pHandle, "profile", "gpu-hq") _mpv_set_option_string($pHandle, "vo", "gpu") EndIf _mpv_set_option_string($pHandle, "gpu-api", "d3d11") _mpv_set_option_string($pHandle, "hwdec", "auto-safe") _mpv_set_option_string($pHandle, "scale", "bilinear") _mpv_set_option_string($pHandle, "cscale", "bilinear") _mpv_set_option_string($pHandle, "dscale", "bilinear") ; Additional options available for higher spec computers to improve video quality ; _mpv_set_option_string($pHandle, "hwdec", "d3d11va") ; _mpv_set_option_string($pHandle, "video-sync", "display-resample") ; _mpv_set_option_string($pHandle, "interpolation", "yes") ; _mpv_set_option_string($pHandle, "tscale", "oversample") ; _mpv_set_option_string($pHandle, "scale", "extir-lanczos") ; or "spline36" ; _mpv_set_option_string($pHandle, "cscale", "lanczos") ; _mpv_set_option_string($pHandle, "dscale", "mitchell") ; Set maximum volume _mpv_set_property($pHandle, "volume-max", 100.0, "double") ; Connect GUI handle (Display video in an AutoIt GUI) ; _mpv_set_option_string($pHandle, "wid", String(Ptr($hVideoGUI))) _mpv_set_option_string($pHandle, "idle", "yes") ; if necesary to improve "seek" accuracy, especially in audio files ;_mpv_set_option_string($pHandle, "hr-seek", "always") ; Options to prevent the system from initialization errors ; 1. Specify Audio Output driver (Prevents delays/crashes during auto-detection) _mpv_set_option_string($pHandle, "ao", "wasapi") ; 2. Pre-allocate audio buffer (Crucial for preventing stuttering on first load) ; This ensures a buffer is filled before playback starts to handle initial CPU spikes. _mpv_set_option_string($pHandle, "audio-buffer", "0.5") ; Buffers 0.5 seconds of audio ; 3. Prevent program exit on initialization errors ; Ensures the player doesn't close if the audio device takes too long to respond. _mpv_set_option_string($pHandle, "stop-playback-on-init-failure", "no") ; 4. Set a timeout for the audio device to open (Wait for the device to be ready) ; Gives the OS more time (in milliseconds) to initialize the hardware. _mpv_set_option_string($pHandle, "audio-wait-open", "2000") ; Set to 2 seconds for reliability ; 5. Fill gaps with silence instead of crashing (Prevents underrun exits) _mpv_set_option_string($pHandle, "audio-stream-silence", "yes") ; 6. Prevent system from using the prior file's metadata in judging video and aspect properties _mpv_set_option_string($pHandle, "reset-on-next-file", "all") EndFunc ; _mpv_set_options Func _mpv_set_option_string($ptr, $name, $value) ; get mpv propertiess in string format DllCall($hMpvDLL, "int:cdecl", "mpv_set_option_string", "ptr", $ptr, "str", $name, "str", $value) EndFunc ; _mpv_set_option_string Func _mpv_set_property($hMpv, $sProperty, $vValue, $sType = "string") ; 0 = MPV_FORMAT_STRING Local $aRet Switch $sType Case "string", "str" $aRet = DllCall($hMpvDLL, "int:cdecl", "mpv_set_property_string", "ptr", $hMpv, "str", $sProperty, "str", String($vValue)) Case "double", "num", "number" Local $tDouble = DllStructCreate("double") DllStructSetData($tDouble, 1, Number($vValue)) $aRet = DllCall($hMpvDLL, "int:cdecl", "mpv_set_property", "ptr", $hMpv, "str", $sProperty, "int", 5, "ptr", DllStructGetPtr($tDouble)) Case Else Return SetError(1, 0, -1) EndSwitch Return $aRet[0] EndFunc ; _mpv_set_property Func _mpv_wait_event($pHandle, $nTimeout = 0) Local $aResult = DllCall($hMpvDLL, "ptr", "mpv_wait_event", "ptr", $pHandle, "double", $nTimeout) If @error Then Return SetError(1, 0, 0) Return $aResult[0] ; return a memory address (pointer) pointing to the event structure EndFunc ; _mpv_wait_event Func _ParseMpvJson($sJson, $sKey) Local $aMatch = StringRegExp($sJson, '"' & $sKey & '":\s*(-?\d+)', 1) If @error Then Return 0 Return Number($aMatch[0]) EndFunc ; _ParseMpvJson Func _PlayCD() ; play .cda files in a CDROM drive If $iIndex = 0 Then $iIndex = 1 $sFile = $aPlaylist[$iIndex] If Not StringInStr(".cda .mid", StringRight($sFile, 4)) Then Return _PlayFile() EndIf If StringInStr($sFile, ":\") Then $sPath = $sFile Else $sPath = $sFolder & $sFile EndIf $bIsLoading = True $iMediaLength = 0 If StringRight($sFile, 4) = ".mid" Then Static Local $isFirstFile = True If $isFirstFile Then GUICtrlSetData($idLoading, "Loading: " & $sFile) GUISetState(@SW_SHOW, $hLoading) EndIf _mciSendString("open """ & $sPath & """ alias myMedia type sequencer wait") While 1 If _mciSendString("status myMedia ready") Then ExitLoop Sleep(10) WEnd Sleep(100) ; should be longer than the while loop wait time _mciSendString("set myMedia time format milliseconds") $iMediaLength = _mciSendString("status myMedia length") If $isFirstFile Then For $i = 1 To 50 Sleep(20) Next $isFirstFile = False GUISetState(@SW_HIDE, $hLoading) EndIf _mciSendString("play myMedia") Else Local $sDrive, $sTrack $sDrive = StringLeft($sPath, StringInStr($sPath, "\", 0, -1)) $sTrack = StringMid($sPath, StringInStr($sPath, "\", 0, -1)+1) If Not IsArray($aTracks) Then GUISetState(@SW_HIDE, $hVideoGUI) $aTracks = _FileListToArrayRec($sDrive, "*.cda", 1, 1, 0, 1) $iRet = _mciSendString("open """ & $sDrive & """ alias myMedia type cdaudio wait") EndIf For $i = 1 To $aTracks[0] If $aTracks[$i] = $sTrack Then $iTrack = $i ExitLoop EndIf Next $iTrackPos = 0 _mciSendString("set myMedia time format milliseconds") While 1 $iMediaLength = _mciSendString("status myMedia length track " & $iTrack) $iTrackPos = _mciSendString("status myMedia position track " & $iTrack) If _mciSendString("status myMedia ready") And $iMediaLength > 0 And $iTrackPos > 0 Then ExitLoop Sleep(10) WEnd Sleep(50) ; should be longer than the while loop wait time _mciSendString("play myMedia from " & $iTrackPos + 100) EndIf GUICtrlSetData($idTitle, $sFile) $sNewTime = _SecondsToTime(Int($iMediaLength/1000), $hMain) GUICtrlSetData($idLength, $sNewTime) GUICtrlSetData($idPlay, "❚❚") AdlibRegister("_VolumeSync", 479) $iSlider = 0 Local $mediaPos = 0, $iLength = 0 While 1 $aGUIMsg = GUIGetMsg(1) $sGUIMsg = $aGUIMsg[0] Switch $aGUIMsg[1] Case $hCover Switch $sGUIMsg Case $idCloseX _Exit() Case $idMinimize AdlibUnRegister("_SaveCoverPos") GUISetState(@SW_MINIMIZE, $hMain) $iMainIsMinimized = 1 While _IsPressed("01", $hUser32DLL) Sleep(10) WEnd Case $idOptions ; _Options() Case $idSetOnTop _SetMainOnTop() Case $idQuestion ; _Help() Case $GUI_EVENT_PRIMARYDOWN ; Click and drag $hCover. WM_WINDOWPOSCHANGED() will move $hMain in sync with $hCover. DllCall($hUser32DLL, "int", "SendMessageW", "hwnd", $hCover, "uint", $WM_NCLBUTTONDOWN, "wparam", $HTCAPTION, "lparam", 0) EndSwitch Case $hMain, $hChildGUI Switch $sGuiMsg Case $idDown _VolumeDown() Case $idUp _VolumeUp() Case $idPlay _PlayPause() Case $idPrevious _PlayPrevious() Case $idNext _PlayNext() Case $idSpeaker If $iMute = 0 Then GUICtrlSetData($idSpeaker, "πŸ”‡") _Audio_Action("SetMute", True) $iMute = 1 Else GUICtrlSetData($idSpeaker, "πŸ”Š") _Audio_MasterVolume("UnMute") _Audio_Action("SetMute", False) $iMute = 0 EndIf Case $idRepeat _RepeatCurrentFile() Case $idSlider _Slider($sGuiMsg) Case $idShuffle _Shuffle_CD() Case $idTitle _PlaylistDisplay() Case $idFile If Not $bIsLoading Then Local $aOldList, $sOldFolder If IsArray($aPlaylist) Then $aOldList = $aPlaylist $sOldFolder = $sFolder EndIf $aPlaylist = 0 _PlaylistCreate() If IsArray($aPlaylist) Then If StringRight($sFile, 4) = ".mid" Then _mciSendString("close myMedia") Else _mciSendString("stop myMedia") EndIf Return _mpv_EndOfFile() ElseIf IsArray($aOldList) Then $aPlaylist = $aOldList $sFolder = $sOldFolder EndIf EndIf EndSwitch EndSwitch If $iSlider = 1 Then ContinueLoop $iCurrentPos = Number(_mciSendString("status myMedia position")) If StringRight($sFile, 4) = ".cda" Then $mediaPos = $iCurrentPos - $iTrackPos Else $mediaPos = $iCurrentPos EndIf $iNewX = $iSliderPosX+$mediaPos/$iMediaLength*$iSliderLength If $iNewX <> $iLastX Then GUICtrlSetPos($idProgBar, $iNewX) $iLastX = $iNewX EndIf $tSeconds = Int($mediaPos/1000) If $iLastTime <> $tSeconds Then ; update $idCurrentPos and $idCurrentPos2 $sNewTime = _SecondsToTime(Int($tSeconds), $hMain) GUICtrlSetData($idCurrentPos, $sNewTime) $iLastTime = $tSeconds EndIf If $bIsLoading = False And $iCurrentPos < 5000 Then $bIsLoading = True ElseIf $bIsLoading = True And $iCurrentPos >= 5000 Then $bIsLoading = False EndIf ; $bIsLoading was set to True in the beginning of _PlayFile() ; _PlayNext(), _PlayPrevious() and some adlibs do not function while $bIsLoading is True If $iLength = 0 Then $iLength = $iMediaLength If StringRight($sFile, 4) = ".cda" Then $iLength = $iLength + $iTrackPos EndIf EndIf If $iCurrentPos >= $iLength Then If $iRepeatCurrentFile = 0 Then Local $nextIndex = $iIndex + 1, $nextFile If $nextIndex > $aPlaylist[0] Then $nextIndex = 1 $nextFile = $aPlaylist[$nextIndex] If StringRight($sFile, 4) = ".cda" Then If StringRight($nextFile, 4) = ".cda" Then _mciSendString("stop myMedia") Else $aTracks = 0 _mciSendString("close myMedia") EndIf If StringInStr(".cda .mid", StringRight($nextFile, 4)) Then $iIndex = $nextIndex Return _PlayCD() Else $aTracks = 0 ExitLoop EndIf Else $aTracks = 0 _mciSendString("close myMedia") If StringInStr(".cda .mid", StringRight($nextFile, 4)) Then $iIndex = $nextIndex Return _PlayCD() Else ExitLoop EndIf EndIf Else _mciSendString("stop myMedia") If StringRight($sFile, 4) = ".cda" Then _mciSendString("play myMedia from " & $iTrackPos + 50) Else _mciSendString("play myMedia from 0") EndIf EndIf EndIf Sleep(10) WEnd ; Returns to _mpv_EndOfFile() EndFunc ; _PlayCD Func _PlayFile() ; Invoked by the main loop when the player is in idle state $sFile = $aPlaylist[$iIndex] If StringInStr($sFile, ":\") Then $sPath = $sFile Else $sPath = $sFolder & $sFile EndIf If Not FileExists($sPath) Then $iRet = MsgBox(270660, "Loading failure", $sPath & @CRLF & _ "This file does not exist." & @CRLF & "Do you want to exit the program?" & @CRLF & _ 'Press "No" to play the next file.') If $iRet = 6 Then _Exit() Else $iIndex += 1 If $iIndex > $aPlaylist[0] Then $iIndex = 1 Return _PlayFile() EndIf EndIf If StringInStr(".cda .mid", StringRight($sFile, 4)) Then If $hWinmmDLL = "" Then $hWinmmDLL = DllOpen("winmm.dll") ; https://learn.microsoft.com/en-us/windows/win32/multimedia/multimedia-command-strings If $hWinmmDLL = -1 Then AdlibUnRegister("_VolumeSync") MsgBox($MB_OK, "DLL Open Failure", "Winmm.dll could not be opened!") AdlibRegister("_VolumeSync", 479) Return -1 EndIf Else $aTracks = 0 _mciSendString("close myMedia") EndIf GUISetState(@SW_HIDE, $hVideoGUI) _PlayCD() Return _mpv_EndOfFile() EndIf _mpv_set_property($pHandle, "speed", 1.0, "double") _mpv_set_property($pHandle, "pause", "yes", "string") ; set "pause" on $bIsLoading = True ; _PlayNext(), _PlayPrevious and Adlibs will not function while $bIsLoading = True $iMediaLength = 0 _mpv_command($pHandle, "loadfile", $sPath, "replace") If $bIsFirstFile Then GUICtrlSetData($idLoading, "Loading: " & $sFile) GUISetState(@SW_SHOW, $hLoading) For $i = 1 To 50 Sleep(20) Next EndIf EndFunc ; _PlayFile Func _PlayMPV() $iTrackCount = 0 While 1 ; $iTrackCount = _mpv_get_property($pHandle, "track-list/count", "double") If $iTrackCount > 0 Then ExitLoop Sleep(50) WEnd If $bIsFirstFile Then GUISetState(@SW_HIDE, $hLoading) $bisFirstFile = False EndIf Local $bHasVideoTrack = False For $j = 0 To $iTrackCount - 1 If _mpv_get_property($pHandle, "track-list/" & $j & "/type", "string") = "video" Then $bHasVideoTrack = True ExitLoop EndIf Next $iAspect = 0 If $bHasVideoTrack Then $iAspect = _mpv_get_property($pHandle, "video-params/aspect", "double") If $iAspect = 0 Then $iAspect = 1.77778 Else $iAspect = 1 ; audio only EndIf Local $sTrackList = "" Local $aRet = DllCall($hMpvDLL, "str:cdecl", "mpv_get_property_string", "ptr", $pHandle, "str", "track-list") $sTrackList = $aRet[0] $isVideo = 0 $isAudio = 0 If StringInStr($sTrackList, '"albumart":true') Then ; audio file with album art If $sDisplayAlbumArt = "Yes" Then $isAudio = 2 ; display album art Else $isAudio = 1 ; do not display album art EndIf ElseIf StringInStr($sTrackList, '"type":"video"') Then ; video file $isVideo = 1 Else $isAudio = 1 ; audio file with no album art EndIf $sTitle = StringMid($sFile, StringInStr($sFile, "\", 0, -1)+1) GUICtrlSetPos($idProgBar, $iSliderPosX) GUICtrlSetData($idTitle, $sTitle) If $isVideo = 1 Or $isAudio = 2 Then WinSetTitle($hVideoGUI, "", $sTitle) Local $x, $y, $w, $h If $isVideo = 1 Then $w = $iVideoWidth Else $w = 500 EndIf If $aVideoDefPos[2] > 0 Then $w = $aVideoDefPos[2] - $iBorderWidth * 2 EndIf If $sKeepAspect = "Yes" Then $h = Int($w/$iAspect) If $h > $iClientHeight-$iTitleHeight-$iBorderWidth Then $h = $iClientHeight-$iTitleHeight-$iBorderWidth $w = Int($h*$iAspect) EndIf Else $h = _Min($w, $iClientHeight) EndIf If $iMaximized+$iFullScreen = 0 Then If $aVideoDefPos[2] = 0 Then $x = ($iClientWidth-$w-$iBorderWidth*2)/2 $y = ($iClientHeight-$h-$iTitleHeight-$iBorderWidth)/2 Else $x = $aVideoDefPos[0] $y = $aVideoDefPos[1] EndIf $w += $iBorderWidth*2 $h += $iTitleHeight+$iBorderWidth WinMove($hVideoGUI, "", $x, $y, $w, $h) ElseIf $iFullScreen = 1 Then WinSetOnTop($hVideoGUI, "", 1) WinMove($hVideoGUI, "", 0, 0, @DesktopWidth, @DesktopHeight) ElseIf $iMaximized = 1 Then WinMove($hVideoGUI, "", 0, 0, @DesktopWidth, $iClientHeight) EndIf _mpv_set_property($pHandle, "vid", "auto", "string") _mpv_set_property($pHandle, "pause", "no", "string") ; set "pause" off GUISetState(@SW_SHOW, $hVideoGUI) GUISetState(@SW_SHOW, $hVCGui) GUICtrlSetPos($idProgBar2, 0) AdlibRegister("_VCShow", 249) AdlibRegister("_VideoRefresh", 300000) If $iFullScreen = 1 Then GUICtrlSetData($idSlider2, " " & $sTitle) Else GUICtrlSetData($idSlider2, "") EndIf Else GUISetState(@SW_HIDE, $hVideoGUI) GUISetState(@SW_HIDE, $hVCGui) _mpv_set_property($pHandle, "vid", "no", "string") _mpv_set_property($pHandle, "pause", "no", "string") EndIf GUICtrlSetData($idPlay, "❚❚") GUICtrlSetData($idPlay2, "❚❚") AdlibRegister("_VolumeSync", 479) $iSlider = 0 GUISwitch($hChildGUI) Local $tmpLabel = GUICtrlCreateLabel($sTitle, 0, 0, -1, 18, BitOR($SS_NOPREFIX, $SS_LEFTNOWORDWRAP)) $iTitleWidth = ControlGetPos($hChildGUI, "", $tmpLabel)[2] - 9 ; The label width is wider than actual string width by 9 pixels. GUICtrlDelete($tmpLabel) If $iTitleWidth > $iMainGuiWidth - $iTitlePosX*2 Then GUICtrlSetData($idTitle, $sTitle & $sGap & $sTitle) $iTitlePosX2 = 0 $iMarquee = 0 AdlibRegister("_Marquee", $iMarqueeInterval) EndIf Local Static $bFirstFile = True If $bFirstFile Then $bFirstFile = False For $i = 1 To 20 Sleep(50) Next Else For $i = 1 to 2 Sleep(50) Next EndIf $bNextAppended = False ; to allow append-play of the next mpvFile in _mpv_EventHandler() EndFunc ; _PlayMPV Func _PlaylistCreate() ; Create a playlist at the beginning of the program Local $sPaused = "No" If $iCurrentPos > 0 And $iPaused = 0 Then _PlayPause() $sPaused = "Yes" EndIf Local $sFiles = FileOpenDialog("Load one or more media files", "", "Media (" & $sFileTypes & ")", 7) If $sPaused = "Yes" Then _PlayPause() EndIf If $sFiles = "" Then Return If Not StringInStr($sFiles, "|") Then Local $iPos = StringInStr($sFiles, "\", 0, -1) $sFiles = StringLeft($sFiles, $iPos) & "|" & StringMid($sFiles, $iPos+1) EndIf $aPlaylist = StringSplit($sFiles, "|") ; Folder name|File 1|File 2... $sFolder = $aPlaylist[1] If StringRight($sFolder, 1) <> "\" Then $sFolder &= "\" _ArrayDelete($aPlaylist, 1) $aPlaylist[0] = UBound($aPlaylist)-1 GUICtrlSetData($idShuffle, "Shuffle") $iIndex = 0 ; _mpv_EndOfFile() will increase $iIndex by 1 ; For testing transition from digital file to CD track or vice versa in the same playlist ; _ArrayAdd($aPlaylist, "I:\Track07.cda") ; _ArrayAdd($aPlaylist, "I:\Track01.cda") ; _ArrayAdd($aPlaylist, "D:\Video\Voorbeeld.mp4") ; $aPlaylist[0] += 3 ; _ArrayShuffle($aPlaylist, 1) EndFunc ; _PlaylistCreate Func _PlaylistDisplay() ; _ArrayDisplay($aPlaylist) (press Ctrl+Alt+L) If $iFullScreen = 1 Then Return If WinExists("Playlist") Then WinClose("Playlist") Else _ArrayDisplay($aPlaylist, "Playlist") EndIf EndFunc ; _PlaylistDisplay Func _PlayNext() ; Play next file (click "β–Ά" or press Ctrl+Alt+Right) If $bIsLoading = True Then Return If $iPaused = 1 Then _PlayPause() EndIf If $iRepeatCurrentFile = 1 Then ; Turn off file repeat mode If Not StringInStr(".cda .mid", StringRight($sFile, 4)) Then _mpv_command($pHandle, "set", "loop-file", "no") EndIf $iRepeatCurrentFile = 0 GUICtrlSetData($idRepeat, "U") GUICtrlSetData($idRepeat2, "U") EndIf ; get file path of the next item in $aPlaylist Local $nextIndex = $iIndex + 1, $nextPath, $nextFile If $nextIndex > $aPlaylist[0] Then $nextIndex = 1 $nextFile = $aPlaylist[$nextIndex] If StringInStr($nextFile, ":\") Then $nextPath = $nextFile Else $nextPath = $sFolder & $nextFile EndIf If Not StringInStr(".cda .mid", StringRight($sFile, 4)) Then ; get file path of the "appended' file Local $iCount = Int(_mpv_get_property($pHandle, "playlist-count", "number")) Local $iLastIndex = $iCount - 1 Local $sLastFilePath = _mpv_get_property($pHandle, "playlist/" & $iLastIndex & "/filename", "string") If $sLastFilePath = $nextPath Then ; 2 files paths are identical _mpv_command($pHandle, "playlist-next", "weak") ; moves to the next file without idle-active event Else _mpv_command($pHandle, "stop") ; the idle-active event will call _mpv_EndOfFile() and play the next file EndIf Else _mciSendString("stop myMedia") If StringRight($sFile, 4) = ".cda" Then _mciSendString("play myMedia from " & $iTrackPos + $iMediaLength - 10) Else _mciSendString("play myMedia from " & $iMediaLength - 10) EndIf EndIf EndFunc ; _PlayNext Func _PlayPause() ; Toggle between play and pause If Not StringInStr(".cda .mid", StringRight($sFile, 4)) Then ; _mpv_command($pHandle, "cycle", "pause") EndIf If $iPaused = 0 Then GUICtrlSetData($idPlay, "β–Ά") GUICtrlSetData($idPlay2, "β–Ά") If StringInStr(".cda .mid", StringRight($sFile, 4)) Then _mciSendString("Pause myMedia") Else _mpv_command($pHandle, "cycle", "pause") EndIf $iPaused = 1 AdlibRegister("_ActivateSpeakers", 30000) Else GUICtrlSetData($idPlay, "❚❚") GUICtrlSetData($idPlay2, "❚❚") If StringInStr(".cda .mid", StringRight($sFile, 4)) Then _mciSendString("Play myMedia") Else _mpv_command($pHandle, "cycle", "pause") EndIf $iPaused = 0 AdlibUnRegister("_ActivateSpeakers") EndIf EndFunc ; _PlayPause Func _PlayPrevious() ; Play privious file (click "β—€" or press Ctrl+Alt+Left) If $bIsLoading = True Then Return If $iPaused = 1 Then _PlayPause() EndIf If $iRepeatCurrentFile = 1 Then ; Turn off file repeat mode _mpv_command($pHandle, "set", "loop-file", "no") $iRepeatCurrentFile = 0 GUICtrlSetData($idRepeat, "U") GUICtrlSetData($idRepeat2, "U") EndIf $iPlayPrevious = 1 If Not StringInStr(".cda .mid", StringRight($sFile, 4)) Then _mpv_command($pHandle, "stop") ; the main loop will handle end-of-file event Else $iIndex -= 1 If $iIndex < 1 Then $iIndex = $aPlaylist[0] If StringRight($sFile, 4) = ".cda" Then _mciSendString("stop myMedia") Else _mciSendString("close myMedia") EndIf Return _PlayCD() EndIf EndFunc ; _PlayPrevious Func _PtrToStringAnsi($pPtr) ; Read ANSI string from a pointer If $pPtr = 0 Then Return "" Local $tStruct = DllStructCreate("char[32767]", $pPtr) Return DllStructGetData($tStruct, 1) EndFunc ; _PtrToStringAnsi Func _RepeatCurrentFile() If $iRepeatCurrentFile = 0 Then $iRepeatCurrentFile = 1 _mpv_command($pHandle, "set", "loop-file", "yes") GUICtrlSetData($idRepeat, "0") GUICtrlSetData($idRepeat2, "0") Else $iRepeatCurrentFile = 0 _mpv_command($pHandle, "set", "loop-file", "no") GUICtrlSetData($idRepeat, "U") GUICtrlSetData($idRepeat2, "U") EndIf EndFunc ; _RepeatCurrentFile Func _SaveCoverPos() ; Adlib to save position of $hCover, for use in $GUI_EVENT_RESTORE of $hMain, 250ms If _WinAPI_IsIconic($hMain) Then Return $aCoverPos = WinGetPos($hCover) EndFunc ; _SaveCoverPos Func _SecondsToTime($Seconds, $hWnd) ; Transform seconds to 00:00:00 time format Local $iH, $iM, $iS If $hWnd = $hMain Then $iM = Int($Seconds / 60) $iS = Mod($Seconds, 60) If $iM < 100 Then Return StringFormat("%02i:%02i", $iM, $iS) Else Return StringFormat("%03i:%02i", $iM, $iS) EndIf Else $iH = Int($Seconds / 3600) $iM = Int(Mod($Seconds, 3600) / 60) $iS = Mod($Seconds, 60) If Int($iMediaLength) > 3600 Then Return StringFormat("%02i:%02i:%02i", $iH, $iM, $iS) Else Return StringFormat("%02i:%02i", $iM, $iS) EndIf EndIf EndFunc ; _SecondsToTime Func _SetMainOnTop() ; If $hMain is not visible, Ctrl+Alt+T brings it to the top. If it is visible, πŸ”/πŸ”™ icon or Ctrl+Alt+T toggles its top window state. HotKeySet("^!t") If Not ($isVideo = 1 And $iFullScreen = 1) Then Local $aPos1 = WinGetPos($hCover) Local $tPoint = _WinAPI_CreatePoint($aPos1[0]+10, $aPos1[1]+2) $hTopWnd = _WinAPI_WindowFromPoint($tPoint) If $hTopWnd <> $hCover Then ; $hMain is minimized or is behind another window If $iMainIsMinimized = 1 Then GUISetState(@SW_RESTORE, $hMain) EndIf WinActivate($hMain) WinMove($hCover, "", $aCoverPos[0], $aCoverPos[1]) WinMove($hMain, "", $aCoverPos[0]-$iMainBorderWidth, $aCoverPos[1]) WinActivate($hMain) While _IsPressed("54", $hUser32DLL) Sleep(10) WEnd HotKeySet("^!t", _SetMainOnTop) Return EndIf If $iMainIsOnTop = 0 Then $iMainIsOnTop = 1 GUICtrlSetData($idSetOnTop, "πŸ”™") WinSetOnTop($hMain, "", 1) ; WinSetOnTop($hRepeatAB, "", 1) ; WinSetOnTop($hRepeatFiles, "", 1) Else $iMainIsOnTop = 0 GUICtrlSetData($idSetOnTop, "πŸ”") WinSetOnTop($hMain, "", 0) ; WinSetOnTop($hRepeatAB, "", 0) ; WinSetOnTop($hRepeatFiles, "", 0) EndIf While _IsPressed("54", $hUser32DLL) Sleep(10) WEnd HotKeySet("^!t", _SetMainOnTop) EndIf While _IsPressed("54", $hUser32DLL) Sleep(10) WEnd HotKeySet("^!t", _SetMainOnTop) EndFunc ; _SetMainOnTop Func _Shuffle_CD() ; shuffle $aPlaylist If GUICtrlRead($idShuffle) = "Shuffle" Then GUICtrlSetData($idShuffle, "Sort") _ArrayShuffle($aPlaylist, 1) Else GUICtrlSetData($idShuffle, "Shuffle") _ArraySort($aPlaylist, 0, 1) EndIf $iIndex = _ArraySearch($aPlaylist, $sFile) EndFunc ; _Shuffle_CD Func _Shuffle_MPV() ; shuffle $aPlaylist Local $nextIndex = $iIndex + 1, $nextFile, $nextPath If $nextIndex > $aPlaylist[0] Then $nextIndex = 1 $nextFile = $aPlaylist[$nextIndex] If StringInStr($nextFile, ":\") Then $nextPath = $nextFile Else $nextPath = $sFolder & $nextFile EndIf If Not StringInStr(".cda .mid", StringRight($nextFile, 4)) Then Local $count = Int(_mpv_get_property($pHandle, "playlist-count", "number")) Local $lastIndex = $count - 1 Local $lastPath = _mpv_get_property($pHandle, "playlist/" & $lastIndex & "/filename", "string") If $nextPath = $lastPath Then _mpv_command($pHandle, "playlist-remove", String($lastIndex)) EndIf EndIf ; ConsoleWrite($lastPath & @CRLF) If GUICtrlRead($idShuffle) = "Shuffle" Then GUICtrlSetData($idShuffle, "Sort") _ArrayShuffle($aPlaylist, 1) Else GUICtrlSetData($idShuffle, "Shuffle") _ArraySort($aPlaylist, 0, 1) EndIf $iIndex = _ArraySearch($aPlaylist, $sFile) $nextIndex = $iIndex + 1 If $nextIndex > $aPlaylist[0] Then $nextIndex = 1 $nextFile = $aPlaylist[$nextIndex] If StringInStr($nextFile, ":\") Then $nextPath = $nextFile Else $nextPath = $sFolder & $nextFile EndIf If Not StringInStr(".cda .mid", StringRight($nextFile, 4)) Then _mpv_command($pHandle, "loadfile", $nextPath, "append-play") EndIf ; ConsoleWrite(_mpv_get_property($pHandle, "playlist/" & $lastIndex & "/filename", "string") & @CRLF) EndFunc ; _Shuffle_MPV Func _Slider($controlID) ; Drag and drop the progrss bar or click anywhere on the slider to jump to a new media position If $bIsLoading Then Return $iSlider = 1 Local $x, $x2, $mediaPos, $aPos1, $sTime While _IsPressed("01", $hUser32DLL) If $controlID = $idSlider Then $aPos1 = WinGetPos($hMain) $x = MouseGetPos(0)-($aPos1[0] + $iMainBorderWidth + $iSliderPosX) If $x >= $iSliderLength Then $x = $iSliderLength ElseIf $x < 0 Then $x = 0 EndIf GUICtrlSetPos($idProgBar, $x + $iSliderPosX) GUICtrlSetPos($idProgBar2, $x / $iSliderLength * $iSliderLength2) If Not StringInStr(".cda .mid", StringRight($sFile, 4)) Then $mediaPos = $x / $iSliderLength * $iMediaLength Else $mediaPos = $x / $iSliderLength * $iMediaLength / 1000 EndIf $sTime =_SecondsToTime(Int($mediaPos), $hMain) GUICtrlSetData($idCurrentPos, $sTime) $sTime =_SecondsToTime(Int($mediaPos), $hVCGui) GUICtrlSetData($idCurrentPos2, $sTime) ElseIf $controlID = $idSlider2 Then $x2 = MouseGetPos(0) - $iVCLeft If $x2 > $iSliderLength2 Then $x2 = $iSliderLength2 If $x2 < 0 Then $x2 = 0 GUICtrlSetPos($idProgBar2, $x2) GUICtrlSetPos($idProgBar, $x2 / $iSliderLength2 * $iSliderLength + $iSliderPosX) $mediaPos = $x2 / $iSliderLength2 * $iMediaLength $sTime =_SecondsToTime(Int($mediaPos), $hMain) GUICtrlSetData($idCurrentPos, $sTime) $sTime =_SecondsToTime(Int($mediaPos), $hVCGui) GUICtrlSetData($idCurrentPos2, $sTime) EndIf Sleep(10) WEnd If Not StringInStr(".cda .mid", StringRight($sFile, 4)) Then _mpv_command($pHandle, "seek", $mediaPos + 0.1, "absolute+exact") Else _mciSendString("stop myMedia") If StringRight($sFile, 4) = ".cda" Then _mciSendString("play myMedia from " & Round($iTrackPos + $mediaPos * 1000 + 500)) Else _mciSendString("play myMedia from " & Round($mediaPos * 1000 + 500)) EndIf EndIf Sleep(20) $iSlider = 0 If $iPaused = 1 Then _PlayPause() EndIf EndFunc ; _Slider Func _SpeedDown() ; Decrease play speed by 0.1x _mpv_command($pHandle, "add", "speed", -0.1) Local $currentSpeed = _mpv_get_property($pHandle, "speed", "double") Local $osdText = "Speed: " & StringFormat("%.1f", $currentSpeed) & "x" _mpv_command($pHandle, "show-text", $osdText, "2000") EndFunc ; _SpeedDown Func _SpeedRevert() ; Revert play speed to default 1.0x _mpv_command($pHandle, "set", "speed", 1.0) _mpv_command($pHandle, "show-text", "Speed: 1.0x", "2000") EndFunc ; _SpeedRever Func _SpeedUp() ; Increase play speed by 0.1x _mpv_command($pHandle, "add", "speed", 0.1) Local $currentSpeed = _mpv_get_property($pHandle, "speed", "double") Local $osdText = "Speed: " & StringFormat("%.1f", $currentSpeed) & "x" _mpv_command($pHandle, "show-text", $osdText, "2000") EndFunc ; _SpeedUp Func _VCCreate() ; Create $hVCGui and video controls $iVCLeft = ($iClientWidth-$iVideoWidth)/2 $iVCTop = ($iClientHeight-$iVideoWidth)/2 $hVCGui = GUICreate("", $iVideoWidth, $iVCHeight, $iVCLeft, $iVCTop, $WS_POPUP, $WS_EX_LAYERED, $hVideoGUI) GUISetFont(10, 400, 0, "Arial", $hVCGui) $idSlider2 = GUICtrlCreateLabel("", 0, 5, $iVideoWidth, 14, BitOR($SS_NOPREFIX, $SS_LEFTNOWORDWRAP)) GUICtrlSetBkColor(-1, 0xD0D0D0) GUICtrlSetFont(-1, 10) GUICtrlSetResizing(-1, $GUI_DOCKBORDERS) $idRepeatAB2 = GUICtrlCreateLabel("", 0, 7, 10, 12) ; Pink bar to indicate A-B repeat positions in slider GUICtrlSetBkColor(-1, 0xD580FF) GUICtrlSetResizing(-1, $GUI_DOCKSIZE) GUICtrlSetState(-1, $GUI_HIDE) $idProgBar2 = GUICtrlCreateLabel("", 0, 5, $iProgBarWidth, 14) GUICtrlSetBkColor(-1, 0x566573) GUICtrlSetResizing(-1, $GUI_DOCKSIZE) $idCurrentPos2 = GUICtrlCreateLabel("00.00", 10, 23, 60, 15, $SS_RIGHT) GUICtrlSetFont(-1, 10, 600) GUICtrlSetResizing(-1, $GUI_DOCKLEFT+$GUI_DOCKSIZE) $idLength2 = GUICtrlCreateLabel("00:00", $iVideoWidth-70, 23, 60, 15, $SS_LEFT) GUICtrlSetFont(-1, 10, 600) GUICtrlSetResizing(-1, $GUI_DOCKRIGHT+$GUI_DOCKSIZE) $idExit = GUICtrlCreateLabel("🞭", $iVideoWidth/2-110, 23, 15, 25, BitOR($SS_CENTER, $SS_CENTERIMAGE)) GUICtrlSetFont(-1, 21, 400) GUICtrlSetResizing(-1, $GUI_DOCKHCENTER+$GUI_DOCKBOTTOM+$GUI_DOCKSIZE) $idPlay2 = GUICtrlCreateLabel("❚❚", $iVideoWidth/2-74, 27, 16, 18, BitOR($SS_CENTER, $SS_CENTERIMAGE)) GUICtrlSetFont($idPlay2, 17) GUICtrlSetResizing(-1, $GUI_DOCKHCENTER+$GUI_DOCKBOTTOM+$GUI_DOCKSIZE) $idPrevious2 = GUICtrlCreateLabel("β—€", $iVideoWidth/2-42, 28, 16, 18, BitOR($SS_CENTER, $SS_CENTERIMAGE)) GUICtrlSetFont(-1, 13) GUICtrlSetResizing(-1, $GUI_DOCKHCENTER+$GUI_DOCKBOTTOM+$GUI_DOCKSIZE) $idRepeat2 = GUICtrlCreateLabel("U", $iVideoWidth/2-29, 28, 16, 20, BitOR($SS_CENTER, $SS_CENTERIMAGE)) GUICtrlSetFont(-1, 10, 900) GUICtrlSetResizing(-1, $GUI_DOCKHCENTER+$GUI_DOCKBOTTOM+$GUI_DOCKSIZE) $idNext2 = GUICtrlCreateLabel("β–Ά", $iVideoWidth/2-16, 28, 16, 18, BitOR($SS_CENTER, $SS_CENTERIMAGE)) GUICtrlSetFont(-1, 13) GUICtrlSetResizing(-1, $GUI_DOCKHCENTER+$GUI_DOCKBOTTOM+$GUI_DOCKSIZE) $idSpeaker2 = GUICtrlCreateLabel("πŸ”Š", $iVideoWidth/2+14, 27, 16, 18, BitOR($SS_CENTER, $SS_CENTERIMAGE)) GUICtrlSetFont(-1, 15, 400) GUICtrlSetResizing(-1, $GUI_DOCKHCENTER+$GUI_DOCKBOTTOM+$GUI_DOCKSIZE) $idUp2 = GUICtrlCreateLabel("β–²", $iVideoWidth/2+30, 22, 15, 15, BitOR($SS_CENTER, $SS_CENTERIMAGE)) GUICtrlSetFont(-1, 10) GUICtrlSetResizing(-1, $GUI_DOCKHCENTER+$GUI_DOCKBOTTOM+$GUI_DOCKSIZE) GUICtrlSetTip(-1, $iVolume) $idDown2 = GUICtrlCreateLabel("β–Ό", $iVideoWidth/2+30, 36, 15, 15, $SS_CENTER);, $SS_CENTERIMAGE)) GUICtrlSetFont(-1, 10) GUICtrlSetResizing(-1, $GUI_DOCKHCENTER+$GUI_DOCKBOTTOM+$GUI_DOCKSIZE) GUICtrlSetTip(-1, $iVolume) $idFullScreen = GUICtrlCreateLabel("⇔", $iVideoWidth/2+58, 23, 20, 24, BitOR($SS_CENTER, $SS_CENTERIMAGE)) GUICtrlSetFont(-1, 20, 600) GUICtrlSetResizing(-1, $GUI_DOCKHCENTER+$GUI_DOCKBOTTOM+$GUI_DOCKSIZE) $idSetDefault = GUICtrlCreateLabel("βœ…", $iVideoWidth/2+92, 28, 20, 20, BitOR($SS_CENTER, $SS_CENTERIMAGE)) GUICtrlSetFont(-1, 12, 600) GUICtrlSetColor($idSetDefault, 0x000000) GUICtrlSetResizing(-1, $GUI_DOCKHCENTER+$GUI_DOCKBOTTOM+$GUI_DOCKSIZE) GUICtrlSetTip(-1, "Set this size and position as your default") Local $iTransColor, $iAlpha _WinAPI_GetLayeredWindowAttributes($hVCGui, $iTransColor, $iAlpha) WinSetTrans($hVCGui, "", 180) GUISetState(@SW_HIDE, $hVCGui) EndFunc ; _VCCreate Func _VCResize() ; Resize $hCVGui when $hVideoGUI is resized ; ConsoleWrite("VC Resized" & @CRLF) $aPos = WinGetPos($hVideoGUI) If Not IsArray($aPos) Then Return Local $iW, $iX, $iY If $iMaximized + $iFullScreen = 0 Then $iW = $aPos[2] - $iBorderWidth * 2 $iX = $aPos[0] + $iBorderWidth $iY = $aPos[1] + $aPos[3] - $iBorderWidth - $iVCHeight Else Local $aClient = WinGetClientSize($hVideoGUI) $iW = $aClient[0] $iX = 0 $iY = $aClient[1] If $iMaximized = 1 And $iFullScreen = 0 Then $iY += $iMaximizedTitleHeight EndIf $iY -= $iVCHeight EndIf $iSliderLength2 = $iW - $iProgBarWidth WinMove($hVCGui, "", $iX, $iY+1, $iW, $iVCHeight) Local $aPos1 = WinGetPos($hVCGui) $iVCLeft = $aPos1[0] $iVCRight = $aPos1[0] + $aPos1[2] $iVCBottom = $aPos1[1] + $aPos1[3] - 2 If @OSVersion = "WIN_11" Then ; Create round corners at left and right bottoms of $hCVGui Local $hRgn = _WinAPI_CreateRoundRectRgn(0, -$iVCHeight-13, $iW+1, $iVCHeight, 13, 13) _WinAPI_SetWindowRgn($hVCGui, $hRgn) _WinAPI_DeleteObject($hRgn) EndIf EndFunc ; _VCResize Func _VCShow() ; Adlib function to show video controls when mouse hovers the bottom area of $hVidoGUI, 249ms If WinGetState($hVideoGUI) < 7 Then Return Local Static $iInitialized = 0, $hTimer = TimerInit(), $iVCShown = 0 If $iInitialized = 0 Then If $iVCShown = 0 Then GUISetState(@SW_SHOWNOACTIVATE, $hVCGui) $iVCShown = 1 EndIf If TimerDiff($hTimer) < 3000 Then Return EndIf $iInitialized = 1 EndIf ; $iVCLeft, $iVCRight and $iVCBottom are defined in _VCResize() Local $iX = MouseGetPos(0), $iY = MouseGetPos(1) Local Static $iPrevX = 0, $iPrevY = 0 If $iX > $iVCLeft And $iX < $iVCRight And $iY > $iVCBottom - $iVCHeight And $iY < $iVCBottom Then ; always show the controls if the mouse is on $hVCGui GUISetState(@SW_SHOWNOACTIVATE, $hVCGui) ElseIf $iX > $iVCLeft And $iX < $iVCRight And $iY > $iVCBottom - 200 And $iY < $iVCBottom Then ; show the controls only if the mouse is inside the "Show" area ; if the mouse moves, the timer is initioalized If $iX <> $iPrevX Or $iY <> $iPrevY Then $hTimer = TimerInit() $iPrevX = $iX $iPrevY = $iY EndIf ; if 3 seconds have elapsed after initialization, $hVCGui is hidden If $hTimer = 0 Or TimerDiff($hTimer) > 3000 Then GUISetState(@SW_HIDE, $hVCGui) Else GUISetState(@SW_SHOWNOACTIVATE, $hVCGui) EndIf Else ; the controls are not visible if the mouse is outside the "Show" area $hTimer = 0 GUISetState(@SW_HIDE, $hVCGui) EndIf EndFunc ; _VC_Show Func _VideoClicked() ; Called by GUIGetMsg() $GUI_EVENT_PRIMARYDOWN in the main loop If MouseGetPos(1) > $iVCBottom + 70 Then Return ; $iVCBottom is defined in _VCResize() Local $tPoint = _WinAPI_GetMousePos() If WinGetHandle(_WinAPI_WindowFromPoint($tPoint)) <> $hVideoGUI Then Return Local $hTimer = TimerInit(), $iCount = 0 While TimerDiff($hTimer) <= $iDoubleclickTime If _IsPressed("01", $hUser32DLL) Then $iCount += 1 While _IsPressed("01", $hUser32DLL) Sleep(50) WEnd EndIf Sleep(10) WEnd If $iCount > 1 Then _FullScreen() ElseIf $iCount = 1 Then _PlayPause() EndIf While _IsPressed("01", $hUser32DLL) Sleep(10) WEnd EndFunc ; _VideoClicked Func _VideoRefresh() ; Adlib to give a heartbeat to the video renderer and prevent the system from freezing the video, 5 minutes ; Check if the center of the video window is visible on the screen ; Position of $hVideoGUI ($aPos) is updated by _VCResize() If $bIsLoading Then Return Local $tPoint = _WinAPI_CreatePoint($aPos[0]+$aPos[2]/2, $aPos[1]+$aPos[3]/2) Local $hTopWnd = _WinAPI_WindowFromPoint($tPoint) If $hTopWnd = $hVideoGUI Then Return ; Return if visible $iVideoRefresh = 1 ; Please let me know if anyone knows of a less intrusive way to keep the video renderer alive while in background EndFunc ; _VideoRefresh Func _VideoResize() ; Resize $hVideoGUI to fit aspect ratio If $sKeepAspect = "No" Then Return GuiSetState(@SW_HIDE, $hVCGui) Local $w, $h, $x, $y Local $aPos1 = WinGetPos($hVideoGUI) $w = $aPos1[2] - $iBorderWidth*2 If $w < 370 Then $w = 370 $h = Round($w/$iAspect) If $h > $iClientHeight-$iTitleHeight Then $h = $iClientHeight-$iTitleHeight $w = Round($h*$iAspect) EndIf $w += $iBorderWidth*2 $h += $iTitleHeight+$iBorderWidth $x = ($iClientWidth-$w)/2 $y = ($iClientHeight-$h)/2 WinMove($hVideoGUI, "", $x, $y, $w, $h) EndFunc ; _VideoResize Func _VolumeDown() ; Decrease application volume by 5/100 (click "β–Ό" or pres Ctrl+Alt+Down) If $bIsLoading Then Return $iVolume -= 5 If $iVolume < 0 Then $iVolume = 0 If Not StringInStr(".cda .mid", StringRight($sFile, 4)) Then _mpv_command($pHandle, "set", "ao-volume", $iVolume) _mpv_command($pHandle, "show-text", "Volume: " & $iVolume, "2000") Else DllCall($hWinmmDLL, "int", "waveOutSetVolume", "int", 0 , "int", Int($iVolume*655.35)) EndIf GUICtrlSetTip($idUp, $iVolume) GUICtrlSetTip($idDown, $iVolume) GUICtrlSetTip($idUp2, $iVolume) GUICtrlSetTip($idDown2, $iVolume) EndFunc ; _VolumeDown Func _VolumeSync() ; Adlib function to sync volume and mute state Windows volume mixer, 479ms If $bIsLoading Then Return Local Static $iAudioInitialized = 0, $iVideoInitialized = 0 If $iAudioInitialized = 0 And $isAudio = 1 Then Local Static $hTimer = TimerInit() If TimerDiff($hTimer) < 5000 Then Return EndIf $iAudioInitialized = 1 $hTimer = 0 EndIf If $iVideoInitialized = 0 And ($isVideo = 1 Or $isAudio = 2) Then Local Static $hTimer2 = TimerInit() If TimerDiff($hTimer2) < 5000 Then Return EndIf $iVideoInitialized = 1 $hTimer2 = 0 EndIf Local $mixerVolume If Not StringInStr(".cda .mid", StringRight($sFile, 4)) Then $mixerVolume = Round(_Audio_Action("GetVolume", "")*100/5)*5 Else $mixerVolume = Round(DllCall($hWinmmDLL, "int", "waveOutGetVolume", "ptr", 0, "DWORD*", 0)[2]/655.35/5)*5 EndIf If $iVolume <> $mixerVolume Then $iVolume = $mixerVolume GUICtrlSetTip($idUp, $iVolume) GUICtrlSetTip($idDown, $iVolume) If $isVideo = 1 Or $isAudio = 2 Then GUICtrlSetTip($idUp2, $iVolume) GUICtrlSetTip($idDown2, $iVolume) EndIf EndIf Local $muteState = _Audio_Action("GetMute", True) ; $muteState is 0 if unmuted, 1 if muted by click on Mixer mute icon, -1 if muted by click on zPlayer mute icon(SetMute) Local $muteStateMaster = _Audio_MasterVolume("GetMute") ; 1 - muted, 0 - unmuted If ($muteState = 1 Or $muteStateMaster = 1) And $iMute = 0 Then $iMute = 1 GUICtrlSetData($idSpeaker, "πŸ”‡") If $isVideo = 1 Or $isAudio = 2 Then GUICtrlSetData($idSpeaker2, "πŸ”‡") EndIf $iCycleMute = 1 ElseIf ($muteState = 0 And $muteStateMaster = 0) And $iMute = 1 Then $iMute = 0 GUICtrlSetData($idSpeaker, "πŸ”Š") If $isVideo = 1 Or $isAudio = 2 Then GUICtrlSetData($idSpeaker2, "πŸ”Š") EndIf $iCycleMute = 1 EndIf EndFunc ; _VolumeSync Func _VolumeUp() ; Increase application volume by 5/100 (click "β–²" or press Ctrl+Alt+Up) If $bIsLoading Then Return $iVolume += 5 If $iVolume > 100 Then $iVolume = 100 If Not StringInStr(".cda .mid", StringRight($sFile, 4)) Then _mpv_command($pHandle, "set", "ao-volume", $iVolume) _mpv_command($pHandle, "show-text", "Volume: " & $iVolume, "2000") Else DllCall($hWinmmDLL, "int", "waveOutSetVolume", "int", 0 , "int", Int($iVolume*655.35)) EndIf GUICtrlSetTip($idUp, $iVolume) GUICtrlSetTip($idDown, $iVolume) GUICtrlSetTip($idUp2, $iVolume) GUICtrlSetTip($idDown2, $iVolume) EndFunc ; _VolumeUp Func WM_WINDOWPOSCHANGED($hWnd, $MsgID, $wParam, $lParam) ; Sync movement of $hVideoGUI and $hVCGui #forceref $hWnd, $MsgID, $wParam, $lParam Local Static $bLock = False If $bLock Or Not BitAND(WinGetState($hWnd), 2) Then Return $GUI_RUNDEFMSG Local $aPos1 If $hWnd = $hCover Then $aPos1 = WinGetPos($hCover) If $aPos1[0] < 1 Then $aPos1[0] = 1 ElseIf $aPos1[0] > $iClientWidth - $iMainGuiWidth -1 Then $aPos1[0] = $iClientWidth - $iMainGuiWidth - 1 EndIf If $aPos1[1] < 0 Then $aPos1[1] = 0 ElseIf $aPos1[1] > $iClientHeight - $iMainGuiHeight - $iMainBarHeight Then $aPos1[1] = $iClientHeight - $iMainGuiHeight - $iMainBarHeight EndIf WinMove($hCover, "", $aPos1[0], $aPos1[1]) WinMove($hMain, "", $aPos1[0]-$iMainBorderWidth, $aPos1[1]) ElseIf $hWnd = $hVideoGUI Then $aPos1 = WinGetPos($hWnd) If Not IsArray($aPos) Then Return $GUI_RUNDEFMSG If $aPos1[0] = $aPos[0] And $aPos1[1] = $aPos[1] And $aPos1[2] = $aPos[2] And $aPos1[3] = $aPos[3] Then Return $GUI_RUNDEFMSG EndIf If $iMaximized = 0 And WinGetState($hVideoGUI) > 32 Then $iMaximized = 1 ; Window was dragged upward causing maximization GUISetState(@SW_MAXIMIZE, $hVideoGUI) If $iMaximizedTitleHeight = 0 Then $aPos1 = WinGetClientSize($hVideoGUI) $iMaximizedTitleHeight = $iClientHeight-$aPos1[1] EndIf EndIf If $iMaximized = 1 And WinGetState($hVideoGUI) < 32 Then $iMaximized = 0 ; Maximized window was dragged downward causing restoration GUISetState(@SW_RESTORE, $hVideoGUI) EndIf $bLock = True _VCResize() Sleep(20) $bLock = False EndIf Return $GUI_RUNDEFMSG EndFunc ; WM_WINDOWPOSCHANGED Func zPlayerIcon() ; When run uncompiled, this will create zPlayer.ico file in the script directory if it does not exist Local $sB64String = "" $sB64String &= "AAABAAIAICAQAAEABADoAgAAJgAAABAQEAABAAQAKAEAAA4DAAAoAAAAIAAAAEAAAAABAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAgAAAAICAAIAA" $sB64String &= "AACAAIAAgIAAAICAgADAwMAAAAD/AAD/AAAA//8A/wAAAP8A/wD//wAA////AAd3d3d3d3d3d3d3d3d3d3AHd3d3d3d3d3d3d3d3d3dwB3iIiIiIiIiIiIiIiIiHcAd4" $sB64String &= "iIiIiIiIiIiIiIiIh3AHeIiIiIiIiIiIiIiIiIdwB3iIiIiIiIiIiIiIiIiHcAd4iIh1VVVVVVBXiIiIh3AHeIiIcAiIiIh1BYiIiIdwB3iIiIcFiIiIiHB4iIiHcAd4" $sB64String &= "iIiIUHiIiIiHWIiIh3AHeIiIiIAIiIiIiHiIiIdwB3iIiIiHBYiIiIiIiIiHcAd4iIiIiFB4iIiIiIiIh3AHeIiIiIiACIiIiIiIiIdwB3iIiIiIhwWIiIiIiIiHcAd4" $sB64String &= "iIiIiIhQeIiIiIiIh3AHeIiIiIiIgAeIiIiIiIdwB3iIiIiIiIcAiIiIiIiHcAd4iIiIiIiIUFiIiIiIh3AHeIiIiIiIiIAHiIiIiIdwB3iIiIiIiIiIAIiIiIiHcAd4" $sB64String &= "iIiHiIiIiHBYiIiIh3AHeIiIhXiIiIiFB4iIiIdwB3iIiIcHiIiIiACIiIiHcAd4iIiIAFeIiIhwGIiIh3AHeIiIiHUFVVVVVViIiIdwB3iIiIiIiIiIiIiIiIiHcAd4" $sB64String &= "iIiIiIiIiIiIiIiIh3AHeIiIiIiIiIiIiIiIiIdwB3iIiIiIiIiIiIiIiIiHcAd3d3d3d3d3d3d3d3d3d3AHd3d3d3d3d3d3d3d3d3dwgAAAAYAAAAGAAAABgAAAAYAA" $sB64String &= "AAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAA" $sB64String &= "AAGAAAABgAAAAYAAAAEoAAAAEAAAACAAAAABAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAgAAAAICAAIAAAACAAIAAgIAAAICAgADAwMAAAAD/AAD/" $sB64String &= "AAAA//8A/wAAAP8A/wD//wAA////AHd3d3d3d3d3eIiIiIiIiId4iIiIiIiIh3iIV3d1WIiHeIhwiIhXiId4iIVYiIeIh3iIiAeIiIiHeIiIcHiIiId4iIiHCIiIh3iI" $sB64String &= "iIhViIiHeIh4iIB4iId4iHWIhweIh3iIhVd3VYiHeIiIiIiIiId4iIiIiIiIh3d3d3d3d3d3AAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAA" $sB64String &= "AAEAAAABAAAAAQAAAAEAAAABAAAAAQ==" Local $aCrypt = DllCall("Crypt32.dll", "bool", "CryptStringToBinaryA", "str", $sB64String, "dword", 0, "dword", 1, "ptr", 0, "dword*", 0, "ptr", 0, "ptr", 0) If @error Or Not $aCrypt[0] Then Return SetError(1, 0, "") Local $bBuffer = DllStructCreate("byte[" & $aCrypt[5] & "]") $aCrypt = DllCall("Crypt32.dll", "bool", "CryptStringToBinaryA", "str", $sB64String, "dword", 0, "dword", 1, "struct*", $bBuffer, "dword*", $aCrypt[5], "ptr", 0, "ptr", 0) If @error Or Not $aCrypt[0] Then Return SetError(2, 0, "") Local $bString = DllStructGetData($bBuffer, 1) Local $hFile = FileOpen($sIconFile, 18) FileWrite($hFile, $bString) FileClose($hFile) EndFunc ; zPlayerIcon