add lyrics module using excetra (lyricwiki), right click on bg for lyrics

This commit is contained in:
zmike 2014-02-06 00:47:34 -05:00
parent 89afa6e3c6
commit 17e5b36deb
12 changed files with 713 additions and 14 deletions

2
.gitignore vendored
View File

@ -33,4 +33,4 @@ install-sh
libtool
ltmain.sh
stamp-h1
Lyricwiki*

View File

@ -103,6 +103,12 @@ if test -n "$want_glyr" ; then
fi
AM_CONDITIONAL([MOD_GLYR], [test "x$want_glyr" = "xyes"])
want_elyr=yes
AC_ARG_ENABLE([module-elyr],
[AC_HELP_STRING([--disable-module-elyr], [disable elyr module. @<:@default=detect@:>@])],
[want_elyr=$enableval], [])
AM_CONDITIONAL([MOD_ELYR], [test "x$want_elyr" = "xyes"])
want_eet_saver=yes
AC_ARG_ENABLE([module-eet-saver],
[AC_HELP_STRING([--disable-module-eet-saver], [disable eet-saver module. @<:@default=detect@:>@])],
@ -171,6 +177,7 @@ cat << MODULES_EOF
Modules:
* glyr_gmpc...........: $want_glyr_gmpc
* glyr................: $want_glyr
* elyr................: $want_elyr
* eet_saver...........: $want_eet_saver
* eet_loader..........: $want_eet_loader
MODULES_EOF

View File

@ -10,12 +10,28 @@ collections {
public timer_controls;
public timer_playlist;
public bg_chooser;
public lyrics_visible;
public playlist_visible;
public controls_visible;
public hide_playlist() {
run_program(get_program_id("playlist_hide"));
/* https://phab.enlightenment.org/T905 */
#define PLAYLIST_HIDE \
stop_program(get_program_id("playlist_show_start")); \
if (get_int(lyrics_visible)) \
run_program(get_program_id("lyrics_show")); \
set_int(playlist_visible, 0); \
run_program(get_program_id("playlist_hide_start"));
PLAYLIST_HIDE
}
public hide_controls() {
run_program(get_program_id("controls_hide"));
#define CONTROLS_HIDE \
stop_program(get_program_id("controls_show_start")); \
set_int(controls_visible, 0); \
run_program(get_program_id("controls_hide_start"));
CONTROLS_HIDE
}
}
parts {
@ -49,6 +65,7 @@ collections {
transition: LINEAR 0.2 CURRENT;
target: "bgchooser_active_clip";
}
/* BACKGROUND */
part { name: EMPC_BASE_SWALLOW_BACKGROUND; type: SWALLOW;
description { state: "default";
}
@ -66,7 +83,7 @@ collections {
program { name: "bg_chooser_active";
signal: "empc,bg_chooser,start"; source: "empc";
script {
if (!get_int(bg_chooser)) {
if ((!get_int(bg_chooser)) && (!get_int(lyrics_visible))) {
emit("empc,bg_chooser,active", "empc");
set_int(bg_chooser, 1);
run_program(get_program_id("text_hide"));
@ -85,7 +102,7 @@ collections {
}
program { signal: "mouse,down,1,double"; source: EMPC_BASE_SWALLOW_BACKGROUND;
script {
if (!get_int(bg_chooser))
if ((!get_int(bg_chooser)) && (!get_int(lyrics_visible)))
run_program(get_program_id("bg_chooser_active"));
else
run_program(get_program_id("bg_chooser_inactive"));
@ -135,6 +152,77 @@ collections {
program { signal: "empc,bg,done"; source: "empc"; //switch to right
after: "empc_bg_done";
}
/* LYRICS */
part { name: EMPC_BASE_SWALLOW_LYRICS; type: SWALLOW;
clip_to: "bgchooser_active_clip";
description { state: "default";
//align: 0.5 0.5;
rel1.to: EMPC_BASE_TEXT_ALBUM;
rel1.relative: 0 1;
rel1.offset: 2 15;
rel2.to: EMPC_BASE_TEXT_TITLE;
rel2.relative: 1 0;
rel2.offset: -2 -15;
map {
backface_cull: 1;
on: 1;
perspective: EMPC_BASE_SWALLOW_BACKGROUND;
rotation.y: -180;
}
visible: 0;
}
description { state: "visible";
inherit: "default";
visible: 1;
map.rotation.y: 0;
}
}
program { name: "lyrics_visible";
action: SIGNAL_EMIT "empc,lyrics,visible" "empc";
}
program { name: "lyrics_show";
action: STATE_SET "visible" 0.0;
transition: LINEAR 0.2 CURRENT;
target: EMPC_BASE_SWALLOW_LYRICS;
after: "lyrics_visible";
}
program { name: "lyrics_show_start";
script {
set_int(lyrics_visible, 1);
}
after: "lyrics_show";
}
program { name: "lyrics_hidden";
action: SIGNAL_EMIT "empc,lyrics,hidden" "empc";
}
program { name: "lyrics_hide";
action: STATE_SET "default" 0.0;
transition: LINEAR 0.2 CURRENT;
target: EMPC_BASE_SWALLOW_LYRICS;
after: "lyrics_hide";
}
program { name: "lyrics_hide_start";
script {
set_int(lyrics_visible, 0);
}
after: "lyrics_hide";
}
program { signal: "mouse,down,3"; source: EMPC_BASE_SWALLOW_BACKGROUND;
script {
if (!get_int(bg_chooser)) {
if (get_int(lyrics_visible))
run_program(get_program_id("lyrics_hide_start"));
else
run_program(get_program_id("lyrics_show_start"));
}
}
}
program { signal: "mouse,down,3"; source: EMPC_BASE_SWALLOW_LYRICS;
after: "lyrics_hide_start";
}
/* TEXT */
part { name: EMPC_BASE_TEXT_ARTIST; type: TEXT; mouse_events: 0;
clip_to: "bgchooser_active_clip";
effect: GLOW;
@ -402,8 +490,11 @@ collections {
filter: EMPC_BASE_SWALLOW_PLAYLIST "default";
signal: "empc,playlist,show"; source: "empc";
script {
if (!get_int(bg_chooser)) {
if ((!get_int(playlist_visible)) && (!get_int(bg_chooser))) {
set_int(playlist_visible, 1);
stop_program(get_program_id("playlist_hide_start"));
if (get_int(lyrics_visible))
run_program(get_program_id("lyrics_hide"));
run_program(get_program_id("playlist_show_start"));
}
}
@ -421,9 +512,9 @@ collections {
program { name: "playlist_hide";
filter: EMPC_BASE_SWALLOW_PLAYLIST "visible";
signal: "empc,playlist,hide"; source: "empc";
action: ACTION_STOP;
target: "playlist_show_start";
after: "playlist_hide_start";
script {
PLAYLIST_HIDE
}
}
program { name: "playlist_hide_start";
action: STATE_SET "default" 0.0;
@ -456,7 +547,8 @@ collections {
filter: EMPC_BASE_SWALLOW_CONTROLS "default";
signal: "empc,controls,show"; source: "empc";
script {
if (!get_int(bg_chooser)) {
if ((!get_int(controls_visible)) && (!get_int(bg_chooser))) {
set_int(controls_visible, 1);
stop_program(get_program_id("controls_hide_start"));
run_program(get_program_id("controls_show_start"));
}
@ -474,9 +566,10 @@ collections {
}
program { name: "controls_hide";
filter: EMPC_BASE_SWALLOW_CONTROLS "visible";
action: ACTION_STOP;
target: "controls_show_start";
after: "controls_hide_start";
signal: "empc,controls,hide"; source: "empc";
script {
CONTROLS_HIDE
}
}
program { name: "controls_hide_start";
action: STATE_SET "default" 0.0;

View File

@ -1,4 +1,5 @@
#define EMPC_BASE_SWALLOW_BACKGROUND "empc.swallow.background"
#define EMPC_BASE_SWALLOW_LYRICS "empc.swallow.lyrics"
#define EMPC_BASE_TEXT_ARTIST "empc.text.artist"
#define EMPC_BASE_TEXT_ALBUM "empc.text.album"

View File

@ -20,6 +20,8 @@ static Evas_Object *win = NULL;
static Evas_Object *bg[2] = {NULL};
static Evas_Object *layout = NULL;
static Eina_Bool lyrics_visible = EINA_FALSE;
static Eina_Bool bgchooser = EINA_FALSE;
static Empc_Fetch_Request *bgfetch = NULL;
@ -585,6 +587,7 @@ module_check(Eina_Module *m, void *d EINA_UNUSED)
switch (type)
{
case EMPC_MODULE_TYPE_METADATA_IMAGE:
case EMPC_MODULE_TYPE_METADATA_TEXT:
{
Empc_Module_Metadata_Fetch *em = (Empc_Module_Metadata_Fetch*)mod;
@ -610,6 +613,28 @@ error:
return EINA_FALSE;
}
void
lyrics_set(Evas_Object *obj)
{
elm_object_part_content_set(layout, EMPC_BASE_SWALLOW_LYRICS, obj);
}
static void
lyrics_show(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, const char *sig EINA_UNUSED, const char *src EINA_UNUSED)
{
lyrics_visible = EINA_TRUE;
if (!elm_object_part_content_get(layout, EMPC_BASE_SWALLOW_LYRICS))
metadata_lyrics_fetch(NULL, layout, empd_song_artist, empd_song_title, EINA_FALSE);
INF("LYRICS SHOWN");
}
static void
lyrics_hide(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, const char *sig EINA_UNUSED, const char *src EINA_UNUSED)
{
lyrics_visible = EINA_FALSE;
INF("LYRICS HID");
}
static void
bg_chooser_next(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, const char *sig EINA_UNUSED, const char *src EINA_UNUSED)
{
@ -691,6 +716,7 @@ main(int argc, char *argv[])
Eina_Free_Cb free_cbs[] =
{
[EMPC_MODULE_TYPE_METADATA_IMAGE] = (Eina_Free_Cb)fetch_req_free,
[EMPC_MODULE_TYPE_METADATA_TEXT] = (Eina_Free_Cb)fetch_req_free,
};
eldbus_init();
@ -748,6 +774,9 @@ main(int argc, char *argv[])
elm_object_signal_callback_add(layout, "empc,title,changed,1", "empc", title_changed, NULL);
elm_object_signal_callback_add(layout, "empc,bg,changed", "empc", bg_changed, NULL);
elm_object_signal_callback_add(layout, "empc,lyrics,visible", "empc", lyrics_show, NULL);
elm_object_signal_callback_add(layout, "empc,lyrics,hidden", "empc", lyrics_hide, NULL);
elm_object_signal_callback_add(layout, "empc,playlist,visible", "empc", queue_list_show, NULL);
elm_object_signal_callback_add(layout, "empc,playlist,hidden", "empc", queue_list_hide, NULL);
elm_object_signal_callback_add(layout, "empc,bg_chooser,active", "empc", bg_chooser_show, NULL);

View File

@ -28,7 +28,31 @@ metadata_fetch_req_new(const char *artist, const char *album, const char *song)
return ireq;
}
void
static void
metadata_text_fetch_done(Empc_Fetch_Request *req, Evas_Object *lyric)
{
Empc_Fetch_Request_Internal *ireq = (Empc_Fetch_Request_Internal*)req;
ireq->in_progress = 0;
INF("LYRIC RETURN(%s) %d", strrchr(eina_module_file_get(ireq->module->module), '/') + 1, !!lyric);
if (!lyric)
{
if (req->force || (!ireq->count))
metadata_lyrics_fetch(ireq, NULL, NULL, NULL, req->force);
else
eina_hash_del_by_data(empc_metadata_fetch_reqs[EMPC_MODULE_TYPE_METADATA_TEXT], req);
return;
}
//evas_object_smart_callback_add(lyric, "download,done", metadata_image_done, NULL);
if (ireq->count++) return;
lyrics_set(lyric);
eina_stringshare_del(evas_object_data_del(req->obj, "artist"));
evas_object_data_set(req->obj, "artist", eina_stringshare_ref(req->artist));
eina_stringshare_del(evas_object_data_del(req->obj, "title"));
evas_object_data_set(req->obj, "title", eina_stringshare_ref(req->song));
}
static void
metadata_image_fetch_done(Empc_Fetch_Request *req, Evas_Object *img)
{
Empc_Fetch_Request_Internal *ireq = (Empc_Fetch_Request_Internal*)req;
@ -94,6 +118,48 @@ metadata_image_fetch(Empc_Fetch_Request_Internal *ireq, Evas_Object *obj, const
return NULL;
}
Empc_Fetch_Request *
metadata_lyrics_fetch(Empc_Fetch_Request_Internal *ireq, Evas_Object *obj, const char *artist, const char *title, Eina_Bool force)
{
Empc_Module *mod;
char buf[2048];
Eina_Inlist *mods;
if (artist && (!artist[0]) && title && (!title[0])) return NULL; //fuck you
if (!ireq)
{
snprintf(buf, sizeof(buf), "%s::%s", artist ?: "", title ?: "");
ireq = eina_hash_find(empc_metadata_fetch_reqs[EMPC_MODULE_TYPE_METADATA_TEXT], buf);
}
if (ireq)
{
if (ireq->in_progress) return NULL;
mods = EINA_INLIST_GET(ireq->module)->next;
ireq->module = NULL;
}
else
{
ireq = metadata_fetch_req_new(artist, NULL, title);
ireq->req.result = metadata_text_fetch_done;
ireq->req.obj = obj;
eina_hash_add(empc_metadata_fetch_reqs[EMPC_MODULE_TYPE_METADATA_TEXT], buf, ireq);
mods = empc_modules[EMPC_MODULE_TYPE_METADATA_TEXT];
}
ireq->req.force = !!force;
EINA_INLIST_FOREACH(mods, mod)
{
Empc_Module_Metadata_Fetch *em = (Empc_Module_Metadata_Fetch*)mod;
if (!em->fetch((Empc_Fetch_Request*)ireq)) continue;
INF("LYRIC FETCH(%s)", strrchr(eina_module_file_get(mod->module), '/') + 1);
ireq->module = mod;
ireq->in_progress = 1;
break;
}
if (ireq->module) return (void*)ireq;
eina_hash_del_by_key(empc_metadata_fetch_reqs[EMPC_MODULE_TYPE_METADATA_TEXT], buf);
return NULL;
}
void
metadata_fetch_cancel(Empc_Fetch_Request *req)
{

View File

@ -51,5 +51,9 @@ extern int empc_log_dom;
extern Eina_Inlist *empc_modules[];
extern Eina_Hash *empc_metadata_fetch_reqs[];
Empc_Fetch_Request *metadata_lyrics_fetch(Empc_Fetch_Request_Internal *ireq, Evas_Object *obj, const char *artist, const char *title, Eina_Bool force);
Empc_Fetch_Request *metadata_image_fetch(Empc_Fetch_Request_Internal *ireq, Evas_Object *obj, const char *artist, const char *album, Eina_Bool force);
void metadata_fetch_cancel(Empc_Fetch_Request *req);
void lyrics_set(Evas_Object *obj);

View File

@ -54,6 +54,44 @@ src_modules_glyr_la_LDFLAGS = -module -avoid-version
src_modules_glyr_la_LIBTOOLFLAGS = --tag=disable-static
endif
if MOD_ELYR
ELYR_AZY_SRC = \
src/modules/Lyricwiki_Common_Azy.c \
src/modules/Lyricwiki_Common_Azy.h \
src/modules/Lyricwiki_Common.c \
src/modules/Lyricwiki_Common.h
DISTCLEANFILES += $(ELYR_AZY_SRC)
EXTRA_DIST += src/modules/excetra.azy
$(ELYR_AZY_SRC): src/modules/excetra.azy
azy_parser -H -o $(top_builddir)/src/modules src/modules/excetra.azy
mod_LTLIBRARIES += src/modules/elyr.la
src_modules_elyr_la_SOURCES = \
src/modules/elyr.c \
src/modules/excetra.c \
src/modules/excetra.h \
$(ELYR_AZY_SRC)
src_modules_elyr_la_CPPFLAGS = \
$(AM_CFLAGS) \
$(mod_cppflags) \
@EFL_CFLAGS@ \
@ELM_CFLAGS@ \
-I$(top_srcdir)/src/bin \
-I$(top_builddir)
src_modules_elyr_la_LIBADD = \
@EFL_LIBS@ \
@ELM_LIBS@
src_modules_elyr_la_LDFLAGS = -module -avoid-version
src_modules_elyr_la_LIBTOOLFLAGS = --tag=disable-static
endif
if MOD_EET_SAVER
mod_LTLIBRARIES += src/modules/eet_saver.la

146
src/modules/elyr.c Normal file
View File

@ -0,0 +1,146 @@
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include "empdd.h"
#include "empc.h"
#include <Ecore.h>
#include <Efreet.h>
#include <Elementary.h>
#define EXCETRA_LIB
#include "excetra.h"
typedef struct Elyr_Req
{
Empc_Fetch_Request *req;
Eina_List *ereqs;
} Elyr_Req;
static Eina_List *reqs = NULL;
static void result_cb(Elyr_Req *eq, Excetra_Req *ereq, const char *lyric);
static void
elyr_req_free(Elyr_Req *eq)
{
E_FREE_LIST(eq->ereqs, excetra_req_cancel);
free(eq);
}
static void
result_cb(Elyr_Req *eq, Excetra_Req *ereq, const char *lyric)
{
Evas_Object *o;
char *txt;
eq->ereqs = eina_list_remove(eq->ereqs, ereq);
if (!lyric)
{
if (excetra_req_is_instrumental(ereq) || (!eq->ereqs))
{
eq->req->result(eq->req, NULL);
reqs = eina_list_remove(reqs, eq);
elyr_req_free(eq);
}
return;
}
o = elm_entry_add(eq->req->obj);
elm_scroller_policy_set(o, ELM_SCROLLER_POLICY_OFF, ELM_SCROLLER_POLICY_AUTO);
elm_entry_editable_set(o, 0);
elm_entry_single_line_set(o, 0);
elm_entry_scrollable_set(o, 1);
elm_object_focus_allow_set(o, 0);
elm_entry_line_wrap_set(o, ELM_WRAP_MIXED);
txt = elm_entry_utf8_to_markup(lyric);
elm_entry_entry_set(o, txt);
free(txt);
eq->req->result(eq->req, o);
if (eq->ereqs && (!eq->req->force)) return;
eq->req->result(eq->req, NULL);
reqs = eina_list_remove(reqs, eq);
elyr_req_free(eq);
}
EAPI void
empc_module_metadata_cancel(const Empc_Fetch_Request *req)
{
Eina_List *l, *ll;
Excetra_Req *ereq;
EINA_LIST_FOREACH_SAFE(reqs, l, ll, ereq)
{
if (excetra_req_data_get(ereq) != req) continue;
reqs = eina_list_remove_list(reqs, l);
excetra_req_cancel(ereq);
break;
}
}
EAPI Eina_Bool
empc_module_metadata_fetch(const Empc_Fetch_Request *req)
{
Excetra_Req *ereq;
Elyr_Req *eq;
const char *p;
char *s, *song;
eq = calloc(1, sizeof(Elyr_Req));
ereq = excetra_req_new(req->artist, req->song, (Excetra_Result_Cb)result_cb, eq);
if (!ereq)
{
free(eq);
return EINA_FALSE;
}
eq->req = (Empc_Fetch_Request*)req;
eq->ereqs = eina_list_append(eq->ereqs, ereq);
s = song = calloc(1, strlen(req->song) * 3);
for (p = req->song; p[0]; p++, s++)
{
if (p[0] == '-')
{
s[0] = '_';
s++;
}
s[0] = p[0];
if (p[0] == '-')
{
s++;
s[0] = '_';
strcpy(s + 1, p + 1);
ereq = excetra_req_new(req->artist, song, (Excetra_Result_Cb)result_cb, eq);
if (ereq)
eq->ereqs = eina_list_append(eq->ereqs, ereq);
}
}
free(song);
return EINA_TRUE;
}
EAPI Empc_Module_Type
empc_module_type(void)
{
return EMPC_MODULE_TYPE_METADATA_TEXT;
}
EAPI int
empc_module_priority(void)
{
return 25;
}
static Eina_Bool
elyr_init(void)
{
return !!excetra_init();
}
static void
elyr_shutdown(void)
{
E_FREE_LIST(reqs, elyr_req_free);
excetra_shutdown();
}
EINA_MODULE_INIT(elyr_init);
EINA_MODULE_SHUTDOWN(elyr_shutdown);

9
src/modules/excetra.azy Normal file
View File

@ -0,0 +1,9 @@
Azy_Namespace Lyricwiki;
struct Lyric
{
string artist;
string song;
string lyrics;
string url;
};

294
src/modules/excetra.c Normal file
View File

@ -0,0 +1,294 @@
#include "excetra.h"
#include <Evas.h>
#include <Ecore.h>
#include <Ecore_Con.h>
#include <Azy.h>
#include "Lyricwiki_Common_Azy.h"
#define DBG(...) EINA_LOG_DOM_DBG(excetra_log_dom, __VA_ARGS__)
#define INF(...) EINA_LOG_DOM_INFO(excetra_log_dom, __VA_ARGS__)
#define WRN(...) EINA_LOG_DOM_WARN(excetra_log_dom, __VA_ARGS__)
#define ERR(...) EINA_LOG_DOM_ERR(excetra_log_dom, __VA_ARGS__)
#define CRI(...) EINA_LOG_DOM_CRIT(excetra_log_dom, __VA_ARGS__)
int excetra_log_dom = -1;
#define LYRICWIKI_SEARCH_TRACK_SIZE sizeof("http://lyrics.wikia.com/api.php?artist=&song=&fmt=json")
#define LYRICWIKI_SEARCH_TRACK "http://lyrics.wikia.com/api.php?artist="
struct Excetra_Req
{
Ecore_Con_Url *url;
Eina_Strbuf *buf;
Excetra_Result_Cb cb;
void *data;
Eina_Bool instrumental : 1;
};
static Ecore_Event_Handler *handler_data;
static Ecore_Event_Handler *handler_done;
static Eina_List *reqs;
static void
excetra_req_free(Excetra_Req *req)
{
reqs = eina_list_remove(reqs, req);
eina_strbuf_free(req->buf);
ecore_con_url_data_set(req->url, NULL);
ecore_con_url_free(req->url);
free(req);
}
static Eina_Bool
lyricwiki_data(void *d EINA_UNUSED, int type EINA_UNUSED, Ecore_Con_Event_Url_Data *ev)
{
Excetra_Req *req = ecore_con_url_data_get(ev->url_con);
if ((!reqs) || (!eina_list_data_find(reqs, req))) return ECORE_CALLBACK_RENEW;
//DBG("Received %i bytes of lyric: %s", ev->size, ecore_con_url_url_get(ev->url_con));
if (req->buf)
eina_strbuf_append_length(req->buf, (char*)&ev->data[0], ev->size);
else
{
req->buf = eina_strbuf_new();
eina_strbuf_append_length(req->buf, (char*)&ev->data[7], ev->size - 7);
}
return ECORE_CALLBACK_DONE;
}
static char *
lyricwiki_parse_lyric(Eina_Strbuf *buf)
{
size_t size;
char *lyric_start, *lyric_end;
const char *s;
size = eina_strbuf_length_get(buf);
if (!size)
{
ERR("size is 0!");
return NULL;
}
s = eina_strbuf_string_get(buf);
lyric_start = strstr(s, "phone_right.gif");
if (!lyric_start) goto error;
lyric_start = strstr(lyric_start, "</div>");
if (!lyric_start) goto error;
if (size - ((lyric_start - s) + sizeof("</div>") - 1) < 10) goto error;
lyric_start += sizeof("</div>") - 1;
lyric_end = strstr(lyric_start, "<!--");
if (!lyric_end) goto error;
lyric_end[0] = 0;
while (lyric_end[-1] == '\n')
{
lyric_end[-1] = 0;
lyric_end--;
}
return evas_textblock_text_markup_to_utf8(NULL, lyric_start);
error:
ERR("Parsing error!");
return NULL;
}
static void
lyricwiki_parse_stub(Excetra_Req *req)
{
size_t size;
Azy_Net *net;
Azy_Content *content;
Lyricwiki_Lyric *lwl;
size = eina_strbuf_length_get(req->buf);
DBG("\n%s", eina_strbuf_string_get(req->buf));
if (!size)
{
ERR("size is 0!");
return;
}
net = azy_net_buffer_new(eina_strbuf_string_steal(req->buf), size, AZY_NET_TRANSPORT_JSON, EINA_TRUE);
content = azy_content_new(NULL);
azy_content_deserialize(content, net);
if (azy_value_to_Lyricwiki_Lyric(azy_content_retval_get(content), &lwl))
{
INF("STUB:");
Lyricwiki_Lyric_print(NULL, 0, lwl);
ecore_con_url_free(req->url);
req->instrumental = lwl->lyrics && (!strcmp(lwl->lyrics, "Instrumental"));
if (req->instrumental)
{
req->cb(req->data, req, NULL);
excetra_req_free(req);
return;
}
req->url = ecore_con_url_new(lwl->url);
ecore_con_url_data_set(req->url, req);
ecore_con_url_get(req->url);
}
Lyricwiki_Lyric_free(lwl);
azy_net_free(net);
azy_content_free(content);
}
static Eina_Bool
lyricwiki_complete(void *d EINA_UNUSED, int type EINA_UNUSED, Ecore_Con_Event_Url_Complete *ev)
{
const Eina_List *headers, *l;
const char *h;
char *lyric = NULL;
Eina_Bool stub = EINA_TRUE;
Azy_Net_Transport tp;
Excetra_Req *req = ecore_con_url_data_get(ev->url_con);
if ((!reqs) || (!eina_list_data_find(reqs, req))) return ECORE_CALLBACK_RENEW;
DBG("%d code for lyrics: %s", ev->status, ecore_con_url_url_get(ev->url_con));
headers = ecore_con_url_response_headers_get(ev->url_con);
EINA_LIST_FOREACH(headers, l, h)
{
if (strncasecmp(h, "content-type: ", sizeof("content-type: ") - 1)) continue;
h += sizeof("content-type: ") - 1;
tp = azy_util_transport_get(h);
if (tp == AZY_NET_TRANSPORT_JAVASCRIPT) break;
if (tp == AZY_NET_TRANSPORT_HTML)
{
stub = EINA_FALSE;
break;
}
req->cb(req->data, req, NULL);
excetra_req_free(req);
return ECORE_CALLBACK_DONE;
}
if (ev->status != 200)
{
req->cb(req->data, req, NULL);
excetra_req_free(req);
return ECORE_CALLBACK_DONE;
}
if (stub)
lyricwiki_parse_stub(req);
else
{
lyric = lyricwiki_parse_lyric(req->buf);
req->cb(req->data, req, lyric);
free(lyric);
excetra_req_free(req);
}
return ECORE_CALLBACK_DONE;
}
void
excetra_req_cancel(Excetra_Req *req)
{
if (req) excetra_req_free(req);
}
void *
excetra_req_data_get(const Excetra_Req *req)
{
EINA_SAFETY_ON_NULL_RETURN_VAL(req, NULL);
return req->data;
}
Excetra_Req *
excetra_req_new(const char *artist, const char *song, Excetra_Result_Cb cb, const void *data)
{
Ecore_Con_Url *url;
char buf[4096];
char *a, *s, *p;
Excetra_Req *req = NULL;
if ((!artist) || (!artist[0]) || (!song) || (!song[0]) || (!cb)) return EINA_FALSE;
a = strdup(artist);
for (p = strchr(a, ' '); p; p = strchr(p + 1, ' '))
*p = '_';
s = strdup(song);
for (p = strchr(s, ' '); p; p = strchr(p + 1, ' '))
*p = '_';
snprintf(buf, sizeof(buf), LYRICWIKI_SEARCH_TRACK "%s&song=%s&fmt=json", a, s);
free(a);
free(s);
url = ecore_con_url_new(buf);
if (ecore_con_url_get(url))
{
req = calloc(1, sizeof(Excetra_Req));
req->url = url;
req->cb = cb;
req->data = (void*)data;
reqs = eina_list_append(reqs, req);
ecore_con_url_data_set(url, req);
}
else
ecore_con_url_free(url);
return req;
}
Eina_Bool
excetra_req_is_instrumental(const Excetra_Req *req)
{
return req->instrumental;
}
int
excetra_init(void)
{
eina_init();
ecore_init();
excetra_log_dom = eina_log_domain_register("excetra", EINA_COLOR_CYAN);
eina_log_domain_level_set("excetra", EINA_LOG_LEVEL_DBG);
if (excetra_log_dom == -1)
{
fprintf(stderr, "Could not init log domain!\n");
return 0;
}
if (!ecore_con_url_init())
{
ERR("CURL support is required!");
return 0;
}
evas_init();
azy_init();
handler_done = ecore_event_handler_add(ECORE_CON_EVENT_URL_COMPLETE, (Ecore_Event_Handler_Cb)lyricwiki_complete, NULL);
handler_data = ecore_event_handler_add(ECORE_CON_EVENT_URL_DATA, (Ecore_Event_Handler_Cb)lyricwiki_data, NULL);
return 1;
}
void
excetra_shutdown(void)
{
ecore_event_handler_del(handler_done);
handler_done = NULL;
ecore_event_handler_del(handler_data);
handler_data = NULL;
azy_shutdown();
evas_shutdown();
ecore_con_url_shutdown();
eina_log_domain_unregister(excetra_log_dom);
excetra_log_dom = -1;
ecore_shutdown();
eina_shutdown();
}
#ifndef EXCETRA_LIB
static void
result_cb(void *data EINA_UNUSED, Excetra_Req *req, const char *lyric)
{
INF("\n%s", excetra_req_is_instrumental(req) ? "Instrumental" : lyric);
ecore_main_loop_quit();
}
int
main(int argc, char *argv[])
{
if (argc != 3)
{
fprintf(stderr, "USAGE: %s ARTIST SONG\n", argv[0]);
exit(1);
}
if (!excetra_init()) exit(1);
excetra_req_new(argv[1], argv[2], result_cb, NULL);
ecore_main_loop_begin();
return 0;
}
#endif

12
src/modules/excetra.h Normal file
View File

@ -0,0 +1,12 @@
#include <Eina.h>
typedef struct Excetra_Req Excetra_Req;
typedef void (*Excetra_Result_Cb)(void *user_data, Excetra_Req *req, const char *lyrics);
EAPI int excetra_init(void);
EAPI void excetra_shutdown(void);
EAPI Excetra_Req *excetra_req_new(const char *artist, const char *song, Excetra_Result_Cb cb, const void *data);
EAPI void excetra_req_cancel(Excetra_Req *req);
EAPI void *excetra_req_data_get(const Excetra_Req *req);
EAPI Eina_Bool excetra_req_is_instrumental(const Excetra_Req *req);