Volume breaks output format, removed for now.
[shell-fm.git] / source / feeds.c
blob55b96d773d5f65812ed733e65a2e49a4e7725f54
1 /*
2 Copyright (C) 2006 by Jonas Kramer
3 Published under the terms of the GNU General Public License (GPL).
4 */
6 #define _GNU_SOURCE
8 #include <assert.h>
9 #include <string.h>
10 #include <stdlib.h>
12 #include "http.h"
13 #include "feeds.h"
14 #include "tag.h"
15 #include "util.h"
16 #include "strary.h"
18 char ** neighbors(const char * user) {
19 char * encoded = NULL, feed[128], ** names = NULL;
20 unsigned i;
22 assert(user != NULL);
24 encode(user, & encoded);
26 memset(feed, (char) 0, sizeof(feed));
27 snprintf(
28 feed, sizeof(feed),
29 "http://ws.audioscrobbler.com/1.0/user/%s/neighbours.txt",
30 encoded
33 free(encoded);
35 names = cache(feed, "neighbors", 0);
37 if(names != NULL)
38 for(i = 0; names[i] != NULL; ++i) {
39 char * ptr = strchr(names[i], ',');
40 if(ptr != NULL) {
41 unsigned length = strlen(ptr + 1);
42 memmove(names[i], ptr + 1, length);
43 names[i][length] = 0;
44 names[i] = realloc(names[i], sizeof(char) * (length + 1));
45 assert(names[i] != NULL);
49 return names;
53 char ** topartists(const char * user) {
54 char * encoded = NULL, feed[128], ** names = NULL;
55 unsigned i;
57 assert(user != NULL);
59 encode(user, & encoded);
61 memset(feed, (char) 0, sizeof(feed));
62 snprintf(
63 feed, sizeof(feed),
64 "http://ws.audioscrobbler.com/1.0/user/%s/topartists.txt",
65 encoded
68 free(encoded);
70 names = cache(feed, "top-artists", 0);
72 if(names != NULL)
73 for(i = 0; names[i] != NULL; ++i) {
74 char * ptr = strchr(names[i], ',');
75 if(ptr != NULL) {
76 ptr = strchr(ptr + 1, ',');
77 if(ptr != NULL) {
78 unsigned length = strlen(ptr + 1);
79 memmove(names[i], ptr + 1, length);
80 names[i][length] = 0;
81 names[i] = realloc(names[i], sizeof(char) * (length + 1));
82 assert(names[i] != NULL);
87 return names;
90 char ** friends(const char * user) {
91 char * encoded = NULL, feed[128];
93 assert(user != NULL);
94 encode(user, & encoded);
96 memset(feed, (char) 0, sizeof(feed));
97 snprintf(
98 feed, sizeof(feed),
99 "http://ws.audioscrobbler.com/1.0/user/%s/friends.txt",
100 encoded
103 free(encoded);
105 return cache(feed, "friends", 0);
109 char ** toptags(char key, struct hash track) {
110 unsigned length, x, count, idx;
111 char ** tags = NULL, url[256], * type = NULL, * artist = NULL,
112 ** resp, cachename[512];
114 memset(cachename, (char) 0, sizeof(cache));
116 /* Get artist, album or track tags? */
117 type = strchr("al", key) ? "artist" : "track";
119 /* Prepare artist name for use in URL. */
120 encode(value(& track, "creator"), & artist);
121 stripslashes(artist);
123 /* Prepare URL for album / artist tags. */
124 memset(url, 0, sizeof(url));
125 length = snprintf(
126 url, sizeof(url),
127 "http://ws.audioscrobbler.com/1.0/%s/%s/",
128 type, artist
131 free(artist);
133 /* Append title if we want track tags. */
134 if(key == 't') {
135 char * title = NULL;
136 encode(value(& track, "title"), & title);
137 snprintf(cachename, sizeof(cachename), "tags-t-%s--%s", artist, title);
138 stripslashes(title);
139 length += snprintf(url + length, sizeof(url) - length, "%s/", title);
140 free(title);
141 } else {
142 snprintf(cachename, sizeof(cachename), "tags-a-%s", artist);
145 strncpy(url + length, "toptags.xml", sizeof(url) - length - 1);
147 /* Fetch XML document. */
148 if((resp = cache(url, cachename, 0)) == NULL)
149 return NULL;
151 /* Count tags in XML. */
152 for(count = x = 0; resp[x]; ++x)
153 if(strstr(resp[x], "<name>") != NULL)
154 ++count;
156 tags = calloc(count + 1, sizeof(char *));
158 assert(tags != NULL);
160 tags[count] = NULL;
162 /* Search tag names in XML document and copy them into our list. */
163 for(x = 0, idx = 0; resp[x] && idx < count; ++x) {
164 char * pbeg = strstr(resp[x], "<name>");
165 if(pbeg) {
166 char * pend = strstr(pbeg += 6, "</name>");
168 if(pend) {
169 tags[idx++] = strndup(pbeg, pend - pbeg);
170 assert(tags[idx - 1] != NULL);
174 free(resp[x]);
177 free(resp);
179 return tags;
183 char ** overalltags(void) {
184 unsigned x, count = 0, idx;
185 const char * url = "http://ws.audioscrobbler.com/1.0/tag/toptags.xml";
186 char ** tags = NULL, ** resp;
188 if((resp = cache(url, "overall-tags", 0)) == NULL)
189 return NULL;
191 for(x = 0; resp[x]; ++x)
192 if(strstr(resp[x], "<tag name=\"") != NULL)
193 ++count;
195 tags = calloc(count + 1, sizeof(char *));
197 assert(tags != NULL);
199 tags[count] = NULL;
201 for(x = 0, idx = 0; resp[x]; ++x) {
202 char * pbeg = strstr(resp[x], "<tag name=\""), * pend;
203 if(pbeg) {
204 pend = strstr(pbeg += 11, "\"");
206 if(pend) {
207 tags[idx++] = strndup(pbeg, pend - pbeg);
208 assert(tags[idx - 1] != NULL);
214 purge(resp);
216 return tags;
220 char ** usertags(const char * user) {
221 char ** tags = NULL, ** resp, * encoded = NULL, url[256], cachename[64];
222 const char * fmt = "http://ws.audioscrobbler.com/1.0/user/%s/tags.txt";
223 unsigned n = 0;
225 memset(url, (char) 0, sizeof(url));
226 memset(cachename, (char) 0, sizeof(cachename));
228 encode(user, & encoded);
230 snprintf(url, sizeof(url), fmt, encoded);
231 snprintf(cachename, sizeof(cachename), "usertags-%s", encoded);
233 free(encoded);
234 encoded = NULL;
236 if((resp = cache(url, cachename, 0)) != NULL) {
237 unsigned ntag = 0;
238 while(resp[n] != NULL) {
239 char * begin = strchr(resp[n], ',');
240 if(begin) {
241 char * end = strchr(begin, ',');
242 if(end) {
243 * end = 0;
245 tags = realloc(tags, sizeof(char *) * (ntag + 2));
247 assert(tags != NULL);
249 tags[ntag++] = strdup(begin);
251 assert(tags[ntag - 1] != NULL);
253 tags[ntag] = NULL;
257 free(resp[n]);
259 ++n;
262 free(resp);
265 return tags;