1. Dashboard
  2. Mitglieder
    1. Letzte Aktivitäten
    2. Benutzer online
    3. Team
    4. Mitgliedersuche
  3. Forenregeln
  4. Forum
    1. Unerledigte Themen
  • Anmelden
  • Registrieren
  • Suche
Alles
  • Alles
  • Artikel
  • Seiten
  • Forum
  • Erweiterte Suche
  1. AutoIt.de - Das deutschsprachige Forum.
  2. Mitglieder
  3. Oscar

Beiträge von Oscar

  • mp3 Searcher

    • Oscar
    • 1. August 2010 um 10:42

    Das Programm ist nun soweit fertig. Ist eine ganze Menge hinzugekommen. :D

    Ich habe mal den Post #1 geändert. Dort ist das Programm (inkl. Skript und Icons) jetzt zu finden.

  • Media Center

    • Oscar
    • 31. Juli 2010 um 22:27

    L3viathan: Eine andere Möglichkeit wäre _GetIP() oder mit TCPNameToIP, also etwas so:

    [autoit]


    MsgBox(0,0, _IsOnline())

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

    Func _IsOnline()
    TCPStartup()
    $ret = TCPNameToIP('www.google.de')
    TCPShutdown()
    Return SetError(@error, 0, $ret <> '')
    EndFunc

    [/autoit]
  • mp3 Searcher

    • Oscar
    • 30. Juli 2010 um 21:58

    Du hast recht, die Suche innerhalb der Liste bzw. die Anzeige des Ergebnisses gefiel mir auch nicht so richtig. Nur markieren ist blöd, weil man nicht alle Suchergebnisse überblicken kann.
    Ich habe jetzt ein zweites Listview (das ist erstmal versteckt und wird nur als Ergebnis angezeigt) erstellt und da kommen dann die Suchergebnisse rein. Das gefällt mir viel besser. ^^

    Außerdem habe ich jetzt die großen Buttons (zum einlesen der MP3s, laden und speichern usw.) oberhalb der Liste angeordnet. Die SuFu ist weiterhin unterhalb. So sieht das übersichtlicher aus, finde ich.

    Ich habe auch noch an verschiedenen Ecken an der Geschwindigkeit gefeilt. Das einlesen der MP3s und das sortieren nach Listviewspalte geht jetzt schneller vonstatten.

    Eine Progressbar in die Statusleiste packen geht zwar, aber da gibt es Probleme mit dem Resizing (die Progressbar bleibt nicht da, wo sie hingehört). Vielleicht mache ich aber noch eine Progressbar außerhalb der Statusleiste?! :S

    Skript:

    Spoiler anzeigen
    [autoit]


    #include <Array.au3>
    #include <ButtonConstants.au3>
    #include <Date.au3>
    #include <GUIConstantsEx.au3>
    #include <GuiListView.au3>
    #include <GuiStatusBar.au3>
    #include <ListViewConstants.au3>
    #include <ProgressConstants.au3>
    #include <StaticConstants.au3>
    #include <StructureConstants.au3>
    #include <WindowsConstants.au3>

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

    Global $sHeader = 'Title|Artist|Length|Album|Year|MPEG-Version|Bitrate|Sample-Freq.|Path' ; Die Überschriften für das Listview
    Global $sInifile = @ScriptDir & '\MP3-Search.ini' ; Inidatei

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

    Global $iWidth = IniRead($sInifile, 'Config', 'Width', 770)
    Global $iHeight = IniRead($sInifile, 'Config', 'Height', 406)
    Global $iLeft = IniRead($sInifile, 'Config', 'Left', @DesktopWidth / 2 - 385)
    Global $iTop = IniRead($sInifile, 'Config', 'Top', @DesktopHeight / 2 - 203)

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

    #region Hauptfenster
    Global $sStyle = BitOR($GUI_SS_DEFAULT_GUI, $WS_MAXIMIZEBOX, $WS_SIZEBOX)
    Global $hGui = GUICreate('MP3-Search', 770, 406, $iLeft, $iTop, $sStyle) ; Hauptfenster erstellen
    GUISetBkColor(0xAAAAAA)

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

    Global $hListView = GUICtrlCreateListView($sHeader, 5, 55, 760, 240, $LVS_SHOWSELALWAYS, BitOR($LVS_EX_FULLROWSELECT, $WS_EX_WINDOWEDGE)) ; Listview erstellen
    GUICtrlSetResizing(-1, 2 + 4 + 32 + 64)
    GUICtrlSetBkColor(-1, 0xffffff)
    Global $hLVHandle = GUICtrlGetHandle($hListView) ; das Handle vom Listview wird für die UDF-Listview-Funktionen benötigt
    _GUICtrlListView_SetColumnWidth($hLVHandle, 0, 180)
    _GUICtrlListView_SetColumnWidth($hLVHandle, 1, 180)
    _GUICtrlListView_SetColumnWidth($hLVHandle, 2, 60)
    _GUICtrlListView_SetColumnWidth($hLVHandle, 3, 120)
    _GUICtrlListView_SetColumnWidth($hLVHandle, 4, 60)
    _GUICtrlListView_SetColumnWidth($hLVHandle, 5, 100)
    _GUICtrlListView_SetColumnWidth($hLVHandle, 6, 100)
    _GUICtrlListView_SetColumnWidth($hLVHandle, 7, 90)
    _GUICtrlListView_SetColumnWidth($hLVHandle, 8, 800)

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

    Global $hSearchListView = GUICtrlCreateListView($sHeader, 5, 55, 760, 240, $LVS_SHOWSELALWAYS, BitOR($LVS_EX_FULLROWSELECT, $WS_EX_WINDOWEDGE)) ; Listview erstellen
    GUICtrlSetResizing(-1, 2 + 4 + 32 + 64)
    GUICtrlSetBkColor(-1, 0xaaffbb)
    Global $hSearchLVHandle = GUICtrlGetHandle($hSearchListView) ; das Handle vom Listview wird für die UDF-Listview-Funktionen benötigt
    _GUICtrlListView_SetColumnWidth($hSearchLVHandle, 0, 180)
    _GUICtrlListView_SetColumnWidth($hSearchLVHandle, 1, 180)
    _GUICtrlListView_SetColumnWidth($hSearchLVHandle, 2, 60)
    _GUICtrlListView_SetColumnWidth($hSearchLVHandle, 3, 120)
    _GUICtrlListView_SetColumnWidth($hSearchLVHandle, 4, 60)
    _GUICtrlListView_SetColumnWidth($hSearchLVHandle, 5, 100)
    _GUICtrlListView_SetColumnWidth($hSearchLVHandle, 6, 100)
    _GUICtrlListView_SetColumnWidth($hSearchLVHandle, 7, 90)
    _GUICtrlListView_SetColumnWidth($hSearchLVHandle, 8, 800)
    GUICtrlSetState($hSearchListView, $GUI_HIDE)

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

    GUICtrlCreateGroup('', 5, 300, 760, 75)
    GUICtrlSetResizing(-1, 512 + 64)
    GUICtrlCreateLabel('Suchbegriff:', 15, 322, 70, 22, $SS_RIGHT)
    GUICtrlSetFont(-1, 10)
    GUICtrlSetResizing(-1, 512 + 64)
    Global $hInput = GUICtrlCreateInput('', 90, 320, 300, 22)
    GUICtrlSetFont(-1, 10)
    GUICtrlSetResizing(-1, 512 + 64)
    Global $hInputOk = GUICtrlCreateButton('Suche starten', 400, 320, 100, 22, $BS_DEFPUSHBUTTON)
    GUICtrlSetFont(-1, 10)
    GUICtrlSetResizing(-1, 512 + 64)
    Global $hCaseSens = GUICtrlCreateCheckbox('Groß-/Kleinschreibung beachten', 90, 345, 240, 22)
    GUICtrlSetFont(-1, 10)
    GUICtrlSetResizing(-1, 512 + 64)
    GUICtrlCreateGroup('', -99, -99, 1, 1)

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

    Global $hSearch = GUICtrlCreateButton('Alle Festplatten durchsuchen', 10, 10, 100, 35, $BS_MULTILINE)
    GUICtrlSetResizing(-1, 512 + 32)
    Global $hSearchPath = GUICtrlCreateButton('Verzeichnis durchsuchen', 120, 10, 80, 35, $BS_MULTILINE)
    GUICtrlSetResizing(-1, 512 + 32)
    Global $hLoad = GUICtrlCreateButton('Liste laden', 230, 10, 70, 35, $BS_MULTILINE)
    GUICtrlSetResizing(-1, 512 + 32)
    Global $hSave = GUICtrlCreateButton('Liste speichern', 310, 10, 70, 35, $BS_MULTILINE)
    GUICtrlSetResizing(-1, 512 + 32)
    Global $hDel = GUICtrlCreateButton("Markierte Einträge löschen", 410, 10, 90, 35, $BS_MULTILINE)
    GUICtrlSetResizing(-1, 512 + 32)
    GUICtrlSetState(-1, $GUI_DISABLE)
    Global $hDelAll = GUICtrlCreateButton('Alle Einträge löschen', 510, 10, 90, 35, $BS_MULTILINE)
    GUICtrlSetResizing(-1, 512 + 32)

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

    Global $aParts[3] = [300, 360, -1], $aText[3] = ['Fertig.', '0', '']
    Global $hStatus = _GUICtrlStatusBar_Create($hGui, $aParts, $aText, $SBARS_SIZEGRIP)
    _GUICtrlStatusBar_SetSimple($hStatus, False)
    _GUICtrlStatusBar_SetMinHeight($hStatus, 20)
    #endregion Hauptfenster

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

    GUISetState(@SW_SHOW, $hGui) ; Hauptfenster sichtbar machen

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

    Global $fStop = False, $iSearchIndex = -1, $iSelCount, $iSelOld, $aListview
    HotKeySet('{ESC}', '_Stop')

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

    Dim $aAccelKeys[1][2] = [['{DEL}', $hDel]] ; beim drücken der [Delete]-Taste wird "Case $hDel" ausgeführt
    GUISetAccelerators($aAccelKeys, $hGui)

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

    GUIRegisterMsg($WM_SIZE, '_WM_SIZE')
    GUIRegisterMsg($WM_MOVE, '_WM_MOVE')
    GUIRegisterMsg($WM_GETMINMAXINFO, '_WM_GETMINMAXINFO')
    GUIRegisterMsg($WM_NOTIFY, '_WM_NOTIFY')
    GUIRegisterMsg($WM_COMMAND, '_WM_COMMAND')

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

    WinMove($hGui, '', $iLeft, $iTop, $iWidth, $iHeight)

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

    While 1
    Switch GUIGetMsg() ; anhand der Control-ID das entsprechende Case aufrufen
    Case $hSearch
    _GUICtrlListView_DeleteAllItems($hLVHandle) ; Alle Listview-Einträge löschen
    _GUICtrlStatusBar_SetText($hStatus, 0, 1)
    $iLVCount = 0 ; Zähler auf Null setzen
    $aDrives = DriveGetDrive('FIXED') ; Alle Festplatten-Buchstaben holen
    If Not @error Then
    GUISetCursor(15, 1, $hGui)
    For $i = 1 To $aDrives[0] ; Alle Festplatten durchgehen
    _GUICtrlStatusBar_SetText($hStatus, 'Durchsuche Festplatte "' & StringUpper($aDrives[$i]) & '\"', 0)
    _DriveSearch(StringUpper($aDrives[$i]))
    Next
    GUISetCursor(2, 1, $hGui)
    EndIf
    _GUICtrlStatusBar_SetText($hStatus, _GUICtrlListView_GetItemCount($hLVHandle), 1)
    _GUICtrlStatusBar_SetText($hStatus, '', 2)
    If $fStop Then
    $fStop = False
    _GUICtrlStatusBar_SetText($hStatus, 'Abgebrochen!', 0)
    Else
    _GUICtrlStatusBar_SetText($hStatus, 'Fertig.', 0)
    EndIf
    Case $hSearchPath
    $sPath = FileSelectFolder('Verzeichnis auswählen!', '', 2, '', $hGui)
    If FileExists($sPath) Then
    _GUICtrlListView_DeleteAllItems($hLVHandle) ; Alle Listview-Einträge löschen
    $iLVCount = 0 ; Zähler auf Null setzen
    GUISetCursor(15, 1, $hGui)
    _GUICtrlStatusBar_SetText($hStatus, 'Durchsuche Verzeichnis "' & $sPath & '"', 0)
    _DriveSearch($sPath)
    GUISetCursor(2, 1, $hGui)
    _GUICtrlStatusBar_SetText($hStatus, _GUICtrlListView_GetItemCount($hLVHandle), 1)
    _GUICtrlStatusBar_SetText($hStatus, '', 2)
    If $fStop Then
    $fStop = False
    _GUICtrlStatusBar_SetText($hStatus, 'Abgebrochen!', 0)
    Else
    _GUICtrlStatusBar_SetText($hStatus, 'Fertig.', 0)
    EndIf
    EndIf
    Case $hInputOk
    ControlFocus($hGui, '', $hInputOk)
    _GUICtrlStatusBar_SetText($hStatus, 'Suche in Liste...', 0)
    GUISetCursor(15, 1, $hGui)
    _LVSearch()
    GUISetCursor(2, 1, $hGui)
    _GUICtrlStatusBar_SetText($hStatus, 'Fertig.', 0)
    Case $hListView ; User hat auf eine Spaltenüberschrift geklickt (sortieren)
    If _GUICtrlListView_GetItemCount($hLVHandle) > 0 Then
    GUISetCursor(15, 1, $hGui)
    $iTimer = TimerInit()
    _GUICtrlStatusBar_SetText($hStatus, '', 2)
    _GUICtrlStatusBar_SetText($hStatus, 'Sortiere Daten! Bitte warten...', 0)
    If Not IsArray($aListview) Then
    $iCount = _GUICtrlListView_GetItemCount($hLVHandle)
    Dim $aListview[$iCount][9]
    For $i = 0 To $iCount - 1
    For $j = 0 To 8
    $aListview[$i][$j] = ControlListView($hGui, '', $hListView, 'GetText', $i, $j)
    Next
    Next
    EndIf
    _ArraySort($aListview, 0, 0, 0, GUICtrlGetState($hListView))
    _GUICtrlListView_DeleteAllItems($hLVHandle)
    _GUICtrlListView_AddArray($hLVHandle, $aListview)
    _GUICtrlStatusBar_SetText($hStatus, _TicksToTimeFormat(TimerDiff($iTimer), '%mm:%ss.%ms'), 2)
    _GUICtrlStatusBar_SetText($hStatus, 'Fertig.', 0)
    GUISetCursor(2, 1, $hGui)
    EndIf
    Case $hLoad ; User hat auf 'Laden' geklickt
    GUISetCursor(15, 1, $hGui)
    _GUICtrlStatusBar_SetText($hStatus, 'Lade Daten...', 0)
    Load()
    _GUICtrlStatusBar_SetText($hStatus, 'Fertig.', 0)
    GUISetCursor(2, 1, $hGui)
    $aListview = ''
    Case $hSave ; User hat auf 'Speichern' geklickt
    GUISetCursor(15, 1, $hGui)
    _GUICtrlStatusBar_SetText($hStatus, 'Speichere Daten...', 0)
    Save()
    _GUICtrlStatusBar_SetText($hStatus, 'Fertig.', 0)
    _GUICtrlStatusBar_SetText($hStatus, '', 2)
    GUISetCursor(2, 1, $hGui)
    Case $hDel
    If MsgBox(256 + 32 + 4, 'Markierte Einträge löschen', 'Wollen sie wirklich die markierten Einträge löschen?') = 6 Then
    GUISetCursor(15, 1, $hGui)
    _GUICtrlListView_DeleteItemsSelected($hLVHandle)
    _GUICtrlStatusBar_SetText($hStatus, _GUICtrlListView_GetItemCount($hLVHandle), 1)
    GUISetCursor(2, 1, $hGui)
    $aListview = ''
    EndIf
    Case $hDelAll ; User hat auf 'Alle Einträge löschen' geklickt
    If MsgBox(256 + 32 + 4, 'Einträge löschen', 'Wollen sie wirklich alle Einträge löschen?') = 6 Then
    _GUICtrlListView_DeleteAllItems($hLVHandle)
    _GUICtrlStatusBar_SetText($hStatus, 0, 1)
    $aListview = ''
    EndIf
    Case $GUI_EVENT_CLOSE ; User hat auf das Schließen-Symbol geklickt
    ;~ If MsgBox(32 + 4, 'Save', 'Wollen sie vor beenden noch Speichern?') = 6 Then Save()
    Exit ; Programm beenden
    EndSwitch
    $iSelCount = _GUICtrlListView_GetSelectedCount($hLVHandle) ; Anzahl der markierten Items holen
    If $iSelCount <> $iSelOld Then ; vergleichen ob der Wert vom vorherigen abweicht (Flackern vermeiden)
    $iSelOld = $iSelCount ; wenn ja, dann alten gleich neuen Wert
    If $iSelCount > 0 Then ; wenn Einträge markiert sind
    GUICtrlSetState($hDel, $GUI_ENABLE) ; dann Button aktivieren
    GUICtrlSetData($hDel, StringFormat('(%i) Markierte Einträge löschen', $iSelCount)) ; und den Text auf dem Button anpassen
    Else ; keine Einträge markiert
    GUICtrlSetState($hDel, $GUI_DISABLE) ; dann Button deaktivieren
    GUICtrlSetData($hDel, 'Markierte Einträge löschen') ; und den Text auf dem Button anpassen
    EndIf
    EndIf
    WEnd

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

    Func _Stop()
    $fStop = True
    EndFunc ;==>_Stop

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

    Func _DriveSearch($sPath)
    Local $aNewMP3, $aID3Tags, $sNewItem, $aItem, $iTimer = TimerInit(), $iCount = _GUICtrlListView_GetItemCount($hLVHandle)
    If StringRight($sPath, 1) <> '\' Then $sPath &= '\'
    _GUICtrlStatusBar_SetText($hStatus, 'Bitte warten...', 2)
    $aNewMP3 = _RecursiveFileListToArray($sPath, '\.mp3', 1) ; Alle MP3s auf der Festplatte auslesen
    If Not @error And $aNewMP3[0] > 0 Then
    _GUICtrlListView_SetItemCount($hListView, $iCount + $aNewMP3[0])
    _GUICtrlStatusBar_SetText($hStatus, 'Lese ID3-Tags... (' & $aNewMP3[0] & ')', 0)
    For $j = 1 To $aNewMP3[0] ; die gefundenen MP3s durchgehen
    $aID3Tags = _ReadID3Tag($aNewMP3[$j]) ; die ID3-Tags auslesen
    If Not @error Then
    For $k = 0 To 10
    $aID3Tags[$k][1] = StringReplace($aID3Tags[$k][1], '|', '') ; evtl. vorhandene "|" entfernen
    Next
    If TimerDiff($iTimer) > 50 Then
    $iTimer = TimerInit()
    _GUICtrlStatusBar_SetText($hStatus, $iCount + $j, 1)
    _GUICtrlStatusBar_SetText($hStatus, $aNewMP3[$j], 2)
    EndIf
    $sNewItem = $aID3Tags[0][1] & '|' & $aID3Tags[1][1] & '|' & $aID3Tags[4][1] & '|' & $aID3Tags[2][1] & '|' & $aID3Tags[3][1]
    $sNewItem &= '|' & $aID3Tags[8][1] & '|' & $aID3Tags[9][1] & '|' & $aID3Tags[10][1] & '|' & $aNewMP3[$j]
    GUICtrlCreateListViewItem($sNewItem, $hListView)
    EndIf
    If $fStop Then ExitLoop
    Next
    _GUICtrlStatusBar_SetText($hStatus, _GUICtrlListView_GetItemCount($hLVHandle), 1)
    EndIf
    EndFunc ;==>_DriveSearch

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

    Func _WM_COMMAND($hWnd, $msg, $wParam, $lParam)
    Local $nNotifyCode = BitShift($wParam, 16)
    Local $nID = BitAND($wParam, 0xFFFF)
    If $nID = $hInput And $nNotifyCode = 256 Then
    GUICtrlSetState($hSearchListView, $GUI_HIDE)
    GUICtrlSetState($hListView, $GUI_SHOW)
    GUICtrlSetBkColor($hInput, 0xffffff)
    GUICtrlSetData($hInput, '')
    GUICtrlSetState($hInputOk, $GUI_ENABLE)
    _GUICtrlStatusBar_SetText($hStatus, '', 2)
    _GUICtrlListView_SetItemSelected($hLVHandle, -1, False)
    EndIf
    Return $GUI_RUNDEFMSG
    EndFunc ;==>_WM_COMMAND

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

    Func _LVSearch()
    Local $sSearch, $iTimer, $iCount, $iCase, $iFound, $sMsg = ' Einträge'
    $iCount = _GUICtrlListView_GetItemCount($hLVHandle)
    If $iCount = 0 Then Return
    $sSearch = GUICtrlRead($hInput)
    If $sSearch = '' Then Return
    _GUICtrlListView_SetItemSelected($hLVHandle, -1, False)
    _GUICtrlListView_DeleteAllItems($hSearchLVHandle)
    $iCase = Number(BitAND(GUICtrlRead($hCaseSens), $GUI_CHECKED) = $GUI_CHECKED)
    $iTimer = TimerInit()
    For $i = 0 To $iCount - 1
    $sItem = ''
    For $j = 0 To 8
    $sItem &= ControlListView($hGui, '', $hListView, 'GetText', $i, $j) & '|'
    Next
    If StringInStr($sItem, $sSearch, $iCase) Then GUICtrlCreateListViewItem(StringTrimRight($sItem, 1), $hSearchListView)
    If TimerDiff($iTimer) > 100 Then
    $iTimer = TimerInit()
    _GUICtrlStatusBar_SetText($hStatus, $i, 2)
    EndIf
    Next
    GUICtrlSetState($hInputOk, $GUI_DISABLE)
    $iFound = _GUICtrlListView_GetItemCount($hSearchLVHandle)
    If $iFound = 1 Then $sMsg = ' Eintrag'
    _GUICtrlStatusBar_SetText($hStatus, $iFound & $sMsg & ' gefunden', 2)
    If $iFound Then
    GUICtrlSetBkColor($hInput, 0xaaffaa)
    GUICtrlSetState($hSearchListView, $GUI_SHOW)
    GUICtrlSetState($hListView, $GUI_HIDE)
    Else
    GUICtrlSetBkColor($hInput, 0xffaaaa)
    EndIf
    EndFunc ;==>_LVSearch

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

    Func _WM_NOTIFY($hWnd, $msg, $wParam, $lParam)
    Local $hWndFrom, $iIDFrom, $iCode, $tNMHDR, $iSelected, $sExecutePath
    $tNMHDR = DllStructCreate($tagNMHDR, $lParam)
    $hWndFrom = HWnd(DllStructGetData($tNMHDR, 'hWndFrom'))
    $iCode = DllStructGetData($tNMHDR, 'Code')
    Switch $hWndFrom
    Case $hLVHandle
    Switch $iCode
    Case $NM_DBLCLK
    $iSelected = ControlListView($hGui, '', $hListView, 'GetSelected')
    $sExecutePath = _GUICtrlListView_GetItemText($hLVHandle, $iSelected, 8)
    ShellExecute($sExecutePath)
    EndSwitch
    Case $hSearchLVHandle
    Switch $iCode
    Case $NM_DBLCLK
    $iSelected = ControlListView($hGui, '', $hSearchListView, 'GetSelected')
    $sExecutePath = _GUICtrlListView_GetItemText($hSearchLVHandle, $iSelected, 8)
    ShellExecute($sExecutePath)
    EndSwitch
    EndSwitch
    Return $GUI_RUNDEFMSG
    EndFunc ;==>_WM_NOTIFY

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

    Func _WM_SIZE($hWnd, $msg, $wParam, $lParam)
    Local $aGuiPos = WinGetPos($hGui)
    If Not BitAND(WinGetState($hGui), 16) Then
    IniWrite($sInifile, 'Config', 'Width', $aGuiPos[2])
    IniWrite($sInifile, 'Config', 'Height', $aGuiPos[3])
    EndIf
    _GUICtrlStatusBar_Resize($hStatus)
    Return $GUI_RUNDEFMSG
    EndFunc ;==>_WM_SIZE

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

    Func _WM_MOVE($hWnd, $msg, $wParam, $lParam)
    Local $aGuiPos = WinGetPos($hGui)
    If Not BitAND(WinGetState($hGui), 16) Then
    IniWrite($sInifile, 'Config', 'Left', $aGuiPos[0])
    IniWrite($sInifile, 'Config', 'Top', $aGuiPos[1])
    EndIf
    Return $GUI_RUNDEFMSG
    EndFunc ;==>_WM_MOVE

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

    Func _WM_GETMINMAXINFO($hWnd, $msg, $wParam, $lParam)
    If $hWnd = $hGui Then
    Local $minmaxinfo = DllStructCreate("int;int;int;int;int;int;int;int;int;int", $lParam)
    DllStructSetData($minmaxinfo, 7, 786) ; min X
    DllStructSetData($minmaxinfo, 8, 444) ; min Y
    ;~ DllStructSetData($minmaxinfo, 9, 800) ; max X
    ;~ DllStructSetData($minmaxinfo, 10, 800) ; max Y
    EndIf
    EndFunc ;==>_WM_GETMINMAXINFO

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

    Func Load() ; Datenbank-Datei laden
    Local $sDBFile, $hFile, $sContent, $aNewItems, $iTimer, $iCount
    FileChangeDir(@ScriptDir)
    $sDBFile = FileOpenDialog('MP3-Datenbank-Datei auswählen', @ScriptDir, 'MP3-Datenbank (*.db3)', 3, '', $hGui)
    If Not FileExists($sDBFile) Then Return
    $hFile = FileOpen($sDBFile, 0) ; Datei zum lesen öffnen
    If $hFile = -1 Then Return; wenn das öffnen nicht erfolgreich war, dann Funktion verlassen
    $sContent = FileRead($hFile) ; Datei komplett einlesen
    FileClose($hFile) ; Datei schließen
    $sContent = StringTrimRight($sContent, 2) ; das letzte @CRLF entfernen
    $aNewItems = StringSplit($sContent, @CRLF, 1) ; Den Dateiinhalt am Zeilenende splitten
    If Not IsArray($aNewItems) Then Return ; Wenn $aNewItems kein Array ist, dann Funktion verlassen
    _GUICtrlListView_DeleteAllItems($hLVHandle)
    _GUICtrlListView_SetItemCount($hLVHandle, $aNewItems[0])
    _GUICtrlStatusBar_SetText($hStatus, 'Lade Daten... (' & $aNewItems[0] & ')', 0)
    _GUICtrlListView_BeginUpdate($hLVHandle) ; Listview sperren
    $iTimer = TimerInit()
    For $i = 1 To $aNewItems[0] ; Alle Einträge des Arrays durchgehen
    $iCount += 1
    If TimerDiff($iTimer) > 100 Then
    $iTimer = TimerInit()
    _GUICtrlStatusBar_SetText($hStatus, $iCount, 1)
    EndIf
    GUICtrlCreateListViewItem($aNewItems[$i], $hListView) ; mit den eingelesenen Daten einen neuen Listview-Eintrag erstellen
    Next
    _GUICtrlStatusBar_SetText($hStatus, $iCount, 1)
    _GUICtrlListView_EndUpdate($hLVHandle) ; Listview wieder freigeben
    EndFunc ;==>Load

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

    Func Save() ; Datenbank-Datei speichern
    Local $sDBFile, $hFile, $iCount, $iTimer
    $sDBFile = FileSaveDialog('MP3-Datenbank-Datei auswählen', '', 'MP3-Datenbank (*.db3)', 18, '', $hGui)
    If @error Then Return
    If StringRight($sDBFile, 4) <> '.db3' Then $sDBFile &= '.db3'
    $iCount = _GUICtrlListView_GetItemCount($hLVHandle); Anzahl der Listview-Einträge holen
    If $iCount = 0 Then Return ; Wenn das Listview keine Einträge enthält, dann Funktion verlassen
    $hFile = FileOpen($sDBFile, 2) ; Datei zum speichern (überschreiben) öffnen
    If $hFile = -1 Then Return; wenn das öffnen nicht erfolgreich war, dann Funktion verlassen
    $iTimer = TimerInit()
    For $i = 0 To $iCount - 1 ; Schleife, um alle Listview-Einträge durchzugehen
    FileWriteLine($hFile, _GUICtrlListView_GetItemTextString($hLVHandle, $i))
    If TimerDiff($iTimer) > 100 Then
    $iTimer = TimerInit()
    _GUICtrlStatusBar_SetText($hStatus, $i + 1, 2)
    EndIf
    Next
    FileClose($hFile) ; Datei schließen
    EndFunc ;==>Save

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

    ;===============================================================================
    ; Function Name: _RecursiveFileListToArray($sPath[, $sPattern][, $iFlag][, $iFormat][, $iRecursion][, $sDelim])
    ; Description:: gibt Verzeichnisse (rekursiv) und/oder Dateien zurück, die einem RegExp-Pattern entsprechen
    ; Parameter(s): $sPath = Startverzeichnis
    ; $sPattern = ein beliebiges RexExp-Pattern für die Auswahl
    ; $iFlag = Auswahl
    ; 0 = Dateien & Verzeichnisse
    ; 1 = nur Dateien
    ; 2 = nur Verzeichnisse
    ; $iFormat = Rückgabeformat
    ; 0 = String
    ; 1 = Array mit [0] = Anzahl
    ; 2 = Nullbasiertes Array
    ; $iRecursion = Verzeichnisse rekursiv durchsuchen
    ; 0 = Nein
    ; 1 = Ja
    ; $sDelim = Trennzeichen für die String-Rückgabe
    ; Requirement(s): AutoIt 3.3.0.0
    ; Return Value(s): Array/String mit den gefundenen Dateien/Verzeichnissen
    ; Author(s): Oscar (http://www.autoit.de)
    ; Anregungen von: bernd670 (http://www.autoit.de)
    ;===============================================================================
    Func _RecursiveFileListToArray($sPath, $sPattern = '', $iFlag = 0, $iFormat = 1, $iRecursion = 1, $sDelim = @CRLF)
    Local $hSearch, $sFile, $sReturn = ''
    If StringRight($sPath, 1) <> '\' Then $sPath &= '\'
    $hSearch = FileFindFirstFile($sPath & '*.*')
    If @error Or $hSearch = -1 Then Return SetError(1, 0, $sReturn)
    While Not $fStop
    $sFile = FileFindNextFile($hSearch)
    If @error Then ExitLoop
    If @extended Then
    If StringRegExp($sPath & $sFile, $sPattern) And ($iFlag = 0 Or $iFlag = 2) Then $sReturn &= $sPath & $sFile & '\' & $sDelim
    If $iRecursion Then $sReturn &= _RecursiveFileListToArray($sPath & $sFile & '\', $sPattern, $iFlag, 0)
    ContinueLoop
    EndIf
    If StringRegExp($sFile, $sPattern) And ($iFlag = 0 Or $iFlag = 1) Then $sReturn &= $sPath & $sFile & $sDelim
    WEnd
    FileClose($hSearch)
    If $iFormat And $sReturn = '' Then Return StringSplit($sReturn, '', $iFormat)
    If $iFormat Then Return StringSplit(StringTrimRight($sReturn, StringLen($sDelim)), $sDelim, $iFormat)
    Return $sReturn
    EndFunc ;==>_RecursiveFileListToArray

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

    ;===============================================================================
    ; Function Name: _ReadID3Tag($sPath)
    ; Description:: gibt ein Array mit den Daten aus den ID3-Tags zurück
    ; unterstützt werden die ID3-Tag-Versionen 1.0, 1.1, 2.3 und 2.4
    ; bei v2.4 müssen sich die ID3-Tags am Anfang der Datei befinden
    ; Parameter(s): $sPath = Pfad zu einer MP3-Datei
    ; Requirement(s): min. AutoIt v3.3.0.0
    ; Return Value(s): bei Erfolg: Array mit den ID3-Tagdaten (@error = 0)
    ; im Fehlerfall bekommt @error:
    ; 1 = Datei existiert nicht
    ; 2 = Datei konnte nicht zum lesen geöffnet werden
    ; 3 = falsche ID3 v2 Version
    ; 4 = Datei ist keine MP3-Datei
    ; Author(s): Oscar (http://www.autoit.de)
    ;===============================================================================
    Func _ReadID3Tag($sPath)
    If Not FileExists($sPath) Then Return SetError(1, 0, 0)
    Local $hFile, $sData, $sID3Header, $iID3HeaderSize = 0, $iOffset, $iSize, $tmp
    Local $aID3v2Tags[8] = ['TIT2', 'TPE1', 'TALB', 'TYER', 'TLEN', 'TRCK', 'TCON', 'TENC']
    Local $aID3[11][2] = [ _
    ['Title', ''],['Artist', ''],['Album', ''],['Year', ''], _
    ['Length', '0'],['Track', ''],['Genre', ''],['Encoder', ''], _
    ['MPEG-Version', ''],['Bitrate', '-'],['Sample-Freq.', '']]
    Local $aMP3Version[4] = ['MPEG2.5', 'Reserved', 'MPEG2', 'MPEG1']
    Local $aMP3Layer[4] = ['Reserved', 'Layer III', 'Layer II', 'Layer I']
    Local $aMP3Bitrate[5][16] = [ _
    [000, 032, 064, 096, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448, 000], _
    [000, 032, 048, 056, 064, 080, 096, 112, 128, 160, 192, 224, 256, 320, 384, 000], _
    [000, 032, 040, 048, 056, 064, 080, 096, 112, 128, 160, 192, 224, 256, 320, 000], _
    [000, 032, 048, 056, 064, 080, 096, 112, 128, 144, 160, 176, 192, 224, 256, 000], _
    [000, 008, 016, 024, 032, 040, 048, 056, 064, 080, 096, 112, 128, 144, 160, 000]]
    Local $aSampleFreq[3][4] = [[44100, 48000, 32000, 0],[22050, 24000, 16000, 0],[11025, 12000, 8000, 0]]
    Local $sMP3FrameHeader, $iMP3Version, $sMP3Version, $sMP3Layer, $iMP3Bitrate, $iMP3SampleFreq
    Local $iVBRFrames = -1, $iVBRFilesize, $iVBRFlags
    $hFile = FileOpen($sPath, 16)
    If $hFile = -1 Then Return SetError(2, 0, 0)
    $sData = Binary(FileRead($hFile, 4))
    If BinaryMid($sData, 1, 3) = '0x494433' Then ; ID3 v2.x Kennung gefunden
    If (BinaryMid($sData, 4, 1) = '0x03') Or (BinaryMid($sData, 4, 1) = '0x04') Then ; nur v2.3 und 2.4
    FileRead($hFile, 2) ; 2 Bytes überspringen
    For $i = 0 To 3 ; berechne ID3-Headergröße (4 Bytes, jedoch nur jeweils die unteren 7 Bit)
    $iID3HeaderSize = BitShift($iID3HeaderSize, -7) + BitAND(Binary(FileRead($hFile, 1)), 0x7F)
    Next
    If $iID3HeaderSize > 0 Then
    $sID3Header = Binary(FileRead($hFile, $iID3HeaderSize)) ; lese gesamten ID3-Header
    For $i = 0 To 7
    $iOffset = StringInStr(BinaryToString($sID3Header), $aID3v2Tags[$i]) ; Offset zu dem ID3-Tag
    If $iOffset > 0 Then
    $iSize = Hex(BinaryMid($sID3Header, $iOffset + 4, 4)) ; Größe des ID3-Frames
    $tmp = BinaryMid($sID3Header, $iOffset + 11, Dec($iSize) - 1)
    If BinaryMid($tmp, 1, 2) = '0xFFFE' Then
    For $x = 3 To BinaryLen($tmp) Step 2
    $aID3[$i][1] &= BinaryToString(BinaryMid($tmp, $x, 2), 2)
    Next
    Else
    For $x = 1 To BinaryLen($tmp)
    $aID3[$i][1] &= BinaryToString(BinaryMid($tmp, $x, 1))
    Next
    EndIf
    $aID3[$i][1] = StringReplace($aID3[$i][1], Chr(0), '')
    EndIf
    Next
    EndIf
    Do
    $sData = String(FileRead($hFile, 1))
    If @error Then ExitLoop
    If BitAND($sData, 0xff) = 0xff Then
    FileSetPos($hFile, -1, 1)
    $sData = String(FileRead($hFile, 4))
    EndIf
    Until BitAND($sData, 0xFFE00000) = 0xFFE00000
    Else
    FileClose($hFile)
    Return SetError(3, 0, 0)
    EndIf
    Else ; ID3 v1.x
    $iOffset = FileGetPos($hFile)
    FileSetPos($hFile, -128, 2)
    $sID3Header = BinaryToString(FileRead($hFile, 3))
    If $sID3Header = 'TAG' Then
    $aID3[0][1] = StringReplace(BinaryToString(FileRead($hFile, 30)), Chr(0), '')
    $aID3[1][1] = StringReplace(BinaryToString(FileRead($hFile, 30)), Chr(0), '')
    $aID3[2][1] = StringReplace(BinaryToString(FileRead($hFile, 30)), Chr(0), '')
    $aID3[3][1] = StringReplace(BinaryToString(FileRead($hFile, 4)), Chr(0), '')
    EndIf
    FileSetPos($hFile, $iOffset, 0)
    EndIf
    $sMP3FrameHeader = String($sData)
    If BitAND($sMP3FrameHeader, 0xFFE00000) <> 0xFFE00000 Then
    FileClose($hFile)
    Return SetError(4, 0, 0) ; keine MP3-Datei, dann Return
    EndIf
    $iMP3Version = BitShift(BitXOR($sMP3FrameHeader, 0xFFE00000), 19) ; welche MP3-Version
    $sMP3Version = $aMP3Version[$iMP3Version] ; in Textform
    $sMP3Layer = $aMP3Layer[BitShift(BitAND($sMP3FrameHeader, 0x60000), 17)] ; welcher Layer
    $aID3[8][1] = $sMP3Version & ' / ' & $sMP3Layer ; ins Ausgabe-Array
    $iMP3Bitrate = BitShift(BitAND($sMP3FrameHeader, 0xF000), 12) ; Bitraten-Index auslesen
    Switch $sMP3Version ; je nach MPEG-Version Bitrate aus der Tabelle holen
    Case 'MPEG1'
    $aID3[9][1] = $aMP3Bitrate[$iMP3Version - ($iMP3Version > 1)][$iMP3Bitrate]
    Case 'MPEG2', 'MPEG2.5'
    If $sMP3Layer = 'Layer I' Then
    $aID3[9][1] = $aMP3Bitrate[3][$iMP3Bitrate]
    Else
    $aID3[9][1] = $aMP3Bitrate[4][$iMP3Bitrate]
    EndIf
    EndSwitch
    $iMP3SampleFreq = BitShift(BitAND($sMP3FrameHeader, 0xC00), 10) ; Sample-Frequenz-Index auslesen
    $aID3[10][1] = $aSampleFreq[2 - ($iMP3Version - ($iMP3Version > 1))][$iMP3SampleFreq] ; und Wert aus der Tabelle holen
    Do ; evtl. Leerbytes überspringen
    $tmp = FileRead($hFile, 1)
    If @error Then ExitLoop
    Until $tmp <> 0x00 Or @error
    If $tmp = 0x58 And BinaryToString(FileRead($hFile, 3)) = 'ing' Then ; MP3 mit VBR (Xing-Header gefunden)?
    $iVBRFlags = '0x' & Hex(FileRead($hFile, 4)) ; VBR-Flags auslesen
    If BitAND($iVBRFlags, 0x3) Then ; wenn die Einträge vorhanden sind, dann...
    $iVBRFrames = Dec(Hex(FileRead($hFile, 4))) ; Anzahl der VBR-Frames auslesen
    $iVBRFilesize = Dec(Hex(FileRead($hFile, 4))) ; Dateigröße auslesen
    $aID3[4][1] = $iVBRFrames * 1152 / $aID3[10][1] * 1000 ; VBR Laufzeit
    $aID3[9][1] = 'VBR ~' & Int($iVBRFilesize * 8 / ($aID3[4][1] / 1000) / 1000) ; VBR durchschnittliche Bitrate
    EndIf
    Else
    If $aID3[4][1] = 0 Then $aID3[4][1] = (FileGetSize($sPath) * 8) / ($aID3[9][1] * 1000) * 1000 ; alternative CBR Laufzeit
    $aID3[9][1] = 'CBR ' & $aID3[9][1]
    EndIf
    $aID3[4][1] = _TicksToTimeFormat($aID3[4][1]) ; Laufzeit (Ticks to hour:min:sec)
    $aID3[9][1] &= ' kBit/s'
    $aID3[10][1] &= ' Hz'
    FileClose($hFile)
    Return SetError(0, 0, $aID3)
    EndFunc ;==>_ReadID3Tag

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

    ;===============================================================================
    ; Function Name: _TicksToTimeFormat($iTicks, $sFormat = '%hh:%mm:%ss')
    ; Description:: Diese Funktion wandelt Millisekunden in ein anzugebenes Zeitformat um
    ; Parameter(s): $iTicks = Zeit in Millisekunden
    ; $sFormat:
    ; %hh für Stunden
    ; %mm für Minuten
    ; %ss für Sekunden
    ; %ms für Millisekunden
    ; sonstige Zeichen, die dazwischen stehen, werden übernommen
    ; Requirement(s): -
    ; Return Value(s): Zeit im ausgewählten Format (String)
    ; Author(s): Oscar (http://www.autoit.de)
    ;===============================================================================
    Func _TicksToTimeFormat($iTicks, $sFormat = '%hh:%mm:%ss')
    Local $aTime[4] = [0, 0, 0, 0], $sOut, $aTimeFormat[4] = ['hh', 'mm', 'ss', 'ms'], $aFormat
    $aTime[2] = Int($iTicks / 1000)
    $aTime[3] = $iTicks - $aTime[2] * 1000
    $aTime[0] = Int($aTime[2] / 3600)
    $aTime[2] = Mod($aTime[2], 3600)
    $aTime[1] = Int($aTime[2] / 60)
    $aTime[2] = Mod($aTime[2], 60)
    $aFormat = StringRegExp($sFormat, '%([^%]+)', 3)
    If Not IsArray($aFormat) Then Return SetError(1, 0, $iTicks)
    For $i = 0 To UBound($aFormat) - 1
    For $j = 0 To UBound($aTimeFormat) - 1
    If StringLeft($aFormat[$i], 2) = $aTimeFormat[$j] Then $sOut &= StringFormat('%02i', $aTime[$j]) & StringMid($aFormat[$i], 3)
    Next
    Next
    Return $sOut
    EndFunc ;==>_TicksToTimeFormat

    [/autoit]

    Edit: Man konnte aus dem Suchergebnis das MP3 nicht starten (Doppelklick). Behoben!

    Dateien

    _MP3Search.au3 28,91 kB – 223 Downloads
  • mp3 Searcher

    • Oscar
    • 30. Juli 2010 um 10:59

    Nachdem wir das mit den MP3s geklärt haben, kommt hier die nächste Version: mit Suchfunktion für die Liste. :)

    Skript:

    Spoiler anzeigen
    [autoit]


    #include <ButtonConstants.au3>
    #include <Date.au3>
    #include <GUIConstantsEx.au3>
    #include <GuiListView.au3>
    #include <GuiStatusBar.au3>
    #include <ListViewConstants.au3>
    #include <StaticConstants.au3>
    #include <StructureConstants.au3>
    #include <WindowsConstants.au3>

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

    Global $sHeader = 'Title|Artist|Length|Album|Year|MPEG-Version|Bitrate|Sample-Freq.|Path' ; Die Überschriften für das Listview
    Global $sInifile = @ScriptDir & '\MP3-Search.ini' ; Inidatei

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

    Global $iWidth = IniRead($sInifile, 'Config', 'Width', 770)
    Global $iHeight = IniRead($sInifile, 'Config', 'Height', 406)
    Global $iLeft = IniRead($sInifile, 'Config', 'Left', @DesktopWidth / 2 - 385)
    Global $iTop = IniRead($sInifile, 'Config', 'Top', @DesktopHeight / 2 - 203)

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

    #region Hauptfenster
    Global $sStyle = BitOR($GUI_SS_DEFAULT_GUI, $WS_MAXIMIZEBOX, $WS_SIZEBOX)
    Global $hGui = GUICreate('MP3-Search', 770, 406, $iLeft, $iTop, $sStyle) ; Hauptfenster erstellen
    GUISetBkColor(0xAAAAAA)

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

    Global $hListView = GUICtrlCreateListView($sHeader, 5, 5, 760, 280, $LVS_SHOWSELALWAYS, BitOR($LVS_EX_FULLROWSELECT, $LVS_EX_DOUBLEBUFFER, $WS_EX_WINDOWEDGE)) ; Listview erstellen
    GUICtrlSetResizing(-1, 2 + 4 + 32 + 64)
    GUICtrlSetBkColor(-1, 0xaabbff)
    Global $hLVHandle = GUICtrlGetHandle($hListView) ; das Handle vom Listview wird für die UDF-Listview-Funktionen benötigt
    _GUICtrlListView_SetColumnWidth($hLVHandle, 0, 180)
    _GUICtrlListView_SetColumnWidth($hLVHandle, 1, 180)
    _GUICtrlListView_SetColumnWidth($hLVHandle, 2, 60)
    _GUICtrlListView_SetColumnWidth($hLVHandle, 3, 120)
    _GUICtrlListView_SetColumnWidth($hLVHandle, 4, 60)
    _GUICtrlListView_SetColumnWidth($hLVHandle, 5, 100)
    _GUICtrlListView_SetColumnWidth($hLVHandle, 6, 100)
    _GUICtrlListView_SetColumnWidth($hLVHandle, 7, 90)
    _GUICtrlListView_SetColumnWidth($hLVHandle, 8, 800)

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

    GUICtrlCreateLabel('Suchbegriff:', 10, 302, 70, 22, $SS_RIGHT)
    GUICtrlSetFont(-1, 10)
    GUICtrlSetResizing(-1, 512 + 64)
    Global $hInput = GUICtrlCreateInput('', 90, 300, 300, 22)
    GUICtrlSetFont(-1, 10)
    GUICtrlSetResizing(-1, 512 + 64)
    Global $hInputOk = GUICtrlCreateButton('Suche starten', 400, 300, 100, 22)
    GUICtrlSetFont(-1, 10)
    GUICtrlSetResizing(-1, 512 + 64)

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

    Global $hSearch = GUICtrlCreateButton('Alle Festplatten durchsuchen', 10, 340, 120, 35, $BS_MULTILINE)
    GUICtrlSetResizing(-1, 512 + 64)
    Global $hSearchPath = GUICtrlCreateButton('Verzeichnis durchsuchen', 140, 340, 100, 35, $BS_MULTILINE)
    GUICtrlSetResizing(-1, 512 + 64)
    Global $hLoad = GUICtrlCreateButton('Laden', 250, 340, 70, 35)
    GUICtrlSetResizing(-1, 512 + 64)
    Global $hSave = GUICtrlCreateButton('Speichern', 330, 340, 70, 35)
    GUICtrlSetResizing(-1, 512 + 64)
    Global $hDel = GUICtrlCreateButton("Markierte Einträge löschen", 410, 340, 90, 35, $BS_MULTILINE)
    GUICtrlSetResizing(-1, 512 + 64)
    GUICtrlSetState(-1, $GUI_DISABLE)
    Global $hDelAll = GUICtrlCreateButton('Alle Einträge löschen', 510, 340, 90, 35, $BS_MULTILINE)
    GUICtrlSetResizing(-1, 512 + 64)

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

    Global $aParts[3] = [300, 360, -1], $aText[3] = ['Fertig.', '0', '']
    Global $hStatus = _GUICtrlStatusBar_Create($hGui, $aParts, $aText)
    #endregion Hauptfenster

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

    GUISetState(@SW_SHOW, $hGui) ; Hauptfenster sichtbar machen

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

    Global $fStop = False, $iSearchIndex = -1, $iSelCount, $iSelOld
    HotKeySet('{ESC}', '_Stop')

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

    Dim $aAccelKeys[1][2] = [['{DEL}', $hDel]] ; beim drücken der [Delete]-Taste wird "Case $hDel" ausgeführt
    GUISetAccelerators($aAccelKeys, $hGui)

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

    GUIRegisterMsg($WM_SIZE, '_WM_SIZE')
    GUIRegisterMsg($WM_MOVE, '_WM_MOVE')
    GUIRegisterMsg($WM_GETMINMAXINFO, '_WM_GETMINMAXINFO')
    GUIRegisterMsg($WM_NOTIFY, '_WM_NOTIFY')
    GUIRegisterMsg($WM_COMMAND, '_WM_COMMAND')

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

    WinMove($hGui, '', $iLeft, $iTop, $iWidth, $iHeight)

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

    While 1
    Switch GUIGetMsg() ; anhand der Control-ID das entsprechende Case aufrufen
    Case $hSearch
    _GUICtrlListView_DeleteAllItems($hLVHandle) ; Alle Listview-Einträge löschen
    _GUICtrlStatusBar_SetText($hStatus, 0, 1)
    $iLVCount = 0 ; Zähler auf Null setzen
    $aDrives = DriveGetDrive('FIXED') ; Alle Festplatten-Buchstaben holen
    If Not @error Then
    GUISetCursor(15, 1, $hGui)
    For $i = 1 To $aDrives[0] ; Alle Festplatten durchgehen
    _GUICtrlStatusBar_SetText($hStatus, 'Durchsuche Festplatte "' & StringUpper($aDrives[$i]) & '\"', 0)
    _DriveSearch(StringUpper($aDrives[$i]))
    Next
    GUISetCursor(2, 1, $hGui)
    EndIf
    _GUICtrlStatusBar_SetText($hStatus, _GUICtrlListView_GetItemCount($hLVHandle), 1)
    _GUICtrlStatusBar_SetText($hStatus, '', 2)
    If $fStop Then
    $fStop = False
    _GUICtrlStatusBar_SetText($hStatus, 'Abgebrochen!', 0)
    Else
    _GUICtrlStatusBar_SetText($hStatus, 'Fertig.', 0)
    EndIf
    Case $hSearchPath
    $sPath = FileSelectFolder('Verzeichnis auswählen!', '', 2, '', $hGui)
    If FileExists($sPath) Then
    _GUICtrlListView_DeleteAllItems($hLVHandle) ; Alle Listview-Einträge löschen
    $iLVCount = 0 ; Zähler auf Null setzen
    GUISetCursor(15, 1, $hGui)
    _GUICtrlStatusBar_SetText($hStatus, 'Durchsuche Verzeichnis "' & $sPath & '"', 0)
    _DriveSearch($sPath)
    GUISetCursor(2, 1, $hGui)
    _GUICtrlStatusBar_SetText($hStatus, _GUICtrlListView_GetItemCount($hLVHandle), 1)
    _GUICtrlStatusBar_SetText($hStatus, '', 2)
    If $fStop Then
    $fStop = False
    _GUICtrlStatusBar_SetText($hStatus, 'Abgebrochen!', 0)
    Else
    _GUICtrlStatusBar_SetText($hStatus, 'Fertig.', 0)
    EndIf
    EndIf
    Case $hInput, $hInputOk
    _GUICtrlStatusBar_SetText($hStatus, 'Suche in Liste...', 0)
    GUISetCursor(15, 1, $hGui)
    _LVSearch()
    GUISetCursor(2, 1, $hGui)
    _GUICtrlStatusBar_SetText($hStatus, 'Fertig.', 0)
    Case $hListView ; User hat auf eine Spaltenüberschrift geklickt (sortieren)
    If _GUICtrlListView_GetItemCount($hLVHandle) > 0 Then
    Dim $aDescending[_GUICtrlListView_GetColumnCount($hLVHandle)]
    GUISetCursor(15, 1, $hGui)
    $iTimer = TimerInit()
    _GUICtrlStatusBar_SetText($hStatus, 'Sortiere Daten! Bitte warten...', 0)
    _GUICtrlListView_SimpleSort($hLVHandle, $aDescending, GUICtrlGetState($hListView))
    _GUICtrlStatusBar_SetText($hStatus, _TicksToTimeFormat(TimerDiff($iTimer), '%mm:%ss.%ms'), 2)
    _GUICtrlStatusBar_SetText($hStatus, 'Fertig.', 0)
    GUISetCursor(2, 1, $hGui)
    EndIf
    Case $hLoad ; User hat auf 'Laden' geklickt
    GUISetCursor(15, 1, $hGui)
    _GUICtrlStatusBar_SetText($hStatus, 'Lade Daten...', 0)
    Load()
    _GUICtrlStatusBar_SetText($hStatus, 'Fertig.', 0)
    GUISetCursor(2, 1, $hGui)
    Case $hSave ; User hat auf 'Speichern' geklickt
    GUISetCursor(15, 1, $hGui)
    _GUICtrlStatusBar_SetText($hStatus, 'Speichere Daten...', 0)
    Save()
    _GUICtrlStatusBar_SetText($hStatus, 'Fertig.', 0)
    _GUICtrlStatusBar_SetText($hStatus, '', 2)
    GUISetCursor(2, 1, $hGui)
    Case $hDel
    GUISetCursor(15, 1, $hGui)
    _GUICtrlListView_DeleteItemsSelected($hLVHandle)
    _GUICtrlStatusBar_SetText($hStatus, _GUICtrlListView_GetItemCount($hLVHandle), 1)
    GUISetCursor(2, 1, $hGui)
    Case $hDelAll ; User hat auf 'Alle Einträge löschen' geklickt
    If MsgBox(256 + 32 + 4, 'Einträge löschen', 'Wollen sie wirklich alle Einträge löschen?') = 6 Then
    _GUICtrlListView_DeleteAllItems($hLVHandle)
    _GUICtrlStatusBar_SetText($hStatus, 0, 1)
    EndIf
    Case $GUI_EVENT_CLOSE ; User hat auf das Schließen-Symbol geklickt
    ;~ If MsgBox(32 + 4, 'Save', 'Wollen sie vor beenden noch Speichern?') = 6 Then Save()
    Exit ; Programm beenden
    EndSwitch
    $iSelCount = _GUICtrlListView_GetSelectedCount($hLVHandle) ; Anzahl der markierten Items holen
    If $iSelCount <> $iSelOld Then ; vergleichen ob der Wert vom vorherigen abweicht (Flackern vermeiden)
    $iSelOld = $iSelCount ; wenn ja, dann alten gleich neuen Wert
    If $iSelCount > 0 Then ; wenn Einträge markiert sind
    GUICtrlSetState($hDel, $GUI_ENABLE) ; dann Button aktivieren
    GUICtrlSetData($hDel, StringFormat('(%i) Markierte Einträge löschen', $iSelCount)) ; und den Text auf dem Button anpassen
    Else ; keine Einträge markiert
    GUICtrlSetState($hDel, $GUI_DISABLE) ; dann Button deaktivieren
    GUICtrlSetData($hDel, 'Markierte Einträge löschen') ; und den Text auf dem Button anpassen
    EndIf
    EndIf
    WEnd

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

    Func _Stop()
    $fStop = True
    EndFunc ;==>_Stop

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

    Func _DriveSearch($sPath)
    Local $aNewMP3, $aID3Tags, $sNewItem, $aItem
    If StringRight($sPath, 1) <> '\' Then $sPath &= '\'
    _GUICtrlStatusBar_SetText($hStatus, 'Bitte warten...', 2)
    $aNewMP3 = _RecursiveFileListToArray($sPath, '\.mp3', 1) ; Alle MP3s auf der Festplatte auslesen
    If Not @error And $aNewMP3[0] > 0 Then
    _GUICtrlListView_SetItemCount($hListView, _GUICtrlListView_GetItemCount($hLVHandle) + $aNewMP3[0])
    _GUICtrlStatusBar_SetText($hStatus, 'Lese ID3-Tags... (' & $aNewMP3[0] & ')', 0)
    For $j = 1 To $aNewMP3[0] ; die gefundenen MP3s durchgehen
    $aID3Tags = _ReadID3Tag($aNewMP3[$j]) ; die ID3-Tags auslesen
    If Not @error Then
    For $k = 0 To 10
    $aID3Tags[$k][1] = StringReplace($aID3Tags[$k][1], '|', '') ; evtl. vorhandene "|" entfernen
    Next
    _GUICtrlStatusBar_SetText($hStatus, _GUICtrlListView_GetItemCount($hLVHandle), 1)
    _GUICtrlStatusBar_SetText($hStatus, $aNewMP3[$j], 2)
    $sNewItem = $aID3Tags[0][1] & '|' & $aID3Tags[1][1] & '|' & $aID3Tags[4][1] & '|' & $aID3Tags[2][1] & '|' & $aID3Tags[3][1]
    $sNewItem &= '|' & $aID3Tags[8][1] & '|' & $aID3Tags[9][1] & '|' & $aID3Tags[10][1] & '|' & $aNewMP3[$j]
    GUICtrlCreateListViewItem($sNewItem, $hListView)
    EndIf
    If $fStop Then ExitLoop
    Next
    EndIf
    EndFunc ;==>_DriveSearch

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

    Func _WM_COMMAND($hWnd, $msg, $wParam, $lParam)
    Local $nNotifyCode = BitShift($wParam, 16)
    Local $nID = BitAND($wParam, 0xFFFF)
    If $nID = $hInput And $nNotifyCode = 256 Then
    GUICtrlSetBkColor($hInput, 0xffffff)
    $iSearchIndex = -1
    GUICtrlSetData($hInputOk, 'Suche starten')
    _GUICtrlListView_SetItemSelected($hLVHandle, -1, False)
    EndIf
    Return $GUI_RUNDEFMSG
    EndFunc ;==>_WM_COMMAND

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

    Func _LVSearch()
    If _GUICtrlListView_GetItemCount($hLVHandle) = 0 Then Return
    Local $sSearch
    $sSearch = GUICtrlRead($hInput)
    $iSearchIndex = _GUICtrlListView_FindInText($hLVHandle, $sSearch, $iSearchIndex)
    If $iSearchIndex > -1 Then
    _GUICtrlListView_EnsureVisible($hLVHandle, $iSearchIndex)
    _GUICtrlListView_SetItemSelected($hLVHandle, $iSearchIndex)
    GUICtrlSetBkColor($hInput, 0xaaffaa)
    GUICtrlSetData($hInputOk, 'weitersuchen...')
    Else
    _GUICtrlListView_EnsureVisible($hLVHandle, 0)
    _GUICtrlListView_SetItemSelected($hLVHandle, -1, False)
    GUICtrlSetBkColor($hInput, 0xffaaaa)
    EndIf
    EndFunc ;==>_LVSearch

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

    Func _WM_NOTIFY($hWnd, $msg, $wParam, $lParam)
    Local $hWndFrom, $iIDFrom, $iCode, $tNMHDR, $iSelected, $sExecutePath
    $tNMHDR = DllStructCreate($tagNMHDR, $lParam)
    $hWndFrom = HWnd(DllStructGetData($tNMHDR, 'hWndFrom'))
    $iCode = DllStructGetData($tNMHDR, 'Code')
    Switch $hWndFrom
    Case $hLVHandle
    Switch $iCode
    Case $NM_DBLCLK
    $iSelected = ControlListView($hGui, '', $hListView, 'GetSelected')
    $sExecutePath = _GUICtrlListView_GetItemText($hLVHandle, $iSelected, 8)
    ShellExecute($sExecutePath)
    EndSwitch
    EndSwitch
    Return $GUI_RUNDEFMSG
    EndFunc ;==>_WM_NOTIFY

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

    Func _WM_SIZE($hWnd, $msg, $wParam, $lParam)
    Local $aGuiPos = WinGetPos($hGui)
    If Not BitAND(WinGetState($hGui), 16) Then
    IniWrite($sInifile, 'Config', 'Width', $aGuiPos[2])
    IniWrite($sInifile, 'Config', 'Height', $aGuiPos[3])
    EndIf
    _GUICtrlStatusBar_Resize($hStatus)
    Return $GUI_RUNDEFMSG
    EndFunc ;==>_WM_SIZE

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

    Func _WM_MOVE($hWnd, $msg, $wParam, $lParam)
    Local $aGuiPos = WinGetPos($hGui)
    If Not BitAND(WinGetState($hGui), 16) Then
    IniWrite($sInifile, 'Config', 'Left', $aGuiPos[0])
    IniWrite($sInifile, 'Config', 'Top', $aGuiPos[1])
    EndIf
    Return $GUI_RUNDEFMSG
    EndFunc ;==>_WM_MOVE

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

    Func _WM_GETMINMAXINFO($hWnd, $msg, $wParam, $lParam)
    If $hWnd = $hGui Then
    Local $minmaxinfo = DllStructCreate("int;int;int;int;int;int;int;int;int;int", $lParam)
    DllStructSetData($minmaxinfo, 7, 786) ; min X
    DllStructSetData($minmaxinfo, 8, 444) ; min Y
    ;~ DllStructSetData($minmaxinfo, 9, 800) ; max X
    ;~ DllStructSetData($minmaxinfo, 10, 800) ; max Y
    EndIf
    EndFunc ;==>_WM_GETMINMAXINFO

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

    Func Load() ; Datenbank-Datei laden
    Local $sDBFile, $hFile, $sContent, $aNewItems, $iTimer, $iCount
    FileChangeDir(@ScriptDir)
    $sDBFile = FileOpenDialog('MP3-Datenbank-Datei auswählen', @ScriptDir, 'MP3-Datenbank (*.db3)', 3, '', $hGui)
    If Not FileExists($sDBFile) Then Return
    $hFile = FileOpen($sDBFile, 0) ; Datei zum lesen öffnen
    If $hFile = -1 Then Return; wenn das öffnen nicht erfolgreich war, dann Funktion verlassen
    $sContent = FileRead($hFile) ; Datei komplett einlesen
    FileClose($hFile) ; Datei schließen
    $sContent = StringTrimRight($sContent, 2) ; das letzte @CRLF entfernen
    $aNewItems = StringSplit($sContent, @CRLF, 1) ; Den Dateiinhalt am Zeilenende splitten
    If Not IsArray($aNewItems) Then Return ; Wenn $aNewItems kein Array ist, dann Funktion verlassen
    _GUICtrlListView_DeleteAllItems($hLVHandle)
    _GUICtrlListView_SetItemCount($hLVHandle, $aNewItems[0])
    _GUICtrlStatusBar_SetText($hStatus, 'Lade Daten... (' & $aNewItems[0] & ')', 0)
    _GUICtrlListView_BeginUpdate($hLVHandle) ; Listview sperren
    $iTimer = TimerInit()
    For $i = 1 To $aNewItems[0] ; Alle Einträge des Arrays durchgehen
    $iCount += 1
    If TimerDiff($iTimer) > 100 Then
    $iTimer = TimerInit()
    _GUICtrlStatusBar_SetText($hStatus, $iCount, 1)
    EndIf
    GUICtrlCreateListViewItem($aNewItems[$i], $hListView) ; mit den eingelesenen Daten einen neuen Listview-Eintrag erstellen
    Next
    _GUICtrlStatusBar_SetText($hStatus, $iCount, 1)
    _GUICtrlListView_EndUpdate($hLVHandle) ; Listview wieder freigeben
    EndFunc ;==>Load

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

    Func Save() ; Datenbank-Datei speichern
    Local $sDBFile, $hFile, $iCount, $iTimer
    $sDBFile = FileSaveDialog('MP3-Datenbank-Datei auswählen', '', 'MP3-Datenbank (*.db3)', 18, '', $hGui)
    If @error Then Return
    If StringRight($sDBFile, 4) <> '.db3' Then $sDBFile &= '.db3'
    $iCount = _GUICtrlListView_GetItemCount($hLVHandle); Anzahl der Listview-Einträge holen
    If $iCount = 0 Then Return ; Wenn das Listview keine Einträge enthält, dann Funktion verlassen
    $hFile = FileOpen($sDBFile, 2) ; Datei zum speichern (überschreiben) öffnen
    If $hFile = -1 Then Return; wenn das öffnen nicht erfolgreich war, dann Funktion verlassen
    $iTimer = TimerInit()
    For $i = 0 To $iCount - 1 ; Schleife, um alle Listview-Einträge durchzugehen
    FileWriteLine($hFile, _GUICtrlListView_GetItemTextString($hLVHandle, $i))
    If TimerDiff($iTimer) > 100 Then
    $iTimer = TimerInit()
    _GUICtrlStatusBar_SetText($hStatus, $i + 1, 2)
    EndIf
    Next
    FileClose($hFile) ; Datei schließen
    EndFunc ;==>Save

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

    ;===============================================================================
    ; Function Name: _RecursiveFileListToArray($sPath[, $sPattern][, $iFlag][, $iFormat][, $iRecursion][, $sDelim])
    ; Description:: gibt Verzeichnisse (rekursiv) und/oder Dateien zurück, die einem RegExp-Pattern entsprechen
    ; Parameter(s): $sPath = Startverzeichnis
    ; $sPattern = ein beliebiges RexExp-Pattern für die Auswahl
    ; $iFlag = Auswahl
    ; 0 = Dateien & Verzeichnisse
    ; 1 = nur Dateien
    ; 2 = nur Verzeichnisse
    ; $iFormat = Rückgabeformat
    ; 0 = String
    ; 1 = Array mit [0] = Anzahl
    ; 2 = Nullbasiertes Array
    ; $iRecursion = Verzeichnisse rekursiv durchsuchen
    ; 0 = Nein
    ; 1 = Ja
    ; $sDelim = Trennzeichen für die String-Rückgabe
    ; Requirement(s): AutoIt 3.3.0.0
    ; Return Value(s): Array/String mit den gefundenen Dateien/Verzeichnissen
    ; Author(s): Oscar (http://www.autoit.de)
    ; Anregungen von: bernd670 (http://www.autoit.de)
    ;===============================================================================
    Func _RecursiveFileListToArray($sPath, $sPattern = '', $iFlag = 0, $iFormat = 1, $iRecursion = 1, $sDelim = @CRLF)
    Local $hSearch, $sFile, $sReturn = ''
    If StringRight($sPath, 1) <> '\' Then $sPath &= '\'
    $hSearch = FileFindFirstFile($sPath & '*.*')
    If @error Or $hSearch = -1 Then Return SetError(1, 0, $sReturn)
    While Not $fStop
    $sFile = FileFindNextFile($hSearch)
    If @error Then ExitLoop
    If @extended Then
    If StringRegExp($sPath & $sFile, $sPattern) And ($iFlag = 0 Or $iFlag = 2) Then $sReturn &= $sPath & $sFile & '\' & $sDelim
    If $iRecursion Then $sReturn &= _RecursiveFileListToArray($sPath & $sFile & '\', $sPattern, $iFlag, 0)
    ContinueLoop
    EndIf
    If StringRegExp($sFile, $sPattern) And ($iFlag = 0 Or $iFlag = 1) Then $sReturn &= $sPath & $sFile & $sDelim
    WEnd
    FileClose($hSearch)
    If $iFormat And $sReturn = '' Then Return StringSplit($sReturn, '', $iFormat)
    If $iFormat Then Return StringSplit(StringTrimRight($sReturn, StringLen($sDelim)), $sDelim, $iFormat)
    Return $sReturn
    EndFunc ;==>_RecursiveFileListToArray

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

    ;===============================================================================
    ; Function Name: _ReadID3Tag($sPath)
    ; Description:: gibt ein Array mit den Daten aus den ID3-Tags zurück
    ; unterstützt werden die ID3-Tag-Versionen 1.0, 1.1, 2.3 und 2.4
    ; bei v2.4 müssen sich die ID3-Tags am Anfang der Datei befinden
    ; Parameter(s): $sPath = Pfad zu einer MP3-Datei
    ; Requirement(s): min. AutoIt v3.3.0.0
    ; Return Value(s): bei Erfolg: Array mit den ID3-Tagdaten (@error = 0)
    ; im Fehlerfall bekommt @error:
    ; 1 = Datei existiert nicht
    ; 2 = Datei konnte nicht zum lesen geöffnet werden
    ; 3 = falsche ID3 v2 Version
    ; 4 = Datei ist keine MP3-Datei
    ; Author(s): Oscar (http://www.autoit.de)
    ;===============================================================================
    Func _ReadID3Tag($sPath)
    If Not FileExists($sPath) Then Return SetError(1, 0, 0)
    Local $hFile, $sData, $sID3Header, $iID3HeaderSize = 0, $iOffset, $iSize, $tmp
    Local $aID3v2Tags[8] = ['TIT2', 'TPE1', 'TALB', 'TYER', 'TLEN', 'TRCK', 'TCON', 'TENC']
    Local $aID3[11][2] = [ _
    ['Title', ''],['Artist', ''],['Album', ''],['Year', ''], _
    ['Length', '0'],['Track', ''],['Genre', ''],['Encoder', ''], _
    ['MPEG-Version', ''],['Bitrate', '-'],['Sample-Freq.', '']]
    Local $aMP3Version[4] = ['MPEG2.5', 'Reserved', 'MPEG2', 'MPEG1']
    Local $aMP3Layer[4] = ['Reserved', 'Layer III', 'Layer II', 'Layer I']
    Local $aMP3Bitrate[5][16] = [ _
    [000, 032, 064, 096, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448, 000], _
    [000, 032, 048, 056, 064, 080, 096, 112, 128, 160, 192, 224, 256, 320, 384, 000], _
    [000, 032, 040, 048, 056, 064, 080, 096, 112, 128, 160, 192, 224, 256, 320, 000], _
    [000, 032, 048, 056, 064, 080, 096, 112, 128, 144, 160, 176, 192, 224, 256, 000], _
    [000, 008, 016, 024, 032, 040, 048, 056, 064, 080, 096, 112, 128, 144, 160, 000]]
    Local $aSampleFreq[3][4] = [[44100, 48000, 32000, 0],[22050, 24000, 16000, 0],[11025, 12000, 8000, 0]]
    Local $sMP3FrameHeader, $iMP3Version, $sMP3Version, $sMP3Layer, $iMP3Bitrate, $iMP3SampleFreq
    Local $iVBRFrames = -1, $iVBRFilesize, $iVBRFlags
    $hFile = FileOpen($sPath, 16)
    If $hFile = -1 Then Return SetError(2, 0, 0)
    $sData = Binary(FileRead($hFile, 4))
    If BinaryMid($sData, 1, 3) = '0x494433' Then ; ID3 v2.x Kennung gefunden
    If (BinaryMid($sData, 4, 1) = '0x03') Or (BinaryMid($sData, 4, 1) = '0x04') Then ; nur v2.3 und 2.4
    FileRead($hFile, 2) ; 2 Bytes überspringen
    For $i = 0 To 3 ; berechne ID3-Headergröße (4 Bytes, jedoch nur jeweils die unteren 7 Bit)
    $iID3HeaderSize = BitShift($iID3HeaderSize, -7) + BitAND(Binary(FileRead($hFile, 1)), 0x7F)
    Next
    If $iID3HeaderSize > 0 Then
    $sID3Header = Binary(FileRead($hFile, $iID3HeaderSize)) ; lese gesamten ID3-Header
    For $i = 0 To 7
    $iOffset = StringInStr(BinaryToString($sID3Header), $aID3v2Tags[$i]) ; Offset zu dem ID3-Tag
    If $iOffset > 0 Then
    $iSize = Hex(BinaryMid($sID3Header, $iOffset + 4, 4)) ; Größe des ID3-Frames
    $tmp = BinaryMid($sID3Header, $iOffset + 11, Dec($iSize) - 1)
    If BinaryMid($tmp, 1, 2) = '0xFFFE' Then
    For $x = 3 To BinaryLen($tmp) Step 2
    $aID3[$i][1] &= BinaryToString(BinaryMid($tmp, $x, 2), 2)
    Next
    Else
    For $x = 1 To BinaryLen($tmp)
    $aID3[$i][1] &= BinaryToString(BinaryMid($tmp, $x, 1))
    Next
    EndIf
    $aID3[$i][1] = StringReplace($aID3[$i][1], Chr(0), '')
    EndIf
    Next
    EndIf
    Do
    $sData = String(FileRead($hFile, 1))
    If @error Then ExitLoop
    If BitAND($sData, 0xff) = 0xff Then
    FileSetPos($hFile, -1, 1)
    $sData = String(FileRead($hFile, 4))
    EndIf
    Until BitAND($sData, 0xFFE00000) = 0xFFE00000
    Else
    FileClose($hFile)
    Return SetError(3, 0, 0)
    EndIf
    Else ; ID3 v1.x
    $iOffset = FileGetPos($hFile)
    FileSetPos($hFile, -128, 2)
    $sID3Header = BinaryToString(FileRead($hFile, 3))
    If $sID3Header = 'TAG' Then
    $aID3[0][1] = StringReplace(BinaryToString(FileRead($hFile, 30)), Chr(0), '')
    $aID3[1][1] = StringReplace(BinaryToString(FileRead($hFile, 30)), Chr(0), '')
    $aID3[2][1] = StringReplace(BinaryToString(FileRead($hFile, 30)), Chr(0), '')
    $aID3[3][1] = StringReplace(BinaryToString(FileRead($hFile, 4)), Chr(0), '')
    EndIf
    FileSetPos($hFile, $iOffset, 0)
    EndIf
    $sMP3FrameHeader = String($sData)
    If BitAND($sMP3FrameHeader, 0xFFE00000) <> 0xFFE00000 Then
    FileClose($hFile)
    Return SetError(4, 0, 0) ; keine MP3-Datei, dann Return
    EndIf
    $iMP3Version = BitShift(BitXOR($sMP3FrameHeader, 0xFFE00000), 19) ; welche MP3-Version
    $sMP3Version = $aMP3Version[$iMP3Version] ; in Textform
    $sMP3Layer = $aMP3Layer[BitShift(BitAND($sMP3FrameHeader, 0x60000), 17)] ; welcher Layer
    $aID3[8][1] = $sMP3Version & ' / ' & $sMP3Layer ; ins Ausgabe-Array
    $iMP3Bitrate = BitShift(BitAND($sMP3FrameHeader, 0xF000), 12) ; Bitraten-Index auslesen
    Switch $sMP3Version ; je nach MPEG-Version Bitrate aus der Tabelle holen
    Case 'MPEG1'
    $aID3[9][1] = $aMP3Bitrate[$iMP3Version - ($iMP3Version > 1)][$iMP3Bitrate]
    Case 'MPEG2', 'MPEG2.5'
    If $sMP3Layer = 'Layer I' Then
    $aID3[9][1] = $aMP3Bitrate[3][$iMP3Bitrate]
    Else
    $aID3[9][1] = $aMP3Bitrate[4][$iMP3Bitrate]
    EndIf
    EndSwitch
    $iMP3SampleFreq = BitShift(BitAND($sMP3FrameHeader, 0xC00), 10) ; Sample-Frequenz-Index auslesen
    $aID3[10][1] = $aSampleFreq[2 - ($iMP3Version - ($iMP3Version > 1))][$iMP3SampleFreq] ; und Wert aus der Tabelle holen
    Do ; evtl. Leerbytes überspringen
    $tmp = FileRead($hFile, 1)
    If @error Then ExitLoop
    Until $tmp <> 0x00 Or @error
    If $tmp = 0x58 And BinaryToString(FileRead($hFile, 3)) = 'ing' Then ; MP3 mit VBR (Xing-Header gefunden)?
    $iVBRFlags = '0x' & Hex(FileRead($hFile, 4)) ; VBR-Flags auslesen
    If BitAND($iVBRFlags, 0x3) Then ; wenn die Einträge vorhanden sind, dann...
    $iVBRFrames = Dec(Hex(FileRead($hFile, 4))) ; Anzahl der VBR-Frames auslesen
    $iVBRFilesize = Dec(Hex(FileRead($hFile, 4))) ; Dateigröße auslesen
    $aID3[4][1] = $iVBRFrames * 1152 / $aID3[10][1] * 1000 ; VBR Laufzeit
    $aID3[9][1] = 'VBR ~' & Int($iVBRFilesize * 8 / ($aID3[4][1] / 1000) / 1000) ; VBR durchschnittliche Bitrate
    EndIf
    Else
    If $aID3[4][1] = 0 Then $aID3[4][1] = (FileGetSize($sPath) * 8) / ($aID3[9][1] * 1000) * 1000 ; alternative CBR Laufzeit
    $aID3[9][1] = 'CBR ' & $aID3[9][1]
    EndIf
    $aID3[4][1] = _TicksToTimeFormat($aID3[4][1]) ; Laufzeit (Ticks to hour:min:sec)
    $aID3[9][1] &= ' kBit/s'
    $aID3[10][1] &= ' Hz'
    FileClose($hFile)
    Return SetError(0, 0, $aID3)
    EndFunc ;==>_ReadID3Tag

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

    ;===============================================================================
    ; Function Name: _TicksToTimeFormat($iTicks, $sFormat = '%hh:%mm:%ss')
    ; Description:: Diese Funktion wandelt Millisekunden in ein anzugebenes Zeitformat um
    ; Parameter(s): $iTicks = Zeit in Millisekunden
    ; $sFormat:
    ; %hh für Stunden
    ; %mm für Minuten
    ; %ss für Sekunden
    ; %ms für Millisekunden
    ; sonstige Zeichen, die dazwischen stehen, werden übernommen
    ; Requirement(s): -
    ; Return Value(s): Zeit im ausgewählten Format (String)
    ; Author(s): Oscar (http://www.autoit.de)
    ;===============================================================================
    Func _TicksToTimeFormat($iTicks, $sFormat = '%hh:%mm:%ss')
    Local $aTime[4] = [0, 0, 0, 0], $sOut, $aTimeFormat[4] = ['hh', 'mm', 'ss', 'ms'], $aFormat
    $aTime[2] = Int($iTicks / 1000)
    $aTime[3] = $iTicks - $aTime[2] * 1000
    $aTime[0] = Int($aTime[2] / 3600)
    $aTime[2] = Mod($aTime[2], 3600)
    $aTime[1] = Int($aTime[2] / 60)
    $aTime[2] = Mod($aTime[2], 60)
    $aFormat = StringRegExp($sFormat, '%([^%]+)', 3)
    If Not IsArray($aFormat) Then Return SetError(1, 0, $iTicks)
    For $i = 0 To UBound($aFormat) - 1
    For $j = 0 To UBound($aTimeFormat) - 1
    If StringLeft($aFormat[$i], 2) = $aTimeFormat[$j] Then $sOut &= StringFormat('%02i', $aTime[$j]) & StringMid($aFormat[$i], 3)
    Next
    Next
    Return $sOut
    EndFunc ;==>_TicksToTimeFormat

    [/autoit]

    Dateien

    _MP3Search.au3 25,65 kB – 220 Downloads
  • frage zu pixelsearch

    • Oscar
    • 29. Juli 2010 um 22:09

    Ich denke auch, die wesentlichen Hilfen wurden genannt und wenn nilsheigener nicht ausführlicher darauf eingeht, dann ist das hier zu Ende.

    [closed]

  • mp3 Searcher

    • Oscar
    • 29. Juli 2010 um 17:26

    Nee, das mit der Datenbank hat damit nichts zu tun (habe ich auch schon getestet).

    Tausch mal die Funktion "_WM_NOTIFY" gegen diese hier aus:

    [autoit]


    Func _WM_NOTIFY($hWnd, $msg, $wParam, $lParam)
    Local $hWndFrom, $iIDFrom, $iCode, $tNMHDR, $iSelected, $sExecutePath
    $tNMHDR = DllStructCreate($tagNMHDR, $lParam)
    $hWndFrom = HWnd(DllStructGetData($tNMHDR, 'hWndFrom'))
    $iCode = DllStructGetData($tNMHDR, 'Code')
    Switch $hWndFrom
    Case $hLVHandle
    Switch $iCode
    Case $NM_DBLCLK
    $iSelected = ControlListView($hGui, '', $hListView, 'GetSelected')
    $sExecutePath = _GUICtrlListView_GetItemText($hLVHandle, $iSelected, 8)
    ShellExecute($sExecutePath)
    EndSwitch
    EndSwitch
    Return $GUI_RUNDEFMSG
    EndFunc

    [/autoit]
  • mp3 Searcher

    • Oscar
    • 29. Juli 2010 um 17:15

    Ändere mal in Zeile 195:

    [autoit]

    $sExecutePath = _GUICtrlListView_GetItemText($hLVHandle, DllStructGetData($tInfo, "SubItem"), 8)

    [/autoit]


    das "SubItem" in "Item" und teste dann mal.
    Es hat mich nämlich schon gewundert, warum da bei mir der Index, also das Item ausgegeben wird. Aber bei mir funktioniert das nur mit "SubItem". Bei "Item" kommt bei mir immer "0" raus. ?(

  • mp3 Searcher

    • Oscar
    • 29. Juli 2010 um 16:37

    Also Win98 wird von AutoIt nicht mehr unterstützt. ^^

    Ich musste beim Löschen ja auch die Einträge aus dem Array löschen (das dauerte so lange, wegen umsortieren/ReDim).
    Jetzt bin ich aber noch auf _GUICtrlListView_SimpleSort gestossen und habe das mal ausprobiert. Das dauert zwar etwas länger als mit 2D-Array und _ArraySort, aber der Vorteil ist: das 2D-Array kann wegfallen, was beim Löschen von Einträgen einen erheblichen Zeitvorteil bringt. Kurzum: Ich habe alles wieder umgestellt. :D

    Außerdem kann man jetzt beim Laden und Speichern die Datei auswählen, wohin gespeichert bzw. von wo geladen werden soll. Das hat den Vorteil, dass man sich mehrere Datenbanken anlegen kann. :)
    Beim speichern wird automatisch die Endung ".db3" (ausgedacht) angehängt. Laden kann man auch nur Dateien mit dieser Endung.

    Und man kann jetzt einen Doppelklick auf einen Listview-Eintrag machen. Das entsprechende MP3 wird dann mit dem Standard-MP3-Player abgespielt.

    Skript:

    Spoiler anzeigen
    [autoit]


    #include <Array.au3>
    #include <ButtonConstants.au3>
    #include <ColorConstants.au3>
    #include <Date.au3>
    #include <GUIConstantsEx.au3>
    #include <GuiListView.au3>
    #include <GuiStatusBar.au3>
    #include <ListViewConstants.au3>
    #include <WindowsConstants.au3>

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

    Global $sHeader = 'Title|Artist|Length|Album|Year|MPEG-Version|Bitrate|Sample-Freq.|Path' ; Die Überschriften für das Listview
    Global $sInifile = @ScriptDir & '\MP3-Search.ini' ; Inidatei

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

    Global $iWidth = IniRead($sInifile, 'Config', 'Width', 770)
    Global $iHeight = IniRead($sInifile, 'Config', 'Height', 406)
    Global $iLeft = IniRead($sInifile, 'Config', 'Left', @DesktopWidth / 2 - 385)
    Global $iTop = IniRead($sInifile, 'Config', 'Top', @DesktopHeight / 2 - 203)

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

    #region Hauptfenster
    Global $sStyle = BitOR($GUI_SS_DEFAULT_GUI, $WS_MAXIMIZEBOX, $WS_SIZEBOX)
    Global $hGui = GUICreate('MP3-Search', 770, 406, $iLeft, $iTop, $sStyle) ; Hauptfenster erstellen
    GUISetBkColor(0xAAAAAA)

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

    Global $hListView = GUICtrlCreateListView($sHeader, 5, 5, 760, 330, $LVS_SHOWSELALWAYS) ; Listview erstellen
    GUICtrlSetResizing(-1, 2 + 4 + 32 + 64)
    Global $hLVHandle = GUICtrlGetHandle($hListView) ; das Handle vom Listview wird für die UDF-Listview-Funktionen benötigt
    _GUICtrlListView_SetColumnWidth($hLVHandle, 0, 180)
    _GUICtrlListView_SetColumnWidth($hLVHandle, 1, 180)
    _GUICtrlListView_SetColumnWidth($hLVHandle, 2, 60)
    _GUICtrlListView_SetColumnWidth($hLVHandle, 3, 120)
    _GUICtrlListView_SetColumnWidth($hLVHandle, 4, 60)
    _GUICtrlListView_SetColumnWidth($hLVHandle, 5, 100)
    _GUICtrlListView_SetColumnWidth($hLVHandle, 6, 100)
    _GUICtrlListView_SetColumnWidth($hLVHandle, 7, 90)
    _GUICtrlListView_SetColumnWidth($hLVHandle, 8, 800)

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

    Global $hSearch = GUICtrlCreateButton('Alle Festplatten durchsuchen', 10, 340, 120, 35, $BS_MULTILINE)
    GUICtrlSetResizing(-1, 512 + 64)
    Global $hSearchPath = GUICtrlCreateButton('Verzeichnis durchsuchen', 140, 340, 100, 35, $BS_MULTILINE)
    GUICtrlSetResizing(-1, 512 + 64)
    Global $hLoad = GUICtrlCreateButton('Laden', 250, 340, 70, 35)
    GUICtrlSetResizing(-1, 512 + 64)
    Global $hSave = GUICtrlCreateButton('Speichern', 330, 340, 70, 35)
    GUICtrlSetResizing(-1, 512 + 64)
    Global $hDel = GUICtrlCreateButton("Markierte Einträge löschen", 410, 340, 90, 35, $BS_MULTILINE)
    GUICtrlSetResizing(-1, 512 + 64)
    Global $hDelAll = GUICtrlCreateButton('Alle Einträge löschen', 510, 340, 90, 35, $BS_MULTILINE)
    GUICtrlSetResizing(-1, 512 + 64)

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

    Global $aParts[3] = [300, 360, -1], $aText[3] = ['Fertig.', '0', '']
    Global $hStatus = _GUICtrlStatusBar_Create($hGui, $aParts, $aText)
    #endregion Hauptfenster

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

    GUISetState(@SW_SHOW, $hGui) ; Hauptfenster sichtbar machen

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

    Global $fStop = False, $iLVCount = 0
    HotKeySet('{ESC}', '_Stop')

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

    Dim $aAccelKeys[1][2] = [['{DEL}', $hDel]] ; beim drücken der [Delete]-Taste wird "Case $hDel" ausgeführt
    GUISetAccelerators($aAccelKeys, $hGui)

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

    GUIRegisterMsg($WM_SIZE, '_WM_SIZE')
    GUIRegisterMsg($WM_MOVE, '_WM_MOVE')
    GUIRegisterMsg($WM_GETMINMAXINFO, '_WM_GETMINMAXINFO')
    GUIRegisterMsg($WM_NOTIFY, '_WM_NOTIFY')

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

    WinMove($hGui, '', $iLeft, $iTop, $iWidth, $iHeight)

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

    While 1
    Switch GUIGetMsg() ; anhand der Control-ID das entsprechende Case aufrufen
    Case $hSearch
    _GUICtrlListView_DeleteAllItems($hLVHandle) ; Alle Listview-Einträge löschen
    _GUICtrlStatusBar_SetText($hStatus, 0, 1)
    $iLVCount = 0 ; Zähler auf Null setzen
    $aDrives = DriveGetDrive('FIXED') ; Alle Festplatten-Buchstaben holen
    If Not @error Then
    GUISetCursor(15, 1, $hGui)
    For $i = 1 To $aDrives[0] ; Alle Festplatten durchgehen
    _GUICtrlStatusBar_SetText($hStatus, 'Durchsuche Festplatte "' & StringUpper($aDrives[$i]) & '\"', 0)
    _DriveSearch(StringUpper($aDrives[$i]))
    Next
    GUISetCursor(2, 1, $hGui)
    EndIf
    _GUICtrlStatusBar_SetText($hStatus, _GUICtrlListView_GetItemCount($hLVHandle), 1)
    _GUICtrlStatusBar_SetText($hStatus, '', 2)
    If $fStop Then
    $fStop = False
    _GUICtrlStatusBar_SetText($hStatus, 'Abgebrochen!', 0)
    Else
    _GUICtrlStatusBar_SetText($hStatus, 'Fertig.', 0)
    EndIf
    Case $hSearchPath
    $sPath = FileSelectFolder('Verzeichnis auswählen!', '', 2, '', $hGui)
    If FileExists($sPath) Then
    _GUICtrlListView_DeleteAllItems($hLVHandle) ; Alle Listview-Einträge löschen
    $iLVCount = 0 ; Zähler auf Null setzen
    GUISetCursor(15, 1, $hGui)
    _GUICtrlStatusBar_SetText($hStatus, 'Durchsuche Verzeichnis "' & $sPath & '"', 0)
    _DriveSearch($sPath)
    GUISetCursor(2, 1, $hGui)
    _GUICtrlStatusBar_SetText($hStatus, _GUICtrlListView_GetItemCount($hLVHandle), 1)
    _GUICtrlStatusBar_SetText($hStatus, '', 2)
    If $fStop Then
    $fStop = False
    _GUICtrlStatusBar_SetText($hStatus, 'Abgebrochen!', 0)
    Else
    _GUICtrlStatusBar_SetText($hStatus, 'Fertig.', 0)
    EndIf
    EndIf
    Case $hListView ; User hat auf eine Spaltenüberschrift geklickt (sortieren)
    If _GUICtrlListView_GetItemCount($hLVHandle) > 0 Then
    Dim $aDescending[_GUICtrlListView_GetColumnCount($hLVHandle)]
    GUISetCursor(15, 1, $hGui)
    $iTimer = TimerInit()
    _GUICtrlStatusBar_SetText($hStatus, 'Sortiere Daten! Bitte warten...', 0)
    _GUICtrlListView_SimpleSort($hLVHandle, $aDescending, GUICtrlGetState($hListView))
    _GUICtrlStatusBar_SetText($hStatus, _TicksToTimeFormat(TimerDiff($iTimer), '%mm:%ss.%ms'), 2)
    _GUICtrlStatusBar_SetText($hStatus, 'Fertig.', 0)
    GUISetCursor(2, 1, $hGui)
    EndIf
    Case $hLoad ; User hat auf 'Laden' geklickt
    GUISetCursor(15, 1, $hGui)
    _GUICtrlStatusBar_SetText($hStatus, 'Lade Daten...', 0)
    Load()
    _GUICtrlStatusBar_SetText($hStatus, 'Fertig.', 0)
    GUISetCursor(2, 1, $hGui)
    Case $hSave ; User hat auf 'Speichern' geklickt
    GUISetCursor(15, 1, $hGui)
    _GUICtrlStatusBar_SetText($hStatus, 'Speichere Daten...', 0)
    Save()
    _GUICtrlStatusBar_SetText($hStatus, 'Fertig.', 0)
    _GUICtrlStatusBar_SetText($hStatus, '', 2)
    GUISetCursor(2, 1, $hGui)
    Case $hDel
    GUISetCursor(15, 1, $hGui)
    _GUICtrlListView_DeleteItemsSelected($hLVHandle)
    _GUICtrlStatusBar_SetText($hStatus, _GUICtrlListView_GetItemCount($hLVHandle), 1)
    GUISetCursor(2, 1, $hGui)
    Case $hDelAll ; User hat auf 'Alle Einträge löschen' geklickt
    If MsgBox(256 + 32 + 4, 'Einträge löschen', 'Wollen sie wirklich alle Einträge löschen?') = 6 Then
    _GUICtrlListView_DeleteAllItems($hLVHandle)
    _GUICtrlStatusBar_SetText($hStatus, 0, 1)
    EndIf
    Case $GUI_EVENT_CLOSE ; User hat auf das Schließen-Symbol geklickt
    If MsgBox(32 + 4, 'Beenden', 'Wollen sie das Programm wirklich beenden?') = 6 Then _End() ; wenn ja, dann End-Funktion aufrufen
    EndSwitch
    WEnd

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

    Func _Stop()
    $fStop = True
    EndFunc ;==>_Stop

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

    Func _End()
    ;~ Save() ; wenn der vordere Kommentar entfernt wird, dann werden vor dem beenden noch die Daten gespeichert
    Exit ; Programm beenden
    EndFunc ;==>End

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

    Func _DriveSearch($sPath)
    Local $aNewMP3, $aID3Tags, $sNewItem, $aItem
    If StringRight($sPath, 1) <> '\' Then $sPath &= '\'
    _GUICtrlStatusBar_SetText($hStatus, 'Bitte warten...', 2)
    $aNewMP3 = _RecursiveFileListToArray($sPath, '\.mp3', 1) ; Alle MP3s auf der Festplatte auslesen
    If Not @error And $aNewMP3[0] > 0 Then
    _GUICtrlListView_SetItemCount($hListView, _GUICtrlListView_GetItemCount($hLVHandle) + $aNewMP3[0])
    _GUICtrlStatusBar_SetText($hStatus, 'Lese ID3-Tags... (' & $aNewMP3[0] & ')', 0)
    For $j = 1 To $aNewMP3[0] ; die gefundenen MP3s durchgehen
    $aID3Tags = _ReadID3Tag($aNewMP3[$j]) ; die ID3-Tags auslesen
    If Not @error Then
    For $k = 0 To 10
    $aID3Tags[$k][1] = StringReplace($aID3Tags[$k][1], '|', '') ; evtl. vorhandene "|" entfernen
    Next
    _GUICtrlStatusBar_SetText($hStatus, _GUICtrlListView_GetItemCount($hLVHandle), 1)
    _GUICtrlStatusBar_SetText($hStatus, $aNewMP3[$j], 2)
    $sNewItem = $aID3Tags[0][1] & '|' & $aID3Tags[1][1] & '|' & $aID3Tags[4][1] & '|' & $aID3Tags[2][1] & '|' & $aID3Tags[3][1]
    $sNewItem &= '|' & $aID3Tags[8][1] & '|' & $aID3Tags[9][1] & '|' & $aID3Tags[10][1] & '|' & $aNewMP3[$j]
    GUICtrlCreateListViewItem($sNewItem, $hListView)
    EndIf
    If $fStop Then ExitLoop
    Next
    EndIf
    EndFunc ;==>_DriveSearch

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

    Func _WM_NOTIFY($hWnd, $msg, $wParam, $lParam)
    Local $hWndFrom, $iIDFrom, $iCode, $tNMHDR, $tInfo, $sExecutePath
    $tNMHDR = DllStructCreate($tagNMHDR, $lParam)
    $hWndFrom = HWnd(DllStructGetData($tNMHDR, 'hWndFrom'))
    $iIDFrom = DllStructGetData($tNMHDR, 'IDFrom')
    $iCode = DllStructGetData($tNMHDR, 'Code')
    Switch $hWndFrom
    Case $hLVHandle
    Switch $iCode
    Case $NM_DBLCLK
    $tInfo = DllStructCreate($tagNMITEMACTIVATE, $lParam)
    $sExecutePath = _GUICtrlListView_GetItemText($hLVHandle, DllStructGetData($tInfo, "SubItem"), 8)
    ShellExecute($sExecutePath)
    EndSwitch
    EndSwitch
    Return $GUI_RUNDEFMSG
    EndFunc

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

    Func _WM_SIZE($hWnd, $msg, $wParam, $lParam)
    Local $aGuiPos = WinGetPos($hGui)
    If Not BitAND(WinGetState($hGui), 16) Then
    IniWrite($sInifile, 'Config', 'Width', $aGuiPos[2])
    IniWrite($sInifile, 'Config', 'Height', $aGuiPos[3])
    EndIf
    _GUICtrlStatusBar_Resize($hStatus)
    Return $GUI_RUNDEFMSG
    EndFunc ;==>WM_SIZE

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

    Func _WM_MOVE($hWnd, $msg, $wParam, $lParam)
    Local $aGuiPos = WinGetPos($hGui)
    If Not BitAND(WinGetState($hGui), 16) Then
    IniWrite($sInifile, 'Config', 'Left', $aGuiPos[0])
    IniWrite($sInifile, 'Config', 'Top', $aGuiPos[1])
    EndIf
    Return $GUI_RUNDEFMSG
    EndFunc

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

    Func _WM_GETMINMAXINFO($hWnd, $msg, $wParam, $lParam)
    If $hWnd = $hGui Then
    Local $minmaxinfo = DllStructCreate("int;int;int;int;int;int;int;int;int;int", $lParam)
    DllStructSetData($minmaxinfo, 7, 786) ; min X
    DllStructSetData($minmaxinfo, 8, 444) ; min Y
    ;~ DllStructSetData($minmaxinfo, 9, 800) ; max X
    ;~ DllStructSetData($minmaxinfo, 10, 800) ; max Y
    EndIf
    EndFunc

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

    Func Load() ; Datenbank-Datei laden
    Local $sDBFile, $hFile, $sContent, $aNewItems, $iTimer, $iCount
    FileChangeDir(@ScriptDir)
    $sDBFile = FileOpenDialog('MP3-Datenbank-Datei auswählen', @ScriptDir, 'MP3-Datenbank (*.db3)', 3, '', $hGui)
    If Not FileExists($sDBFile) Then Return
    $hFile = FileOpen($sDBFile, 0) ; Datei zum lesen öffnen
    If $hFile = -1 Then Return; wenn das öffnen nicht erfolgreich war, dann Funktion verlassen
    $sContent = FileRead($hFile) ; Datei komplett einlesen
    FileClose($hFile) ; Datei schließen
    $sContent = StringTrimRight($sContent, 2) ; das letzte @CRLF entfernen
    $aNewItems = StringSplit($sContent, @CRLF, 1) ; Den Dateiinhalt am Zeilenende splitten
    If Not IsArray($aNewItems) Then Return ; Wenn $aNewItems kein Array ist, dann Funktion verlassen
    _GUICtrlListView_DeleteAllItems($hLVHandle)
    _GUICtrlListView_SetItemCount($hLVHandle, $aNewItems[0])
    _GUICtrlStatusBar_SetText($hStatus, 'Lade Daten... (' & $aNewItems[0] & ')', 0)
    _GUICtrlListView_BeginUpdate($hLVHandle) ; Listview sperren
    $iTimer = TimerInit()
    For $i = 1 To $aNewItems[0] ; Alle Einträge des Arrays durchgehen
    $iCount += 1
    If TimerDiff($iTimer) > 100 Then
    $iTimer = TimerInit()
    _GUICtrlStatusBar_SetText($hStatus, $iCount, 1)
    EndIf
    GUICtrlCreateListViewItem($aNewItems[$i], $hListView) ; mit den eingelesenen Daten einen neuen Listview-Eintrag erstellen
    Next
    _GUICtrlStatusBar_SetText($hStatus, $iCount, 1)
    _GUICtrlListView_EndUpdate($hLVHandle) ; Listview wieder freigeben
    EndFunc ;==>Load

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

    Func Save() ; Datenbank-Datei speichern
    Local $sDBFile, $hFile, $iCount, $iTimer
    $sDBFile = FileSaveDialog('MP3-Datenbank-Datei auswählen', '', 'MP3-Datenbank (*.db3)', 18, '', $hGui)
    If @error Then Return
    If StringRight($sDBFile, 4) <> '.db3' Then $sDBFile &= '.db3'
    $iCount = _GUICtrlListView_GetItemCount($hLVHandle); Anzahl der Listview-Einträge holen
    If $iCount = 0 Then Return ; Wenn das Listview keine Einträge enthält, dann Funktion verlassen
    $hFile = FileOpen($sDBFile, 2) ; Datei zum speichern (überschreiben) öffnen
    If $hFile = -1 Then Return; wenn das öffnen nicht erfolgreich war, dann Funktion verlassen
    $iTimer = TimerInit()
    For $i = 0 To $iCount - 1 ; Schleife, um alle Listview-Einträge durchzugehen
    FileWriteLine($hFile, _GUICtrlListView_GetItemTextString($hLVHandle, $i))
    If TimerDiff($iTimer) > 100 Then
    $iTimer = TimerInit()
    _GUICtrlStatusBar_SetText($hStatus, $i + 1, 2)
    EndIf
    Next
    FileClose($hFile) ; Datei schließen
    EndFunc ;==>Save

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

    ;===============================================================================
    ; Function Name: _RecursiveFileListToArray($sPath[, $sPattern][, $iFlag][, $iFormat][, $iRecursion][, $sDelim])
    ; Description:: gibt Verzeichnisse (rekursiv) und/oder Dateien zurück, die einem RegExp-Pattern entsprechen
    ; Parameter(s): $sPath = Startverzeichnis
    ; $sPattern = ein beliebiges RexExp-Pattern für die Auswahl
    ; $iFlag = Auswahl
    ; 0 = Dateien & Verzeichnisse
    ; 1 = nur Dateien
    ; 2 = nur Verzeichnisse
    ; $iFormat = Rückgabeformat
    ; 0 = String
    ; 1 = Array mit [0] = Anzahl
    ; 2 = Nullbasiertes Array
    ; $iRecursion = Verzeichnisse rekursiv durchsuchen
    ; 0 = Nein
    ; 1 = Ja
    ; $sDelim = Trennzeichen für die String-Rückgabe
    ; Requirement(s): AutoIt 3.3.0.0
    ; Return Value(s): Array/String mit den gefundenen Dateien/Verzeichnissen
    ; Author(s): Oscar (http://www.autoit.de)
    ; Anregungen von: bernd670 (http://www.autoit.de)
    ;===============================================================================
    Func _RecursiveFileListToArray($sPath, $sPattern = '', $iFlag = 0, $iFormat = 1, $iRecursion = 1, $sDelim = @CRLF)
    Local $hSearch, $sFile, $sReturn = ''
    If StringRight($sPath, 1) <> '\' Then $sPath &= '\'
    $hSearch = FileFindFirstFile($sPath & '*.*')
    If @error Or $hSearch = -1 Then Return SetError(1, 0, $sReturn)
    While Not $fStop
    $sFile = FileFindNextFile($hSearch)
    If @error Then ExitLoop
    If @extended Then
    If StringRegExp($sPath & $sFile, $sPattern) And ($iFlag = 0 Or $iFlag = 2) Then $sReturn &= $sPath & $sFile & '\' & $sDelim
    If $iRecursion Then $sReturn &= _RecursiveFileListToArray($sPath & $sFile & '\', $sPattern, $iFlag, 0)
    ContinueLoop
    EndIf
    If StringRegExp($sFile, $sPattern) And ($iFlag = 0 Or $iFlag = 1) Then $sReturn &= $sPath & $sFile & $sDelim
    WEnd
    FileClose($hSearch)
    If $iFormat And $sReturn = '' Then Return StringSplit($sReturn, '', $iFormat)
    If $iFormat Then Return StringSplit(StringTrimRight($sReturn, StringLen($sDelim)), $sDelim, $iFormat)
    Return $sReturn
    EndFunc ;==>_RecursiveFileListToArray

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

    ;===============================================================================
    ; Function Name: _ReadID3Tag($sPath)
    ; Description:: gibt ein Array mit den Daten aus den ID3-Tags zurück
    ; unterstützt werden die ID3-Tag-Versionen 1.0, 1.1, 2.3 und 2.4
    ; bei v2.4 müssen sich die ID3-Tags am Anfang der Datei befinden
    ; Parameter(s): $sPath = Pfad zu einer MP3-Datei
    ; Requirement(s): min. AutoIt v3.3.0.0
    ; Return Value(s): bei Erfolg: Array mit den ID3-Tagdaten (@error = 0)
    ; im Fehlerfall bekommt @error:
    ; 1 = Datei existiert nicht
    ; 2 = Datei konnte nicht zum lesen geöffnet werden
    ; 3 = falsche ID3 v2 Version
    ; 4 = Datei ist keine MP3-Datei
    ; Author(s): Oscar (http://www.autoit.de)
    ;===============================================================================
    Func _ReadID3Tag($sPath)
    If Not FileExists($sPath) Then Return SetError(1, 0, 0)
    Local $hFile, $sData, $sID3Header, $iID3HeaderSize = 0, $iOffset, $iSize, $tmp
    Local $aID3v2Tags[8] = ['TIT2', 'TPE1', 'TALB', 'TYER', 'TLEN', 'TRCK', 'TCON', 'TENC']
    Local $aID3[11][2] = [ _
    ['Title', ''],['Artist', ''],['Album', ''],['Year', ''], _
    ['Length', '0'],['Track', ''],['Genre', ''],['Encoder', ''], _
    ['MPEG-Version', ''],['Bitrate', '-'],['Sample-Freq.', '']]
    Local $aMP3Version[4] = ['MPEG2.5', 'Reserved', 'MPEG2', 'MPEG1']
    Local $aMP3Layer[4] = ['Reserved', 'Layer III', 'Layer II', 'Layer I']
    Local $aMP3Bitrate[5][16] = [ _
    [000, 032, 064, 096, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448, 000], _
    [000, 032, 048, 056, 064, 080, 096, 112, 128, 160, 192, 224, 256, 320, 384, 000], _
    [000, 032, 040, 048, 056, 064, 080, 096, 112, 128, 160, 192, 224, 256, 320, 000], _
    [000, 032, 048, 056, 064, 080, 096, 112, 128, 144, 160, 176, 192, 224, 256, 000], _
    [000, 008, 016, 024, 032, 040, 048, 056, 064, 080, 096, 112, 128, 144, 160, 000]]
    Local $aSampleFreq[3][4] = [[44100, 48000, 32000, 0],[22050, 24000, 16000, 0],[11025, 12000, 8000, 0]]
    Local $sMP3FrameHeader, $iMP3Version, $sMP3Version, $sMP3Layer, $iMP3Bitrate, $iMP3SampleFreq
    Local $iVBRFrames = -1, $iVBRFilesize, $iVBRFlags
    $hFile = FileOpen($sPath, 16)
    If $hFile = -1 Then Return SetError(2, 0, 0)
    $sData = Binary(FileRead($hFile, 4))
    If BinaryMid($sData, 1, 3) = '0x494433' Then ; ID3 v2.x Kennung gefunden
    If (BinaryMid($sData, 4, 1) = '0x03') Or (BinaryMid($sData, 4, 1) = '0x04') Then ; nur v2.3 und 2.4
    FileRead($hFile, 2) ; 2 Bytes überspringen
    For $i = 0 To 3 ; berechne ID3-Headergröße (4 Bytes, jedoch nur jeweils die unteren 7 Bit)
    $iID3HeaderSize = BitShift($iID3HeaderSize, -7) + BitAND(Binary(FileRead($hFile, 1)), 0x7F)
    Next
    If $iID3HeaderSize > 0 Then
    $sID3Header = Binary(FileRead($hFile, $iID3HeaderSize)) ; lese gesamten ID3-Header
    For $i = 0 To 7
    $iOffset = StringInStr(BinaryToString($sID3Header), $aID3v2Tags[$i]) ; Offset zu dem ID3-Tag
    If $iOffset > 0 Then
    $iSize = Hex(BinaryMid($sID3Header, $iOffset + 4, 4)) ; Größe des ID3-Frames
    $tmp = BinaryMid($sID3Header, $iOffset + 11, Dec($iSize) - 1)
    If BinaryMid($tmp, 1, 2) = '0xFFFE' Then
    For $x = 3 To BinaryLen($tmp) Step 2
    $aID3[$i][1] &= BinaryToString(BinaryMid($tmp, $x, 2), 2)
    Next
    Else
    For $x = 1 To BinaryLen($tmp)
    $aID3[$i][1] &= BinaryToString(BinaryMid($tmp, $x, 1))
    Next
    EndIf
    $aID3[$i][1] = StringReplace($aID3[$i][1], Chr(0), '')
    EndIf
    Next
    EndIf
    Do
    $sData = String(FileRead($hFile, 1))
    If @error Then ExitLoop
    If BitAND($sData, 0xff) = 0xff Then
    FileSetPos($hFile, -1, 1)
    $sData = String(FileRead($hFile, 4))
    EndIf
    Until BitAND($sData, 0xFFE00000) = 0xFFE00000
    Else
    FileClose($hFile)
    Return SetError(3, 0, 0)
    EndIf
    Else ; ID3 v1.x
    $iOffset = FileGetPos($hFile)
    FileSetPos($hFile, -128, 2)
    $sID3Header = BinaryToString(FileRead($hFile, 3))
    If $sID3Header = 'TAG' Then
    $aID3[0][1] = StringReplace(BinaryToString(FileRead($hFile, 30)), Chr(0), '')
    $aID3[1][1] = StringReplace(BinaryToString(FileRead($hFile, 30)), Chr(0), '')
    $aID3[2][1] = StringReplace(BinaryToString(FileRead($hFile, 30)), Chr(0), '')
    $aID3[3][1] = StringReplace(BinaryToString(FileRead($hFile, 4)), Chr(0), '')
    EndIf
    FileSetPos($hFile, $iOffset, 0)
    EndIf
    $sMP3FrameHeader = String($sData)
    If BitAND($sMP3FrameHeader, 0xFFE00000) <> 0xFFE00000 Then
    FileClose($hFile)
    Return SetError(4, 0, 0) ; keine MP3-Datei, dann Return
    EndIf
    $iMP3Version = BitShift(BitXOR($sMP3FrameHeader, 0xFFE00000), 19) ; welche MP3-Version
    $sMP3Version = $aMP3Version[$iMP3Version] ; in Textform
    $sMP3Layer = $aMP3Layer[BitShift(BitAND($sMP3FrameHeader, 0x60000), 17)] ; welcher Layer
    $aID3[8][1] = $sMP3Version & ' / ' & $sMP3Layer ; ins Ausgabe-Array
    $iMP3Bitrate = BitShift(BitAND($sMP3FrameHeader, 0xF000), 12) ; Bitraten-Index auslesen
    Switch $sMP3Version ; je nach MPEG-Version Bitrate aus der Tabelle holen
    Case 'MPEG1'
    $aID3[9][1] = $aMP3Bitrate[$iMP3Version - ($iMP3Version > 1)][$iMP3Bitrate]
    Case 'MPEG2', 'MPEG2.5'
    If $sMP3Layer = 'Layer I' Then
    $aID3[9][1] = $aMP3Bitrate[3][$iMP3Bitrate]
    Else
    $aID3[9][1] = $aMP3Bitrate[4][$iMP3Bitrate]
    EndIf
    EndSwitch
    $iMP3SampleFreq = BitShift(BitAND($sMP3FrameHeader, 0xC00), 10) ; Sample-Frequenz-Index auslesen
    $aID3[10][1] = $aSampleFreq[2 - ($iMP3Version - ($iMP3Version > 1))][$iMP3SampleFreq] ; und Wert aus der Tabelle holen
    Do ; evtl. Leerbytes überspringen
    $tmp = FileRead($hFile, 1)
    If @error Then ExitLoop
    Until $tmp <> 0x00 Or @error
    If $tmp = 0x58 And BinaryToString(FileRead($hFile, 3)) = 'ing' Then ; MP3 mit VBR (Xing-Header gefunden)?
    $iVBRFlags = '0x' & Hex(FileRead($hFile, 4)) ; VBR-Flags auslesen
    If BitAND($iVBRFlags, 0x3) Then ; wenn die Einträge vorhanden sind, dann...
    $iVBRFrames = Dec(Hex(FileRead($hFile, 4))) ; Anzahl der VBR-Frames auslesen
    $iVBRFilesize = Dec(Hex(FileRead($hFile, 4))) ; Dateigröße auslesen
    $aID3[4][1] = $iVBRFrames * 1152 / $aID3[10][1] * 1000 ; VBR Laufzeit
    $aID3[9][1] = 'VBR ~' & Int($iVBRFilesize * 8 / ($aID3[4][1] / 1000) / 1000) ; VBR durchschnittliche Bitrate
    EndIf
    Else
    If $aID3[4][1] = 0 Then $aID3[4][1] = (FileGetSize($sPath) * 8) / ($aID3[9][1] * 1000) * 1000 ; alternative CBR Laufzeit
    $aID3[9][1] = 'CBR ' & $aID3[9][1]
    EndIf
    $aID3[4][1] = _TicksToTimeFormat($aID3[4][1]) ; Laufzeit (Ticks to hour:min:sec)
    $aID3[9][1] &= ' kBit/s'
    $aID3[10][1] &= ' Hz'
    FileClose($hFile)
    Return SetError(0, 0, $aID3)
    EndFunc ;==>_ReadID3Tag

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

    ;===============================================================================
    ; Function Name: _TicksToTimeFormat($iTicks, $sFormat = '%hh:%mm:%ss')
    ; Description:: Diese Funktion wandelt Millisekunden in ein anzugebenes Zeitformat um
    ; Parameter(s): $iTicks = Zeit in Millisekunden
    ; $sFormat:
    ; %hh für Stunden
    ; %mm für Minuten
    ; %ss für Sekunden
    ; %ms für Millisekunden
    ; sonstige Zeichen, die dazwischen stehen, werden übernommen
    ; Requirement(s): -
    ; Return Value(s): Zeit im ausgewählten Format (String)
    ; Author(s): Oscar (http://www.autoit.de)
    ;===============================================================================
    Func _TicksToTimeFormat($iTicks, $sFormat = '%hh:%mm:%ss')
    Local $aTime[4] = [0, 0, 0, 0], $sOut, $aTimeFormat[4] = ['hh', 'mm', 'ss', 'ms'], $aFormat
    $aTime[2] = Int($iTicks / 1000)
    $aTime[3] = $iTicks - $aTime[2] * 1000
    $aTime[0] = Int($aTime[2] / 3600)
    $aTime[2] = Mod($aTime[2], 3600)
    $aTime[1] = Int($aTime[2] / 60)
    $aTime[2] = Mod($aTime[2], 60)
    $aFormat = StringRegExp($sFormat, '%([^%]+)', 3)
    If Not IsArray($aFormat) Then Return SetError(1, 0, $iTicks)
    For $i = 0 To UBound($aFormat) - 1
    For $j = 0 To UBound($aTimeFormat) - 1
    If StringLeft($aFormat[$i], 2) = $aTimeFormat[$j] Then $sOut &= StringFormat('%02i', $aTime[$j]) & StringMid($aFormat[$i], 3)
    Next
    Next
    Return $sOut
    EndFunc ;==>_TicksToTimeFormat

    [/autoit]

    Edit: Kleinen Bug behoben.

    Dateien

    _MP3Search.au3 23,26 kB – 240 Downloads
  • mp3 Searcher

    • Oscar
    • 29. Juli 2010 um 14:45

    Mit "Geschwindikeit ohne Speichern" meinst Du vermutlich das einlesen/durchsuchen der Festplatten, oder?
    Wenn ja, das ist normal. Die Funktion muss ja alle Dateien auf den Festplatten durchgehen. Ganz witzig in diesem Zusammenhang ist, dass, wenn man die Funktion ein zweites Mal (gleich danach) aufruft, es dann wesentlich schneller geht (Verzeichnisse/Dateien befinden sich im Cache).

    Ressourcenverbrauch ist normal.

    Geschwindigkeit auch, bis auf das mit dem Löschen. Das könnte evtl. auch schneller gehen, wenn man alle Einträge löscht und neu erstellen lässt (analog zum sortieren). Muss ich mal testen...

  • mp3 Searcher

    • Oscar
    • 29. Juli 2010 um 11:27

    Das mit dem Fenster anpassen habe ich jetzt mal auf ReSizing gesetzt. Das Fenster kann also in der Größe verändert werden (wird abgespeichert).

    Die Buttons waren eigentlich noch nicht vollzählig. ;)
    Da habe ich jetzt noch [Verzeichnis durchsuchen] hinzugefügt und dann etwas zusammengerückt.

    Das mit der DEL-Taste kannst Du so nicht machen. Es sieht zwar erstmal richtig aus, aber dabei wird das 2D-Array nicht angepasst und beim nächsten sortieren sind die Einträge wieder da. Ich hab's mal kommentiert (so ist es einfacher).

    Beim sortieren wird jetzt unten in der Statusleiste angezeigt, was das Programm gerade macht (mit Zeitstempel wie lange es dafür gebraucht hat).

    Skript:

    Spoiler anzeigen
    [autoit]


    #include <Array.au3>
    #include <ButtonConstants.au3>
    #include <ColorConstants.au3>
    #include <Date.au3>
    #include <GUIConstantsEx.au3>
    #include <GuiListView.au3>
    #include <GuiStatusBar.au3>
    #include <ListViewConstants.au3>
    #include <WindowsConstants.au3>

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

    Global $sHeader = 'Title|Artist|Album|Year|Length|MPEG-Version|Bitrate|Sample-Freq.|Path' ; Die Überschriften für das Listview
    Global $sDBFile = @ScriptDir & '\MP3-Search.txt' ; Pfad und Name der Datenbank-Datei
    Global $sInifile = @ScriptDir & '\MP3-Search.ini' ; Inidatei
    Global $aListview[1][9]

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

    Global $iWidth = IniRead($sInifile, 'Config', 'Width', 770)
    Global $iHeight = IniRead($sInifile, 'Config', 'Height', 406)
    Global $iLeft = IniRead($sInifile, 'Config', 'Left', @DesktopWidth / 2 - 385)
    Global $iTop = IniRead($sInifile, 'Config', 'Top', @DesktopHeight / 2 - 203)

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

    #region Hauptfenster
    Global $sStyle = BitOR($GUI_SS_DEFAULT_GUI, $WS_MAXIMIZEBOX, $WS_SIZEBOX)
    Global $hGui = GUICreate('MP3-Search', 770, 406, $iLeft, $iTop, $sStyle) ; Hauptfenster erstellen
    GUISetBkColor(0xAAAAAA)

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

    Global $hListView = GUICtrlCreateListView($sHeader, 5, 5, 760, 330, $LVS_SHOWSELALWAYS) ; Listview erstellen
    GUICtrlSetResizing(-1, 2 + 4 + 32 + 64)
    Global $hLVHandle = GUICtrlGetHandle($hListView) ; das Handle vom Listview wird für die UDF-Listview-Funktionen benötigt
    _GUICtrlListView_SetColumn($hLVHandle, 0, 'Title', 180, 0)
    _GUICtrlListView_SetColumn($hLVHandle, 1, 'Artist', 180, 0)
    _GUICtrlListView_SetColumn($hLVHandle, 2, 'Length', 60, 0)
    _GUICtrlListView_SetColumn($hLVHandle, 3, 'Album', 120, 0)
    _GUICtrlListView_SetColumn($hLVHandle, 4, 'Year', 60, 0)
    _GUICtrlListView_SetColumn($hLVHandle, 5, 'MPEG-Version', 100, 0)
    _GUICtrlListView_SetColumn($hLVHandle, 6, 'Bitrate', 100, 0)
    _GUICtrlListView_SetColumn($hLVHandle, 7, 'Sample-Freq.', 90, 0)
    _GUICtrlListView_SetColumn($hLVHandle, 8, 'Path', 800, 0)

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

    Global $hSearch = GUICtrlCreateButton('Alle Festplatten durchsuchen', 10, 340, 120, 35, $BS_MULTILINE)
    GUICtrlSetResizing(-1, 512 + 64)
    Global $hSearchPath = GUICtrlCreateButton('Verzeichnis durchsuchen', 140, 340, 100, 35, $BS_MULTILINE)
    GUICtrlSetResizing(-1, 512 + 64)
    Global $hLoad = GUICtrlCreateButton('Laden', 250, 340, 70, 35)
    GUICtrlSetResizing(-1, 512 + 64)
    Global $hSave = GUICtrlCreateButton('Speichern', 330, 340, 70, 35)
    GUICtrlSetResizing(-1, 512 + 64)
    Global $hDel = GUICtrlCreateButton("Markierte Einträge löschen", 410, 340, 90, 35, $BS_MULTILINE)
    GUICtrlSetResizing(-1, 512 + 64)
    Global $hDelAll = GUICtrlCreateButton('Alle Einträge löschen', 510, 340, 90, 35, $BS_MULTILINE)
    GUICtrlSetResizing(-1, 512 + 64)

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

    Global $aParts[3] = [300, 360, -1], $aText[3] = ['Fertig.', '0', '']
    Global $hStatus = _GUICtrlStatusBar_Create($hGui, $aParts, $aText)
    #endregion Hauptfenster

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

    GUISetState(@SW_SHOW, $hGui) ; Hauptfenster sichtbar machen

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

    Global $fStop = False, $iLVCount = 0
    HotKeySet('{ESC}', '_Stop')

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

    Dim $aAccelKeys[1][2] = [['{DEL}', $hDel]] ; beim drücken der [Delete]-Taste wird "Case $hDel" ausgeführt
    GUISetAccelerators($aAccelKeys, $hGui)

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

    GUIRegisterMsg($WM_SIZE, '_WM_SIZE')
    GUIRegisterMsg($WM_MOVE, '_WM_MOVE')
    GUIRegisterMsg($WM_GETMINMAXINFO, '_WM_GETMINMAXINFO')

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

    WinMove($hGui, '', $iLeft, $iTop, $iWidth, $iHeight)

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

    While 1
    Switch GUIGetMsg() ; anhand der Control-ID das entsprechende Case aufrufen
    Case $hSearch
    _GUICtrlListView_DeleteAllItems($hLVHandle) ; Alle Listview-Einträge löschen
    $iLVCount = 0 ; Zähler auf Null setzen
    $aDrives = DriveGetDrive('FIXED') ; Alle Festplatten-Buchstaben holen
    If Not @error Then
    GUISetCursor(15, 1, $hGui)
    For $i = 1 To $aDrives[0] ; Alle Festplatten durchgehen
    _GUICtrlStatusBar_SetText($hStatus, 'Durchsuche Festplatte "' & StringUpper($aDrives[$i]) & '"', 0)
    _DriveSearch(StringUpper($aDrives[$i]))
    Next
    GUISetCursor(2, 1, $hGui)
    EndIf
    _GUICtrlStatusBar_SetText($hStatus, $iLVCount, 1)
    _GUICtrlStatusBar_SetText($hStatus, '', 2)
    If $fStop Then
    $fStop = False
    _GUICtrlStatusBar_SetText($hStatus, 'Abgebrochen!', 0)
    Else
    _GUICtrlStatusBar_SetText($hStatus, 'Fertig.', 0)
    EndIf
    Case $hSearchPath
    $sPath = FileSelectFolder('Verzeichnis auswählen!', '', 2, '', $hGui)
    If FileExists($sPath) Then
    _GUICtrlListView_DeleteAllItems($hLVHandle) ; Alle Listview-Einträge löschen
    $iLVCount = 0 ; Zähler auf Null setzen
    GUISetCursor(15, 1, $hGui)
    _GUICtrlStatusBar_SetText($hStatus, 'Durchsuche Verzeichnis "' & $sPath & '"', 0)
    _DriveSearch($sPath)
    GUISetCursor(2, 1, $hGui)
    _GUICtrlStatusBar_SetText($hStatus, $iLVCount, 1)
    _GUICtrlStatusBar_SetText($hStatus, '', 2)
    If $fStop Then
    $fStop = False
    _GUICtrlStatusBar_SetText($hStatus, 'Abgebrochen!', 0)
    Else
    _GUICtrlStatusBar_SetText($hStatus, 'Fertig.', 0)
    EndIf
    EndIf
    Case $hListView ; User hat auf eine Spaltenüberschrift geklickt
    If $iLVCount > 0 Then
    GUISetCursor(15, 1, $hGui)
    _GUICtrlStatusBar_SetBkColor($hStatus, $CLR_MONEYGREEN)
    _GUICtrlStatusBar_SetText($hStatus, 'Sortiere Daten! Bitte warten...', 0)
    $iSort = GUICtrlGetState($hListView)
    $iTimer = TimerInit()
    _GUICtrlStatusBar_SetText($hStatus, '[' & _TicksToTimeFormat(TimerDiff($iTimer), '%mm:%ss.%ms') & '] Sortiere nach Spalte: ' & $iSort, 2)
    _ArraySort($aListview, 0, 0, 0, $iSort)
    _GUICtrlStatusBar_SetText($hStatus, '[' & _TicksToTimeFormat(TimerDiff($iTimer), '%mm:%ss.%ms') & '] Lösche alle Einträge', 2)
    _GUICtrlListView_DeleteAllItems($hLVHandle)
    _GUICtrlStatusBar_SetText($hStatus, '[' & _TicksToTimeFormat(TimerDiff($iTimer), '%mm:%ss.%ms') & '] Einträge neu erstellen', 2)
    _GUICtrlListView_BeginUpdate($hLVHandle) ; Listview sperren
    _GUICtrlListView_AddArray($hLVHandle, $aListview)
    _GUICtrlListView_EndUpdate($hLVHandle) ; Listview wieder freigeben
    _GUICtrlStatusBar_SetText($hStatus, '[' & _TicksToTimeFormat(TimerDiff($iTimer), '%mm:%ss.%ms') & '] Sortiert.', 2)
    _GUICtrlStatusBar_SetText($hStatus, 'Fertig.', 0)
    _GUICtrlStatusBar_SetBkColor($hStatus, $CLR_DEFAULT)
    GUISetCursor(2, 1, $hGui)
    EndIf
    Case $hLoad ; User hat auf 'Laden' geklickt
    GUISetCursor(15, 1, $hGui)
    _GUICtrlStatusBar_SetText($hStatus, 'Lade Daten...', 0)
    Load()
    _GUICtrlStatusBar_SetText($hStatus, 'Fertig.', 0)
    GUISetCursor(2, 1, $hGui)
    Case $hSave ; User hat auf 'Speichern' geklickt
    GUISetCursor(15, 1, $hGui)
    _GUICtrlStatusBar_SetText($hStatus, 'Speichere Daten...', 0)
    Save()
    _GUICtrlStatusBar_SetText($hStatus, 'Fertig.', 0)
    _GUICtrlStatusBar_SetText($hStatus, '', 2)
    GUISetCursor(2, 1, $hGui)
    Case $hDel
    $aSelectedItems = _GUICtrlListView_GetSelectedIndices($hLVHandle, True)
    If $aSelectedItems[0] > 0 Then
    GUISetCursor(15, 1, $hGui)
    For $i = $aSelectedItems[0] To 1 Step -1
    _ArrayDelete($aListview, $aSelectedItems[$i])
    Next
    _GUICtrlListView_DeleteItemsSelected($hLVHandle)
    $iLVCount -= $aSelectedItems[0]
    _GUICtrlStatusBar_SetText($hStatus, $iLVCount, 1)
    GUISetCursor(2, 1, $hGui)
    EndIf
    Case $hDelAll ; User hat auf 'Alle Einträge löschen' geklickt
    If MsgBox(256 + 32 + 4, 'Einträge löschen', 'Wollen sie wirklich alle Einträge löschen?') = 6 Then
    _GUICtrlListView_DeleteAllItems($hLVHandle)
    ReDim $aListview[1][9]
    $iLVCount = 0
    _GUICtrlStatusBar_SetText($hStatus, $iLVCount, 1)
    EndIf
    Case $GUI_EVENT_CLOSE ; User hat auf das Schließen-Symbol geklickt (bzw. die ESC-Taste gedrückt)
    If MsgBox(32 + 4, 'Beenden', 'Wollen sie das Programm wirklich beenden?') = 6 Then _End() ; wenn ja, dann End-Funktion aufrufen
    EndSwitch
    WEnd

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

    Func _Stop()
    $fStop = True
    EndFunc ;==>_Stop

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

    Func _End()
    ;~ Save() ; wenn der vordere Kommentar entfernt wird, dann werden vor dem beenden noch die Daten gespeichert
    Exit ; Programm beenden
    EndFunc ;==>End

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

    Func _DriveSearch($sPath)
    Local $aNewMP3, $aID3Tags, $sNewItem, $aItem
    If StringRight($sPath, 1) <> '\' Then $sPath &= '\'
    _GUICtrlStatusBar_SetText($hStatus, 'Bitte warten...', 2)
    $aNewMP3 = _RecursiveFileListToArray($sPath, '\.mp3', 1) ; Alle MP3s auf der Festplatte auslesen
    If Not @error And $aNewMP3[0] > 0 Then
    _GUICtrlListView_SetItemCount($hListView, $iLVCount + $aNewMP3[0])
    ReDim $aListview[$iLVCount + $aNewMP3[0] + 1][9]
    _GUICtrlStatusBar_SetText($hStatus, 'Lese ID3-Tags... (' & $aNewMP3[0] & ')', 0)
    For $j = 1 To $aNewMP3[0] ; die gefundenen MP3s durchgehen
    _GUICtrlStatusBar_SetText($hStatus, $iLVCount, 1)
    $aID3Tags = _ReadID3Tag($aNewMP3[$j]) ; die ID3-Tags auslesen
    If Not @error Then
    For $k = 0 To 10
    $aID3Tags[$k][1] = StringReplace($aID3Tags[$k][1], '|', '') ; evtl. vorhandene "|" entfernen
    Next
    _GUICtrlStatusBar_SetText($hStatus, $aNewMP3[$j], 2)
    $sNewItem = $aID3Tags[0][1] & '|' & $aID3Tags[1][1] & '|' & $aID3Tags[4][1] & '|' & $aID3Tags[2][1] & '|' & $aID3Tags[3][1]
    $sNewItem &= '|' & $aID3Tags[8][1] & '|' & $aID3Tags[9][1] & '|' & $aID3Tags[10][1] & '|' & $aNewMP3[$j]
    $aItem = StringSplit($sNewItem, '|')
    For $k = 1 To $aItem[0]
    $aListview[$iLVCount][$k - 1] = $aItem[$k]
    Next
    GUICtrlCreateListViewItem($sNewItem, $hListView)
    $iLVCount += 1
    EndIf
    If $fStop Then ExitLoop
    Next
    ReDim $aListview[$iLVCount][9]
    EndIf
    EndFunc ;==>_DriveSearch

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

    Func _WM_SIZE($hWnd, $msg, $wParam, $lParam)
    Local $aGuiPos = WinGetPos($hGui)
    If Not BitAND(WinGetState($hGui), 16) Then
    IniWrite($sInifile, 'Config', 'Width', $aGuiPos[2])
    IniWrite($sInifile, 'Config', 'Height', $aGuiPos[3])
    EndIf
    _GUICtrlStatusBar_Resize($hStatus)
    Return $GUI_RUNDEFMSG
    EndFunc ;==>WM_SIZE

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

    Func _WM_MOVE($hWnd, $msg, $wParam, $lParam)
    Local $aGuiPos = WinGetPos($hGui)
    If Not BitAND(WinGetState($hGui), 16) Then
    IniWrite($sInifile, 'Config', 'Left', $aGuiPos[0])
    IniWrite($sInifile, 'Config', 'Top', $aGuiPos[1])
    EndIf
    Return $GUI_RUNDEFMSG
    EndFunc

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

    Func _WM_GETMINMAXINFO($hWnd, $msg, $wParam, $lParam)
    If $hWnd = $hGui Then
    Local $minmaxinfo = DllStructCreate("int;int;int;int;int;int;int;int;int;int", $lParam)
    DllStructSetData($minmaxinfo, 7, 786) ; min X
    DllStructSetData($minmaxinfo, 8, 444) ; min Y
    ;~ DllStructSetData($minmaxinfo, 9, 800) ; max X
    ;~ DllStructSetData($minmaxinfo, 10, 800) ; max Y
    EndIf
    EndFunc

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

    Func Load() ; Datenbank-Datei laden
    Local $hFile, $sContent, $aNewItems, $iTimer, $iCount, $aItem
    $hFile = FileOpen($sDBFile, 0) ; Datei zum lesen öffnen
    If $hFile <> -1 Then ; wenn das öffnen erfolgreich war, dann...
    $sContent = FileRead($hFile) ; Datei komplett einlesen
    FileClose($hFile) ; Datei schließen
    $sContent = StringTrimRight($sContent, 2) ; das letzte @CRLF entfernen
    $aNewItems = StringSplit($sContent, @CRLF, 1) ; Den Dateiinhalt am Zeilenende splitten
    If Not IsArray($aNewItems) Then Return ; Wenn $aNewItems kein Array ist, dann Funktion verlassen
    _GUICtrlListView_DeleteAllItems($hLVHandle)
    _GUICtrlListView_SetItemCount($hLVHandle, $aNewItems[0])
    Global $aListview[$aNewItems[0]][9]
    _GUICtrlStatusBar_SetText($hStatus, 'Lade Daten... (' & $aNewItems[0] & ')', 0)
    _GUICtrlListView_BeginUpdate($hLVHandle) ; Listview sperren
    $iTimer = TimerInit()
    For $i = 1 To $aNewItems[0] ; Alle Einträge des Arrays durchgehen
    $iCount += 1
    If TimerDiff($iTimer) > 100 Then
    $iTimer = TimerInit()
    _GUICtrlStatusBar_SetText($hStatus, $iCount, 1)
    EndIf
    $aItem = StringSplit($aNewItems[$i], '|')
    For $j = 1 To $aItem[0]
    $aListview[$i - 1][$j - 1] = $aItem[$j]
    Next
    GUICtrlCreateListViewItem($aNewItems[$i], $hListView) ; mit den eingelesenen Daten einen neuen Listview-Eintrag erstellen
    Next
    _GUICtrlStatusBar_SetText($hStatus, $iCount, 1)
    _GUICtrlListView_EndUpdate($hLVHandle) ; Listview wieder freigeben
    $iLVCount = UBound($aListview)
    EndIf
    EndFunc ;==>Load

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

    Func Save() ; Datenbank-Datei speichern
    Local $sContent, $hFile, $iCount, $iTimer
    $iCount = _GUICtrlListView_GetItemCount($hLVHandle); Anzahl der Listview-Einträge holen
    If $iCount = 0 Then Return ; Wenn das Listview keine Einträge enthält, dann Funktion verlassen
    $iTimer = TimerInit()
    For $i = 0 To $iCount - 1 ; Schleife, um alle Listview-Einträge durchzugehen
    $sContent &= _GUICtrlListView_GetItemTextString($hLVHandle, $i) & @CRLF
    If TimerDiff($iTimer) > 100 Then
    $iTimer = TimerInit()
    _GUICtrlStatusBar_SetText($hStatus, $i + 1, 2)
    EndIf
    Next
    $hFile = FileOpen($sDBFile, 2) ; Datei zum speichern (überschreiben) öffnen
    If $hFile <> -1 Then ; wenn das öffnen erfolgreich war, dann...
    FileWrite($hFile, $sContent)
    FileClose($hFile) ; Datei schließen
    EndIf
    EndFunc ;==>Save

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

    ;===============================================================================
    ; Function Name: _RecursiveFileListToArray($sPath[, $sPattern][, $iFlag][, $iFormat][, $iRecursion][, $sDelim])
    ; Description:: gibt Verzeichnisse (rekursiv) und/oder Dateien zurück, die einem RegExp-Pattern entsprechen
    ; Parameter(s): $sPath = Startverzeichnis
    ; $sPattern = ein beliebiges RexExp-Pattern für die Auswahl
    ; $iFlag = Auswahl
    ; 0 = Dateien & Verzeichnisse
    ; 1 = nur Dateien
    ; 2 = nur Verzeichnisse
    ; $iFormat = Rückgabeformat
    ; 0 = String
    ; 1 = Array mit [0] = Anzahl
    ; 2 = Nullbasiertes Array
    ; $iRecursion = Verzeichnisse rekursiv durchsuchen
    ; 0 = Nein
    ; 1 = Ja
    ; $sDelim = Trennzeichen für die String-Rückgabe
    ; Requirement(s): AutoIt 3.3.0.0
    ; Return Value(s): Array/String mit den gefundenen Dateien/Verzeichnissen
    ; Author(s): Oscar (http://www.autoit.de)
    ; Anregungen von: bernd670 (http://www.autoit.de)
    ;===============================================================================
    Func _RecursiveFileListToArray($sPath, $sPattern = '', $iFlag = 0, $iFormat = 1, $iRecursion = 1, $sDelim = @CRLF)
    Local $hSearch, $sFile, $sReturn = ''
    If StringRight($sPath, 1) <> '\' Then $sPath &= '\'
    $hSearch = FileFindFirstFile($sPath & '*.*')
    If @error Or $hSearch = -1 Then Return SetError(1, 0, $sReturn)
    While Not $fStop
    $sFile = FileFindNextFile($hSearch)
    If @error Then ExitLoop
    If @extended Then
    If StringRegExp($sPath & $sFile, $sPattern) And ($iFlag = 0 Or $iFlag = 2) Then $sReturn &= $sPath & $sFile & '\' & $sDelim
    If $iRecursion Then $sReturn &= _RecursiveFileListToArray($sPath & $sFile & '\', $sPattern, $iFlag, 0)
    ContinueLoop
    EndIf
    If StringRegExp($sFile, $sPattern) And ($iFlag = 0 Or $iFlag = 1) Then $sReturn &= $sPath & $sFile & $sDelim
    WEnd
    FileClose($hSearch)
    If $iFormat And $sReturn = '' Then Return StringSplit($sReturn, '', $iFormat)
    If $iFormat Then Return StringSplit(StringTrimRight($sReturn, StringLen($sDelim)), $sDelim, $iFormat)
    Return $sReturn
    EndFunc ;==>_RecursiveFileListToArray

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

    ;===============================================================================
    ; Function Name: _ReadID3Tag($sPath)
    ; Description:: gibt ein Array mit den Daten aus den ID3-Tags zurück
    ; unterstützt werden die ID3-Tag-Versionen 1.0, 1.1, 2.3 und 2.4
    ; bei v2.4 müssen sich die ID3-Tags am Anfang der Datei befinden
    ; Parameter(s): $sPath = Pfad zu einer MP3-Datei
    ; Requirement(s): min. AutoIt v3.3.0.0
    ; Return Value(s): bei Erfolg: Array mit den ID3-Tagdaten (@error = 0)
    ; im Fehlerfall bekommt @error:
    ; 1 = Datei existiert nicht
    ; 2 = Datei konnte nicht zum lesen geöffnet werden
    ; 3 = falsche ID3 v2 Version
    ; 4 = Datei ist keine MP3-Datei
    ; Author(s): Oscar (http://www.autoit.de)
    ;===============================================================================
    Func _ReadID3Tag($sPath)
    If Not FileExists($sPath) Then Return SetError(1, 0, 0)
    Local $hFile, $sData, $sID3Header, $iID3HeaderSize = 0, $iOffset, $iSize, $tmp
    Local $aID3v2Tags[8] = ['TIT2', 'TPE1', 'TALB', 'TYER', 'TLEN', 'TRCK', 'TCON', 'TENC']
    Local $aID3[11][2] = [ _
    ['Title', ''],['Artist', ''],['Album', ''],['Year', ''], _
    ['Length', '0'],['Track', ''],['Genre', ''],['Encoder', ''], _
    ['MPEG-Version', ''],['Bitrate', '-'],['Sample-Freq.', '']]
    Local $aMP3Version[4] = ['MPEG2.5', 'Reserved', 'MPEG2', 'MPEG1']
    Local $aMP3Layer[4] = ['Reserved', 'Layer III', 'Layer II', 'Layer I']
    Local $aMP3Bitrate[5][16] = [ _
    [000, 032, 064, 096, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448, 000], _
    [000, 032, 048, 056, 064, 080, 096, 112, 128, 160, 192, 224, 256, 320, 384, 000], _
    [000, 032, 040, 048, 056, 064, 080, 096, 112, 128, 160, 192, 224, 256, 320, 000], _
    [000, 032, 048, 056, 064, 080, 096, 112, 128, 144, 160, 176, 192, 224, 256, 000], _
    [000, 008, 016, 024, 032, 040, 048, 056, 064, 080, 096, 112, 128, 144, 160, 000]]
    Local $aSampleFreq[3][4] = [[44100, 48000, 32000, 0],[22050, 24000, 16000, 0],[11025, 12000, 8000, 0]]
    Local $sMP3FrameHeader, $iMP3Version, $sMP3Version, $sMP3Layer, $iMP3Bitrate, $iMP3SampleFreq
    Local $iVBRFrames = -1, $iVBRFilesize, $iVBRFlags
    $hFile = FileOpen($sPath, 16)
    If $hFile = -1 Then Return SetError(2, 0, 0)
    $sData = Binary(FileRead($hFile, 4))
    If BinaryMid($sData, 1, 3) = '0x494433' Then ; ID3 v2.x Kennung gefunden
    If (BinaryMid($sData, 4, 1) = '0x03') Or (BinaryMid($sData, 4, 1) = '0x04') Then ; nur v2.3 und 2.4
    FileRead($hFile, 2) ; 2 Bytes überspringen
    For $i = 0 To 3 ; berechne ID3-Headergröße (4 Bytes, jedoch nur jeweils die unteren 7 Bit)
    $iID3HeaderSize = BitShift($iID3HeaderSize, -7) + BitAND(Binary(FileRead($hFile, 1)), 0x7F)
    Next
    If $iID3HeaderSize > 0 Then
    $sID3Header = Binary(FileRead($hFile, $iID3HeaderSize)) ; lese gesamten ID3-Header
    For $i = 0 To 7
    $iOffset = StringInStr(BinaryToString($sID3Header), $aID3v2Tags[$i]) ; Offset zu dem ID3-Tag
    If $iOffset > 0 Then
    $iSize = Hex(BinaryMid($sID3Header, $iOffset + 4, 4)) ; Größe des ID3-Frames
    $tmp = BinaryMid($sID3Header, $iOffset + 11, Dec($iSize) - 1)
    If BinaryMid($tmp, 1, 2) = '0xFFFE' Then
    For $x = 3 To BinaryLen($tmp) Step 2
    $aID3[$i][1] &= BinaryToString(BinaryMid($tmp, $x, 2), 2)
    Next
    Else
    For $x = 1 To BinaryLen($tmp)
    $aID3[$i][1] &= BinaryToString(BinaryMid($tmp, $x, 1))
    Next
    EndIf
    $aID3[$i][1] = StringReplace($aID3[$i][1], Chr(0), '')
    EndIf
    Next
    EndIf
    Do
    $sData = String(FileRead($hFile, 1))
    If @error Then ExitLoop
    If BitAND($sData, 0xff) = 0xff Then
    FileSetPos($hFile, -1, 1)
    $sData = String(FileRead($hFile, 4))
    EndIf
    Until BitAND($sData, 0xFFE00000) = 0xFFE00000
    Else
    FileClose($hFile)
    Return SetError(3, 0, 0)
    EndIf
    Else ; ID3 v1.x
    $iOffset = FileGetPos($hFile)
    FileSetPos($hFile, -128, 2)
    $sID3Header = BinaryToString(FileRead($hFile, 3))
    If $sID3Header = 'TAG' Then
    $aID3[0][1] = StringReplace(BinaryToString(FileRead($hFile, 30)), Chr(0), '')
    $aID3[1][1] = StringReplace(BinaryToString(FileRead($hFile, 30)), Chr(0), '')
    $aID3[2][1] = StringReplace(BinaryToString(FileRead($hFile, 30)), Chr(0), '')
    $aID3[3][1] = StringReplace(BinaryToString(FileRead($hFile, 4)), Chr(0), '')
    EndIf
    FileSetPos($hFile, $iOffset, 0)
    EndIf
    $sMP3FrameHeader = String($sData)
    If BitAND($sMP3FrameHeader, 0xFFE00000) <> 0xFFE00000 Then
    FileClose($hFile)
    Return SetError(4, 0, 0) ; keine MP3-Datei, dann Return
    EndIf
    $iMP3Version = BitShift(BitXOR($sMP3FrameHeader, 0xFFE00000), 19) ; welche MP3-Version
    $sMP3Version = $aMP3Version[$iMP3Version] ; in Textform
    $sMP3Layer = $aMP3Layer[BitShift(BitAND($sMP3FrameHeader, 0x60000), 17)] ; welcher Layer
    $aID3[8][1] = $sMP3Version & ' / ' & $sMP3Layer ; ins Ausgabe-Array
    $iMP3Bitrate = BitShift(BitAND($sMP3FrameHeader, 0xF000), 12) ; Bitraten-Index auslesen
    Switch $sMP3Version ; je nach MPEG-Version Bitrate aus der Tabelle holen
    Case 'MPEG1'
    $aID3[9][1] = $aMP3Bitrate[$iMP3Version - ($iMP3Version > 1)][$iMP3Bitrate]
    Case 'MPEG2', 'MPEG2.5'
    If $sMP3Layer = 'Layer I' Then
    $aID3[9][1] = $aMP3Bitrate[3][$iMP3Bitrate]
    Else
    $aID3[9][1] = $aMP3Bitrate[4][$iMP3Bitrate]
    EndIf
    EndSwitch
    $iMP3SampleFreq = BitShift(BitAND($sMP3FrameHeader, 0xC00), 10) ; Sample-Frequenz-Index auslesen
    $aID3[10][1] = $aSampleFreq[2 - ($iMP3Version - ($iMP3Version > 1))][$iMP3SampleFreq] ; und Wert aus der Tabelle holen
    Do ; evtl. Leerbytes überspringen
    $tmp = FileRead($hFile, 1)
    If @error Then ExitLoop
    Until $tmp <> 0x00 Or @error
    If $tmp = 0x58 And BinaryToString(FileRead($hFile, 3)) = 'ing' Then ; MP3 mit VBR (Xing-Header gefunden)?
    $iVBRFlags = '0x' & Hex(FileRead($hFile, 4)) ; VBR-Flags auslesen
    If BitAND($iVBRFlags, 0x3) Then ; wenn die Einträge vorhanden sind, dann...
    $iVBRFrames = Dec(Hex(FileRead($hFile, 4))) ; Anzahl der VBR-Frames auslesen
    $iVBRFilesize = Dec(Hex(FileRead($hFile, 4))) ; Dateigröße auslesen
    $aID3[4][1] = $iVBRFrames * 1152 / $aID3[10][1] * 1000 ; VBR Laufzeit
    $aID3[9][1] = 'VBR ~' & Int($iVBRFilesize * 8 / ($aID3[4][1] / 1000) / 1000) ; VBR durchschnittliche Bitrate
    EndIf
    Else
    If $aID3[4][1] = 0 Then $aID3[4][1] = (FileGetSize($sPath) * 8) / ($aID3[9][1] * 1000) * 1000 ; alternative CBR Laufzeit
    $aID3[9][1] = 'CBR ' & $aID3[9][1]
    EndIf
    $aID3[4][1] = _TicksToTimeFormat($aID3[4][1]) ; Laufzeit (Ticks to hour:min:sec)
    $aID3[9][1] &= ' kBit/s'
    $aID3[10][1] &= ' Hz'
    FileClose($hFile)
    Return SetError(0, 0, $aID3)
    EndFunc ;==>_ReadID3Tag

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

    ;===============================================================================
    ; Function Name: _TicksToTimeFormat($iTicks, $sFormat = '%hh:%mm:%ss')
    ; Description:: Diese Funktion wandelt Millisekunden in ein anzugebenes Zeitformat um
    ; Parameter(s): $iTicks = Zeit in Millisekunden
    ; $sFormat:
    ; %hh für Stunden
    ; %mm für Minuten
    ; %ss für Sekunden
    ; %ms für Millisekunden
    ; sonstige Zeichen, die dazwischen stehen, werden übernommen
    ; Requirement(s): -
    ; Return Value(s): Zeit im ausgewählten Format (String)
    ; Author(s): Oscar (http://www.autoit.de)
    ;===============================================================================
    Func _TicksToTimeFormat($iTicks, $sFormat = '%hh:%mm:%ss')
    Local $aTime[4] = [0, 0, 0, 0], $sOut, $aTimeFormat[4] = ['hh', 'mm', 'ss', 'ms'], $aFormat
    $aTime[2] = Int($iTicks / 1000)
    $aTime[3] = $iTicks - $aTime[2] * 1000
    $aTime[0] = Int($aTime[2] / 3600)
    $aTime[2] = Mod($aTime[2], 3600)
    $aTime[1] = Int($aTime[2] / 60)
    $aTime[2] = Mod($aTime[2], 60)
    $aFormat = StringRegExp($sFormat, '%([^%]+)', 3)
    If Not IsArray($aFormat) Then Return SetError(1, 0, $iTicks)
    For $i = 0 To UBound($aFormat) - 1
    For $j = 0 To UBound($aTimeFormat) - 1
    If StringLeft($aFormat[$i], 2) = $aTimeFormat[$j] Then $sOut &= StringFormat('%02i', $aTime[$j]) & StringMid($aFormat[$i], 3)
    Next
    Next
    Return $sOut
    EndFunc ;==>_TicksToTimeFormat

    [/autoit]

    Dateien

    _MP3Search.au3 23,63 kB – 296 Downloads
  • mp3 Searcher

    • Oscar
    • 29. Juli 2010 um 00:46

    Also, die Sortierfunktion mit Hilfe von _GUICtrlListView_RegisterSortCallBack ausführen zu lassen dauert ewig: bei 42000 Einträgen = ca. 8 Minuten (!).
    Jetzt habe ich das Skript dahingehend umgeschrieben, dass die Einträge auch in einem 2D-Array vorhanden sind. Dieses lasse ich dann per _ArraySort sortieren, lösche die Listview-Einträge und erstelle sie neu. Das verringert die Sortierung auf etwa 20-30 Sekunden (!). Das ist immer noch relativ lange, aber das kann man noch akzeptieren, IMHO.

    Außerdem habe ich mal alle langwierigen Aktionen mit Rückmeldungen versehen, sodass man nicht den Eindruck hat, das Programm wäre abgestürzt. Das einlesen der Festplatten kann man mit [ESC] abbrechen.

    Skript:

    Spoiler anzeigen
    [autoit]


    #include <Array.au3>
    #include <ButtonConstants.au3>
    #include <GUIConstantsEx.au3>
    #include <GuiListView.au3>
    #include <GuiStatusBar.au3>
    #include <ListViewConstants.au3>

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

    Global $sHeader = 'Title|Artist|Album|Year|Length|MPEG-Version|Bitrate|Sample-Freq.|Path' ; Die Überschriften für das Listview
    Global $sDBFile = @ScriptDir & '\MP3_Collection.txt' ; Pfad und Name der Datenbank-Datei

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

    #region Hauptfenster
    Global $iWidth = @DesktopWidth - 100
    Global $hGui = GUICreate('MP3-Search', $iWidth, 500) ; Hauptfenster erstellen
    GUISetBkColor(0xAAAAAA)
    Global $hListView = GUICtrlCreateListView($sHeader, 5, 5, $iWidth - 10, 420, $LVS_SHOWSELALWAYS) ; Listview erstellen
    Global $aListview[1][9]
    Global $hLVHandle = GUICtrlGetHandle($hListView) ; das Handle vom Listview wird für die UDF-Listview-Funktionen benötigt
    _GUICtrlListView_SetColumn($hLVHandle, 0, 'Title', 180, 0)
    _GUICtrlListView_SetColumn($hLVHandle, 1, 'Artist', 180, 0)
    _GUICtrlListView_SetColumn($hLVHandle, 2, 'Length', 60, 0)
    _GUICtrlListView_SetColumn($hLVHandle, 3, 'Album', 120, 0)
    _GUICtrlListView_SetColumn($hLVHandle, 4, 'Year', 60, 0)
    _GUICtrlListView_SetColumn($hLVHandle, 5, 'MPEG-Version', 100, 0)
    _GUICtrlListView_SetColumn($hLVHandle, 6, 'Bitrate', 100, 0)
    _GUICtrlListView_SetColumn($hLVHandle, 7, 'Sample-Freq.', 90, 0)
    _GUICtrlListView_SetColumn($hLVHandle, 8, 'Path', 800, 0)

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

    Global $hSearch = GUICtrlCreateButton('Alle Festplatten durchsuchen', 10, 430, 160, 35, $BS_MULTILINE)
    Global $hLoad = GUICtrlCreateButton('Laden', 230, 430, 70, 35)
    Global $hSave = GUICtrlCreateButton('Speichern', 310, 430, 70, 35)
    Global $hDel = GUICtrlCreateButton("Markierte Einträge löschen", 400, 430, 90, 35, $BS_MULTILINE)
    Global $hDelAll = GUICtrlCreateButton('Alle Einträge löschen', 500, 430, 90, 35, $BS_MULTILINE)

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

    Global $aParts[3] = [180, 240, -1], $aText[3] = ['Fertig.', '0', '']
    Global $hStatus = _GUICtrlStatusBar_Create($hGui, $aParts, $aText)
    #endregion Hauptfenster

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

    GUISetState(@SW_SHOW, $hGui) ; Hauptfenster sichtbar machen

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

    Global $fStop = False, $iLVCount = 0
    HotKeySet('{ESC}', '_Stop')

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

    While 1
    Switch GUIGetMsg() ; anhand der Control-ID das entsprechende Case aufrufen
    Case $hSearch
    _GUICtrlListView_DeleteAllItems($hLVHandle) ; Alle Listview-Einträge löschen
    $iLVCount = 0 ; Zähler auf Null setzen
    $aDrives = DriveGetDrive('FIXED') ; Alle Festplatten-Buchstaben holen
    ;~ Dim $aDrives[2] = [1, 'c:']
    If Not @error Then
    GUISetCursor(15, 1, $hGui)
    For $i = 1 To $aDrives[0] ; Alle Festplatten durchgehen
    $aDrives[$i] = StringUpper($aDrives[$i]) & '\'
    _GUICtrlStatusBar_SetText($hStatus, 'Durchsuche Festplatte "' & $aDrives[$i] & '"', 0)
    _GUICtrlStatusBar_SetText($hStatus, 'Bitte warten...', 2)
    $aNewMP3 = _RecursiveFileListToArray($aDrives[$i], '\.mp3', 1) ; Alle MP3s auf der Festplatte auslesen
    If Not @error Then
    _GUICtrlListView_SetItemCount($hListView, $iLVCount + $aNewMP3[0])
    ConsoleWrite('$iLVCount = ' & $iLVCount & @CR & '$aNewMP3[0] = ' & $aNewMP3[0] & @CR)
    ReDim $aListview[$iLVCount + $aNewMP3[0] + 1][9]
    _GUICtrlStatusBar_SetText($hStatus, 'Lese ID3-Tags... (' & UBound($aListview) & ')', 0)
    For $j = 1 To $aNewMP3[0] ; die gefundenen MP3s durchgehen
    _GUICtrlStatusBar_SetText($hStatus, $iLVCount, 1)
    $aID3Tags = _ReadID3Tag($aNewMP3[$j]) ; die ID3-Tags auslesen
    If Not @error Then
    For $k = 0 To 10
    $aID3Tags[$k][1] = StringReplace($aID3Tags[$k][1], '|', '') ; evtl. vorhandene "|" entfernen
    Next
    _GUICtrlStatusBar_SetText($hStatus, $aNewMP3[$j], 2)
    $sNewItem = $aID3Tags[0][1] & '|' & $aID3Tags[1][1] & '|' & $aID3Tags[4][1] & '|' & $aID3Tags[2][1] & '|' & $aID3Tags[3][1]
    $sNewItem &= '|' & $aID3Tags[8][1] & '|' & $aID3Tags[9][1] & '|' & $aID3Tags[10][1] & '|' & $aNewMP3[$j]
    $aItem = StringSplit($sNewItem, '|')
    For $k = 1 To $aItem[0]
    $aListview[$iLVCount][$k - 1] = $aItem[$k]
    Next
    GUICtrlCreateListViewItem($sNewItem, $hListView)
    $iLVCount += 1
    EndIf
    If $fStop Then ExitLoop 2 ; Wenn [ESC] gedrückt wurde, die Schleifen verlassen
    Next
    ReDim $aListview[$iLVCount][9]
    EndIf
    Next
    GUISetCursor(2, 1, $hGui)
    EndIf
    _GUICtrlStatusBar_SetText($hStatus, $iLVCount, 1)
    _GUICtrlStatusBar_SetText($hStatus, '', 2)
    If $fStop Then
    $fStop = False
    _GUICtrlStatusBar_SetText($hStatus, 'Abgebrochen!', 0)
    Else
    _GUICtrlStatusBar_SetText($hStatus, 'Fertig.', 0)
    EndIf
    Case $hListView ; User hat auf eine Spaltenüberschrift geklickt
    If $iLVCount > 0 Then
    GUISetCursor(15, 1, $hGui)
    _GUICtrlStatusBar_SetText($hStatus, 'Sortiere Daten...', 0)
    $iSort = GUICtrlGetState($hListView)
    $iTimer = TimerInit()
    ConsoleWrite('Start Sort col: ' & $iSort & @CR)
    _ArraySort($aListview, 0, 0, 0, $iSort)
    ConsoleWrite('Sort: ' & Int(TimerDiff($iTimer)) & ' ms' & @CR)
    _GUICtrlListView_DeleteAllItems($hLVHandle)
    ConsoleWrite('Delete all: ' & Int(TimerDiff($iTimer)) & ' ms' & @CR)
    _GUICtrlListView_BeginUpdate($hLVHandle) ; Listview sperren
    _GUICtrlListView_AddArray($hLVHandle, $aListview)
    _GUICtrlListView_EndUpdate($hLVHandle) ; Listview wieder freigeben
    ConsoleWrite('Create new: ' & Int(TimerDiff($iTimer)) & ' ms' & @CR)
    ConsoleWrite('End.' & @CR)
    _GUICtrlStatusBar_SetText($hStatus, 'Fertig.', 0)
    GUISetCursor(2, 1, $hGui)
    EndIf
    Case $hLoad ; User hat auf 'Laden' geklickt
    GUISetCursor(15, 1, $hGui)
    _GUICtrlStatusBar_SetText($hStatus, 'Lade Daten...', 0)
    Load()
    _GUICtrlStatusBar_SetText($hStatus, 'Fertig.', 0)
    GUISetCursor(2, 1, $hGui)
    Case $hSave ; User hat auf 'Speichern' geklickt
    GUISetCursor(15, 1, $hGui)
    _GUICtrlStatusBar_SetText($hStatus, 'Speichere Daten...', 0)
    Save()
    _GUICtrlStatusBar_SetText($hStatus, 'Fertig.', 0)
    _GUICtrlStatusBar_SetText($hStatus, '', 2)
    GUISetCursor(2, 1, $hGui)
    Case $hDel
    $aSelectedItems = _GUICtrlListView_GetSelectedIndices($hLVHandle, True)
    If $aSelectedItems[0] > 0 Then
    GUISetCursor(15, 1, $hGui)
    For $i = $aSelectedItems[0] To 1 Step - 1
    _ArrayDelete($aListview, $aSelectedItems[$i])
    Next
    _GUICtrlListView_DeleteItemsSelected($hLVHandle)
    $iLVCount -= $aSelectedItems[0]
    _GUICtrlStatusBar_SetText($hStatus, $iLVCount, 1)
    GUISetCursor(2, 1, $hGui)
    EndIf
    Case $hDelAll ; User hat auf 'Alle Einträge löschen' geklickt
    If MsgBox(256 + 32 + 4, 'Einträge löschen', 'Wollen sie wirklich alle Einträge löschen?') = 6 Then
    _GUICtrlListView_DeleteAllItems($hLVHandle)
    ReDim $aListview[1][9]
    $iLVCount = 0
    _GUICtrlStatusBar_SetText($hStatus, $iLVCount, 1)
    EndIf
    Case $GUI_EVENT_CLOSE ; User hat auf das Schließen-Symbol geklickt (bzw. die ESC-Taste gedrückt)
    If MsgBox(32 + 4, 'Beenden', 'Wollen sie das Programm wirklich beenden?') = 6 Then End() ; wenn ja, dann End-Funktion aufrufen
    EndSwitch
    WEnd

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

    Func _Stop()
    $fStop = True
    EndFunc ;==>_Stop

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

    Func End()
    ;~ Save() ; wenn der vordere Kommentar entfernt wird, dann werden vor dem beenden noch die Daten gespeichert
    Exit ; Programm beenden
    EndFunc ;==>End

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

    Func Load() ; Datenbank-Datei laden
    Local $hFile, $sContent, $aNewItems, $iTimer, $iCount, $aItem
    $hFile = FileOpen($sDBFile, 0) ; Datei zum lesen öffnen
    If $hFile <> -1 Then ; wenn das öffnen erfolgreich war, dann...
    $sContent = FileRead($hFile) ; Datei komplett einlesen
    FileClose($hFile) ; Datei schließen
    $sContent = StringTrimRight($sContent, 2) ; das letzte @CRLF entfernen
    $aNewItems = StringSplit($sContent, @CRLF, 1) ; Den Dateiinhalt am Zeilenende splitten
    If Not IsArray($aNewItems) Then Return ; Wenn $aNewItems kein Array ist, dann Funktion verlassen
    _GUICtrlListView_DeleteAllItems($hLVHandle)
    _GUICtrlListView_SetItemCount($hLVHandle, $aNewItems[0])
    Global $aListview[$aNewItems[0]][9]
    _GUICtrlStatusBar_SetText($hStatus, 'Lade Daten... (' & $aNewItems[0] & ')', 0)
    _GUICtrlListView_BeginUpdate($hLVHandle) ; Listview sperren
    $iTimer = TimerInit()
    For $i = 1 To $aNewItems[0] ; Alle Einträge des Arrays durchgehen
    $iCount += 1
    If TimerDiff($iTimer) > 100 Then
    $iTimer = TimerInit()
    _GUICtrlStatusBar_SetText($hStatus, $iCount, 1)
    EndIf
    $aItem = StringSplit($aNewItems[$i], '|')
    For $j = 1 To $aItem[0]
    $aListview[$i - 1][$j - 1] = $aItem[$j]
    Next
    GUICtrlCreateListViewItem($aNewItems[$i], $hListView) ; mit den eingelesenen Daten einen neuen Listview-Eintrag erstellen
    Next
    _GUICtrlStatusBar_SetText($hStatus, $iCount, 1)
    _GUICtrlListView_EndUpdate($hLVHandle) ; Listview wieder freigeben
    $iLVCount = UBound($aListview)
    EndIf
    EndFunc ;==>Load

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

    Func Save() ; Datenbank-Datei speichern
    Local $sContent, $hFile, $iCount, $iTimer
    $iCount = _GUICtrlListView_GetItemCount($hLVHandle); Anzahl der Listview-Einträge holen
    If $iCount = 0 Then Return ; Wenn das Listview keine Einträge enthält, dann Funktion verlassen
    $iTimer = TimerInit()
    For $i = 0 To $iCount - 1 ; Schleife, um alle Listview-Einträge durchzugehen
    $sContent &= _GUICtrlListView_GetItemTextString($hLVHandle, $i) & @CRLF
    If TimerDiff($iTimer) > 100 Then
    $iTimer = TimerInit()
    _GUICtrlStatusBar_SetText($hStatus, $i + 1, 2)
    EndIf
    Next
    $hFile = FileOpen($sDBFile, 2) ; Datei zum speichern (überschreiben) öffnen
    If $hFile <> -1 Then ; wenn das öffnen erfolgreich war, dann...
    FileWrite($hFile, $sContent)
    FileClose($hFile) ; Datei schließen
    EndIf
    EndFunc ;==>Save

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

    ;===============================================================================
    ; Function Name: _RecursiveFileListToArray($sPath[, $sPattern][, $iFlag][, $iFormat][, $iRecursion][, $sDelim])
    ; Description:: gibt Verzeichnisse (rekursiv) und/oder Dateien zurück, die einem RegExp-Pattern entsprechen
    ; Parameter(s): $sPath = Startverzeichnis
    ; $sPattern = ein beliebiges RexExp-Pattern für die Auswahl
    ; $iFlag = Auswahl
    ; 0 = Dateien & Verzeichnisse
    ; 1 = nur Dateien
    ; 2 = nur Verzeichnisse
    ; $iFormat = Rückgabeformat
    ; 0 = String
    ; 1 = Array mit [0] = Anzahl
    ; 2 = Nullbasiertes Array
    ; $iRecursion = Verzeichnisse rekursiv durchsuchen
    ; 0 = Nein
    ; 1 = Ja
    ; $sDelim = Trennzeichen für die String-Rückgabe
    ; Requirement(s): AutoIt 3.3.0.0
    ; Return Value(s): Array/String mit den gefundenen Dateien/Verzeichnissen
    ; Author(s): Oscar (http://www.autoit.de)
    ; Anregungen von: bernd670 (http://www.autoit.de)
    ;===============================================================================
    Func _RecursiveFileListToArray($sPath, $sPattern = '', $iFlag = 0, $iFormat = 1, $iRecursion = 1, $sDelim = @CRLF)
    Local $hSearch, $sFile, $sReturn = ''
    If StringRight($sPath, 1) <> '\' Then $sPath &= '\'
    $hSearch = FileFindFirstFile($sPath & '*.*')
    If @error Or $hSearch = -1 Then Return SetError(1, 0, $sReturn)
    While Not $fStop
    $sFile = FileFindNextFile($hSearch)
    If @error Then ExitLoop
    If @extended Then
    If StringRegExp($sPath & $sFile, $sPattern) And ($iFlag = 0 Or $iFlag = 2) Then $sReturn &= $sPath & $sFile & '\' & $sDelim
    If $iRecursion Then $sReturn &= _RecursiveFileListToArray($sPath & $sFile & '\', $sPattern, $iFlag, 0)
    ContinueLoop
    EndIf
    If StringRegExp($sFile, $sPattern) And ($iFlag = 0 Or $iFlag = 1) Then $sReturn &= $sPath & $sFile & $sDelim
    WEnd
    FileClose($hSearch)
    If $iFormat And $sReturn = '' Then Return StringSplit($sReturn, '', $iFormat)
    If $iFormat Then Return StringSplit(StringTrimRight($sReturn, StringLen($sDelim)), $sDelim, $iFormat)
    Return $sReturn
    EndFunc ;==>_RecursiveFileListToArray

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

    ;===============================================================================
    ; Function Name: _ReadID3Tag($sPath)
    ; Description:: gibt ein Array mit den Daten aus den ID3-Tags zurück
    ; unterstützt werden die ID3-Tag-Versionen 1.0, 1.1, 2.3 und 2.4
    ; bei v2.4 müssen sich die ID3-Tags am Anfang der Datei befinden
    ; Parameter(s): $sPath = Pfad zu einer MP3-Datei
    ; Requirement(s): min. AutoIt v3.3.0.0
    ; Return Value(s): bei Erfolg: Array mit den ID3-Tagdaten (@error = 0)
    ; im Fehlerfall bekommt @error:
    ; 1 = Datei existiert nicht
    ; 2 = Datei konnte nicht zum lesen geöffnet werden
    ; 3 = falsche ID3 v2 Version
    ; 4 = Datei ist keine MP3-Datei
    ; Author(s): Oscar (http://www.autoit.de)
    ;===============================================================================
    Func _ReadID3Tag($sPath)
    If Not FileExists($sPath) Then Return SetError(1, 0, 0)
    Local $hFile, $sData, $sID3Header, $iID3HeaderSize = 0, $iOffset, $iSize, $tmp
    Local $aID3v2Tags[8] = ['TIT2', 'TPE1', 'TALB', 'TYER', 'TLEN', 'TRCK', 'TCON', 'TENC']
    Local $aID3[11][2] = [ _
    ['Title', ''],['Artist', ''],['Album', ''],['Year', ''], _
    ['Length', '0'],['Track', ''],['Genre', ''],['Encoder', ''], _
    ['MPEG-Version', ''],['Bitrate', '-'],['Sample-Freq.', '']]
    Local $aMP3Version[4] = ['MPEG2.5', 'Reserved', 'MPEG2', 'MPEG1']
    Local $aMP3Layer[4] = ['Reserved', 'Layer III', 'Layer II', 'Layer I']
    Local $aMP3Bitrate[5][16] = [ _
    [000, 032, 064, 096, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448, 000], _
    [000, 032, 048, 056, 064, 080, 096, 112, 128, 160, 192, 224, 256, 320, 384, 000], _
    [000, 032, 040, 048, 056, 064, 080, 096, 112, 128, 160, 192, 224, 256, 320, 000], _
    [000, 032, 048, 056, 064, 080, 096, 112, 128, 144, 160, 176, 192, 224, 256, 000], _
    [000, 008, 016, 024, 032, 040, 048, 056, 064, 080, 096, 112, 128, 144, 160, 000]]
    Local $aSampleFreq[3][4] = [[44100, 48000, 32000, 0],[22050, 24000, 16000, 0],[11025, 12000, 8000, 0]]
    Local $sMP3FrameHeader, $iMP3Version, $sMP3Version, $sMP3Layer, $iMP3Bitrate, $iMP3SampleFreq
    Local $iVBRFrames = -1, $iVBRFilesize, $iVBRFlags
    $hFile = FileOpen($sPath, 16)
    If $hFile = -1 Then Return SetError(2, 0, 0)
    $sData = Binary(FileRead($hFile, 4))
    If BinaryMid($sData, 1, 3) = '0x494433' Then ; ID3 v2.x Kennung gefunden
    If (BinaryMid($sData, 4, 1) = '0x03') Or (BinaryMid($sData, 4, 1) = '0x04') Then ; nur v2.3 und 2.4
    FileRead($hFile, 2) ; 2 Bytes überspringen
    For $i = 0 To 3 ; berechne ID3-Headergröße (4 Bytes, jedoch nur jeweils die unteren 7 Bit)
    $iID3HeaderSize = BitShift($iID3HeaderSize, -7) + BitAND(Binary(FileRead($hFile, 1)), 0x7F)
    Next
    If $iID3HeaderSize > 0 Then
    $sID3Header = Binary(FileRead($hFile, $iID3HeaderSize)) ; lese gesamten ID3-Header
    For $i = 0 To 7
    $iOffset = StringInStr(BinaryToString($sID3Header), $aID3v2Tags[$i]) ; Offset zu dem ID3-Tag
    If $iOffset > 0 Then
    $iSize = Hex(BinaryMid($sID3Header, $iOffset + 4, 4)) ; Größe des ID3-Frames
    $tmp = BinaryMid($sID3Header, $iOffset + 11, Dec($iSize) - 1)
    If BinaryMid($tmp, 1, 2) = '0xFFFE' Then
    For $x = 3 To BinaryLen($tmp) Step 2
    $aID3[$i][1] &= BinaryToString(BinaryMid($tmp, $x, 2), 2)
    Next
    Else
    For $x = 1 To BinaryLen($tmp)
    $aID3[$i][1] &= BinaryToString(BinaryMid($tmp, $x, 1))
    Next
    EndIf
    $aID3[$i][1] = StringReplace($aID3[$i][1], Chr(0), '')
    EndIf
    Next
    EndIf
    Do
    $sData = String(FileRead($hFile, 1))
    If @error Then ExitLoop
    If BitAND($sData, 0xff) = 0xff Then
    FileSetPos($hFile, -1, 1)
    $sData = String(FileRead($hFile, 4))
    EndIf
    Until BitAND($sData, 0xFFE00000) = 0xFFE00000
    Else
    FileClose($hFile)
    Return SetError(3, 0, 0)
    EndIf
    Else ; ID3 v1.x
    $iOffset = FileGetPos($hFile)
    FileSetPos($hFile, -128, 2)
    $sID3Header = BinaryToString(FileRead($hFile, 3))
    If $sID3Header = 'TAG' Then
    $aID3[0][1] = StringReplace(BinaryToString(FileRead($hFile, 30)), Chr(0), '')
    $aID3[1][1] = StringReplace(BinaryToString(FileRead($hFile, 30)), Chr(0), '')
    $aID3[2][1] = StringReplace(BinaryToString(FileRead($hFile, 30)), Chr(0), '')
    $aID3[3][1] = StringReplace(BinaryToString(FileRead($hFile, 4)), Chr(0), '')
    EndIf
    FileSetPos($hFile, $iOffset, 0)
    EndIf
    $sMP3FrameHeader = String($sData)
    If BitAND($sMP3FrameHeader, 0xFFE00000) <> 0xFFE00000 Then
    FileClose($hFile)
    Return SetError(4, 0, 0) ; keine MP3-Datei, dann Return
    EndIf
    $iMP3Version = BitShift(BitXOR($sMP3FrameHeader, 0xFFE00000), 19) ; welche MP3-Version
    $sMP3Version = $aMP3Version[$iMP3Version] ; in Textform
    $sMP3Layer = $aMP3Layer[BitShift(BitAND($sMP3FrameHeader, 0x60000), 17)] ; welcher Layer
    $aID3[8][1] = $sMP3Version & ' / ' & $sMP3Layer ; ins Ausgabe-Array
    $iMP3Bitrate = BitShift(BitAND($sMP3FrameHeader, 0xF000), 12) ; Bitraten-Index auslesen
    Switch $sMP3Version ; je nach MPEG-Version Bitrate aus der Tabelle holen
    Case 'MPEG1'
    $aID3[9][1] = $aMP3Bitrate[$iMP3Version - ($iMP3Version > 1)][$iMP3Bitrate]
    Case 'MPEG2', 'MPEG2.5'
    If $sMP3Layer = 'Layer I' Then
    $aID3[9][1] = $aMP3Bitrate[3][$iMP3Bitrate]
    Else
    $aID3[9][1] = $aMP3Bitrate[4][$iMP3Bitrate]
    EndIf
    EndSwitch
    $iMP3SampleFreq = BitShift(BitAND($sMP3FrameHeader, 0xC00), 10) ; Sample-Frequenz-Index auslesen
    $aID3[10][1] = $aSampleFreq[2 - ($iMP3Version - ($iMP3Version > 1))][$iMP3SampleFreq] ; und Wert aus der Tabelle holen
    Do ; evtl. Leerbytes überspringen
    $tmp = FileRead($hFile, 1)
    If @error Then ExitLoop
    Until $tmp <> 0x00 Or @error
    If $tmp = 0x58 And BinaryToString(FileRead($hFile, 3)) = 'ing' Then ; MP3 mit VBR (Xing-Header gefunden)?
    $iVBRFlags = '0x' & Hex(FileRead($hFile, 4)) ; VBR-Flags auslesen
    If BitAND($iVBRFlags, 0x3) Then ; wenn die Einträge vorhanden sind, dann...
    $iVBRFrames = Dec(Hex(FileRead($hFile, 4))) ; Anzahl der VBR-Frames auslesen
    $iVBRFilesize = Dec(Hex(FileRead($hFile, 4))) ; Dateigröße auslesen
    $aID3[4][1] = $iVBRFrames * 1152 / $aID3[10][1] * 1000 ; VBR Laufzeit
    $aID3[9][1] = 'VBR ~' & Int($iVBRFilesize * 8 / ($aID3[4][1] / 1000) / 1000) ; VBR durchschnittliche Bitrate
    EndIf
    Else
    If $aID3[4][1] = 0 Then $aID3[4][1] = (FileGetSize($sPath) * 8) / ($aID3[9][1] * 1000) * 1000 ; alternative CBR Laufzeit
    $aID3[9][1] = 'CBR ' & $aID3[9][1]
    EndIf
    $aID3[4][1] = _MyTicksToTime($aID3[4][1]) ; Laufzeit (Ticks to hour:min:sec)
    $aID3[9][1] &= ' kBit/s'
    $aID3[10][1] &= ' Hz'
    FileClose($hFile)
    Return SetError(0, 0, $aID3)
    EndFunc ;==>_ReadID3Tag

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

    Func _MyTicksToTime($iTicks)
    Local $iHour, $iMins, $iSecs
    $iHour = Int($iTicks / 3600000)
    $iTicks -= $iHour * 3600000
    $iMins = Int($iTicks / 60000)
    $iTicks -= $iMins * 60000
    $iSecs = Int($iTicks / 1000)
    Return StringFormat('%02i:%02i:%02i', $iHour, $iMins, $iSecs)
    EndFunc ;==>_MyTicksToTime

    [/autoit]

    Dateien

    _MP3Search.au3 19,22 kB – 284 Downloads
  • mp3 Searcher

    • Oscar
    • 28. Juli 2010 um 09:53

    Also zu der Sortierfunktion: Du brauchst vieeeeel Geduld, wenn Du >20000 Einträge im Listview hast! Das war der Grund, warum ich das im obigen Skript auskommentiert habe.
    Und wenn man schon so lange braucht, um die Liste zu sortieren, ist das eigentlich schon der Todesstoss für das Projekt. Es sei denn, jemand kennt eine Möglichkeit (C-Routine oder so) wie man ein Listview mit so vielen Einträgen wirklich schnell sortieren kann...

    Kopieren/verschieben der Dateien (inkl. erstellen evtl. Verzeichnisse) ist eher die einfache Aufgabe.

  • mp3 Searcher

    • Oscar
    • 27. Juli 2010 um 10:48

    Es hatte mich mal interessiert, wie "schnell" AutoIt dabei ist und deshalb habe ich mal meine Skripte (Listview-Datenbank, _RecursiveFileListToArray und _ReadID3Tag) zusammengefasst und mit ein paar Statusmeldungen versehen (damit der User sieht, was passiert). Es wird jetzt ein Listview mit den ID3-Tags von allen MP3s von allen installierten Festplatten erstellt.
    Nach dem erstellen, kann man das ganze Listview abspeichern, sodass man es beim nächsten Start des Programms wieder laden kann (ohne es neu erstellen zu müssen).

    Hier das Skript:

    Spoiler anzeigen
    [autoit]


    #include <ButtonConstants.au3>
    #include <GUIConstantsEx.au3>
    #include <GuiListView.au3>
    #include <GuiStatusBar.au3>
    #include <ListViewConstants.au3>

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

    Global $sHeader = "Title|Artist|Album|Year|Length|MPEG-Version|Bitrate|Sample-Freq.|Path" ; Die Überschriften für das Listview
    Global $sDBFile = @ScriptDir & "\MP3_Collection.txt" ; Pfad und Name der Datenbank-Datei

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

    #Region Hauptfenster
    Global $hGui = GUICreate("MP3-Search", 800, 500) ; Hauptfenster erstellen
    Global $hListView = GUICtrlCreateListView($sHeader, 0, 0, 800, 420, $LVS_SHOWSELALWAYS) ; Listview erstellen

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

    Global $hLVHandle = GUICtrlGetHandle($hListView) ; das Handle vom Listview wird für die UDF-Listview-Funktionen benötigt
    _GUICtrlListView_SetColumn($hLVHandle, 0, "Title", 180, 0)
    _GUICtrlListView_SetColumn($hLVHandle, 1, "Artist", 180, 0)
    _GUICtrlListView_SetColumn($hLVHandle, 2, "Length", 60, 0)
    _GUICtrlListView_SetColumn($hLVHandle, 3, "Album", 120, 0)
    _GUICtrlListView_SetColumn($hLVHandle, 4, "Year", 60, 0)
    _GUICtrlListView_SetColumn($hLVHandle, 5, "MPEG-Version", 100, 0)
    _GUICtrlListView_SetColumn($hLVHandle, 6, "Bitrate", 100, 0)
    _GUICtrlListView_SetColumn($hLVHandle, 7, "Sample-Freq.", 90, 0)
    _GUICtrlListView_SetColumn($hLVHandle, 8, "Path", 800, 0)

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

    Global $hSearch = GUICtrlCreateButton("Alle Festplatten durchsuchen", 10, 430, 160, 35, $BS_MULTILINE)
    Global $hLoad = GUICtrlCreateButton("Laden", 230, 430, 70, 35)
    Global $hSave = GUICtrlCreateButton("Speichern", 310, 430, 70, 35)
    Global $hDelAll = GUICtrlCreateButton("Alle Einträge löschen", 500, 430, 90, 35, $BS_MULTILINE)

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

    Global $aParts[3] = [160, 220, -1], $aText[3] =["Fertig.", "0", ""]
    Global $hStatus = _GUICtrlStatusBar_Create($hGui, $aParts, $aText)
    #EndRegion Hauptfenster

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

    ;~ _GUICtrlListView_RegisterSortCallBack($hLVHandle) ; damit man das Listview (mit Klick auf die Spaltenüberschrift) sortieren kann

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

    GUISetState(@SW_SHOW, $hGui) ; Hauptfenster sichtbar machen

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

    Global $fStop = False, $iCount = 0
    HotKeySet("{ESC}", "_Stop")

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

    While 1
    Switch GUIGetMsg() ; anhand der Control-ID das entsprechende Case aufrufen
    Case $hSearch
    _GUICtrlListView_DeleteAllItems($hLVHandle) ; Alle Listview-Einträge löschen
    $iCount = 0 ; Zähler auf Null setzen
    $aDrives = DriveGetDrive("FIXED") ; Alle Festplatten-Buchstaben holen
    If Not @error Then
    For $i = 1 To $aDrives[0] ; Alle Festplatten durchgehen
    $aDrives[$i] = StringUpper($aDrives[$i]) & "\"
    _GUICtrlStatusBar_SetText($hStatus, 'Durchsuche Festplatte "' & $aDrives[$i] & '"', 0)
    _GUICtrlStatusBar_SetText($hStatus, "Bitte warten...", 2)
    $aNewMP3 = _RecursiveFileListToArray($aDrives[$i], '\.mp3', 1) ; Alle MP3s auf der Festplatte auslesen
    If Not @error Then
    _GUICtrlStatusBar_SetText($hStatus, "Lese ID3-Tags...", 0)
    _GUICtrlListView_SetItemCount($hListView, $iCount + $aNewMP3[0])
    For $j = 1 To $aNewMP3[0] ; die gefundenen MP3s durchgehen
    _GUICtrlStatusBar_SetText($hStatus, $iCount, 1)
    $aID3Tags = _ReadID3Tag($aNewMP3[$j]) ; die ID3-Tags auslesen
    If Not @error Then
    _GUICtrlStatusBar_SetText($hStatus, $aNewMP3[$j], 2)
    $sNewItem = $aID3Tags[0][1] & "|" & $aID3Tags[1][1] & "|" & $aID3Tags[4][1] & "|" & $aID3Tags[2][1] & "|" & $aID3Tags[3][1]
    $sNewItem &= "|" & $aID3Tags[8][1] & "|" & $aID3Tags[9][1] & "|" & $aID3Tags[10][1] & "|" & $aNewMP3[$j]
    GUICtrlCreateListViewItem($sNewItem, $hListView)
    $iCount += 1
    EndIf
    If $fStop Then ExitLoop 2 ; Wenn [ESC] gedrückt wurde, die Schleifen verlassen
    Next
    EndIf
    Next
    EndIf
    _GUICtrlStatusBar_SetText($hStatus, "", 2)
    If $fStop Then
    $fStop = False
    _GUICtrlStatusBar_SetText($hStatus, "Abgebrochen!", 0)
    Else
    _GUICtrlStatusBar_SetText($hStatus, "Fertig.", 0)
    EndIf
    ;~ Case $hListView ; User hat auf eine Spaltenüberschrift geklickt
    ;~ _GUICtrlListView_SortItems($hLVHandle, GUICtrlGetState($hListView)) ; Einträge entsprechend sortieren
    Case $hLoad ; User hat auf "Laden" geklickt
    _GUICtrlStatusBar_SetText($hStatus, "Lade Daten...", 0)
    Load()
    _GUICtrlStatusBar_SetText($hStatus, "Fertig.", 0)
    Case $hSave ; User hat auf "Speichern" geklickt
    _GUICtrlStatusBar_SetText($hStatus, "Speichere Daten...", 0)
    Save()
    _GUICtrlStatusBar_SetText($hStatus, "Fertig.", 0)
    _GUICtrlStatusBar_SetText($hStatus, "", 2)
    Case $hDelAll ; User hat auf "Alle Einträge löschen" geklickt
    If MsgBox(256 + 32 + 4, "Einträge löschen", "Wollen sie wirklich alle Einträge löschen?") = 6 Then
    _GUICtrlListView_DeleteAllItems($hLVHandle)
    $iCount = 0
    EndIf
    Case $GUI_EVENT_CLOSE ; User hat auf das Schließen-Symbol geklickt (bzw. die ESC-Taste gedrückt)
    End()
    ;~ If MsgBox(32 + 4, "Beenden", "Wollen sie das Programm wirklich beenden?") = 6 Then End() ; wenn ja, dann End-Funktion aufrufen
    EndSwitch
    WEnd

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

    Func _Stop()
    $fStop = True
    EndFunc

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

    Func End()
    ;~ Save() ; wenn der vordere Kommentar entfernt wird, dann werden vor dem beenden noch die Daten gespeichert
    _GUICtrlListView_UnRegisterSortCallBack($hLVHandle) ; Sortierroutine wieder de-registrieren
    Exit ; Programm beenden
    EndFunc

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

    Func Load() ; Datenbank-Datei laden
    Local $hFile, $sContent, $aNewItems
    $hFile = FileOpen($sDBFile, 0) ; Datei zum lesen öffnen
    If $hFile <> -1 Then ; wenn das öffnen erfolgreich war, dann...
    $sContent = FileRead($hFile) ; Datei komplett einlesen
    FileClose($hFile) ; Datei schließen
    $sContent = StringTrimRight($sContent, 2) ; das letzte @CRLF entfernen
    $aNewItems = StringSplit($sContent, @CRLF, 1) ; Den Dateiinhalt am Zeilenende splitten
    If Not IsArray($aNewItems) Then Return ; Wenn $aNewItems kein Array ist, dann Funktion verlassen
    _GUICtrlListView_SetItemCount($hListView, $aNewItems[0])
    _GUICtrlListView_BeginUpdate($hLVHandle) ; Listview sperren
    For $i = 1 To $aNewItems[0] ; Alle Einträge des Arrays durchgehen
    $iCount += 1
    _GUICtrlStatusBar_SetText($hStatus, $iCount, 1)
    GUICtrlCreateListViewItem($aNewItems[$i], $hListView) ; mit den eingelesenen Daten einen neuen Listview-Eintrag erstellen
    Next
    _GUICtrlListView_EndUpdate($hLVHandle) ; Listview wieder freigeben
    EndIf
    EndFunc ;==>Load

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

    Func Save() ; Datenbank-Datei speichern
    Local $sContent, $hFile, $iCount
    $iCount = _GUICtrlListView_GetItemCount($hLVHandle); Anzahl der Listview-Einträge holen
    If $iCount = 0 Then Return ; Wenn das Listview keine Einträge enthält, dann Funktion verlassen
    For $i = 0 To $iCount - 1 ; Schleife, um alle Listview-Einträge durchzugehen
    $sContent &= _GUICtrlListView_GetItemTextString($hLVHandle, $i) & @CRLF
    _GUICtrlStatusBar_SetText($hStatus, $i + 1, 2)
    Next
    $hFile = FileOpen($sDBFile, 2) ; Datei zum speichern (überschreiben) öffnen
    If $hFile <> -1 Then ; wenn das öffnen erfolgreich war, dann...
    FileWrite($hFile, $sContent)
    FileClose($hFile) ; Datei schließen
    EndIf
    EndFunc ;==>Save

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

    ;===============================================================================
    ; Function Name: _RecursiveFileListToArray($sPath[, $sPattern][, $iFlag][, $iFormat][, $iRecursion][, $sDelim])
    ; Description:: gibt Verzeichnisse (rekursiv) und/oder Dateien zurück, die einem RegExp-Pattern entsprechen
    ; Parameter(s): $sPath = Startverzeichnis
    ; $sPattern = ein beliebiges RexExp-Pattern für die Auswahl
    ; $iFlag = Auswahl
    ; 0 = Dateien & Verzeichnisse
    ; 1 = nur Dateien
    ; 2 = nur Verzeichnisse
    ; $iFormat = Rückgabeformat
    ; 0 = String
    ; 1 = Array mit [0] = Anzahl
    ; 2 = Nullbasiertes Array
    ; $iRecursion = Verzeichnisse rekursiv durchsuchen
    ; 0 = Nein
    ; 1 = Ja
    ; $sDelim = Trennzeichen für die String-Rückgabe
    ; Requirement(s): AutoIt 3.3.0.0
    ; Return Value(s): Array/String mit den gefundenen Dateien/Verzeichnissen
    ; Author(s): Oscar (http://www.autoit.de)
    ; Anregungen von: bernd670 (http://www.autoit.de)
    ;===============================================================================
    Func _RecursiveFileListToArray($sPath, $sPattern = '', $iFlag = 0, $iFormat = 1, $iRecursion = 1, $sDelim = @CRLF)
    Local $hSearch, $sFile, $sReturn = ''
    If StringRight($sPath, 1) <> '\' Then $sPath &= '\'
    $hSearch = FileFindFirstFile($sPath & '*.*')
    If @error Or $hSearch = -1 Then Return SetError(1, 0, $sReturn)
    While True
    $sFile = FileFindNextFile($hSearch)
    If @error Then ExitLoop
    If @extended Then
    If StringRegExp($sPath & $sFile, $sPattern) And ($iFlag = 0 Or $iFlag = 2) Then $sReturn &= $sPath & $sFile & '\' & $sDelim
    If $iRecursion Then $sReturn &= _RecursiveFileListToArray($sPath & $sFile & '\', $sPattern, $iFlag, 0)
    ContinueLoop
    EndIf
    If StringRegExp($sFile, $sPattern) And ($iFlag = 0 Or $iFlag = 1) Then $sReturn &= $sPath & $sFile & $sDelim
    WEnd
    FileClose($hSearch)
    If $iFormat And $sReturn = '' Then Return StringSplit($sReturn, '', $iFormat)
    If $iFormat Then Return StringSplit(StringTrimRight($sReturn, StringLen($sDelim)), $sDelim, $iFormat)
    Return $sReturn
    EndFunc

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

    ;===============================================================================
    ; Function Name: _ReadID3Tag($sPath)
    ; Description:: gibt ein Array mit den Daten aus den ID3-Tags zurück
    ; unterstützt werden die ID3-Tag-Versionen 1.0, 1.1, 2.3 und 2.4
    ; bei v2.4 müssen sich die ID3-Tags am Anfang der Datei befinden
    ; Parameter(s): $sPath = Pfad zu einer MP3-Datei
    ; Requirement(s): min. AutoIt v3.3.0.0
    ; Return Value(s): bei Erfolg: Array mit den ID3-Tagdaten (@error = 0)
    ; im Fehlerfall bekommt @error:
    ; 1 = Datei existiert nicht
    ; 2 = Datei konnte nicht zum lesen geöffnet werden
    ; 3 = falsche ID3 v2 Version
    ; 4 = Datei ist keine MP3-Datei
    ; Author(s): Oscar (http://www.autoit.de)
    ;===============================================================================
    Func _ReadID3Tag($sPath)
    If Not FileExists($sPath) Then Return SetError(1, 0, 0)
    Local $hFile, $sData, $sID3Header, $iID3HeaderSize = 0, $iOffset, $iSize, $tmp
    Local $aID3v2Tags[8] = ['TIT2', 'TPE1', 'TALB', 'TYER', 'TLEN', 'TRCK', 'TCON', 'TENC']
    Local $aID3[11][2] = [ _
    ['Title', ''],['Artist', ''],['Album', ''],['Year', ''], _
    ['Length', '0'],['Track', ''],['Genre', ''],['Encoder', ''], _
    ['MPEG-Version', ''],['Bitrate', '-'],['Sample-Freq.', '']]
    Local $aMP3Version[4] = ['MPEG2.5', 'Reserved', 'MPEG2', 'MPEG1']
    Local $aMP3Layer[4] = ['Reserved', 'Layer III', 'Layer II', 'Layer I']
    Local $aMP3Bitrate[5][16] = [ _
    [000, 032, 064, 096, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448, 000], _
    [000, 032, 048, 056, 064, 080, 096, 112, 128, 160, 192, 224, 256, 320, 384, 000], _
    [000, 032, 040, 048, 056, 064, 080, 096, 112, 128, 160, 192, 224, 256, 320, 000], _
    [000, 032, 048, 056, 064, 080, 096, 112, 128, 144, 160, 176, 192, 224, 256, 000], _
    [000, 008, 016, 024, 032, 040, 048, 056, 064, 080, 096, 112, 128, 144, 160, 000]]
    Local $aSampleFreq[3][4] = [[44100, 48000, 32000, 0],[22050, 24000, 16000, 0],[11025, 12000, 8000, 0]]
    Local $sMP3FrameHeader, $iMP3Version, $sMP3Version, $sMP3Layer, $iMP3Bitrate, $iMP3SampleFreq
    Local $iVBRFrames = -1, $iVBRFilesize, $iVBRFlags
    $hFile = FileOpen($sPath, 16)
    If $hFile = -1 Then Return SetError(2, 0, 0)
    $sData = Binary(FileRead($hFile, 4))
    If BinaryMid($sData, 1, 3) = '0x494433' Then ; ID3 v2.x Kennung gefunden
    If (BinaryMid($sData, 4, 1) = '0x03') Or (BinaryMid($sData, 4, 1) = '0x04') Then ; nur v2.3 und 2.4
    FileRead($hFile, 2) ; 2 Bytes überspringen
    For $i = 0 To 3 ; berechne ID3-Headergröße (4 Bytes, jedoch nur jeweils die unteren 7 Bit)
    $iID3HeaderSize = BitShift($iID3HeaderSize, -7) + BitAND(Binary(FileRead($hFile, 1)), 0x7F)
    Next
    If $iID3HeaderSize > 0 Then
    $sID3Header = Binary(FileRead($hFile, $iID3HeaderSize)) ; lese gesamten ID3-Header
    For $i = 0 To 7
    $iOffset = StringInStr(BinaryToString($sID3Header), $aID3v2Tags[$i]) ; Offset zu dem ID3-Tag
    If $iOffset > 0 Then
    $iSize = Hex(BinaryMid($sID3Header, $iOffset + 4, 4)) ; Größe des ID3-Frames
    $tmp = BinaryMid($sID3Header, $iOffset + 11, Dec($iSize) - 1)
    If BinaryMid($tmp, 1, 2) = '0xFFFE' Then
    For $x = 3 To BinaryLen($tmp) Step 2
    $aID3[$i][1] &= BinaryToString(BinaryMid($tmp, $x, 2), 2)
    Next
    Else
    For $x = 1 To BinaryLen($tmp)
    $aID3[$i][1] &= BinaryToString(BinaryMid($tmp, $x, 1))
    Next
    EndIf
    $aID3[$i][1] = StringReplace($aID3[$i][1], Chr(0), '')
    EndIf
    Next
    EndIf
    Do
    $sData = String(FileRead($hFile, 1))
    If @error Then ExitLoop
    If BitAND($sData, 0xff) = 0xff Then
    FileSetPos($hFile, -1, 1)
    $sData = String(FileRead($hFile, 4))
    EndIf
    Until BitAND($sData, 0xFFE00000) = 0xFFE00000
    Else
    FileClose($hFile)
    Return SetError(3, 0, 0)
    EndIf
    Else ; ID3 v1.x
    $iOffset = FileGetPos($hFile)
    FileSetPos($hFile, -128, 2)
    $sID3Header = BinaryToString(FileRead($hFile, 3))
    If $sID3Header = 'TAG' Then
    $aID3[0][1] = StringReplace(BinaryToString(FileRead($hFile, 30)), Chr(0), '')
    $aID3[1][1] = StringReplace(BinaryToString(FileRead($hFile, 30)), Chr(0), '')
    $aID3[2][1] = StringReplace(BinaryToString(FileRead($hFile, 30)), Chr(0), '')
    $aID3[3][1] = StringReplace(BinaryToString(FileRead($hFile, 4)), Chr(0), '')
    EndIf
    FileSetPos($hFile, $iOffset, 0)
    EndIf
    $sMP3FrameHeader = String($sData)
    If BitAND($sMP3FrameHeader, 0xFFE00000) <> 0xFFE00000 Then
    FileClose($hFile)
    Return SetError(4, 0, 0) ; keine MP3-Datei, dann Return
    EndIf
    $iMP3Version = BitShift(BitXOR($sMP3FrameHeader, 0xFFE00000), 19) ; welche MP3-Version
    $sMP3Version = $aMP3Version[$iMP3Version] ; in Textform
    $sMP3Layer = $aMP3Layer[BitShift(BitAND($sMP3FrameHeader, 0x60000), 17)] ; welcher Layer
    $aID3[8][1] = $sMP3Version & ' / ' & $sMP3Layer ; ins Ausgabe-Array
    $iMP3Bitrate = BitShift(BitAND($sMP3FrameHeader, 0xF000), 12) ; Bitraten-Index auslesen
    Switch $sMP3Version ; je nach MPEG-Version Bitrate aus der Tabelle holen
    Case 'MPEG1'
    $aID3[9][1] = $aMP3Bitrate[$iMP3Version - ($iMP3Version > 1)][$iMP3Bitrate]
    Case 'MPEG2', 'MPEG2.5'
    If $sMP3Layer = 'Layer I' Then
    $aID3[9][1] = $aMP3Bitrate[3][$iMP3Bitrate]
    Else
    $aID3[9][1] = $aMP3Bitrate[4][$iMP3Bitrate]
    EndIf
    EndSwitch
    $iMP3SampleFreq = BitShift(BitAND($sMP3FrameHeader, 0xC00), 10) ; Sample-Frequenz-Index auslesen
    $aID3[10][1] = $aSampleFreq[2 - ($iMP3Version - ($iMP3Version > 1))][$iMP3SampleFreq] ; und Wert aus der Tabelle holen
    Do ; evtl. Leerbytes überspringen
    $tmp = FileRead($hFile, 1)
    If @error Then ExitLoop
    Until $tmp <> 0x00 Or @error
    If $tmp = 0x58 And BinaryToString(FileRead($hFile, 3)) = 'ing' Then ; MP3 mit VBR (Xing-Header gefunden)?
    $iVBRFlags = '0x' & Hex(FileRead($hFile, 4)) ; VBR-Flags auslesen
    If BitAND($iVBRFlags, 0x3) Then ; wenn die Einträge vorhanden sind, dann...
    $iVBRFrames = Dec(Hex(FileRead($hFile, 4))) ; Anzahl der VBR-Frames auslesen
    $iVBRFilesize = Dec(Hex(FileRead($hFile, 4))) ; Dateigröße auslesen
    $aID3[4][1] = $iVBRFrames * 1152 / $aID3[10][1] * 1000 ; VBR Laufzeit
    $aID3[9][1] = 'VBR ~' & Int($iVBRFilesize * 8 / ($aID3[4][1] / 1000) / 1000) ; VBR durchschnittliche Bitrate
    EndIf
    Else
    If $aID3[4][1] = 0 Then $aID3[4][1] = (FileGetSize($sPath) * 8) / ($aID3[9][1] * 1000) * 1000 ; alternative CBR Laufzeit
    $aID3[9][1] = 'CBR ' & $aID3[9][1]
    EndIf
    $aID3[4][1] = _MyTicksToTime($aID3[4][1]) ; Laufzeit (Ticks to hour:min:sec)
    $aID3[9][1] &= ' kBit/s'
    $aID3[10][1] &= ' Hz'
    FileClose($hFile)
    Return SetError(0, 0, $aID3)
    EndFunc ;==>_ReadID3Tag

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

    Func _MyTicksToTime($iTicks)
    Local $iHour, $iMins, $iSecs
    $iHour = Int($iTicks / 3600000)
    $iTicks -= $iHour * 3600000
    $iMins = Int($iTicks / 60000)
    $iTicks -= $iMins * 60000
    $iSecs = Int($iTicks / 1000)
    Return StringFormat('%02i:%02i:%02i', $iHour, $iMins, $iSecs)
    EndFunc ;==>_MyTicksToTime

    [/autoit]

    Naja, habe ich Dir schon eine Menge Arbeit abgenommen, aber wie gesagt, es war eigentlich nur das zusammensetzen von meinen bereits vorhandenen Skripten. :)

    Dateien

    _MP3Search.au3 16,48 kB – 327 Downloads
  • GUICtrlSetResizing und GUICtrlCreateTab bzw. GUICtrlCreateTabItem

    • Oscar
    • 26. Juli 2010 um 11:36

    Welches Verhalten erwartest Du denn?
    Soll sich das Tab-Control ebenfalls der Größe anpassen?
    Dann so:

    Spoiler anzeigen
    [autoit]


    #include <ButtonConstants.au3>
    #include <GUIConstantsEx.au3>
    #include <ListViewConstants.au3>
    #include <TabConstants.au3>
    #include <WindowsConstants.au3>
    #Region ### START Koda GUI section ### Form=
    $Form1 = GUICreate("Form1", 413, 298, -1, -1, BitOR($WS_MAXIMIZEBOX,$WS_MINIMIZEBOX,$WS_SIZEBOX,$WS_THICKFRAME,$WS_SYSMENU,$WS_CAPTION,$WS_OVERLAPPEDWINDOW,$WS_TILEDWINDOW,$WS_POPUP,$WS_POPUPWINDOW,$WS_GROUP,$WS_TABSTOP,$WS_BORDER,$WS_CLIPSIBLINGS))
    $Tab1 = GUICtrlCreateTab(8, 8, 401, 281)
    GUICtrlSetResizing(-1, $GUI_DOCKBORDERS)
    $TabSheet1 = GUICtrlCreateTabItem("TabSheet1")
    $ListView1 = GUICtrlCreateListView("a|b|c|d", 32, 48, 250, 150)
    GUICtrlSendMsg($ListView1, $LVM_SETCOLUMNWIDTH, 0, 50)
    GUICtrlSendMsg($ListView1, $LVM_SETCOLUMNWIDTH, 1, 50)
    GUICtrlSendMsg($ListView1, $LVM_SETCOLUMNWIDTH, 2, 50)
    GUICtrlSendMsg($ListView1, $LVM_SETCOLUMNWIDTH, 3, 50)
    $ListView1_0 = GUICtrlCreateListViewItem("Test1a|Test1b|Test1c|Test1d", $ListView1)
    $ListView1_1 = GUICtrlCreateListViewItem("Test2a|Test2b|Test2c|Test2d", $ListView1)
    $Button1 = GUICtrlCreateButton("Button1", 32, 232, 75, 25, 0)
    $Button2 = GUICtrlCreateButton("Button2", 128, 232, 75, 25, 0)
    GUICtrlCreateTabItem("")
    GUISetState(@SW_SHOW)
    #EndRegion ### END Koda GUI section ###

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

    While 1
    $nMsg = GUIGetMsg()
    Switch $nMsg
    Case $GUI_EVENT_CLOSE
    Exit

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

    EndSwitch
    WEnd

    [/autoit]
  • mp3 Searcher

    • Oscar
    • 26. Juli 2010 um 08:40

    Da hast Du Dir ja einiges vorgenommen. Wobei ich zweifle, ob man das einfach so "by doing" lernen kann, aber ich lasse mich da gern eines Besseren belehren.

    Ein Edit-Control-Element halte ich für so ein Projekt aber für falsch oder sagen wir: suboptimal. Ich würde Dir lieber zu einem Listview raten. Falls Dir da auch die Grundlagen fehlen, kannst Du Dir vielleicht mal mein Listview-Datenbank-Beispiel anschauen:

    Spoiler anzeigen
    [autoit]


    #include <ButtonConstants.au3>
    #include <GUIConstantsEx.au3>
    #include <GuiListView.au3>
    #include <ListViewConstants.au3>
    #include <WindowsConstants.au3>

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

    Global $sHeader = "Artikelnummer|Art|Nummer|Baureihe|Name" ; Die Überschriften für das Listview und für das "Neuer Eintrag"-Fenster
    Global $sDBFile = @ScriptDir & "\datenbank.txt" ; Pfad und Name der Datenbank-Datei
    Global $iEdit = -1 ; Wert auf -1 setzen, weil _GUICtrlListView_GetSelectionMark() einen Nullbasierten Wert liefert

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

    #Region Hauptfenster
    Global $hGui = GUICreate("Listview-Datenbank-Beispiel", 600, 480) ; Hauptfenster erstellen
    Global $hListView = GUICtrlCreateListView($sHeader, 0, 0, 600, 420, $LVS_SHOWSELALWAYS) ; Listview erstellen

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

    Global $hLVHandle = GUICtrlGetHandle($hListView) ; das Handle vom Listview wird für die UDF-Listview-Funktionen benötigt
    _GUICtrlListView_SetColumn($hLVHandle, 0, "Artikelnummer", 120, 1) ; 1. Spalte = 120 Px breit, rechts ausgerichtet
    _GUICtrlListView_SetColumn($hLVHandle, 1, "Art", 60, 0) ; 2. Spalte = 60 Px breit, links ausgerichtet
    _GUICtrlListView_SetColumn($hLVHandle, 2, "Nummer", 90, 0) ; 3. Spalte = 90 Px breit, links ausgerichtet
    _GUICtrlListView_SetColumn($hLVHandle, 3, "Baureihe", 100, 0) ; 4. Spalte = 100 Px breit, links ausgerichtet
    _GUICtrlListView_SetColumn($hLVHandle, 4, "Name", 120, 0) ; 5. Spalte = 120 Px breit, links ausgerichtet

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

    Global $hNew = GUICtrlCreateButton("Neuer Eintrag", 5, 430, 80, 35, $BS_DEFPUSHBUTTON) ; Dieser Button ist der Default-Push-Button (wenn der User [Enter] drückt)
    Global $hEdit = GUICtrlCreateButton("Markierten Eintrag bearbeiten", 95, 430, 110, 35, $BS_MULTILINE) ; $BS_Multiline für mehrzeiligen Button
    Global $hLoad = GUICtrlCreateButton("Laden", 230, 430, 70, 35)
    Global $hSave = GUICtrlCreateButton("Speichern", 310, 430, 70, 35)
    Global $hDel = GUICtrlCreateButton("Markierte Einträge löschen", 400, 430, 90, 35, $BS_MULTILINE)
    Global $hDelAll = GUICtrlCreateButton("Alle Einträge löschen", 500, 430, 90, 35, $BS_MULTILINE)

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

    Global $hCM = GUICtrlCreateContextMenu($hListView) ; ein Kontextmenü für das Listview erstellen
    Global $hCMNew = GUICtrlCreateMenuItem("Neuer Eintrag", $hCM) ; der 1. Kontextmenüeintrag
    Global $hCMEdit = GUICtrlCreateMenuItem("Eintrag bearbeiten", $hCM) ; der 2. Kontextmenüeintrag
    Global $hCMDel = GUICtrlCreateMenuItem("Markierte Einträge löschen", $hCM) ; der 3. Kontextmenüeintrag
    #EndRegion Hauptfenster

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

    #Region Fenster für neuen Eintrag
    Global $hGuiNew = GUICreate("Neuer Eintrag", 632, 140, -1, -1, $WS_SYSMENU) ; das Fenster "Neuer Eintrag" erstellen
    Global $aHeader = StringSplit($sHeader, '|') ; Überschriften-Array
    Global $aNew[$aHeader[0]] ; Array für die Input-IDs
    For $i = 1 To $aHeader[0]
    GUICtrlCreateLabel($aHeader[$i], 4 + ($i - 1) * 125, 15, 110, 20) ; Überschriften-Label erstellen
    GUICtrlSetFont(-1, 8, 400, 0, 'Verdana') ; Schriftgröße und -art der Überschriften festlegen
    $aNew[$i - 1] = GUICtrlCreateInput("", 2 + ($i - 1) * 125, 30, 120, 20, Default, $WS_EX_STATICEDGE) ; Eingabefelder erstellen
    GUICtrlSetFont(-1, 10, 600, 0, 'Verdana') ; Schriftgröße und -art der Eingabefelder festlegen
    Next
    Global $hCreate = GUICtrlCreateButton("Eintrag speichern", 254, 65, 120, 25, $BS_DEFPUSHBUTTON) ; Button zum speichern
    #EndRegion Fenster für neuen Eintrag

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

    _GUICtrlListView_RegisterSortCallBack($hLVHandle) ; damit man das Listview (mit Klick auf die Spaltenüberschrift) sortieren kann

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

    GUISetState(@SW_SHOW, $hGui) ; Hauptfenster sichtbar machen

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

    If FileExists($sDBFile) Then Load() ; wenn Datenbank-Datei existiert, dann Datenbank laden

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

    While 1
    $nMsg = GUIGetMsg(1) ; Message-Event holen (1) = erweiterter Modus
    Switch $nMsg[0] ; anhand der Control-ID das entsprechende Case aufrufen
    Case $hListView ; User hat auf eine Spaltenüberschrift geklickt
    _GUICtrlListView_SortItems($hLVHandle, GUICtrlGetState($hListView)) ; Einträge entsprechend sortieren
    Case $hNew, $hCMNew ; User hat auf "Neuer Eintrag" geklickt
    WinSetTitle($hGuiNew, "", "Neuer Eintrag") ; den Titel des Fenster anpassen
    GUISetState(@SW_SHOW, $hGuiNew) ; das Fenster "Neuer Eintrag" anzeigen
    GUISetState(@SW_DISABLE, $hGui) ; das Hauptfenster deaktivieren
    Case $hEdit, $hCMEdit ; User hat auf "Eintrag bearbeiten" geklickt
    WinSetTitle($hGuiNew, "", "Eintrag bearbeiten") ; den Titel des Fenster anpassen
    GUISetState(@SW_SHOW, $hGuiNew) ; das Fenster "Neuer Eintrag" anzeigen
    GUISetState(@SW_DISABLE, $hGui) ; das Hauptfenster deaktivieren
    Edit()
    Case $hLoad ; User hat auf "Laden" geklickt
    Load()
    Case $hSave ; User hat auf "Laden" geklickt
    Save()
    Case $hDel, $hCMDel ; User hat auf "Markierte Einträge löschen" geklickt
    If MsgBox(256 + 32 + 4, "Einträge löschen", "Wollen sie die markierten Einträge wirklich löschen?") = 6 Then _GUICtrlListView_DeleteItemsSelected($hLVHandle)
    Case $hDelAll ; User hat auf "Alle Einträge löschen" geklickt
    If MsgBox(256 + 32 + 4, "Einträge löschen", "Wollen sie wirklich alle Einträge löschen?") = 6 Then _GUICtrlListView_DeleteAllItems($hLVHandle)
    Case $hCreate ; User hat auf "Eintrag speichern" im Fenster "Neuer Eintrag" geklickt
    NewItem()
    Case $GUI_EVENT_CLOSE ; User hat auf das Schließen-Symbol geklickt (bzw. die ESC-Taste gedrückt)
    Switch $nMsg[1] ; erweiterte Abfrage für welches Fenster
    Case $hGui ; User will das Hauptfenster schließen
    If MsgBox(32 + 4, "Beenden", "Wollen sie das Programm wirklich beenden?") = 6 Then End() ; wenn ja, dann End-Funktion aufrufen
    Case $hGuiNew ; User will das "Neuer Eintrag"-Fenster schließen
    $iEdit = -1
    For $i = 0 To UBound($aNew) - 1
    GUICtrlSetData($aNew[$i], "") ; Alle Eingabefelder leeren
    Next
    GUISetState(@SW_HIDE, $hGuiNew) ; "Neuer Eintrag"-Fenster verstecken
    GUISetState(@SW_ENABLE, $hGui) ; Hauptfenster wieder aktivieren
    WinActivate($hGui) ; und in den Vordergrund holen
    EndSwitch
    EndSwitch
    WEnd

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

    Func End()
    ;~ Save() ; wenn der vordere Kommentar entfernt wird, dann werden vor dem beenden noch die Daten gespeichert
    _GUICtrlListView_UnRegisterSortCallBack($hLVHandle) ; Sortierroutine wieder de-registrieren
    Exit ; Programm beenden
    EndFunc

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

    Func NewItem() ; Funktion zum auslesen der Eingabefelder (Neuer Eintrag bzw. Eintrag bearbeiten)
    Local $sItem = ""
    For $i = 0 To UBound($aNew) - 1 ; Schleife, um alle Eingabefelder durchzugehen
    If $iEdit > -1 Then ; wenn $iEdit > -1 (Eintrag bearbeiten), dann...
    _GUICtrlListView_SetItemText($hLVHandle, $iEdit, GUICtrlRead($aNew[$i]), $i) ; den Eintrag aus dem Eingabefeld ins Listview schreiben
    Else ; sonst $iEdit = -1 (neuer Eintrag)
    $sItem &= GUICtrlRead($aNew[$i]) & "|" ; den Eintrag aus dem Eingabefeld erstmal in einer Variablen ($sItem) speichern
    EndIf
    GUICtrlSetData($aNew[$i], "") ; das entsprechende Eingabefeld leeren
    Next
    If $iEdit > -1 Then ; wenn $iEdit > -1 (Eintrag bearbeiten), dann...
    $iEdit = -1
    GUISetState(@SW_HIDE, $hGuiNew) ; "Neuer Eintrag"-Fenster verstecken
    GUISetState(@SW_ENABLE, $hGui) ; Hauptfenster wieder aktivieren
    Sleep(300)
    WinActivate($hGui) ; und in den Vordergrund holen
    Else ; sonst $iEdit = -1 (neuer Eintrag)
    GUICtrlSetState($aNew[0], $GUI_FOCUS) ; den Focus wieder auf das erste Eingabefeld setzen, für weitere Eingaben
    GUICtrlCreateListViewItem(StringTrimRight($sItem, 1), $hListView) ; mit den Werten aus $sItem einen neuen Listview-Eintrag hinzufügen
    EndIf
    EndFunc ;==>NewItem

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

    Func Edit() ; Funktion zum bearbeiten eines Listview-Eintrags im "Eintrag bearbeiten"-Fenster
    $iEdit = _GUICtrlListView_GetSelectionMark($hLVHandle) ; auslesen, welcher Listview-Eintrag markiert (bei mehreren, den obersten) ist
    If $iEdit > -1 Then
    Local $aItem = _GUICtrlListView_GetItemTextArray($hLVHandle, $iEdit) ; die Einträge aus dem Listview in ein Array holen
    For $i = 1 To $aItem[0]
    GUICtrlSetData($aNew[$i - 1], $aItem[$i]) ; und in die entsprechenden Eingabefelder schreiben
    Next
    EndIf
    EndFunc ;==>Edit

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

    Func Load() ; Datenbank-Datei laden
    Local $hFile, $sContent, $aNewItems
    $hFile = FileOpen($sDBFile, 0) ; Datei zum lesen öffnen
    If $hFile <> -1 Then ; wenn das öffnen erfolgreich war, dann...
    $sContent = FileRead($hFile) ; Datei komplett einlesen
    FileClose($hFile) ; Datei schließen
    $sContent = StringTrimRight($sContent, 2) ; das letzte @CRLF entfernen
    $aNewItems = StringSplit($sContent, @CRLF, 1) ; Den Dateiinhalt am Zeilenende splitten
    If Not IsArray($aNewItems) Then Return ; Wenn $aNewItems kein Array ist, dann Funktion verlassen
    _GUICtrlListView_BeginUpdate($hLVHandle) ; Listview sperren
    For $i = 1 To $aNewItems[0] ; Alle Einträge des Arrays durchgehen
    GUICtrlCreateListViewItem($aNewItems[$i], $hListView) ; mit den eingelesenen Daten einen neuen Listview-Eintrag erstellen
    Next
    _GUICtrlListView_EndUpdate($hLVHandle) ; Listview wieder freigeben
    EndIf
    EndFunc ;==>Load

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

    Func Save() ; Datenbank-Datei speichern
    Local $sItem, $hFile, $iCount
    $iCount = _GUICtrlListView_GetItemCount($hLVHandle) - 1 ; Anzahl der Listview-Einträge holen
    If $iCount = -1 Then Return ; Wenn das Listview keine Einträge enthält, dann Funktion verlassen
    $hFile = FileOpen($sDBFile, 2) ; Datei zum speichern (überschreiben) öffnen
    If $hFile <> -1 Then ; wenn das öffnen erfolgreich war, dann...
    For $i = 0 To $iCount ; Schleife, um alle Listview-Einträge durchzugehen
    $sItem = _GUICtrlListView_GetItemTextString($hLVHandle, $i) ; die Werte aus dem Listview-Eintrag holen
    FileWriteLine($hFile, $sItem) ; und in die Datei schreiben
    Next
    FileClose($hFile) ; Datei schließen
    EndIf
    EndFunc ;==>Save

    [/autoit]


    Ein Listview bietet halt einfach eine bessere Übersicht (Spalten-Zeilenorientiert) und man kann nach einzelnen Spalten sortieren lassen.

  • mp3 Searcher

    • Oscar
    • 25. Juli 2010 um 22:48

    Naja, Möglichkeiten gibt es viele, die Daten weiter zu verwenden. Ich verwende gerne ListViews, da könnte man die ID3-Tags auslesen und dann in jeweils eine Spalte einfügen (zusätzlich zum Dateipfad).
    Entscheidend ist aber, was willst Du damit erreichen, also: Was soll am Ende dabei rauskommen?
    Einfach eine Auflistung aller MP3s ist ja ganz schön, aber was soll man damit anfangen? Nicht falsch verstehen, ich will Dein Projekt nicht runtermachen, nur voranbringen. :)

    Wenn Du noch nicht viel mit Arrays anfangen kannst, dann wäre es vielleicht angebracht, dieses Projekt erstmal aufzuschieben und sich mit Grundlagen (Arrays) zu befassen.
    Oder anders ausgedrückt: Bevor Du anfängst zu rennen, lerne erst das gehen. ;)

  • suche Konst. Wert jedoch verschieden

    • Oscar
    • 25. Juli 2010 um 21:41

    Windows ab Vista unterstützt das auslesen der Hardware-Seriennummer aller eingebauten Festplatten. Die werden vom jeweiligen Hersteller vergeben und sind einmalig (sollten sie jedenfalls).
    Auslesen kann man sie so:

    Spoiler anzeigen
    [autoit]


    #include <Array.au3>
    $aDisks = _CI_GetHarddrives()
    _ArrayDisplay($aDisks)

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

    Func _CI_GetHarddrives($strComputer = '.')
    Local $aReturn[1][8] = [[ _
    'Bezeichnung:', 'Größe:', 'Anschluss:', 'Bytes/Sektor:', 'Anzahl der Sektoren:', _
    'PNPDeviceID:', 'Status:', 'Seriennr. (Hardware):']]
    Local $x = 0, $objWMIService, $colItems
    $objWMIService = ObjGet('winmgmts:\\' & $strComputer & '\root\cimv2')
    If Not IsObj($objWMIService) Then Return SetError(1, 0, 0)
    $colItems = $objWMIService.ExecQuery('SELECT * FROM Win32_DiskDrive', 'WQL', 0x30)
    If IsObj($colItems) Then
    For $objItem In $colItems
    $x += 1
    ReDim $aReturn[$x + 1][8]
    $aReturn[$x][0] = $objItem.Model
    $aReturn[$x][1] = $objItem.Size
    $aReturn[$x][2] = $objItem.InterfaceType
    $aReturn[$x][3] = $objItem.BytesPerSector
    $aReturn[$x][4] = $objItem.TotalSectors
    $aReturn[$x][5] = $objItem.PNPDeviceID
    $aReturn[$x][6] = $objItem.Status
    Switch @OSVersion
    Case 'WIN_VISTA', 'WIN_7'
    If Number($objItem.SerialNumber) > 0 Then
    $aReturn[$x][7] = $objItem.SerialNumber & ' ("' & _CI_SerialToString($objItem.SerialNumber) & '")'
    Else
    $aReturn[$x][7] = 'nicht vorhanden'
    EndIf
    Case Else
    $aReturn[$x][7] = 'Wird von ' & @OSVersion & ' nicht unterstützt!'
    EndSwitch
    Next
    EndIf
    Return $aReturn
    EndFunc ;==>_CI_GetHarddrives

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

    Func _CI_SerialToString($sSerial)
    Local $sOut = ''
    For $i = 1 To StringLen($sSerial) Step 2
    $sOut &= Chr(Dec(StringMid($sSerial, $i, 2)))
    Next
    Return $sOut
    EndFunc ;==>_CI_SerialToString

    [/autoit]
  • Danke für die Zeit bei Euch!

    • Oscar
    • 24. Juli 2010 um 11:35

    Schade, dass Du uns verlässt. Aber viel Glück und Erfolg in Deiner neuen Heimat.
    Und vielleicht findet sich ja irgendwo ein Internet-Cafe. ^^

  • Button für externen Programmaufruf reagiert nur einmal

    • Oscar
    • 24. Juli 2010 um 10:01

    WinWaitActive wartet bis zum Sanktnimmerleinstag (ohne Timeout), wenn das Updatefenster nicht auftaucht. ;)
    Mit anderen Worten: das Skript wird an dieser Stelle pausiert, bis das Fenster auftaucht (die While-Schleife wird nicht weiter durchlaufen).
    Teste lieber innerhalb der While-Schleife mit "If WinExists("update", "OK") Then...", ob das Fenster existiert.

  • Starplayer v3

    • Oscar
    • 24. Juli 2010 um 09:52

    Danke für den Hinweis auf _BASS_ChannelSlideAttribute und das Beispiel! Das erleichtert das crossfading ungemein. :thumbup:

    Es gibt jetzt auch gleich eine neue Version (Post #1).

Spenden

Jeder Euro hilft uns, Euch zu helfen.

Download

AutoIt Tutorial
AutoIt Buch
Onlinehilfe
AutoIt Entwickler
  1. Datenschutzerklärung
  2. Impressum
  3. Shoutbox-Archiv
Community-Software: WoltLab Suite™