Volume breaks output format, removed for now.
[shell-fm.git] / source / playlist.c
blobaa029b35d9232c0f81f69c7338989fadf7724483
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
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include <assert.h>
13 #include <unistd.h>
14 #include <sys/types.h>
17 #include "hash.h"
18 #include "http.h"
19 #include "settings.h"
20 #include "service.h"
21 #include "strary.h"
22 #include "util.h"
24 #include "playlist.h"
25 #include "globals.h"
27 #include "interface.h"
30 int expand(struct playlist * list) {
31 char url[512], ** response, * xml = NULL;
32 const char * fmt =
33 "http://ws.audioscrobbler.com/radio/xspf.php"
34 "?sk=%s&discovery=%d&desktop=0";
36 assert(list != NULL);
38 memset(url, 0, sizeof(url));
39 snprintf(
40 url, sizeof(url), fmt,
41 value(& data, "session"), !!enabled(DISCOVERY)
44 response = fetch(url, NULL, NULL, NULL);
46 if(response != NULL) {
47 int retval;
49 xml = join(response, 0);
50 response = NULL;
52 retval = parsexspf(list, xml);
53 return retval;
56 return 0;
59 void trim(char * string){
60 int offset = 0;
61 while(string[offset] == ' ')
62 offset++;
64 if(offset)
65 memmove(string, string + offset, strlen(string + offset) + 1);
69 int parsexspf(struct playlist * list, char * xml) {
70 char * ptr = xml;
71 unsigned i, tracks = 0;
72 char * track;
74 assert(list != NULL);
75 assert(xml != NULL);
77 while((track = strcasestr(ptr, "<track>")) != NULL) {
78 struct tracknode * node = NULL;
79 char * next = strcasestr(track + 7, "<track>"), * duration;
81 const char * tags [] = {
82 "location", "title", "album", "creator", "duration", "image",
83 "lastfm:trackauth",
86 const char * links [] = { "artistpage", "albumpage", "trackpage", "freeTrackURL", };
89 if(next)
90 * (next - 1) = 0;
92 node = malloc(sizeof(struct tracknode));
93 assert(node != NULL);
95 memset(node, 0, sizeof(struct tracknode));
97 for(i = 0; i < (sizeof(tags) / sizeof(char *)); ++i) {
98 char begin[32] = { 0 }, end[32] = { 0 };
100 sprintf(begin, "<%s>", tags[i]);
101 sprintf(end, "</%s>", tags[i]);
103 if((ptr = strcasestr(track, begin)) != NULL) {
104 char * text = strndup(
105 ptr + strlen(begin),
106 (strcasestr(ptr, end)) - (ptr + strlen(begin))
109 assert(text != NULL);
111 unhtml(text);
112 set(& node->track, tags[i], text);
113 free(text);
117 for(i = 0; i < (sizeof(links) / sizeof(char *)); ++i) {
118 char begin[64] = { 0 };
120 sprintf(begin, "<link rel=\"http://www.last.fm/%s\">", links[i]);
122 if((ptr = strcasestr(track, begin)) != NULL) {
123 char * text = strndup(
124 ptr + strlen(begin),
125 (strcasestr(ptr, "</link>")) - (ptr + strlen(begin))
128 assert(text != NULL);
130 set(& node->track, links[i], text);
131 free(text);
135 if(list->title) {
136 trim(list->title);
138 set(& node->track, "station", list->title);
140 else {
141 set(& node->track, "station", "Unknown Station");
144 duration = strdup(value(& node->track, "duration"));
145 if(duration != NULL) {
146 duration[strlen(duration) - 3] = 0;
147 set(& node->track, "duration", duration);
150 push(list, node);
152 ++tracks;
154 if(!next)
155 break;
157 ptr = next;
160 return 1;
164 void freelist(struct playlist * list) {
165 if(list->title != NULL)
166 free(list->title);
168 while(list->track)
169 shift(list);
171 memset(list, 0, sizeof(struct playlist));
175 void push(struct playlist * list, struct tracknode * node) {
176 if(!list->track)
177 list->track = node;
178 else {
179 struct tracknode * last = list->track;
180 while(last->next != NULL)
181 last = last->next;
182 last->next = node;
185 ++list->left;
189 void shift(struct playlist * list) {
190 if(list->track) {
191 struct tracknode * node = list->track;
192 list->track = node->next;
193 empty(& node->track);
194 free(node);
195 --(list->left);
199 void preview(struct playlist list) {
200 struct tracknode * node;
201 unsigned n = 0;
203 if (list.track != NULL)
204 node = list.track->next;
205 else
207 puts("No tracks in queue.");
208 return;
211 if(node == NULL) {
212 puts("No tracks in queue.");
214 else {
215 puts("Upcoming tracks:");
216 while(node != NULL) {
217 const char * format;
219 format = haskey(& rc, "preview-format")
220 ? value(& rc, "preview-format")
221 : "%a - %t";
223 printf("%2d %s\n", n++, meta(format, M_COLORED, & node->track));
225 node = node->next;