Last.FM Recorder mit Audioscrobbler
Warum sollte man Last.FM oder besser Audioscrobbler in eine Anwendung integrieren? Gut Frage! Dafür gibt es mit Sicherheit einige Gründe, meine liegen aber ganz einfach darin begründet, dass ich dem Benutzer einen Radiostream in einer Anwendung bieten will. Ich werde deswegen Audioscrobbler auch vornehmlich zur Generierung von Playlisten einsetzten, die auf dem Musikgeschmack des Benutzers beruhen. Natürlich soll der Benutzer auch die Möglichkeit erhalten, die Titel die er hört zu bewerten. Dadurch werden dann auch die angesprochenen Playlisten immer besser an seinen Musikgeschmack angepasst.
Also, für die erste Implementierung verwende ich die ascrblr Java Bibliothek. Kleine Beispiele [0] haben gezeigt, dass man mit wenig Code viel machen, ein wichtiger Punkt für die Entscheidung. Der wichtigste war aber die gut Unterstützung von Audioscrobbler. scrobblerJ implementiert nur einige Funktionen und ist für mich daher durch. Ausserdem ist ascrblr etwas besser Dokumentiert wie ich finde. Aus der Projektseite finden sich direkt Beispiele zum loslegen.
Aufgabe für diesen ersten Test wird das Anmelden eines Benutzers, Abrufen einer Playlist und wiedergaben eines Titels. Da die Unterstützung von Audio und Video in Java meiner Meinung nach unter aller Sau ist, werden die Audiodaten in eine Datei geschrieben. Diese kann man anschließend mit einem beliebigen Player abspielen, der das MP3 Format unterstützt. Nehmen wir das als Feature, haben wir anschließend einen minimalen Last.FM Recorder.
Zuerst muss natürlich die ascrblr (schrecklicher Name) Bibliothek heruntergeladen werden. Ich entscheide mich für den checkout aus dem SVN-Repository direkt in Eclipse.
Dazu einfach: Import.. -> “Checkout Project from SVN” -> “Create a new repository location” ->
URL: http://ascrblr.googlecode.com/svn/trunk/ascrblr-api
Dort den Ordner src auswählen, finish betätigen und als Java-Project importieren (Eclipse fragt welcher Projekttyp).
Nun muss man wahrscheinlich noch den Sourceordner korrekt setzen, der sich nicht in $project_home/src befindet, sonder unter $project_home/main/java. Dies kann man bei den Buildpath Einstellungen des Projektes machen. Einfach den Ordner /main/java neu hinzufügen und /src entfernen.
Damit wäre der erste Punkt erledigt! Weiter geht es mit der eigentlichen Arbeit. Dazu wird ein neues Java-Projekt angelegt. Da es sich hierbei lediglich um einen kleinen Test handelt, werde ich einfach eine Klasse anlegen und in der Main alles erledigen, soweit das geht. Auch um Exceptionhandling wird sich hier nicht gekümmert. Natürlich sollte man das im Gebrauch etwas schöner machen! Das neue Projekt muss nun mit dem zuvor ausgecheckten verbunden werden. Dies wird wieder in den Properties unter Build Path erledigt.
Beim Implementieren fiel mir eine Schwachstele der ascrblr Bibliothek auf. Zum Lesen eines Titels brauch man neben dem InputStream, den die Klasse RadioService liefert, auch die Länge dieser. Das hängt damit zusammen, das der Stream am Ende nicht unterbrochen wird und Daten nur sehr unterschiedlich hereinkommen. Man müßte also mit einem Timeout oder etwas in der Art arbeiten, da man nicht weiß wann die Datei zu Ende ist. Darum habe ich zum einen LastFMInputStream implementiert, der neben dem Mp3-Stream auch über die Länge des Content bescheid weiß. Damit sich das irgendwie in die Bibliothek integriert habe ich von RadioService abgeleitet und einen Methode getMyMp3Stream hinzugefügt. Diese verwendet die Mittel der Oberklasse um den LastFmInputStream zu erzeugen und gibt ihn dann zurück. Die Quellen befinden sich im angehängten Archiv [2]
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.List;
import com.googlecode.ascrblr.api.radio.StationUrl;
import com.googlecode.ascrblr.api.radio.xspf.Track;
import com.googlecode.ascrblr.api.radio.xspf.XSPF;
import com.googlecode.ascrblr.api.util.ServiceException;
public class Main {
/**
* @param args
* @throws ServiceException
* @throws IOException
*/
public static void main(String[] args) throws IOException, ServiceException {
// Anmelden am System
MyRadioService radioService = new MyRadioService();
radioService.setCredentials("username", "pasword");
// Eine Station auswählen. Genaue Anleitung wie man den String baut
// gibts unter [1]
radioService.tuneInStation(new StationUrl("lastfm://artist/magda"));
// Playlist holen, ersten Titel auspacken und abspielen.
XSPF playlist = radioService.getXSPF();
List
tracks = playlist.getTracklist();
Track track1 = tracks.get(0);
/*
* Hier wird ein MP3 Strom geholt von dem wir lesen. Jeder Track kann
* mehrere Locations mitbringen, aber wir verwenden der Einfachheit
* halber nur die Erste.
*/
LastFMInputStream mp3In = radioService.getMyMp3Stream(track1
.getLocations().get(0).toString());
// Datei zum Schreiben anlegen.
File outFile = new File(String.format("/tmp/%s-%s-%s.mp3", track1
.getCreator(), track1.getAlbum(), track1.getTitle()));
outFile.createNewFile();
OutputStream mp3Out = new BufferedOutputStream(new FileOutputStream(
outFile));
// Puffer anlegen, in den die Audiodaten geschreiben werden.
byte[] buffer = new byte[512];
try {
/*
* Von eingehenden Strom lesen, bis der Puffer voll ist. Der
* zurückgegebene int gibt an wie viele Bytes gelesen wurden, was
* wichig wird beim schreiben.
*/
int bytesRead;
int overallBytesRead = 0;
while (overallBytesRead < mp3In.getContentLength()) {
if (mp3In.available() > 0) {
bytesRead = mp3In.read(buffer);
overallBytesRead += bytesRead;
System.out
.println(String
.format(
"Es wurden %d bytes gelesen und %d insgesamt von %d",
bytesRead, overallBytesRead, mp3In
.getContentLength()));
/*
* Hier schrieben wir aus dem Puffer in die Datei. Dabei
* wird auf die Anzahl der gelesenen Bytes beschränkt. Das
* ist wichtig, damit am Ende des Liedes, wenn keine
* vollständigen 1024 Bytes mehr gelesen werden können,
* nicht noch Fragmente aus dem Puffer der vorherigen
* Iteration gelesen werden. Das würde zu seltsamen
* Geräuschen führen.
*/
mp3Out.write(buffer, 0, bytesRead);
}
}
} finally {
mp3Out.close();
mp3In.close();
}
}
}
Ich hoffe die Dokumentation innerhalb des Codes genügt um alles zu verstehen. Wer lust hat kann mit ganz kleinen Änderungen Playlist für Playlist aufzeichnen. Natürlich muss das nach der Wiedergabe sofort gelöscht werden. Viel Spaß damit.
Noch eine kleine Anmerkung: Ich verwende einen Mac bzw. auch Linux. Soll das Beispiel unter Windows laufen, müssen die Pfade noch angepasst werden.
[0] ascrblr http://code.google.com/p/ascrblr/wiki/Usage
[1] http://code.google.com/p/thelastripper/wiki/LastFM12UnofficialDocumentation
[2] Sourcecode zum Weitermachen
[...] Last.FM Recorder – Audioscrobbler Beispiel mit ascrblr Veröffentlicht Juni 14, 2008 Uncategorized Tags: ascrblr, Audioscrobbler, java, Last.FM Diesen Artikel findest du auf: http://blog.thenextradio.info/2008/06/lastfm-recorder-mit-audioscrobbler/ [...]