Modify version string to post-release version 11.8.17
[gmpc-lyrics.git] / src / plugin.c
blob0842e5dcd47d23a889cc1404e6d3abae720c073d
1 /* gmpc-lyrics (GMPC plugin)
2 * Copyright (C) 2006-2009 Qball Cow <qball@sarine.nl>
3 * Copyright (C) 2006 Maxime Petazzoni <maxime.petazzoni@bulix.org>
4 * Project homepage: http://gmpc.wikia.com/
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 #include "gmpc-lyrics.h"
23 #define LYRICS_FROM "\n\nLyric from "
24 gmpcPlugin plugin;
27 static GtkWidget *lyrics_pref_vbox = NULL;
28 static GtkWidget *lyrics_pref_table = NULL;
30 static const gchar *lyrics_get_translation_domain(void);
31 static xmlGenericErrorFunc handler = NULL;
33 int lyrics_get_enabled();
34 void lyrics_set_enabled(int enabled);
35 /* Playlist window row reference */
36 int fetch_lyric(mpd_Song *song, MetaDataType type, char **path);
38 void fetch_lyric_uris(mpd_Song *song, MetaDataType type, void (*callback)(GList *list, void *data), void *user_data);
40 void xml_error_func(void * ctx, const char * msg, ...);
41 void setup_xml_error();
42 void destroy_xml_error();
44 /**
45 * Used by gmpc to check against what version the plugin is compiled
47 int plugin_api_version = PLUGIN_API_VERSION;
49 /**
50 * Get plugin priority, the lower the sooner checked
52 static int fetch_priority()
54 return cfg_get_single_value_as_int_with_default(config, "lyric-provider", "priority", 90);
56 static void set_priority(int priority)
58 cfg_set_single_value_as_int(config, "lyric-provider", "priority", priority);
61 /**
62 * Preferences structure
64 gmpcPrefPlugin lyrics_gpp = {
65 .construct = lyrics_construct,
66 .destroy = lyrics_destroy
69 /**
70 * Meta data structure
72 gmpcMetaDataPlugin lyric_fetch = {
73 .get_priority = fetch_priority,
74 .set_priority = set_priority,
75 .get_metadata = fetch_lyric_uris
78 gmpcPlugin plugin = {
79 /** Name */
80 .name = N_("Lyrics fetcher"),
81 /** Version */
82 .version = {PLUGIN_MAJOR_VERSION,PLUGIN_MINOR_VERSION,PLUGIN_MICRO_VERSION},
83 /** Plugin type */
84 .plugin_type = GMPC_PLUGIN_META_DATA,
85 /** initialize function */
86 .init = &lyrics_init,
87 /** Preferences structure */
88 .pref = &lyrics_gpp,
89 /** Meta data structure */
90 .metadata = &lyric_fetch,
91 /** get_enabled() */
92 .get_enabled = lyrics_get_enabled,
93 /** set enabled() */
94 .set_enabled = lyrics_set_enabled,
97 .get_translation_domain = lyrics_get_translation_domain
100 static int num_apis = 2;
101 static struct lyrics_api apis[] =
103 {N_("LeosLyrics"),
104 "http://api.leoslyrics.com/",
105 "api_search.php?auth=" PLUGIN_AUTH "&artist=%s&songtitle=%s",
106 "api_search.php?auth=" PLUGIN_AUTH "&songtitle=%s",
107 "api_lyrics.php?auth=" PLUGIN_AUTH "&hid=%s",
108 __leoslyrics_get_id,
109 __leoslyrics_get_lyrics,
111 {N_("Lyrics Tracker"),
112 "http://lyrictracker.com/soap.php?cln=" PLUGIN_AUTH "&clv=undef",
113 "&act=query&ar=%s&ti=%s",
114 "&act=query&ti=%s",
115 "&act=detail&id=%s",
116 __lyrictracker_get_id,
117 __lyrictracker_get_lyrics,
119 {NULL,NULL,NULL,NULL,NULL, NULL, NULL}
123 typedef struct Query {
124 mpd_Song *song;
125 void (*callback)(GList *, gpointer );
126 gpointer user_data;
127 int index;
128 int pref;
129 int exact_match;
130 GList *list;
131 }Query;
134 void fetch_query_iterate (Query *q);
136 void xml_error_func(void * ctx, const char * msg, ...) { } // yes.. do this much on error
138 void setup_xml_error() {
139 if (handler==NULL)
140 handler = (xmlGenericErrorFunc)xml_error_func;
141 initGenericErrorDefaultFunc(&handler);
143 void destroy_xml_error() {
144 initGenericErrorDefaultFunc((xmlGenericErrorFunc *)NULL);
147 void lyrics_init (void)
149 bindtextdomain(GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR);
150 bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
154 static const gchar *lyrics_get_translation_domain(void)
156 return GETTEXT_PACKAGE;
159 xmlNodePtr get_node_by_name (xmlNodePtr node, xmlChar *name)
161 xmlNodePtr cur;
163 for (cur = node; cur; cur = cur->next)
164 if (xmlStrEqual(cur->name, name) &&
165 (cur->type == XML_ELEMENT_NODE))
166 return cur;
168 return NULL;
171 static char * __lyrics_process_string(char *name)
173 return gmpc_easy_download_uri_escape(name);//g_escape_uri_string(name);
175 static void fetch_query_lyrics_result(const GEADAsyncHandler *handle, GEADStatus status, gpointer user_data)
177 Query *q = (Query *)user_data;
178 if(status == GEAD_PROGRESS) return;
179 if(status == GEAD_DONE)
181 struct lyrics_api *api = &(apis[q->index]);
182 gchar *result = NULL;
183 goffset size = 0;
184 const gchar *data = gmpc_easy_handler_get_data(handle, &size);
185 //gmpc_easy_download_struct dl = {(char *)data,(int)size,-1, NULL, NULL};
186 result = api->get_lyrics(data, size);
187 if(result)
189 MetaData *mtd = meta_data_new();
190 printf("Found result: %s\n", api->name);
191 mtd->type = META_SONG_TXT;
192 mtd->plugin_name = plugin.name;
193 mtd->content_type = META_DATA_CONTENT_TEXT;
194 mtd->content = result;
195 mtd->size= -1;
196 if(q->index == q->pref)
197 q->list = g_list_prepend(q->list,mtd);
198 else
199 q->list = g_list_append(q->list, mtd);
202 q->index++;
203 fetch_query_iterate (q);
206 static void fetch_query_search_result(const GEADAsyncHandler *handle, GEADStatus status, gpointer user_data)
208 Query *q = (Query *)user_data;
209 if(status == GEAD_PROGRESS) return;
210 if(status == GEAD_DONE)
212 struct lyrics_api *api = &(apis[q->index]);
213 xmlDocPtr results_doc;
214 goffset size = 0;
215 xmlChar *hid = NULL;
216 const gchar *data = gmpc_easy_handler_get_data(handle, &size);
217 results_doc = xmlParseMemory(data, (int)size);
218 /* Get song id */
219 hid = (xmlChar *)api->get_id(results_doc, q->song->artist, q->song->title, q->exact_match);
220 xmlFreeDoc(results_doc);
221 if(hid && strlen((char *)hid) > 0)
223 gchar *temp = NULL, *lyrics_url = NULL;
224 char *esc_hid = __lyrics_process_string((char *)hid);
225 xmlFree(hid);
226 hid = NULL;
228 temp = g_strdup_printf("%s%s", api->host, api->lyrics_uri);
229 lyrics_url = g_strdup_printf(temp, esc_hid);
230 g_free(esc_hid);
231 g_free(temp);
233 if(gmpc_easy_async_downloader(lyrics_url,fetch_query_lyrics_result , q)!= NULL)
235 return;
238 if(hid) xmlFree(hid);
240 q->index++;
241 fetch_query_iterate (q);
243 void fetch_query_iterate (Query *q)
245 printf("Itteration: %i\n", q->index);
246 if(q->index < num_apis)
248 gchar *search_url;
249 struct lyrics_api *api = &(apis[q->index]);
250 printf("Trying data %s\n", api->name);
251 if (q->song->artist)
253 char *esc_artist = __lyrics_process_string(q->song->artist);
254 char *esc_title = __lyrics_process_string(q->song->title);
255 gchar *temp = g_strdup_printf("%s%s", api->host, api->search_full);
256 search_url = g_strdup_printf(temp, esc_artist,esc_title);
257 g_free(esc_artist);
258 g_free(esc_title);
259 g_free(temp);
261 else
263 char *esc_title = __lyrics_process_string(q->song->title);
264 gchar *temp = g_strdup_printf("%s%s", api->host, api->search_title);
265 search_url = g_strdup_printf(temp, esc_title);
266 g_free(temp);
267 g_free(esc_title);
270 if(gmpc_easy_async_downloader(search_url,fetch_query_search_result , q) != NULL)
272 g_free(search_url);
273 return;
275 q->index++;
276 g_free(search_url);
277 fetch_query_iterate(q);
278 return;
280 /* Return results */
281 printf("Return lyrics api v2\n");
282 q->callback(q->list,q->user_data);
283 g_free(q);
286 void fetch_lyric_uris(mpd_Song *song, MetaDataType type, void (*callback)(GList *list, void *data), void *user_data)
289 printf("lyrics api v2\n");
290 if(song->title != NULL && type == META_SONG_TXT)
292 Query *q = g_malloc0(sizeof(*q));
293 q->callback = callback;
294 q->user_data = user_data;
295 q->index = 0;
296 q->song = song;
297 q->pref =cfg_get_single_value_as_int_with_default(config, "lyrics-plugin", "api-id", 0);
298 q->exact_match = cfg_get_single_value_as_int_with_default(config, "lyrics-plugin", "exact-match", 1);
299 q->list = NULL;
301 fetch_query_iterate(q);
303 return;
305 callback(NULL, user_data);
308 /** Called when enabling the plugin from the preferences dialog. Set
309 * the configuration so that we'll know that the plugin is enabled
310 * afterwards.
313 static void lyrics_match_toggle (GtkWidget *wid)
315 int match = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(wid));
316 cfg_set_single_value_as_int(config, "lyrics-plugin", "exact-match", match);
320 /** Called when the user changes the lyrics API. Set a configuration
321 * value to the new API id.
323 void lyrics_api_changed (GtkWidget *wid)
325 int id = gtk_combo_box_get_active(GTK_COMBO_BOX(wid));
326 cfg_set_single_value_as_int(config, "lyrics-plugin", "api-id", id);
328 debug_printf(DEBUG_INFO, "Saved API ID: %d\n", cfg_get_single_value_as_int_with_default(config, "lyrics-plugin", "api-id", 0));
331 void lyrics_destroy (GtkWidget *container)
333 gtk_container_remove(GTK_CONTAINER(container), lyrics_pref_vbox);
336 /**
337 * Initialize GTK widgets for the preferences window.
339 void lyrics_construct (GtkWidget *container)
341 GtkWidget *label, *combo, *match;
342 int i;
344 label = gtk_label_new(_("Preferred lyric site :"));
345 combo = gtk_combo_box_new_text();
346 match = gtk_check_button_new_with_mnemonic(_("Exact _match only"));
348 lyrics_pref_table = gtk_table_new(2, 2, FALSE);
349 lyrics_pref_vbox = gtk_vbox_new(FALSE,6);
351 for (i=0; apis[i].name ; i++)
352 gtk_combo_box_append_text(GTK_COMBO_BOX(combo), _(apis[i].name));
354 gtk_combo_box_set_active(GTK_COMBO_BOX(combo),
355 cfg_get_single_value_as_int_with_default(config, "lyrics-plugin", "api-id", 0));
357 gtk_table_attach_defaults(GTK_TABLE(lyrics_pref_table), label, 0, 1, 0, 1);
358 gtk_table_attach_defaults(GTK_TABLE(lyrics_pref_table), combo, 1, 2, 0, 1);
359 gtk_table_attach_defaults(GTK_TABLE(lyrics_pref_table), match, 0, 2, 1, 2);
361 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(match),
362 cfg_get_single_value_as_int_with_default(config, "lyrics-plugin", "exact-match", 1));
364 gtk_widget_set_sensitive(lyrics_pref_table, cfg_get_single_value_as_int_with_default(config, "lyrics-plugin", "enable", 0));
366 /* TODO: check that this stuff actually works */
367 //gtk_widget_set_sensitive(match, 0);
369 /* Connect signals */
370 g_signal_connect(G_OBJECT(combo), "changed", G_CALLBACK(lyrics_api_changed), NULL);
371 g_signal_connect(G_OBJECT(match), "toggled", G_CALLBACK(lyrics_match_toggle), NULL);
373 gtk_box_pack_start(GTK_BOX(lyrics_pref_vbox), lyrics_pref_table, FALSE, FALSE, 0);
375 gtk_container_add(GTK_CONTAINER(container), lyrics_pref_vbox);
376 gtk_widget_show_all(container);
379 int lyrics_get_enabled()
381 return cfg_get_single_value_as_int_with_default(config, "lyrics-plugin", "enable", 0);
384 void lyrics_set_enabled(int enabled)
386 cfg_set_single_value_as_int(config, "lyrics-plugin", "enable", enabled);