Seite 1 von 4

Titel von AudioCDs von FreeDB.org holen & DiscID berechnen

Verfasst: 17.12.2007 18:03
von alen
Hallo Zusammen,

ich programmiere an meinem ersten Purebasic Projekt das zusammenhängend auch einen Sinn ergibt. Bisher habe ich mehr Codeschnippsel als ganze Projekte realisiert.


Die Idee:

Ich habe viele Audio CDs und würde diese gerne in einer SQL Datenbank verwalten. Aber dabei habe ich keine Lust sämtliche Titel manuell abzutippen. Das soll schon automatischer ablaufen.

Ansatz war die Audio CD Daten durch die Berechnung einer DiscID aus einer freien CDDB Datenbank auszulesen und in einer MySQL Datenbank zu speichern. Als Dienst hatte ich mir FreeDB.org ausgesucht. Purebasic sollte für die GUI, Ablauf und die anderen String Parsing Aufgaben genutzt werden. Wenns möglich wäre, sollte auch eine Plattformübergreifende Speicherung in eine MySQL Datenbank erfolgen.




Der aktuelle Stand:


Im Moment existiert ein Programmgerüst bzw. Mini GUI die bereits die DiscID berechnet und mittels DiscID die FreeDB Datenbank abfragt. Die Ergebnisse der FreeDB.org werden derzeit nur angezeigt und nicht weiter verarbeitet. Jetzt wäre das String Parsing dran und evtl. bei Doppeleinträgen der Datenbank eine Auswahlmöglichkeit (1x DiscID ergibt mehr als einen Treffer) zu realisieren. Auch der Code zur Speicherung in der Datenbank wäre noch zu realisieren. Dabei müsste ich mir Gedanken machen wie ich eine Plattformübergreifende Speicherung hinbekomme.

Also wenn jetzt jemand Lust bekommen haben sollte mitzumachen wäre er sehr willkommen. Ich würde für das Projekt bei Sourceforge eine SVN Versionverwaltung einrichten und ggf. mir einen Namen dazu ausdenken.

Da das mein Einstiegsprojekt wäre würde ich den Quellcode allen die wollen bzw. der Community, frei zur Verfügung stellen. Und auch jeder der sich daran beteiligt sollte seine Programmteile auch so spenden.

Ich persönlich sehe dieses Projekt als Lernobjekt an um mit Purebasic Programmiererfahrungen zu sammeln und ggf. andere komplexere Projekte damit zu realisieren.



Bei Interesse bitte melden. :D

Grüße
Alen Hopek

Re: Interesse an Mitarbeit an Hobby Projekt ?

Verfasst: 17.12.2007 18:42
von Kiffi
@alen:

hört sich gut an. Als DB würde ich SQLite empfehlen. Dann könnte das
gesamte Projekt 'installationsfrei' auch beispielsweise von einem USB-Stick
gestartet werden.

MySQL ist zwar insgesamt mächtiger aber für Deine Zwecke etwas
oversized und meines Erachtens auch nicht stand-alone betreibbar.

Für ein CD-Verwaltungstool ist der Funktionsumfang von SQLite vollkommen
ausreichend.

Wenn Interesse besteht, könnte ich Dir / Euch beratend beiseite stehen.

Grüße ... Kiffi

Verfasst: 17.12.2007 19:35
von Criss
Mich würde noch interessieren wie Du auf die FreeDB.org per Purebasic zugreifst? Währe Dir zutiefst dankbar für ein bisschen Codeschnipsel!

FreeDB.org: Wie ich es bisher gemacht habe.

Verfasst: 17.12.2007 21:48
von alen
Criss hat geschrieben:Mich würde noch interessieren wie Du auf die FreeDB.org per Purebasic zugreifst? Währe Dir zutiefst dankbar für ein bisschen Codeschnipsel!
@Criss:
Hallo Criss,

eigentlich ist es sehr einfach an die FreeDB Daten zu kommen. Ich habe mich dabei an der Entwickler Dokumentation orientiert.



Quellenangaben:

Die kannst Du hier finden:
http://www.freedb.org/en/download__misc ... us.11.html

In der Datei:
http://ftp.freedb.org/pub/freedb/misc/f ... coldoc.zip
findest Du die Protokollaufrufe gelistet und mehr schlecht als recht, wie man sie benutzt.


Hintergrundinfos:

Im großen und ganzen wird eine URL mit allerhand Parametern zusammengebaut. Diese URL kannst Du dann auch im Browser deiner Wahl eintippen und und erhällst dann Antwortdaten zurück. Diese Antworten greife ich mit Purebasic auf und zerlege dann in ihre Bestandteile. Die Einzelteile werden dann zu Strings, die ich für die Befüllung der Felder einer Datenbank speichere.

