CD Infomationen (Artist, Name, Titel und noch vieles mehr) von FreeDB.org empfangen

    • Offizieller Beitrag

    Hallo

    Mit diesem schönen von mir geschrieben Tool könnt ihr kinderleicht CD Informationen von einer CD bekommen.
    Folgende Informationen werden per TCP übermittelt:

    • Artist
    • Album Name
    • Jahr
    • Genre
    • Sonstige CD Infos (EXTD)
    • Titel mit länge und position auf der CD

    Das alles funktioniert über die freie Datenbank FreeDB.org.
    Das gleiche verfahren benutzt auch z.B. Audiograbber, ein Tool zum CD rippen.

    Legt einfach irgendeine CD (keine MP3 CD sondern eine normale im Fachhandel erhätliche CD) ein und startet das Beispiel und guckt was passiert :)

    Kleines Dankeschön an pee, der mir geholfen hat ein paar Parts von Perl nach AutoIt zu übertragen :love:

    Hier die CDDB.au3 (include Datei)

    Spoiler anzeigen
    [autoit]

    #include-once

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

    ;CDDB.au3 - By GtaSpider

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

    Global $hWinmmDLL = DllOpen("winmm.dll")

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

    ;===============================================================================
    ;
    ; Function Name: _CDDBCreateQuery($sCD)
    ; Description:: Create a CDDB Query for e.g. freedb.org
    ; Parameter(s): $sCd - The CD Drive, e.g. e: or D:
    ; Requirement(s): -
    ; Return Value(s): On Success: Returns the CD Query.
    ; : On Error:
    ; : @error = 1 $sCD isn't a CD Drive
    ; : @error = 2 MCICommand failed - @extended = 0 --> Open CD faild
    ; @extended = 1 --> Number of Tracks faild
    ; : @error = 3 Failed to get the CD Checksum (CD ID) - @extended: Errorcode from __CDDBGetCDID()
    ; : @error = 4 Failed to get tracks
    ; : @error = 5 Failed to get LeadOut
    ;
    ; Author(s): GtaSpider
    ;
    ;===============================================================================
    ;
    Func _CDDBCreateQuery($sCD)
    Local $sRet, $iTotal, $i
    $sCD = StringUpper(StringLeft($sCD, 2))
    If (Not FileExists($sCD)) Or DriveGetType($sCD) <> "CDROM" Then Return SetError(1, 0, 0)
    $sRet = __SendMCIString("open " & $sCD & " type cdaudio alias cd1")
    If @error Then Return SetError(2, 0, 0)
    $sRet = __SendMCIString("status cd1 number of tracks wait")
    If @error Then Return SetError(2, 1, 0)
    $iTotal = $sRet
    $sRet = "cddb query " & __CDDBGetCDID($iTotal) & " " & $iTotal & " "
    If @error Then Return SetError(3, @error, 0)
    For $i = 1 To $iTotal
    $sRet &= __CDDBGetTrack($i) & " "
    If @error Then Return SetError(4, 0, 0)
    Next
    $sRet &= __CDDBGetLeadOut()
    If @error Then Return SetError(4, 0, 0)
    Return $sRet
    EndFunc ;==>_CDDBCreateQuery

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

    ;===============================================================================
    ;
    ; Function Name: _RecvFreeDB
    ; Description:: Connect to the Freedb.org Database
    ; Parameter(s): $sQuery: The Query Returned e.g. by _CDDBCreateQuery
    ; Requirement(s): Internet Connection
    ; Return Value(s): On Success: Returns the string received from freedb.org in "INI format"
    ; : On Error:
    ; : @error = 1 - Wrong Query
    ; : @error = 2 - Failed to get the IP from freedb.org
    ; : @error = 3 - Failed to connect to freedb.org
    ; : @error = 4 - Error on freedb.org - Freedb is not ready (maybe too much Clients)
    ; : @error = 5 - Error on freedb.org - Authorization failed
    ; : @error = 6 - Error on freedb.org - Failed to set protocol ID
    ; : @error = 7 - Error on freedb.org - No matches found
    ; : @error = 8 - Error on freedb.org - No informations found
    ; Author(s): GtaSpider
    ;
    ;===============================================================================
    ;
    Func _FreeDBRecvDB($sQuery, $fSecTry = False)
    Local $sIP, $hSocket, $sCDChcksum
    $sCDChcksum = StringRegExp($sQuery, "cddb query (.*?) ", 3)
    If @error Or (Not IsArray($sCDChcksum)) Then Return SetError(1, 0, 0)
    $sCDChcksum = $sCDChcksum[0]
    TCPStartup()
    $sIP = TCPNameToIP("mirror1.freedb.org")
    If @error Or (Not StringLen($sIP)) Then Return SetError(2, 0, 0)
    $hSocket = TCPConnect($sIP, 8880)
    If @error Then Return SetError(3, @error, 0)
    $sRecv = __TCPRecv($hSocket)
    If (Not StringInStr($sRecv, "201")) And (Not StringInStr($sRecv, "ready")) Then Return SetError(4, 0, $sRecv)
    TCPSend($hSocket, "cddb hello GtaSpider AutoIt AutoIt " & @AutoItVersion & @CRLF)
    $sRecv = __TCPRecv($hSocket)
    If Not StringInStr($sRecv, "200 Hello and welcome") Then Return SetError(5, 0, $sRecv)

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

    TCPSend($hSocket, "proto 5" & @CRLF)
    $sRecv = __TCPRecv($hSocket)
    If Not StringInStr($sRecv, "201 OK, CDDB protocol level now: 5") Then Return SetError(6, 0, $sRecv)

    TCPSend($hSocket, $sQuery & @CRLF)
    $sRecv = __TCPRecv($hSocket) ; genre CDID Artist / CDName, z.B. 200 rock b009520e Green Day / Dookie
    If StringInStr($sRecv, "211 Found inexact matches") And $fSecTry = False Then
    TCPCloseSocket($hSocket)
    TCPShutdown()
    Return _FreeDBRecvDB(StringReplace($sQuery, $sCDChcksum, StringLower(Hex(Number("0x" & $sCDChcksum) - 0x200, 8))), True)
    ElseIf StringInStr($sRecv, "211 Found inexact matches") And $fSecTry Then
    Return $sRecv
    EndIf
    If Not StringInStr($sRecv, "200") Then Return SetError(7, 0, $sRecv)
    $aSS = StringSplit($sRecv, " ")
    TCPSend($hSocket, "cddb read " & $aSS[2] & " " & $sCDChcksum & @CRLF)
    $sRecv = __TCPRecv($hSocket)
    If Not StringInStr($sRecv, "210") Then Return SetError(8, 0, $sRecv)
    Return $sRecv
    EndFunc ;==>_FreeDBRecvDB

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

    ;===============================================================================
    ;
    ; Function Name: _FreeDBRetCDInfos
    ; Description:: Returns Artist, Albumname, Genre, Year and other informations of the CD in an array
    ; Parameter(s): $sDatabase - The Databasestring from e.g. _FreeDBRecvDB
    ; Requirement(s): -
    ; Return Value(s): On Success: Returns an array with following informations:
    ; : $aRet[0] = Artist
    ; : $aRet[1] = Album
    ; : $aRet[2] = Genre
    ; : $aRet[3] = Year
    ; : $aRet[4] = Other Informations
    ; Author(s): GtaSpider
    ;
    ;===============================================================================
    ;

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

    Func _FreeDBRetCDInfos($sDatabase)
    Local $aSS, $aRet[5], $sRDB
    $sRDB = __ReadDatabase($sDatabase, "DTITLE")
    If @error Then
    $aRet[0] = "NO ARTIST"
    $aRet[1] = "NO ALBUM"
    Else
    $aSS = StringSplit($sRDB, " / ", 1)
    If $aSS[0] < 2 Then
    $aRet[0] = __ReadDatabase($sDatabase, "DTITLE")
    Else
    $aRet[0] = $aSS[1]
    $aRet[1] = $aSS[2]
    EndIf
    EndIf
    $sRDB = __ReadDatabase($sDatabase, "DGENRE")
    If @error Then
    $aRet[2] = "NO GENRE"
    Else
    $aRet[2] = $sRDB
    EndIf
    $sRDB = __ReadDatabase($sDatabase, "DYEAR")
    If @error Then
    $aRet[3] = "NO YEAR"
    Else
    $aRet[3] = $sRDB
    EndIf
    $sRDB = __ReadDatabase($sDatabase, "EXTD")
    If @error Then
    $aRet[4] = "NO EXTD"
    Else
    $aRet[4] = $sRDB
    EndIf

    Return $aRet
    EndFunc ;==>_FreeDBRetCDInfos

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

    ;===============================================================================
    ;
    ; Function Name: _FreeDBRetCDTracks
    ; Description:: Returns tracks, length of tracks and position of tracks of the CD in an 2D array
    ; Parameter(s): $sDatabase - The Databasestring from e.g. _FreeDBRecvDB
    ; Requirement(s): -
    ; Return Value(s): On Success returns an 0 based 2D array:
    ; : $aRet[0][0] = First track name
    ; : $aRet[0][1] = First track length
    ; : $aRet[0][2] = First track position
    ; : $aRet[n][0] = n track name
    ; : ....
    ; Author(s): GtaSpider
    ;
    ;===============================================================================
    ;

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

    Func _FreeDBRetCDTracks($sDatabase)
    Local $aRet[1][1], $sRead, $iTotal
    $iTotal = __SendMCIString("status cd1 number of tracks wait")
    If @error Then Return SetError(1, 0, 0)
    ReDim $aRet[$iTotal][3]
    For $i = 1 To $iTotal
    $sRead = __ReadDatabase($sDatabase, "TTITLE" & $i - 1)
    If @error Or $sRead = '' Then Return SetError(2, 0, 0)
    $aRet[$i - 1][0] = $sRead
    $aMSF = __SplitMSF(__SendMCIString("status cd1 length track " & $i))
    If @error Then Return SetError(3, 0, 0)
    $aRet[$i - 1][1] = $aMSF[1] & ":" & StringTrimLeft("00", StringLen(Round(Number($aMSF[2] & "." & $aMSF[3])))) & Round(Number($aMSF[2] & "." & $aMSF[3]))
    $aMSF = __SplitMSF(__SendMCIString("status cd1 position track " & $i))
    If @error Then Return SetError(3, 1, 0)
    $aRet[$i - 1][2] = $aMSF[1] & ":" & StringTrimLeft("00", StringLen(Round(Number($aMSF[2] & "." & $aMSF[3])))) & Round(Number($aMSF[2] & "." & $aMSF[3]))
    Next
    Return $aRet
    EndFunc ;==>_FreeDBRetCDTracks

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

    Func __CDDBGetTrack($iTrack)
    Local $sRet = __SendMCIString("status cd1 position track " & $iTrack), $aMSF
    If @error Then Return SetError(1, 0, 0)
    $aMSF = __SplitMSF($sRet)
    If @error Then Return SetError(2, @extended, 0)
    Return ($aMSF[1] * 75 * 60) + ($aMSF[2] * 75) + $aMSF[3]
    EndFunc ;==>__CDDBGetTrack

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

    Func __CDDBGetLeadOut()
    Local $sRet = __SendMCIString("status cd1 length wait"), $aMSF
    If @error Then Return SetError(1, 0, 0)
    $aMSF = __SplitMSF($sRet)
    If @error Then Return SetError(2, @extended, 0)
    Return ($aMSF[1] * 60) + $aMSF[2] + 2
    EndFunc ;==>__CDDBGetLeadOut

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

    Func __CDDBSum($iSum)
    Local $aSS = StringSplit($iSum, ""), $iRet
    For $i = 1 To $aSS[0]
    $iRet += Number($aSS[$i])
    Next
    Return $iRet
    EndFunc ;==>__CDDBSum

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

    Func __CDDBGetCDID($iTotal)
    Local $iChecksum
    For $i = 1 To $iTotal
    $sRet = __SendMCIString("status cd1 position track " & $i)
    $aMSF = __SplitMSF($sRet)
    If @error Then Return SetError(1, @extended, 0)
    $iChecksum += __CDDBSum($aMSF[1] * 60 + $aMSF[2])
    Next
    $aMSF = __SplitMSF(__SendMCIString("status cd1 length wait"))
    If @error Then Return SetError(1, @extended, 0)
    $leadout = ($aMSF[1] * 60 * 75 + ($aMSF[2]) * 75 + $aMSF[3])
    $tottime = ($leadout / 75) - ($iTotal / 75)
    $iChecksum = BitOR(BitShift(Mod($iChecksum, 0xff), -24), BitShift($tottime, -8), $iTotal)
    Return StringLower(Hex($iChecksum, 8))
    EndFunc ;==>__CDDBGetCDID

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

    Func __SplitMSF($sMSF)
    Local $aSS = StringSplit($sMSF, ":")
    If @error Or $aSS[0] <> 3 Then Return SetError(1, @error, 0)
    Return $aSS
    EndFunc ;==>__SplitMSF

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

    Func __ReadDatabase($sDatabase, $sKey)
    Local $aRet = StringRegExp($sDatabase, $sKey & "=(.*?)\r\n", 3)
    If @error Or IsArray($aRet) = False Then Return SetError(1, @error, 0)
    Return $aRet[0]
    EndFunc ;==>__ReadDatabase

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

    Func __SendMCIString($sString, $iBuf = 255)
    Local $aRet = DllCall($hWinmmDLL, "int", "mciSendString", "str", $sString, "str", "str", "int", $iBuf, "long", 0)
    If @error Then Return SetError(@error, 0, 0)
    Return $aRet[2]
    EndFunc ;==>__SendMCIString

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

    Func __TCPRecv($hSocket, $iSleep = 50, $iTimeOut = 20000, $iBuffersize = 1024, $iForceBinary = 0)
    Local $sRecv, $sRet, $iErr = 0, $hTi
    $hTi = TimerInit()
    While TimerDiff($hTi) <= $iTimeOut
    $sRecv = TCPRecv($hSocket, $iBuffersize, $iForceBinary)
    $iErr = @error
    If $iErr Then ExitLoop
    While StringLen($sRecv)
    $sRet &= $sRecv
    $sRecv = TCPRecv($hSocket, $iBuffersize, $iForceBinary)
    $iErr = @error
    If (Not StringLen($sRecv)) Or $iErr Then ExitLoop 2
    If TimerDiff($hTi) > $iTimeOut Then ExitLoop
    WEnd
    Sleep($iSleep)
    WEnd
    If TimerDiff($hTi) > $iTimeOut Then Return SetError(1, 0, "Timeout")
    If $iErr Then Return SetError($iErr, 0, 0)
    Return $sRet
    EndFunc ;==>__TCPRecv

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

    Func OnAutoItExit()
    __SendMCIString("close cd1")
    DllClose($hWinmmDLL)
    EndFunc ;==>OnAutoItExit

    [/autoit]

    Und hier ein Beispiel

    Spoiler anzeigen
    [autoit]

    #include "CDDB.au3"

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

    ;Example for CDDB.au3 - By GtaSpider

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

    $aDGCD = DriveGetDrive("CDROM")
    $sCombostring = ''
    For $i = 1 To $aDGCD[0]
    $sCombostring &= StringUpper($aDGCD[$i]) & "|"
    Next
    StringTrimRight($sCombostring, 1)

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

    GUICreate("Choose one drive", 150, 95, -1, -1, -1, 128);$WS_EX_TOOLWINDOW
    $hComb_Drive = GUICtrlCreateCombo("", 10, 10, 50, 22)
    GUICtrlSetData(-1, $sCombostring, $aDGCD[1])
    $hBut_AskFreeDB = GUICtrlCreateButton("Ask FreeDB", 65, 10, 80, 22, 1) ; Style = $BS_DEFPUSHBUTTON
    $hLab_Text = GUICtrlCreateLabel('Please choose one of the CD drives and click on "Ask FreeDB" to receive informations of the CD.', 10, 35, 130, 60)
    GUISetState()

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

    While 1
    Switch GUIGetMsg()
    Case $hBut_AskFreeDB
    $sLW = GUICtrlRead($hComb_Drive)
    GUICtrlDelete($hComb_Drive)
    GUICtrlDelete($hBut_AskFreeDB)
    GUICtrlSetData($hLab_Text, "Please wait until I try to get the CDDBQuery of " & $sLW & " and send the query to FreeDB. This may take a couple of seconds.")
    $hProg_Progress = GUICtrlCreateProgress(10, 10, 130, 14, 8);Stlye = $PBS_MARQUEE = 0x08 = 8
    GUICtrlSetColor(-1, 0)
    DllCall("UxTheme.dll", "int", "SetWindowTheme", "hwnd", GUICtrlGetHandle(-1), "wstr", "", "wstr", "")
    GUICtrlSetPos($hLab_Text, 10, 25, 130, 65)
    ExitLoop
    Case - 3 ;$GUI_EVENT_CLOSE = -3
    Exit
    EndSwitch
    WEnd

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

    Global $iProg = 0
    AdlibEnable("_SetProg", 100)

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

    $hTi = TimerInit()
    $sQuery = _CDDBCreateQuery($sLW)
    If @error Or (Not $sQuery) Then Exit MsgBox(16, "Error", "errorcode " & @error)
    ConsoleWrite($sQuery & @CRLF)

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

    $sDatabase = _FreeDBRecvDB($sQuery)
    If @error Or (Not $sDatabase) Then Exit MsgBox(16, "Error", "2errorcode " & @error & @CRLF & $sDatabase)

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

    If StringInStr($sDatabase, "211 Found inexact matches") Then
    GUICreate("More than just one found", 220, 185)
    $hListV = GUICtrlCreateListView("Founded matches", 10, 10, 200, 150)
    GUICtrlSendMsg(-1, 0x101E, 0, 180)
    $aSS = StringSplit($sDatabase, @CRLF, 1)
    For $i = 2 To $aSS[0] - 2
    GUICtrlCreateListViewItem($aSS[$i], $hListV)
    If $i = 2 Then GUICtrlSetState(-1,256);$GUI_FOCUS
    Next
    $hBut_OK = GUICtrlCreateButton("OK", 10, 165, 200, 15,1)
    GUISetState()
    While 1
    Switch GUIGetMsg()
    Case $hBut_OK
    $aRead = StringSplit(StringTrimRight(GUICtrlRead(GUICtrlRead($hListV)), 1), " ")
    GUIDelete()
    $aQuery = StringSplit($sQuery, " ")
    $sQuery = StringReplace($sQuery, $aQuery[3], $aRead[2])
    ConsoleWrite($sQuery & @CRLF)
    $sDatabase = _FreeDBRecvDB($sQuery)
    If @error Or (Not $sDatabase) Then Exit MsgBox(16, "Error", "2errorcode " & @error & @CRLF & $sDatabase)
    ExitLoop
    Case - 3 ;$GUI_EVENT_CLOSE = -3
    Exit
    EndSwitch
    WEnd
    EndIf
    $aCDInfos = _FreeDBRetCDInfos($sDatabase)
    $aCDTracks = _FreeDBRetCDTracks($sDatabase)
    $hTi = TimerDiff($hTi)
    AdlibDisable()
    GUIDelete()

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

    GUICreate("Informations of the CD tooks " & Round($hTi / 1000, 1) & " seconds", 420, 110)
    GUICtrlCreateLabel("CD Title:", 8, 10, 50)
    GUICtrlCreateInput($aCDInfos[1], 55, 8, 150, 18)
    GUICtrlCreateLabel("CD Artist:", 8, 30, 50)
    GUICtrlCreateInput($aCDInfos[0], 55, 28, 150, 18)
    GUICtrlCreateLabel("CD Genre:", 8, 50, 50)
    GUICtrlCreateInput($aCDInfos[2], 55, 48, 150, 18)
    GUICtrlCreateLabel("CD Year:", 8, 70, 50)
    GUICtrlCreateInput($aCDInfos[3], 55, 68, 150, 18)
    GUICtrlCreateLabel("CD Extd:", 8, 90, 50)
    GUICtrlCreateInput($aCDInfos[4], 55, 88, 150, 18)
    $hListV = GUICtrlCreateListView("Title|Length|Position", 210, 8, 200, 99)
    GUICtrlSendMsg(-1, 0x101E, 0, 90)
    GUICtrlSendMsg(-1, 0x101E, 1, 35)
    GUICtrlSendMsg(-1, 0x101E, 2, 35)
    For $i = 0 To UBound($aCDTracks) - 1
    GUICtrlCreateListViewItem($aCDTracks[$i][0] & "|" & $aCDTracks[$i][1] & "|" & $aCDTracks[$i][2], $hListV)
    Next

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

    GUISetState()

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

    While GUIGetMsg() <> -3
    WEnd

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

    Func _SetProg()
    $iProg += 1
    GUICtrlSetData($hProg_Progress, $iProg)
    EndFunc ;==>_SetProg

    [/autoit]

    Ich hoffe es kann jemand gebrauchen, würde mich um Rückmeldungen freuen :)

    Mfg Spider

  • Hallo GtaSpider,

    super Idee Dein Script.
    Ich hab es mal mit 2 CD's getestet.
    Leider ohne Erfolg:

    CD 1:
    2errorcode 7
    210 Found exact matches, list follows (until terminating `.')
    misc 34124815 Haindling / Die 90er Jahre
    rock 34124815 Haindling / 78 min. - Die 90er Jahre

    CD 2:
    Folgendes wird angezeigt:

    CD title: Songs an einem Sommerabend Die 3.
    CD Artist: Various
    CD genre: Liedermacher
    CD Year: 2002
    CD extd: NO EXTD

    Aber leider kein einziger Track- Titel.

    Mit EAC funktioniert das Holen einwandfrei.

    Servus
    Euer Cubaner

  • //Edit: Meien Vermutung war falsch, dass es an der Stringverarbeitung liegt. Der Fehler liegt im Empfang von $sDatabase, der nicht komplett war. FreeDB sendet das nicht am Stück, darauf muss Rücksicht genommen werden. 1 neue Funktion+ die letzten, gänderten Zeilen von _FreeDBRecvDB :

    Spoiler anzeigen
    [autoit]

    TCPSend($hSocket, "cddb read " & $aSS[2] & " " & $sCDChcksum & @CRLF)
    $sRecv = __TCPRecv2($hSocket)
    If Not StringInStr($sRecv, "210") Then Return SetError(8, 0, $sRecv)
    Return $sRecv
    EndFunc ;==>_FreeDBRecvDB

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

    Func __TCPRecv2($hSocket,$iEmptyTime=500,$iTimeOut=20000)
    Local $sRecv = ""
    Local $hTi = TimerInit()
    While 1
    $sRecvt = ""
    $timer2 = TimerInit()
    Do
    $sRecvt &= TCPRecv($hSocket,1024)
    If @error Then Return SetError(@error,0,0)
    Until $sRecvt <> "" Or TimerDiff($timer2) > $iEmptyTime
    If $sRecvt = "" Then ExitLoop
    $sRecv &= $sRecvt
    If TimerDiff($hTi) > $iTimeOut Then ExitLoop
    WEnd
    If TimerDiff($hTi) > $iTimeOut Then Return SetError(1, 0, "Timeout")
    Return $sRecv
    EndFunc

    [/autoit]

    Einmal editiert, zuletzt von progandy (24. Juli 2008 um 13:33)

  • Hi,

    ich habe mal die modifizierte Version (mit Code von progandy) getestet (inkl. Anpassung von "AdlibRegister" und "AdlibUnregister"). Scheint zunächst perfekt zu funktionieren. Allerdings - wenn es mehrere "found matches" gibt - kommt ein errorcode 7. Bezogen auf "_FreeDBRecvDB". Das dürfte daran liegen, dass in diesem Code-Teil in "_FreeDBRecvDB" (CDDB.au3)

    [autoit]


    TCPSend($hSocket, $sQuery & @CRLF)
    $sRecv = __TCPRecv($hSocket) ; genre CDID Artist / CDName, z.B. 200 rock b009520e Green Day / Dookie
    If StringInStr($sRecv, "211 Found inexact matches") And $fSecTry = False Then
    TCPCloseSocket($hSocket)
    TCPShutdown()
    Return _FreeDBRecvDB(StringReplace($sQuery, $sCDChcksum, StringLower(Hex(Number("0x" & $sCDChcksum) - 0x200, 8))), True)
    ElseIf StringInStr($sRecv, "211 Found inexact matches") And $fSecTry Then
    Return $sRecv
    EndIf
    If Not StringInStr($sRecv, "200") Then Return SetError(7, 0, $sRecv)
    $aSS = StringSplit($sRecv, " ")

    [/autoit]

    oder in dem folgenden modif. Code von progandy der Fall "210 Found exact matches" (also mehrere "matches") nicht behandelt ist. Allerdings steige ich hier noch nicht so ganz durch.

    Hat jemand eine Idee?

    Unten noch ein Bildschirmfoto einer solchen CD (Dire Straits - Love over Gold). Trifft wahrscheinlich auf die meisten weitverbreiteten CDs zu.

    Dank und Gruß
    Thomas

  • Wenn man mal testweise aus dem example.au3 die folgenden beiden Zeilen (Zeile 45 und 47) ändert (testweise auch den @error rausnimmt), also diese beiden Zeilen

    [autoit]


    If @error Or (Not $sDatabase) Then Exit MsgBox(16, "Errorcode", "_FreeDBRecvDB: " & @error & @CRLF & $sDatabase)
    If StringInStr($sDatabase, "211 Found inexact matches") Then

    [/autoit]

    durch diese ersetzt

    [autoit]


    If Not $sDatabase Then Exit MsgBox(16, "Errorcode", "_FreeDBRecvDB: " & @error & @CRLF & $sDatabase)
    If StringInStr($sDatabase, "211 Found inexact matches") Or StringInStr($sDatabase, "210 Found exact matches") Then

    [/autoit]

    dann wird immerhin "Found" richtig, d.h. mit mehreren Zeilen angezeigt. Allerdings bleibt dann das Fenster mit den Infos leer. Der @error wird also auf jeden Fall fehlerhaft generiert...

  • Ok. Lösung gefunden:

    example.au3 Änderung der Zeile 47

    [autoit]


    If StringInStr($sDatabase, "211 Found inexact matches") Then

    [/autoit]

    in:

    [autoit]


    If StringInStr($sDatabase, "211 Found inexact matches") Or StringInStr($sDatabase, "210 Found exact matches") Then

    [/autoit]

    CDDB.au3 Änderung der modifizierten Version, Zeile 90

    [autoit]


    If StringInStr($sRecv, "211 Found inexact matches") And $fSecTry = False Then

    [/autoit]

    in

    [autoit]


    If StringInStr($sRecv, "211 Found inexact matches") Or StringInStr($sRecv, "210 Found exact matches") And $fSecTry = False Then

    [/autoit]

    und Zeile 94

    [autoit]


    ElseIf StringInStr($sRecv, "211 Found inexact matches") And $fSecTry Then

    [/autoit]

    in:

    [autoit]


    ElseIf StringInStr($sRecv, "211 Found inexact matches") Or StringInStr($sRecv, "210 Found exact matches") And $fSecTry Then

    [/autoit]

    Gruß
    Thomas

  • Durch die Änderungen von TJF geht das ganze zumindestens Teilweise. Es werden nur eine bestimmte anzahl Zeichen zurück geliefert. Dies hat dann den Effekt, dass bei einer CD mit vielen Liedern nicht alle angezeigt werden. Eine Änderung von $iBuffersize in der Funktion __TCPRecv der UDF hat leider auch nichts gebracht.

    Hier mal ein Beispiel bei der es abgeschnitten ist weil einfach zu viele Lieder auf der CD sind.

    Spoiler anzeigen

    210 rock 8c10cc1c CD database entry follows (until terminating `.')
    # xmcd CD database file
    #
    # Track frame offsets:
    # 150
    # 3681
    # 20975
    # 23333
    # 44497
    # 46386
    # 73402
    # 75342
    # 95458
    # 96948
    # 115159
    # 117675
    # 139039
    # 142597
    # 159784
    # 163574
    # 181497
    # 183792
    # 205016
    # 207178
    # 225736
    # 228072
    # 250141
    # 253069
    # 268863
    # 272182
    # 295720
    # 298074
    #
    # Disc length: 4302 seconds
    #
    # Revision: 6
    # Processed by: cddbd v1.5.2PL0 Copyright (c) Steve Scherf et al.
    # Submitted via: CDex 1.40Release
    #
    DISCID=8c10cc1c
    DTITLE=E Nomine / Finsternis
    DYEAR=2002
    DGENRE=Euro-House
    TTITLE0=Am Anfang war die Finsternis ...!
    TTITLE1=Mitternacht (Synchronstimme Robert de Niro)
    TTITLE2=Die Wandlung Interlude
    TTITLE3=Wolfen Das Tier in mir (Synchronstimme Jack Nicholson)
    TTITLE4=Reise nach Transsylvanien Interlude
    TTITLE5=Dracul`s Bluthochzeit (Synchronstimme Gary Oldmann)
    TTITLE6=Die Offenbarung Interlude
    TTITLE7=Seance (Synchronstimme Bruce Willis)
    TTITLE8=Die Bedrohung In

    Wie man sieht steht als letztes "TTITLE8=Die Bedrohung In" und das war es dann.
    Hat jemand eine Idee wie man das Problem beheben könnte?

    Andy hat mir ein Schnitzel gebacken aber da war ein Raupi drauf und bevor Oscar das Bugfixen konnte kam Alina und gab mir ein AspirinJunkie.

  • Hi,

    doch noch nicht perfekt. Nach der x-ten CD kommt der Fall "200" - ohne Auflistung. Lösung folgt in Kürze, wenn ich (oder jemand anders Zeit hat... :) ).

    Das ist die Serverkommunikation im Fall 210:

    Code
    cddb query 270e2d04 4 150 23715 126335 174815 3631
    210 Found exact matches, list follows (until terminating `.')
    misc 270e2d04 Carl Orff / Carmina Burana
    classical 270e2d04 Orff - Robert Shaw, Atlanta Symphony Orch / Carmina Burana
    .
    cddb read misc 270e2d04

    Das passiert im Falle 200:

    Code
    cddb query a911560b 11 150 35920 64065 102007 129775 159565 188485 217245 244237 274870 299050 4440
    200 blues a911560b Reinhard Mey / Lebenszeichen Live (CD1)
    cddb read blues a911560b

    Viele Grüße
    Thomas

  • So sollte es passen. Die If-Anweisung durch diese ersetzen:

    Spoiler anzeigen
    [autoit]


    If StringInStr($sDatabase, "211 Found inexact matches") Or StringInStr($sDatabase, "210 Found exact matches") Then
    GUICreate("Found", 520, 485)
    $hListV = GUICtrlCreateListView("Founded matches", 10, 10, 500, 450)
    GUICtrlSendMsg(-1, 0x101E, 0, 180)
    $aSS = StringSplit($sDatabase, @CRLF, 1)
    For $i = 2 To $aSS[0] - 2
    GUICtrlCreateListViewItem($aSS[$i], $hListV)
    If $i = 2 Then GUICtrlSetState(-1,256);$GUI_FOCUS
    Next
    $hBut_OK = GUICtrlCreateButton("OK", 10, 463, 500, 20,1)
    GUISetState()
    While 1
    Switch GUIGetMsg()
    Case $hBut_OK
    $aRead = StringSplit(StringTrimRight(GUICtrlRead(GUICtrlRead($hListV)), 1), " ")
    GUIDelete()
    $read = "cddb read " & $aRead[1] & " " & $aRead[2]
    Local $hSocket
    TCPSend($hSocket, $read & @CRLF)
    $sDatabase = __TCPRecv2($hSocket)
    If @error Or (Not $sDatabase) Then Exit MsgBox(16, "Error", "2errorcode " & @error & @CRLF & $sDatabase)
    ExitLoop
    Case - 3 ;$GUI_EVENT_CLOSE = -3
    Exit
    EndSwitch
    WEnd
    ElseIf StringInStr($sDatabase, "200") Then
    $aSS = StringSplit($sDatabase, @CRLF, 1)
    $aRead = StringSplit($ass[1], " ")
    $read = "cddb read " & $aRead[2] & " " & $aRead[3]
    Local $hSocket
    TCPSend($hSocket, $read & @CRLF)
    $sDatabase = __TCPRecv2($hSocket)
    If @error Or (Not $sDatabase) Then Exit MsgBox(16, "Error", "2errorcode " & @error & @CRLF & $sDatabase)
    EndIf

    [/autoit]

    Viele Grüße
    Thomas

  • Also ich habe das Problem noch nicht gehabt mit dem "Fall "200" - ohne Auflistung".

    Andy hat mir ein Schnitzel gebacken aber da war ein Raupi drauf und bevor Oscar das Bugfixen konnte kam Alina und gab mir ein AspirinJunkie.

  • Ich auch nicht - bis Heute :) Das ist der Fall, wenn es nur eine einzige DiscID für einen einzigen Titel in FreeDB.org gibt. Übrigens habe ich jetzt gesehen, dass das auch EAC genauso "handelt". Wenn es mehrere Einträge gibt, erscheint zuerst eine Auflistung. Wenn der o.g. eindeutige Fall vorliegt, wird alles sofort in die Felder eingetragen. Meine heutige Ergänzung ist also unbedingt notwendig, sonst gibt es einen Laufzeitfehler...

    Viele Grüße
    Thomas

  • Hallo,

    vieleicht steh' ich grade auf dem Schlauch: Warum funktioniert die Sache nicht mehr, wenn das Programm in eine Funktion gesetzt wird? Also einfach:

    [autoit]


    _Test()

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

    Func _Test()
    ; bekannter Quelltext
    EndFunc

    [/autoit]

    Viele Grüße
    Thomas

  • Hi,

    bei einer sehr großen Anzahl an CDs einwandfrei funktionierend, bin ich Heute auf Fehler 202 gestoßen und habe dabei folgende Beobachtung gemacht (und die Fehlermeldung noch aufgenommen...):

    DJ Jondal "Klassik lounge summer" CD2 ( Telnet -> 202 No match for disc ID b9126f0d.)

    Es wird über die Funktion in CDDB.au3 die folgende discID errechnet: b9126f0d . Ich habe in der FreeDB-Datenbank mal händisch nachgeschaut und finde dort diese discID: b912700d

    Manuell in Telnet mit dieser discID abgefragt ergibt es als Ergebnis die richtige CD (cddb query b912700d 13 150 29533 58672 84017 105667 130041 153095 178378 191216 218686 247257 265406 296304 4721). Der Rest der Anfrage - außer der discID - war oben gleich.

    Nun hätte es ja sein können, dass jemand eine falsche discID in der Datenbank hinterlegt hat. Jedoch erkennt das aktuelle EAC die CD ebenfalls sofort...

    Kann es sein, dass die discID in der CDDB.au3 falsch berechnet wird? Hat jemand eine Idee woran das liegen kann? Weil es ja sonst gut funktioniert, vielleicht noch der Hinweis von FreeDB.org:

    Spoiler anzeigen

    Viele Grüße
    Thomas

  • Hallo,

    kann sein, dass es an Win7/8 oder am neueren Compiler liegt. Auf jeden Fall funktionierte das nicht mehr wie es sollte...

    Deshalb ein schnelles Update zur Korrektur einer Funktion in der "CDDB.au3":

    Spoiler anzeigen
    [autoit]


    Func __TCPRecv($hSocket, $iSleep = 100, $iTimeOut = 20000, $iBuffersize = 1024, $iForceBinary = 0) ; NEU Sleep auf 100 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    Local $sRecv, $sRet, $iErr = 0, $hTi
    $hTi = TimerInit()
    Sleep($iSleep) ; NEU !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    While TimerDiff($hTi) <= $iTimeOut
    $sRecv = TCPRecv($hSocket, $iBuffersize, $iForceBinary)
    Sleep($iSleep) ; NEU !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    $iErr = @error
    If $iErr Then ExitLoop
    While StringLen($sRecv)
    $sRet &= $sRecv
    Sleep($iSleep) ; NEU !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    $sRecv = TCPRecv($hSocket, $iBuffersize, $iForceBinary)
    Sleep($iSleep) ; NEU !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    $iErr = @error
    If (Not StringLen($sRecv)) Or $iErr Then ExitLoop 2
    If TimerDiff($hTi) > $iTimeOut Then ExitLoop
    WEnd
    Sleep($iSleep)
    WEnd
    If TimerDiff($hTi) > $iTimeOut Then Return SetError(1, 0, "Timeout")
    If $iErr Then Return SetError($iErr, 0, 0)
    Return $sRet
    EndFunc ;==>__TCPRecv

    [/autoit]

    Das kann man insgesamt auch anders machen, indem man auf die konkreten Strings wartet. So sollte es aber auch gehen...

    Gruß
    Thomas

    Einmal editiert, zuletzt von TJF (3. März 2014 um 09:59)

  • ...schöner ist in diesem Sinne die Version von progandy, die die o.g. Variante einfach ersetzt. Eine überflüssige Zeile (doppelt gemoppelter error...) raus und es funktioniert:

    Spoiler anzeigen
    [autoit]


    Func __TCPRecv($hSocket,$iEmptyTime=500,$iTimeOut=20000)
    Local $sRecv = ""
    Local $hTi = TimerInit()
    While 1
    $sRecvt = ""
    $timer2 = TimerInit()
    Do
    $sRecvt &= TCPRecv($hSocket,1024)
    ;If @error Then Return SetError(@error,0,0)
    Until $sRecvt <> "" Or TimerDiff($timer2) > $iEmptyTime
    If $sRecvt = "" Then ExitLoop
    $sRecv &= $sRecvt
    If TimerDiff($hTi) > $iTimeOut Then ExitLoop
    WEnd
    If TimerDiff($hTi) > $iTimeOut Then Return SetError(1, 0, "Timeout")
    Return $sRecv
    EndFunc

    [/autoit]