; https://www.autoitscript.com/forum/files/file/484-zplayer-a-small-audio-and-video-play #Region ;**** Directives created by AutoIt3Wrapper_GUI **** #AutoIt3Wrapper_UseX64=Y ; Set this value to N if you want to run/compile this script in x86 mode #AutoIt3Wrapper_Icon=zPlayer.ico #AutoIt3Wrapper_OutFile=zPlayer-mpv.exe #AutoIt3Wrapper_Res_Fileversion=7.0.0.0 #AutoIt3Wrapper_Res_Description=zPlayer-mpv Beta 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 **** ; Launch a background instance of zPlayer asynchronously via command-line arguments right after startup. ; This prevents the main UI thread and progress bar from freezing while waiting for Windows to initialize ; the MIDI synthesizer, which takes about 15 seconds. This lag typically occurs when zPlayer encounters ; a MIDI file for the first time after system boot. This background instance will exit immediately after ; executing the _ExecuteBackgroundMidi() function. Global $hWinmmDLL = DllOpen("winmm.dll") ; https://learn.microsoft.com/en-us/windows/win32/multimedia/multimedia-command-strings If $hWinmmDLL = -1 Then Exit MsgBox(0, "DLL Open Failure", "Winmm.dll could not be opened!") If $CmdLine[0] > 0 And $CmdLine[1] = "/PreloadMidiMode" Then _PlayBackgroundMidi() EndIf #include _Singleton("zPlayer") #include ; includes Array.au3 #include #include ; includes WindowsConstants.au3 #include ; includes WinAPIMisc.au3 #include #include #include #include ; includes WinAPIProc.au3 #include ; includes WinAPISysInternals.au3 Opt("GUICloseOnESC", 0) Opt("MustDeclareVars", 1) Global $iRet If Not FileExists(@ScriptDir & "\mpv.exe") Then $iRet = MsgBox(262148, "Welcome to zPlayer", _ "This program requires 'mpv.exe' to be placed in the player folder." & @CRLF & @CRLF & _ "Would you like to open the download page in your web browser?" & @CRLF & @CRLF & _ "[Instructions]" & @CRLF & _ "1. Download the latest 'mpv-x86_64-YYYYMMDD-git-xxxxxxx.7z' file." & @CRLF & _ "2. Extract Only 'mpv.exe' and copy it into this player folder." & @CRLF & _ "3. Restart zPlayer.") If $iRet = 6 Then ShellExecute("https://sourceforge.net/projects/mpv-player-windows/files/64bit/") EndIf Exit EndIf ; Create icon file from Base64 string Global $sIconFile = @ScriptDir & "\zPlayer.ico" If Not FileExists($sIconFile) And Not @Compiled Then zPlayerIcon() Global $aPos = WinGetPos("[Class:Shell_TrayWnd]") ; 0, 1032, 1920, 48 Global $iClientHeight = $aPos[1] Global $iClientWidth = $aPos[2] ; Create $hVideoGUI to enclose video image Global $iVideoWidth = Int($iClientWidth/3*2) Global $iVideoHeight = Int($iVideoWidth*9/16) If $iVideoHeight > Int($iClientHeight*2/3) Then $iVideoHeight = Int($iClientHeight*2/3) $iVideoWidth = Int($iVideoHeight*16/9) EndIf Global $iMinimized Global $hVideoGUI = GUICreate("zPlayer", $iVideoWidth, $iVideoHeight, -1, -1, $WS_OVERLAPPEDWINDOW) GUISetIcon($sIconFile) GUISetBkColor(0x000000, $hVideoGUI) 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 $aVideoPrePos = WinGetPos($hVideoGUI) Global $aVideoDefPos = $aVideoPrePos Global $aNewPos Global $sPipePath = "\\.\pipe\mpvsocket" Global $hMPV_Process = 0 Global $hPipe = -1 ; A single pipe handle to send and receive data Global $sBuffer = "" Local $sArgs = '--wid=' & Int($hVideoGUI) & _ ' --vo=gpu' & _ ' --gpu-api=auto' & _ ; d3d11 ' --profile=gpu-hq' & _ ' --hwdec=auto-safe' & _ ' --scale=bilinear' & _ ' --cscale=bilinear' & _ ' --dscale=bilinear' & _ ' --sub-auto=all' & _ ' --no-osc' & _ ' --no-input-default-bindings' & _ ' --keep-open=yes' & _ ' --idle=yes' & _ ' --reset-on-next-file=all' & _ ' --keepaspect-window=yes' & _ ' --input-ipc-server=' & $sPipePath Local $sCmd = 'mpv.exe ' & $sArgs Run($sCmd) $hMPV_Process = ProcessExists("mpv.exe") If Not $hMPV_Process Then $hMPV_Process = ProcessWait("mpv.exe", 3) EndIf If Not $hMPV_Process Then MsgBox(16, "Error", "mpv.exe could not be executed." & @CRLF & "Please try again.") Exit EndIf ; Allow time for mpv core engine and IPC server to be ready Sleep(500) $hPipe = 0 For $iAttempt = 1 To 10 ; Request Windows to wait a maximum of 500ms until $sPipePath is opened DllCall("kernel32.dll", "bool", "WaitNamedPipeW", "wstr", $sPipePath, "dword", 500) Local $aRet = DllCall("kernel32.dll", "handle", "CreateFileW", _ "wstr", $sPipePath, _ "dword", 0xC0000000, _ ; GENERIC_READ | GENERIC_WRITE "dword", 3, _ ; FILE_SHARE_READ | FILE_SHARE_WRITE "ptr", 0, _ "dword", 3, _ ; OPEN_EXISTING "dword", 0x40000000, _ ; FILE_FLAG_OVERLAPPED "ptr", 0) If Not @error And IsArray($aRet) And $aRet[0] <> -1 And $aRet[0] <> 0 Then $hPipe = $aRet[0] ExitLoop EndIf Sleep(100) Next If $hPipe = 0 Or $hPipe = -1 Then MsgBox(16, "Error", "Connection to mpv IPC pipe failed." & @CRLF & "Please try again.") ProcessClose($hMPV_Process) Exit EndIf ; Register mpv properties to observe _MPV_SendCommand('{"command": ["observe_property", 1, "time-pos"]}') ; Absolutely required to get $iCurrentPos ; duration, video-out-params and track-list properties to be requested by file-loaded event of _MPV_ParseResponse() _MPV_SendCommand('{"command": ["set_property", "keep-open", "no"]}') _MPV_SendCommand('{"command": ["set_property", "gapless-audio", "yes"]}') HotKeySet("^!{right}", _PlayNext) ; Play next file HotKeySet("^!{left}", _PlayPrevious) ; Play previous file HotKeySet("^!{up}", _VolumeUp) ; Increase application volume level HotKeySet("^!{down}", _VolumeDown) ; Decrease application volume level ; 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 HotKeySet("^!{-}", _VolumeDown) ; Decrease application volume level HotKeySet("^!{]}", _SpeedUp) ; Increase play speed by 1/10 HotKeySet("^!{[}", _SpeedDown) ; Decrease play speed by 1/10 HotKeySet("^!{BS}", _SpeedRevert) ; Revert speed to 1 HotKeySet("^!{END}", _Exit) ; Exit the program HotKeySet("^!p", _Pause) ; Play/Pause HotKeySet("^!s", _Shuffle) ; Shuffle/Sort playlist HotKeySet("^!m", _Mute) ; Mute on/off HotKeySet("^!r", _RepeatCurrentFile) ; Repeat current file on/off HotKeySet("^!h", _Help) ; Open/Close Help window HotKeySet("^!l", _PlaylistShow) ; Open/Close Playlist and double click an item to play HotKeySet("^!i", _InternetSearch) ; Search the current title in internet HotKeySet("^!f", _FilePropertiesShow) ; Open/Close properties of current file ;HotKeySet("{F11}", _FullScreen) ; Full screen mode on/off, to be declared in _HotkeySet() adlib function ;HotKeySet("{ESC}", _FullScreen) ; Full screen mode off, to be declared in _HotkeySet() adlib function HotKeySet("^!o", _Options) ; Open/Close Options window HotKeySet("^!c", _LoadFolder) ; Change folder HotKeySet("^!v", _Execute) ; Execute an expression HotKeySet("^!z", _MinimizeRestore) ; Minimize/Restore a full screen video window HotKeySet("^!w", _WinDefaultPos) ; Move all GUIs to default positions and bring them to foreground HotKeySet("^!t", _SetMainOnTop) ; Bring $hMain to foreground + Toggle its top window state HotKeySet("^{left}", _JumpPosition) ; Jump 5 seconds backward HotKeySet("^+{left}", _JumpPosition) ; Jump 30 seconds backward HotKeySet("^{right}", _JumpPosition) ; Jump 5 seconds forward HotKeySet("^+{right}", _JumpPosition) ; Jump 30 seconds forwaard ; Read playack environment vaiables from zPlayer.ini file Global $sIniFile = @ScriptDir & "\zPlayer.ini" Global $sFolder = IniRead($sIniFile, "Player", "Folder", @ScriptDir) If StringRight($sFolder, 1) <> "\" Then $sFolder &= "\" Global $sAudioTypes = IniRead($sIniFile, "Player", "Audio File Types", "mp3 wav wma ogg ape flac") Global $sVideoTypes = IniRead($sIniFile, "Player", "Video File Types", "asf mp4 wmv avi mkv flv webM") Global $sMpvFileTypes = $sAudioTypes & " " & $sVideoTypes Global $sMciFileTypes = "mid midi rmi cda" Global $sFileTypes = $sMpvFileTypes & " " & $sMciFileTypes Global $sKeepAspect = IniRead($sIniFile, "Player", "Keep Video Aspect", "Yes") If $sKeepAspect = "Yes" Then _MPV_SendCommand('{"command": ["set_property", "keepaspect", true]}') Else _MPV_SendCommand('{"command": ["set_property", "keepaspect", false]}') EndIf Global $iVolume = IniRead($sIniFile, "Player", "Audio Volume Level", 100) If $iVolume > 100 Then $iVolume = 100 If $iVolume < 20 Then $iVolume = 20 Global $sAudioMode = IniRead($sIniFile, "Player", "Audio EQ Mode", "Normal") Global $sColorScheme = IniRead($sIniFile, "Player", "Color Scheme", "Lavender") Global $iMainIsOnTop = IniRead($sIniFile, "Player", "Always On Top", "No") If $iMainIsOnTop = "No" Then $iMainIsOnTop = 0 Else $iMainIsOnTop = 1 EndIf Global $aCoverPos = IniRead($sIniFile, "Player", "Main Window Position", "1,0") 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" ; Create main GUI 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 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 $ctrlClose = 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 ; Global variables for window metrics $aPos = WinGetPos($hVideoGUI) Global $iBorderWidth = ($aPos[2]-$iVideoWidth)/2 Global $iTitleHeight = $aPos[3]-$iVideoHeight-$iBorderWidth Global $iMaximizedTitleHeight ; To be defined in _Play() ; Global variables for playback Global $aGUIMsg Global $sGUIMsg Global $aFiles Global $aItems[1][3] Global $aColors[1][3] Global $sCurrentFile Global $sFile Global $sPath Global $sTitle Global $iExecute Global $iFolderLoaded Global $iIndex Global $iMainIsMinimized Global $iMediaLength Global $iCurrentPos Global $iMute Global $iOptions Global $iPaused Global $iPlaying Global $iPlaylist Global $iProperties Global $iResumePosition Global $iShuffled Global $iFadeStep Global $iPlayPrevious Global $hTopWnd Global $bFirstMidiFile = True 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 Exit MsgBox($MB_OK, "DLL Open Failure", "user32.dll could not be opened!") Global $oShellApp = ObjCreate("shell.application") ; GetDetailsOf() ; Global variables for repeat functions Global $iRepeatAB Global $iRepeatABWin Global $iRepeatCurrentFile Global $iRepeatFilesWin Global $aFilesToRepeat[1] ; Global variables for mpv Global $isAudio, $isVideo, $bHasAlbumArt Global $iImageHeight Global $iImageWidth Global $iAspect Global $iMaximized Global $iFullScreen Global $bNextTrackTriggered = False Global $iTrimTime ; To be defined in _Play() depending on file type ; 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, $iCD ; 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 variables for _GetLength() adlib function Global $iAllDone = -1 Global $iDoing Global $iTitleColored ; 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, $aLinks ; 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 _PlaylistCreate() ; Create file properties window Global $iPropertyWidth = 450 Global $iPropertyHeight = 320 Global $iNameColWidth = 100 Global $hProperties = GUICreate("File Properties", $iPropertyWidth, $iPropertyHeight+25, -1, 0, $WS_SIZEBOX, -1) GUISetIcon($sIconFile) GUISetFont(9, 400, 0, $sFontName, $hProperties) Global $idPropertiesView = GUICtrlCreateListView("Property|Value (Double-click to copy)", 5, 0, $iPropertyWidth-3, $iPropertyHeight-5, _ BitOR($LVS_SHOWSELALWAYS, $LVS_NOSORTHEADER, $LVS_REPORT, $LVS_SINGLESEL), _ BitOR($LVS_EX_FULLROWSELECT, $LVS_EX_GRIDLINES)) GUICtrlSetResizing(-1, $GUI_DOCKBORDERS) _GUICtrlListView_SetColumnWidth($idPropertiesView, 0, $iNameColWidth) _GUICtrlListView_SetColumnWidth($idPropertiesView, 1, $iPropertyWidth-$iNameColWidth-15) _SetTaskBar($hProperties, "Delete Tab") ; Create GUI for A-B repeat function Global $iRepeatABWidth = 200 Global $iRepeatABHeieght = 96 Global $iRepeatABStart Global $iRepeatABEnd Global $hRepeatAB = GUICreate("", $iRepeatABWidth, $iRepeatABHeieght, 0, 0, $WS_POPUPWINDOW, -1, $hMain) GUISetFont(10, 400, 0, $sFontName, $hRepeatAB) GUICtrlCreateLabel("Set A-B Repeat Positions", 10, 8, 160, 15) GUICtrlSetFont(-1, -1, -1, $GUI_FONTUNDER) GUICtrlCreateLabel("Start Position:", 10, 29, 85, 15) GUICtrlCreateLabel("End Position:", 10, 49, 85, 15) Global $idStart = GUICtrlCreateInput("", 97, 27, 53, 18, $SS_RIGHT) GUICtrlSetLimit(-1, 6) Global $idEnd = GUICtrlCreateInput("", 97, 47, 53, 18, $SS_RIGHT) GUICtrlSetLimit(-1, 6) GUICtrlCreateLabel("mm:ss", 152, 29, 45, 15) GUICtrlCreateLabel("mm:ss", 152, 49, 45, 15) Global $idApply = GUICtrlCreateButton("Apply", 35, 69, 50, 22) Global $idHide = GUICtrlCreateButton("Close", 115, 69, 50, 22) GUISetState(@SW_HIDE, $hRepeatAB) ; Create GUI for multi-file repeat function Global $hRepeatFiles = GUICreate("", $iRepeatABWidth, $iRepeatABHeieght, 0, 0, $WS_POPUPWINDOW, -1, $hMain) GUISetFont(10, 400, 0, $sFontName, $hRepeatFiles) GUICtrlCreateLabel("Enter item numbers of files to", 15, 10, 170, 15) GUICtrlCreateLabel("repeat. (Example: 1,3-5,9-7)", 15, 27, 170, 15) Global $idFiles = GUICtrlCreateInput("", 15, 47, 170, 18, $SS_LEFT) Global $idFilesApply = GUICtrlCreateButton("Apply", 35, 69, 50, 22) Global $idFilesHide = GUICtrlCreateButton("Close", 115, 69, 50, 22) GUISetState(@SW_HIDE, $hRepeatFiles) ; Create video controls at the bottom of $hVideoGUI Global $iVCHeight = 60 Global $iSliderLength2, $iVCLeft, $iVCRight, $iVCBottom, $iVCTop ; Controls in $hVCGui Global $hVCGui, $idSlider2, $idProgBar2, $idRepeatAB2, $idCurrentPos2, $idLength2, $idExit, $idPlay2 Global $idPrevious2, $idRepeat2, $idNext2, $idSpeaker2, $idUp2, $idDown2, $idVolume2, $idFullScreen, $idSetDefault _VCCreate() ; Create GUI for execution of AutoIt expression Global $hExecute = GUICreate("Execute an Expression", 350, 250, -1, -1, $WS_SYSMENU, -1) GUISetIcon($sIconFile) GUISetFont(10, 400, 0, $sFontName, $hExecute) GUICtrlCreateLabel("Enter Expression:", 15, 15, 170, 15) Global $idExpression = GUICtrlCreateInput("", 15, 35, 250, 18) Global $idExecute = GUICtrlCreateButton("Execute", 265, 34, 70, 20) GUICtrlCreateLabel("The value is:", 15, 70, 320, 15) Global $idResult = GUICtrlCreateLabel("", 15, 90, 320, 120) WinSetOnTop($hExecute, "", 1) _SetTaskBar($hExecute, "Delete Tab") ; Create GUI for moving a playlist item to different position Global $hMove = GUICreate("Move Item", 400, 170, -1, -1, $WS_SYSMENU, -1) GUISetIcon($sIconFile) GUISetFont(10, 400, 0, $sFontName, $hMove) Global $idMoveFile = GUICtrlCreateLabel("", 20, 15, 360, 30) GUICtrlCreateLabel("Move this item to item number: ", 20, 60, 200, 20) Global $idMoveItem = GUICtrlCreateInput("", 210, 60, 50, 18, $ES_NUMBER+$ES_CENTER) Global $idMoveOk = GUICtrlCreateButton("OK", 125, 100, 60, 25) Global $idMoveCancel = GUICtrlCreateButton("Cancel", 215, 100, 60, 25) ; Create GUI for saving a custom playlist Global $hCustom = GUICreate("Save Custom Playlist", 414, 170, -1, -1, $WS_SYSMENU, -1) GUISetIcon($sIconFile) GUISetFont(10, 400, 0, $sFontName, $hCustom) GUICtrlCreateLabel("Enter full path to the folder where custom playlist is to be saved:", 20, 15, 374, 20) Global $idCustomDir = GUICtrlCreateInput("", 20, 40, 351, 18) Global $idCustomSelect = GUICtrlCreateButton("<", 370, 39, 20, 20) GUICtrlSetFont(-1, 10, 600) GUICtrlCreateLabel("(Create if it does not exist. Overwrite if it does exist.)", 20, 60, 360, 20) Global $idCustomOk = GUICtrlCreateButton("OK", 132, 100, 60, 25) Global $idCustomCancel = GUICtrlCreateButton("Cancel", 222, 100, 60, 25) ; Create Options window Global $hOptions Global $idResume1, $idResume2, $idResume3, $idPrefTotal, $idPrefPlayed Global $idAudioTypes, $idVideoTypes Global $idLavender, $idBlue, $idGreen, $idDefault Global $idAspectYes, $idAspectNo Global $idNormal, $idBass, $idClear, $idPop, $idCinema, $idMidnight, $idSpeech Global $idResumePosition _OptionsCreate() ; 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 GUIRegisterMsg($WM_MOVE, "WM_MOVE") ; Sync Movement of $hRepeatAB and $hRepeatFiles with $hMain GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY") ; Fill virtual listview GUIRegisterMsg($WM_WINDOWPOSCHANGED, "WM_WINDOWPOSCHANGED") ; Sync movement of $hMain/$hCover and $hVideoGUI Global $oPlaylist = ObjCreate("Scripting.Dictionary") WinMove($hCover, "", $aCoverPos[0], $aCoverPos[1]) ; Main window inherits its position from previous session ; Global variables for $hMain colors Global $iBarColor ; Color of maian GUI's title bar Global $iBKColor ; Background color of main GUI Global $iBtnColor ; Color of buttons Global $iBtnColor2 ; Color of buttons when the mouse hovers over them Global $iSliderColor ; Color of slider _OptionsColorChange() GUISetState(@SW_SHOW, $hCover) GUISetState(@SW_SHOW, $hMain) GUISetState(@SW_SHOW, $hChildGUI) If @Compiled Then ; If running as a compiled EXE: Launch another instance of itself with the argument. Run('"' & @ScriptFullPath & '" /PreloadMidiMode', "", @SW_HIDE) Else ; If running as an uncompiled script (.au3): Use the AutoIt interpreter to run the script file. Run('"' & @AutoItExe & '" "' & @ScriptFullPath & '" /PreloadMidiMode', "", @SW_HIDE) EndIf ;~ AdlibRegister("_Marquee", 40) ; Display title with long file name in marquee style ;~ AdlibRegister("_VCShow", 500) ; Show video control when mouse pointer enters the lower side of video window ;~ AdlibRegister("_HotkeySet", 1000) ; Set/unset {F11} and {ESC} hotkeys for video fullscreen ;~ AdlibRegister("_ProgressBar", 250) ; Display progress of playback, with progress bar and time in hh:mm:ss format ;~ AdlibRegister("_VolumeFadein", 100) ; Simulate audio fade-in when resuming playback of previous session ;~ AdlibRegister("_GetLength", 25) ; Fill the Length column of playlist with media lengths in hh:mm:ss format ;~ AdlibRegister("_SaveCoverPos", 1000) ; Save position of $hCover for $GUI_EVENT_RESTORE to previous position ;~ AdlibRegister("_SaveVideoPos", 1000) ; Save position of $hVideoGUI 1 sec after its position is changed ;~ AdlibRegister("_ActivateSpeakers", 30000); Keep the speakers continuously active while media is paused AdlibRegister("_OptionsColorButton", 150) ; Change colors of $hMain buttons when the mouse hovers over them Opt("TrayMenuMode", 3) TrayCreateItem("zPlayer") TrayCreateItem("") Global $idTrayExit = TrayCreateItem("Exit") TrayItemSetState($idTrayExit, 4) ; Menuitem will be unchecked TraySetIcon($sIconFile) _LoadLastFolder() While 1 ; Main loop $aGUIMsg = GUIGetMsg(1) $sGUIMsg = $aGUIMsg[0] Switch $aGUIMsg[1] Case $hCover Switch $sGUIMsg Case $ctrlClose _Exit() Case $idMinimize 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, $hVCGui, $hChildGUI Switch $sGUIMsg Case $GUI_EVENT_CLOSE, $idExit _Exit() Case $GUI_EVENT_MINIMIZE ; When $hMain is minimized by clicking on zPlayer taskbar icon $iMainIsMinimized = 1 Case $GUI_EVENT_RESTORE ; When $hMain is restored by clicking on zPlayer taskbar icon $iMainIsMinimized = 0 Case $idFile _LoadFiles() Case $idFolder $sLoadFolderFrom = "idFolder" _LoadFolder() Case $idPlay, $idPlay2 _Pause() Case $idPrevious, $idPrevious2 _PlayPrevious() Case $idNext, $idNext2 _PlayNext() Case $idSpeaker, $idSpeaker2 _Mute() Case $idUp, $idUp2 While _IsPressed("01", $hUser32DLL) = 1 ; Left mouse button _VolumeUp() WEnd Case $idDown, $idDown2 While _IsPressed("01", $hUser32DLL) = 1 ; Left mouse button _VolumeDown() WEnd Case $idShuffle _Shuffle() Case $idTitle $sPlaylistShowFrom = "idTitle" _PlaylistShow() $sPlaylistShowFrom = "" Case $idRepeat, $idRepeat2 _RepeatCurrentFile() Case $idFullScreen _FullScreen() While _IsPressed("01", $hUser32DLL) Sleep(10) WEnd Case $idSetDefault If $iFullScreen = 1 Then _FullScreen() ElseIf $iMaximized = 1 Then $iMaximized = 0 GUISetState(@SW_RESTORE, $hVideoGUI) EndIf $aPos = WinGetPos($hVideoGUI) If $aPos[0] <> $aVideoDefPos[0] Or $aPos[1] <> $aVideoDefPos[1] Or $aPos[2] <> $aVideoDefPos[2] Or $aPos[3] <> $aVideoDefPos[3] Then WinMove($hVideoGUI, "", $aVideoDefPos[0], $aVideoDefPos[1], $aVideoDefPos[2], $aVideoDefPos[3]) _VCResize() EndIf While _IsPressed("01", $hUser32DLL) Sleep(10) WEnd Case $idSlider, $idSlider2 _Slider($aGUIMsg[1]) Case $idCurrentPos, $idCurrentPos2 _RepeatAB() Case $idLength, $idLength2 _RepeatFiles() EndSwitch Case $hVideoGUI Switch $sGUIMsg Case $GUI_EVENT_CLOSE _PlayNext() Case $GUI_EVENT_MAXIMIZE ; $x = -$iBorderWidth; $y = -$iBorderWidth; $w = @DesktopWidth+$iBorderWidth*2; $h = $iClientHeight+$iBorderWidth $iMaximized = 1 _VCResize() Case $GUI_EVENT_MINIMIZE $iMinimized = 1 Case $GUI_EVENT_RESIZED _VideoResize() Case $GUI_EVENT_RESTORE $iMinimized = 0 $iMaximized = 0 _VCResize() Case $idAspect_Hotkey _AspectToggler() Case $idShot_Hotkey Local $sTimestamp = @YEAR & @MON & @MDAY & "_" & @HOUR & @MIN & @SEC Local $sFilePath = StringReplace(@ScriptDir & "\Shot_" & $sTimestamp & ".jpg", '\', '\\') _MPV_SendCommand('{"command": ["screenshot-to-file", "' & $sFilePath & '", "video"]}') _MPV_SendCommand('{"command": ["show-text", "Screenshot Saved", 2000]}') Case $idF11_Hotkey _FullScreen() Case $idEsc_Hotkey If $iFullScreen = 1 Then _FullScreen() EndIf EndSwitch Case $hPlaylist _PlaylistMsg() Case $hCustom Switch $aGUIMsg[0] Case $GUI_EVENT_CLOSE, $idCustomCancel GUICtrlSetData($idCustomDir, "") GUISetState(@SW_HIDE, $hCustom) Case $idCustomSelect $sDir = FileSelectFolder("Select folder", @ScriptDir, 0, "", $hPlaylist) If $sDir <> "" Then GUICtrlSetData($idCustomDir, $sDir) GUICtrlSetState($idCustomDir, $GUI_FOCUS) Send("{END}") Case $idCustomOk _PlaylistCustomize() EndSwitch Case $hProperties Switch $aGUIMsg[0] Case $GUI_EVENT_CLOSE WinSetOnTop($hProperties, "", 0) GUISetState(@SW_HIDE, $hProperties) $iProperties = 0 Case $GUI_EVENT_RESIZED $aPos = WinGetClientSize($hProperties) _GUICtrlListView_SetColumnWidth($idPropertiesView, 1, $aPos[0]-$iNameColWidth-15) EndSwitch Case $hHelp Switch $aGUIMsg[0] Case $GUI_EVENT_CLOSE GUIDelete($hHelp) $hHelp = "" EndSwitch Case $hRepeatAB _RepeatABMsg() Case $hRepeatFiles _RepeatFilesMsg() Case $hExecute Switch $aGUIMsg[0] Case $GUI_EVENT_CLOSE GUICtrlSetData($idExpression, "") GUICtrlSetData($idResult, "") GUISetState(@SW_HIDE, $hExecute) $iExecute = 0 Case $idExpression, $idExecute Local $sExpression = GUICtrlRead($idExpression) If $sExpression <> "" Then Local $sValue = Execute($sExpression) If $sValue = "" Then GUICtrlSetData($idResult, '""') Else GUICtrlSetData($idResult, $sValue) EndIf EndIf EndSwitch Case $hOptions _OptionsMsg() EndSwitch If TrayGetMsg() = $idTrayExit Then _Exit() If StringInStr($sMpvFileTypes, _GetFileExtension($sCurrentFile)) Then If IsArray($aFiles) Then _MPV_CheckIPCResponse() EndIf If _IsPressed("01", $hUser32DLL) And $isVideo Then _VideoClicked() EndIf ContinueLoop Else If $iPlaying = 0 Or $iPaused = 1 Then ContinueLoop Local $mediaPos= mciSendString("status myMedia position") If $iRepeatAB = 1 Then If $iTrack = 0 Then If Int($mediaPos/1000) >= $iRepeatABEnd Or Int($mediaPos/1000) < $iRepeatABStart Then mciSendString("play myMedia from " & $iRepeatABStart*1000) EndIf Else If $mediaPos >= $iTrackPos + $iRepeatABEnd*1000 Or $mediaPos < $iTrackPos + $iRepeatABStart*1000 Then mciSendString("play myMedia from " & $iTrackPos+$iRepeatABStart*1000) EndIf EndIf EndIf If $iTrack > 0 And Int(mciSendString("status myMedia position")/1000) >= Int(($iTrackPos+$iMediaLength)/1000) Then mciSendString("stop myMedia") EndIf If mciSendString("status myMedia mode") <> "stopped" Then ContinueLoop If $iRepeatCurrentFile = 1 Then If $iTrack = 0 Then mciSendString("play myMedia from 0") Else mciSendString("play myMedia from " & $iTrackPos) EndIf ContinueLoop EndIf EndIf GUISetState(@SW_HIDE, $hVideoGUI) AdlibUnRegister("_Marquee") AdlibUnRegister("_ProgressBar") GUICtrlSetData($idTitle, "Media title") GUICtrlSetData($idCurrentPos, "00:00") GUICtrlSetData($idCurrentPos2, "00:00") GUICtrlSetData($idLength, "00:00") GUICtrlSetData($idLength2, "00:00") If $iTrack = 0 Then mciSendString("close myMedia") EndIf While 1 If $iRescanned <> 1 Then $iIndex += 1 Else $iRescanned = 0 ; If $sCurrentFile not found in rescanned playlist, $iIndex becomes 2 per _PlaylistLoad_1() EndIf If $iIndex > $aFiles[0][0] Then $iIndex = 2 ElseIf $iIndex < 2 Then $iIndex = $aFiles[0][0] EndIf If $aFilesToRepeat[0] > 0 Then For $i = 1 To $aFilesToRepeat[0] If $aFilesToRepeat[$i] >= $iIndex-1 Then ExitLoop EndIf Next If $i > $aFilesToRepeat[0] Then $iIndex = $aFilesToRepeat[1]+1 Else $iIndex = $aFilesToRepeat[$i]+1 EndIf EndIf $sCurrentFile = $aFiles[$iIndex][0] If StringInStr($sCurrentFile, ":\") Then $sPath = $sCurrentFile Else $sPath = $sFolder & $sCurrentFile EndIf If FileExists($sPath) Then ExitLoop Else ContinueLoop EndIf WEnd $iPlaying = 0 $iPaused = 0 _SwitchToTrack($iIndex) WEnd ; Main Loop Func _ActivateSpeakers() ; Adlib function to keep the speakers continuously active Beep(1, 1) ; once in 30 seconds EndFunc ;==> _ActivateSpeakers Func _AspectToggler() ; Called by "a" hotkey Local $sMsg If $sKeepAspect = "Yes" Then $sKeepAspect = "No" $sMsg = "Keep aspect: No" GUICtrlSetState($idAspectNo, $GUI_CHECKED) Else $sKeepAspect = "Yes" $sMsg = "Keep aspect: Yes" _VideoResize() GUICtrlSetState($idAspectYes, $GUI_CHECKED) EndIf _MPV_SendCommand('{"command": ["cycle", "keepaspect"]}') _MPV_SendCommand('{"command": ["show-text", "' & $sMsg & '"]}') EndFunc ;==> _AspectToggler Func _Audio_Action($action, $value, $pid) ; 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 = $pid Then ;@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 ; SetMasterVolume is not used in this program because it is effective only while a file is playing ; waveOutSetVolume is effective even before loading the file 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($sMode) ; Set audio equalizer mode Local $sAF = "" Switch $sMode Case "Normal" $sAF = "" Case "Deep Bass" ; superequalizer 18 bands. We boost the first 3 sub-bass bands significantly $sAF = "superequalizer=b1=5:b2=5:b3=4" Case "Crystal Clear" ; We cut muddy lows and boost the crisp higher-end treble frequencies $sAF = "superequalizer=b1=-2:b2=-2:b15=4:b16=5:b17=5" Case "Cinema/Voice" ; Cut lowest frequencies to remove rumble, boost vocal presence bands $sAF = "superequalizer=b1=-5:b2=-3:b8=3:b9=4:b10=4" Case "Pop/Rock" ; The classic V-Shape: boosted bass, dipped mids, boosted highs $sAF = "superequalizer=b1=4:b2=3:b9=-2:b10=-2:b16=3:b17=4" Case "Midnight" ; Fallback to the stable dynamic normalizer $sAF = "dynaudnorm=p=0.9:m=5" Case "Speech/Podcast" ; Drastic low-end cutoff to highlight pure speech intelligibility $sAF = "superequalizer=b1=-10:b2=-10:b3=-7:b9=4:b10=4" Case Else $sAF = "" EndSwitch ; Merge volume headroom and your 0.5 second fade-in safely into a single string expression If $sAF <> "" Then $sAF = "afade=t=in:d=2," & $sAF Else $sAF = "afade=t=in:d=2" EndIf Local $sJsonCmd = '{"command": ["set_property", "af", "' & $sAF & '"]}' _MPV_SendCommand($sJsonCmd) EndFunc ;==> _AudioModeSet Func _Execute() ; Execute an expression(Ex: _Pause(), _ArrayDisplay($aFiles), $sPath), triggered by Ctrl+Alt+V ;~ ; Verify audio mode property ;~ Local $sResponse = _MPV_GetProperty("af") ;~ ConsoleWrite($sAudioMode & "/" & $sResponse & @CRLF) ;~ Return HotKeySet("^!v") If $iExecute = 0 Then GUISetState(@SW_SHOW, $hExecute) GUICtrlSetState($idExpression, $GUI_FOCUS) $iExecute = 1 Else GUICtrlSetData($idExpression, "") GUICtrlSetData($idResult, "") GUISetState(@SW_HIDE, $hExecute) $iExecute = 0 EndIf While _IsPressed("56", $hUser32DLL) Sleep(10) WEnd HotKeySet("^!v", _Execute) EndFunc ;==> _Execute Func _Exit() ; Terminate the program (Click main GUI Close button or 🞭 button on video control GUI, or press Ctrl+Alt+End)\ _IniSave() _PlaylistSave() mciSendString("close myMedia") _MPV_SendCommand('{"command": ["stop"]}') GUIDelete($hVideoGUI) ; Avoid possibility of black full screen remaining after termination of program GUIDelete($hHelp) ; Destroy $helpEdit, a RichEdit control in $hHelp _GUICtrlRichEdit_Destroy($helpEdit) $tText = 0 _WinAPI_SetThreadExecutionState($ES_CONTINUOUS) ; Back to normal windows behavior DllClose($hWinmmDLL) DllClose($hUser32DLL) If $hPipe <> -1 Then DllCall("kernel32.dll", "bool", "CloseHandle", "handle", $hPipe) ProcessClose($hMPV_Process) Exit EndFunc ;==> _Exit Func _FilePropertiesGet($path) ; Obtian properties of a file ; This process will take less than 250 milliseconds for most of the file types, but a large mp4 moive file may take up to 2 seconds If $path = "" Then Return $sFileName = StringTrimLeft($path, StringInStr($path, "\", 0, -1)) $sDir = StringTrimRight($path, (StringLen($path) - StringInStr($path, "\", 0, -1))) $oDir = $oShellApp.NameSpace ($sDir) $oFile = $oDir.Parsename ($sFileName) $aFileInfo[0][0] = "Path" $aFileInfo[0][1] = $sPath $aFileInfo[1][0] = "File Size" $aFileInfo[1][1] = $oDir.GetDetailsOf($oFile, 1) $aFileInfo[2][0] = "Date Created" $aFileInfo[2][1] = $oDir.GetDetailsOf($oFile, 4) $aFileInfo[3][0] = "File Type" $aFileInfo[3][1] = $oDir.GetDetailsOf($oFile, 2) Local $sPropertyValue If $iLenColNumber = 0 Then For $i = 10 To 350 $sPropertyValue = $oDir.GetDetailsOf($oFile, $i) If StringRegExp($sPropertyValue, "^(?:\d{1,2}:)?\d{1,2}:\d{1,2}$") Then $iLenColNumber = $i ExitLoop EndIf Next EndIf $aFileInfo[4][0] = "Length" If StringRight($sPath, 4) = ".cda" Then Local $track = _ArraySearch($aTracks, $sFileName) mciSendString("set myMedia time format tmsf") $sPropertyValue = mciSendString("status myMedia length track " & $track) If StringLeft($sPropertyValue, 2) > 59 Then $sPropertyValue = StringFormat("%02i:%02i:%92i", 1, StringLeft($sPropertyValue,2)-59, StringMid($sPropertyValue,4, 2)) Else $sPropertyValue = "00:" & StringLeft($sPropertyValue, 5) EndIf $aFileInfo[4][1] = $sPropertyValue mciSendString("set myMedia time format milliseconds") Else If $iLenColNumber > 0 Then $aFileInfo[4][1] = $oDir.GetDetailsOf($oFile, $iLenColNumber) EndIf EndIf $aFileInfo[5][0] = "Audio Bitrate" $aFileInfo[5][1] = $oDir.GetDetailsOf($oFile, $iLenColNumber+1) If $oFile.ExtendedProperty("System.Video.FrameWidth") = 0 Then ; Audio files If $iLenColNumber = 27 Then $aFileInfo[6][0] = "Artist" $aFileInfo[6][1] = $oDir.GetDetailsOf($oFile, 13) $aFileInfo[7][0] = "Title" $aFileInfo[7][1] = $oDir.GetDetailsOf($oFile, 21) $aFileInfo[8][0] = "Album" $aFileInfo[8][1] = $oDir.GetDetailsOf($oFile, 14) $aFileInfo[9][0] = "Track Number" $aFileInfo[9][1] = $oDir.GetDetailsOf($oFile, 26) $aFileInfo[10][0] = "Year" $aFileInfo[10][1] = $oDir.GetDetailsOf($oFile, 15) $aFileInfo[11][0] = "Genre" $aFileInfo[11][1] = $oDir.GetDetailsOf($oFile, 16) ElseIf $iLenColNumber = 21 Then $aFileInfo[6][0] = "Artist" $aFileInfo[6][1] = $oDir.GetDetailsOf($oFile, 16) $aFileInfo[7][0] = "Title" $aFileInfo[7][1] = $oDir.GetDetailsOf($oFile, 10) $aFileInfo[8][0] = "Album" $aFileInfo[8][1] = $oDir.GetDetailsOf($oFile, 17) $aFileInfo[9][0] = "Track Number" $aFileInfo[9][1] = $oDir.GetDetailsOf($oFile, 19) $aFileInfo[10][0] = "Year" $aFileInfo[10][1] = $oDir.GetDetailsOf($oFile, 18) $aFileInfo[11][0] = "Genre" $aFileInfo[11][1] = $oDir.GetDetailsOf($oFile, 20) EndIf Else ; Video files $aFileInfo[6][0] = "Frame Height" $aFileInfo[6][1] = $oFile.ExtendedProperty("System.Video.FrameHeight") $aFileInfo[7][0] = "Frame Width" $aFileInfo[7][1] = $oFile.ExtendedProperty("System.Video.FrameWidth") $aFileInfo[8][0] = "Frame Rate" $aFileInfo[8][1] = Round($oFile.ExtendedProperty("System.Video.FrameRate")/1000, 1) & " frames/sec" $aFileInfo[9][0] = "Total Bitrate" $aFileInfo[9][1] = Round($oFile.ExtendedProperty("System.Video.TotalBitrate")/1000) & "kbps" $aFileInfo[10][0] = "" $aFileInfo[10][1] = "" $aFileInfo[11][0] = "" $aFileInfo[11][1] = "" EndIf EndFunc ;==> _FilePropertiesGet Func _FilePropertiesShow() ; View the file properties, Atrl+Alt+f or playlist context menu If $iAllDone < 0 Then Return HotKeySet("^!f") Local $aPos1 = WinGetPos($hProperties) Local $tPoint = _WinAPI_CreatePoint($aPos1[0], $aPos1[1]) $hTopWnd = _WinAPI_WindowFromPoint($tPoint) If $iProperties = 1 And $hProperties <> $hTopWnd Then ; If $hProperties was minimized or behind another window If $iFullScreen = 1 Then WinSetOnTop($hProperties, "", 1) EndIf WinActivate($hProperties) While _IsPressed("46", $hUser32DLL) Sleep(10) WEnd HotKeySet("^!f", _FilePropertiesShow) Return EndIf If $iProperties = 1 And $iFilePropertiesFrom = "" Then ; This If...Endif clause is executed only when hotkey has been pressed WinSetOnTop($hProperties, "", 0) GUISetState(@SW_HIDE, $hProperties) $iProperties = 0 While _IsPressed("46", $hUser32DLL) Sleep(10) WEnd HotKeySet("^!f", _FilePropertiesShow) Return EndIf If $iFullScreen = 1 Then WinSetOnTop($hProperties, "", 1) EndIf _GUICtrlListView_DeleteAllItems($idPropertiesView) If $iFilePropertiesFrom <> "" Then ; If triggered by context menu Local $tFile = $aFiles[$iFilePropertiesFrom+2][0] If StringInStr($tFile, ":\") Then $sPath = $tFile Else $sPath = $sFolder & $tFile EndIf _FilePropertiesGet($sPath) _GUICtrlListView_AddArray($idPropertiesView, $aFileInfo) Else _GUICtrlListView_AddArray($idPropertiesView, $sCurrentFileProperties) EndIf WinMove($hProperties, "", (@DesktopWidth-$aPos1[2])/2, (@DesktopHeight-$aPos1[3])/2) GUISetState(@SW_SHOW, $hProperties) WinActivate($hProperties) $iProperties = 1 While _IsPressed("46", $hUser32DLL) Sleep(10) WEnd HotKeySet("^!f", _FilePropertiesShow) EndFunc ;==> _FilePropertiesShow Func _FullScreen() ; Video in full screen mode on/off (Click ⇔/⇙ icon, press F11 hotkey, double-click on video image) HotKeySet("{F11}") AdlibUnRegister("_VCShow") If $iFullScreen = 0 Then $iFullScreen = 1 $iMaximized = 0 GUICtrlSetData($idFullScreen, "⇙") GUISetStyle($WS_OVERLAPPEDWINDOW, -1, $hVideoGUI) Local $x, $y, $w, $h $x = -$iBorderWidth $y = 0 $w = @DesktopWidth+$iBorderWidth*2 $h = @DesktopHeight+$iBorderWidth GUISetStyle($WS_POPUP, -1, $hVideoGUI) WinMove($hVideoGUI, "", $x, $y, $w, $h) ; Not required for full screen, but needed to keep the screen black while moving to next file WinSetOnTop($hVideoGUI, "", 1) _VCResize() GUICtrlSetData($idSlider2, " " & $sTitle) Else GUISetStyle($WS_OVERLAPPEDWINDOW-$WS_MINIMIZEBOX, -1, $hVideoGUI) WinSetOnTop($hVideoGUI, "", 0) GUICtrlSetData($idSlider2, "") $iFullScreen = 0 GUISetStyle($WS_OVERLAPPEDWINDOW, -1, $hVideoGUI) WinMove($hVideoGUI, "", $aVideoPrePos[0], $aVideoPrePos[1], $aVideoPrePos[2], $aVideoPrePos[3]) If $iMinimized = 1 Then GUISetState(@SW_RESTORE, $hMain) EndIf WinSetOnTop($hPlaylist, "", 0) WinSetOnTop($hProperties, "", 0) If $hHelp <> "" Then WinSetOnTop($hHelp, "", 0) EndIf WinSetOnTop($hOptions, "", 0) GUICtrlSetData($idFullScreen, "⇔") _VCResize() EndIf AdlibRegister("_VCShow", 500) While _IsPressed("7A", $hUser32DLL) Sleep(10) WEnd HotKeySet("{F11}", _FullScreen) EndFunc ;==> _FullScreen Func _GetFileExtension($File) ; Get file extension Local $sExt = StringLower(StringMid($File, StringInStr($File, ".", 0, -1) + 1)) Return $sExt EndFunc ;==> _GetFileExtension Func _GetIndexByFileName($fileName) ; Get index from $oPlaylist dictionary - replace error-prone _ArraySearch() If $oPlaylist.Exists($fileName) Then Return $oPlaylist.Item($fileName) EndIf Return -1 EndFunc ;==> _GetIndexByFileName Func _GetLength() ; Adlib function to obtain media length at 25 ms interval, registered at the end of _PlaylistLoad_2() If $iDoing = 1 Or $iAllDone = 1 Then Return $iDoing = 1 For $iList = 2 To $aFiles[0][0] If $aFiles[$iList][1] = "" Then ; Find an item, media length column of which is empty ExitLoop EndIf Next If $iList > $aFiles[0][0] Then ; When all media length fields are filled, total playlist length is calculated If $iTitleColored = 1 Then GUICtrlSetColor($idTitle, 0) $iTitleColored = 0 EndIf AdlibUnRegister("_GetLength") $iAllDone = 1 $iDoing = 0 _GetLengthTotal() If $iFolderLoaded = 1 Then _PlaylistSave() EndIf Return EndIf If $iTitleColored = 0 Then GUICtrlSetColor($idTitle, 0xFF0055) $iTitleColored = 1 EndIf $sFile = $aFiles[$iList][0] Local $sPropertyValue If $iTrack = 0 Then If $iLenColNumber = 0 Then $iDoing = 0 Return EndIf If Not StringInStr($sFile, ":\") Then $sFile = $sFolder & $sFile EndIf Local $sFileName, $sDir, $oDir, $oFile $sFileName = StringMid($sFile, StringInStr($sFile, "\", 0, -1)+1) $sDir = StringLeft($sFile, StringInStr($sFile, "\", 0, -1)) $oDir = $oShellApp.NameSpace($sDir) $oFile = $oDir.Parsename($sFileName) If $iLenColNumber > 0 Then $sPropertyValue = $oDir.GetDetailsOf($oFile, $iLenColNumber) EndIf Else Local $track = _ArraySearch($aTracks, $sFile) mciSendString("set myMedia time format tmsf") $sPropertyValue = mciSendString("status myMedia length track " & $track) If StringLeft($sPropertyValue, 2) > 59 Then $sPropertyValue = StringFormat("%02i:%02i:%92i", 1, StringLeft($sPropertyValue,2)-59, StringMid($sPropertyValue,4, 2)) Else $sPropertyValue = "00:" & StringLeft($sPropertyValue, 5) EndIf mciSendString("set myMedia time format milliseconds") EndIf If StringInStr($sPropertyValue, ":") = 0 Then $sPropertyValue = "00:00:00" EndIf $aFiles[$iList][1] = $sPropertyValue $aItems[$iList-2][2] = $sPropertyValue GUICtrlSendMsg($ctrlView, $LVM_UPDATE, $iList-2, 0) $iDoing = 0 EndFunc ;==> _GetLength Func _GetLengthTotal() ; Update total playback length of current playlist Local $iHours, $iMinutes, $iSeconds, $tSeconds, $tString, $aSplit, $sText For $i = 2 To $aFiles[0][0] $tString = $aFiles[$i][1] If $tString = "" Then ContinueLoop $aSplit = StringSplit($tString, ":") Select Case $aSplit[0] = 3 ; HH:MM:SS $iHours += $aSplit[1] $iMinutes += $aSplit[2] $iSeconds += $aSplit[3] Case $aSplit[0] = 2 ; MM:SS $iMinutes += $aSplit[1] $iSeconds += $aSplit[2] EndSelect Next $tSeconds = $iHours*3600+$iMinutes*60+$iSeconds $iHours = Int($tSeconds/3600) $iMinutes = StringFormat("%02i", Int(Mod($tSeconds, 3600)/60)) $iSeconds = StringFormat("%02i", Mod($tSeconds, 60)) $aFiles[1][1] = $iHours & ":" & $iMinutes & ":" & $iSeconds If $iFolderLoaded = 1 Then $sText = "Folder (" & $sFolder Else $sText = "Files (" & $sFolder EndIf $sText &= $sCDLabel $sText &= ") [" & $aFiles[1][1] & "]" _GUICtrlListView_SetColumn($ctrlView, 1, $sText) EndFunc ;==> _GetLengthTotal Func _Help() ; Show/Hide Help window GUICtrlSetState($idPlay, $GUI_FOCUS) ; Prevent dotted frames in $hMain buttons HotKeySet("^!h") Local $aPos1 = WinGetPos($hHelp) Local $tPoint = _WinAPI_CreatePoint($aPos1[0]+$aPos1[2]-5, $aPos1[1]) $hTopWnd = _WinAPI_WindowFromPoint($tPoint) If $hHelp = "" Then zPlayerHelp() If $iFullScreen = 1 Then WinSetOnTop($hHelp, "", 1) EndIf ControlSend($hHelp, "", $helpEdit, "^{home}") Else If $hHelp <> $hTopWnd Then If $iFullScreen = 1 Then WinSetOnTop($hHelp, "", 1) EndIf WinActivate($hHelp) Else GUIDelete($hHelp) $hHelp = "" EndIf EndIf While _IsPressed("48", $hUser32DLL) Sleep(10) WEnd HotKeySet("^!h", _Help) EndFunc ;==> _Help Func _HotkeySet() ; Adlib function to set/unset {F11} and {ESC} hotkeys, 990ms If Not WinExists($hVideoGUI) Then Return ; Set or unset {F11} and {ESC} full screen hotkeys depending on visibility of video window Local $aPos1 = WinGetPos($hVideoGUI) Local $tPoint = _WinAPI_CreatePoint($aPos1[0]+$aPos1[2]/2, $aPos1[1]+$aPos1[3]/2) Local Static $iHotkeySet_Esc, $iHotkeySet_F11 If WinGetTitle(_WinAPI_WindowFromPoint($tPoint)) = "ActiveMovie Window" Then If $iHotkeySet_F11 = 0 Then HotKeySet("{F11}", _FullScreen) $iHotkeySet_F11 = 1 EndIf If $iFullScreen = 1 And $iHotkeySet_Esc = 0 Then HotKeySet("{ESC}", _FullScreen) $iHotkeySet_Esc = 1 ElseIf $iFullScreen = 0 And $iHotkeySet_Esc = 1 Then HotKeySet("{ESC}") $iHotkeySet_Esc = 0 EndIf Else If $iHotkeySet_F11 = 1 Then HotKeySet("{F11}") $iHotkeySet_F11 = 0 If $iHotkeySet_Esc = 1 Then HotKeySet("{ESC}") $iHotkeySet_Esc = 0 EndIf EndIf EndIf EndFunc ;==> _HotkeySet Func _IniSave() ; Save zPlayer.ini file in @ScrDirectory If $iFolderLoaded = 0 Or IsArray($aFiles) = 0 Or $aFiles[0][0] < 2 Then Return Local $sPlayer = "Folder=" & $sFolder & @LF $sPlayer &= "Audio File Types=" & $sAudioTypes & @LF $sPlayer &= "Video File Types=" & $sVideoTypes & @LF $sPlayer &= "Keep Video Aspect=" & $sKeepAspect & @LF $sPlayer &= "Audio Volume Level=" & $iVolume & @LF $sPlayer &= "Audio EQ Mode=" & $sAudioMode & @LF $sPlayer &= "Color Scheme=" & $sColorScheme & @LF $sPlayer &= "Always On Top=" & (($iMainIsOnTop = 1) ? "Yes" : "No") & @LF If $aCoverPos[0] >= $iClientWidth-$iMainGuiWidth-1 And $aCoverPos[1] >= $iClientHeight-$iMainGuiHeight-$iMainBarHeight Then $sPlayer &= "Main Window Position=5000,5000" & @LF ; Ensure $hMain is positioned at bottom right corner regardles of screen resolution Else $sPlayer &= "Main Window Position=" & $aCoverPos[0] & "," & $aCoverPos[1] & @LF EndIf Local $sResume = "Mode=" & $sResumeMode & @LF $sResume &= "Minimum Total Length=" & $iMinTotalLength & @LF $sResume &= "Minimum Playback Length=" & $iMinPlaybackLength If Not FileExists($sIniFile) Then Local $hFile = FileOpen($sIniFile, 2+32) FileWriteLine($hFile, "[Player]") FileWrite($hFile, $sPlayer) FileWriteLine($hFile, "[Resume Playback]") FileWrite($hFile, $sResume) FileClose($hFile) Else IniWriteSection($sIniFile, "Player", $sPlayer) IniWriteSection($sIniFile, "Resume Playback", $sResume) EndIf EndFunc ;==> _IniSave Func _InternetSearch() ; Search current file in internet (Press Ctrl+Alt+I) HotKeySet("^!i") If Not _WinAPI_IsInternetConnected() Then MsgBox($MB_OK, "zPlayer", "Internet connection is not available!", 5) HotKeySet("^!i", _InternetSearch) Return EndIf If $iFullScreen = 1 Then _FullScreen() EndIf If $iInternetSearchFrom <> "" Then ; This If...Endif clause is executed only when hotkey has been pressed Local $tFile = $aFiles[$iInternetSearchFrom+2][0], $sPath2 If StringInStr($tFile, ":\") Then $sPath2 = $tFile Else $sPath2 = $sFolder & $tFile EndIf Else $sPath2 = $sPath EndIf Local $searchStr = StringMid($sPath, StringInStr($sPath2, "\", 0, -1)+1) $searchStr = StringLeft($searchStr, StringInStr($searchStr, ".", 0, -1)-1) $searchStr = StringReplace(StringReplace(StringReplace(StringReplace(StringReplace($searchStr, "-", " "), "(", " "), ")", " "), "&", " "), "_", " ") $searchStr = StringStripWS($searchStr, 7) $searchStr = StringReplace($searchStr, " ", "+") Local $url = "https://duckduckgo.com/?q=" & $searchStr If WinExists(" at DuckDuckGo ") Then WinActivate(" at DuckDuckGo ") Sleep(100) Send("{F6}") ClipPut($url) Sleep(100) Send("^v") Sleep(100) Send("{enter}") Else ShellExecute($url, "", "", "", @SW_MAXIMIZE) EndIf While _IsPressed("49", $hUser32DLL) Sleep(10) WEnd HotKeySet("^!i", _InternetSearch) EndFunc ;==> _InternetSearch Func _JumpPosition() ; Jump playback position 5/30 seconds forward/backward HotKeySet("^{left}") HotKeySet("^+{left}") HotKeySet("^{right}") HotKeySet("^+{right}") Local $iJump If _IsPressed("10", $hUser32DLL) Then ; Shift key $iJump = 30000 Else $iJump = 5000 EndIf Local $mediaPos If StringInStr($sMciFileTypes, _GetFileExtension($sCurrentFile)) Then $mediaPos = mciSendString("status myMedia position") If _IsPressed("25", $hUser32DLL) Then ; Left arrow $mediaPos = _Max($mediaPos - $iJump, 0) Else ; Right arrow $mediaPos = _Min($mediaPos + $iJump, $iMediaLength) EndIf mciSendString("seek myMedia to " & $mediaPos) mciSendString("play myMedia") Else If _IsPressed("25", $hUser32DLL) Then ; Left arrow _MPV_SendCommand('{"command": ["seek", ' & -($iJump/1000) & ', "relative"]}') Else _MPV_SendCommand('{"command": ["seek", ' & $iJump/1000 & ', "relative"]}') EndIf EndIf While _IsPressed("11", $hUser32DLL) ; Ctrl key Sleep(10) WEnd HotKeySet("^{left}", _JumpPosition) HotKeySet("^+{left}", _JumpPosition) HotKeySet("^{right}", _JumpPosition) HotKeySet("^+{right}", _JumpPosition) EndFunc ;==> _JummpPosition Func _LoadFiles() ; Load files GUICtrlSetState($idPlay, $GUI_FOCUS) ; Prevent dotted frames in $hMain buttons If $iAllDone = 0 Then Return $sCDLabel = "" $iCD = 0 Local $fileTypes = "*." & StringReplace($sFileTypes, " ", ";*.") Local $sFiles, $sMsg, $iRet $sFiles = FileOpenDialog("Load one or more media files", "", "Audio/Video (" & $fileTypes & ")", 7, "", $hMain) _MPV_FlushPipe() ; Clears mpv's clogged IPC pipe buffer If $sFiles = "" Then Return EndIf If $iFolderLoaded = 1 Then _IniSave() _PlaylistSave() EndIf _Unload() If Not StringInStr($sFiles, "|") Then Local $iPos = StringInStr($sFiles, "\", 0, -1) $sFiles = StringLeft($sFiles, $iPos) & "|" & StringMid($sFiles, $iPos+1) EndIf $aFiles = StringSplit($sFiles, "|") ; Folder name|File 1|File 2... $sFolder = $aFiles[1] If StringRight($sFolder, 1) <> "\" Then $sFolder &= "\" If DriveGetType($sFolder) = "CDROM" Then If StringRight($sFiles, 4) <> ".cda" Then $sMsg = "This CD does not have audio tracks." & @CRLF $sMsg &= "zPlayer does not support a data CD with music files." MsgBox($MB_OK, "No Audio CD", $sMsg, 0, $hMain) Return Else $aTracks = _FileListToArrayRec($sFolder, "*.cda", 1, 1, 0, 1) $sCurrentFile = $sFolder & $aFiles[2] $aFiles[1] = $aFiles[2] $iTrack = _ArraySearch($aTracks, $sCurrentFile) _ArrayColInsert($aFiles, 1) $sCDLabel = DriveGetLabel($sFolder) $iFolderLoaded = 0 _PlaylistLoad_1() mciSendString("close myMedia") $iRet = mciSendString("open """ & $sFolder & """ alias myMedia type cdaudio wait") If $iRet <> 0 Then $sMsg = "This CDROM folder cannot be opened." & @CRLF & _ "Please load another folder." MsgBox($MB_OK+$MB_ICONWARNING, "No File", $sMsg) Return EndIf EndIf Else $sCurrentFile = $aFiles[2] If StringInStr($sCurrentFile, ":\") Then $sPath = $sCurrentFile Else $sPath = $sFolder & $sCurrentFile EndIf $aFiles[1] = $aFiles[2] _ArrayColInsert($aFiles, 1) $iFolderLoaded = 0 $iShuffled = 0 _PlaylistLoad_1() If StringInStr($sMciFileTypes, _GetFileExtension($sCurrentFile)) Then mciSendString("close myMedia") If $bFirstMidiFile Then $bFirstMidiFile = False GUICtrlSetData($idTitle, StringFormat("%17s", "") & "Initializing MIDI Synthesizer...") EndIf $iRet = mciSendString("open """ & $sPath & """ alias myMedia type Sequencer wait") ; style popup parent " & $iGui) If $iRet <> 0 Then $sMsg = "This file cannot be opened." & @CRLF & _ "Please load another folder." MsgBox($MB_OK+$MB_ICONWARNING, "Loading error", $sMsg) Return EndIf Else _MPV_LoadFile($sPath) _PlaylistLoad_2() If $iMute = 1 Then _Mute() Return EndIf EndIf _Play() _PlaylistLoad_2() If $iMute = 1 Then _Mute() EndFunc ;==> _LoadFiles Func _LoadFolder() ; Load folder or CD GUICtrlSetState($idPlay, $GUI_FOCUS) ; Prevent dotted frames in $hMain buttons If $iAllDone = 0 Then Return If GUICtrlGetState($idFolder) > 80 Then Return ; $idFolder is disabled HotKeySet("^!c") If $isVideo And $iFullScreen = 1 Then _FullScreen() Local $sFolder2, $aFiles2, $aFile, $iShuffled2, $sFile, $iNoFiles = 0 Local $fileTypes = "*." & StringReplace($sFileTypes, " ", ";*.") Local $sMsg, $iRet While 1 If $iFullScreen = 1 And $sLoadFolderFrom <> "idFolder" And $iMainIsOnTop = 0 Then WinSetOnTop($hMain, "", 1) WinActivate($hMain) EndIf ; Load all files in a folder (and its subfolders) If $sFolder = "" Then $sFolder2 = FileSelectFolder("Select a folder with media files", "C:\", 0, "", $hMain) Else $sFolder2 = FileSelectFolder("Select a folder with media files", StringLeft($sFolder, 3), 0, "", $hMain) EndIf _MPV_FlushPipe() ; Clears mpv's clogged IPC pipe buffer If $iFullScreen = 1 And $sLoadFolderFrom <> "idFolder" And $iMainIsOnTop = 0 Then WinSetOnTop($hMain, "", 0) $sLoadFolderFrom = "" EndIf If $sFolder2 = "" Then HotKeySet("^!c", _LoadFolder) Return EndIf If StringRight($sFolder2, 1) <> "\" Then $sFolder2 &= "\" If $sFolder2 = $sFolder And $iFolderLoaded = 1 Then HotKeySet("^!c", _LoadFolder) Return EndIf If IsArray($aFiles) And $iFolderLoaded = 1 Then _IniSave() _PlaylistSave() EndIf If DriveGetType($sFolder2) <> "CDROM" Then Local $makePlaylist = 0 If FileExists($sFolder2 & "zPlaylist.txt") Then _FileReadToArray($sFolder2 & "zPlaylist.txt", $aFiles2, 1+4, ":|") ; 2D array If $aFiles2[0][0] < 2 Then $makePlaylist = 1 Else For $v = 2 To $aFiles2[0][0] $sFile = $aFiles2[$v][0] If Not StringInStr($sFile, ":\") Then $sFile = $sFolder2 & $sFile EndIf If Not FileExists($sFolder2 & $aFiles2[$v][0]) Then $iNoFiles += 1 EndIf Next If $iNoFiles = $aFiles2[0][0] Then $makePlaylist = 1 EndIf EndIf If $makePlaylist = 1 Then $sMsg = "None of the items in the playlist are valid." & @CRLF & _ "Please delete the playlists and restart this program." MsgBox($MB_OK+$MB_ICONWARNING, "No File", $sMsg) Return EndIf $aFile = StringSplit($aFiles2[1][0], "||", 1) $sCurrentFile = $aFile[1] If $aFile[0] > 1 And $aFile[2] = "Shuffled" Then $iShuffled2 = 1 Else $iShuffled2 = 0 EndIf If $aFile[0] = 3 Then $iResumePosition = _Max(($aFile[3]-10), 0)*1000 ; Resume playback at 10 seconds before last playback position EndIf Else $aFiles2 = _FileListToArrayRec($sFolder2, $fileTypes, 1, 1, 1, 1) ; include files in subfolders If Not (IsArray($aFiles2) And $aFiles2[0] > 0) Then If $iFullScreen = 1 Then _FullScreen() EndIf Local $iRes = MsgBox($MB_RETRYCANCEL, "Select Folder", "This folder does not contain any media file." & @CRLF & "Try once again?", 0, $hMain) If $iRes = $IDRETRY Then ContinueLoop Else HotKeySet("^!c", _LoadFolder) Return EndIf EndIf ; If the selected folder has media files in both top-level and sub-level folders, you have an option to include or exclude files in subfolders Local $iRootFolders, $iSubFolders For $i = 1 To $aFiles2[0] If StringInStr($aFiles2[$i], "\") Then $iSubFolders += 1 Else $iRootFolders += 1 EndIf Next If $iSubFolders > 0 And $iRootFolders > 0 Then If $iFullScreen = 1 Then _FullScreen() EndIf $sMsg = "Number of files in top-level folder:" & @TAB & $iRootFolders & @CRLF $sMsg &= "Number of files in sub-level folders:" & @TAB & $iSubFolders & @CRLF & @CRLF $sMsg &= "Do you want to include files in the subfolders?" $iRet = MsgBox($MB_YESNO, "Include files in subfolders?", $sMsg, 0, $hMain) If $iRet = $IDNO Then $aFiles2 = _FileListToArrayRec($sFolder2, $fileTypes, 1, 0, 1, 1) ; exclude files in subfolders EndIf EndIf _ArrayInsert($aFiles2, 1, $aFiles2[1]) _ArrayColInsert($aFiles2, 1) $aFiles2[0][0] += 1 $aFiles2[1][0] = $aFiles2[2][0] $iShuffled2 = 0 $sCurrentFile = $aFiles2[2][0] EndIf _Unload() ; initialize playback environment and close current file Sleep(10) $iCD = 0 $sFolder = $sFolder2 $aFiles = $aFiles2 $iShuffled = $iShuffled2 $iFolderLoaded = 1 $iIndex = _GetIndexByFileName($sCurrentFile) _PlaylistLoad_1() $sPath = $sFolder & $sCurrentFile If $iMute = 1 Then _Mute() _SwitchToTrack($iIndex) _PlaylistLoad_2() ExitLoop Else ; Play whole CD $sCDLabel = DriveGetLabel($sFolder) Local $aTracks2 = _FileListToArrayRec($sFolder2, "*.cda", 1, 1, 0, 1) If Not IsArray($aTracks2) Then $sMsg = "This CDROM folder does not contain .cda files." & @CRLF & _ "Please load another folder." MsgBox($MB_OK+$MB_ICONWARNING, "Loading error", $sMsg) Return EndIf _Unload() $sCDLabel = DriveGetLabel($sFolder) $iCD = 1 $iTrack = 1 $aTracks = $aTracks2 $aFiles = $aTracks $sFolder = $sFolder2 _ArrayInsert($aFiles, 1, $aTracks[$iTrack]) $aFiles[0] += 1 _ArrayColInsert($aFiles, 1) $iIndex = 0 $iShuffled = 0 _PlaylistLoad_1() $iRet = mciSendString("open """ & $sFolder & """ alias myMedia type cdaudio wait") If $iRet <> 0 Then $sMsg = "This CDROM folder cannot be opened." & @CRLF & _ "Please load another folder." MsgBox($MB_OK+$MB_ICONWARNING, "Loading error", $sMsg) Return EndIf $iFolderLoaded = 1 If $iMute = 1 Then _Mute() _Play() _PlaylistLoad_2() ExitLoop EndIf WEnd HotKeySet("^!c", _LoadFolder) EndFunc ;==> _LoadFolder Func _LoadLastFolder() ; Load the playlist which was saved when the program was terminated last time If Not FileExists($sIniFile) Then Return Local $iRet If DriveGetType($sFolder) = "CDROM" Then Local $aTracks2 = _FileListToArrayRec($sFolder, "*.cda", 1, 1, 1, 1) If Not IsArray($aTracks2) Then Return $iRet = mciSendString("open """ & $sFolder & """ alias myMedia type cdaudio wait") If $iRet <> 0 Then Local $sMsg = "This CDROM folder cannot be opened." & @CRLF & _ "Please load another folder." MsgBox($MB_OK+$MB_ICONWARNING, "Loading error", $sMsg) Return EndIf $sCDLabel = DriveGetLabel($sFolder) $iCD = 1 $iTrack = 1 $aTracks = $aTracks2 $aFiles = $aTracks _ArrayInsert($aFiles, 1, $aTracks[$iTrack]) $aFiles[0] += 1 _ArrayColInsert($aFiles, 1) $sCurrentFile = $aTracks[$iTrack] $iFolderLoaded = 1 $iShuffled = 0 _PlaylistLoad_1() _Play() Else $iCD = 0 If Not FileExists($sFolder & "zPlaylist.txt") Then Return _FileReadToArray($sFolder & "zPlaylist.txt", $aFiles, 1+4, ":|") ; 2D array If IsArray($aFiles) = 0 Then _FileReadToArray($sFolder & "zPlaylist.txt", $aFiles) ; 1D array If IsArray($aFiles) = 0 Or $aFiles[0] < 2 Then FileDelete($sFolder & "zPlaylist.txt") FileDelete($sFolder & "zPlaylist-Shuffled.txt") Return EndIf _ArrayColInsert($aFiles, 1) Local $iChanged = 0 For $i = 1 To $aFiles[0][0] If StringInStr($aFiles[$i][0], ":|") Then $iChanged = 1 ExitLoop EndIf Next If $iChanged = 1 Then Local $s For $i = 1 To $aFiles[0][0] $s = $aFiles[$i][0] If StringInStr($s, ":|") Then $aFiles[$i][0] = StringLeft($s, StringInStr($s, ":|")-1) $aFiles[$i][1] = StringMid($s, StringInStr($s, ":|")+2) EndIf Next _ArraySort($aFiles, 0, 2) FileDelete($sFolder & "zPlaylist-Shuffled.txt") EndIf ElseIf $aFiles[0][0] < 2 Then FileDelete($sFolder & "zPlaylist.txt") FileDelete($sFolder & "zPlaylist-Shuffled.txt") Return EndIf Local $bFolder, $iNoFiles = 0 For $v = 2 To $aFiles[0][0] If Not StringInStr($aFiles[$v][0], ":\") Then $bFolder = $sFolder Else $bFolder = "" EndIf If Not FileExists($bFolder & $aFiles[$v][0]) Then $iNoFiles += 1 EndIf Next If $iNoFiles = $aFiles[0][0] Then $sMsg = "None of the items in the playlist are valid." & @CRLF & _ "Please delete the playlists and restart this program." MsgBox($MB_OK+$MB_ICONWARNING, "Loading error", $sMsg) _Exit() EndIf $sCurrentFile = $aFiles[1][0] If StringInStr($sCurrentFile, "||") Then $sCurrentFile = StringLeft($sCurrentFile, StringInStr($sCurrentFile, "||")-1) EndIf $iFolderLoaded = 1 Local $aFile = StringSplit($aFiles[1][0], "||", 1) If $aFile[0] > 1 And $aFile[2] = "Shuffled" Then $iShuffled = 1 Else $iShuffled = 0 EndIf _PlaylistLoad_1() $iIndex = _GetIndexByFileName($sCurrentFile) If $iIndex = -1 Then Return If $aFile[0] = 3 Then $iResumePosition = _Max(($aFile[3]-10), 0)*1000 ; Resume playback at 10 seconds before last playback position EndIf _SwitchToTrack($iIndex) EndIf _PlaylistLoad_2() EndFunc ;==> _LoadLastFolder 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 _MinimizeRestore() ; Minimize or restore a full screen video window, triggered by Ctr+Alt+Z HotKeySet("^!z") If $iFullScreen = 1 Then If $iMinimized = 0 Then GUISetState(@SW_MINIMIZE, $hVideoGUI) $iMinimized = 1 Else GUISetState(@SW_RESTORE, $hVideoGUI) $iMinimized = 0 $iFullScreen = 0 _FullScreen() EndIf EndIf While _IsPressed("5A", $hUser32DLL) Sleep(10) WEnd HotKeySet("^!z", _MinimizeRestore) EndFunc ;==> _MinimizeRestore Func _MPV_CheckIPCResponse() ; Called by the main loop to check if there is any response If $hPipe = -1 Then Return ; Peek at the pipe to see if any data has been input Local $tBytesAvail = DllStructCreate("dword") Local $aPipeInfo = DllCall("kernel32.dll", "bool", "PeekNamedPipe", _ "handle", $hPipe, "ptr", 0, "dword", 0, "ptr", 0, _ "ptr", DllStructGetPtr($tBytesAvail), "ptr", 0) If @error Or Not $aPipeInfo[0] Or DllStructGetData($tBytesAvail, 1) = 0 Then Return ; Prepare to perform data read Local $iRead = DllStructGetData($tBytesAvail, 1) ; Create a raw 1-byte data block byte structure ; This completely prevents interference from automatic ANSI conversion by AutoIt Local $tBuf = DllStructCreate("byte[" & $iRead & "]") Local $tBytesRead = DllStructCreate("dword") ; Directly below the ReadFile call section DllCall("kernel32.dll", "bool", "ReadFile", _ "handle", $hPipe, _ "ptr", DllStructGetPtr($tBuf), _ "dword", $iRead, _ "ptr", DllStructGetPtr($tBytesRead), "ptr", 0) ; Double-check the actual number of bytes read (Safety guard) Local $iActualRead = DllStructGetData($tBytesRead, 1) If $iActualRead = 0 Then Return ; Extract the binary data precisely matching the size of the read buffer Local $bData = BinaryMid(DllStructGetData($tBuf, 1), 1, $iActualRead) Local $sData = BinaryToString($bData, 4) ; Perform UTF-8 decoding ; Process stream line parsing If $sData <> "" Then $sBuffer &= $sData If StringInStr($sBuffer, @LF) Then Local $aLines = StringSplit($sBuffer, @LF, 3) For $i = 0 To UBound($aLines) - 2 Local $sLine = StringStripWS($aLines[$i], 3) If $sLine <> "" Then _MPV_ParseResponse($sLine) Next $sBuffer = $aLines[UBound($aLines) - 1] EndIf EndIf EndFunc ;==> _MPV_CheckIPCResponse Func _MPV_FlushPipe() ; Clear data in mpv's IPC pipe, required ater FileOpenDialog() and FileSelectFolder() If $hPipe = -1 Or $hPipe = 0 Then Return False Local $tAvail = DllStructCreate("dword") ; Check if there is data clogging the pipe buffer DllCall("kernel32.dll", "bool", "PeekNamedPipe", _ "handle", $hPipe, _ "ptr", 0, _ "dword", 0, _ "ptr", 0, _ "ptr", DllStructGetPtr($tAvail), _ "ptr", 0) Local $iBytesAvailable = DllStructGetData($tAvail, 1) ; If data is backed up, pull it all out to un-freeze MPV's thread If $iBytesAvailable > 0 Then Local $tTmpBuf = DllStructCreate("byte[" & $iBytesAvailable & "]") Local $tRead = DllStructCreate("dword") DllCall("kernel32.dll", "bool", "ReadFile", _ "handle", $hPipe, _ "ptr", DllStructGetPtr($tTmpBuf), _ "dword", $iBytesAvailable, _ "ptr", DllStructGetPtr($tRead), _ "ptr", 0) Return True EndIf _MPV_CheckIPCResponse() Return False EndFunc ;==> _MPV_FlushPipe Func _MPV_GetProperty($sPropertyName) ; Request mpv for propperty data and get the respose If $hPipe = -1 Or $hPipe = 0 Then Return "" ; 1. Create JSON for get_property command Local $sJsonCmd = '{"command": ["get_property", "' & $sPropertyName & '"], "request_id":999}' & @LF ; 2. Convert to UTF-8 binary send to IPC pipe Local $bBinaryData = StringToBinary($sJsonCmd, 4) ; 4 = UTF-8 Local $iBytesToWrite = BinaryLen($bBinaryData) Local $tBufWrite = DllStructCreate("byte[" & $iBytesToWrite & "]") DllStructSetData($tBufWrite, 1, $bBinaryData) Local $tBytesWritten = DllStructCreate("dword") Local $aRet = DllCall("kernel32.dll", "bool", "WriteFile", _ "handle", $hPipe, _ "ptr", DllStructGetPtr($tBufWrite), _ "dword", $iBytesToWrite, _ "ptr", DllStructGetPtr($tBytesWritten), _ "ptr", 0) If @error Or Not $aRet[0] Then Return "" ; 3. Get response from mpv ; MPV sends response with @LF at the end Local $sResponse = "" Local $tBufRead = DllStructCreate("byte[4096]") ; 4KB μˆ˜μ‹  버퍼 Local $tBytesRead = DllStructCreate("dword") Local $bData, $sChunk ; Give mpv to fill pipe with data Sleep(20) While True $aRet = DllCall("kernel32.dll", "bool", "ReadFile", _ "handle", $hPipe, _ "ptr", DllStructGetPtr($tBufRead), _ "dword", 4096, _ "ptr", DllStructGetPtr($tBytesRead), _ "ptr", 0) If @error Or Not $aRet[0] Then ExitLoop Local $iRead = DllStructGetData($tBytesRead, 1) If $iRead = 0 Then ExitLoop ; Extract binary data from struct $bData = DllStructGetData($tBufRead, 1) If $iRead < 4096 Then $bData = BinaryMid($bData, 1, $iRead) ; Convert UTF-8 binary to AutoIt string $sChunk = BinaryToString($bData, 4) $sResponse &= $sChunk ; @LF is the end of response string If StringInStr($sChunk, @LF) Then ExitLoop WEnd Return StringStripWS($sResponse, 3) EndFunc ;==> _MPV_GetProperty Func _MPV_LoadFile($sFilePath) ; Load a file in paused mode $bNextTrackTriggered = False If Not StringInStr($sFilePath, ":\") Then $sFilePath = $sFolder & $sFilePath Local $sEscapedPath = StringReplace($sFilePath, '\', '\\') ; Convert Unicode characters to Unicode escaped codes(\uXXXX) for JSON Local $sUnicodePath = "" Local $aChars = StringSplit($sEscapedPath, "") For $i = 1 To $aChars[0] Local $iCode = StringToASCIIArray($aChars[$i])[0] If $iCode > 127 Then $sUnicodePath &= "\u" & Hex($iCode, 4) ; Non-ASCII character Else $sUnicodePath &= $aChars[$i] ; ASCII character EndIf Next ; Assemble JSON with converted path Local $sCmd = '{"command": ["loadfile", "' & $sUnicodePath & '", "replace", -1, "pause=yes"]}' _MPV_SendCommand($sCmd) ; To be followed by _Play() called by _MPV_ParseResponse() Sleep(100) ; _MPV_SendCommand('{"command": ["observe_property", 1, "time-pos"]}') _MPV_SendCommand('{"command": ["keypress", "IGNORE"]}') EndFunc ;==> _MPV_LoadFile Func _MPV_ParseResponse($sLine) Local $aMatch, $sExt, $bIsAudioExt, $iNextIdx ;~ ; File path ;~ If StringInStr($sLine, '"request_id":"req_path"') Then ;~ Local $aMatch = StringRegExp($sLine, '"data"\s*:\s*"([^"]+)"', 3) ;~ If UBound($aMatch) > 0 Then $sPath = FileGetLongName(StringReplace($aMatch[0], '\\', '\')) ;~ Return ;~ EndIf ; Total duration property If StringInStr($sLine, '"request_id":"req_duration"') Then $aMatch = StringRegExp($sLine, '"data"\s*:\s*(\d+\.?\d*)', 3) If UBound($aMatch) > 0 Then GUICtrlSetData($idLength, _SecondsToTime(Int(Number($aMatch[0])), $hMain)) If StringInStr($sVideoTypes, _GetFileExtension($sPath)) Then GUICtrlSetData($idLength2, _SecondsToTime(Int(Number($aMatch[0])), $hVideoGUI)) EndIf $iMediaLength = Int(Number($aMatch[0]) * 1000) EndIf Return EndIf ; Track-list property to determine $isAudio, $isVideo and %bHasAlbumArt If StringInStr($sLine, '"request_id":"req_tracks"') Then $sExt = _GetFileExtension($sPath) $bIsAudioExt = (StringInStr($sAudioTypes, $sExt) > 0) Local $bHasPureVideoTrack = StringInStr($sLine, '"type":"video"') > 0 And StringInStr($sLine, '"albumart":false') > 0 If $bHasPureVideoTrack And (Not $bIsAudioExt) Then $isAudio = False $isVideo = True Else $isAudio = True $isVideo = False $iAspect = 0.0 EndIf _Play() ; _Play() is called by file-loaded event for other file types Return EndIf ; Video aspect property If StringInStr($sLine, '"request_id":"req_video_out"') Then $sExt = _GetFileExtension($sPath) $bIsAudioExt = (StringInStr($sAudioTypes, $sExt) > 0) If StringInStr($sLine, '"data":null') Or $isAudio = True Then $iAspect = 0.0 Else $aMatch = StringRegExp($sLine, '"aspect"\s*:\s*([0-9\.]+)', 3) If UBound($aMatch) > 0 Then $iAspect = Number($aMatch[0]) If $bHasAlbumArt Or $bIsAudioExt Then $iAspect = 0.0 Else $iAspect = 0.0 EndIf EndIf Return EndIf ; file-loaded event If StringInStr($sLine, '"event":"file-loaded"') Then $bNextTrackTriggered = False $isVideo = False $isAudio = False $bHasAlbumArt = False $iAspect = 0.0 $iPlayPrevious = 0 ; Send queries to IPC for properties ;_MPV_SendCommand('{"command": ["get_property", "path"], "request_id":"req_path"}') _MPV_SendCommand('{"command": ["get_property", "duration"], "request_id":"req_duration"}') _MPV_SendCommand('{"command": ["get_property", "video-out-params"], "request_id":"req_video_out"}') _MPV_SendCommand('{"command": ["get_property", "track-list"], "request_id":"req_tracks"}') Return EndIf ; end-file event If StringInStr($sLine, '"event":"end-file"') Then If StringInStr($sLine, '"reason":"eof"') Then _MPV_SendCommand('{"command": ["playlist-clear"]}') $iNextIdx = ($iRescanned <> 1) ? ($iIndex + 1) : 0 If $iRescanned = 1 Then $iRescanned = 0 If $aFilesToRepeat[0] = 0 Then If $iNextIdx > $aFiles[0][0] Then $iNextIdx = 2 Else Local $i For $i = 1 To $aFilesToRepeat[0] If $aFilesToRepeat[$i] >= $iNextIdx-1 Then ExitLoop Next $iNextIdx = ($i > $aFilesToRepeat[0]) ? ($aFilesToRepeat[1] + 1) : ($aFilesToRepeat[$i] + 1) EndIf _SwitchToTrack($iNextIdx) ElseIf StringInStr($sLine, '"reason":"error"') Then If $iPlayPrevious = 0 Then _PlayNext() Else _PlayPrevious() EndIf EndIf Return EndIf ; time-pos property as per "observe_property" command issued at the beginning of the program If StringInStr($sLine, '"id":1') Then ; _MPV_SendCommand('{"command": ["observe_property", 1, "time-pos"]}') $aMatch = StringRegExp($sLine, '"data"\s*:\s*([0-9\.]+)', 3) If UBound($aMatch) > 0 Then Local $fCurrentSec = Number($aMatch[0]) $iCurrentPos = Int($fCurrentSec * 1000) If $iRepeatAB = 1 Then If $fCurrentSec < $iRepeatABStart Or $fCurrentSec > $iRepeatABEnd Then _MPV_SendCommand('{"command": ["seek", ' & $iRepeatABStart & ', "absolute+exact"]}') EndIf ElseIf Not $bNextTrackTriggered And $iMediaLength > 0 And (($iMediaLength - $iCurrentPos) <= $iTrimTime) Then If $iRepeatCurrentFile = 1 Then _MPV_SendCommand('{"command": ["seek", 0, "absolute"]}') Return EndIf $bNextTrackTriggered = True $iNextIdx = ($iRescanned <> 1) ? ($iIndex + 1) : 0 If $iRescanned = 1 Then $iRescanned = 0 If $aFilesToRepeat[0] = 0 Then If $iNextIdx > $aFiles[0][0] Then $iNextIdx = 2 Else For $i = 1 To $aFilesToRepeat[0] If $aFilesToRepeat[$i] >= $iNextIdx-1 Then ExitLoop Next $iNextIdx = ($i > $aFilesToRepeat[0]) ? ($aFilesToRepeat[1] + 1) : ($aFilesToRepeat[$i] + 1) EndIf _SwitchToTrack($iNextIdx) EndIf EndIf EndIf EndFunc ;==> _MPV_ParseResponse Func _MPV_SendCommand($sJsonCmd) ; Send command to mpv If $hPipe = -1 Or $hPipe = 0 Then Return False ; Extra safety check for invalid handle Local $sDataToSend = $sJsonCmd & @LF ; 1. Convert the AutoIt UTF-16 string into a raw UTF-8 binary string Local $bBinaryData = StringToBinary($sDataToSend, 4) ; 4 = UTF-8 flags Local $iBytesToWrite = BinaryLen($bBinaryData) ; 2. Create a byte structure matched exactly to the binary size Local $tBuf = DllStructCreate("byte[" & $iBytesToWrite & "]") DllStructSetData($tBuf, 1, $bBinaryData) Local $tBytesWritten = DllStructCreate("dword") ; 3. Use Windows API WriteFile to pass the raw UTF-8 data Local $aRet = DllCall("kernel32.dll", "bool", "WriteFile", _ "handle", $hPipe, _ "ptr", DllStructGetPtr($tBuf), _ "dword", $iBytesToWrite, _ ; Must be bytes, not StringLen "ptr", DllStructGetPtr($tBytesWritten), _ "ptr", 0) If @error Or Not $aRet[0] Then Return False Return True EndFunc ;==> _MPV_SendCommand Func _Mute() ; Mute on/off HotKeySet("^!m") If $iMute = 0 Then _Audio_Action("SetMute", True, $hMPV_Process) ; Returns True if muted, False if unmuted _Audio_Action("SetMute", True, @AutoItPID) GUICtrlSetData($idSpeaker, "πŸ”‡") GUICtrlSetData($idSpeaker2, "πŸ”‡") $iMute = 1 Else _Audio_MasterVolume("UnMute") _Audio_Action("SetMute", False, $hMPV_Process) ; Returns True if muted, False if unmuted _Audio_Action("SetMute", False, @AutoItPID) ; Returns True if muted, False if unmuted GUICtrlSetData($idSpeaker, "πŸ”Š") GUICtrlSetData($idSpeaker2, "πŸ”Š") $iMute = 0 ; If folder is changed, the new audio device(myMedia) resumes default unmuted state EndIf While _IsPressed("4D", $hUser32DLL) Sleep(10) WEnd HotKeySet("^!m", _Mute) EndFunc ;==> _Mute Func _Options() ; Set options HotKeySet("^!o") If $iOptions = 0 Then $iOptions = 1 _OptionsUpdate() GUISetState(@SW_SHOW, $hOptions) If $iFullScreen = 1 Then WinSetOnTop($hOptions, "", 1) WinActivate($hOptions) EndIf Else WinSetOnTop($hOptions, "", 0) GUISetState(@SW_HIDE, $hOptions) $iOptions = 0 EndIf While _IsPressed("4F", $hUser32DLL) Sleep(10) WEnd HotKeySet("^!o", _Options) EndFunc ;==> _Options Func _OptionsColorButton() ; Adlib to change the color of $hMain buttons when the mouse is over them - 250ms Local $aArray1 = GUIGetCursorInfo($hMain) Local Static $iShuffle = 0, $iFile = 0, $iFolder = 0 If $aArray1[4] = $idShuffle Then If $iShuffle = 0 Then GUICtrlSetBkColor($idShuffle, $iBtnColor2) $iShuffle = 1 EndIf Else If $iShuffle = 1 Then GUICtrlSetBkColor($idShuffle, $iBtnColor) $iShuffle = 0 EndIf EndIf If $aArray1[4] = $idFile Then If $iFile = 0 Then GUICtrlSetBkColor($idFile, $iBtnColor2) $iFile = 1 EndIf Else If $iFile = 1 Then GUICtrlSetBkColor($idFile, $iBtnColor) $iFile = 0 EndIf EndIf If $aArray1[4] = $idFolder Then If $iFolder = 0 Then GUICtrlSetBkColor($idFolder, $iBtnColor2) $iFolder = 1 EndIf Else If $iFolder = 1 Then GUICtrlSetBkColor($idFolder, $iBtnColor) $iFolder = 0 EndIf EndIf If $iRepeatABWin = 1 Then Local $aArray2 = GUIGetCursorInfo($hRepeatAB) Local Static $iApply, $iHide If $aArray2[4] = $idApply Then If $iApply = 0 Then GUICtrlSetBkColor($idApply, $iBtnColor2) $iApply = 1 EndIf Else If $iApply = 1 Then GUICtrlSetBkColor($idApply, $iBtnColor) $iApply = 0 EndIf EndIf If $aArray2[4] = $idHide Then If $iHide = 0 Then GUICtrlSetBkColor($idHide, $iBtnColor2) $iHide = 1 EndIf Else If $iHide = 1 Then GUICtrlSetBkColor($idHide, $iBtnColor) $iHide = 0 EndIf EndIf EndIf If $iRepeatFilesWin = 1 Then Local $aArray3 = GUIGetCursorInfo($hRepeatFiles) Local Static $iFilesApply, $iFilesHide If $aArray3[4] = $idFilesApply Then If $iFilesApply = 0 Then GUICtrlSetBkColor($idFilesApply, $iBtnColor2) $iFilesApply = 1 EndIf Else If $iFilesApply = 1 Then GUICtrlSetBkColor($idFilesApply, $iBtnColor) $iFilesApply = 0 EndIf EndIf If $aArray3[4] = $idFilesHide Then If $iFilesHide = 0 Then GUICtrlSetBkColor($idFilesHide, $iBtnColor2) $iFilesHide = 1 EndIf Else If $iFilesHide = 1 Then GUICtrlSetBkColor($idFilesHide, $iBtnColor) $iFilesHide = 0 EndIf EndIf EndIf Local $aArray4 = GUIGetCursorInfo($hCover) Local Static $iClose, $iMinimize, $iOption, $iSetOnTop, $iQuestion If $aArray4[4] = $ctrlClose Then If $iClose = 0 Then GUICtrlSetBkColor($ctrlClose, 0xC42B1C) GUICtrlSetColor($ctrlClose, 0xEEEEEE) $iClose = 1 EndIf Else If $iClose = 1 Then GUICtrlSetBkColor($ctrlClose, $iBarColor) GUICtrlSetColor($ctrlClose, 0x404040) $iClose = 0 EndIf EndIf If $aArray4[4] = $idMinimize Then If $iMinimize = 0 Then GUICtrlSetBkColor($idMinimize, $iBtnColor) $iMinimize = 1 EndIf Else If $iMinimize = 1 Then GUICtrlSetBkColor($idMinimize, $iBarColor) $iMinimize = 0 EndIf EndIf If $aArray4[4] = $idOptions Then If $iOption = 0 Then GUICtrlSetBkColor($idOptions, $iBtnColor) $iOption = 1 EndIf Else If $iOption = 1 Then GUICtrlSetBkColor($idOptions, $iBarColor) $iOption = 0 EndIf EndIf If $aArray4[4] = $idSetOnTop Then If $iSetOnTop = 0 Then GUICtrlSetBkColor($idSetOnTop, $iBtnColor) $iSetOnTop = 1 EndIf Else If $iSetOnTop = 1 Then GUICtrlSetBkColor($idSetOnTop, $iBarColor) $iSetOnTop = 0 EndIf EndIf If $aArray4[4] = $idQuestion Then If $iQuestion = 0 Then GUICtrlSetBkColor($idQuestion, $iBtnColor) $iQuestion = 1 EndIf Else If $iQuestion = 1 Then GUICtrlSetBkColor($idQuestion, $iBarColor) $iQuestion = 0 EndIf EndIf EndFunc ;==> _OptionsColorButton Func _OptionsColorChange() ; Change colors of $hMain when color scheme is changed in Options window Switch $sColorScheme Case "Lavender" $iBarColor = 0xEA80FF $iBtnColor = 0xF2B3FF $iBKColor = 0xF6CCFF $iSliderColor = 0xFBE6FF $iBtnColor2 = $iSliderColor Case "Ocean Blue" $iBarColor = 0x80BFFF $iBtnColor = 0xB3D9FF $iBKColor = 0xCCE6FF $iSliderColor = 0xE6F2FF $iBtnColor2 = $iSliderColor Case "Mint Green" $iBarColor = 0x4DFF6A $iBtnColor = 0xB3FFBF $iBKColor = 0xCCFFD4 $iSliderColor = 0xE6FFEA $iBtnColor2 = $iSliderColor Case "Windows Default" $iBarColor = 0xEFF4F9 $iBtnColor = 0xFDFDFD $iBKColor = 0xF0F0F0 $iSliderColor = 0xD0D0D0 $iBtnColor2 = 0xE0EEF9 EndSwitch ; $hMain GUISetBkColor($iBarColor, $hCover) GUISetBkColor($iBKColor, $hMain) GUISetBkColor($iBKColor, $hChildGUI) GUICtrlSetBkColor($idSlider, $iSliderColor) GUICtrlSetBkColor($idShuffle, $iBtnColor) GUICtrlSetBkColor($idFile, $iBtnColor) GUICtrlSetBkColor($idFolder, $iBtnColor) GUICtrlSetBkColor($idQuestion, $iBarColor) GUICtrlSetBkColor($idSetOnTop, $iBarColor) GUICtrlSetBkColor($idOptions, $iBarColor) GUICtrlSetBkColor($idMinimize, $iBarColor) GUICtrlSetBkColor($ctrlClose, $iBarColor) ; $hRepeatAB GUISetBkColor($iBKColor, $hRepeatAB) GUICtrlSetBkColor($idStart, $iSliderColor) GUICtrlSetBkColor($idEnd, $iSliderColor) GUICtrlSetBkColor($idApply, $iBtnColor) GUICtrlSetBkColor($idHide, $iBtnColor) ; $hRepeatFiles GUISetBkColor($iBKColor, $hRepeatFiles) GUICtrlSetBkColor($idFiles, $iSliderColor) GUICtrlSetBkColor($idFilesApply, $iBtnColor) GUICtrlSetBkColor($idFilesHide, $iBtnColor) EndFunc ;==> _OptionsColorChange Func _OptionsCreate() ; Create Options window $hOptions = GUICreate("Options", 600, 510, -1, 0, $WS_SYSMENU) GUISetIcon($sIconFile) GUISetFont(11, 400, 0, $sFontName, $hOptions) GUICtrlCreateLabel("Set options for resuming playback", 20, 5, 500, 18) GUICtrlSetFont(-1, 12, 400, 0, $sFontName) GUICtrlCreateLabel("", 20, 24, 236, 1) GUICtrlSetBkColor(-1, 0x000000) GUICtrlCreateLabel("Playback Resume Mode", 35, 28, 500, 18) GUICtrlCreateLabel("", 35, 44, 154, 1) GUICtrlSetBkColor(-1, 0x000000) GUIStartGroup() $idResume1 = GUICtrlCreateRadio("Never", 50, 53, 60, 18) $idResume2 = GUICtrlCreateRadio("Ask", 120, 53, 40, 18) $idResume3 = GUICtrlCreateRadio("Always", 190, 53, 60, 18) GUICtrlCreateLabel("Playback Resume Criteria", 35, 78, 350, 18) GUICtrlCreateLabel("", 35, 94, 165, 1) GUICtrlSetBkColor(-1, 0x000000) GUICtrlCreateLabel("Minimum Total Length:", 50, 103, 170, 20) $idPrefTotal = GUICtrlCreateInput($iMinTotalLength, 230, 100, 45, 20, $ES_NUMBER+$ES_RIGHT) GUICtrlCreateLabel("seconds", 280, 103, 75, 18) GUICtrlCreateLabel("Minimum Playback Length:", 50, 123, 170, 18) $idPrefPlayed = GUICtrlCreateInput($iMinPlaybackLength, 230, 120, 45, 20, $ES_NUMBER+$ES_RIGHT) GUICtrlCreateLabel("seconds", 280, 123, 75, 18) GUICtrlSetData($idPrefTotal, $iMinTotalLength) GUICtrlSetData($idPrefPlayed, $iMinPlaybackLength) GUICtrlCreateLabel("Set media file types to include in the playlist", 20, 156, 500, 18) GUICtrlSetFont(-1, 12, 400, 0, $sFontName) GUICtrlCreateLabel("", 20, 175, 301, 1) GUICtrlSetBkColor(-1, 0x000000) GUICtrlCreateLabel("Audio File Types: ", 50, 185, 150, 18) $idAudioTypes = GUICtrlCreateInput($sAudioTypes, 165, 183, 300, 20) GUICtrlCreateLabel("Video File Types: ", 50, 208, 150, 18) $idVideoTypes = GUICtrlCreateInput($sVideoTypes, 165, 206, 300, 20) GUICtrlCreateLabel("(MIDI and CD file types are included by default.)", 50, 231, 350, 18) GUICtrlCreateLabel("Set color scheme for the main window", 20, 266, 500, 18) GUICtrlSetFont(-1, 12, 400, 0, $sFontName) GUICtrlCreateLabel("", 20, 285, 264, 1) GUICtrlSetBkColor(-1, 0x000000) GUIStartGroup() $idLavender = GUICtrlCreateRadio("Lavender", 50, 291, 80, 18) GUICtrlSetBkColor(-1, 0xF6CCFF) $idBlue = GUICtrlCreateRadio("Ocean Blue", 160, 291, 100, 18) GUICtrlSetBkColor(-1, 0xCCE6FF) $idGreen = GUICtrlCreateRadio("Mint Green", 270, 291, 100, 18) GUICtrlSetBkColor(-1, 0xCCFFDA) $idDefault = GUICtrlCreateRadio("Windows Default", 380, 291, 150, 18) GUICtrlSetBkColor(-1, 0xF0F0F0) GUICtrlCreateLabel("Keep video aspect when its window is resized?", 20, 326, 330, 18) GUICtrlSetFont(-1, 12, 400, 0, $sFontName) GUICtrlCreateLabel("", 20, 344, 327, 1) GUICtrlSetBkColor(-1, 0x000000) GUIStartGroup() $idAspectYes = GUICtrlCreateRadio("Yes", 50, 350, 80, 18) $idAspectNo = GUICtrlCreateRadio("No", 160, 350, 80, 18) GUICtrlCreateLabel("Set audio equalizer mode", 20, 385, 200, 18) GUICtrlSetFont(-1, 12, 400, 0, $sFontName) GUICtrlCreateLabel("", 20, 403, 182, 1) GUICtrlSetBkColor(-1, 0x000000) GUIStartGroup() $idNormal = GUICtrlCreateRadio("Normal", 50, 411, 100, 18) $idBass = GUICtrlCreateRadio("Deep Bass", 160, 411, 100, 18) $idClear = GUICtrlCreateRadio("Crystal Clear", 270, 411, 100, 18) $idPop = GUICtrlCreateRadio("Cinema/Voice", 380, 411, 120, 18) $idCinema = GUICtrlCreateRadio("Pop/Rock", 50, 434, 100, 18) $idMidnight = GUICtrlCreateRadio("Midnight", 160, 434, 100, 18) $idSpeech = GUICtrlCreateRadio("Speech/Podcast", 270, 434, 120, 18) _OptionsUpdate() _SetTaskBar($hOptions, "Delete Tab") EndFunc ;==> _OptionsCreate Func _OptionsMsg() ; Handle $sGUIMsg in $hOptions Switch $sGUIMsg Case $GUI_EVENT_CLOSE GUISetState(@SW_HIDE, $hOptions) $iOptions = 0 Case $idResume1 If BitAND(GUICtrlRead($idResume1), $GUI_CHECKED) = $GUI_CHECKED Then $sResumeMode = "Never" EndIf Case $idResume2 If BitAND(GUICtrlRead($idResume2), $GUI_CHECKED) = $GUI_CHECKED Then $sResumeMode = "Ask" EndIf Case $idResume3 If BitAND(GUICtrlRead($idResume3), $GUI_CHECKED) = $GUI_CHECKED Then $sResumeMode = "Always" EndIf Case $idPrefTotal $iMinTotalLength = GUICtrlRead($idPrefTotal) GUICtrlSetState($idPrefPlayed, $GUI_FOCUS) Case $idPrefPlayed $iMinPlaybackLength = GUICtrlRead($idPrefPlayed) Case $idAudioTypes $sAudioTypes = GUICtrlRead($idAudioTypes) Case $idVideoTypes $sVideoTypes = GUICtrlRead($idVideoTypes) Case $idLavender $sColorScheme = "Lavender" _OptionsColorChange() Case $idBlue $sColorScheme = "Ocean Blue" _OptionsColorChange() Case $idGreen $sColorScheme = "Mint Green" _OptionsColorChange() Case $idDefault $sColorScheme = "Windows Default" _OptionsColorChange() Case $idAspectYes $sKeepAspect = "Yes" _MPV_SendCommand('{"command": ["set_property", "keepaspect", true]}') _MPV_SendCommand('{"command": ["show-text", "' & "Keep aspect: Yes" & '"]}') _VideoResize() Case $idAspectNo $sKeepAspect = "No" _MPV_SendCommand('{"command": ["set_property", "keepaspect", false]}') _MPV_SendCommand('{"command": ["show-text", "' & "Keep aspect: No" & '"]}') Case $idNormal $sAudioMode = "Normal" _AudioModeSet($sAudioMode) Case $idBass $sAudioMode = "Deep Bass" _AudioModeSet($sAudioMode) Case $idClear $sAudioMode = "Crystal Clear" _AudioModeSet($sAudioMode) Case $idCinema $sAudioMode = "Cinema/Voice" _AudioModeSet($sAudioMode) Case $idPop $sAudioMode = "Pop/Rock" _AudioModeSet($sAudioMode) Case $idMidnight $sAudioMode = "Midnight" _AudioModeSet($sAudioMode) Case $idSpeech $sAudioMode = "Speech/Podcast" _AudioModeSet($sAudioMode) EndSwitch EndFunc ;==> _OptionsMsg Func _OptionsUpdate() Switch $sResumeMode Case "Never" GUICtrlSetState($idResume1, $GUI_CHECKED) Case "Ask" GUICtrlSetState($idResume2, $GUI_CHECKED) Case "Always" GUICtrlSetState($idResume3, $GUI_CHECKED) EndSwitch GUICtrlSetData($idPrefTotal, $iMinTotalLength) GUICtrlSetData($idPrefPlayed, $iMinPlaybackLength) GUICtrlSetData($idAudioTypes, $sAudioTypes) GUICtrlSetData($idVideoTypes, $sVideoTypes) Switch $sColorScheme Case "Lavender" GUICtrlSetState($idLavender, $GUI_CHECKED) Case "Ocean Blue" GUICtrlSetState($idBlue, $GUI_CHECKED) Case "Mint Green" GUICtrlSetState($idGreen, $GUI_CHECKED) Case "Windows Default" GUICtrlSetState($idDefault, $GUI_CHECKED) EndSwitch If $sKeepAspect = "Yes" Then GUICtrlSetState($idAspectYes, $GUI_CHECKED) Else GUICtrlSetState($idAspectNo, $GUI_CHECKED) EndIf Switch $sAudioMode Case "Normal" GUICtrlSetState($idNormal, $GUI_CHECKED) Case "Deep Bass" GUICtrlSetState($idBass, $GUI_CHECKED) Case "Crystal Clear" GUICtrlSetState($idClear, $GUI_CHECKED) Case "Cinema/Voice" GUICtrlSetState($idCinema, $GUI_CHECKED) Case "Pop/Rock" GUICtrlSetState($idPop, $GUI_CHECKED) Case "Midnight" GUICtrlSetState($idMidnight, $GUI_CHECKED) Case "Speech/Podcast" GUICtrlSetState($idSpeech, $GUI_CHECKED) EndSwitch EndFunc Func _Pause() ; Play or pause the playback (Click β–Ά/𝅛𝅛 icon on graphical control or press Ctrl+Alt+P) If $iPlaying = 0 Then Return HotKeySet("^!p") If $iPaused = 1 Then AdlibRegister("_ProgressBar", 250) If StringInStr($sMciFileTypes, _GetFileExtension($sCurrentFile)) Then mciSendString("resume myMedia") Else _MPV_SendCommand('{"command": ["set_property", "pause", false]}') EndIf $iPaused = 0 $iPlaying = 1 GUICtrlSetData($idPlay, "❚❚") GUICtrlSetData($idPlay2, "❚❚") _WinAPI_SetThreadExecutionState(BitOR($ES_DISPLAY_REQUIRED, $ES_CONTINUOUS, $ES_SYSTEM_REQUIRED, $ES_AWAYMODE_REQUIRED)) ; Disable ScreenSaver and other windows sleep features AdlibUnRegister("_ActivateSpeakers") Else AdlibUnRegister("_ProgressBar") If StringInStr($sMciFileTypes, _GetFileExtension($sCurrentFile)) Then mciSendString("pause myMedia") Else _MPV_SendCommand('{"command": ["set_property", "pause", true]}') EndIf $iPaused = 1 $iPlaying = 1 GUICtrlSetData($idPlay, "β–Ά") GUICtrlSetData($idPlay2, "β–Ά") _WinAPI_SetThreadExecutionState($ES_CONTINUOUS) ; Back to normal windows behavior AdlibRegister("_ActivateSpeakers", 30000) ; Keep the speakers continuously active EndIf While _IsPressed("50", $hUser32DLL) Sleep(10) WEnd HotKeySet("^!p", _Pause) EndFunc ;==> _Pause Func _Play() ; Play a new file $bNextTrackTriggered = False $sCurrentFile = $aFiles[$iIndex][0] If StringInStr($sCurrentFile, ":\") Then $sPath = $sCurrentFile Else $sPath = $sFolder & $sCurrentFile EndIf $sTitle = StringMid($sCurrentFile, StringInStr($sCurrentFile, "\", 0, -1)+1) AdlibUnRegister("_Marquee") ControlMove($hChildGUI, "", $idTitle, 0, 0) If StringInStr($sMciFileTypes, _GetFileExtension($sCurrentFile)) Then mciSendString("set myMedia time format milliseconds") If StringRight($sCurrentFile, 4) = ".cda" Then $iTrack = _ArraySearch($aTracks, $sCurrentFile) $iMediaLength = mciSendString("status myMedia length track " & $iTrack) $iTrackPos = mciSendString("status myMedia position track " & $iTrack) Else $iMediaLength = mciSendString("status myMedia length") ; milliseconds EndIf EndIf ; for mpv files, $iMediaLength is obtained by "duration" property in _MPV_ParseResponse() Local $tSeconds = Int($iMediaLength/1000) Local $sTime = _SecondsToTime($tSeconds, $hMain) ; mmm:ss GUICtrlSetData($idLength, $sTime) $sTime = _SecondsToTime($tSeconds, $hVideoGUI) If $isVideo Then GUICtrlSetData($idLength2, $sTime) ; hh:mm:ss EndIf ; In case length obtained in _GetLength() <> length obtained by winmm.dll, e.g, .mid files If $iAllDone = 1 And $aItems[$iIndex-2][2] <> $sTime Then $aFiles[$iIndex][1] = $sTime $aItems[$iIndex-2][2] = $sTime GUICtrlSendMsg($ctrlView, $LVM_UPDATE, $iIndex-2, 0) _GetLengthTotal() ; Update total time EndIf _PlaylistHighlight($iIndex, 1) If $iResumePosition > 0 Then If $iResumePosition/1000 < $iMinPlaybackLength Or Int($iMediaLength/1000) < $iMinTotalLength Or $sResumeMode = "Never" Then $iResumePosition = 0 ; $iResumePosition defined in _LoadFolder() function ElseIf $sResumeMode = "Ask" Then If $iFullScreen = 1 Then _FullScreen() EndIf Local $iRet = MsgBox($MB_YESNO, "Resume Playback", "Do you want to resume playback from the last playback position?", 0, $hMain) If $iRet = $IDNO Then $iResumePosition = 0 EndIf EndIf Local $playPos If _GetFileExtension($sCurrentFile) = "cda" Then $playPos = $iTrackPos Else If $iResumePosition = 0 Then $playPos = 0 Else $playPos = $iResumePosition EndIf EndIf If $iLenColNumber = 0 Then ; When this program is launched _Audio_MasterVolume("UnMute") _Audio_Action("SetMute", False, $hMPV_Process) _Audio_Action("SetMute", False, @AutoItPID) EndIf If $isVideo Then If $iMaximizedTitleHeight = 0 Then ; First video file of the session Local $tmp = GUICreate("", @DesktopWidth, @DesktopHeight, 0, 0) ; obtain title height of a maximized window GUISetState(@SW_MAXIMIZE, $tmp) Local $aPos1 = WinGetClientSize($tmp) GUIDelete($tmp) $aPos1 = WinGetClientSize($hVideoGUI) $iMaximizedTitleHeight = @DesktopHeight-$aPos1[1] ; 23 ; To normalize image size in screen whose Display Scale is set to exceed 100% WinMove($hVideoGUI, "", $aVideoPrePos[0], $aVideoPrePos[1], $aVideoPrePos[2], $aVideoPrePos[3]-1) WinMove($hVideoGUI, "", $aVideoPrePos[0], $aVideoPrePos[1], $aVideoPrePos[2], $aVideoPrePos[3]) EndIf If $sKeepAspect = "Yes" Then _MPV_SendCommand('{"command": ["set_property", "keepaspect", true]}') Else _MPV_SendCommand('{"command": ["set_property", "keepaspect", false]}') EndIf If $iFullScreen = 0 Then WinSetTitle($hVideoGUI, "", $sTitle) Else GUICtrlSetData($idSlider2, " " & $sTitle) EndIf GUISetState(@SW_SHOW, $hVideoGUI) GUISetState(@SW_SHOW, $hVCGui) $iTrimTime = 500 If $iMinimized = 1 Then GUISetState(@SW_MINIMIZE, $hVideoGUI) Else GUISetState(@SW_SHOW, $hVideoGUI) GUISetState(@SW_SHOW, $hVCGui) EndIf AdlibRegister("_VCShow", 500) AdlibRegister("_HotkeySet", 990) If $iExecute = 1 Then WinActivate($hExecute) Else GUISetState(@SW_HIDE, $hVCGui) GUISetState(@SW_HIDE, $hVideoGUI) $iTrimTime = 400 AdlibUnRegister("_VCShow") AdlibUnRegister("_HotkeySet") HotKeySet("{F11}") WinSetOnTop($hPlaylist, "", 0) WinSetOnTop($hProperties, "", 0) If $hHelp <> "" Then WinSetOnTop($hHelp, "", 0) EndIf WinSetOnTop($hOptions, "", 0) EndIf If StringInStr($sMciFileTypes, _GetFileExtension($sCurrentFile)) Then mciSendString("play myMedia from " & $playPos) While 1 If mciSendString("status myMedia mode") = "playing" Then ExitLoop Sleep(10) WEnd GUICtrlSetData($idTitle, $sTitle) ; allow time for MIDI synth initialization Else GUICtrlSetData($idTitle, $sTitle) If $playPos > 0 Then _MPV_SendCommand('{"command": ["seek", ' & $playPos/1000 & ', "absolute"]}') EndIf EndIf $iPaused = 0 GUICtrlSetData($idPlay, "❚❚") $iPlaying = 1 _AudioModeSet($sAudioMode) If $iResumePosition > 0 Then _VolumeSet(0) $iFadeStep = 0 AdlibRegister("_VolumeFadein", 100) Else _VolumeSet($iVolume) EndIf $iResumePosition = 0 _MPV_SendCommand('{"command": ["set_property", "pause", false]}') AdlibRegister("_ProgressBar", 250) _SetTaskBar($hMain, $sMainGuiTitle & @CRLF & $sTitle) 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 _FilePropertiesGet($sPath) $sCurrentFileProperties = $aFileInfo If $iProperties = 1 Then _GUICtrlListView_DeleteAllItems($idPropertiesView) _GUICtrlListView_AddArray($idPropertiesView, $sCurrentFileProperties) EndIf $aFiles[1][0] = $sCurrentFile _WinAPI_SetThreadExecutionState(BitOR($ES_DISPLAY_REQUIRED, $ES_CONTINUOUS, $ES_SYSTEM_REQUIRED, $ES_AWAYMODE_REQUIRED)) ; Disable ScreenSaver and other Windows sleep features EndFunc ;==> _Play Func _PlayBackgroundMidi() ; Define fallback paths for system MIDI files used to trigger the synthesizer driver. Local $aTargetMidis = [ _ @WindowsDir & "\Media\onestop.mid", _ @WindowsDir & "\Media\flourish.mid", _ @WindowsDir & "\Media\town.mid" _ ] ; Locate the first available MIDI file on the system. Local $sValidMidiPath = "" For $i = 0 To 2 If FileExists($aTargetMidis[$i]) Then $sValidMidiPath = $aTargetMidis[$i] ExitLoop EndIf Next If $sValidMidiPath <> "" Then mciSendString("open """ & $sValidMidiPath & """ alias dummyMidi type Sequencer") DllCall($hWinmmDLL, "int", "waveOutSetVolume", "int", 0 , "int", 0) mciSendString("play dummyMidi from 0") While Not mciSendString("status myMedia mode") <> "playing" Sleep(10) WEnd mciSendString("close dummyMidi") EndIf ; Terminate this background instance cleanly so it never spawns a duplicate zPlayer GUI. DllClose($hWinmmDLL) Exit EndFunc ;==> _ExecuteBackgroundMidi Func _PlaylistAddFiles() ; Add files to a custom playlist Local $fileTypes = "*." & StringReplace($sFileTypes, " ", ";*.") Local $sFiles = FileOpenDialog("Add one or more files to this playlist", "", "Audio/Video (" & $fileTypes & ")", 7, "", $hPlaylist) If $sFiles = "" Then Return EndIf If Not StringInStr($sFiles, "|") Then Local $iPos = StringInStr($sFiles, "\", 0, -1) $sFiles = StringLeft($sFiles, $iPos) & "|" & StringMid($sFiles, $iPos+1) EndIf Local $aFiles2 = StringSplit($sFiles, "|") ; Folder name|File 1|File 2... If DriveGetType($aFiles2[1]) = "CDROM" Then MsgBox($MB_OK+$MB_ICONWARNING, "CDROM Drive", "CD tracks cannot be added!", 5) Return EndIf If StringRight($aFiles2[1], 1) <> "\" Then $aFiles2[1] &= "\" _ArrayColInsert($aFiles2, 1) For $i = 2 To $aFiles2[0][0] $sFile = $aFiles2[1][0] & $aFiles2[$i][0] If _GetIndexByFileName($sFile) = -1 Then _ArrayAdd($aFiles, $sFile & "|" & $aFiles2[$i][1]) $aFiles[0][0] += 1 EndIf Next Local $sList, $aFiles1, $hFile If $iShuffled = 1 Then _ArrayShuffle($aFiles, 2) $sList = $sFolder & "zPlaylist-Shuffled.txt" $hFile = FileOpen($sList, 2+32) _FileWriteFromArray($hFile, $aFiles, 1, Default, ":|") FileClose($hFile) $aFiles1 = $aFiles _ArraySort($aFiles1, 0, 2) $sList = $sFolder & "zPlaylist.txt" $hFile = FileOpen($sList, 2+32) _FileWriteFromArray($hFile, $aFiles1, 1, Default, ":|") FileClose($hFile) Else $sList = $sFolder & "zPlaylist.txt" _ArraySort($aFiles, 0, 2) $hFile = FileOpen($sList, 2+32) _FileWriteFromArray($hFile, $aFiles, 1, Default, ":|") FileClose($hFile) $aFiles1 = $aFiles _ArrayShuffle($aFiles1, 2) $sList = $sFolder & "zPlaylist-Shuffled.txt" $hFile = FileOpen($sList, 2+32) _FileWriteFromArray($hFile, $aFiles1, 1, Default, ":|") FileClose($hFile) EndIf _PlaylistLoad_1() $iIndex = _GetIndexByFileName($sCurrentFile) _PlaylistLoad_2() EndFunc ;==> _PlaylistAddFiles Func _PlaylistCreate() ; Create playlist window $hPlaylist = GUICreate("Playing in Sorted Order...", $iListWidth, $iListHeight+25, -1, 0, $WS_SIZEBOX, -1) GUISetIcon($sIconFile) GUISetFont(9, 400, 0, $sFontName, $hPlaylist) Local $iStyles = BitOR($LVS_SHOWSELALWAYS, $LVS_NOSORTHEADER, $LVS_REPORT, $LVS_SINGLESEL, $LVS_OWNERDATA) Local $iStylesEx = BitOR($LVS_EX_FULLROWSELECT, $LVS_EX_GRIDLINES, $LVS_EX_DOUBLEBUFFER) $ctrlView = GUICtrlCreateListView("No|Folder|Length", 0, 0, $iListWidth, $iViewHeight, $iStyles, $iStylesEx) GUICtrlSetResizing(-1, $GUI_DOCKBORDERS) GUICtrlSetPos($ctrlView, 0, 0, $iListWidth+2, $iViewHeight) ; +2 eliminates right-side black borderline _GUICtrlListView_SetColumnWidth($ctrlView, 0, $iColumn1Width) _GUICtrlListView_SetColumnWidth($ctrlView, 1, $iListWidth-$iColumn1Width-60-21) ; -21 eliminates horizontal scroll bar _GUICtrlListView_SetColumnWidth($ctrlView, 2, 60) _GUICtrlListView_SetColumn($ctrlView, 0, "No", -1, 2) ; center align _GUICtrlListView_SetColumn($ctrlView, 2, "Length", -1, 2) ; center align Local $center = $iListWidth/2 $ctrlSearchBox = GUICtrlCreateInput("", $center-220, $iViewHeight+4, 120, 18) GUICtrlSetResizing(-1, $GUI_DOCKHCENTER+$GUI_DOCKBOTTOM+$GUI_DOCKSIZE) GUICtrlSetTip(-1, 'Enter search strings. Use quotation' & @CRLF & "marks for exact-match.", "", 1, 1) $ctrlFind = GUICtrlCreateButton("Find First", $center-100, $iViewHeight+3, 65, 20, $BS_BOTTOM) GUICtrlSetCursor(-1, 0) GUICtrlSetResizing(-1, $GUI_DOCKHCENTER+$GUI_DOCKBOTTOM+$GUI_DOCKSIZE) GUICtrlSetTip(-1, "Find first file containing these strings", "", 1, 1) $ctrlNext = GUICtrlCreateButton("Find Next", $center-35, $iViewHeight+3, 65, 20, $BS_BOTTOM) GUICtrlSetCursor(-1, 0) GUICtrlSetResizing(-1, $GUI_DOCKHCENTER+$GUI_DOCKBOTTOM+$GUI_DOCKSIZE) GUICtrlSetTip(-1, "Find next file containing these strings", "", 1, 1) $ctrlRevert = GUICtrlCreateButton("Revert", $center+30, $iViewHeight+3, 50, 20, $BS_BOTTOM) GUICtrlSetCursor(-1, 0) GUICtrlSetResizing(-1, $GUI_DOCKHCENTER+$GUI_DOCKBOTTOM+$GUI_DOCKSIZE) GUICtrlSetTip(-1, "Go back to currrent file", "", 1, 1) $ctrlRescan = GUICtrlCreateButton("Rescan", $center+90, $iViewHeight+3, 65, 20, $BS_BOTTOM) GUICtrlSetCursor(-1, 0) GUICtrlSetResizing(-1, $GUI_DOCKHCENTER+$GUI_DOCKBOTTOM+$GUI_DOCKSIZE) $ctrlReshuffle = GUICtrlCreateButton("Reshuffle", $center+155, $iViewHeight+3, 65, 20, $BS_BOTTOM) GUICtrlSetCursor(-1, 0) GUICtrlSetResizing(-1, $GUI_DOCKHCENTER+$GUI_DOCKBOTTOM+$GUI_DOCKSIZE) GUICtrlSetTip(-1, "Reshuffle the current playlist", "", 1, 1) $idContextmenu = GUICtrlCreateContextMenu($ctrlView) $idSubmenuPlay = GUICtrlCreateMenuItem("Play This File", $idContextmenu) $idSubmenuFileInfo = GUICtrlCreateMenuItem("File Properties", $idContextmenu) $idSubmenuSearch = GUICtrlCreateMenuItem("Search Internet", $idContextmenu) $idSubmenuFolder = GUICtrlCreateMenuItem("Go to This Folder", $idContextmenu) $idSubmenuMove = GUICtrlCreateMenuItem("Move This Item", $idContextmenu) $idSubmenuRemove = GUICtrlCreateMenuItem("Remove from Playlist", $idContextmenu) Local $aPos1 = WinGetPos($hPlaylist) WinMove($hPlaylist, "", (@DesktopWidth-$aPos1[2])/2, 0) _SetTaskBar($hPlaylist, "Delete Tab") EndFunc ;==> _PlaylistCreate Func _PlaylistCustomize() ; Create a custom playlist Local $sDir = GUICtrlRead($idCustomDir) If $sDir = "" Then Return If StringRight($sDir, 1) <> "\" Then $sDir &= "\" For $i = 1 To $aFiles[0][0] $aFiles[$i][0] = $sFolder & $aFiles[$i][0] Next Local $hFile, $aFiles2 If $iShuffled = 1 Then $hFile = FileOpen($sDir & "zPlaylist-Shuffled.txt", 2+8+32) ; Overwrite + Create directory if not existing _FileWriteFromArray($hFile, $aFiles, 1) FileClose($hFile) $aFiles2 = $aFiles _ArraySort($aFiles2, 0, 2) $hFile = FileOpen($sDir & "zPlaylist.txt", 2+8+32) ; Overwrite + Create directory if not existing _FileWriteFromArray($hFile, $aFiles2, 1) FileClose($hFile) Else $hFile = FileOpen($sDir & "zPlaylist.txt", 2+8+32) ; Overwrite + Create directory if not existing _FileWriteFromArray($hFile, $aFiles, 1) FileClose($hFile) $aFiles2 = $aFiles _ArrayShuffle($aFiles2, 2) $hFile = FileOpen($sDir & "zPlaylist-Shuffled.txt", 2+8+32) ; Overwrite + Create directory if not existing _FileWriteFromArray($hFile, $aFiles2, 1) FileClose($hFile) EndIf $iFolderLoaded = 1 $sFolder = $sDir $sCurrentFile = $aFiles[$iIndex][0] _PlaylistLoad_2() GUISetState(@SW_HIDE, $hCustom) EndFunc ;==> _PlaylistCustomize Func _PlaylistHighlight($Index, $iFocus) ; Highlight the current file in the playlist window _GUICtrlListView_Scroll($ctrlView, 0, $aFiles[0][0]*-$iItemHeight) _GUICtrlListView_Scroll($ctrlView, 0, ($Index-(ControlGetPos($hPlaylist, "", $ctrlView)[3])/$iItemHeight/2)*$iItemHeight) If $iFocus = 1 Then _GUICtrlListView_SetItemSelected($ctrlView, $Index-2, True, True) GUICtrlSetState($ctrlView, $GUI_FOCUS) EndIf EndFunc ;==> _PlaylistHighlight Func _PlaylistLoad_1() ; Shuffle or sort $aFiles as necessary and define $iIndex and $sPath If DriveGetType($sFolder) <> "CDROM" Then If $iShuffled = 1 Then If $iFolderLoaded = 1 Then Local $sList, $aFiles2 $sList = $sFolder & "zPlaylist-Shuffled.txt" If FileExists($sList) Then _FileReadToArray($sList, $aFiles2, 1+4, ":|") EndIf if IsArray($aFiles2) Then $aFiles = $aFiles2 Else _ArrayShuffle($aFiles, 2) EndIf Else _ArrayShuffle($aFiles, 2) EndIf EndIf EndIf _PlaylistToDictionary() $sCurrentFile = $aFiles[1][0] If StringInStr($sCurrentFile, "||") Then $sCurrentFile = StringLeft($sCurrentFile, StringInStr($sCurrentFile, "||")-1) EndIf $iIndex = _GetIndexByFileName($sCurrentFile) If $iIndex = -1 Then $iIndex = 2 $aFiles[1][0] = $aFiles[$iIndex][0] EndIf $sCurrentFile = $aFiles[$iIndex][0] $sPath = $sCurrentFile If Not StringInStr($sCurrentFile, ":\") Then $sPath = $sFolder & $sCurrentFile EndIf EndFunc ;==> _PlaylistLoad_1 Func _PlaylistLoad_2() ; Create $hPlaylist and fill the listview with playlist items ; _PlaylistLoad() was split into 2 so that _Play() can start as early as possible Local $winLoading = GUICreate("Playlist", $iListMinimumWidth-20, 45, -1, 150, $WS_POPUPWINDOW, $WS_EX_TOPMOST) GUISetFont(9, 600, 0, "Arial Bold", $winLoading) GUICtrlCreateLabel("Loading playlist...", 0, 15, $iListMinimumWidth-20, 20, $SS_CENTER) GUISetState() If $aFiles[0][0]-1 < 1000 Then $iColumn1Width = 29 ElseIf $aFiles[0][0]-1 < 10000 Then $iColumn1Width = 38 Else $iColumn1Width = 47 EndIf Local $lenArray[$aFiles[0][0]-1] For $v = 2 To $aFiles[0][0] $lenArray[$v-2] = StringLen($aFiles[$v][0]) Next _ArraySort($lenArray) ; this array contains string lengths of playlist items Local $iTitleLen = $lenArray[Int(($aFiles[0][0]-2)*0.85+0.5)] ; column will be wide enough to show full length of 85 percentile of items $iListWidth = $iTitleLen*$iCharacterWidth+$iColumn1Width+60 ; 60 is the width of Length column $iListWidth = _Min(@DesktopWidth, _Max($iListMinimumWidth, $iListWidth)) GUIDelete($hPlaylist) $hPlaylist = "" _PlaylistCreate() ; Fill up the virtual listview of $hPlaylist window Local $iRows = UBound($aFiles)-2 ReDim $aItems[$iRows][3], $aColors[$iRows][3] For $i = 0 To $iRows-1 $aItems[$i][0] = $i+1 $aItems[$i][1] = $aFiles[$i+2][0] $aItems[$i][2] = $aFiles[$i+2][1] For $j = 0 To 2 $aColors[$i][$j] = "0xFFFFFF" ; Background color for all items will be white Next Next GUICtrlSendMsg($ctrlView, $LVM_SETITEMCOUNT, $iRows, 0) If $iShuffled = 1 Then WinSetTitle($hPlaylist, "", "Playing in Shuffled Order...") GUICtrlSetData($idShuffle, "Sort") Else WinSetTitle($hPlaylist, "", "Playing in Sorted Order...") GUICtrlSetData($idShuffle, "Shuffle") EndIf GUICtrlSetState($idPlay, $GUI_FOCUS) ; Prevent dotted frames in $hMain buttons GUICtrlSetState($ctrlReshuffle, $GUI_DISABLE) Local $sText If $iFolderLoaded = 1 Then $sText = "Folder (" & $sFolder Else $sText = "Files (" & $sFolder EndIf $sText &= $sCDLabel & ")" _GUICtrlListView_SetColumn($ctrlView, 1, $sText) If $iFolderLoaded = 1 Then If StringInStr($aFiles[1][0], ":\") Then GUICtrlSetData($ctrlRescan, "Add Files") GUICtrlSetTip($ctrlRescan, "Add files to the current playlist", "", 1, 1) Else GUICtrlSetData($ctrlRescan, "Rescan") GUICtrlSetTip($ctrlRescan, "Rescan the current folder", "", 1, 1) EndIf Else GUICtrlSetData($ctrlRescan, "Save List") GUICtrlSetTip($ctrlRescan, "Create a custom playlist", "", 1, 1) EndIf If $iShuffled = 1 Then GUICtrlSetState($ctrlReshuffle, $GUI_ENABLE) EndIf If $iItemHeight = 0 Then Local $aItemRect = _GUICtrlListView_GetItemRect($ctrlView, 0, 0) $iItemHeight = $aItemRect[3] - $aItemRect[1] Local $hHeader = _GUICtrlListView_GetHeader($ctrlView) $iHeaderHeight = _WinAPI_GetWindowHeight($hHeader) EndIf If $iPlaylist = 1 Then ; Show playlist even after change of folder GUISetState(@SW_SHOW, $hPlaylist) EndIf _PlaylistHighlight($iIndex, 1) ; Fill length column of playlist $iAllDone = 0 $iTitleColored = 0 AdlibRegister("_GetLength", 25) GUIDelete($winLoading) If $aFiles[0][0] <= 2 Then GUICtrlDelete($idSubmenuMove) GUICtrlDelete($idSubmenuRemove) $idSubmenuMove = "" $idSubmenuRemove = "" ElseIf $idSubmenuRemove = "" Then $idSubmenuMove = GUICtrlCreateMenuItem("Move This Item", $idContextmenu) $idSubmenuRemove = GUICtrlCreateMenuItem("Remove From Playlist", $idContextmenu) EndIf EndFunc ;==> _PlaylistLoad_2 Func _PlaylistMsg() ; Respond to GUIGetMsg() from playlist window Local $id, $hFile, $tFile, $aPos1 Switch $aGUIMsg[0] Case $GUI_EVENT_CLOSE _PlaylistShow() $iPlaylist = 0 Case $GUI_EVENT_RESIZED $aPos1 = WinGetPos($hPlaylist) Local $w = $aPos1[2]-$iBorderWidth*2 GUICtrlSetPos($ctrlView, 0, 0, $aPos1[2]-$iBorderWidth*2+2, $aPos1[3]-$iTitleHeight-$iBorderWidth-35) ; +2 eliminates right-side black borderline _GUICtrlListView_SetColumnWidth($ctrlView, 0, $iColumn1Width) _GUICtrlListView_SetColumnWidth($ctrlView, 1, $w-$iColumn1Width-60-21) ; -21 eliminates horizontal scroll bar _GUICtrlListView_SetColumnWidth($ctrlView, 2, 60) Case $ctrlSearchBox _PlaylistSearch("First") Case $ctrlFind _PlaylistSearch("First") Case $ctrlNext _PlaylistSearch("Next") Case $ctrlRevert _PlaylistHighlight($iIndex, 1) Case $ctrlRescan If GUICtrlRead($ctrlRescan) = "Rescan" Then _Rescan() ElseIf GUICtrlRead($ctrlRescan) = "Add Files" Then _PlaylistAddFiles() ElseIf GUICtrlRead($ctrlRescan) = "Save List" Then If WinGetState($hCustom) < 7 Then GUISetState(@SW_SHOW, $hCustom) GUICtrlSetState($idCustomSelect, $GUI_FOCUS) EndIf EndIf Case $ctrlReshuffle _ArrayShuffle($aFiles, 2) If $iCD = 0 Then $hFile = FileOpen($sFolder & "zPlaylist-Shuffled.txt", 2+32) _FileWriteFromArray($hFile, $aFiles, 1, Default, ":|") FileClose($hFile) EndIf _PlaylistLoad_1() $iIndex = _GetIndexByFileName($sCurrentFile) _PlaylistLoad_2() Case $idSubmenuPlay $id = _GUICtrlListView_GetSelectedIndices($ctrlView) If $aFiles[$id+2][0] = $sCurrentFile Then If $iPaused = 1 Then _Pause() EndIf Return EndIf If $iRepeatAB = 1 Then _RepeatABCancel(1) EndIf If $iRepeatCurrentFile = 1 Then $iRepeatCurrentFile = 0 GUICtrlSetData($idRepeat, "U") ; No repeat GUICtrlSetData($idRepeat2, "U") EndIf If $iMute = 1 Then _Mute() $iPaused = 0 _SwitchToTrack($id+2) Case $idSubmenuFileInfo $iFilePropertiesFrom = _GUICtrlListView_GetSelectedIndices($ctrlView) ; Differentiate from function call by hotkey $iProperties = 0 _FilePropertiesShow() ; Hotkey for current file, context menu for selected item $iFilePropertiesFrom = "" Case $idSubmenuSearch $iInternetSearchFrom = _GUICtrlListView_GetSelectedIndices($ctrlView) ; Differentiate from function call by hotkey _InternetSearch() ; Hotkey for current file, context menu for selected item $iInternetSearchFrom = "" Case $idSubmenuFolder $tFile = $aFiles[_GUICtrlListView_GetSelectedIndices($ctrlView)+2][0] If StringInStr($tFile, ":\") Then $sPath = $tFile Else $sPath = $sFolder & $tFile EndIf RunWait("C:\Windows\explorer.exe /e," & '"' & StringLeft($sPath, StringInStr($sPath, "\", 0, -1)) & '"', "", @SW_MAXIMIZE) Sleep(1000) Send(StringMid($sPath, StringInStr($sPath, "\", 0, -1)+1)) Case $idSubmenuRemove $id = _GUICtrlListView_GetSelectedIndices($ctrlView)+2 _PlaylistRemove($id) Case $idSubmenuMove $id = _GUICtrlListView_GetSelectedIndices($ctrlView)+2 $tFile = $aFiles[$id][0] $aPos1 = MouseGetPos() WinMove($hMove, "", $aPos1[0]-80, $aPos1[1]-90) GUICtrlSetData($idMoveFile, $tFile) GUISetState(@SW_SHOW, $hMove) GUICtrlSetState($idMoveItem, $GUI_FOCUS) Local $sMsg, $iItem While 1 $sMsg = GUIGetMsg() Switch $sMsg Case $GUI_EVENT_CLOSE, $idMoveCancel $iItem = 0 ExitLoop Case $idMoveItem GUICtrlSetState($idMoveOk, $GUI_FOCUS) Case $idMoveOk $iItem = GUICtrlRead($idMoveItem) If String($iItem) = "0" Then $iItem = 1 ExitLoop EndSwitch WEnd GUISetState(@SW_HIDE, $hMove) GUICtrlSetData($idMoveItem, "") If $iItem <> 0 And $iItem <> $id-1 Then Local $a[1][2] $a[0][0] = $aFiles[$id][0] $a[0][1] = $aFiles[$id][1] _ArrayDelete($aFiles, $id) If $iItem < $id-1 Then _ArrayInsert($aFiles, $iItem+1, $a[0][0] & "|" & $a[0][1]) Else If $iItem+1 < UBound($aFiles) Then _ArrayInsert($aFiles, $iItem+1, $a[0][0] & "|" & $a[0][1]) Else _ArrayAdd($aFiles, $a[0][0] & "|" & $a[0][1]) $iItem = UBound($aFiles)-2 EndIf EndIf _PlaylistToDictionary() $iIndex = _GetIndexByFileName($sCurrentFile) _PlaylistLoad_2() _PlaylistHighlight($iItem+1, 1) EndIf EndSwitch If $iDoubleClicked = 1 Then $iDoubleClicked = 0 $id = _GUICtrlListView_GetSelectedIndices($ctrlView) If $aFiles[$id+2][0] = $sCurrentFile Then Return ; ignore a doubleclick on current item GUICtrlSetData($idPlay, "❚❚") If $iRepeatAB = 1 Then _RepeatABCancel(1) EndIf If $iRepeatCurrentFile = 1 Then $iRepeatCurrentFile = 0 GUICtrlSetData($idRepeat, "U") ; No repeat GUICtrlSetData($idRepeat2, "U") EndIf If $iMute = 1 Then _Mute() $iPaused = 0 _SwitchToTrack($id+2) EndIf EndFunc ;==> ListViewMsg Func _PlaylistRemove($id) ; Remove an item from playlist Local $clip, $sMsg, $iRet, $aList, $hFile $clip = $aFiles[$id][0] $sMsg = $clip & @CRLF & @CRLF $iRet = "" $sMsg &= "This item will be removed from playlist." $iRet = MsgBox($MB_OKCANCEL+$MB_ICONWARNING, "Remove from Playlist", $sMsg, 0, $hPlaylist) If $iRet = $IDCANCEL Then Return ; Remove item from playlist _ArrayDelete($aFiles, $id) $aFiles[0][0] -= 1 If $id = $iIndex Then If $iIndex > $aFiles[0][0] Then $iIndex = 2 $aFiles[1][0] = $aFiles[$iIndex][0] $sFile = $sCurrentFile Else $sFile = "" EndIf _PlaylistLoad_1() If $clip = $sFile Then If $iRepeatAB = 1 Then _RepeatABCancel(1) EndIf If $iRepeatCurrentFile = 1 Then $iRepeatCurrentFile = 0 GUICtrlSetData($idRepeat, "U") ; No repeat GUICtrlSetData($idRepeat2, "U") EndIf If StringInStr($sMpvFileTypes, _GetFileExtension($sFile)) Then _MPV_SendCommand('{"command": ["stop"]}') Else If _GetFileExtension($sFile) = "cda" Then mciSendString("stop MyMedia") Else mciSendString("close myMedia") EndIf EndIf _SwitchToTrack($iIndex) EndIf If $iCD = 0 And $iFolderLoaded = 1 Then If FileExists($sFolder & "zPlaylist-Shuffled.txt") Then _FileReadToArray($sFolder & "zPlaylist-Shuffled.txt", $aList, 1+4, ":|") $id = _ArraySearch($aList, $clip, 2) If $id >= 2 Then _ArrayDelete($aList, $id) $aList[1][0] = $aFiles[$iIndex][0] $hFile = FileOpen($sFolder & "zPlaylist-Shuffled.txt", 2+32) _FileWriteFromArray($hFile, $aList, 1, Default, ":|") FileClose($hFile) EndIf EndIf If FileExists($sFolder & "zPlaylist.txt") Then _FileReadToArray($sFolder & "zPlaylist.txt", $aList, 1+4, ":|") $id = _ArraySearch($aList, $clip, 2) If $id >= 2 Then _ArrayDelete($aList, $id) $aList[1][0] = $aFiles[$iIndex][0] $hFile = FileOpen($sFolder & "zPlaylist.txt", 2+32) _FileWriteFromArray($hFile, $aList, 1, Default, ":|") FileClose($hFile) EndIf EndIf EndIf _PlaylistLoad_2() EndFunc ;==> _PlaylistRemove Func _PlaylistSave() ; Save playlist before the program leaves a folder If $iFolderLoaded = 0 Or $iCD = 1 Or ($iPlaying = 1 And $iAllDone = 0) Then Return If IsArray($aFiles) = 0 Or $aFiles[0][0] < 2 Then Return Local $sPref = "", $iSeconds If Int($iMediaLength/1000) >= $iMinTotalLength Then If StringInStr($sMciFileTypes, _GetFileExtension($sCurrentFile)) Then $iSeconds = mciSendString("status myMedia position") Else $iSeconds = $iCurrentPos EndIf $iSeconds = Int($iSeconds/1000) If $iSeconds >= $iMinPlaybackLength Then $sPref = "||" & $iSeconds Else $sPref = "" EndIf EndIf Local $hFile, $aFiles2, $sList If GUICtrlRead($idShuffle) = "Sort" Then ; $iShuffled = 1 $aFiles[1][0] = $sCurrentFile & "||Shuffled" & $sPref $hFile = FileOpen($sFolder & "zPlaylist-Shuffled.txt", 2+32) _FileWriteFromArray($hFile, $aFiles, 1, Default, ":|") FileClose($hFile) $sList = $sFolder & "zPlaylist.txt" If FileExists($sList) Then _FileReadToArray($sList, $aFiles2, 1+4, ":|") EndIf If IsArray($aFiles2) Then $aFiles2[1][0] = $sCurrentFile & "||Shuffled" & $sPref Else $aFiles2 = $aFiles _ArraySort($aFiles2, 0, 2) EndIf $hFile = FileOpen($sList, 2+32) _FileWriteFromArray($hFile, $aFiles2, 1, Default, ":|") FileClose($hFile) Else $aFiles[1][0] = $sCurrentFile & "||Sorted" & $sPref $hFile = FileOpen($sFolder & "zPlaylist.txt", 2+32) _FileWriteFromArray($hFile, $aFiles, 1, Default, ":|") FileClose($hFile) $sList = $sFolder & "zPlaylist-Shuffled.txt" If FileExists($sList) Then _FileReadToArray($sList, $aFiles2, 1+4, ":|") EndIf If IsArray($aFiles2) Then $aFiles2[1][0] = $sCurrentFile & "||Sorted" & $sPref Else $aFiles2 = $aFiles _ArrayShuffle($aFiles2, 2) EndIf $hFile = FileOpen($sList, 2+32) _FileWriteFromArray($hFile, $aFiles2, 1, Default, ":|") FileClose($hFile) EndIf EndFunc ;==> _PlaylistSave Func _PlaylistSearch($round) ; Search a string in the playlist Local $now, $str, $viewItemID, $found, $a, $aPos1 $str = StringStripWS(GUICtrlRead($ctrlSearchBox), 3) If $str = "" Then Return If $round = "First" Then $now = 2 Else $now = _GUICtrlListView_GetSelectedIndices($ctrlView)+3 EndIf $viewItemID = 0 If (StringInStr(StringLeft($str, 1), '"') And StringRight($str, 1)) = '"' Or _ (StringInStr(StringLeft($str, 1), "'") And StringRight($str, 1)) = "'" Then $str = StringMid($str, 2, StringLen($str)-2) For $y = $now To $aFiles[0][0] If StringInStr($aFiles[$y][0], $str) Then $viewItemID = $y-1 ExitLoop EndIf Next Else If StringInStr($str, " ") Then For $y = $now To $aFiles[0][0] $found = True $a = StringSplit($str, " ") For $z = 1 To $a[0] If StringInStr($aFiles[$y][0], $a[$z]) Then $found = $found And True Else $found = $found And False ExitLoop EndIf Next If $found Then $viewItemID = $y-1 ExitLoop EndIf Next Else For $y = $now To $aFiles[0][0] If $y-1 = $str Or StringInStr($aFiles[$y][0], $str) Then $viewItemID = $y-1 ExitLoop EndIf Next EndIf EndIf If $viewItemID = 0 Then Local $sMsg If $round = "First" Then $sMsg = "Cannot find the string..." Else $sMsg = "No more found..." EndIf $aPos1 = WinGetPos($hPlaylist) Local $hMsg = GUICreate("Search", 200, 80, $aPos1[0]+($aPos1[2]-200)/2, $aPos1[1]+($aPos1[3])/2, $WS_SYSMENU, -1, $hPlaylist) GUISetFont(10, 400, 0, $sFontName, $hMsg) GUICtrlCreateLabel($sMsg, 0, 15, 200, 20, $SS_CENTER) GUISetIcon($sIconFile) GUISetState() Sleep(1500) GUIDelete($hMsg) GUICtrlSetState($ctrlSearchBox, $GUI_FOCUS) Else _PlaylistHighlight($viewItemID+1, 1) Sleep(300) GUICtrlSetState($ctrlNext, $GUI_FOCUS) Sleep(10) GUICtrlSetState($ctrlNext, $GUI_FOCUS) ; Don't know why, but this is required EndIf EndFunc ;==> _PlaylistSearch Func _PlaylistShow() ; Show the playlist (Click media title control, or press Ctrl+Alt+L) If GUICtrlRead($idTitle) = "Media title" Then Return HotKeySet("^!l") Local $aPos1 = WinGetPos($hPlaylist) Local $tPoint = _WinAPI_CreatePoint($aPos1[0]+$aPos1[2]-5, $aPos1[1]) ; If $idTitle is clicked when $hVideoGUI overlaps $hPlaylist, $hPlaylist will hide behind $hVideoGUI If $iPlaylist = 1 And $sPlaylistShowFrom = "idTitle" And $isVideo Then $aPos = WinGetPos($hVideoGUI) If $aPos[0] <= $aPos1[0] And $aPos[1] <= $aPos1[1] Then WinMove($hPlaylist, "", $aPos1[0], $aPos[1]-10) $tPoint = _WinAPI_CreatePoint($aPos1[0], $aPos[1]-10) EndIf EndIf $hTopWnd = _WinAPI_WindowFromPoint($tPoint) If $iPlaylist = 0 Then If $iFullScreen = 1 Then WinSetOnTop($hPlaylist, "", 1) EndIf WinMove($hPlaylist, "", (@DesktopWidth-$aPos1[2])/2, 0) GUISetState(@SW_SHOW, $hPlaylist) _PlaylistHighlight($iIndex, 1) $iPlaylist = 1 Else If $hPlaylist <> $hTopWnd Then ; If $hPlaylist was minimized or behind another window If $iFullScreen = 1 Then WinSetOnTop($hPlaylist, "", 1) EndIf WinActivate($hPlaylist) Else WinSetOnTop($hPlaylist, "", 0) GUISetState(@SW_HIDE, $hPlaylist) $iPlaylist = 0 EndIf EndIf While _IsPressed("4C", $hUser32DLL) Sleep(10) WEnd HotKeySet("^!l", _PlaylistShow) EndFunc ;==> _PlaylistShow Func _PlaylistToDictionary() ; Populate $oPlaylist with file names and index numbers, 9ms to add 1384 items Local $lastIdx = $aFiles[0][0], $sKey With $oPlaylist .RemoveAll() For $i = 2 To $lastIdx $sKey = $aFiles[$i][0] If $sKey <> "" Then .Item($sKey) = $i Next EndWith EndFunc ;==> _PlaylistToDictionary Func _PlayNext() If Not IsArray($aFiles) Or $aFiles[0][0] <= 0 Then Return AdlibUnRegister("_VolumeFadein") HotKeySet("^!{right}") HotKeySet("^!{.}") Local $sExt = _GetFileExtension($sCurrentFile) If $sExt = "cda" Then mciSendString("stop myMedia") ElseIf StringInStr($sMciFileTypes, $sExt) Then mciSendString("close myMedia") EndIf Local $iNextIdx = $iIndex, $sNextFile While 1 If $aFilesToRepeat[0] = 0 Then $iNextIdx += 1 If $iNextIdx > $aFiles[0][0] Then $iNextIdx = 2 Else For $i = 1 To $aFilesToRepeat[0] If $aFilesToRepeat[$i] > $iIndex - 1 Then ExitLoop EndIf Next If $i > $aFilesToRepeat[0] Then $iNextIdx = $aFilesToRepeat[1] + 1 Else $iNextIdx = $aFilesToRepeat[$i] + 1 EndIf EndIf $sNextFile = $aFiles[$iNextIdx][0] If Not StringInStr($sNextFile, ":\") Then $sNextFile = $sFolder & $aFiles[$iNextIdx][0] EndIf If FileExists($sNextFile) Then ExitLoop EndIf WEnd $sPath= $sNextFile If $iRepeatAB = 1 Then _RepeatABCancel(1) EndIf If $iRepeatCurrentFile = 1 Then $iRepeatCurrentFile = 0 GUICtrlSetData($idRepeat, "U") ; No repeat GUICtrlSetData($idRepeat2, "U") EndIf GUICtrlSetData($idPlay, "❚❚") GUICtrlSetData($idPlay2, "❚❚") $iPaused = 0 If $iMute = 1 Then _Mute() _SwitchToTrack($iNextIdx) While _IsPressed("27", $hUser32DLL) Or _IsPressed("BE", $hUser32DLL) Sleep(10) WEnd HotKeySet("^!{right}", _PlayNext) HotKeySet("^!{.}", _PlayNext) Sleep(20) EndFunc ;==> _PlayNext Func _PlayPrevious() If Not IsArray($aFiles) Or $aFiles[0][0] <= 0 Then Return AdlibUnRegister("_VolumeFadein") HotKeySet("^!{right}") HotKeySet("^!{.}") Local $sExt = _GetFileExtension($sCurrentFile) If $sExt = "cda" Then mciSendString("stop myMedia") ElseIf StringInStr($sMciFileTypes, $sExt) Then mciSendString("close myMedia") EndIf Local $iNextIdx = $iIndex, $sNextFile While 1 If $aFilesToRepeat[0] = 0 Then $iNextIdx -= 1 If $iNextIdx < 2 Then $iNextIdx = $aFiles[0][0] Else For $i = $aFilesToRepeat[0] To 1 Step -1 If $aFilesToRepeat[$i] < $iIndex - 1 Then ExitLoop EndIf Next If $i < 1 Then $iNextIdx = $aFilesToRepeat[$aFilesToRepeat[0]] + 1 Else $iNextIdx = $aFilesToRepeat[$i] + 1 EndIf EndIf $sNextFile = $aFiles[$iNextIdx][0] If Not StringInStr($sNextFile, ":\") Then $sNextFile = $sFolder & $aFiles[$iNextIdx][0] EndIf If FileExists($sNextFile) Then ExitLoop EndIf WEnd If $iRepeatAB = 1 Then _RepeatABCancel(1) EndIf If $iRepeatCurrentFile = 1 Then $iRepeatCurrentFile = 0 GUICtrlSetData($idRepeat, "U") ; No repeat GUICtrlSetData($idRepeat2, "U") EndIf GUICtrlSetData($idPlay, "❚❚") GUICtrlSetData($idPlay2, "❚❚") $iPaused = 0 If $iMute = 1 Then _Mute() _SwitchToTrack($iNextIdx) While _IsPressed("27", $hUser32DLL) Or _IsPressed("BE", $hUser32DLL) Sleep(10) WEnd HotKeySet("^!{right}", _PlayNext) HotKeySet("^!{.}", _PlayNext) $iPlayPrevious = 1 Sleep(20) EndFunc ;==> _PlayPrevious Func _ProgressBar() ; Adlib function to display progress of playback, 250ms Local $mediaPos If StringInStr($sMciFileTypes, _GetFileExtension($sCurrentFile)) Then $mediaPos = mciSendString("status myMedia position") If $bNextTrackTriggered = False And $mediaPos >= $iMediaLength - $iTrimTime Then $bNextTrackTriggered = True ; Without this, a MIDI file between 2 MPV files may be skipped EndIf If _GetFileExtension($sCurrentFile) = "cda" Then $mediaPos = $mediaPos - $iTrackPos EndIf Else $mediaPos = $iCurrentPos ; Obtained by mpv's "time-pos" property in _MPV_ParseResponse() EndIf GUICtrlSetPos($idProgBar, $iSliderPosX+$mediaPos/$iMediaLength*$iSliderLength) Local $tSeconds = Int($mediaPos/1000) Local $sTime = _SecondsToTime($tSeconds, $hMain) If GUICtrlRead($idCurrentPos) <> $sTime Then GUICtrlSetData($idCurrentPos, $sTime) EndIf If $isVideo Then GUICtrlSetPos($idProgBar2, $mediaPos/$iMediaLength*$iSliderLength2) $sTime = _SecondsToTime($tSeconds, $hVideoGUI) If GUICtrlRead($idCurrentPos2) <> $sTime Then GUICtrlSetData($idCurrentPos2, $sTime) EndIf EndIf EndFunc ;==> _ProgressBar Func _RepeatAB() ; Respond to click on $idCurrentPos/$idCurrentPos2 If $iAllDone < 0 Then Return If $iRepeatABWin = 0 Then GUISetState(@SW_HIDE, $hRepeatFiles) $iRepeatFilesWin = 0 Local $aPos1 = WinGetPos($hMain) If $aPos1[0] < $iRepeatABWidth Then WinMove($hRepeatAB, "", $aPos1[0]+$iMainGuiWidth+$iMainBorderWidth, $aPos1[1]+1) Else WinMove($hRepeatAB, "", $aPos1[0]-$iRepeatABWidth, $aPos1[1]+1) EndIf GUISetState(@SW_SHOW, $hRepeatAB) If $iRepeatAB = 0 Then GUICtrlSetState($idStart, $GUI_FOCUS) Else GUICtrlSetState($idApply, $GUI_FOCUS) EndIf $iRepeatABWin = 1 Else GUISetState(@SW_HIDE, $hRepeatAB) $iRepeatABWin = 0 EndIf EndFunc ;==> _RepeatAB Func _RepeatABCancel($iHide) ; Cancel AB repeat setup, 1: Hide the window If $iRepeatAB = 0 Then Return If $iHide = 1 Then ; When moving to a different file or unloading the playlist GUISetState(@SW_HIDE, $hRepeatAB) $iRepeatABWin = 0 EndIf GUICtrlSetState($idRepeatAB, $GUI_HIDE) GUICtrlSetState($idRepeatAB2, $GUI_HIDE) GUICtrlSetColor($idCurrentPos, 0) GUICtrlSetColor($idCurrentPos2, 0) GUICtrlSetData($idApply, "Apply") GUICtrlSetTip($idApply, "Start A-B repeat function.", "", 1, 1) GUICtrlSetState($idStart, $GUI_ENABLE) GUICtrlSetState($idEnd, $GUI_ENABLE) GUICtrlSetData($idStart, "") GUICtrlSetData($idEnd, "") $iRepeatABStart = 0 $iRepeatABEnd = 0 $iRepeatAB = 0 EndFunc ;==> _RepeatABCancel Func _RepeatABMsg() ; Respond to GUIGetMsg() from $hRepeatAB window Local $start, $end, $min, $sec, $i Switch $aGUIMsg[0] Case $idStart ; Define starting position $start = GUICtrlRead($idStart) If $start = "" Then Return For $i = 1 To StringLen($start) If Not StringInStr("0123456789:", StringMid($start, $i, 1)) Then GUICtrlSetData($idStart, "") Return EndIf Next $i = StringInStr($start, ":") If $i > 0 Then $start = StringLeft($start, $i-1)*60+StringMid($start, $i+1) EndIf If $start >= Int($iMediaLength /1000) Then GUICtrlSetData($idStart, "") Return EndIf $min = Int($start/60) $sec = StringFormat("%02i", $start-$min*60) GUICtrlSetData($idStart, $min & ":" & $sec) Case $idEnd ; Define ending position $end = StringStripWS(GUICtrlRead($idEnd), 8) If $end = "" Then GUICtrlSetData($idEnd, "") Return EndIf For $i = 1 To StringLen($end) If Not StringInStr("0123456789:", StringMid($end, $i, 1)) Then GUICtrlSetData($idEnd, "") Return EndIf Next $i = StringInStr($end, ":") If $i > 0 Then $end = StringLeft($end, $i-1)*60+StringMid($end, $i+1) EndIf If $end >= Int($iMediaLength /1000) Then $end = Int($iMediaLength /1000) EndIf If $start >= $end Then GUICtrlSetData($idStart, "") GUICtrlSetData($idEnd, "") Return EndIf $min = Int($end/60) $sec = StringFormat("%02i", $end-$min*60) GUICtrlSetData($idEnd, $min & ":" & $sec) Case $idApply If GUICtrlRead($idApply) = "Apply" Then ; Apply A-B repeat function $end = StringStripWS(GUICtrlRead($idEnd), 8) If Not StringInStr($end, ":") Then If $end = "" Then GUICtrlSetData($idEnd, "") Return EndIf For $i = 1 To StringLen($end) If Not StringInStr("0123456789:", StringMid($end, $i, 1)) Then GUICtrlSetData($idEnd, "") Return EndIf Next $i = StringInStr($end, ":") If $i > 0 Then $end = StringLeft($end, $i-1)*60+StringMid($end, $i+1) EndIf If $end >= Int($iMediaLength /1000) Then $end = Int($iMediaLength /1000) EndIf If $start >= $end Then GUICtrlSetData($idStart, "") GUICtrlSetData($idEnd, "") Return EndIf $min = Int($end/60) $sec = StringFormat("%02i", $end-$min*60) GUICtrlSetData($idEnd, $min & ":" & $sec) EndIf $iRepeatABStart = GUICtrlRead($idStart) If $iRepeatABStart = "" Then Return EndIf $i = StringInStr($iRepeatABStart, ":") If $i > 0 Then $iRepeatABStart = StringLeft($iRepeatABStart, $i-1)*60+StringMid($iRepeatABStart, $i+1) EndIf $iRepeatABEnd = GUICtrlRead($idEnd) If $iRepeatABEnd = "" Then Return EndIf $i = StringInStr($iRepeatABEnd, ":") If $i > 0 Then $iRepeatABEnd = StringLeft($iRepeatABEnd, $i-1)*60+StringMid($iRepeatABEnd, $i+1) EndIf If $iRepeatABStart >= $iRepeatABEnd Then GUICtrlSetData($idStart, "") GUICtrlSetData($idEnd, "") Return EndIf GUICtrlSetData($idApply, "Cancel") GUICtrlSetTip($idApply, "Stop A-B repeat function.", "", 1, 1) GUICtrlSetPos($idRepeatAB, $iSliderPosX+$iSliderLength/$iMediaLength*$iRepeatABStart*1000, 27, $iSliderLength/$iMediaLength*($iRepeatABEnd-$iRepeatABStart)*1000+$iProgBarWidth) GUICtrlSetPos($idRepeatAB2, $iSliderLength2/$iMediaLength*$iRepeatABStart*1000, 5, $iSliderLength2/$iMediaLength*($iRepeatABEnd-$iRepeatABStart)*1000+$iProgBarWidth) GUICtrlSetState($idRepeatAB, $GUI_SHOW) GUICtrlSetState($idRepeatAB2, $GUI_SHOW) GUICtrlSetColor($idCurrentPos, 0xFF0055) GUICtrlSetColor($idCurrentPos2, 0xFF0055) GUICtrlSetState($idStart, $GUI_DISABLE) GUICtrlSetState($idEnd, $GUI_DISABLE) $iRepeatAB = 1 $start = 0 $end = 0 If StringInStr($sMciFileTypes, _GetFileExtension($sCurrentFile)) Then Local $mediaPos = mciSendString("status myMedia position") If $mediaPos < $iRepeatABStart*1000 Or $mediaPos > $iRepeatABEnd*1000 Then mciSendString("stop myMedia") mciSendString("play myMedia from " & $iRepeatABStart*1000) EndIf EndIf If $iPaused = 1 Then _Pause() EndIf ElseIf GUICtrlRead($idApply) = "Cancel" Then ; Cancel A-B repeat function _RepeatABCancel(0) EndIf Case $idHide ; Hide window GUISetState(@SW_HIDE, $hRepeatAB) $iRepeatABWin = 0 EndSwitch EndFunc ;==> _RepeatABMsg Func _RepeatCurrentFile() ; Repeat current file on/off (Click center of β—€Uβ–Ά icon or press Ctrl+Alt+R) If $iAllDone < 0 Then Return HotKeySet("^!r") If $iRepeatCurrentFile = 0 Then $iRepeatCurrentFile = 1 If $iRepeatAB = 1 Then _RepeatABCancel(1) EndIf GUICtrlSetData($idRepeat, "0") ; The curent file will be repeated GUICtrlSetData($idRepeat2, "0") Else $iRepeatCurrentFile = 0 GUICtrlSetData($idRepeat, "U") ; No repeat GUICtrlSetData($idRepeat2, "U") EndIf While _IsPressed("52", $hUser32DLL) Sleep(10) WEnd HotKeySet("^!r", _RepeatCurrentFile) EndFunc ;==> _Repeat Func _RepeatFiles() ; Respond to click on $idLength/$idLength2 If $iAllDone < 0 Then Return If $iRepeatFilesWin = 0 Then GUISetState(@SW_HIDE, $hRepeatAB) $iRepeatABWin = 0 Local $aPos1 = WinGetPos($hMain) If $aPos1[0]+$iMainGuiWidth+$iRepeatABWidth+$iMainBorderWidth <= $iClientWidth Then WinMove($hRepeatFiles, "", $aPos1[0]+$iMainGuiWidth+$iMainBorderWidth, $aPos1[1]+1) Else WinMove($hRepeatFiles, "", $aPos1[0]-$iRepeatABWidth, $aPos1[1]+1) EndIf GUISetState(@SW_SHOW, $hRepeatFiles) If $aFilesToRepeat[0] = 0 Then GUICtrlSetState($idFiles, $GUI_FOCUS) Send("{END}") Else GUICtrlSetState($idFilesApply, $GUI_FOCUS) EndIf $iRepeatFilesWin = 1 Else GUISetState(@SW_HIDE, $hRepeatFiles) $iRepeatFilesWin = 0 EndIf EndFunc ;==> _RepeatFiles Func _RepeatFilesCancel($sFrom) ; Cancel multi-file repeat set-up and reload playlist If $sFrom <> "_RepeatFiles" Then ; When unloading the playlist or moving to a different folder GUISetState(@SW_HIDE, $hRepeatFiles) $iRepeatFilesWin = 0 GUICtrlSetData($idFiles, "") EndIf Local $iColor = 0xFFFFFF For $i = 1 To $aFilesToRepeat[0] If _ArraySearch($aColors, $aFilesToRepeat[$i]-1) Then For $j = 0 To 2 $aColors[$aFilesToRepeat[$i]-1][$j] = $iColor ; Background color for files to be repeated will be white Next GUICtrlSendMsg($ctrlView, $LVM_UPDATE, $aFilesToRepeat[$i]-1, 0) EndIf Next If $sFrom <> "_Unload" Then _PlaylistHighlight($iIndex, 0) GUICtrlSetState($idFilesApply, $GUI_FOCUS) EndIf GUICtrlSetState($idShuffle, $GUI_ENABLE) GUICtrlSetState($ctrlRescan, $GUI_ENABLE) If $iShuffled = 1 Then GUICtrlSetState($ctrlReshuffle, $GUI_ENABLE) EndIf $aFilesToRepeat[0] = 0 ReDim $aFilesToRepeat[1] GUICtrlSetData($idFilesApply, "Apply") GUICtrlSetState($idFiles, $GUI_ENABLE) GUICtrlSetTip($idFilesApply, "Start multi-file repeat function.", "", 1, 1) GUICtrlSetColor($idLength, 0) GUICtrlSetColor($idLength2, 0) $idSubmenuMove = GUICtrlCreateMenuItem("Move This Item", $idContextmenu) $idSubmenuRemove = GUICtrlCreateMenuItem("Remove from Playlist", $idContextmenu) EndFunc ;==> _RepeatFilesCancel Func _RepeatFilesMsg() ; Respond to GUIGetMsg() from $hRepeatFiles Switch $aGUIMsg[0] Case $idFiles If _IsPressed("0D") Then GUICtrlSetState($idFilesApply, $GUI_FOCUS) EndIf Case $idFilesApply If GUICtrlRead($idFilesApply) = "Apply" Then Local $sFilesToRepeat = GUICtrlRead($idFiles) If $sFilesToRepeat = "" Then $aFilesToRepeat[0] = 0 Return EndIf $sFilesToRepeat = StringStripWS($sFilesToRepeat, 8) Local $aTemp = StringSplit($sFilesToRepeat, ","), $sTemp = "," For $i = 1 To $aTemp[0] If StringInStr($aTemp[$i], "-") Then Local $iFrom = Number(StringLeft($aTemp[$i], StringInStr($aTemp[$i], "-")-1)) Local $iTo = Number(StringMid($aTemp[$i], StringInStr($aTemp[$i], "-", 0, -1)+1)) If $iTo >= $iFrom Then For $j = $iFrom To $iTo If $j >= $aFiles[0][0] Or StringInStr($sTemp, "," & $j & ",") Then ContinueLoop $sTemp &= $j & "," Next Else For $j = $iFrom To $iTo Step -1 If $j >= $aFiles[0][0] Or StringInStr($sTemp, "," & $j & ",") Then ContinueLoop $sTemp &= $j & "," Next EndIf Else If $aTemp[$i] >= $aFiles[0][0] Or StringInStr($sTemp, "," & $aTemp[$i] & ",") Then ContinueLoop $sTemp &= $aTemp[$i] & "," EndIf Next If $sTemp == "," Then MsgBox(0, "", "Invalid item numbers!", 3) Return EndIf $sTemp = StringTrimRight(StringTrimLeft($sTemp, 1), 1) $aFilesToRepeat = StringSplit($sTemp, ",") If $iRepeatAB = 1 Then _RepeatABCancel(1) EndIf If $iRepeatCurrentFile = 1 Then $iRepeatCurrentFile = 0 GUICtrlSetData($idRepeat, "U") ; No repeat GUICtrlSetData($idRepeat2, "U") EndIf If $iPaused = 1 Then _Pause() EndIf For $i = 1 To $aFilesToRepeat[0] $aFilesToRepeat[$i] = Number($aFilesToRepeat[$i]) Next _ArraySort($aFilesToRepeat, 0, 1) $sFilesToRepeat = "," For $i = 1 To $aFilesToRepeat[0] $sFilesToRepeat &= $aFilesToRepeat[$i] & "," Next Local $iColor = _WinAPI_SwitchColor(0xFFB3E6) ; Convert RGB to BGR For $i = 1 To $aFilesToRepeat[0] Local $iTargetRow = $aFilesToRepeat[$i] - 1 For $j = 0 To 2 $aColors[$iTargetRow][$j] = $iColor ; Background color for files to be repeated will be pink Next GUICtrlSendMsg($ctrlView, $LVM_UPDATE, $iTargetRow, 0) Next _PlaylistHighlight($iIndex, 1) GUICtrlSetState($idFilesApply, $GUI_FOCUS) GUICtrlSetState($idShuffle, $GUI_DISABLE) GUICtrlSetState($ctrlRescan, $GUI_DISABLE) GUICtrlSetState($ctrlReshuffle, $GUI_DISABLE) GUICtrlSetData($idFilesApply, "Cancel") GUICtrlSetState($idFiles, $GUI_DISABLE) GUICtrlSetTip($idFilesApply, "Stop multi-file repeat function.", "", 1, 1) GUICtrlSetColor($idLength, 0xFF0055) GUICtrlSetColor($idLength2, 0xFF0055) GUICtrlDelete($idSubmenuMove) GUICtrlDelete($idSubmenuRemove) $idSubmenuMove = "" $idSubmenuRemove = "" GUICtrlSetState($idFilesApply, $GUI_FOCUS) If Not StringInStr($sFilesToRepeat, "," & $iIndex-1 & ",") Then Local $iNextIdx = $aFilesToRepeat[1] + 1 _SwitchToTrack($iNextIdx) EndIf Else _RepeatFilesCancel("_RepeatFiles"); EndIf Case $idFilesHide GUISetState(@SW_HIDE, $hRepeatFiles) $iRepeatFilesWin = 0 EndSwitch EndFunc ;==> _RepeatFilesMsg Func _Rescan() ; Rescan the folder and refresh the playlist Local $aList, $hFile If $iCD = 0 Then Local $fileTypes = "*." & StringReplace($sFileTypes, " ", ";*.") $aList = _FileListToArrayRec($sFolder, $fileTypes, 1, 1, 1, 1) Local $iRootFolders, $iSubFolders, $iRet For $i = 1 To $aList[0] If StringInStr($aList[$i], "\") Then $iSubFolders += 1 Else $iRootFolders += 1 EndIf Next If $iSubFolders > 0 And $iRootFolders > 0 Then If $iFullScreen = 1 Then _FullScreen() EndIf Local $sMsg = "Number of files in top-level folder:" & @TAB & $iRootFolders & @CRLF $sMsg &= "Number of files in sub-level folders:" & @TAB & $iSubFolders & @CRLF & @CRLF $sMsg &= "Do you want to include files in the subfolders?" $iRet = MsgBox($MB_YESNO, "Include files in subfolders?", $sMsg, 0, $hPlaylist) EndIf If $iRet = $IDNO Then $aList = _FileListToArrayRec($sFolder, $fileTypes, 29, 0, 1, 1) ; exclude files in subfolders EndIf _ArrayInsert($aList, 1, $sCurrentFile) $aList[0] += 1 _ArrayColInsert($aList, 1) If $iShuffled = 0 Then $hFile = FileOpen($sFolder & "zPlaylist.txt", 2+32) FileDelete($sFolder & "zPlaylist-Shuffled.txt") Else _ArrayShuffle($aList, 2) $hFile = FileOpen($sFolder & "zPlaylist-Shuffled.txt", 2+32) FileDelete($sFolder & "zPlaylist.txt") EndIf _FileWriteFromArray($hFile, $aList, 1, Default, ":|") FileClose($hFile) Else $aList = $aTracks _ArrayInsert($aList, 1, $sCurrentFile) $aList[0] += 1 _ArrayColInsert($aList, 1) EndIf $aFiles = $aList _PlaylistLoad_1() $iIndex = _GetIndexByFileName($sCurrentFile) If $iIndex = -1 Then $iRescanned = 1 ; $iIndex becomes 2 per _PlaylistLoad_1() and not adjusted in main While loop mciSendString("stop myMedia") _SwitchToTrack(2) EndIf _PlaylistLoad_2() HotKeySet("^!l", _PlaylistShow) EndFunc ;==> _Rescan Func _SaveCoverPos() ; Adlib to save position of $hCover after 1 second of position change, if it stays the same AdlibUnRegister("_SaveCoverPos") Local $aPos1 = WinGetPos($hCover) Local $sNowPos = $aPos1[0] & "," & $aPos1[1] Local $sNewPos = $aNewPos[0] & "," & $aNewPos[1] Local $sCoverPos = $aCoverPos[0] & "," & $aCoverPos[1] If $sNowPos = $sNewPos And $sNowPos <> $sCoverPos Then $aCoverPos = $aPos1 EndIf EndFunc ;==> _SaveCoverPos Func _SaveVideoPos() ; Save position of $hVideoGUI after 1 second of position change, if it stays the same AdlibUnRegister("_SaveVideoPos") Local $aPos1 = WinGetPos($hVideoGUI) If Not IsArray($aPos1) Then Return If $aPos1[2] > $iClientWidth Then Return Local $sNowPos = $aPos1[0] & "," & $aPos1[1] & "," & $aPos1[2] & "," & $aPos1[3] Local $sChangedPos = $aNewPos[0] & "," & $aNewPos[1] & "," & $aNewPos[2] & "," & $aNewPos[3] Local $sPrePos = $aVideoPrePos[0] & "," & $aVideoPrePos[1] & "," & $aVideoPrePos[2] & "," & $aVideoPrePos[3] If $sNowPos = $sChangedPos And $sNowPos <> $sPrePos Then $aVideoPrePos = $aPos1 EndIf EndFunc ;==> _SaveVideoPos 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 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 _SetTaskBar($hWnd, $sText) ; Manage task bar thumbnail properties ; https://www.autoitscript.com/forum/topic/212211-solved-setthumbnailtooltip/#comment-1536366 ; Declare the CLSID, IID, and interface description for ITaskbarList3. Local Const $sCLSID_TaskbarList = "{56FDF344-FD6D-11D0-958A-006097C9A090}" Local Const $sIID_ITaskbarList3 = "{ea1afb91-9e28-4b86-90e9-9e9f8a5eefaf}" Local Const $sTagITaskbarList3 = "HrInit hresult();" & _ "AddTab hresult(hwnd);" & _ "DeleteTab hresult(hwnd);" & _ "ActivateTab hresult(hwnd);" & _ "SetActiveAlt hresult(hwnd);" & _ "MarkFullscreenWindow hresult(hwnd;boolean);" & _ "SetProgressValue hresult(hwnd;uint64;uint64);" & _ "SetProgressState hresult(hwnd;int);" & _ "RegisterTab hresult(hwnd;hwnd);" & _ "UnregisterTab hresult(hwnd);" & _ "SetTabOrder hresult(hwnd;hwnd);" & _ "SetTabActive hresult(hwnd;hwnd;dword);" & _ "ThumbBarAddButtons hresult(hwnd;uint;ptr);" & _ "ThumbBarUpdateButtons hresult(hwnd;uint;ptr);" & _ "ThumbBarSetImageList hresult(hwnd;ptr);" & _ "SetOverlayIcon hresult(hwnd;ptr;wstr);" & _ "SetThumbnailTooltip hresult(hwnd;wstr);" & _ "SetThumbnailClip hresult(hwnd;ptr);" ; Create the object. Local $oTB = ObjCreateInterface($sCLSID_TaskbarList, $sIID_ITaskbarList3, $sTagITaskbarList3) ; Initialize the iTaskbarList3 object. $oTB.HrInit() If $hWnd = $hMain Then $oTB.SetThumbnailTooltip($hWnd, $sText) ; Taskbar thumbnail tooltip ElseIf $sText = "Delete Tab" Then $oTB.DeleteTab($hWnd) ; Help, Playlist and File Properties windows will not have taskbar icons EndIf EndFunc ;==> _SetTaskBar Func _Shuffle() ; Shuffle or sort playlist GUICtrlSetState($idPlay, $GUI_FOCUS) ; Prevent dotted frames in $hMain buttons If $iAllDone < 1 Then Return HotKeySet("^!s") If $iCD = 1 Or $iFolderLoaded = 0 Then If $iShuffled = 1 Then _ArraySort($aFiles, 0, 2) $iShuffled = 0 Else _ArrayShuffle($aFiles, 2) $iShuffled = 1 EndIf Else Local $hFile, $sList, $aFiles2 If $iShuffled = 0 Then $iShuffled = 1 $sList = $sFolder & "zPlaylist-Shuffled.txt" If FileExists($sList) Then _FileReadToArray($sList, $aFiles2, 1+4, ":|") EndIf If IsArray($aFiles2) Then $aFiles2[1][0] = $aFiles[1][0] Else $aFiles2 = $aFiles _ArrayShuffle($aFiles2, 2) EndIf $hFile = FileOpen($sList, 2+32) _FileWriteFromArray($hFile, $aFiles2, 1, Default, ":|") FileClose($hFile) Else $iShuffled = 0 $sList = $sFolder & "zPlaylist.txt" If FileExists($sList) Then _FileReadToArray($sList, $aFiles2, 1+4, ":|") EndIf If IsArray($aFiles2) Then $aFiles2[1][0] = $aFiles[1][0] Else $aFiles2 = $aFiles _ArraySort($aFiles2, 0, 2) EndIf $hFile = FileOpen($sList, 2+32) _FileWriteFromArray($hFile, $aFiles2, 1, Default, ":|") FileClose($hFile) EndIf $aFiles = $aFiles2 EndIf _PlaylistLoad_1() $iIndex = _GetIndexByFileName($sCurrentFile) _PlaylistLoad_2() While _IsPressed("53", $hUser32DLL) Sleep(10) WEnd HotKeySet("^!s", _Shuffle) EndFunc ;==> _Shuffle Func _Slider($hWnd) ; Drag and drop the progrss bar or click anywhere on the slider to jump to a new media position AdlibUnRegister("_ProgressBar") Local $aPos1 = WinGetPos($hWnd), $x, $x2, $iBorderWidth, $mediaPos If $hWnd = $hMain Then $iBorderWidth = 3 EndIf While _IsPressed("01", $hUser32DLL) = 1 ; Left mouse button If $hWnd = $hMain Then $x = MouseGetPos(0)-($aPos1[0]+$iBorderWidth+$iSliderPosX+$iProgBarWidth/2) ; Mouse position relative to slider position If $x > $iSliderLength Then ; Effective slider length = actual length - progress bar width $x = $iSliderLength ElseIf $x < 0 Then $x = 0 EndIf GUICtrlSetPos($idProgBar, $x+$iSliderPosX) GUICtrlSetPos($idProgBar2, $x/$iSliderLength*$iSliderLength2) $mediaPos = _Min(Int($x/$iSliderLength*$iMediaLength), $iMediaLength-$iTrimTime) ; otherwide, next file may be skipped ElseIf $hWnd = $hVCGui Then $x2 = MouseGetPos(0)-($aPos1[0]+$iProgBarWidth/2) If $x2 > $iSliderLength2 Then $x2 = $iSliderLength2 ElseIf $x2 < 0 Then $x2 = 0 EndIf GUICtrlSetPos($idProgBar2, $x2) GUICtrlSetPos($idProgBar, $x2/$iSliderLength2*$iSliderLength+$iSliderPosX) $mediaPos = _Min(Int($x2/$iSliderLength2*$iMediaLength), $iMediaLength-$iTrimTime) ; otherwide, next file may be skipped EndIf Local $tSeconds = Int($mediaPos/1000) Local $iMinutes = Int($tSeconds/60) Local $iSeconds = StringFormat("%02i", $tSeconds-$iMinutes*60) GUICtrlSetData($idCurrentPos, $iMinutes & ":" & $iSeconds) If $iMinutes > 59 Then Local $iHours = Int($iMinutes/60) $iMinutes = StringFormat("%02i", $iMinutes-$iHours*60) GUICtrlSetData($idCurrentPos2, $iHours & ":" & $iMinutes & ":" & $iSeconds) Else GUICtrlSetData($idCurrentPos2, $iMinutes & ":" & $iSeconds) EndIf Sleep(1) WEnd $iPlaying = 0 If StringInStr($sMciFileTypes, _GetFileExtension($sCurrentFile)) Then mciSendString("stop myMedia") If $mediaPos < 50 Then $mediaPos = 50 ; Skip beginning noise If $iTrack > 0 Then mciSendString("seek myMedia to " & $iTrackPos+$mediaPos) Else mciSendString("seek myMedia to " & $mediaPos) EndIf mciSendString("play myMedia") Else _MPV_SendCommand('{"command": ["seek", ' & $mediaPos/1000 & ', "absolute"]}') EndIf GUICtrlSetData($idPlay, "❚❚") GUICtrlSetData($idPlay2, "❚❚") $iPaused = 0 $iPlaying = 1 AdlibRegister("_ProgressBar", 250) EndFunc ;==> _Slider Func _SpeedDown() ; Decrease play speed by 0.1x _MPV_SendCommand('{"command": ["osd-msg-bar", "add", "speed", -0.1]}') EndFunc ;==> _SpeedDown Func _SpeedRevert() ; Revert play speed to default 1.0x _MPV_SendCommand('{"command": ["set_property", "speed", 1.0]}') _MPV_SendCommand('{"command": ["show-text", "Normal Speed", 2000]}') EndFunc ;==> _SpeedRevert Func _SpeedUp() ; Increase play speed by 0.1x _MPV_SendCommand('{"command": ["osd-msg-bar", "add", "speed", 0.1]}') EndFunc ;==> _SpeedUp Func _SwitchToTrack($iTargetIdx) Local $sCurrentExt = _GetFileExtension($sCurrentFile) If StringInStr($sMpvFileTypes, $sCurrentExt) Then _MPV_SendCommand('{"command": ["stop"]}') Else If $sCurrentExt = "cda" Then mciSendString("stop myMedia") Else mciSendString("close myMedia") EndIf EndIf Local $iNoFiles = 0 While 1 Local $sNextFile = $aFiles[$iTargetIdx][0] If Not StringInStr($sNextFile, ":\") Then $sNextFile = $sFolder & $aFiles[$iTargetIdx][0] EndIf If FileExists($sNextFile) Then ExitLoop Else $iNoFiles += 1 $iTargetIdx += 1 If $iTargetIdx > $aFiles[0][0] Then $iTargetIdx = 2 If $iNoFiles >= $aFiles[0][0] Then Local $sMsg = "None of the items in the playlist are valid." & @CRLF & _ "Please delete the playlists and restart this program." MsgBox($MB_OK+$MB_ICONWARNING, "No File", $sMsg) _Exit() EndIf EndIf WEnd Local $sNextExt = _GetFileExtension($sNextFile) $iIndex = $iTargetIdx $sPath = $sNextFile $sCurrentFile = $aFiles[$iIndex][0] If StringInStr($sVideoTypes, $sNextExt) = 0 Then GUISetState(@SW_HIDE, $hVideoGUI) GUISetState(@SW_HIDE, $hVCGui) EndIf AdlibUnRegister("_Marquee") ControlMove($hChildGUI, "", $idTitle, 0, 0) GUICtrlSetData($idTitle, $aFiles[$iTargetIdx][0]) GUICtrlSetData($idCurrentPos, "00:00") GUICtrlSetData($idLength, "00:00") If StringInStr($sMciFileTypes, $sNextExt) Then If $sNextExt <> "cda" Then If $bFirstMidiFile Then $bFirstMidiFile = False GUICtrlSetData($idTitle, StringFormat("%17s", "") & "Initializing MIDI Synthesizer...") EndIf $iRet = mciSendString("open """ & $sPath & """ alias myMedia type Sequencer wait") If $iRet <> 0 Then If $iPlayPrevious = 0 Then Return _PlayNext() Else Return _PlayPrevious() EndIf EndIf While Not mciSendString("status myMedia ready") Sleep(10) WEnd EndIf $isVideo = False $isAudio = True $bHasAlbumArt = False _Play() Sleep(10) Else _MPV_LoadFile($sNextFile) ; _Play() will be called by _MPV_ParseResponse() EndIf EndFunc ;==> _SwitchToTrack Func _Unload() ; Partial initialization triggered by 'Load Folder' button AdlibUnRegister("_GetLength") AdlibUnRegister("_Marquee") AdlibUnRegister("_ProgressBar") $iAllDone = -1 $iDoing = 0 $iPlaying = 0 $iPaused = 0 $isAudio = False $isVideo = False $bHasAlbumArt = False $iShuffled = 0 If $iMute = 1 Then _Mute() _RepeatFilesCancel("_Unload") GUISetState(@SW_HIDE, $hRepeatAB) GUISetState(@SW_HIDE, $hRepeatFiles) If $iRepeatAB = 1 Then _RepeatABCancel(1) EndIf If $iRepeatCurrentFile = 1 Then $iRepeatCurrentFile = 0 GUICtrlSetData($idRepeat, "U") ; No repeat GUICtrlSetData($idRepeat2, "U") EndIf mciSendString("close myMedia") _MPV_SendCommand('{"command": ["stop"]}') ControlMove($hChildGUI, "", $idTitle, 0, 0) GUICtrlSetData($idTitle, "Media title") GUICtrlSetData($idCurrentPos, "00:00") GUICtrlSetData($idLength, "00:00") GUICtrlSetPos($idProgBar, $iSliderPosX) GUISetState(@SW_HIDE, $hPlaylist) $aFiles = 0 GUISetState(@SW_HIDE, $hVideoGUI) GUISetState(@SW_HIDE, $hVCGui) EndFunc ;==> _Unload Func _VCCreate() ; Create $hVCGui as a child of $hVideoGUI $iVCLeft = ($iClientWidth-$iVideoWidth)/2 $iVCTop = ($iClientHeight-$iVideoWidth)/2 $hVCGui = GUICreate("", $iVideoWidth, $iVCHeight, $iVCLeft, $iVCTop, $WS_POPUP, BitOR($WS_EX_MDICHILD, $WS_EX_TOOLWINDOW, $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, 5, 10, 14) ; 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:00", 10, 23, 60, 15, $SS_RIGHT) GUICtrlSetFont(-1, 10, 600) GUICtrlSetResizing(-1, $GUI_DOCKLEFT+$GUI_DOCKSIZE) $idLength2 = GUICtrlCreateLabel("00: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, "Move video window to default position") Local $iTransColor, $iAlpha _WinAPI_GetLayeredWindowAttributes($hVCGui, $iTransColor, $iAlpha) WinSetTrans($hVCGui, "", 180) GUISetState(@SW_HIDE, $hVCGui) EndFunc ;==> _VCCreate Func _VCResize() ; Resize video control, called by _VideoResize(), _FullScreen() and WM_MOVE() $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 $iW = $iClientWidth $iX = 0 If $iMaximized = 1 Then $iY = $iClientHeight - $iVCHeight ElseIf $iFullScreen = 1 Then $iY = @DesktopHeight - $iVCHeight EndIf 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 control when mouse pointer enters the lower side of video window, 500ms 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 ;==> _VCShow Func _VideoClicked() ; Single click on video image to pause or play the video, double-click to turn full screen on or off If MouseGetPos(1) > $iVCBottom + 70 Then Return ; $iVCBottom is defined in _VCResize() Local $tPoint = _WinAPI_GetMousePos() If WinGetHandle(_WinAPI_WindowFromPoint($tPoint)) = $hVideoGUI Then Local $doubleclicked Local $doubleclickTime = DllCall($hUser32DLL, 'uint', 'GetDoubleClickTime')[0] Local $hTimer = TimerInit() While _IsPressed("01", $hUser32DLL) Sleep(10) If TimerDiff($hTimer) > $doubleclickTime Then ExitLoop WEnd While TimerDiff($hTimer) <= $doubleclickTime If _IsPressed("01", $hUser32DLL) Then $doubleclicked = 1 ExitLoop EndIf Sleep(10) WEnd If $doubleclicked Then _FullScreen() Else _Pause() EndIf While _IsPressed("01", $hUser32DLL) Sleep(10) WEnd EndIf EndFunc ;==> _VideoClicked Func _VideoResize() ; Resize $hVideoGUI except when the window is in maximized or fullsreen mode If $sKeepAspect = "Yes" Then Local $iWidth, $iHeight, $x, $y, $w, $h Local $aPos1 = WinGetPos($hVideoGUI) $x = $aPos1[0] $y = $aPos1[1] $iWidth = $aPos1[2] - $iBorderWidth * 2 $iHeight = Round($iWidth/16*9) $w = $iWidth+$iBorderWidth*2 $h = $iHeight+$iTitleHeight+$iBorderWidth WinMove($hVideoGUI, "", $x, $y, $w, $h) EndIf _VCResize() EndFunc ;==> _VideoResize Func _VolumeDown() ; Decrease audio volune by 10 percentage points (Click β–Ό icon on graphical control or press Ctrl+Alt+down arrow) If $iMute = 1 Then _Mute() $iVolume -= 5 $iVolume = _Max($iVolume, 0) _VolumeSet($iVolume) _VolumeShow() Sleep(50) EndFunc ;==> _VolumeDown Func _VolumeFadeIn() ; Adlib to simulate audio fade-in, S-Curve increase of volume in 15 steps at 100ms interval Local Const $iTotalSteps = 15 $iFadeStep += 1 Local $fProgress = $iFadeStep / $iTotalSteps Local $fCurve = $fProgress ^ 2 Local $iCurrentVol = Int($iVolume * $fCurve) _VolumeSet($iCurrentVol) If $iFadeStep >= $iTotalSteps Then AdlibUnRegister("_VolumeFadeIn") _VolumeSet($iVolume) EndIf EndFunc ;==> _VolumeFadein Func _VolumeGet() ; Gets the volume, 0 ~ 100 Local $aRet = DllCall($hWinmmDLL, "int", "waveOutGetVolume", "ptr", 0, "DWORD*", 0) Local $nVolume _Audio_Action("GetVolume", $nVolume, $hMPV_Process) ConsoleWrite(_Audio_Action("GetVolume", $nVolume, $hMPV_Process) & @CRLF) Return Int($aRet[2]/655.35) EndFunc ;==> _VolumeGet Func _VolumeSet($volume) ; Sets the volume, 0 ~ 100 _Audio_Action("SetVolume", $volume/100, $hMPV_Process) _Audio_Action("SetVolume", $volume/100, @AutoItPID) EndFunc ;==> _VolumeSet Func _VolumeShow() ; Show current volume GUICtrlSetData($idVolume, $iVolume) GUICtrlSetData($idVolume2, $iVolume) GUICtrlSetState($idVolume, $GUI_SHOW) GUICtrlSetState($idVolume2, $GUI_SHOW) Sleep(200) GUICtrlSetState($idVolume, $GUI_HIDE) GUICtrlSetState($idVolume2, $GUI_HIDE) GUICtrlSetTip($idUp, $iVolume) GUICtrlSetTip($idUp2, $iVolume) GUICtrlSetTip($idDown, $iVolume) GUICtrlSetTip($idDown2, $iVolume) EndFunc ;==> _VolumeShow Func _VolumeUp() ; Increase audio volume by 10 percentage points (Click β–² icon on graphical control or press Ctrl+Alt+up arrow) If $iMute = 1 Then _Mute() $iVolume += 5 $iVolume = _Min($iVolume, 100) _VolumeSet($iVolume) _VolumeShow() Sleep(50) EndFunc ;==> _VolumeUp Func _WinDefaultPos() ; Triggered by Ctrl+Alt+W, bring up all open GUIs to foreground and move them to their default positions HotKeySet("^!w") GUISetState(@SW_RESTORE, $hMain) WinMove($hCover, "", $iMainBorderWidth, 0) Local $aPos1 = WinGetPos($hMain) Local $x, $y, $w, $h If $hHelp <> "" Then $aPos1 = WinGetPos($hHelp) WinMove($hHelp, "", (@DesktopWidth-$aPos1[2])/2, 0) EndIf If $iPlaylist = 1 Then $x = (@DesktopWidth-$iListWidth)/2-$iBorderWidth WinMove($hPlaylist, "", $x, 0, $iListWidth+$iBorderWidth*2, $iListHeight+$iTitleHeight+$iBorderWidth) $aPos1= WinGetPos($hPlaylist) GUICtrlSetPos($ctrlView, 0, 0, $aPos1[2]-$iBorderWidth*2+2, $aPos1[3]-$iTitleHeight-$iBorderWidth-35) ; +2 eliminates right-side black borderline _GUICtrlListView_SetColumnWidth($ctrlView, 0, $iColumn1Width) _GUICtrlListView_SetColumnWidth($ctrlView, 1, $iListWidth-$iColumn1Width-60-21) ; -21 eliminates horizontal scroll bar _GUICtrlListView_SetColumnWidth($ctrlView, 2, 60) WinActivate($hPlaylist) _PlaylistHighlight($iIndex, 1) EndIf If $iProperties = 1 Then $x = (@DesktopWidth-$iPropertyWidth)/2-$iBorderWidth $y = (@DesktopHeight-$iPropertyHeight-$iTitleHeight-$iBorderWidth)/2 $w = $iPropertyWidth+$iBorderWidth*2 $h = $iPropertyHeight+$iTitleHeight+$iBorderWidth WinMove($hProperties, "", $x, $y, $w, $h) _GUICtrlListView_SetColumnWidth($idPropertiesView, 1, $iPropertyWidth-$iNameColWidth-15) EndIf If $isVideo Then If $iFullScreen = 1 Then _FullScreen() EndIf $iMaximized = 0 GUISetState(@SW_RESTORE, $hVideoGUI) WinMove($hVideoGUI, "", $aVideoDefPos[0], $aVideoDefPos[1], $aVideoDefPos[2], $aVideoDefPos[3]) _VCResize() Else GUISetState(@SW_HIDE, $hVideoGUI) EndIf If $iOptions = 1 Then WinMove($hOptions, "", (@DesktopWidth-606)/2, 0) WinActivate($hOptions) EndIf If $iProperties = 1 Then WinActivate($hProperties) EndIf While _IsPressed("57", $hUser32DLL) Sleep(10) WEnd HotKeySet("^!w", _WinDefaultPos) EndFunc ;==> _WinDefaultPos 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 Local $str = StringStripWS(StringLower(StringReplace($string, '"', " ")), 3) $str = StringLeft($string, StringInStr($string, " ")-1) If StringInStr("open, play, stop, close, pause, resume", $str) Then Return $aRet[0] Else Return $aRet[2] EndIf EndIf EndFunc ;==> mciSendString Func WM_MOVE($hWnd, $MsgID, $wParam, $lParam) ; Move $hRepeatAB/$hRepeatFiles to new position when $hMainehfvnd cnlth moves #forceref $hWnd, $MsgID, $wParam, $lParam If $hWnd = $hMain Then Local $aPos1 = WinGetPos($hMain) If $iRepeatABWin = 1 Then If $aPos1[0] < $iRepeatABWidth Then WinMove($hRepeatAB, "", $aPos1[0]+$iMainGuiWidth+$iMainBorderWidth, $aPos1[1]+1) Else WinMove($hRepeatAB, "", $aPos1[0]-$iRepeatABWidth, $aPos1[1]+1) EndIf ElseIf $iRepeatFilesWin = 1 Then If $aPos1[0]+$iMainGuiWidth+$iRepeatABWidth+$iMainBorderWidth <= $iClientWidth Then WinMove($hRepeatFiles, "", $aPos1[0]+$iMainGuiWidth+$iMainBorderWidth, $aPos1[1]+1) Else WinMove($hRepeatFiles, "", $aPos1[0]-$iRepeatABWidth, $aPos1[1]+1) EndIf EndIf EndIf Return $GUI_RUNDEFMSG EndFunc ;==> WM_MOVE Func WM_NOTIFY($hWnd, $MsgID, $wParam, $lParam) ; Detect mouse click on a playlist item #forceref $MsgID, $wParam Local $tNMHDR, $iCode $tNMHDR = DllStructCreate( $tagNMHDR, $lParam ) $iCode = DllStructGetData( $tNMHDR, "Code" ) Local $hWndFrom = DllStructGetData($tNMHDR, "hWndFrom") $tNMHDR = 0 If $hWnd = $hPlaylist And $wParam = $ctrlView Then ;Return $GUI_RUNDEFMSG Switch $iCode Case $NM_DBLCLK If _GUICtrlListView_GetSelectedIndices($ctrlView) = "" Then _PlaylistHighlight($iIndex, 1) Else $iDoubleClicked = 1 EndIf Case $NM_RCLICK If _GUICtrlListView_GetSelectedIndices($ctrlView) = "" Then _PlaylistHighlight($iIndex, 1) Else ConsoleWrite("contextmenu" & @CRLF) EndIf Case $NM_CLICK, $NM_RDBLCLK If _GUICtrlListView_GetSelectedIndices($ctrlView) = "" Then _PlaylistHighlight($iIndex, 1) EndIf Case $LVN_GETDISPINFOW ; Fill virtual listview. ; https://www.autoitscript.com/forum/topic/168707-listview-item-subitem-background-colour/#comment-1234009 Local $tNMLVDISPINFO = DllStructCreate($tagNMLVDISPINFO, $lParam) If BitAND( DllStructGetData($tNMLVDISPINFO, "Mask"), $LVIF_TEXT) Then Local $sItem = $aItems[DllStructGetData($tNMLVDISPINFO,"Item")][DllStructGetData($tNMLVDISPINFO, "SubItem")] DllStructSetData($tText, 1, $sItem) DllStructSetData($tNMLVDISPINFO, "TextMax", StringLen($sItem)) DllStructSetData($tNMLVDISPINFO, "Text", DllStructGetPtr($tText)) EndIf $tNMLVDISPINFO = 0 Case $NM_CUSTOMDRAW Local $tNMLVCUSTOMDRAW = DllStructCreate($tagNMLVCUSTOMDRAW, $lParam) Local $dwDrawStage = DllStructGetData($tNMLVCUSTOMDRAW, "dwDrawStage") Switch $dwDrawStage ; Holds a value that specifies the drawing stage Case $CDDS_PREPAINT ; Before the paint cycle begins Return $CDRF_NOTIFYITEMDRAW ; Notify the parent window of any item-related drawing operations Case $CDDS_ITEMPREPAINT ; Before painting an item Return $CDRF_NOTIFYSUBITEMDRAW ; Notify the parent window of any subitem-related drawing operations Case BitOR( $CDDS_ITEMPREPAINT, $CDDS_SUBITEM ) ; Before painting a subitem Local $iItem = DllStructGetData($tNMLVCUSTOMDRAW, "dwItemSpec") ; Item index Local $iSubItem = DllStructGetData($tNMLVCUSTOMDRAW, "iSubItem") ; Subitem index DllStructSetData($tNMLVCUSTOMDRAW, "ClrTextBk", $aColors[$iItem][$iSubItem]) ; Backcolor of item/subitem Return $CDRF_NEWFONT ; $CDRF_NEWFONT must be returned after changing font or colors EndSwitch $tNMLVCUSTOMDRAW = 0 EndSwitch ElseIf $hWnd = $hProperties And $wParam = $idPropertiesView And $iCode = $NM_DBLCLK Then Local $aValue = _GUICtrlListView_GetSelectedIndices($idPropertiesView, True) If $aValue[0] = 0 Then ClipPut("") Return EndIf Local $value = $aFileInfo[$aValue[1]][1] ClipPut($value) If $value <> "" Then MsgBox(0, "Copied to clipboard", $value, 3) ElseIf $hWndFrom = $helpEdit And $iCode = $EN_LINK Then Local $tENLINK = DllStructCreate("hwnd hwndFrom;UINT_PTR idFrom;UINT code;UINT msg;WPARAM wParam;LPARAM lParam;LONG cpMin;LONG cpMax", $lParam) Local $iMsgLink = DllStructGetData($tENLINK, "msg") If $iMsgLink = $WM_LBUTTONDOWN Then Local $iMin = DllStructGetData($tENLINK, "cpMin") Local $iMax = DllStructGetData($tENLINK, "cpMax") Local $sClickedText = _GUICtrlRichEdit_GetTextInRange($helpEdit, $iMin, $iMax) If $sClickedText = "sourceforge.net" Then ShellExecute("https://sourceforge.net/projects/mpv-player-windows/files/64bit/") EndIf EndIf EndIf Return $GUI_RUNDEFMSG EndFunc ;==> WM_NOTIFY Func WM_WINDOWPOSCHANGED($hWnd, $MsgID, $wParam, $lParam) ; Sync movement of $hMain and $hCover #forceref $hWnd, $MsgID, $wParam, $lParam If $hWnd = $hCover Then Local $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]) $aNewPos = $aPos1 AdlibRegister("_SaveCoverPos", 1000) ElseIf $hWnd = $hVideoGUI Then _VCResize() $aNewPos = WinGetPos($hVideoGUI) AdlibRegister("_SaveVideoPos", 1000) EndIf Return $GUI_RUNDEFMSG EndFunc ;==> WM_WINDOWPOSCHANGED Func zPlayerHelp() ; Create Help window with RichEdit control Local $sText = "β–Ά/❚❚" & @LF & _ ; This increases the font weight of the entire text to an optimum level "Welcome to zPlayer!" & @LF & @LF & _ "zPlayer is a lightweight, dual-engine media player featuring a minimalist GUI and zero-installation design. " & _ "To unlock its full potential, including seamless 4K video playback, it utilizes mpv.exe, which can be securely " & _ "downloaded from the sourceforge.net. Leveraging standard AutoIt UDFs and native Windows components, zPlayer " & _ "delivers a completely standalone experience with no other third-party dependencies." & @LF & @LF & _ "It has the following features:" & @LF & @LF & _ "Click Press Function " & @LF & _ "Load Files Load file(s) or CD tracks into playlist and start playing" & @LF & _ "Load Folder Ctrl+Alt+C Load a folder or CD into playlist and start playing" & @LF & _ "Media title Ctrl+Alt+L Open/Close playlist window" & @LF & _ "Shuffle/Sort Ctrl+Alt+S Load a shuffled or sorted playlist" & @LF & _ "Progress bar Click and drag the progress bar to change playback position" & @LF & _ "Current media position Set A-B repeat positions" & @LF & _ "Total media length Set multi-file repeat function" & @LF & _ "β–Ά/❚❚ Ctrl+Alt+P Play/Pause (single-click on video image has the same effect)" & @LF & _ "β—€ Ctrl+Alt+Left Play previous file" & @LF & _ "U/O Ctrl+Alt+R Repeat/Unrepeat current file" & @LF & _ "β–Ά Ctrl+Alt+Right Play next file" & @LF & _ "πŸ”Š/πŸ”‡ Ctrl+Alt+M Toggle audio on/off" & @LF & _ "β–²/β–Ό Ctrl+Alt+Up/Down Increase/decrease volume by 10% points" & @LF & _ "? Ctrl+Alt+H Open/Close Help window" & @LF & _ "⇔/⇙ F11/Esc Full screen on/off (double-click on video image has the same effect)" & @LF & _ "βœ… Move video window to deault size and position" & @LF & _ "βš™ Ctrl+Alt+O Open/Close options window" & @LF & _ "πŸ”/πŸ”™ Ctrl+Alt+T Bring the main GUI to foregound + Toggle its top window state" & @LF & _ " Ctrl+Alt+I Internet search result on the current file" & @LF & _ " Ctrl+Alt+F Open/Close file properties of the current file" & @LF & _ " Ctrl+Alt+V Execute an AutoIt expression" & @LF & _ " Ctrl+Alt+W Move all GUIs to their default positions and bring them to the front" & @LF & _ " Ctrl+Alt+Z Minimize/Restore a full screen video window" & @LF & _ " Ctrl+Alt+[ Or ] [Ctrl+Alt+Left/Right Bracket] Speed down/up by 10% points" & @LF & _ " Ctrl+Alt+Backspace Revert speed to normal" & @LF & _ " Ctrl+Left/Right Jump playback 5 seconds backward/forward (Add Shift key to make it 30)" & @LF & _ " s (on video) Capture the screen and save it as a .jpg file in the script directory" & @LF & _ ' a (on video) Set "Keep Aspect" feature on or off for video' & @LF & _ "🞭 Ctrl+Alt+End Exit the program" & @LF & @LF & _ "Initialization and Playback Settings" & @LF & _ "When this program is run, it looks for the zPlayer.ini file in the script directory. This file stores the last session's playback settings, such as the folder and playlist loaded, the play mode (shuffled or sorted), the volume, the position of the main window and its 'Always On Top' attribute, and the 'resume playback' options in effect at the time the program was terminated. If the file exists, zPlayer will resume these playback settings and start playing the saved playlist immediately." & @LF & @LF & _ "Loading Files and Playlists" & @LF & _ "If the zPlayer.ini file does not exist in the script directory, or if the folder stored in zPlayer.ini does not have a playlist file (zPlaylist.txt), the program will wait for you to select files or a folder to load into the playlist. You can do this by clicking one of the two Load buttons: β€˜Load Files’ will load one or more files in a folder, and β€˜Load Folder’ will load all files in a folder. When you load a folder, you have the option to include or exclude files from the sub-folders in the playlist. This option is available only if the folder has media files in both top-level and sub-level folders and there is no existing playlist in the top-level folder. Upon loading the files or a folder, the program will immediately start playing the playlist. If the β€˜Shuffle’ button is clicked at any time thereafter, the playlist will be shuffled to a random order." & @LF & @LF & _ "Media Length Calculation" & @LF & _ "When you load a folder for the first time, zPlayer calculates media lengths in the background and fills the Length column of the playlist. During this time, the media will continue to play, but shuffling or sorting the playlist, loading files or folders, and rescanning will be disabled, and the media title will be displayed in red. This process will take approximately 15 seconds for a folder containing 500 media files." & @LF & @LF & _ "Continuous Playback and Playlist Management" & @LF & _ "zPlayer will endlessly loop through the playlist unless you change the folder or exit the program. If a folder was loaded, the playlist will be saved in that folder just before zPlayer leaves the folder. zPlaylist.txt stores the sorted playlist and zPlaylist-Shuffled.txt saves the shuffled playlist. The first line of these playlists contains the file name last played, the playing mode, and any options for resuming playback. You can switch between the sorted and shuffled playlists by clicking the Shuffle/Sort button or pressing the Ctrl+Alt+S. For an audio CD, the playlist and playback environment are not saved." & @LF & @LF & _ "Custom Playlists" & @LF & _ "You can create a custom playlist by following these simple steps. It may be saved in any folder, but it is a good idea to save it in an empty one. Afterwards, you can load this folder the same way you would load others with media files." & @LF & _ " β€’ Click the β€˜Load Files’ button located in the main window." & @LF & _ " β€’ Select one or more of your favourite files from a folder and load them." & @LF & _ " β€’ While your files are playing, go to the playlist window." & @LF & _ " β€’ Click the β€˜Save List’ button." & @LF & _ " β€’ You will be prompted for the full path to the folder where you want to save the playlist." & @LF & _ " β€’ If the folder does not exist, it will be created." & @LF & _ " β€’ If the folder does exist, the playlist will be overwritten." & @LF & _ " β€’ If you click the 'OK' button, the playlist files will be created in that folder." & @LF & _ " β€’ Click the β€˜Add Files’ button in the playlist window to add files from other folders." & @LF & @LF & _ "Display and Control" & @LF & _ "The current file name is displayed in the media title control of the main window. If the file name is longer than the display control width, the file name will scroll in a marquee style." & @LF & @LF & _ "Playlist Window Features" & @LF & _ "The playlist window is hidden by default. You can display it by clicking on the media title control or pressing Ctrl+Alt+L. In the playlist window, you can search for strings, rescan the folder, or reorder the shuffled playlist. The β€˜Rescan’ button transforms to β€˜Save List’ button if files were loaded instead of a folder. Double-clicking an item in the playlist will play that item. Right-clicking on any item brings up a context menu: available menus are 'Play This File', 'File Properties', 'Internet Search', 'Go to This Folder', 'Move This Item', and 'Remove from Playlist'. CD tracks do not contain metadata by design, so file properties are not relevant to them. The file properties of the current file can also be viewed by pressing Ctrl+Alt+F." & @LF & @LF & _ "Setting Options" & @LF & _ "If you click the gear icon (βš™) in the title bar of the main window, or press Ctrl+Alt+O, a settings window entitled 'Options' will appear. The options currently available are:" & @LF & _ "Set playback resume criteria: You can set options for resuming playback from the last playback position. If you leave a folder in the middle of a file, these options will be saved and resumed when you return to that folder." & @LF & _ "Set media file types: The file types you want to include in the playlist can be added or deleted here. If you make any changes, they will take effect when you rescan the folder in the Playlist window" & @LF & _ "Set color scheme: You can change the colors of the main window, including the color of the title bar. Currently available color schemes are Lavender, Ocean Blue, Mint Green and the Windows Default color." & @LF & _ "Set keep-aspect on/off: You can set keep-aspect property of video image on or off." & @LF & _ "Set audio equalizer mode: You can select one of six audio eaualizer modes." & @LF & @lf & _ "Video Playback" & @LF & _ "When a video file is opened for playback, a separate video window is opened and initially positioned in the center of the desktop screen, with a default width of approximately 2/3 of the desktop width and 16:9 aspect. The video window can be moved or resized during playback, and the size of the window is automatically adjusted to maintain the 16:9 aspect ratio. When you move the mouse to the bottom of the video window, a graphical control appears at the bottom of the video. You can toggle full-screen mode on and off by clicking the ⇔/⇙ icon in the graphical control panel, double-clicking the video image, or pressing the F11 key when the center of the video is visible. Once the video is maximized, turned into full screen, or moved and resized, zPlayer will play subsequent files at that size and position. When the video is playing in full screen, the Minimize button is not visible. Ctrl+Alt+Z can be useful to minimize a full-screen video and restore it to full screen. You can use hotkeys to bring up any other helper window, such as the playlist, even when the video is playing in full screen." & @LF & _ "mpv.exe enables zPlayer to play 4K videos and introduces seamless, gapless transitions between media files." & @LF & _ " β€’ [S] Key : Capture screen and save as .jpg in script directory" & @CRLF & _ " β€’ [A] Key : Toggle keep-aspect ratio property" & @LF & @LF & _ "Playback Controls" & @LF & _ "Playback can be paused and resumed by clicking the Play (β–Ά)/Pause (❚❚) icon, pressing Ctrl+Alt+P, or clicking on the video image. You can move to the previous file or to the next file by clicking the left or right side of the β—€Uβ–Ά icon or pressing Ctrl+Alt+Left or Right arrow." & @LF & @LF & _ "Repeat Functions" & @LF & _ "zPlayer offers three levels of repeat functions: A-B repeat, current file repeat and multi-file repeat. If you want to repeat a specific part of the current file, click the current media position label (located to the left of the slider), and set the start and end positions in seconds or mm:ss format. When set, the corresponding part of the slider will turn pink. Clicking the center of the β—€Uβ–Ά icon changes the letter U to 0, and repeats the current file until you click it back to U or select another file to play. This function can also be performed by pressing Ctrl+Alt+R. If you want to repeat multiple files from a large playlist, you can click the total media length label (located to the right of the slider), and set the files to repeat. When set, the playlist will reload with the corresponding items displayed on a pink background. While this function is active, shuffle, sort and rescan functions are disabled for obvious reasons. If a larger scale repeat is activated while a smaller scale repeat is in effect, the smaller scale repeat will be cancelled. However, the smaller scale repeat can be activated while the larger scale repeat is in effect." & @LF & @LF & _ "Volume Control" & @LF & _ "The program audio volume can be increased or decreased by clicking the β–² or β–Ό icon or by pressing Ctrl+Alt+Up or Down arrow. The volume will be adjusted by 5 percentage points per click, with the result displayed in a tooltip near the icon. The sound can be muted or unmuted by clicking the πŸ”Š/πŸ”‡ icon or pressing Ctrl+Alt+M. If the master volume of your audio device happens to be muted when zPlayer starts, zPlayer will automatically unmute the master volume." & @LF & @LF & _ "Hotkeys and Screen Rotation" & @LF & _ "If your computer has an Intel CPU and Intel HD Graphics Control Panel, Windows uses the Ctrl+Alt+Arrow hotkeys to rotate the screen. You can either disable the screen rotation hotkeys in PC Settings, or use alternative hotkey combinations that replace the arrows with the following keys: up arrow with the equal (=) key, down arrow with the minus (-) key, left arrow with the comma (,) key, and right arrow with the dot (.) key." & @LF & @LF & _ "Internet Search" & @LF & _ "If you press Ctrl+Alt+I, the result of an internet search on the current file will be displayed." & @LF & @LF & _ "Playback Progress and Jump" & @LF & _ "Playback progress is displayed both graphically and in text. Ctrl+Right/Left moves the playback position forward/backward 5 seconds. Adding the Shift key makes it 30 seconds. For larger jumps, you can click and drag the small rectangular progress bar along the slider, or click anywhere on the slider." & @LF & @LF & _ "Executing AutoIt Expressions" & @LF & _ "Ctrl+Alt+V brings up a small GUI where you can execute a valid AutoIt expression. This is mainly for checking the current value of variables, including arrays. This function may be of help to those who want to tweak this program. Note that AutoIt functions such as _ArrayDelete() and user defined functions such as _Exit() can be executed and may break the flow of the program." & @LF & @LF & _ "Setting Main GUI as Top Window" & @LF & _ "If the main window is not visible for any reason except when the video is playing in full screen, Ctrl+Alt+T will bring it to the foreground. If it is visible, Ctrl+Alt+T or the πŸ”/πŸ”™ icon will toggle its 'Always On Top' attribute." & @LF & @LF & _ "Moving Windows to Default Positions" & @LF & _ "By pressing Ctrl+Alt+W anytime, you can move all GUIs to their default positions and bring them to the front. If you click the check icon (βœ…) in the video window graphical control, only the video window is moved to its default size and position. " & @LF & @LF & _ "Exiting and Resuming Settings" & @LF & _ "You can exit the program by clicking the main GUI Close button, the 🞭 icon on the video control, or by pressing Ctrl+Alt+End. If a folder was loaded at the time of quitting, a zPlayer.ini file is created in the script directory, which stores all the playback environment settings, including the folder name, playback mode (shuffled or sorted), audio volume, etc. zPlayer will use these settings during the next session." & @LF & @LF & _ "File Types Supported" & @LF & _ "Out of the box, mpv.exe supports most popular audio and video formats without requiring any external codecs. Legacy Audio CD tracks and MIDI files are handled natively via the built-in Windows component winmm.dll." & @LF & @LF & _ "Background Instance of zPlayer" & @LF & _ "zPlayer launches a background instance of itself asynchronously via command-line arguments right after startup. This prevents the main UI thread and progress bar from freezing while waiting for Windows to initialize the MIDI synthesizer, which takes about 15 seconds. This lag typically occurs when zPlayer encounters a MIDI file for the first time after system boot. This background instance will exit immediately after initializing the MIDI synthesizer." & @LF & @LF & _ "Compatibility" & @LF & _ "zPlayer has been fully verified and compatible with Windows 10 and 11. For the optimal playback of high-bitrate 4K videos, a system equipped with a hardware GPU is highly recommended." & @LF & @LF & @LF Local $helpWidth = 800, $helpHeight = 760, $a[0][3], $s, $s1, $n1, $n2 $hHelp = GUICreate("The Features and Functions of zPlayer", $helpWidth, $helpHeight, -1, 0, $WS_SYSMENU, -1) GUISetIcon($sIconFile) $helpEdit = _GUICtrlRichEdit_Create($hHelp, "", 15, 0, $helpWidth-30, $helpHeight-45, BitOR($WS_VSCROLL, $ES_MULTILINE, $ES_READONLY), $WS_EX_STATICEDGE) _GUICtrlRichEdit_SetBkColor($helpEdit, 0xF0F0F0) _GUICtrlRichEdit_SetFont($helpEdit, 11, $sFontName, 129) ; 129 is Hangeul character set where β–Ά/❚❚ makes the typeface thicker _GUICtrlRichEdit_AppendText($helpEdit, $sText) _GUICtrlRichEdit_SetSel($helpEdit, 0, 4, True) _GUICtrlRichEdit_SetCharColor($helpEdit, 0xF0F0F0) ; Make β–Ά/❚❚ at the beginning invisible _GUICtrlRichEdit_ChangeFontSize($helpEdit, -7) ; Underline paragraph headings $s = "Welcome to zPlayer!" $n1 = StringInStr($sText, $s)-1 _ArrayAdd($a, $n1 & "|" & $n1+StringLen($s) & "|Welcome to zPlayer!") $s = "Click " $n1 = StringInStr($sText, $s, 1)-1 _ArrayAdd($a, $n1 & "|" & $n1+10 & "|Click") $s = "Press " $n1 = StringInStr($sText, $s, 1)-1 _ArrayAdd($a, $n1 & "|" & $n1+10 & "|Press") $s = "Function " $n1 = StringInStr($sText, $s, 1)-1 _ArrayAdd($a, $n1 & "|" & $n1+20 & "|Function") Local $i = 2 While 1 $i += 1 $n1 = StringInStr($sText, @LF & @LF, 0, $i)+2 If $n1 = 2 Then ExitLoop $s = StringMid($sText, $n1) $n2 = StringInStr($s, @LF, 0, 1)-1 $s1 = StringLeft($s, $n2) $n1 -= 1 $n2 = $n1+$n2 _ArrayAdd($a, $n1 & "|" & $n2 & "|" & $s1) If StringInStr($s1, "Options") Then Local $s3 = StringLeft($s, StringInStr($s, @LF & @LF)-2) $s3 = StringMid($s3, StringInStr($s3, @LF)+1) Local $a1 = StringRegExp($s3, "\n(.*:)", 3) For $j = 0 To UBound($a1)-1 $n1 = StringInStr($sText, $a1[$j])-1 $n2 = $n1 + StringLen($a1[$j]) _ArrayAdd($a, $n1 & "|" & $n2 & "|" & $a1[$j]) Next EndIf WEnd $n1 = _ArraySearch($a, "Playback Controls") For $i = $n1 To UBound($a) -1 $a[$i][0] -= 1 Next ; Set hyperlink For $i = 0 To UBound($a)-1 _GUICtrlRichEdit_SetSel($helpEdit, $a[$i][0], $a[$i][1], True) _GUICtrlRichEdit_SetCharAttributes($helpEdit, "+un") Next $n1 = StringInStr($sText, "βš™") _GUICtrlRichEdit_SetSel($helpEdit, $n1-1, $n1, True) _GUICtrlRichEdit_SetFont($helpEdit, 15, $sFontName, 129) _GUICtrlRichEdit_SetEventMask($helpEdit, $ENM_LINK) Local $sLinkText = "sourceforge.net" Local $iStartPos = StringInStr($sText, $sLinkText) - 1 ; 0-based 인덱슀 If $iStartPos >= 0 Then Local $iEndPos = $iStartPos + StringLen($sLinkText) _GUICtrlRichEdit_SetSel($helpEdit, $iStartPos, $iEndPos) _GUICtrlRichEdit_SetCharColor($helpEdit, 0xFF0000) Local const $CFM_LINK = 0x00000020 Local const $CFE_LINK = 0x00000020 Local const $EM_SETCHARFORMAT = 0x0444 Local const $SCF_SELECTION = 0x0001 Local $tCF = DllStructCreate($tagCHARFORMAT) DllStructSetData($tCF, "cbSize", DllStructGetSize($tCF)) DllStructSetData($tCF, "dwMask", $CFM_LINK) DllStructSetData($tCF, "dwEffects", $CFE_LINK) DllCall("user32.dll", "lresult", "SendMessageW", "hwnd", $helpEdit, "uint", $EM_SETCHARFORMAT, "wparam", $SCF_SELECTION, "lparam", DllStructGetPtr($tCF)) EndIf _GUICtrlRichEdit_SetSel($helpEdit, 0, 0) GUISetState(@SW_SHOW, $hHelp) _SetTaskBar($hHelp, "Delete Tab") EndFunc ;==> zPlayerHelp 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