Beispiel:

Code: Alles auswählen

http://freedb.freedb.org/~cddb/cddb.cgi?cmd=cddb+lscat+&hello=test+localhost+Purebasic+4.10&proto=5
Diese URL liefert im Browser eingegeben liefert eine Liste mit Kategorien die in der FreeDB.org Datenbank als Genres gespeichert sind.

Ähnlich geht das auch mit den eigentlichen Daten zur jeweils eingelesenen CD. Man muss auch in diesem Fall eine URL zusammenbauen worin dann Angaben wie: Befehl für die Datenbank ("read"), E-Mail Adresse des Anfragenden, Clientversion, DiscID und das Protokoll als Parameter an ein CGI Script übergibt. Stimmen diese Angaben, liefert das Script die Ergebnisdaten an den Browser bzw. Purebasic aus. Diese Daten sind wieder zu zerlegen so das man Felder für die Datenbank herausholt.

Ein weiterer Punkt ist die Erzeugung der mehr oder weniger eindeutigen DiscID. Aus den Startzeiten der jeweiligen Stücke auf der Audio CD wird eine Quersumme gebildet und zusammen mit der kompletten Länge der CD (in Sek.) und der Anzahl der Tracks auf der CD ein Hexadezimaler String erstellt. Das ist die sog. RawDiscID. Diese wird in der Generierung der Abfrage URL gebraucht.

Am Beispiel: 9f0e010c:

Code: Alles auswählen

http://freedb.freedb.org/~cddb/cddb.cgi?cmd=cddb+read+rock+9f0e010c&hello=test+localhost+Purebasic+4.10&proto=5
Da eine AudioCD bei FreeDB.org auch in mehreren Kategorien als Datensatz abgelegt sein kann oder auch die DiscID mehrfach vorkommen kann, steckt hier ein wenig mehr Geschick beim Parsing mit Purebasic auf dem Programm. Hat man diese Fälle abgedeckt, steht der Speicherung in der Datenbank nichts mehr im Weg.

Hat man sich dann diese Abfrage URL zusammengebaut und sie funktionert, dann übergebe ich sie an folgende Funktion. Die Funktion liefert bei jetzigem Stand nur die reinen Textdaten zurück. Ähnlich wie in dem Beispiel mit der DiscID "9f0e010c".

Als Eingabe Parameter gebe ich den String für den Servernamen ("freedb.freedb.org") und die Abfrage URL wie oben beschrieben mit:

Code: Alles auswählen

Global Server.s = "freedb.freedb.org"
Global Referer.s   = "http://www.purebasic.com"
Global UserAgent.s = "Purebasic/4.10 (Windows; U; Windows NT 5.1; de; rv:4.1.0)"

