From 002913a406f6beb4fd834c38851616d18f1c0610 Mon Sep 17 00:00:00 2001
From: Conrad Zelck <git@simpel.cc>
Date: Sat, 28 Mar 2020 15:33:52 +0100
Subject: [PATCH] Complete rewrite

Working with ffmpeg instead sox

Signed-off-by: Conrad Zelck <git@simpel.cc>
---
 pro_audio.au3 | 293 +++++++++++++++++++++++---------------------------
 1 file changed, 136 insertions(+), 157 deletions(-)

diff --git a/pro_audio.au3 b/pro_audio.au3
index 7f92416..c24ecfb 100644
--- a/pro_audio.au3
+++ b/pro_audio.au3
@@ -1,36 +1,35 @@
 #Region ;**** Directives created by AutoIt3Wrapper_GUI ****
-#AutoIt3Wrapper_Icon=Icons\wav.ico
-#AutoIt3Wrapper_Res_Comment=Converts Audio-Files to 48kHz 24bit.
-#AutoIt3Wrapper_Res_Description=Converts Audio-Files to 48kHz 24bit.
-#AutoIt3Wrapper_Res_Fileversion=1.0.0.12
+#AutoIt3Wrapper_Icon=Icons\peakmeter.ico
+#AutoIt3Wrapper_Res_Comment=Converting to wav with 48kHz 24bit.
+#AutoIt3Wrapper_Res_Description=Converting to wav with 48kHz 24bit.
+#AutoIt3Wrapper_Res_Fileversion=1.1.0.14
 #AutoIt3Wrapper_Res_Fileversion_AutoIncrement=y
+#AutoIt3Wrapper_Res_CompanyName=Norddeutscher Rundfunk
 #AutoIt3Wrapper_Res_LegalCopyright=Conrad Zelck
+#AutoIt3Wrapper_Res_SaveSource=y
 #AutoIt3Wrapper_Res_Language=1031
+#AutoIt3Wrapper_Res_Field=Copyright|Conrad Zelck
+#AutoIt3Wrapper_Res_Field=Compile Date|%date% %time%
+#AutoIt3Wrapper_AU3Check_Parameters=-q -d -w 1 -w 2 -w 3 -w- 4 -w 5 -w 6 -w- 7
+#AutoIt3Wrapper_Run_Au3Stripper=y
+#Au3Stripper_Parameters=/mo
 #EndRegion ;**** Directives created by AutoIt3Wrapper_GUI ****
 #include <AutoItConstants.au3>
+#include <ButtonConstants.au3>
+#include <Date.au3>
+#include <FileConstants.au3>
+#include <GUIConstantsEx.au3>
+#include <MsgBoxConstants.au3>
+#include <StaticConstants.au3>
 #include <File.au3>
 #include <Array.au3>
-#include <TrayCox.au3>
-Opt("GuiCoordMode", 0) ;relative position to the start of the last control with "-1"
+#include <Sound.au3>
+#include <TrayCox.au3> ; source: https://github.com/SimpelMe/TrayCox - not needed for functionality
 
