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 "
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();
45 * Used by gmpc to check against what version the plugin is compiled
47 int plugin_api_version
= PLUGIN_API_VERSION
;
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
);
62 * Preferences structure
64 gmpcPrefPlugin lyrics_gpp
= {
65 .construct
= lyrics_construct
,
66 .destroy
= lyrics_destroy
72 gmpcMetaDataPlugin lyric_fetch
= {
73 .get_priority
= fetch_priority
,
74 .set_priority
= set_priority
,
75 .get_metadata
= fetch_lyric_uris
80 .name
= N_("Lyrics fetcher"),
82 .version
= {PLUGIN_MAJOR_VERSION
,PLUGIN_MINOR_VERSION
,PLUGIN_MICRO_VERSION
},
84 .plugin_type
= GMPC_PLUGIN_META_DATA
,
85 /** initialize function */
87 /** Preferences structure */
89 /** Meta data structure */
90 .metadata
= &lyric_fetch
,
92 .get_enabled
= lyrics_get_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
[] =
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",
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",
116 __lyrictracker_get_id
,
117 __lyrictracker_get_lyrics
,
119 {NULL
,NULL
,NULL
,NULL
,NULL
, NULL
, NULL
}
123 typedef struct Query
{
125 void (*callback
)(GList
*, gpointer
);
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() {
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
)
163 for (cur
= node
; cur
; cur
= cur
->next
)
164 if (xmlStrEqual(cur
->name
, name
) &&
165 (cur
->type
== XML_ELEMENT_NODE
))
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
;
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
);
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
;
196 if(q
->index
== q
->pref
)
197 q
->list
= g_list_prepend(q
->list
,mtd
);
199 q
->list
= g_list_append(q
->list
, mtd
);
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
;
216 const gchar
*data
= gmpc_easy_handler_get_data(handle
, &size
);
217 results_doc
= xmlParseMemory(data
, (int)size
);
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
);
228 temp
= g_strdup_printf("%s%s", api
->host
, api
->lyrics_uri
);
229 lyrics_url
= g_strdup_printf(temp
, esc_hid
);
233 if(gmpc_easy_async_downloader(lyrics_url
,fetch_query_lyrics_result
, q
)!= NULL
)
238 if(hid
) xmlFree(hid
);
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
)
249 struct lyrics_api
*api
= &(apis
[q
->index
]);
250 printf("Trying data %s\n", api
->name
);
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
);
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
);
270 if(gmpc_easy_async_downloader(search_url
,fetch_query_search_result
, q
) != NULL
)
277 fetch_query_iterate(q
);
281 printf("Return lyrics api v2\n");
282 q
->callback(q
->list
,q
->user_data
);
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
;
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);
301 fetch_query_iterate(q
);
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
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
);
337 * Initialize GTK widgets for the preferences window.
339 void lyrics_construct (GtkWidget
*container
)
341 GtkWidget
*label
, *combo
, *match
;
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
);