From 77794d1c22da6378938590e2ed393d5e6dbccc40 Mon Sep 17 00:00:00 2001 From: Yuriy Date: Wed, 31 Jul 2024 04:37:48 -0400 Subject: [PATCH] gui rework, added option to shutdown on all completion, upload each result to ntfy, hide CMD popups --- Whisper-AHK-GUI2.ahk | 740 +++++++++++++++++++++++++++++++++++++++++++ Whisper-AHK.ahk | 417 +++++++++++++----------- 2 files changed, 976 insertions(+), 181 deletions(-) create mode 100644 Whisper-AHK-GUI2.ahk diff --git a/Whisper-AHK-GUI2.ahk b/Whisper-AHK-GUI2.ahk new file mode 100644 index 0000000..7791be1 --- /dev/null +++ b/Whisper-AHK-GUI2.ahk @@ -0,0 +1,740 @@ +; ENVIRONMENT +;------------------------------------------------ +#NoEnv ; Recommended for performance and compatibility with future AutoHotkey releases. +;#Warn ; Enable warnings to assist with detecting common errors. +;DetectHiddenWindows, On +#SingleInstance, Force +SendMode Input ; Recommended for new scripts due to its superior speed and reliability. +SetWorkingDir %A_ScriptDir% ; Ensures a consistent starting directory. +;SetKeyDelay, 500 +CoordMode, ToolTip, Screen +CoordMode, Mouse, Screen +;#NoTrayIcon + +; Notes/Extra Info/#Includes +;------------------------------------------------ + + + +; VARIABLES +;------------------------------------------------ +EnvGet, ProcessorCount, NUMBER_OF_PROCESSORS + + +; FONTS + +HeaderFontSize := 10 +NormalFontSize := 10 + + + +Margin := 10 +gui, Margin, %Margin%, 10 + +ColumnOneXPos := 10 + + +GUIHeight = 400 +ColumnHeaderButtonHeight := 30 +ButtonHeight := 20 + + + +ExecuteButtonYPos := GUIHeight - ButtonHeight + + +ColumnOneHeaderWidth := 250 +ColumnTwoHeaderWidth := 300 +ColumnThreeHeaderWidth := 150 + + + +; ColumnOneHeaderWidth + +ColumnTwoVerticalLineXPos := ColumnOneHeaderWidth + ColumnOneXPos + 10 + +ColumnTwoXPos := ColumnTwoVerticalLineXPos + Margin + +Column_Three_Vertical_line_x_Pos := ColumnTwoXPos + ColumnTwoHeaderWidth + Margin +ColumnThreeXPos := Column_Three_Vertical_line_x_Pos + Margin + +ColumnTwoSubCheckboxesXPos := ColumnTwoXPos + 20 + +ColumnOneWidth := ColumnTwoXPos - ColumnOneXPos - margin + + +; MAIN SCRIPT +;------------------------------------------------ + + +; Column One +;------------------------------------------------ + +Gui, Font, s%HeaderFontSize% +Gui, Font, Bold +Gui, Add, Button, x%ColumnOneXPos% y0 w%ColumnOneHeaderWidth% h%ColumnHeaderButtonHeight%, FILE SELECTION +Gui, font, normal + +; Gui, Add, Text, w%ColumnOneHeaderWidth% center, Select Files to Transcribe +; Gui, font, normal +Gui, Add, Edit, vFilesFilepath gUpdateGUI w%ColumnOneHeaderWidth% +Gui, Add, Button, y+1 gSelectFile w%ColumnOneHeaderWidth%, Select Files to Transcribe +Gui, Add, Checkbox, gUpdateGUI vTranscribeDirectory, Transcribe all files in this folder + + + +Gui, Font, s%HeaderFontSize% +Gui, Font, Bold +Gui, Add, Button, x%ColumnOneXPos% y+50 w%ColumnOneHeaderWidth% h%ColumnHeaderButtonHeight%, TRANSCRIPTION SETTINGS +Gui, font, normal +Gui, Add, Edit, gUpdateGUI w%ColumnOneHeaderWidth%, +Gui, Add, UpDown, vCPUThreads Range1-20, %CPUThreads% +Gui, Add, Text, x%margin% y+%margin% w%ColumnOneHeaderWidth% center, Number of CPU Threads If Using CPU (PC MAX: %ProcessorCount%) ; `nTotal Processors on PC: %ProcessorCount% + + + +gui, add, text, y+20 w%ColumnOneWidth% 0x10 ;Horizontal Line > Etched Gray + +Gui, Font, s%HeaderFontSize% +Gui, Font, Bold +Gui, Add, Button, x%ColumnOneXPos% w%ColumnOneHeaderWidth% h%ColumnHeaderButtonHeight%, MODEL +Gui, Font, Normal +; Gui, Add, Checkbox, vCheckboxColOne, Checkbox + +Gui, Add, Checkbox, vBaseM checked%BaseM%, Base +Gui, Add, Checkbox, vSmallM checked%SmallM%, Small +Gui, Add, Checkbox, vMediumM checked%MediumM%, Medium +Gui, Add, Checkbox, vLargeM checked%LargeM% ,Large +Gui, Add, Checkbox, vAllMQualities, ALL (One by One) + +/* +Gui, Font, Bold +Gui, Add, Button, x%ColumnOneXPos% w%ColumnOneHeaderWidth% h%ColumnHeaderButtonHeight%, LENGTH +Gui, font, normal +Gui, Add, Checkbox, gUpdateGUI vShortPodcasts checked%ShortPodcastsCheckStatus%, Short ( < 30 Mins) +Gui, Add, Checkbox, vMediumPodcasts gUpdateGUI checked%MediumPodcastsCheckStatus%, Medium (30-60 Mins) +Gui, Add, Checkbox, vLongPodcasts gUpdateGUI checked%LongPodcastsCheckStatus%, Long ( > 60 Mins) +Gui, Add, Checkbox, vAnyLengthMediaFile gUpdateGUI checked%AnyLengthMediaFileCheckStatus%, ANY Length + +*/ + + +; Column Two +;------------------------------------------------ +Gui, Font, s%HeaderFontSize% +Gui, Font, Bold +gui, add, text, x%ColumnTwoVerticalLineXPos% y0 h%GUIHeight% 0x11 ;Vertical Line > Etched Gray +Gui, Add, Button, x%ColumnTwoXPos% y0 w%ColumnTwoHeaderWidth% h%ColumnHeaderButtonHeight%, Settings + +Gui, Font, Normal +Gui, Add, Checkbox, vKeepCMD, Keep CMD Open After Model Completion +Gui, Add, Checkbox, vShowTooltip checked%ShowTooltip%, Show Tooltip of Progress at Top of Screen +Gui, Add, Checkbox, vNTFYPost checked%NTFYURLCheckStatus%, NTFY After Each Transcription +Gui, Add, Checkbox, vNTFYUpload checked%NTFYUploadCheckStatus%, Upload Transcript to NTFY +Gui, Add, Checkbox, vContinueAfterCMDClose checked%ContinueAfterCMDCloseCheckStatus%, Start After Current Running Transcription Ends + + + +; Column Three +;------------------------------------------------ +Gui, Font, s%HeaderFontSize% +Gui, Font, Bold +gui, add, text, x%Column_Three_Vertical_line_x_Pos% y0 h%GUIHeight% 0x11 ;Vertical Line > Etched Gray +Gui, Add, Button, x%ColumnThreeXPos% y0 w%ColumnThreeHeaderWidth% h%ColumnHeaderButtonHeight%, COLUMNTHREE +Gui, Font, Normal + + +Gui, Add, Checkbox, vCheckboxColThree, Checkbox + + + +Gui, Font, Bold + +; Gui, Add, Button, yp+70 w%ColumnThreeHeaderWidth% gUpgradeChocolatey, Upgrade Chocolatey +; Gui, Add, Button, yp+100 w%ColumnThreeHeaderWidth% gUncheckAll, Uncheck All +Gui, Add, Button, w%ColumnThreeHeaderWidth% gSubmit h%ButtonHeight% y%ExecuteButtonYPos% x%ColumnThreeXPos%, Execute +; Gui, Add, Text, x+5, Debloat + +; Gui, Show, ; w1230 ; , w600 h200 +gui, Show,,%GUI_Title% +Return + + + + + +; GoSubs +;------------------------------------------------ + +UpdateGUI: +gui, Submit, NoHide +Return + + +SelectFile: +if(SelectedDirectoryPath){ + Msgbox, Your already have a directory selected. `nThis script can only handle one or the other at the moment. + return +} +FileSelectFile, SelectedFiles, M3 ; M3 = Multiselect existing files. +if (SelectedFiles = "") +return + +GUIFilesText := StrReplace(SelectedFiles, "`n", "|") + +GuiControl, Text,FilesFilepath, %GUIFilesText% +return + +SelectDirectory: +if(SelectedFiles){ + Msgbox, Your already have individual files selected. `nThis script can only handle one or the other at the moment. + return +} + +; have user select a file within the directory they want transcribed. +; Will later get the directory name from this file +FileSelectFile, SelectedDirectoryPath +if (SelectedDirectoryPath = "") +return + +GuiControl,Text,SelectedDirectoryPath, %SelectedDirectoryPath% + +return + + +GuiClose: +ExitApp + +ReloadScript: +Reload +ExitApp + +Submit: +gui, Submit, NoHide + +if(NTFY){ + IniRead, NTFYURL, Settings.ini, %ScriptName%, NTFYURL, %A_space% + ; Msgbox % "NTFYURL: " NTFYURL + if(!NTFYURL){ + InputBox, NTFYURL, Input NTFY URL, Please input NTFY url for notifications.`nGenerate a URL at: https://ntfy.sh/app + if(ErrorLevel){ + NTFY := 0 + } + else, { ; save url to settings.ini + IniWrite, %NTFYURL%, Settings.ini, %ScriptName%, NTFYURL + } + } + +} + +IniWrite, %CPUThreads%, Settings.ini, %ScriptName%, CPUThreads +IniWrite, %ShowTooltip%, Settings.ini, %ScriptName%, ShowTooltip +IniWrite, %MinutesToPauseBetweenTranscriptions%, Settings.ini, %ScriptName%, MinutesToPauseBetweenTranscriptions +; IniWrite, %ContinueAfterCMDClose%, Settings.ini, %A_ScriptName%, ContinueAfterCMDClose + +if(SelectedDirectoryPath){ + IniWrite, %SelectedDirectoryPath%, Settings.ini, %ScriptName%, SelectedDirectoryPath +} +else, { + IniWrite, %A_space%, Settings.ini, %ScriptName%, SelectedDirectoryPath +} + + +if(!SelectedFiles AND !SelectedDirectoryPath){ + msgbox, Please select individual files or a directory that you want Transcribed. + return +} + + +Status := RunCMD("ffmpeg") +; Msgbox % "Status: " Status +if(!InStr(Status, "ffmpeg version")){ + MsgBox, Error:, FFMPEG was not found in System PATH.`nPlease install it and add it to System PATH to automatically convert files to the Whisper.cpp required 16-bit WAV file + return +} + +Message = Creating Required Variables +ShowTooltipText(Message) + +; if files selected, add them all to array +if(SelectedFiles){ + + SelectedAudioFilesArray := [] ; Create array + + ; loop through all selected files and add them to the array + Loop, parse, SelectedFiles, `n + { + if (A_Index = 1){ + AudioFilesDIR = %A_LoopField% + ; MsgBox, The selected files are all contained in %A_LoopField%. + } + else + { + AudioFileFP = %AudioFilesDIR%\%A_LoopField% + SelectedAudioFilesArray.Push(AudioFileFP) ; Append an item to the array + ; SelectedAudioFilesVAR .= AudioFileFP . "," + } + } +} + + +; if directory selected, loop through all files and add them to the array +if(SelectedDirectoryPath){ + SplitPath, SelectedDirectoryPath, OutFileName, AudioFilesDIR, OutExtension, OutNameNoExt, OutDrive + ; msgbox, adding files in directory to var + SelectedAudioFilesArray := [] ; Create array + + Text = Creating Array of Whitelisted Files (%WhitelistedMediaFilesExtensions%) `nin Directory: %AudioFilesDIR% + ShowTooltipText(Text) + PrePendToErrorLogText(text) + + Loop, files, %AudioFilesDIR%\*.*, F + { + + SplitPath, A_LoopFileFullPath, FileNameWExt, FileDir, FileExt, FileNameNoExt, + + if(InStr(WhitelistedMediaFilesExtensions, FileExt)){ + SelectedAudioFilesArray.Push(A_LoopFileFullPath) + } + } +} + + +; If directory selected, add all files to array + + +; Msgbox % "AudioFilesDIR: " AudioFilesDIR + + + +; KeepCMD := 0 +OverwritePreviousTranscriptions := 0 + +if(KeepCMD){ + KeepCMD := "K" +} +else, { + KeepCMD := "C" +} + +; clear variable from GUI +TranscriptionModelsSelected := + +; push to array each quality selected +if(TinyM Or AllMQualities){ + TranscriptionModels.Push("Tiny") ; Append an item to the array + TranscriptionModelPaths.Push(tinyM_FP) ; Append an item to the array + TranscriptionModelsSelected .= "Tiny|" +} +if(SmallM Or AllMQualities){ + TranscriptionModels.Push("Small") ; Append an item to the array + TranscriptionModelPaths.Push(smallM_FP) ; Append an item to the array + TranscriptionModelsSelected .= "Small|" +} +if(BaseM Or AllMQualities){ + TranscriptionModels.Push("Base") ; Append an item to the array + TranscriptionModelPaths.Push(baseM_FP) ; Append an item to the array + TranscriptionModelsSelected .= "Base|" +} +if(MediumM Or AllMQualities){ + TranscriptionModels.Push("Medium") ; Append an item to the array + TranscriptionModelPaths.Push(mediumM_FP) ; Append an item to the array + TranscriptionModelsSelected .= "Medium|" +} +if(LargeM Or AllMQualities){ + TranscriptionModels.Push("Large") ; Append an item to the array + TranscriptionModelPaths.Push(largeM_FP) ; Append an item to the array + TranscriptionModelsSelected .= "Large|" +} + + +if(TranscriptionModelsSelected = ""){ + ToolTip + Text = Please Select at Least ONE Model to Transcribe With + msgbox, %Text% + return +} +; save selected models to ini files +IniWrite, %TranscriptionModelsSelected%, Settings.ini, %ScriptName%, TranscriptionModelsSelected + +TranscriptionLengthsSelected := +(ShortPodcasts)?(TranscriptionLengthsSelected .= "Short|"):("") +(MediumPodcasts)?(TranscriptionLengthsSelected .= "Medium|"):("") +(LongPodcasts)?(TranscriptionLengthsSelected .= "Long|"):("") +(AnyLengthMediaFile)?(TranscriptionLengthsSelected .= "AnyLengthMediaFile|"):("") + + +if(TranscriptionLengthsSelected = ""){ + ToolTip + Text = Please Select the Audio Length you'd like to Transcribe + msgbox, %Text% + return +} + +IniWrite, %TranscriptionLengthsSelected%, Settings.ini, %ScriptName%, TranscriptionLengthsSelected + + +; msgbox + + +text = Creating Required Directories +ShowTooltipText(Text) +FileCreateDir, %AudioFilesDIR%\Transcriptions +FileCreateDir, %AudioFilesDIR%\WAVFiles + + +text = Starting Transcription +ShowTooltipText(Text) +PrePendToErrorLogText(text) + + + +; loop through the array and transcribe using options selected +; Msgbox % TranscriptionModels.Length() ; Display total number of items in the array +; ArrayLenght := TranscriptionModels.Length() ; Save total number of items in the array + + +if(ContinueAfterCMDClose and WinExist("Podcast-Transcription-In-Progress")){ + ; msgbox, cmd found. + Text = Waiting for Current Running Transcription to Finish in CMD + ShowTooltipText(Text) + PrePendToErrorLogText(text) + WinWaitClose, ahk_class ConsoleWindowClass ;, WinText, Seconds [, ExcludeTitle, ExcludeText] + ; msgbox, cmd closed +} + + +; loop for each selected audio file +loop % SelectedAudioFilesArray.Length() { + + + Filepath := SelectedAudioFilesArray[A_Index] + OriginalFilepath := SelectedAudioFilesArray[A_Index] + + SplitPath, Filepath, OutFileName, OutDir, OutExtension, OutNameNoExt, OutDrive + + ; Convert the file to 16-bit WAV file as required by whisper.cpp + WavFilepath = %AudioFilesDIR%\WAVFiles\%OutNameNoExt%.wav + + ; loop through each selected transcription model + Loop % TranscriptionModels.Length() { + + ModelName := TranscriptionModels[A_Index] + ModelPath := TranscriptionModelPaths[A_Index] + + + ; create filepaths where outputs will be saved to + OutputPath = %AudioFilesDIR%\Transcriptions\%OutNameNoExt%_%ModelName% + OutputModelTxtFile = %AudioFilesDIR%\Transcriptions\%OutNameNoExt%_%ModelName%.txt + OutputTxtFP = %OutputPath%.txt + LogFileFP = %OutputPath%.log + + + Text = Checking for Previous Transcription + ShowTooltipText(Text) + + ; If .txt Transcription file exists, move on to next model + if(FileExist(OutputModelTxtFile)){ + Message :="Skipping " . OutFileName . " - already transcribed with " . ModelName . " Model" + PrePendToErrorLogText(Message) + Continue + } + + ; otherwise check if log file exists from a previous run, or current run on different node (if using shared folder) + if(FileExist(LogFileFP)){ + FileGetTime, LogFileFPModificationTime, %LogFileFP%, M ; + ; EnvSub, Var, Value [, TimeUnits] + EnvSub, LogFileFPModificationTime, A_Now, S ; get hours SINCE last modified + + ; Check if log file was last added to more than 24 hours ago + ; No podcast transcription should take more than that, and it means that a node started, but never finished it + LogFileFPModificationTime := (LogFileFPModificationTime * -1 ) + ; Msgbox % "LogFileFPModificationTime: " LogFileFPModificationTime + if((LogFileFPModificationTime < 86400)){ + text = Skipping %OutFileName% with Model:%ModelName% - Currently being Transcribed by a different node. + PrePendToErrorLogText(text) + ShowTooltipText(Text) + ; sleep, 1000 + Continue + } + } + + + + ; get information about audio file + Obj := Filexpro(Filepath,, + , "Length" + , "Size" ) + AudioLength := obj["Length"] + + AudioLengthArray := StrSplit(AudioLength,":") + TotalTimeInSeconds := ((AudioLengthArray[1] * 60 ) * 60) + (AudioLengthArray[2] * 60) + AudioLengthArray[3] + + + if(AnyLengthMediaFile){ + ; continue onwards + } + else, { ; otherwise check length and skip accordingly + if(ShortPodcasts){ + if(TotalTimeInSeconds > 1860){ ; greater than 31 minutes + Text = Podcast is longer than 30 minutes. Skipping + ShowTooltipText(Text) + PrePendToErrorLogText(text) + ; msgbox, skipping medium/Long podcast + Continue + } + + } + + if(MediumPodcasts){ ; if less than 31 minutes or greater than 61 minutes + if(TotalTimeInSeconds < 1860 OR TotalTimeInSeconds > 3660){ + Text = Podcast is either shorter than 30 minutes or longer than 60 minutes. Skipping + ShowTooltipText(Text) + PrePendToErrorLogText(text) + Continue + } + } + + if(LongPodcasts){ + if(TotalTimeInSeconds < 3660){ + Text = Podcast is shorter than 60 minutes Skipping + ShowTooltipText(Text) + PrePendToErrorLogText(text) + ; msgbox, skipping short/medium podcast + Continue + } + + } + } + + + if(FileExist(WavFilepath)){ ; re-use previously converted wav file if it exists + Filepath := WavFilepath + }else, { + text = Converting File: %OutFileName% To 16-bit WAV file + ShowTooltipText(Text) + PrePendToErrorLogText(text) + runwait, %ComSpec% /%KeepCMD% ffmpeg -i "%Filepath%" -ar 16000 -ac 1 -c:a pcm_s16le "%WavFilepath%" + } + + + ; msgbox, checking filepath + if(!FileExist(WavFilepath)){ + Message = WAV file not found at:`n%WavFilepath%`nConversion failed for some reason.`nPlease select the "Keep CMD Open" checkbox and run again to see the error.`nClick OK to exit. + PrePendToErrorLogText(text) + Continue + } + + + + FormatTime, TodayDate , YYYYMMDDHH24MISS,hh:mm + text = Transcription in Progress`nModel: %ModelName% CPU Threads: %CPUThreads% Length: %AudioLength%`nFile: %OutNameNoExt%`nStart Time: %TodayDate% + LogToTextFile(text, LogFileFP) + PrePendToErrorLogText(text) + ShowTooltipText(Text) + ; msgbox + + UStartTime := A_TickCount ; start time + + runwait, %ComSpec% /%KeepCMD% title Podcast-Transcription-In-Progress & %A_scriptdir%\Models\main.exe -m %ModelPath% -f "%WavFilepath%" -t %CPUThreads% -otxt -ovtt -osrt -owts -ocsv -of "%OutputPath%" + + URunTime := round(((A_TickCount - UStartTime) / 1000), 2) ; end time + Message = Time to Transcribe: %URunTime% seconds + LogToTextFile(Message, LogFileFP) + + ; get time it took to transcribe in seconds + TranscriptionLength := round(((A_TickCount - UStartTime) / 1000), 2) + + ; if more than 1 hour, convert time to hours:minutes for NTFY message + (TranscriptionLength > 3600)?(NTFYTranscriptionTime := round((TranscriptionLength / 3600),2) . " Hours"):(NTFYTranscriptionTime := TranscriptionLength . " Seconds") + + SecondsToTranscribe1Sec := round((TranscriptionLength / TotalTimeInSeconds), 2) + + ; TotalTimeInSeconds + text = Transcription of %WavFilepath% took a total of %TranscriptionLength% Seconds + LogToTextFile(text, LogFileFP) + PrePendToErrorLogText(text) + + if(NTFY){ + Message = Transcription Complete `nNode: %A_ComputerName% `nFile: %OutNameNoExt% `nAudio Length: %AudioLength%`nModel: %ModelName%`nCPU Threads: %CPUThreads% `nTTTS: %NTFYTranscriptionTime%`nTTS 1 (s): %SecondsToTranscribe1Sec% Seconds + SendMessagetoNTFY(Message, NTFYURL) + } + + } + ; / All transcriptions have been looped through + + ; take a short rest so CPU has time to cool down + ; IF the last model tool longer than 10 seconds to complete (AKA not skipped over) + if(MinutesToPauseBetweenTranscriptions AND TranscriptionLength > 1000){ + if(ModelName = "Medium" OR ModelName="Large"){ + text = Waiting for %MinutesToPauseBetweenTranscriptions% Minutes before moving on to next item + ShowTooltipText(Text) + PrePendToErrorLogText(text) + + MilisecondsToSleep := MinutesToPauseBetweenTranscriptions * 60000 + sleep, %MilisecondsToSleep% + } + + ; reset timer for next loop + TranscriptionLength := + } + + + } + ToolTip + + if(NTFY){ + Message = Node: %A_ComputerName% Has Completed Transcribing ALL Selected Files! ;`nFile: %OutNameNoExt% `nModel: %ModelName%`nCPU Threads: %CPUThreads% `nLength: %AudioLength%`nTime: %TranscriptionLength% Seconds + SendMessagetoNTFY(Message, NTFYURL) + } + + + msgbox, All Transcriptions have been completed. + return + + ; Functions + ;------------------------------------------------ + LogToTextFile(Text, Filepath){ + ; ErrorLoggingFile := Filepath + FileAppend, %Text%`n`n, %Filepath% + } + + ShowTooltipText(Text){ + if(ShowTooltip){ + TooltipFirstLine := StrSplit(Text, "`n") + TooltipFirstLine := TooltipFirstLine[1] + ToolTipLen := StrLen(TooltipFirstLine) + TooltipXPos := A_ScreenWidth / 2 - ((ToolTipLen * 9) / 2) + ; Msgbox % "TooltipXPos: " TooltipXPos + ToolTip, %Text%, %TooltipXPos%, 0 + } + } + + PrePendToErrorLogText(Text){ + ErrorLogText := Text "`n`n" . ErrorLogText + + GuiControl, Text,StatusLog, %ErrorLogText% + } + + + SendMessagetoNTFY(Message, URL){ + + command = powershell (Invoke-RestMethod -Method 'Post' -Uri %URL% -Body '%Message%' -UseBasicParsing) + Status := RunCMD(Command) + ; Msgbox % "Status: " Status + } + + +/* +*/ + +; -------------------------------FileXPro Get File Attributes------------------------------- +;https://www.autohotkey.com/boards/viewtopic.php?t=59882 + +Filexpro( sFile := "", Kind := "", P* ) { ; v.90 By SKAN on D1CC @ goo.gl/jyXFo9 + Local + Static xDetails + + If ( sFile = "" ) + { ; Deinit static variable + xDetails := "" + Return + } + + fex := {}, _FileExt := "" + + Loop, Files, % RTrim(sfile,"\*/."), DF + { + If not FileExist( sFile:=A_LoopFileLongPath ) + { + Return + } + + SplitPath, sFile, _FileExt, _Dir, _Ext, _File, _Drv + + If ( p[p.length()] = "xInfo" ) ; Last parameter is xInfo + { + p.Pop() ; Delete parameter + fex.SetCapacity(11) ; Make room for Extra info + fex["_Attrib"] := A_LoopFileAttrib + fex["_Dir"] := _Dir + fex["_Drv"] := _Drv + fex["_Ext"] := _Ext + fex["_File"] := _File + fex["_File.Ext"] := _FileExt + fex["_FilePath"] := sFile + fex["_FileSize"] := A_LoopFileSize + fex["_FileTimeA"] := A_LoopFileTimeAccessed + fex["_FileTimeC"] := A_LoopFileTimeCreated + fex["_FileTimeM"] := A_LoopFileTimeModified + } + Break + } + + If Not ( _FileExt ) ; Filepath not resolved + { + Return + } + + + objShl := ComObjCreate("Shell.Application") + objDir := objShl.NameSpace(_Dir) + objItm := objDir.ParseName(_FileExt) + + If ( VarSetCapacity(xDetails) = 0 ) ; Init static variable + { + i:=-1, xDetails:={}, xDetails.SetCapacity(309) + + While ( i++ < 309 ) + { + xDetails[ objDir.GetDetailsOf(0,i) ] := i + } + + xDetails.Delete("") + } + + If ( Kind and Kind <> objDir.GetDetailsOf(objItm,11) ) ; File isn't desired kind + { + Return + } + + i:=0, nParams:=p.Count(), fex.SetCapacity(nParams + 11) + + While ( i++ < nParams ) + { + Prop := p[i] + + If ( (Dot:=InStr(Prop,".")) and (Prop:=(Dot=1 ? "System":"") . Prop) ) + { + fex[Prop] := objItm.ExtendedProperty(Prop) + Continue + } + + If ( PropNum := xDetails[Prop] ) > -1 + { + fex[Prop] := ObjDir.GetDetailsOf(objItm,PropNum) + Continue + } + } + + fex.SetCapacity(-1) + Return fex + + } ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + ; Misc + ;------------------------------------------------ + ; Escape::ExitApp + + ; Functions + ;------------------------------------------------ + + + + + ; Misc + ;------------------------------------------------ +; Escape::ExitApp \ No newline at end of file diff --git a/Whisper-AHK.ahk b/Whisper-AHK.ahk index ead90ae..a262389 100644 --- a/Whisper-AHK.ahk +++ b/Whisper-AHK.ahk @@ -24,12 +24,11 @@ ScriptName = Whisper-AHK ScriptVersion = V1.0 - ; VARIABLES ;------------------------------------------------ WhitelistedMediaFilesExtensions = mp3,wav,mp4 -; Models + largeM_FP = %A_scriptdir%\Models\ggml-large-v1.bin mediumM_FP = %A_scriptdir%\Models\ggml-medium.bin baseM_FP = %A_scriptdir%\Models\ggml-base.en.bin @@ -41,17 +40,26 @@ EnvGet, ProcessorCount, NUMBER_OF_PROCESSORS ; EnvGet, ProcessorCount, NUMBER_OF_PROCESSORS +IniRead, ShutdownOnFinish, Settings.ini, %ScriptName%, ShutdownOnFinish, 0 IniRead, CPUThreads, Settings.ini, %ScriptName%, CPUThreads, %A_space% IniRead, ShowTooltip, Settings.ini, %ScriptName%, ShowTooltip, %A_space% IniRead, MinutesToPauseBetweenTranscriptions, Settings.ini, %ScriptName%, MinutesToPauseBetweenTranscriptions, 0 IniRead, SelectedDirectoryPath, Settings.ini, %ScriptName%, SelectedDirectoryPath, %A_space% IniRead, TranscriptionModelsSelected, Settings.ini, %ScriptName%, TranscriptionModelsSelected, %A_space% IniRead, TranscriptionLengthsSelected, Settings.ini, %ScriptName%, TranscriptionLengthsSelected, %A_space% -IniRead, NTFYURL, Settings.ini, %ScriptName%, NTFYURL, %A_space% +IniRead, NTFYURL, Settings.ini, %ScriptName%, NTFYURL, 0 (NTFYURL)?(NTFYURLCheckStatus := 1):(NTFYURLCheckStatus := 0) + + + (WinExist("Podcast-Transcription-In-Progress"))?(ContinueAfterCMDCloseCheckStatus := 1):(ContinueAfterCMDCloseCheckStatus := 0) +IniRead, HideCMDWindows, Settings.ini, %ScriptName%, HideCMDWindows, 0 +IniRead, UploadResultToNTFY, Settings.ini, %ScriptName%, UploadResultToNTFY, 0 +IniRead, NTFYEXEFilepath, Settings.ini, %ScriptName%, NTFYEXEFilepath, 0 +IniRead, NTFYTopic, Settings.ini, %ScriptName%, NTFYTopic, 0 + ; Msgbox % "ContinueAfterCMDCloseCheckStatus: " ContinueAfterCMDCloseCheckStatus /* @@ -91,20 +99,23 @@ TranscriptionModelGPUNames := [] ; Create an array ; -------------------------------GUI Variables------------------------------- -GUIMargin := 5 +GUIMargin := 10 -GUIRowTwoXPos := 300 -GUIRowTwoVerticalLineXPos := GUIRowTwoXPos - 10 +VerticalLineHeight := 600 -GUIRowThreeXPos := 650 -GUIRowThreeVerticalLineXPos := GUIRowThreeXPos - 10 +GUIRowTwoXPos := 350 +GUIRowTwoWidth := 350 +GUIRowTwoVerticalLineXPos := GUIRowTwoXPos - (10 * 2) + + +GUIRowThreeXPos := GUIRowTwoXPos + GUIRowTwoWidth + (GUIMargin * 2) +GUIRowThreeVerticalLineXPos := GUIRowThreeXPos - GUIMargin GUIButtonWidths := 50 - GUIEditBoxWidth := GUIRowTwoXPos - (GUIMargin * 4) -GuiWidth := 1000 +GuiWidth := 1100 GuiStartButtonXPos := GUIRowTwoXPos + %GUIMargin% GUISelectButtonWidths := 70 @@ -115,8 +126,9 @@ TranscribeButtonWidth := GuiWidth - GUIRowThreeXPos - (GUIMargin * 2) gui, font, s12 -Gui, font, Bold -; Gui, Add, Text,x%GUIMargin% y%GUIMargin% w%GUIRowTwoXPos% center, Transcription Settings +Gui, Font, Bold +Gui, Font, underline +Gui, Add, Text,x%GUIMargin% y%GUIMargin% w%GUIRowTwoXPos% center, Transcription Settings Gui, font, normal ; Gui, Add, Text, , Number of CPU Threads ; `nTotal Processors on PC: %ProcessorCount% @@ -124,7 +136,7 @@ Gui, Add, Text, x%GUIMargin% y+%GUIMargin% w%GUIEditBoxWidth% center, Number o Gui, Add, Edit, gUpdateGUI w%GUIEditBoxWidth%, Gui, Add, UpDown, vCPUThreads Range1-20, %CPUThreads% -Gui, Add, Text, x%GUIMargin% y+15 w%GUIEditBoxWidth% center, Minutes to Pause After M/L Models ; `nTotal Processors on PC: %ProcessorCount% +Gui, Add, Text, x%GUIMargin% y+40 w%GUIEditBoxWidth% center, Minutes to Pause After M/L Models ; `nTotal Processors on PC: %ProcessorCount% Gui, Add, Edit, gUpdateGUI w%GUIEditBoxWidth%, Gui, Add, UpDown, vMinutesToPauseBetweenTranscriptions Range0-20, %MinutesToPauseBetweenTranscriptions% @@ -134,7 +146,7 @@ Gui, Add, UpDown, vMinutesToPauseBetweenTranscriptions Range0-20, %MinutesToPaus ; Gui, Add, Text ; Gui, font, Bold -Gui, Add, Text,x%GUIMargin% y+15 w%GUIEditBoxWidth% center, Transcribe Individual File(s): +Gui, Add, Text,x%GUIMargin% y+40 w%GUIEditBoxWidth% center, Transcribe Individual File(s) ; Gui, font, normal Gui, Add, Edit, vFilesFilepath gUpdateGUI w%GUIEditBoxWidth% Gui, Add, Button, y+1 gSelectFile w%GUIEditBoxWidth%, Select @@ -142,33 +154,38 @@ Gui, Add, Button, y+1 gSelectFile w%GUIEditBoxWidth%, Select ; Gui, font, Bold ; Gui, Add, Text, cRed center w200 x%GUIMargin%, OR -Gui, Add, Text,x%GUIMargin% y+15 w%GUIEditBoxWidth% center, Transcribe All Audio Files within Folder: -Gui, Add, Edit, vSelectedDirectoryPath gUpdateGUI w%GUIEditBoxWidth%, %SelectedDirectoryPath% +; Gui, Add, Text,x%GUIMargin% y+40 w%GUIEditBoxWidth% center, OR + +; Gui, Font, s10 +Gui, Add, Text,x%GUIMargin% y+40 w%GUIEditBoxWidth% center, Transcribe Directory +; gui, font, s12 +Gui, Add, Edit, h30 vSelectedDirectoryPath gUpdateGUI w%GUIEditBoxWidth%, %SelectedDirectoryPath% Gui, Add, Button, y+1 w%GUIEditBoxWidth% gSelectDirectory , Select -gui, add, text, y%GUIMargin% x%GUIRowTwoVerticalLineXPos% 0x11 h270 ; 0x11 is a "line" ; refer to here: https://autohotkey.com/board/topic/50910-draw-line-gui/ +gui, add, text, y%GUIMargin% x%GUIRowTwoVerticalLineXPos% 0x11 h%VerticalLineHeight% ; 0x11 is a "line" ; refer to here: https://autohotkey.com/board/topic/50910-draw-line-gui/ -Gui, font, Bold -Gui, Add, Text,x%GUIRowTwoXPos% y%GUIMargin% w%GUIRowTwoXPos% center,Transcription Model +Gui, Font, Bold +Gui, Font, underline +Gui, Add, Text,x%GUIRowTwoXPos% y%GUIMargin% w%GUIRowTwoWidth% center,Transcription Model Gui, font, normal ; , Param2, Param3, Param4] ; Gui, Add, Radio -Gui, Add, Checkbox, vBaseM checked%BaseM%, Base (142 MB Disk, ~210 MB RAM) -Gui, Add, Checkbox, vSmallM checked%SmallM%, Small (466 MB Disk, ~600 MB RAM) -Gui, Add, Checkbox, vMediumM checked%MediumM%, Medium (1.5 GB Disk, ~1.7 GB RAM) -Gui, Add, Checkbox, vLargeM checked%LargeM% ,Large (2.9 GB Disk, ~3.3 GB RAM) -Gui, Add, Checkbox, vAllMQualities, ALL (One by One) +Gui, Add, Checkbox, w%GUIRowTwoWidth% vBaseM checked%BaseM%, Base (142 MB Disk, ~210 MB RAM) +Gui, Add, Checkbox, w%GUIRowTwoWidth% vSmallM checked%SmallM%, Small (466 MB Disk, ~600 MB RAM) +Gui, Add, Checkbox, w%GUIRowTwoWidth% vMediumM checked%MediumM%, Medium (1.5 GB Disk, ~1.7 GB RAM) +Gui, Add, Checkbox, w%GUIRowTwoWidth% vLargeM checked%LargeM% ,Large (2.9 GB Disk, ~3.3 GB RAM) +Gui, Add, Checkbox, w%GUIRowTwoWidth% vAllMQualities, ALL (One by One) ; Gui, Add, Slider, w200 h20 Range1-5, test, one, two ; Creates a horizontal slider Gui, Font, Bold Gui, Font, underline -Gui, Add, Text,x%GUIRowTwoXPos% y+15 w%GUIRowTwoXPos% center,Length of Podcasts to Transcribe +Gui, Add, Text,x%GUIRowTwoXPos% y+15 w%GUIRowTwoXPos% center,Length of File to Transcribe Gui, font, normal Gui, Add, Checkbox, vAnyLengthMediaFile gUpdateGUI checked%AnyLengthMediaFileCheckStatus%, ANY Length Gui, Add, Checkbox,y+%GUIMargin% gUpdateGUI vShortPodcasts checked%ShortPodcastsCheckStatus%, Short ( < 30 Mins) @@ -176,32 +193,40 @@ Gui, Add, Checkbox, vMediumPodcasts gUpdateGUI checked%MediumPodcastsCheckStatus Gui, Add, Checkbox, vLongPodcasts gUpdateGUI checked%LongPodcastsCheckStatus%, Long ( > 60 Mins) -; Gui, Add, Text Gui, Font, Bold -Gui, Add, Text,x%GUIRowTwoXPos% y+15 w200 center,Other Settings +Gui, Font, underline +Gui, Add, Text,x%GUIRowTwoXPos% y+15 w%GUIRowTwoWidth% center,Other Settings Gui, font, normal -Gui, Add, Checkbox, vKeepCMD, Keep CMD Open After Model Completion +Gui, Add, Checkbox, vHideCMDWindows checked%HideCMDWindows%, Hide CMD Windows +Gui, Add, Checkbox, vKeepCMDOpenOrClose checked%HideCMDWindows%, Keep CMD Open After Model Completion Gui, Add, Checkbox, vShowTooltip checked%ShowTooltip%, Show Tooltip of Progress at Top of Screen -Gui, Add, Checkbox, vNTFY checked%NTFYURLCheckStatus%, NTFY After Each Transcription +Gui, Add, Checkbox, vNTFYURL checked%NTFYURL%, NTFY After Each Transcription +Gui, Add, Checkbox, vUploadResultToNTFY checked%UploadResultToNTFY%, Upload Transcription to NTFY + Gui, Add, Checkbox, vContinueAfterCMDClose checked%ContinueAfterCMDCloseCheckStatus%, Start After Current Running Transcription Ends +Gui, Add, Checkbox, vShutdownOnFinish, Shutdown PC on Completion -gui, add, text, y20 x%GUIRowThreeVerticalLineXPos% 0x11 h400 ; 0x11 is a "line" ; refer to here: https://autohotkey.com/board/topic/50910-draw-line-gui/ -Gui, font, Bold + +gui, add, text, y20 x%GUIRowThreeVerticalLineXPos% 0x11 h%VerticalLineHeight% ; 0x11 is a "line" ; refer to here: https://autohotkey.com/board/topic/50910-draw-line-gui/ + + gui, font, s12 +Gui, Font, Bold +Gui, Font, underline Gui, Add, text,y%GUIMargin% w%TranscribeButtonWidth% x%GUIRowThreeXPos% h20 Center, Status Log gui, font, normal gui, font, s7 -Gui, Add, Edit, y+%GUIMargin% w%TranscribeButtonWidth% x%GUIRowThreeXPos% h300 vStatusLog +Gui, Add, Edit, y+%GUIMargin% w%TranscribeButtonWidth% x%GUIRowThreeXPos% h450 vStatusLog Gui, font, Bold Gui, Font, s12 Gui, Add, Button, y+20 x%GUIRowThreeXPos% w%TranscribeButtonWidth% h40 gSubmit Center, Transcribe gui, font, normal Gui, Font, s9 -Gui, Add, Button, y+%GUIMargin% x%GUIRowThreeXPos% w%TranscribeButtonWidth% h15 gReloadScript Center, Restart +Gui, Add, Button, y+%GUIMargin% x%GUIRowThreeXPos% w%TranscribeButtonWidth% h30 gReloadScript Center, Restart Gui, Font, s5 ; Gui, Add, StatusBar,Center, This Node: Minutes Transcribed by Node: Total Minutes Transcribed by All Nodes: Total Minutes of All Transcriptions: Average time to transcribe 1 min: @@ -218,9 +243,9 @@ Return SelectFile: if(SelectedDirectoryPath){ - Msgbox, Your already have a directory selected. `nThis script can only handle one or the other at the moment. - return + GuiControl,Text,SelectedDirectoryPath, } + FileSelectFile, SelectedFiles, M3 ; M3 = Multiselect existing files. if (SelectedFiles = "") return @@ -231,9 +256,8 @@ GuiControl, Text,FilesFilepath, %GUIFilesText% return SelectDirectory: -if(SelectedFiles){ - Msgbox, Your already have individual files selected. `nThis script can only handle one or the other at the moment. - return +if(FilesFilepath){ + GuiControl, Text,FilesFilepath, } ; have user select a file within the directory they want transcribed. @@ -257,6 +281,13 @@ ExitApp Submit: gui, Submit, NoHide +; Hide CMD popups when doing run, or runwait or comspec commands +if(HideCMDWindows){ + DllCall("AllocConsole") + WinHide % "ahk_id " DllCall("GetConsoleWindow", "ptr") +} + + if(NTFY){ IniRead, NTFYURL, Settings.ini, %ScriptName%, NTFYURL, %A_space% ; Msgbox % "NTFYURL: " NTFYURL @@ -272,9 +303,13 @@ if(NTFY){ } +IniWrite, %ShutdownOnFinish%, Settings.ini, %ScriptName%, ShutdownOnFinish IniWrite, %CPUThreads%, Settings.ini, %ScriptName%, CPUThreads IniWrite, %ShowTooltip%, Settings.ini, %ScriptName%, ShowTooltip IniWrite, %MinutesToPauseBetweenTranscriptions%, Settings.ini, %ScriptName%, MinutesToPauseBetweenTranscriptions +IniWrite, %HideCMDWindows%, Settings.ini, %ScriptName%, HideCMDWindows +IniWrite, %UploadResultToNTFY%, Settings.ini, %ScriptName%, UploadResultToNTFY + ; IniWrite, %ContinueAfterCMDClose%, Settings.ini, %A_ScriptName%, ContinueAfterCMDClose if(SelectedDirectoryPath){ @@ -352,14 +387,14 @@ if(SelectedDirectoryPath){ -; KeepCMD := 0 +; KeepCMDOpenOrClose := 0 OverwritePreviousTranscriptions := 0 -if(KeepCMD){ - KeepCMD := "K" +if(KeepCMDOpenOrClose){ + KeepCMDOpenOrClose := "K" } else, { - KeepCMD := "C" + KeepCMDOpenOrClose := "C" } ; clear variable from GUI @@ -521,7 +556,7 @@ loop % SelectedAudioFilesArray.Length() { if(AnyLengthMediaFile){ - ; continue onwards + ; continue onwards } else, { ; otherwise check length and skip accordingly if(ShortPodcasts){ @@ -563,7 +598,7 @@ loop % SelectedAudioFilesArray.Length() { text = Converting File: %OutFileName% To 16-bit WAV file ShowTooltipText(Text) PrePendToErrorLogText(text) - runwait, %ComSpec% /%KeepCMD% ffmpeg -i "%Filepath%" -ar 16000 -ac 1 -c:a pcm_s16le "%WavFilepath%" + runwait, %ComSpec% /%KeepCMDOpenOrClose% ffmpeg -i "%Filepath%" -ar 16000 -ac 1 -c:a pcm_s16le "%WavFilepath%" } @@ -585,7 +620,7 @@ loop % SelectedAudioFilesArray.Length() { UStartTime := A_TickCount ; start time - runwait, %ComSpec% /%KeepCMD% title Podcast-Transcription-In-Progress & %A_scriptdir%\Models\main.exe -m %ModelPath% -f "%WavFilepath%" -t %CPUThreads% -otxt -ovtt -osrt -owts -ocsv -of "%OutputPath%" + runwait, %ComSpec% /%KeepCMDOpenOrClose% title Podcast-Transcription-In-Progress & %A_scriptdir%\Models\main.exe -m %ModelPath% -f "%WavFilepath%" -t %CPUThreads% -otxt -ovtt -osrt -owts -ocsv -of "%OutputPath%" URunTime := round(((A_TickCount - UStartTime) / 1000), 2) ; end time Message = Time to Transcribe: %URunTime% seconds @@ -604,9 +639,19 @@ loop % SelectedAudioFilesArray.Length() { LogToTextFile(text, LogFileFP) PrePendToErrorLogText(text) - if(NTFY){ - Message = Transcription Complete `nNode: %A_ComputerName% `nFile: %OutNameNoExt% `nAudio Length: %AudioLength%`nModel: %ModelName%`nCPU Threads: %CPUThreads% `nTTTS: %NTFYTranscriptionTime%`nTTS 1 (s): %SecondsToTranscribe1Sec% Seconds - SendMessagetoNTFY(Message, NTFYURL) + + if(NTFY OR UploadResultToNTFY){ + if(UploadResultToNTFY){ + Command = "%NTFYEXEFilepath%" publish -t "%OutNameNoExt%" -f "%OutputPath%.txt" %NTFYTopic% + ; Clipboard := Command + ; Msgbox % "Command: " Command + Status := RunCMD(Command) + ; Msgbox % "Status: " Status + } + else if(NTFY){ + Message = Transcription Complete `nNode: %A_ComputerName% `nFile: %OutNameNoExt% `nAudio Length: %AudioLength%`nModel: %ModelName%`nCPU Threads: %CPUThreads% `nTTTS: %NTFYTranscriptionTime%`nTTS 1 (s): %SecondsToTranscribe1Sec% Seconds + SendMessagetoNTFY(Message, NTFYURL) + } } } @@ -638,141 +683,151 @@ loop % SelectedAudioFilesArray.Length() { } + + msgbox, All Transcriptions have been completed. + + if(ShutdownOnFinish){ + Shutdown, 9 ; shutdown + power down: 1 + 8 = 9 + } + return - ; Functions +/* +*/ + +; Functions +;------------------------------------------------ +LogToTextFile(Text, Filepath){ + ; ErrorLoggingFile := Filepath + FileAppend, %Text%`n`n, %Filepath% +} + +ShowTooltipText(Text){ + if(ShowTooltip){ + TooltipFirstLine := StrSplit(Text, "`n") + TooltipFirstLine := TooltipFirstLine[1] + ToolTipLen := StrLen(TooltipFirstLine) + TooltipXPos := A_ScreenWidth / 2 - ((ToolTipLen * 9) / 2) + ; Msgbox % "TooltipXPos: " TooltipXPos + ToolTip, %Text%, %TooltipXPos%, 0 + } +} + +PrePendToErrorLogText(Text){ + ErrorLogText := Text "`n`n" . ErrorLogText + + GuiControl, Text,StatusLog, %ErrorLogText% +} + + +SendMessagetoNTFY(Message, URL){ + + command = powershell (Invoke-RestMethod -Method 'Post' -Uri %URL% -Body '%Message%' -UseBasicParsing) + Status := RunCMD(Command) + ; Msgbox % "Status: " Status +} + + + + +; -------------------------------FileXPro Get File Attributes------------------------------- +;https://www.autohotkey.com/boards/viewtopic.php?t=59882 + +Filexpro( sFile := "", Kind := "", P* ) { ; v.90 By SKAN on D1CC @ goo.gl/jyXFo9 + Local + Static xDetails + + If ( sFile = "" ) + { ; Deinit static variable + xDetails := "" + Return + } + + fex := {}, _FileExt := "" + + Loop, Files, % RTrim(sfile,"\*/."), DF + { + If not FileExist( sFile:=A_LoopFileLongPath ) + { + Return + } + + SplitPath, sFile, _FileExt, _Dir, _Ext, _File, _Drv + + If ( p[p.length()] = "xInfo" ) ; Last parameter is xInfo + { + p.Pop() ; Delete parameter + fex.SetCapacity(11) ; Make room for Extra info + fex["_Attrib"] := A_LoopFileAttrib + fex["_Dir"] := _Dir + fex["_Drv"] := _Drv + fex["_Ext"] := _Ext + fex["_File"] := _File + fex["_File.Ext"] := _FileExt + fex["_FilePath"] := sFile + fex["_FileSize"] := A_LoopFileSize + fex["_FileTimeA"] := A_LoopFileTimeAccessed + fex["_FileTimeC"] := A_LoopFileTimeCreated + fex["_FileTimeM"] := A_LoopFileTimeModified + } + Break + } + + If Not ( _FileExt ) ; Filepath not resolved + { + Return + } + + + objShl := ComObjCreate("Shell.Application") + objDir := objShl.NameSpace(_Dir) + objItm := objDir.ParseName(_FileExt) + + If ( VarSetCapacity(xDetails) = 0 ) ; Init static variable + { + i:=-1, xDetails:={}, xDetails.SetCapacity(309) + + While ( i++ < 309 ) + { + xDetails[ objDir.GetDetailsOf(0,i) ] := i + } + + xDetails.Delete("") + } + + If ( Kind and Kind <> objDir.GetDetailsOf(objItm,11) ) ; File isn't desired kind + { + Return + } + + i:=0, nParams:=p.Count(), fex.SetCapacity(nParams + 11) + + While ( i++ < nParams ) + { + Prop := p[i] + + If ( (Dot:=InStr(Prop,".")) and (Prop:=(Dot=1 ? "System":"") . Prop) ) + { + fex[Prop] := objItm.ExtendedProperty(Prop) + Continue + } + + If ( PropNum := xDetails[Prop] ) > -1 + { + fex[Prop] := ObjDir.GetDetailsOf(objItm,PropNum) + Continue + } + } + + fex.SetCapacity(-1) + Return fex + + } ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + ; Misc ;------------------------------------------------ - LogToTextFile(Text, Filepath){ - ; ErrorLoggingFile := Filepath - FileAppend, %Text%`n`n, %Filepath% - } - - ShowTooltipText(Text){ - if(ShowTooltip){ - TooltipFirstLine := StrSplit(Text, "`n") - TooltipFirstLine := TooltipFirstLine[1] - ToolTipLen := StrLen(TooltipFirstLine) - TooltipXPos := A_ScreenWidth / 2 - ((ToolTipLen * 9) / 2) - ; Msgbox % "TooltipXPos: " TooltipXPos - ToolTip, %Text%, %TooltipXPos%, 0 - } - } - - PrePendToErrorLogText(Text){ - ErrorLogText := Text "`n`n" . ErrorLogText - - GuiControl, Text,StatusLog, %ErrorLogText% - } - - - SendMessagetoNTFY(Message, URL){ - - command = powershell (Invoke-RestMethod -Method 'Post' -Uri %URL% -Body '%Message%' -UseBasicParsing) - Status := RunCMD(Command) - ; Msgbox % "Status: " Status - } - - - - - ; -------------------------------FileXPro Get File Attributes------------------------------- - ;https://www.autohotkey.com/boards/viewtopic.php?t=59882 - - Filexpro( sFile := "", Kind := "", P* ) { ; v.90 By SKAN on D1CC @ goo.gl/jyXFo9 - Local - Static xDetails - - If ( sFile = "" ) - { ; Deinit static variable - xDetails := "" - Return - } - - fex := {}, _FileExt := "" - - Loop, Files, % RTrim(sfile,"\*/."), DF - { - If not FileExist( sFile:=A_LoopFileLongPath ) - { - Return - } - - SplitPath, sFile, _FileExt, _Dir, _Ext, _File, _Drv - - If ( p[p.length()] = "xInfo" ) ; Last parameter is xInfo - { - p.Pop() ; Delete parameter - fex.SetCapacity(11) ; Make room for Extra info - fex["_Attrib"] := A_LoopFileAttrib - fex["_Dir"] := _Dir - fex["_Drv"] := _Drv - fex["_Ext"] := _Ext - fex["_File"] := _File - fex["_File.Ext"] := _FileExt - fex["_FilePath"] := sFile - fex["_FileSize"] := A_LoopFileSize - fex["_FileTimeA"] := A_LoopFileTimeAccessed - fex["_FileTimeC"] := A_LoopFileTimeCreated - fex["_FileTimeM"] := A_LoopFileTimeModified - } - Break - } - - If Not ( _FileExt ) ; Filepath not resolved - { - Return - } - - - objShl := ComObjCreate("Shell.Application") - objDir := objShl.NameSpace(_Dir) - objItm := objDir.ParseName(_FileExt) - - If ( VarSetCapacity(xDetails) = 0 ) ; Init static variable - { - i:=-1, xDetails:={}, xDetails.SetCapacity(309) - - While ( i++ < 309 ) - { - xDetails[ objDir.GetDetailsOf(0,i) ] := i - } - - xDetails.Delete("") - } - - If ( Kind and Kind <> objDir.GetDetailsOf(objItm,11) ) ; File isn't desired kind - { - Return - } - - i:=0, nParams:=p.Count(), fex.SetCapacity(nParams + 11) - - While ( i++ < nParams ) - { - Prop := p[i] - - If ( (Dot:=InStr(Prop,".")) and (Prop:=(Dot=1 ? "System":"") . Prop) ) - { - fex[Prop] := objItm.ExtendedProperty(Prop) - Continue - } - - If ( PropNum := xDetails[Prop] ) > -1 - { - fex[Prop] := ObjDir.GetDetailsOf(objItm,PropNum) - Continue - } - } - - fex.SetCapacity(-1) - Return fex - - } ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; Misc - ;------------------------------------------------ ; Escape::ExitApp \ No newline at end of file