Fixing dependency and remove commented code.
[gmpc-coveramazon.git] / src / plugin.c
blobcb43b545425ed7d5d2645b3b0454c528a41f0e74
1 #include <stdio.h>
2 #include <string.h>
3 #include <gtk/gtk.h>
4 #include <libxml/parser.h>
5 #include <libxml/tree.h>
6 #include <libmpd/debug_printf.h>
7 #include <gmpc/plugin.h>
8 #include <gmpc/gmpc_easy_download.h>
9 #include <config.h>
10 #define AMAZONKEY "14TC04B24356BPHXW1R2"
12 static char * host = "http://ecs.amazonaws.%s/onca/xml?Service=AWSECommerceService&Operation=ItemSearch&SearchIndex=Music&ResponseGroup=Images,EditorialReview&AWSAccessKeyId=%s&%s=%s&%s=%s";
14 static void amazon_cover_art_pref_construct(GtkWidget *container);
15 static void amazon_cover_art_pref_destroy(GtkWidget *container);
16 static int fetch_cover_art(mpd_Song *song,int type, char **url);
17 static int fetch_cover_priority();
19 static int fetch_metadata(mpd_Song *song,MetaDataType type, char **path);
21 static void amazon_set_enabled(int enabled);
22 static int amazon_get_enabled();
24 #define ENDPOINTS 6
25 static char *endpoints[ENDPOINTS][2] =
27 {"com", "United States"},
28 {"co.uk", "United Kingdom"},
29 {"jp", "Japan"},
30 {"fr", "France"},
31 {"ca", "Canada"},
32 {"de", "Germany"}
35 static GtkWidget *wp_pref_vbox = NULL;
37 typedef struct amazon_song_info {
38 char *image_big;
39 char *image_medium;
40 char *image_small;
41 char *album_info;
43 }amazon_song_info;
45 /**
46 * Get Set enabled
48 static int amazon_get_enabled()
50 return cfg_get_single_value_as_int_with_default(config, "cover-amazon", "enable", TRUE);
52 static void amazon_set_enabled(int enabled)
54 cfg_set_single_value_as_int(config, "cover-amazon", "enable", enabled);
57 static int fetch_cover_priority(){
58 return cfg_get_single_value_as_int_with_default(config, "cover-amazon", "priority", 80);
62 static int fetch_metadata(mpd_Song *song,MetaDataType type, char **path)
64 gchar *url = NULL;
66 if(song->artist == NULL || song->album == NULL)
68 return META_DATA_UNAVAILABLE;
70 if(type != META_ALBUM_ART && type != META_ALBUM_TXT) {
71 return META_DATA_UNAVAILABLE;
73 /* Always fetch it. */
74 fetch_cover_art(song,type, &url);
75 if(url){
76 *path = url;
77 return META_DATA_AVAILABLE;
80 g_free(url);
81 return META_DATA_UNAVAILABLE;
84 static amazon_song_info * amazon_song_info_new()
86 amazon_song_info *asi = g_malloc(sizeof(amazon_song_info));
87 asi->image_big = NULL;
88 asi->image_medium = NULL;
89 asi->image_small = NULL;
90 asi->album_info = NULL;
91 return asi;
93 static void amazon_song_info_free(amazon_song_info *asi)
95 if(asi->image_big != NULL) g_free(asi->image_big);
96 if(asi->image_medium != NULL) g_free(asi->image_medium);
97 if(asi->image_small != NULL) g_free(asi->image_small);
98 if(asi->album_info != NULL) g_free(asi->album_info);
99 g_free(asi);
100 return;
103 static xmlNodePtr get_first_node_by_name(xmlNodePtr xml, gchar *name) {
104 if(xml) {
105 xmlNodePtr c = xml->xmlChildrenNode;
106 for(;c;c=c->next) {
107 if(xmlStrEqual(c->name, (xmlChar *) name))
108 return c;
111 return NULL;
114 static amazon_song_info *__cover_art_xml_get_image(char *data,int size)
116 xmlDocPtr doc = xmlParseMemory(data,size);
117 if(doc)
119 xmlNodePtr root = xmlDocGetRootElement(doc);
120 xmlNodePtr cur = get_first_node_by_name(root, "Items");
121 amazon_song_info *asi = NULL;
122 if(cur) {
123 cur = get_first_node_by_name(cur, "Item");
124 if(cur) {
125 xmlNodePtr child = NULL;
126 asi = amazon_song_info_new();
127 if((child = get_first_node_by_name(cur, "LargeImage"))) {
128 xmlChar *temp = xmlNodeGetContent(get_first_node_by_name(child, "URL"));
129 /* copy it, so we can free it, and don't need xmlFree */
130 asi->image_big = g_strdup((char *)temp);
131 xmlFree(temp);
133 if((child = get_first_node_by_name(cur, "MediumImage"))){
134 xmlChar *temp = xmlNodeGetContent(get_first_node_by_name(child, "URL"));
135 asi->image_medium = g_strdup((char *)temp);
136 xmlFree(temp);
138 if((child = get_first_node_by_name(cur, "SmallImage"))){
139 xmlChar *temp = xmlNodeGetContent(get_first_node_by_name(child, "URL"));
140 asi->image_small = g_strdup((char *)temp);
141 xmlFree(temp);
144 if((child = get_first_node_by_name(cur, "EditorialReviews"))) {
145 child = get_first_node_by_name(child, "EditorialReview");
146 if(child) {
147 xmlChar *temp = xmlNodeGetContent(get_first_node_by_name(child, "Content")); /* ugy, lazy */
148 asi->album_info = g_strdup((char *)temp);
149 xmlFree(temp);
154 xmlFreeDoc(doc);
155 return asi;
157 xmlCleanupParser();
158 return NULL;
162 static int __fetch_metadata_amazon(char *sfield, char *nartist, char *stype,char *nalbum,int type, char **url)
165 gmpc_easy_download_struct data= {NULL, 0,-1, NULL, NULL};
166 int found = 0;
167 char furl[1024];
168 int endpoint = cfg_get_single_value_as_int_with_default(config, "cover-amazon", "location", 0);
169 char *endp = endpoints[endpoint][0];
171 debug_printf(DEBUG_INFO, "search-type: %s\n", stype);
172 snprintf(furl,1024, host,endp, AMAZONKEY,sfield, nartist, stype, nalbum);
173 printf("amazon url: '%s'\n", furl);
174 if(gmpc_easy_download(furl, &data))
176 amazon_song_info *asi = __cover_art_xml_get_image(data.data, data.size);
177 gmpc_easy_download_clean(&data);
178 if(asi)
180 if(type&META_ALBUM_ART)
182 debug_printf(DEBUG_INFO, "Trying to fetch album art");
183 gmpc_easy_download(asi->image_big, &data);
184 if(data.size <= 900){
185 gmpc_easy_download_clean(&data);
186 gmpc_easy_download(asi->image_medium, &data);
187 if(data.size <= 900){
188 gmpc_easy_download_clean(&data);
189 gmpc_easy_download(asi->image_small, &data);
190 if(data.size <= 900)
192 gmpc_easy_download_clean(&data);
196 if(data.size){
197 FILE *fp = NULL;
198 gchar *imgpath = NULL;
199 gchar *filename = g_strdup_printf("%s-%s.jpg",nartist,nalbum);
200 imgpath = gmpc_get_covers_path(filename);
201 g_free(filename);
202 fp = fopen(imgpath, "wb");
203 if(fp)
205 fwrite(data.data, sizeof(char), data.size,fp);
206 *url = g_strdup(imgpath);
207 found = 1;
208 fclose(fp);
210 g_free(imgpath);
212 gmpc_easy_download_clean(&data);
216 else if(type&META_ALBUM_TXT)
218 debug_printf(DEBUG_INFO, "Trying to fetch album txt");
219 if(asi->album_info)
221 FILE *fp;
222 gchar *filename, *imgpath;
223 filename = g_strdup_printf("%s-%s.albuminfo",nartist,nalbum);
224 imgpath = gmpc_get_covers_path(filename);
225 g_free(filename);
226 fp = fopen(imgpath, "w");
227 if(fp)
229 int j=0,depth=0;;
230 *url = g_strdup(imgpath);
232 * Quick 'n Dirty html stripper
234 for(j=0; j < strlen(asi->album_info);j++)
236 if((asi->album_info)[j] == '<') depth++;
237 else if((asi->album_info)[j] == '>' && depth) depth--;
238 else if(depth == 0)
240 fputc((asi->album_info)[j],fp);
243 fclose(fp);
244 found = 1;
247 g_free(imgpath);
250 amazon_song_info_free(asi);
254 return found;
256 static int fetch_cover_art(mpd_Song *song,int type, char **url)
258 int retval=0;
259 gchar *artist = g_uri_escape_string(song->artist,NULL, TRUE);
260 gchar *album = g_uri_escape_string(song->album,NULL, TRUE);
262 retval = __fetch_metadata_amazon(
263 "Title",album,
264 "Artist", artist,
265 type,url);
266 if(!retval && song->performer)
268 gchar *performer = g_uri_escape_string(song->performer, NULL, TRUE);
269 retval = __fetch_metadata_amazon(
270 "Title",album,
271 "Performer", performer,
272 type,url);
273 g_free(performer);
276 g_free(artist);
277 g_free(album);
278 return retval;
282 * Preferences
285 static void amazon_cover_art_enable_toggle(GtkWidget *wid)
287 int kk = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(wid));
288 amazon_set_enabled(kk);
290 static void amazon_cover_art_pref_destroy(GtkWidget *container)
292 gtk_container_remove(GTK_CONTAINER(container), wp_pref_vbox);
294 static void amazon_cover_art_pref_selection_changed(GtkWidget *box)
296 cfg_set_single_value_as_int(config, "cover-amazon", "location", gtk_combo_box_get_active(GTK_COMBO_BOX(box)));
299 static void amazon_cover_art_pref_construct(GtkWidget *container)
301 GtkWidget *enable_cg = gtk_check_button_new_with_mnemonic("_Enable amazon as cover art source");
302 GtkWidget *label = NULL;
303 GtkWidget *selection = NULL;
304 GtkWidget *hbox = NULL;
305 int i;
306 wp_pref_vbox = gtk_vbox_new(FALSE,6);
308 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(enable_cg), amazon_get_enabled());
310 g_signal_connect(G_OBJECT(enable_cg), "toggled", G_CALLBACK(amazon_cover_art_enable_toggle), NULL);
311 gtk_box_pack_start(GTK_BOX(wp_pref_vbox), enable_cg, FALSE, FALSE, 0);
313 /* Location */
314 hbox = gtk_hbox_new(FALSE, 6);
315 label = gtk_label_new("Location:");
316 gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE,0);
317 selection = gtk_combo_box_new_text();
318 for(i=0;i<ENDPOINTS;i++)
319 gtk_combo_box_append_text(GTK_COMBO_BOX(selection), endpoints[i][1]);
320 gtk_combo_box_set_active(GTK_COMBO_BOX(selection),cfg_get_single_value_as_int_with_default(config, "cover-amazon", "location", 0));
321 g_signal_connect(G_OBJECT(selection), "changed",G_CALLBACK(amazon_cover_art_pref_selection_changed), NULL);
323 gtk_box_pack_start(GTK_BOX(hbox), selection, TRUE,TRUE,0);
324 gtk_box_pack_start(GTK_BOX(wp_pref_vbox), hbox, FALSE, FALSE, 0);
326 gtk_container_add(GTK_CONTAINER(container), wp_pref_vbox);
327 gtk_widget_show_all(container);
330 gmpcPrefPlugin cam_pref = {
331 .construct = amazon_cover_art_pref_construct,
332 .destroy = amazon_cover_art_pref_destroy
335 gmpcMetaDataPlugin cam_cover = {
336 .get_priority = fetch_cover_priority,
337 .get_image = fetch_metadata
340 int plugin_api_version = PLUGIN_API_VERSION;
341 gmpcPlugin plugin = {
342 .name = "Amazon Cover Fetcher",
343 .version = {PLUGIN_MAJOR_VERSION,PLUGIN_MINOR_VERSION,PLUGIN_MICRO_VERSION},
344 .plugin_type = GMPC_PLUGIN_META_DATA,
345 .pref = &cam_pref,
346 .metadata = &cam_cover,
347 .get_enabled = amazon_get_enabled,
348 .set_enabled = amazon_set_enabled