Procedure.s FreeDBRequest(Server.s, HttpGetCommand.s)
  If Server = "" Or HttpGetCommand = "" 
    ProcedureReturn ""
  EndIf
  
  NetStack = InitNetwork()
  If NetStack = 0
    MessageRequester("Error", "No Network valid Stack found", 0): End
  EndIf
  
  HttpHeader.s = ""
  HttpHeader + "GET " + HttpGetCommand +" HTTP/1.0" + #CRLF
  HttpHeader + "Referer: " + Referer  + #CRLF
  HttpHeader + "User-Agent: " + UserAgent + #CRLF
  HttpHeader + #CRLF+#CRLF
  
  MessageRequester("HEADER",HttpHeader) 
  
  ConnectionID = OpenNetworkConnection( Server, #NetPort , #PB_Network_TCP )
  SendNetworkString(ConnectionID, HttpHeader)
  
  *Buffer = AllocateMemory(10000)
  
  Repeat
    ReceiveNetworkData(ConnectionID, *Buffer, MemorySize(*Buffer))
  Until NetworkClientEvent(ConnectionID) = 0
  
  ResultData.s = PeekS(*Buffer)
  FreeMemory(*Buffer)
  
  CloseNetworkConnection(ConnectionID)
  
  ProcedureReturn ResultData
EndProcedure
Wie man sieht baue ich auch gleich einen HTTP-Header zusammen der die Abfrage URL an die FreeDB.org übergibt. Als Ergebnis erhalte ich in Purebasic so wie am Beispiel der DiscID auch wieder die reinen Textdaten zurück. Und genau hier könnte ich Unterstützung gut gebrauchen. Das Zerlegen bereitet mir mehr Probleme als ich dachte. In Python und PHP würde ich das sicher schneller hinbekommen aber Purebasic ist Neuland.

Hoffe Du hast jetzt ein wenig Durchblick wie man an die Daten von FreeDB.org mit Purebasic kommt. Falls nicht, kann ich auch ein wenig mehr als nur Codeschnipsel und kleine Infos rausrücken.

Grüße
Alen

Re: Interesse an Mitarbeit an Hobby Projekt ?

Verfasst: 17.12.2007 22:00
von alen
Kiffi hat geschrieben:MySQL ist zwar insgesamt mächtiger aber für Deine Zwecke etwas
oversized und meines Erachtens auch nicht stand-alone betreibbar.

Wenn Interesse besteht, könnte ich Dir / Euch beratend beiseite stehen.
@Kiffi:
Hallo Kiffi,

das mit der MySQL Datenbank als Standalone Version ohne Installation als USB Stick Anwendung wäre kein Problem. Da habe ich schon was fertiges. Nur Verzeichnis kopieren, Batch Datei starten und los gehts. Vielleicht könnte man da sogar eine Purebasic Control Panel schreiben der MySQL als Dienst startet und stoppt so das nicht das Fenter der Batch Datei offen bleiben muss.

Könnte man denn Purebasic beibringen SQLite auf allen Plattformen benutzen zu können ? Gibt es da eine Plattform übergreifende Library oder sowas ?

Grüße
Alen

Verfasst: 17.12.2007 22:32
von HeX0R
Ich hoffe das da oben ist wirklich nur ein Schnippsel und nicht deine tatsächliche Datenübertragung.
Weil das so wie es da steht ziemlich unbrauchbar ist.

Verfasst: 17.12.2007 22:53
von alen
HeX0R hat geschrieben:Ich hoffe das da oben ist wirklich nur ein Schnippsel und nicht deine tatsächliche Datenübertragung.
Weil das so wie es da steht ziemlich unbrauchbar ist.
@HeX0R:
Hallo HeX0R,

Was genau ist daran unbrauchbar ? Das sollte nur das Prinzip beschreiben.

Ein Bisserl mehr Details wären ratsam bei so hilfreichen Aussagen wie "unbrauchbar". :)

Ausserdem hatte ich erwähnt das dies erstmal ein Ansatz ist und noch lange nicht fertig. Eine Idee mit Minimalumsetzung ! Das ist nicht dazu gedacht es in Deine Purebasic IDE zu ziehen und dann zu starten, und alles geht.

Grüße
Alen

Re: Interesse an Mitarbeit an Hobby Projekt ?

Verfasst: 17.12.2007 23:20
von Kiffi
alen hat geschrieben:das mit der MySQL Datenbank als Standalone Version ohne Installation als USB Stick Anwendung wäre kein Problem.
OK, danke für die Info. Wusste ich nicht.
alen hat geschrieben:Batch Datei starten und los gehts
Allerdings würde mich persönlich stören, dass dieser wie auch immer
geartete Hintergrundprozess laufen müsste, wenn ich mit Deinem
Programm arbeiten wollte.

Wie bereits geschrieben: SQLite erscheint mir am geeignetsten für die
Datenhaltung einer CD-Verwaltung. Schnell, klein und einfach zu bedienen.
alen hat geschrieben:Könnte man denn Purebasic beibringen SQLite auf allen Plattformen benutzen zu können ? Gibt es da eine Plattform übergreifende Library oder sowas ?
Yepp, SQLite gibt es (unter anderem) für die drei von PB unterstützen
Plattformen Win, Lin und Mac.

Grüße ... Kiffi

Verfasst: 17.12.2007 23:39
von HeX0R
alen hat geschrieben:
@HeX0R:
Hallo HeX0R,

Was genau ist daran unbrauchbar ? Das sollte nur das Prinzip beschreiben.

Ein Bisserl mehr Details wären ratsam bei so hilfreichen Aussagen wie "unbrauchbar". :)
Ja, ich weiss, ich bin als a weng maulfaul...

Unbrauchbar weil:
1.) Du nicht überprüfst, ob die Verbindung überhaupt zustande gekommen ist.
2.) Du den Rückgabewert von ReceiveNetworkData vernachlässigst.
3.) Deine Receive-Schleife allgemein unbrauchbar ist, bei starkem Netztraffic kann das Zeugs auch mal zerstückelt ankommen.
4.) Du ERST auf NetworkClientEvent() = #PB_NetworkEvent_Data überprüfen musst und NUR DANN ein ReceiveNetworkData aufrufen solltest.
5.) Du keine Ahung hast, wann das empfangene Datenpaket zu Ende ist.
6.)* [eigene Empfehlung] OpenNetworkConnection()-Aufrufe eigentlich immer in einen Thread gepackt werden sollten. Gerade, wenn der angesprochene Server sich mal eben ne Stulle schmiert oder von Scriptkiddies ins Nirvana gebombt wird und nicht erreichbar ist, kann das ziemlich störend für deine Applikation sein.

