MultiCoreLame - flottes Frontend für Lame mit Tagging und Unterordnerstrukturierung

  • Moin,

    schon lange hatte ich vor, einen Ersatz für das inzwischen etwas in die Jahre gekommene Razorlame zu basteln. Es ist alt und wird nicht mehr weiterentwickelt. Die Parameter für Lame sind auch nicht mehr aktuell, und außerdem stammt es aus einer Zeit, als die CPUs nur einen Kern hatten. Das Encoding größerer Mengen an .WAV-Dateien dauert länglich, während die CPU bei lausigen 25-30% vor sich hindümpelt und gar nicht richtig warm wird.

    Außerdem ist hinterher immer etwas Nacharbeit mit mp3bookhelper erforderlich (ebenfalls schon etwas älter): ID3-Tags anhand der Dateinamen erstellen und anschließend die .mp3s in Unterordner einsortieren.

    Das alles macht nun das Script in einem Rutsch - und es werden mehrere Lames gestartet, sofern mehrere .WAV-Files zu encoden sind (bei nur EINER Datei bringt das Script nullkommagarkeinen Geschwindigkeitsvorteil), damit die CPU auch "mal in Schweiß kommt".

    Wenn das Script im selben Verzeichnis wie die Lame.exe liegt, ist alles gut. Ansonsten wird beim ersten Start danach gefragt, wo die Lame.exe ist.

    Beim Beenden wird eine MultiCoreLame.ini geschrieben, damit man nicht jedesmal wieder bei Adam und Eva anfangen muß. Der Rest sollte anhand der Programmoberfläche und der dargestellten Hilfe selbsterklärend sein.

    Anstatt es herauszukopieren, könnt Ihr das Script auch direkt hier herunterladen.

    Spoiler anzeigen
    [autoit]

    #cs

    [/autoit] [autoit][/autoit] [autoit]

    Name.............: MultiCoreLame
    Version..........: 0.7.20140814
    AutoItVersion....: 3.3.12.0
    Author...........: Moon ( [email='multicorelame@foto-gama.net'][/email] )
    Requirements.....: LAME.EXE, Windows XP... 8.1
    Purpose..........: A Front-End for LAME, using multiple threads to be
    a faster replacement for the old-fashioned Razorlame.
    Also tags the mp3-files and structures them into sub-folders,
    if the originating filename contains this information.
    Licence..........: CC0 (Public Domain)

    [/autoit] [autoit][/autoit] [autoit]

    #ce

    [/autoit] [autoit][/autoit] [autoit]

    Opt("MustDeclareVars",1)

    [/autoit] [autoit][/autoit] [autoit]

    #include <GUIConstantsEx.au3> ; GUI Create, events
    #include <ButtonConstants.au3> ; Button, Group, Radio, Checkbox
    #include <EditConstants.au3> ; Edit, Input
    #include <FileConstants.au3> ; File related
    #cs

    [/autoit] [autoit][/autoit] [autoit]

    Do not include:

    [/autoit] [autoit][/autoit] [autoit]

    #include <WindowsConstants.au3> ;Gui erweiterte Stile
    #include <SliderConstants.au3> ;Slider
    #include <ListviewConstants.au3> ;Listview
    #include <AVIConstants.au3> ;AVI
    #include <ComboConstants.au3> ;Combo
    #include <Constants.au3> ;Tray, Run, StdIO,
    #include <DateTimeConstants.au3> ;Date, MonthCal
    #include <ListboxConstants.au3> ;List
    #include <ProgressConstants.au3> ;Progress
    #include <StaticConstants.au3> ;Label, Pic, Icon
    #include <TabConstants.au3> ;Tab
    #include <TreeviewConstants.au3> ;Treeview
    #include <UpdownConstants.au3> ;Updown

    [/autoit] [autoit][/autoit] [autoit]

    #ce

    [/autoit] [autoit][/autoit] [autoit]

    Global _ ; Window related variables
    $HdlMainWindow , _ ; Main Window Handle (sic!)
    $GUImsg , _ ; Messages from Windows...
    $GUIheight , _ ; Height of the main window may vary, at least 270 pixel
    $CIDlamegroup , _ ; Control IDentifier Group Lame settings...
    $CIDcbr , _ ; Control IDentifier Radio selects CBR
    $CIDvbr , _ ; Control IDentifier Radio selects VBR
    $CIDvbrcbr , _ ; Control IDentifier Selection Menu Combo for VBR 0..9 or CBR 8..320
    $CIDmono , _ ; Control IDentifier Checkbox for mono encoding
    $CIDsystemgroup , _ ; Control IDentifier Group System settings...
    $CIDThreadlabel , _ ; Control IDentifier Label number of Threads
    $CIDThreads , _ ; Control IDentifier Selection Menu Combo for the number of threads to use
    $CIDdelsrc , _ ; Control IDentifier Checkbox to delete source file after encoding
    $CIDtagginggroup , _ ; Control IDentifier Group tagging and directory structure settings...
    $CIDaddid3 , _ ; Control IDentifier Checkbox to use tagging or not
    $CIDTagFormat , _ ; Control IDentifier Inputbox for tagging format, example "<Artist> - <Album> - <Title>"
    $CIDrestruct , _ ; Control IDentifier Checkbox to use restructuring or not
    $CIDrestructPattern , _ ; Control IDentifier Inputbox for structure format, example "<Artist>\<Album>\"
    $CIDdstdir , _ ; Control IDentifier Button, select destination directory
    $CIDFileOpen , _ ; Control IDentifier Button, select WAV File(s) and start encoding
    $CIDsuccess , _ ; Control IDentifier Label for a successful encoding of x files in y seconds...
    $CIDlamecommandlabel , _ ; Control IDentifier Label displays encoding settings, such as "lame -m m -V 0 (x4)"
    $CIDhelpdisplay , _ ; Control IDentifier big Editbox displaying help before encoding starts
    $CIDStopNew , _ ; Control IDentifier Button displayed during encoding, don't start more lames
    $CIDKillAll ; Control IDentifier Button displayed during encoding, stop all encoders immediately

    [/autoit] [autoit][/autoit] [autoit]

    Global _ ; Initialized variables read and written from and to program's INI-file. Predefined for missing .ini
    $bitrate = "192" , _ ; CBR bitrate
    $vbrquality = "2" , _ ; VBR quality
    $usevbr = True , _ ; default is VBR
    $mono = False , _ ; default is stereo
    $NumberOfThreads = 4 , _ ; starts 4 instances of Lame simultaneously
    $MaxThreads = 20 , _ ; Maximum number of threads, read only, has to be written manually to INI
    $delsrc = False , _ ; source WAV-file is NOT deleted by default
    $addID3 = False , _ ; no ID3 tag is written by default
    $restruct = False , _ ; no restructuring by default, only destination directory is used
    $TagFormat = "" , _ ; nothing as ID3 tag...
    $restructPattern = "" , _ ; nothing as restrucure pattern...
    $LameLocation = "" , _ ; complete path to lame.exe, such as "d:\utilities\mp3encoder\lame.exe"
    $dstdir = "" , _ ; destination directory for MP3-files
    $LastSrcDir = @WindowsDir & "\" , _ ; Source directory for WAV-files
    $WindowPos[4] = [10, 10, 0, 0] , _ ; Window position will be saved and next time placed there, width and height are ignored
    $changed = True ; flag to indicate a change of the lame command, in order to update the lame command label

    [/autoit] [autoit][/autoit] [autoit]

    Global _ ; ID3 tagging values
    $ID3Artist , _ ; These can only be used if the filename contains these informations!
    $ID3Year , _ ; Also the information must be separated by unique limiters.
    $ID3Album , _ ; The filename is fragmented by these unique limiters one by one.
    $ID3Track , _ ; Example pattern: <Artist> - <Album> - <Year> - <Track#> - <Title>
    $ID3Title , _ ; A valid filename for this pattern:
    $ID3Comment ; Klaus Schulze - Shadowlands - 2013 - 03 - Licht und Schatten.wav

    Global _ ; other stuff
    $lamecommand = "-V 2 " , _ ; encoding settings, may be something like "-b 192 " or "-m m -V 6"
    $SelectedFiles = "" ; returned by the file open dialog/button, example:
    ; "Z:\_Audio_Test|Calexico_(2006) Garden Ruin_01 Cruel.wav|Calexico_(2006) Garden Ruin_02
    ; Yours and Mine.wav|Calexico_(2006) Garden Ruin_03 Bisbee Blue.wav|Harald Grosskopf_(1980)
    ; Synthesist_01 So Weit, So Gut.wav|Harald Grosskopf_(1980) Synthesist_02 B.
    ; Aldrian.wav|Manuel Göttsching_(2005) Die Mulde_01 Schopferische Stille.wav|Manuel
    ; Göttsching_(2005) Die Mulde_02 Die Mulde.wav" (*** all in one line! ***)

    [/autoit] [autoit][/autoit] [autoit]

    Global _ ; help message displayed in big edit control
    $HelpMessage = "Lame Einstellungen:" & @CRLF & _
    " Nutze variable Bitrate für eine konstante Qualität, wobei '0' die beste Qualität bei größten Dateien liefert, während '9' die kleinsten Dateien" & @CRLF & _
    " mit schlechtester Qualität erzeugt. Konstante Bitrate für eine schwankende Qualität, wobei größere Werte bessere Qualität bedeuten." & @CRLF & _
    " Mono z.B. für Hörbücher. Genauer steht's in der Dokumentation zu LAME..." & @CRLF & _
    "" & @CRLF & _
    "System:" & @CRLF & _
    " Anzahl Threads gibt an, wie viele Instanzen von Lame maximal gleichzeitig gestartet werden sollen, je mehr Threads laufen umso schneller sind" & @CRLF & _
    " alle Dateien abgearbeitet. Allerdings läuft immer nur eine Instanz pro Quelldatei. Ein zu hoher Wert macht das System träge." & @CRLF & _
    " Lösche Quelldatei gibt an, ob die Quelldatei (.WAV) nach der Erzeugung des MP3 gelöscht werden soll." & @CRLF & _
    "" & @CRLF & _
    "Tagging und Struktur:" & @CRLF & _
    " Der ID3 Tag gibt an, wie die Metainformationen aus dem Dateinamen gebildet werden sollen und wie diese im Dateinamen getrennt sind." & @CRLF & _
    " Unterstützt werden <Artist>, <Year>, <Album>, <Track#>, <Title> und <Comment>." & @CRLF & _
    " Die Dateinamen müssen genau so aufgebaut sein wie in dem angegebenen Muster." & @CRLF & _
    " Beispielmuster: <Artist>_(<Year>) <Album>_<Track#> <Title>" & @CRLF & _
    " passende Dateinamen:" & @CRLF & _
    " Element of Crime_(2005) Mittelpunkt der Welt_01 Delmenhorst.wav" & @CRLF & _
    " Loney, Dear_(2009) Dear John_07 Summers.wav" & @CRLF & _
    " Struktur gibt an, ob und wie die erzeugten MP3-Dateien unterhalb des Zielverzeichnisses einsortiert werden sollen. Ist kein Zielverzeichnis" & @CRLF & _
    " ausgewählt, gilt das Quellverzeichnis als solches. Als Beispiel nehmen wir das Zielverzeichnis E:\neue Musik\" & @CRLF & _
    " Beispielmuster: <Artist>\<Year> <Album>\" & @CRLF & _
    " Die Dateien von oben würden dann so in den Verzeichnissen " & @CRLF & _
    " E:\neue Musik\Element of Crime\2005 Mittelpunkt der Welt\Element of Crime_(2005) Mittelpunkt der Welt_01 Delmenhorst.mp3" & @CRLF & _
    " E:\neue Musik\Loney, Dear\2009 Dear John\Loney, Dear_(2009) Dear John_07 Summers.mp3" & @CRLF & _
    " zu liegen kommen." & @CRLF & _
    "" & @CRLF & _
    "Auf geht's..."

    ; begin Program ****************************************************************************************************************

    [/autoit] [autoit][/autoit] [autoit]

    LoadIniValues () ; Load user's default values
    CreateGUI () ; Construct Graphical User Interface
    GUISetState(@SW_SHOW, $HdlMainWindow) ; Fire up GUI...
    $CIDsuccess = 0 ; Nothing done so far...
    Do
    $GUImsg = GUIGetMsg()
    If $GUImsg <> 0 Then
    Switch $GUImsg
    Case $CIDvbr ; user switches Radio to use Variable Bitrate Encoding
    GUICtrlDelete( $CIDvbrcbr ) ; delete and re-built control for VBR
    $usevbr = True
    $CIDvbrcbr = GUICtrlCreateCombo ( "", 150, 25, 70, 135)
    GUICtrlSetData ( $CIDvbrcbr, "|0|1|2|3|4|5|6|7|8|9|", $vbrquality)
    $changed = True ; re-display lame command
    Case $CIDcbr ; user switches Radio to use Constant Bitrate Encoding
    GUICtrlDelete( $CIDvbrcbr ) ; delete and re-built control for CBR
    $usevbr = False
    $CIDvbrcbr = GUICtrlCreateCombo ( "", 150, 25, 70, 135)
    GUICtrlSetData ( $CIDvbrcbr, "|8|16|24|32|40|48|56|64|96|112|128|160|192|224|256|320|", $bitrate)
    $changed = True
    Case $CIDmono ; user switches mono on or off
    $mono = NOT $mono
    $changed = True
    Case $CIDvbrcbr ; user selects either vbr-qualitylevel or a constant bitrate
    If $usevbr Then
    $vbrquality = GUICtrlRead ( $CIDvbrcbr )
    Else
    $bitrate = GUICtrlRead ( $CIDvbrcbr )
    EndIf
    $changed = True
    Case $CIDThreads ; changing the number of simultaneously running lames
    $NumberOfThreads = Int ( GUICtrlRead ( $CIDThreads ))
    $changed = True
    Case $CIDdstdir ; select destination directory for mp3-files
    $dstdir = FileSelectFolder ( "Zielverzeichnis auswählen", $dstdir, 4)
    If $dstdir = "" Then
    GUICtrlSetData ( $CIDdstdir, "Zielverzeichnis: (keins gewählt)" )
    Else
    If StringRight ( $dstdir, 1) <> "\" Then $dstdir = $dstdir & "\"
    GUICtrlSetData ( $CIDdstdir, "Zielverzeichnis: " & $dstdir )
    EndIf
    Case $CIDdelsrc ; change of delete source file
    $delsrc = NOT $delsrc
    Case $CIDaddID3 ; change of using ID3 tags
    $addID3 = NOT $addID3
    If $addID3 Then ; enable both the format input box and the restruct checkbox:
    GUICtrlSetState ( $CIDTagFormat, $GUI_ENABLE )
    GUICtrlSetState ( $CIDrestruct, $GUI_ENABLE )
    If $restruct Then ; in case of restruct, check it and enable input box for directory structure:
    GUICtrlSetState ( $CIDrestruct, $GUI_CHECKED )
    GUICtrlSetState ( $CIDrestructPattern, $GUI_ENABLE )
    Else ; no restructuring, uncheck it and disable input box for directory structure:
    GUICtrlSetState ( $CIDrestruct, $GUI_UNCHECKED )
    GUICtrlSetState ( $CIDrestructPattern, $GUI_DISABLE )
    EndIf ; $restruct
    Else ; no ID3 should be added, so disable tag format input box,
    GUICtrlSetState ( $CIDTagFormat, $GUI_DISABLE )
    GUICtrlSetState ( $CIDrestruct, $GUI_UNCHECKED ) ; uncheck restructure checkbox
    GUICtrlSetState ( $CIDrestruct, $GUI_DISABLE ) ; disable restructure checkbox and
    GUICtrlSetState ( $CIDrestructPattern, $GUI_DISABLE ) ; disable input box for directory structure
    EndIf ; $addID3
    Case $CIDrestruct ; change of using subfolders
    $restruct = NOT $restruct
    If $restruct Then ; enable input box
    GUICtrlSetState ( $CIDrestructPattern, $GUI_ENABLE )
    Else ; no subfolders should be used, disable input box:
    GUICtrlSetState ( $CIDrestructPattern, $GUI_DISABLE )
    EndIf ; $restruct
    Case $CIDTagFormat ; user enters a tag format pattern:
    $TagFormat = GUICtrlRead ( $CIDTagFormat )
    Case $CIDrestructPattern ; user enters a subfolder pattern:
    $restructPattern = GUICtrlRead ( $CIDrestructPattern ) ; a check for valid pattern is not done so far!
    Case $CIDFileOpen ; user wants to select source .wav-files and start encoding:
    $SelectedFiles = FileOpenDialog(" Datei(en) auswählen", $LastSrcDir, "Wave-Dateien (*.wav)", 7 )
    If @error <> 0 Then ; user decided to abort file selection:
    MsgBox(0,"Dateiauswahldialog abgebrochen", "Keine Dateien gewählt.")
    $SelectedFiles = ""
    Else ; user has given some files to work on...
    If $CIDsuccess <> 0 Then GUICtrlDelete ( $CIDsuccess ) ; if program has done work already, remove the
    ; label placed by EncoderWork before
    $CIDsuccess = EncoderWork($SelectedFiles, $lamecommand, $dstdir, $NumberOfThreads) ; here we go for it!
    EndIf ; @error <> 0
    EndSwitch
    If $changed Then ; lame command or number of threads have been changed
    $lamecommand = BuildLameCommand() ; re-build lame command and show it
    GuiCtrlSetData ( $CIDlamecommandlabel, "lame " & $lamecommand & " (" & String($NumberOfThreads) & " Threads) using L.A.M.E. encoding engine" )
    $changed = False
    EndIf ; $changed
    EndIf ; $GUImsg <> 0
    Until $GUImsg = $GUI_EVENT_CLOSE ; User has finished and wants to quit...
    SaveIniValues() ; Save user's default values for the next time
    GUIDelete( $HdlMainWindow ) ; Remove GUI
    Exit ; END.

    [/autoit] [autoit][/autoit] [autoit]

    ; end Program ******************************************************************************************************************

    [/autoit] [autoit][/autoit] [autoit]

    Func ID3parse ( $Form, $FileName )
    ; generate a proper command line addition for lame to add id3-tags
    ; $Form looks like: <Artist>_<Album>-<Track#> <Title>
    ; $Filename is the name of the source file ending in .wav, like "Metric_Fantasies-09 Blindness.wav"
    LOCAL $pref ; prefix for lame
    ; Begin ID3parse
    $ID3Artist = "" ; clean up...
    $ID3Year = ""
    $ID3Album = ""
    $ID3Track = ""
    $ID3Title = ""
    $ID3Comment = ""
    $Filename = StringReplace ( $Filename, ".wav", "<wav>", -1, 2) ; easy splitting
    If $Form = "" Then
    Return "" ; no Form given... -> nothing to return
    Else
    $pref = "--ignore-tag-errors --add-id3v2 " ; indicate lame to add id3v2 tags and ignore errors
    $pref = $pref & ID3stacking ( "", $Form, $Filename ) ; get information from Form and Filename...
    EndIf ; $Form = ""
    Return $pref
    EndFunc ; ID3parse ( $Form, $FileName )

    [/autoit] [autoit][/autoit] [autoit]

    Func ID3stacking ( $Carrier, $Form, $Filename ) ; - recursive -
    ; $Carrier contains all previous extraced information, $Form & $Filename as above ( ID3parse )
    ; 1st entry is ID3stacking ( '', '<Artist>_<Album>-<Track#> <Title>', 'Metric_Fantasies-09 Blindness<wav>')
    ; construct main ID3 info from Form and Filename, as "--ta Metric --tl Fantasies --tn 09 --tt Blindness "
    ; last char will be a space, because next parameter (source file.wav) for lame follows (later).

    [/autoit] [autoit][/autoit] [autoit]

    LOCAL _
    $SelectTag, _ ; What do we process? Artist, Year, Album, Track#, Title or Comment?
    $Limiter ; What is between the tags?

    [/autoit] [autoit][/autoit] [autoit]

    ; begin ID3stacking
    If StringLeft ( $Form, 1 ) = "<" Then ; a tagname follows
    $Form = StringTrimLeft ( $Form, 1 ) ; isolate the tagname... Artist>_<Album>-<Track#> <Title>
    $SelectTag = LeftOf ( ">", $Form ) ; Got it in $SelectTag: Artist
    $Form = RightOf ( ">", $Form ) ; we don't need this part of the form anymore, but keep the rest:
    ; _<Album>-<Track#> <Title>
    If $Form <> "" Then ; Something to do...
    $Limiter = LeftOf ( "<", $Form ) ; Got the limiter before the next tag: _
    $Form = RightOf ( $Limiter, $Form ) ; Keep the rest of the form: <Album>-<Track#> <Title>
    Else ; $Form is empty
    $Limiter = "<wav>" ; <wav> is no valid tag, all our filenames given from ID3parse end as <wav>
    EndIf ; $Form <> ""
    Switch $SelectTag ; Extract selected information from Filename and assign properly
    Case "Artist"
    $Carrier = $Carrier & "--ta " ; indicate lame what we want...
    $ID3Artist = LeftOf ( $Limiter, $Filename ) ; This is not needed for adding ID3 tags, but in order to...
    Case "Year"
    $Carrier = $Carrier & "--ty "
    $ID3Year = LeftOf ( $Limiter, $Filename ) ; ...restructure the destination file in subfolders we...
    Case "Album"
    $Carrier = $Carrier & "--tl "
    $ID3Album = LeftOf ( $Limiter, $Filename ) ; ...keep these infos.
    Case "Title"
    $Carrier = $Carrier & "--tt "
    $ID3Title = LeftOf ( $Limiter, $Filename )
    Case "Track#"
    $Carrier = $Carrier & "--tn "
    $ID3Track = LeftOf ( $Limiter, $Filename )
    Case "Comment"
    $Carrier = $Carrier & "--tc "
    $ID3Comment = LeftOf ( $Limiter, $Filename )
    EndSwitch ; $SelectTag

    [/autoit] [autoit][/autoit] [autoit]

    ; Now we put this together with the actual characters from the filename, pretty enclosed in double quotes and...
    $Carrier = $Carrier & Chr(34) & LeftOf ( $Limiter, $Filename ) & Chr(34) & " " ; with a space at the end
    ; $Carrier now looks like '--ta "Metric" '

    [/autoit] [autoit][/autoit] [autoit]

    ; cut off this from the filename and continue with the rest: "Fantasies-09 Blindness<wav>":
    $Filename = RightOf ( $Limiter, $Filename)

    [/autoit] [autoit][/autoit] [autoit]

    ; if more than <wav> is remaining in filename and our pattern has workload left, do it again with our so far
    ; digged cargo - $Filename is more than "<wav>" and $Form is more than or equal to "<Year>":
    If (StringLen ( $Filename ) > 5) And (StringLen( $Form ) > 5) Then $Carrier = ID3stacking ( $Carrier, $Form, $Filename )
    ; 2nd level: ID3stacking ('--ta "Metric" ', '<Album>-<Track#> <Title>', 'Fantasies-09 Blindness<wav>')
    ; 3rd level: ID3stacking ('--ta "Metric" --tl "Fantasies" ', '<Track#> <Title>', '09 Blindness<wav>')
    ; 4th level: ID3stacking ('--ta "Metric" --tl "Fantasies" --tn "09" ', '<Title>', 'Blindness<wav>')
    ; 5th level: ID3stacking ('--ta "Metric" --tl "Fantasies" --tn "09" --tt "Blindness" ', '', '<wav>')
    ; finish ;)
    EndIf ; StringLeft ( $Form, 1 ) = "<"
    Return $Carrier ; Got it for now...
    EndFunc ; ID3stacking ( $Carrier, $Form, $Filename ) - recursive -

    [/autoit] [autoit][/autoit] [autoit]

    Func EncoderWork ( $SelFiles, $lamepar, $dst, $Threads)
    ; Start some threads and heat up the CPU...
    LOCAL _
    $iFile , _ ; index to next source file to process in $FileListArray, starting at 2
    $ActiveThreads , _ ; Number of working lames
    $iProcess , _ ; index to process number we look at in the main loop
    $FileListArray , _ ; will contain all filenames to process, [0] is the quantity + 1, [1] is the path
    $Worktime , _ ; TimerInit / TimerDiff used to tell the user how incredible FAST it's all done...
    $RunCommand , _ ; String with lame and all command-line parameters for it
    $deletedFiles , _ ; counting deleted source files
    $workedFiles , _ ; counting encoded (finished) files
    $Procs[$Threads][4] ; for each lame running, this array contains process data:
    ; [n][0] - PID returned by Run().
    ; Used to (a) check if it is still running and
    ; (b) to kill it in case of user abort
    ; [n][1] - Index to source file in $FileListArray
    ; [n][2] - ControlID of the displayed label during lifetime of PID
    ; [n][3] - Full path and filename of the destination file created by lame - in case of
    ; hard user abortion we need to delete this file because it's incomplete.

    [/autoit] [autoit][/autoit] [autoit]

    ; begin EncoderWork
    $Worktime = TimerInit() ; want to know how long it takes...
    GUICtrlSetState ( $CIDFileOpen, $GUI_DISABLE )
    GUICtrlSetState ( $CIDvbrcbr, $GUI_DISABLE )
    GUICtrlSetState ( $CIDcbr, $GUI_DISABLE )
    GUICtrlSetState ( $CIDvbr, $GUI_DISABLE )
    GUICtrlSetState ( $CIDmono, $GUI_DISABLE )
    GUICtrlSetState ( $CIDThreads, $GUI_DISABLE ) ; at first disable all controls during heavy work...
    GUICtrlSetState ( $CIDdelsrc, $GUI_DISABLE )
    GUICtrlSetState ( $CIDdstdir, $GUI_DISABLE )
    GUICtrlSetState ( $CIDaddid3, $GUI_DISABLE )
    GUICtrlSetState ( $CIDTagFormat, $GUI_DISABLE )
    GUICtrlSetState ( $CIDrestruct, $GUI_DISABLE )
    GUICtrlSetState ( $CIDrestructPattern, $GUI_DISABLE )
    GUICtrlDelete ( $CIDhelpdisplay ) ; help not needed anymore, but the GUIplace of this (large) control
    ; is used for labels of filenames of running lames

    ; New button to stop after finishing the current running threads:
    $CIDStopNew = GUICtrlCreateButton ( "Keine weiteren starten", 10, $GUIheight - 60, 380, 30 )

    [/autoit] [autoit][/autoit] [autoit]

    ; New button to hard stop all threads immediately:
    $CIDKillAll = GUICtrlCreateButton ( "Alles sofort stoppen!", 410, $GUIheight - 60, 380, 30 )
    GUICtrlSetBkColor ( $CIDKillAll, 0xE08080) ; make this one a little red...

    [/autoit] [autoit][/autoit] [autoit]

    $deletedFiles = 0 ; no files deleted so far...
    $workedFiles = 0 ; nothing finished so far...

    [/autoit] [autoit][/autoit] [autoit]

    ; check if there is only one file to work on like "Y:\Audio\Dingsda.wav" and make it look like "Y:\Audio|Dingsda.wav":
    If StringInStr ( $SelFiles,"|") = 0 Then $SelFiles = StringReplace ( $SelFiles, "\", "|", -1)

    [/autoit] [autoit][/autoit] [autoit]

    $FileListArray = StringSplit( $SelFiles, "|") ; all files are now in array elements,
    $FileListArray[1] = $FileListArray[1] & "\" ; $FileListArray[1] - containing the path - needs a backslash
    $ActiveThreads = 0 ; no lame started so far...
    $iFile = 2 ; index points to $FileListArray[2], where we have the first filename
    For $iProcess = 0 To $Threads - 1 ; initialize the Processarray
    $Procs[$iProcess][0] = 0 ; no PID
    $Procs[$iProcess][1] = 0 ; no fileindex
    $Procs[$iProcess][2] = 0 ; no label displayed so far (not really needed to be initialized)
    $Procs[$iProcess][3] = "" ; no destination file so far (not really needed to beinitialized)
    Next ; $iProcess
    If $dst = "" Then $dst = $FileListArray[1] ; User has not selected a destination directory, so it is our source dir.

    [/autoit] [autoit][/autoit] [autoit]

    $iProcess = 0 ; Process index starts from 0
    ; *** Now all preparation is done, here we start to fire up lame instances until all files are encoded ***
    Do ; Loop runs through the processarray 0 - 1 - 2 - 3 - 0 - 1 - 2...
    ; (in case of 4 threads) until all files are processed
    $GUImsg = GUIGetMsg () ; Check if the user wants to stop
    If $GUImsg <> 0 Then
    Switch $GUImsg
    Case $CIDStopNew ; do not start any new lame process
    $iFile = $FileListArray[0] + 1 ; mock all is done, although it's a lie
    GUICtrlSetData ( $CIDStopNew, "Beende nur noch die laufenden...") ; change the button message...
    Case $CIDKillAll ; hard stop of all running lames!
    GUICtrlSetData ( $CIDKillAll, "Terminiere laufende Prozesse...") ; change the button message...
    For $iProcess = 0 To $Threads - 1 ; check all processes
    If ProcessExists ( $Procs[$iProcess][0] ) = $Procs[$iProcess][0] Then ; this one is still running
    ProcessClose ( $Procs[$iProcess][0] ) ; kill it!
    $Procs[$iProcess][1] = -1 ; and mark
    EndIf ; ProcessExists ( $Procs[$iProcess][0] ) = $Procs[$iProcess][0]
    GUICtrlDelete ( $Procs[$iProcess][2] ) ; delete label of process
    Next ; $iProcess
    GUICtrlSetData ( $CIDKillAll, "Lösche unfertige Dateien...") ; user is waiting...
    Sleep($Threads * 250) ; wait while Windows still kills lames
    For $iProcess = 0 To $Threads - 1 ; now check the previously marked processes
    ; If it has been marked, delete the incomplete file:
    If $Procs[$iProcess][1] = -1 Then FileDelete ( $Procs[$iProcess][3])
    Next ; $iProcess
    ExitLoop ( 1 ) ; all is clean now, leave Do-loop running through processarray
    EndSwitch ; $GUImsg
    EndIf ; $GUImsg

    [/autoit] [autoit][/autoit] [autoit]

    ; check for free process, still files left AND number of running threads
    If ($Procs[$iProcess][0] = 0) And ($iFile <= $FileListArray[0]) And ( $ActiveThreads < $Threads) Then
    ; begin to start a new lame...
    $RunCommand = $LameLocation & " " & $lamepar & " " & ID3parse( $TagFormat, $FileListArray[$iFile] ) & _
    Chr(34) & $FileListArray[1] & $FileListArray[$iFile] & chr(34)
    ; so far, we have x:\wherelame\lame.exe -V 1 [--ta "Metric"... ]"Metric_Fantasies-09 Blindness.wav"
    ; As a result of calling ID3parse, $ID3Artist, $ID3Album, $ID3... are set in case of using tagging
    $Procs[$iProcess][3] = $dst ; at least the destination file is placed in destination directory

    ; in case of using subfolders we now add these to destination:
    If $restruct Then $Procs[$iProcess][3] = $Procs[$iProcess][3] & GetNewStruct( $dst )

    ; finally we add the filename ending up in .mp3 instead of .wav
    $Procs[$iProcess][3] = $Procs[$iProcess][3] & StringReplace ( $FileListArray[$iFile], ".wav", ".mp3", -1, 2)

    ; add this to our command line enclosed in double quotes
    $RunCommand = $RunCommand & " " & Chr(34) & $Procs[$iProcess][3] & Chr(34)
    $Procs[$iProcess][0] = Run ( $RunCommand,"",@SW_HIDE) ; lame starts working here!
    $Procs[$iProcess][1] = $iFile ; save source file index
    $Procs[$iProcess][2] = GUICtrlCreateLabel($FileListArray[$iFile], _ ; display a label for the user's eyes
    10 + (BitAND($iProcess, 1) * 400), _ ; x-pos in GUI
    160 + 10 * $iProcess - 10 * BitAND($iProcess, 1), _ ; y-pos in GUI
    390, 15)
    $ActiveThreads += 1 ; one more lame running
    $iFile += 1 ; next file please
    Else ; busy or nothing left to do
    Sleep(10)
    EndIf ;($Procs[$iProcess][0] = 0) And ($iFile <= $FileListArray[0]) And ( $ActiveThreads < $Threads)

    [/autoit] [autoit][/autoit] [autoit]

    ; now for the opposite lane: look for the actual $iProcess if it's finished and was active last time:
    If ($Procs[$iProcess][0] <> 0) And (ProcessExists ( $Procs[$iProcess][0] ) = 0) Then
    $workedFiles += 1 ; one more file done
    $Procs[$iProcess][0] = 0 ; PID done, free it
    If $delsrc Then ; user does not need the source file anymore
    If FileDelete ( $FileListArray[1] & $FileListArray[$Procs[$iProcess][1]] ) Then $deletedFiles += 1
    ; one more source file deleted
    EndIf ; $delsrc
    GUICtrlDelete ( $Procs[$iProcess][2] ) ; remove label displaying filename
    $ActiveThreads -= 1 ; a thread is free
    EndIf ; (ProcessExists ( $Procs[$iProcess][0] ) = 0) And ($Procs[$iProcess][0] <> 0)
    $iProcess += 1 ; next time in Do-loop look at the next process
    If $iProcess >= $Threads Then $iProcess = 0 ; in case of overflow, restart at 0
    Until ($ActiveThreads = 0) And ($iFile > $FileListArray[0]) ; all threads finisehd and all files processed
    $LastSrcDir = $FileListArray[1] ; save this for the next time
    GUICtrlSetState ( $CIDFileOpen, $GUI_ENABLE ) ; re-enable GUI - system is not busy anymore
    GUICtrlSetState ( $CIDvbrcbr, $GUI_ENABLE )
    GUICtrlSetState ( $CIDcbr, $GUI_ENABLE )
    GUICtrlSetState ( $CIDvbr, $GUI_ENABLE )
    GUICtrlSetState ( $CIDmono, $GUI_ENABLE )
    GUICtrlSetState ( $CIDThreads, $GUI_ENABLE )
    GUICtrlSetState ( $CIDdstdir, $GUI_ENABLE )
    GUICtrlSetState ( $CIDdelsrc, $GUI_ENABLE )
    GUICtrlSetState ( $CIDaddid3, $GUI_ENABLE )
    If $addID3 Then
    GUICtrlSetState ( $CIDTagFormat, $GUI_ENABLE )
    GUICtrlSetState ( $CIDrestruct, $GUI_ENABLE )
    If $restruct Then GUICtrlSetState ( $CIDrestructPattern, $GUI_ENABLE )
    EndIf ; $addID3
    GUICtrlDelete ( $CIDStopNew ) ; remove stop button - nothing to stop anymore
    GUICtrlDelete ( $CIDKillAll ) ; remove kill button - nothing to kill anymore

    [/autoit] [autoit][/autoit] [autoit]

    ; re-display help message
    $CIDhelpdisplay = GUICtrlCreateEdit ( $HelpMessage, 30, 150, 740, $GUIheight - 180, BitOr ($ES_READONLY, $ES_AUTOVSCROLL))
    GUICtrlSetBkColor ( $CIDhelpdisplay, 0xD0D0D0 )

    [/autoit] [autoit][/autoit] [autoit]

    $Worktime = TimerDiff ($Worktime) ; finished here
    $Worktime = Round ($Worktime / 1000, 1) ; display time and number of processed files
    Return GUICtrlCreateLabel ("Fertig nach " & String($Worktime) & " s mit " & String($workedFiles) & _
    " (gelöscht: " & String($deletedFiles) & ") Dateien.", 400, $GUIheight - 20, 300, 20)
    ; give back just the controlID of the label - it has to be removed in case of another run
    EndFunc ; EncoderWork ( $SelFiles, $lamepar, $dst, $Threads)

    [/autoit] [autoit][/autoit] [autoit]

    Func CreateGUI()
    LOCAL _
    $i , _
    $ThreadComboMenu = "|"

    [/autoit] [autoit][/autoit] [autoit]

    ; begin CreateGUI
    For $i = 1 To $MaxThreads ; Make a suitable number of threads menu
    $ThreadComboMenu = $ThreadComboMenu & String ( $i ) & "|" ; Example "|1|2|3|4|5|6|7|8|" in case of max 8 threads.
    Next ; $i
    If $NumberOfThreads > $MaxThreads Then $NumberOfThreads = $MaxThreads
    $GUIheight = 220 + ( Round ( $MaxThreads / 2 ) * 20 )
    If $GUIheight < 270 Then $GUIheight = 270
    $HdlMainWindow = GUICreate ( "MultiCoreLame", 800, $GUIheight, $WindowPos[0], $WindowPos[1] )

    [/autoit] [autoit][/autoit] [autoit]

    $CIDlamegroup = GUICtrlCreateGroup ( "Lame Einstellungen", 5, 5, 225, 90 )
    $CIDvbr = GUICtrlCreateRadio ( "variable Bitrate", 20, 27, 100, 20 )
    $CIDcbr = GUICtrlCreateRadio ( "konstante Bitrate", 20, 57, 100, 20 )
    $CIDvbrcbr = GUICtrlCreateCombo ( "", 150, 25, 70, 135 )
    If $usevbr Then
    GUICtrlSetState ( $CIDvbr, $GUI_CHECKED )
    GUICtrlSetData ( $CIDvbrcbr, "|0|1|2|3|4|5|6|7|8|9|", $vbrquality)
    Else
    GUICtrlSetState ( $CIDcbr, $GUI_CHECKED )
    GUICtrlSetData ( $CIDvbrcbr, "|8|16|24|32|40|48|56|64|96|112|128|160|192|224|256|320|", $bitrate )
    EndIf ; $usevbr
    $CIDmono = GUICtrlCreateCheckbox ( "Mono", 150, 57, 60, 20 )
    If $mono Then GUICtrlSetState ( $CIDmono, $GUI_CHECKED )

    [/autoit] [autoit][/autoit] [autoit]

    $CIDsystemgroup = GUICtrlCreateGroup ( "System", 240, 5, 185, 90 )
    $CIDThreadlabel = GUICtrlCreateLabel ( "Anzahl Threads:", 250, 27, 80, 20 )
    $CIDThreads = GUICtrlCreateCombo ( "", 340, 25, 70, 20 )
    GUICtrlSetData ( $CIDThreads, $ThreadComboMenu, String($NumberOfThreads) )
    $CIDdelsrc = GUICtrlCreateCheckbox ( "Lösche Quelldatei", 250, 57, 120, 20 )
    If $delsrc Then GUICtrlSetState ( $CIDdelsrc, $GUI_CHECKED )

    [/autoit] [autoit][/autoit] [autoit]

    $CIDtagginggroup = GUICtrlCreateGroup ( "Tagging und Struktur", 435, 5, 360, 90 )
    $CIDaddid3 = GUICtrlCreateCheckbox ( "ID3 Tag:", 445, 27, 80, 20 )
    $CIDTagFormat = GUICtrlCreateInput ( $TagFormat, 520, 27, 260, 20 )
    $CIDrestruct = GUICtrlCreateCheckbox ("Struktur:", 445, 57, 80, 20 )
    $CIDrestructPattern = GUICtrlCreateInput ( $restructPattern, 520, 57, 260, 20 )
    If $addID3 Then
    GUICtrlSetState ( $CIDaddID3, $GUI_CHECKED )
    Else
    GUICtrlSetState ( $CIDTagFormat, $GUI_DISABLE )
    GUICtrlSetState ( $CIDrestruct, $GUI_DISABLE )
    $restruct = False
    EndIf ; Not $addID3
    If $restruct Then
    GUICtrlSetState ( $CIDrestruct, $GUI_CHECKED )
    Else
    GUICtrlSetState ( $CIDrestruct, $GUI_UNCHECKED )
    GUICtrlSetState ( $CIDrestructpattern, $GUI_DISABLE )
    EndIf ; Not $restruct

    [/autoit] [autoit][/autoit] [autoit]

    GUICtrlCreateGroup ( "", -99, -99, 1, 1)

    [/autoit] [autoit][/autoit] [autoit]

    If $dstdir = "" Then
    $CIDdstdir = GUICtrlCreateButton ( "Zielverzeichnis: (keins gewählt)", 10, 110, 380, 30 )
    Else
    $CIDdstdir = GUICtrlCreateButton ( "Zielverzeichnis: " & $dstdir, 10, 110, 380, 30)
    EndIf
    $CIDFileOpen = GUICtrlCreateButton ( "Dateien auswählen und starten", 410, 110, 380, 30)

    [/autoit] [autoit][/autoit] [autoit]

    $CIDhelpdisplay = GUICtrlCreateEdit ( $HelpMessage, 30, 150, 740, $GUIheight - 180, _
    BitOr ($ES_READONLY, $ES_AUTOVSCROLL))
    GUICtrlSetBkColor ( $CIDhelpdisplay, 0xD0D0D0 )

    [/autoit] [autoit][/autoit] [autoit]

    $lamecommand = BuildLameCommand()
    $CIDlamecommandlabel= GUICtrlCreateLabel ( "", 10, $GUIheight - 20, 380, 18, $BS_CENTER)
    ; GUICtrlSetBkColor ( $CIDlamecommandlabel, 0xFFEEEE)
    EndFunc ; CreateGUI()

    [/autoit] [autoit][/autoit] [autoit]

    Func LoadIniValues()
    LOCAL _
    $iniFilename = @ScriptDir & "\" & "MultiCoreLame.ini"

    ; begin LoadIniValues
    If FileExists ( $iniFilename ) Then
    $bitrate = IniRead ( $iniFilename, "LameParameters", "Bitrate", "192" )
    $usevbr = StringToBool ( IniRead ( $iniFilename, "LameParameters", "VBR", "True" ))
    $vbrquality = IniRead ( $iniFilename, "LameParameters", "VBRquality", "2" )
    $mono = StringToBool ( IniRead ( $iniFilename, "LameParameters", "ModeMono", "False" ))
    $LameLocation = IniRead ( $iniFilename, "System", "Encoder", "" )
    $NumberOfThreads= Int ( IniRead ( $iniFilename, "System", "Threads", "4" ))
    $MaxThreads = Int ( IniRead ( $iniFilename, "System", "MaxThreads", "20" ))
    $dstdir = IniRead ( $iniFilename, "System", "DestinationDirectory", "" )
    $LastSrcDir = IniRead ( $iniFilename, "System", "LastSourceDirectory", _
    @WindowsDir & "\" )
    $delsrc = StringToBool ( IniRead ( $iniFilename, "System", "DeleteSourceFile", "False" ))
    $WindowPos[0] = Int ( IniRead ( $iniFilename, "System", "WindowPosX", 10))
    $WindowPos[1] = Int ( IniRead ( $iniFilename, "System", "WindowPosY", 10))
    $addID3 = StringToBool ( IniRead ( $iniFilename, "Tagging", "addID3", "False" ))
    $TagFormat = IniRead ( $iniFilename, "Tagging", "Format", "" )
    $restruct = StringToBool ( IniRead ( $iniFilename, "Tagging", "Restructure", "False" ))
    $restructPattern= IniRead ( $iniFilename, "Tagging", "RestructPattern", "" )
    EndIf ; FileExists ( $iniFilename )
    ; if inifile does not exist, it doesn't matter - BUT:
    ; Need to know where lame.exe is:
    If $LameLocation = "" Then
    If FileExists ( @ScriptDir & "\" & "lame.exe" ) Then ; fine, found it just there
    $LameLocation = @ScriptDir & "\" & "lame.exe"
    Else ; ask user for lame.exe location:
    $LameLocation = FileOpenDialog ("Zeige mir die Lame.Exe", @ScriptDir & "\", "Lame.exe (lame.exe)", _
    BitOr ( $FD_FILEMUSTEXIST , $FD_PATHMUSTEXIST ) )
    If @error = 1 Then ; File selection failed
    MsgBox(0,"Fataler Fehler", "Tut mir leid, ohne LAME.EXE kann ich nicht arbeiten")
    Exit ; without lame.exe this script is senseless - we're off
    EndIf
    EndIf ; FileExists ( @ScriptDir & "\" & "lame.exe" )
    EndIf ; $LameLocation = ""
    EndFunc ; LoadIniValues()

    [/autoit] [autoit][/autoit] [autoit]

    #cs

    [/autoit] [autoit][/autoit] [autoit]

    ********************* primitives following *********************

    [/autoit] [autoit][/autoit] [autoit]

    #ce

    [/autoit] [autoit][/autoit] [autoit]

    Func GetNewStruct ( $dst )
    LOCAL $path
    ; begin GetNewStruct
    $path = $RestructPattern
    $path = StringReplace ( $path, "<Artist>", $ID3Artist )
    $path = StringReplace ( $path, "<Album>", $ID3Album )
    $path = StringReplace ( $path, "<Year>", $ID3Year )
    $path = StringReplace ( $path, "<Track#>", $ID3Track )
    $path = StringReplace ( $path, "<Title>", $ID3Title )
    $path = StringReplace ( $path, "<Comment>", $ID3Comment )
    $path = StringReplace ( $path, "\\", "\" )
    If StringRight ( $path, 1 ) <> "\" Then $path = $path & "\"
    If Not FileExists ( $dst & $path ) Then DirCreate ( $dst & $path )
    Return $path
    EndFunc ; GetNewStruct ( $dst )

    [/autoit] [autoit][/autoit] [autoit]

    Func SaveIniValues()
    LOCAL $iniFilename = @ScriptDir & "\" & "MultiCoreLame.ini"
    ; begin SaveIniValues
    $WindowPos = WinGetPos ( $HdlMainWindow )
    If $dstdir = "" Then $dstdir = $LastSrcDir
    IniWrite ( $iniFilename, "LameParameters", "Bitrate", $bitrate )
    IniWrite ( $iniFilename, "LameParameters", "VBR", $usevbr)
    IniWrite ( $iniFilename, "LameParameters", "VBRquality", $vbrquality)
    IniWrite ( $iniFilename, "LameParameters", "ModeMono", $mono)
    IniWrite ( $iniFilename, "System", "Encoder", $LameLocation)
    IniWrite ( $iniFilename, "System", "Threads", String( $NumberOfThreads ))
    IniWrite ( $iniFilename, "System", "DestinationDirectory", $dstdir)
    IniWrite ( $iniFilename, "System", "LastSourceDirectory", $LastSrcDir)
    IniWrite ( $iniFilename, "System", "DeleteSourceFile", $delsrc)
    IniWrite ( $iniFilename, "System", "WindowPosX", String( $WindowPos[0] ))
    IniWrite ( $iniFilename, "System", "WindowPosY", String( $WindowPos[1] ))
    IniWrite ( $iniFilename, "Tagging", "addID3", $addID3 )
    IniWrite ( $iniFilename, "Tagging", "Format", $TagFormat )
    IniWrite ( $iniFilename, "Tagging", "Restructure", $restruct )
    IniWrite ( $iniFilename, "Tagging", "RestructPattern", $restructPattern )
    EndFunc ; SaveIniValues()

    [/autoit] [autoit][/autoit] [autoit]

    Func BuildLameCommand()
    LOCAL $commandstring
    ; begin BuildLameCommand
    If $mono Then
    $commandstring = "-m m "
    Else
    $commandstring = ""
    EndIf
    If $usevbr Then
    $commandstring = $commandstring & "-V " & String ( $vbrquality ) & " "
    Else
    $commandstring = $commandstring & "-b " & String ( $bitrate ) & " "
    EndIf
    Return $commandstring
    EndFunc ; BuildLameCommand()

    [/autoit] [autoit][/autoit] [autoit]

    Func StringToBool($check)
    If ($check = "True") Or ($check = "true") Or ($check = "TRUE") Then
    Return True
    Else
    Return False
    EndIf
    EndFunc ; StringToBool($check)

    [/autoit] [autoit][/autoit] [autoit]

    Func LeftOf ( $sub, $instr)
    LOCAL $p
    $p = StringInStr ( $instr, $sub )
    If $p > 1 Then
    Return StringLeft ( $instr, $p - 1 )
    Else
    Return ""
    EndIf
    EndFunc ; LeftOf ( $sub, $instr)

    [/autoit] [autoit][/autoit] [autoit]

    Func RightOf ( $sub, $instr)
    LOCAL $p
    $p = StringInStr ( $instr, $sub )
    If ($p > 0) And ($p < StringLen ( $instr )) Then
    Return StringRight ( $instr, StringLen ( $instr ) - ($p + (StringLen ( $sub ) - 1)))
    Else
    Return ""
    EndIf
    EndFunc ; RightOf ( $sub, $instr)

    [/autoit] [autoit][/autoit] [autoit]

    #cs

    [/autoit] [autoit][/autoit] [autoit]

    ********************* end primitives *********************

    [/autoit] [autoit][/autoit] [autoit]

    #ce

    [/autoit] [autoit][/autoit] [autoit]

    #cs

    [/autoit] [autoit][/autoit] [autoit]

    ********************* Debug *******************************

    [/autoit] [autoit][/autoit] [autoit]

    Func WriteLog ( $msg )
    FileWriteLine ( @ScriptDir & "\" & "MultiCoreLame.log", @YEAR & @MON & @MDAY & @HOUR & @MIN & @SEC & @MSEC & ": <" & $msg & ">" )
    EndFunc ; WriteLog ( $msg )

    [/autoit] [autoit][/autoit] [autoit]

    #ce

    [/autoit]

    Die geschriebene .INI-Datei, die im selben Verzeichnis wie das Script zu liegen kommt, sieht dann ungefähr so aus:

    Spoiler anzeigen

    Die bitte NICHT hier wechkopieren, weil der Kram auf Eurem System nicht paßt, es ist hier nur zur Ansicht!

    Jaja, ich weiß:
    * Es gibt schon drölfhausent Fantastilliarden Frontends für Lame. (Ja, aber die gefielen mir nicht so recht)
    * Foobar2000 kann das auch, mit der Nutzung aller Prozessorkerne. (Ja, aber bei genügend Threads ist mein Script schneller ;) )
    * Das Script könnte unter bestimmten Umständen vielleicht fehlerhaft arbeiten. (Ja, gerne nehme ich Hinweise entgegen. So'n Ding ist halt "nie" fertig)
    * Es haben sich schon welche totformatiert. (ich wollt's grad' übersichtlich halten)
    * Es haben sich schon welche totkommentiert. (ist klar, der wahre AutoIt-Profi liest so'n bischen Code morgens mit halbem Auge noch vor dem ersten Kaffee runter und hat schon 42 Bugs gefunden, davon 23 tödliche... - ich bin aber kein solcher Nerd und wenn ich "das Ding" ein halbes Jahr nicht angesehen habe, verstehe ich mein eigenes Gefummel da nicht mehr... außerdem KÖNNTE es vielleicht sein, daß ein Neuling (zu denen ich mich zähle) es so etwas einfacher hat, den fremden Quelltext zu verstehen und womöglich etwas abzugucken.

    Nun setze ich mich ganz bewußt Eurer vernichtenden Kritik aus, um (vielleicht) noch die groben Böcke (?) um die Ohren gehauen zu bekommen...

    Gruß Moon