-Global $bGUI = 1 ; GUI soll angezeigt werden
-Global $hEnableGUI = TrayCreateItem("Verstecken", -1, 0)
-TrayItemSetOnEvent (-1, "_Hide")
-TrayCreateItem("", -1, 1)
-
-Local $hGUI
-Local $sCurTrack, $sCurTrackMinusExt, $sCurTrackNewExt, $sCurTrackName
-Local $sOutput, $sOutError, $iPID ; Auslesen STDOUT + STDERR
-Local $aOutput, $aBitRate, $iBitRate, $iFaktorFileSize
-Local $iOldSize, $iShouldSize, $iTempSize, $iProzent, $iProzentTemp = 0
-Local $aProzent
-
-FileInstall("H:\_Conrad lokal\Downloads\AutoIt3\_COX\sox\zlib1.dll", @TempDir & "\", 1)
-FileInstall("H:\_Conrad lokal\Downloads\AutoIt3\_COX\sox\pthreadgc2.dll", @TempDir & "\", 1)
-FileInstall("H:\_Conrad lokal\Downloads\AutoIt3\_COX\sox\libgomp-1.dll", @TempDir & "\", 1)
-FileInstall("H:\_Conrad lokal\Downloads\AutoIt3\_COX\sox\libmp3lame.dll", @TempDir & "\", 1)
-FileInstall("H:\_Conrad lokal\Downloads\AutoIt3\_COX\sox\libmad.dll", @TempDir & "\", 1)
-FileInstall("H:\_Conrad lokal\Downloads\AutoIt3\_COX\sox\sox.exe", @TempDir & "\", 1)
+Opt("GUICloseOnESC", 0)
+FileInstall('K:\ffmpeg\bin\ffmpeg.exe', @TempDir & "\ffmpeg.exe", $FC_OVERWRITE)
+Local $sPathFFmpeg = @TempDir & "\"
+Global $g_sStdErrAll
 
 Local $aCmdLineCopy = $CmdLine
 Local $sAttrib
@@ -47,6 +46,7 @@ EndIf
 Local $aOneFolderFileList
 Local $aFileList[0]
 Local $sChoosenMedia
+Local $hGUI
 If $aCmdLineCopy[0] > 0 Then ; if already Files exist
 	For $i = 1 to $aCmdLineCopy[0]
 		$sAttrib = FileGetAttrib($aCmdLineCopy[$i])
@@ -60,31 +60,30 @@ If $aCmdLineCopy[0] > 0 Then ; if already Files exist
 	Next
 	_ArrayInsert($aFileList, 0, UBound($aFileList))
 Else ; no file in $CmdLine
-	$hGUI = GUICreate(StringTrimRight(@ScriptName, 4) & " - Auswahl",258,63)
+	$hGUI = GUICreate(StringTrimRight(@ScriptName, 4) & " - Auswahl", 290, 70)
 	GUISetFont(10)
-	GUICtrlCreateButton ("Ordner auswählen",10,20,-1,-1,$BS_DEFPUSHBUTTON)
-	GUICtrlCreateButton ("Dateien auswählen",121,-1)
+	Local $idButtonFiles = GUICtrlCreateButton("Dateien auswählen", 10, 20, 130, 30, $BS_DEFPUSHBUTTON)
+	Local $idButtonFolder = GUICtrlCreateButton("Ordner auswählen", 150, 20, 130, 30)
 	GUISetState()
 	Local $msg
 	While 1
         $msg = GUIGetMsg()
         If $msg = $GUI_EVENT_CLOSE Then _Beenden() ; defined at TrayCox.au3
-		If $msg = 3 Then ExitLoop
-		If $msg = 4 Then ExitLoop
+		If $msg = $idButtonFolder Or $msg = $idButtonFiles Then ExitLoop
 	WEnd
 	GUIDelete()
 	Switch $msg
-		Case 3 ; choose folder
+		Case $idButtonFolder
 			$sChoosenMedia = FileSelectFolder (StringTrimRight(@ScriptName, 4) & " - Ordner aussuchen", "")
 			If @error Then
-				MsgBox(262144,StringTrimRight(@ScriptName, 4) & " - Abbruch","Keine Datei(en) ausgewählt")
+				MsgBox($MB_TOPMOST,StringTrimRight(@ScriptName, 4) & " - Abbruch","Keine Datei(en) ausgewählt")
 				Exit
 			EndIf
 			$aFileList = _FileListToArrayRec($sChoosenMedia, "*.*", $FLTAR_FILES + $FLTAR_NOSYSTEM + $FLTAR_NOLINK, $FLTAR_RECUR, $FLTAR_SORT, $FLTAR_FULLPATH)
-		Case 4 ; choose files
+		Case $idButtonFiles
 			$sChoosenMedia = FileOpenDialog(StringTrimRight(@ScriptName, 4),"", "Alle (*.*)","4")
 			If @error Then
-				MsgBox(262144,StringTrimRight(@ScriptName, 4) & " - Abbruch","Keine Datei(en) ausgewählt")
+				MsgBox($MB_TOPMOST,StringTrimRight(@ScriptName, 4) & " - Abbruch","Keine Datei(en) ausgewählt")
 				Exit
 			EndIf
 			$aFileList = StringSplit($sChoosenMedia, "|")
@@ -99,153 +98,133 @@ Else ; no file in $CmdLine
 EndIf
 
 If $aFileList[0] <= 0 Then
-	MsgBox($MB_SYSTEMMODAL + $MB_ICONWARNING, @ScriptName, "Es ist keine zu wandelnde Datei zu finden.")
+	MsgBox($MB_TOPMOST, @ScriptName, "Es ist keine zu wandelnde Datei zu finden.")
 	Exit
 EndIf
 
-Opt("GuiOnEventMode", 1)
-Local $iWidthLabel = 400
-$hGUI = GUICreate(StringTrimRight(@ScriptName, 4),$iWidthLabel + 40,150) ; 150
-GUISetFont(10)
-GUISetOnEvent($GUI_EVENT_CLOSE, "_Beenden")
-Local $hLabelCounter = GUICtrlCreateLabel("Dateien werden gewandelt: ", 20, 20, $iWidthLabel)
-Local $hProgress = GUICtrlCreateProgress(-1, 25, $iWidthLabel)
-Local $sLabelFile = GUICtrlCreateLabel(".", -1, 32, $iWidthLabel, 80) ; label has to have some text ; 80
-GUICtrlSetFont(-1,9)
-GUISetState()
-
-Local $hTimerStart = TimerInit()
-
+$hGUI = GUICreate("Pro Audio", 600, 160)
+Local $idLabelFileName = GUICtrlCreateLabel("", 10, 10, 580, 30, $SS_LEFTNOWORDWRAP)
+GUICtrlSetFont(-1, 14, 400, 0, "Lucida Sans Typewriter")
+Local $idLabelConvert = GUICtrlCreateLabel("Konvertiere Datei:", 10, 50, 580, 30)
+GUICtrlSetFont(-1, 12, 400, 0, "Lucida Sans Typewriter")
+Global $g_idProgress = GUICtrlCreateProgress(10, 80, 580, 20)
+GUICtrlSetFont(-1, 14, 400, 0, "Lucida Sans Typewriter")
+Local $g_hLabelRunningTime = GUICtrlCreateLabel("", 440, 120, 150, 30, $SS_RIGHT)
+GUICtrlSetFont(-1, 14, 400, 0, "Lucida Sans Typewriter")
+GUISetState(@SW_SHOW)
+
+Global $hTimerStart = TimerInit()
+
+Local $sCommand
+Local $sCurTrack, $sCurTrackMinusExt, $sCurTrackNewExt
+Local $iDelimiter
 For $i = 1 To $aFileList[0]
 	$sCurTrack = $aFileList[$i]
-	ConsoleWrite("ShortName: " & $sCurTrack & @CRLF)
-	$sCurTrackMinusExt = StringTrimRight($sCurTrack, 4)
+	GUICtrlSetData($idLabelFileName, $i & "/" & $aFileList[0] & ": " & _FileName($sCurTrack))
+	$iDelimiter = StringInStr($sCurTrack, ".", 0, -1)
+	$sCurTrackMinusExt = StringLeft($sCurTrack, $iDelimiter - 1)
 	$sCurTrackNewExt = '_48kHz_24bit.wav'
+	$sCommand = '-i "' & $sCurTrack & '" -c:a pcm_s24le -ar 48000 -y ' & $sCurTrackMinusExt & $sCurTrackNewExt
 
-	$sOutput = "" ; für jede Runde löschen
-	$sOutError = "" ; für jede Runde löschen
-	$iPID = Run(@TempDir & "\sox.exe --i " & _quotePath($sCurTrack), "", @SW_HIDE, $STDERR_CHILD + $STDOUT_CHILD) ; Metadaten auslesen
-	While ProcessExists($iPID)
-		$sOutput &= StdoutRead($iPID)
-		$sOutError &= StderrRead($iPID)
-	WEnd
+	_runFFmpeg('ffmpeg ' & $sCommand, $sPathFFmpeg)
+	GUICtrlSetData($g_idProgress, 100) ; if ffmpeg is done than set progress to 100 - sometimes last StderrRead with 100 is missed
+Next
+GUICtrlSetData($idLabelFileName, "Alle möglichen Dateien konvertiert.")
+GUICtrlSetData($idLabelConvert, "")
+WinActivate($hGUI,"")
+_PlayReadySound()
+
+While 1
+	Switch GUIGetMsg()
+		Case $GUI_EVENT_CLOSE
+			ExitLoop
+	EndSwitch
+WEnd
+Exit
 
-	If $sOutput = "" Then ; no Metadata
-		$sOutError = StringRegExpReplace($sOutError, ".*\\sox.exe", "")
-		MsgBox($MB_SYSTEMMODAL + $MB_ICONWARNING, @ScriptName, $sCurTrack & ":" & @CRLF & @CRLF & $sOutError)
-	Else
-		GUICtrlSetData($sLabelFile, _WordWrapTextForLabel($sCurTrack, 59))
-		GUICtrlSetData($hLabelCounter, "Dateien werden gewandelt: " & $i & "/" & $aFileList[0])
-		$aOutput = StringSplit($sOutput, @CRLF)
-		$aBitRate = StringRegExp($aOutput[15], "[\d.]{1,5}", 1) ; Bitrate steht im Metadaten-Array auf Platz 15
-		$iBitRate = $aBitRate[0]
-		If StringInStr($iBitRate,".") Then ; Falls in z.B. 2.31M statt 192k angegeben
-			$iBitRate *= 1024 ; mbit to kbit
+Func _runFFmpeg($command, $sWorkingDirectory)
+	Local $hPid = Run('"' & @ComSpec & '" /c ' & $command, $sWorkingDirectory, @SW_HIDE, $STDOUT_CHILD + $STDERR_CHILD)
+	Local $sStdErr, $sTimer
+	Local $iTicksDuration = 0, $iTicksTime = 0, $iTimer
+	While 1
+		Sleep(500)
+		$sStdErr = StderrRead($hPid)
+		If @error Then ExitLoop
+		$g_sStdErrAll &= $sStdErr
+		If StringLen($sStdErr) > 0 Then
+			If Not $iTicksDuration Then $iTicksDuration = _GetDuration($sStdErr)
+			$iTicksTime = _GetTime($sStdErr)
+			If Not @error Then $sStdErr = ""
+			GUICtrlSetData($g_idProgress, $iTicksTime * 100 / $iTicksDuration)
 		EndIf
-		ConsoleWrite("BitRate: " & $iBitRate & @CRLF)
-		$iFaktorFileSize = 2365.44 / $iBitRate ; 2365.44 = Bitrate für 24bit und 48kHz
-		ConsoleWrite("FaktorFileSize: " & $iFaktorFileSize & @CRLF)
-
-		#cs Alternative für Fortschrittsbalken mit Auslesen StdErr von sox.exe - liest aber immer nur alle 6 Sekunden aus
-		$iPID = Run(@TempDir & "\sox.exe " & _quotePath($sCurTrack) & " -b 24 -r 48k " & _quotePath($sCurTrackMinusExt & $sCurTrackNewExt) & " -S", "", @SW_HIDE, $STDERR_CHILD + $STDOUT_CHILD) ; Metadaten auslesen
-		$hTimerStart = TimerInit()
-		While ProcessExists($iPID)
-	;~ 		$sOutput &= StdoutRead($iPID)
-			$sOutError = StderrRead($iPID)
-	;~ 		$sOutput = StderrRead($iPID)
-			If $sOutError <> "" Then
-	;~ 			ConsoleWrite("New Block:" & @CRLF & $sOutError & @CRLF)
-				$aProzent = StringRegExp($sOutError, "(?i)In:([\d.]*)%", 3)
-				If Not @error Then
-	;~ 				_ArrayDisplay($aProzent,"Zeile " & @ScriptLineNumber)
-		;~ 			$sOutput = $aProzent[0]
-					$iProzent = $aProzent[UBound($aProzent) - 1]
-					ConsoleWrite($iProzent & @CRLF)
-					GUICtrlSetData($sLabelFile, $iProzent)
-					GUICtrlSetData($hProgress,$iProzent)
-				EndIf
-	;~ 		GUICtrlSetData($sLabelFile, $sOutError)
-			EndIf
-
-		If $sOutError <> "" Then ; no Metadata
+		$iTimer = TimerDiff($hTimerStart)
+		$sTimer = _Zeit($iTimer)
+		If GUICtrlRead($g_hLabelRunningTime) <> $sTimer Then
+			GUICtrlSetData($g_hLabelRunningTime, $sTimer)
 		EndIf
-	;~ 		Sleep(100)
-		WEnd
-		ConsoleWrite($sOutError & @CRLF)
-		ConsoleWrite(_Zeit(TimerDiff($hTimerStart), True) & @CRLF)
-;~ 		ClipPut("OUT:" & @CRLF & $sOutput & @CRLF & @CRLF & "ERROR:" & @CRLF & $sOutError )
-;~ 		MsgBox($MB_SYSTEMMODAL + $MB_ICONWARNING, @ScriptName, $sOutError)
-		#ce
-
-		$iPID = ShellExecute(@TempDir & "\sox.exe", _quotePath($sCurTrack) & " −b 24 -r 48k " & _quotePath($sCurTrackMinusExt & $sCurTrackNewExt),"","", @SW_HIDE) ; run converter
-		$iOldSize = FileGetSize($sCurTrack)
-		ConsoleWrite("OldSize: " & $iOldSize & @CRLF)
-		$iShouldSize = Round($iOldSize * $iFaktorFileSize)
-		ConsoleWrite("ShouldSize: " & $iShouldSize & @CRLF)
-		$sCurTrackName = StringTrimLeft($sCurTrack, StringInStr($sCurTrack, "\", 0, -1))
-		While ProcessExists($iPID)
-			$iTempSize = FileGetSize($sCurTrackMinusExt & $sCurTrackNewExt)
-			$iProzent = Round(100 * $iTempSize / $iShouldSize)
-			If $iProzent <> $iProzentTemp Then
-				ConsoleWrite($iProzent & "% ")
-				$iProzentTemp = $iProzent
-			EndIf
-			GUICtrlSetData($hProgress,$iProzent)
-		WEnd
-		ConsoleWrite(@CRLF) ; neue Zeile
-		Sleep(100)
-	EndIf
-	ConsoleWrite(@CRLF) ; neue Zeile
-Next
-Exit
+	WEnd
+EndFunc
 
-Func _quotePath($sPath) ; versieht Pfade mit Anführungszeichen " - nötig für Run sowie die Parameter in ShellExecute
-	$sPath = '"' & $sPath & '"'
-	Return $sPath
+Func _PlayReadySound()
+	Local $aSound = _SoundOpen(@WindowsDir & "\media\tada.wav")
+	_SoundPlay($aSound, 1)
+	_SoundClose($aSound)
 EndFunc
 
-Func _Hide() ; Fenster verstecken oder anzeigen
-	If $bGUI = 1 Then
-		GUISetState(@SW_HIDE,$hGUI )
-		TrayItemSetText($hEnableGUI, "Anzeigen")
+Func _GetDuration($sStdErr)
+    If Not StringInStr($sStdErr, "Duration:") Then Return SetError(1, 0, 0)
+    Local $aRegExp = StringRegExp($sStdErr, "(?i)Duration.+?([0-9:]+)", 3)
+    If @error Or Not IsArray($aRegExp) Then Return SetError(2, 0, 0)
+    Local $sTime = $aRegExp[UBound($aRegExp) - 1]
+    Local $aTime = StringSplit($sTime, ":", 2)
+    If @error Or Not IsArray($aTime) Then Return SetError(3, 0, 0)
+    Return _TimeToTicks($aTime[0], $aTime[1], $aTime[2])
+EndFunc   ;==>_GetDuration
+
+Func _GetTime($sStdErr)
+    If Not StringInStr($sStdErr, "time=") Then Return SetError(1, 0, 0)
+    Local $aRegExp = StringRegExp($sStdErr, "(?i)time.+?([0-9:]+)", 3)
+    If @error Or Not IsArray($aRegExp) Then Return SetError(2, 0, 0)
+    Local $sTime = $aRegExp[UBound($aRegExp) - 1]
+    Local $aTime = StringSplit($sTime, ":", 2)
+    If @error Or Not IsArray($aTime) Then Return SetError(3, 0, 0)
+    Return _TimeToTicks($aTime[0], $aTime[1], $aTime[2])
+EndFunc   ;==>_GetTime
+
+
+Func _FileName($sFullPath)
+	Local $iDelimiter = StringInStr($sFullPath, "\", 0, -1)
+	Local $sFilename, $sDisplayName
+	$sFilename = StringTrimLeft($sFullPath, $iDelimiter)
+	If StringLen($sFilename) > 45 Then
+		$sDisplayName &= StringLeft($sFilename, 20) & "[...]" & StringRight($sFilename, 20)
 	Else
-		GUISetState(@SW_SHOW,$hGUI )
-		TrayItemSetText($hEnableGUI, "Verstecken")
+		$sDisplayName = $sFilename
 	EndIf
-	$bGUI = Not $bGUI
+	Return $sDisplayName
 EndFunc
 
-Func _WordWrapTextForLabel($sText, $iCounter)
-	Local $sResult
-	Local $iTotalChar = StringLen($sText)
-	For $i = 1 To Ceiling($iTotalChar / $iCounter)
-		$sResult &= StringLeft($sText, $iCounter) & " "
-		$sText = StringTrimLeft($sText, $iCounter)
-	Next
-	$sResult = StringTrimRight($sResult, 1) ; cut last " "
-	Return $sResult
-EndFunc
-
-Func _Zeit($iMs, $bComfortView = False) ; from ms to a format: "12h 36m 56s 13f" (with special space between - ChrW(8239))
+Func _Zeit($iMs, $bComfortView = True) ; from ms to a format: "12h 36m 56s 13f" (with special space between - ChrW(8239))
 	Local $sReturn
-    $iMs = Int($iMs)
-    Local $iFrames, $iMSec, $iSec, $iMin, $iHour, $sSign
-    If $iMs < 0 Then
-        $iMs = Abs($iMs)
-        $sSign = '-'
-    EndIf
+	$iMs = Int($iMs)
+	Local $iFrames, $iMSec, $iSec, $iMin, $iHour, $sSign
+	If $iMs < 0 Then
+		$iMs = Abs($iMs)
+		$sSign = '-'
+	EndIf
 	$iMSec = StringRight($iMs, 3)
 	$iFrames = $iMSec / 40
-    $iSec = $iMs / 1000
-    $iMin = $iSec / 60
-    $iHour = $iMin / 60
-    $iMin -= Int($iHour) * 60
-    $iSec -= Int($iMin) * 60
+	$iSec = $iMs / 1000
+	$iMin = $iSec / 60
+	$iHour = $iMin / 60
+	$iMin -= Int($iHour) * 60
+	$iSec -= Int($iMin) * 60
 	If $bComfortView Then ; no hours if not present and no frames
 		If Not Int($iHour) = 0 Then $sReturn &= StringRight('0' & Int($iHour), 2) & 'h' & ChrW(8239)
-		$sReturn &= StringRight('0' & Int($iMin), 2) & 'm' & ChrW(8239) & StringRight('0' & Int($iSec), 2) & 's'
+		$sReturn &= StringRight('0' & Int($iMin), 2) & 'm' & ChrW(8239)
+		If Int($iHour) = 0 Then $sReturn &= StringRight('0' & Int($iSec), 2) & 's' ; zum DEBUGGING auskommentieren
 	Else
 		$sReturn = $sSign & StringRight('0' & Int($iHour), 2) & 'h' & ChrW(8239) & StringRight('0' & Int($iMin), 2) & 'm' & ChrW(8239) & StringRight('0' & Int($iSec), 2) & 's' & ChrW(8239) & StringRight('0' & Int($iFrames), 2) & 'f'
 	EndIf
 	Return $sReturn
-EndFunc
\ No newline at end of file
+EndFunc   ;==>_Zeit
-- 
GitLab