Ich hab mir mal die Freiheit genommen einen Code zusammenzubasteln, leider nix kommentiert, meine Semikolon-Taste wurde mir irgendwie geklaut 8)

Code: Alles auswählen

Structure CON_THREAD
	CID.l
	*IP
	Port.l
EndStructure

If InitNetwork() = 0
	MessageRequester("Error", "No Network valid Stack found", 0)
	End
EndIf

Procedure OpenNetworkConnectionThread(*COM.CON_THREAD)
	Protected ConnectionID.l

	ConnectionID = OpenNetworkConnection(PeekS(*COM\IP), *COM\Port)
	If ConnectionID = 0
		*COM\CID = -1
	Else
		*COM\CID = ConnectionID
	EndIf

EndProcedure

Procedure Main()
	Protected ConVar.CON_THREAD, Connected.l, HttpHeader.s, *Buffer, Received.s, Recv.l
	Protected Referer.s, UserAgent.s

	OpenWindow(0, 0, 0, 450, 340, "Test", #PB_Window_SystemMenu)
	CreateGadgetList(WindowID(0))
	StringGadget(0, 5, 5, 350, 20, "/~cddb/cddb.cgi?cmd=cddb+lscat+&hello=test+localhost+Purebasic+4.10&proto=5")
	ButtonGadget(1, 360, 5, 80, 20, "Send")
	EditorGadget(2, 5, 35, 435, 300, #PB_Editor_ReadOnly)

	HttpHeader = "GET {HTTPGETCOMMAND} HTTP/1.0" + #CRLF$
	HttpHeader + "Referer: " + Referer           + #CRLF$
	HttpHeader + "User-Agent: " + UserAgent      + #CRLF$
	HttpHeader + #CRLF$ + #CRLF$

	ConVar\IP   = @"freedb.freedb.org"
	ConVar\Port = 80
	*Buffer     = AllocateMemory(8192)

	Repeat
		Select WaitWindowEvent(10)
			Case #PB_Event_CloseWindow
				Break
			Case #PB_Event_Gadget
				Select EventGadget()
					Case 0
						If EventType() = #PB_EventType_Change
							If GetGadgetText(0)
								DisableGadget(1, 0)
							Else
								DisableGadget(1, 1)
							EndIf
						EndIf
					Case 1
						ConVar\CID = 0
						Connected  = 0
						CreateThread(@OpenNetworkConnectionThread(), @ConVar)
						ClearGadgetItemList(2)
						DisableGadget(0, 1)
						DisableGadget(1, 1)
				EndSelect
		EndSelect
		If Connected = 0 And ConVar\CID <> 0
			Connected = 1
			If ConVar\CID <> -1
				SendNetworkString(ConVar\CID, ReplaceString(HttpHeader, "{HTTPGETCOMMAND}", GetGadgetText(0)))
			Else
				AddGadgetItem(2, -1, "Unable to reach Host")
				DisableGadget(0, 0)
				DisableGadget(1, 0)
			EndIf
		EndIf
		If ConVar\CID < -1 Or ConVar\CID > 0
			Select NetworkClientEvent(ConVar\CID)
				Case #PB_NetworkEvent_Data
					Recv = ReceiveNetworkData(ConVar\CID, *Buffer, 8192)
					If Recv > 0
						Received + PeekS(*Buffer, Recv)
						If Right(Received, 3) = "." + #CR$ + #LF$
							AddGadgetItem(2, -1, Received)
							Received = ""
							DisableGadget(0, 0)
							DisableGadget(1, 0)
							CloseNetworkConnection(ConVar\CID)
							ConVar\CID = 0
						EndIf
					EndIf
			EndSelect
		EndIf

	ForEver

	If ConVar\CID < -1 Or ConVar\CID > 0
		CloseNetworkConnection(ConVar\CID)
	EndIf
	FreeMemory(*Buffer)

EndProcedure

Main()

Verfasst: 18.12.2007 00:18
von alen
HeX0R hat geschrieben:Ja, ich weiss, ich bin als a weng maulfaul...
@HeX0R:

Hallo HeX0R,

genau das hatte ich mir schon gedacht. :wink:

Danke für den etwas ausführlicheren Vorschlag. Da ich nicht gerade der Purebasic Profi bin und gerade damit anfange das eine oder andere zu blicken, bin ich immer interessiert an Vorschlägen und Kritk, also immer her damit.

Aber im Ernst, in meinen Experimemten hat es auch bisher in der "Billigversion" halbwegs funktioniert. Auch wenns etwas einfach Aussieht. :)

Grüße
Alen