1
/** Queries last.fm for information and similar tracks. yay. third try.
2
* @author Scott Ringwelski
6
public class LastFM.Core : Object {
7
BeatBox.LibraryManager _lm;
8
public static const string api = "a40ea1720028bd40c66b17d7146b3f3b";
9
public static const string secret = "92ba5023f6868e680a3352c71e21243d";
11
public string session_key;
13
Gee.ArrayList<BeatBox.Song> similar;
14
BeatBox.Song similarToAdd;
16
public Core(BeatBox.LibraryManager lm) {
20
/** vala sucks here **/
21
public static string fix_for_url(string fix) {
22
var fix1 = fix.replace(" ", "%20");
23
var fix2 = fix1.replace("!", "%21");
24
var fix3 = fix2.replace("\"","%22");
25
var fix4 = fix3.replace("#", "%23");
26
var fix5 = fix4.replace("$", "%24");
27
var fix6 = fix5.replace("&", "%26");
28
var fix7 = fix6.replace("'", "%27");
29
var fix8 = fix7.replace("(", "%28");
30
var fix9 = fix8.replace(")", "%29");
31
var fix0 = fix9.replace("*", "%2A");
35
public string generate_md5(string text) {
36
return GLib.Checksum.compute_for_string(ChecksumType.MD5, text, text.length);
39
public string generate_signature(string token, string method) {
40
return generate_md5("api_key" + api + "method" + method + "token" + token + secret);
43
public string? getToken() {
44
var url = "http://ws.audioscrobbler.com/2.0/?method=auth.gettoken&api_key=" + api;
46
Xml.Doc* doc = Parser.parse_file (url);
47
if(doc == null) return null;
49
Xml.Node* root = doc->get_root_element();
50
if(root == null) return null;
52
for (Xml.Node* iter = root->children; iter != null; iter = iter->next) {
53
if(iter->name == "token") {
54
return iter->get_content();
61
public string? getSessionKey(string token) {
62
var url = "http://ws.audioscrobbler.com/2.0/?method=auth.getSession&api_key=" + api + "&api_sig=" + generate_signature(token, "auth.getSession") + "&token=" + token;
64
Xml.Doc* doc = Parser.parse_file (url);
65
if(doc == null) return null;
67
Xml.Node* root = doc->get_root_element();
68
if(root == null) return null;
70
for (Xml.Node* iter = root->children; iter != null; iter = iter->next) {
71
if(iter->name == "session") {
72
for(Xml.Node* n = iter->children; n != null; n = n->next) {
74
return n->get_content();
82
public bool loveTrack(string title, string artist) {
87
public bool banTrack(string title, string artist) {
92
/** Gets similar songs
93
* @param artist The artist of song to get similar to
94
* @param title The title of song to get similar to
95
* @return The songs that are similar
97
public Gee.ArrayList<BeatBox.Song> getSimilarTracks(string title, string artist) {
98
var artist_fixed = fix_for_url(artist);
99
var title_fixed = fix_for_url(title);
100
var url = "http://ws.audioscrobbler.com/2.0/?method=track.getsimilar&artist=" + artist_fixed + "&track=" + title_fixed + "&api_key=" + api;
101
Xml.Doc* doc = Parser.parse_file (url);
104
stdout.printf("Could not load similar artist information for %s by %s", title, artist);
105
else if(doc->get_root_element() == null)
106
stdout.printf("Oddly, similar artist information was invalid");
108
//stdout.printf("Getting similar tracks with %s... \n", url);
109
similar = new Gee.ArrayList<BeatBox.Song>();
111
parse_similar_nodes(doc->get_root_element(), "");
116
return new Gee.ArrayList<BeatBox.Song>();
119
public void parse_similar_nodes(Xml.Node* node, string parent) {
120
for (Xml.Node* iter = node->children; iter != null; iter = iter->next) {
122
if (iter->type != ElementType.ELEMENT_NODE) {
126
string node_name = iter->name;
127
string node_content = iter->get_content ();
129
if(parent == "similartrackstrack") {
130
if(node_name == "name") {
131
if(similarToAdd != null) {
132
similar.add(similarToAdd);
135
similarToAdd = new BeatBox.Song("");
136
similarToAdd.title = node_content;
139
else if(parent == "similartrackstrackartist") {
140
if(node_name == "name") {
141
similarToAdd.artist = node_content;
145
parse_similar_nodes(iter, parent+node_name);