#include <libxml/parser.h>
#include <libxml/xpath.h>
+#include <json-glib/json-glib.h>
+
+#include "mvs-tmdb-movie.h"
+#include "mvs-tmdb-image.h"
+#include "mvs-watc-movie.h"
#define TMDB_API_KEY "249e1a42df9bee09fac5e92d3a51396b"
#define TMDB_LANGUAGE "en"
#define TMDB_BASE_URL "http://api.themoviedb.org/2.1/%s/%s/%s/%s/%s"
#define TMDB_MOVIE_XPATH "/OpenSearchDescription/movies/movie"
+#define WATC_BASE_URL "http://whatsafterthecredits.com/api.php?action=%s&format=%s&search=%s"
+#define WATC_ACTION "opensearch"
+#define WATC_FORMAT "json"
+
G_DEFINE_TYPE (MvsMInfoProvider, mvs_minfo_provider, G_TYPE_OBJECT)
enum {
struct _MvsMInfoProviderPrivate {
gchar *format;
+ MvsService service;
};
enum {
TMDB_FORMAT,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
- signals[RESPONSE_RECEIVED] = g_signal_new ("response-received", MVS_TYPE_MINFO_PROVIDER,
- G_SIGNAL_RUN_LAST,
+ signals[RESPONSE_RECEIVED] = g_signal_new ("response-received",
+ MVS_TYPE_MINFO_PROVIDER,
+ G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS,
0,
NULL,
NULL,
- g_cclosure_marshal_VOID__VOID,
+ g_cclosure_marshal_VOID__UINT_POINTER,
G_TYPE_NONE,
- 0,
+ 2,
+ G_TYPE_UINT,
+ G_TYPE_POINTER,
NULL);
}
{
self->priv = GET_PRIVATE (self);
self->priv->format = NULL;
+ self->priv->service = MVS_SERVICE_TMDB;
}
MvsMInfoProvider*
return g_object_new (MVS_TYPE_MINFO_PROVIDER, NULL);
}
-static void
-display_movie_info (xmlNodePtr node)
+static MvsTmdbImage*
+create_tmdb_image (xmlNodePtr node)
+{
+ MvsTmdbImage *image = mvs_tmdb_image_new ();
+ gchar *value = NULL;
+ int i;
+
+ /* <image type="poster"
+ * url="http://....jpg"
+ * size="original"
+ * id="4bc91...e007304"/> */
+
+ for (i = 0; i < LAST_FIELD; i ++) {
+
+ const gchar *image_field = mvs_tmdb_image_get_field (i);
+
+ value = xmlGetProp (node, image_field);
+ g_object_set (image, image_field, value, NULL);
+
+ g_free (value);
+ }
+
+ return image;
+}
+
+static MvsTmdbMovie*
+create_tmdb_movie (xmlNodePtr node)
{
xmlNodePtr cur_node = NULL;
+ MvsTmdbMovie *movie_info = mvs_tmdb_movie_new ();
+ GList *image_list = NULL;
+ /* We use the loop to append each property to the movie object */
for (cur_node = node; cur_node; cur_node = cur_node->next) {
if (cur_node->type == XML_ELEMENT_NODE) {
- gchar *value = xmlNodeGetContent (cur_node);
- g_print ("[%s] = %s\n", cur_node->name, value);
+ gchar *value = NULL;
+
+ if (g_strcmp0 (cur_node->name, "images") == 0) {
+ xmlNodePtr cur_image = NULL;
+ for (cur_image = cur_node->children; cur_image;
+ cur_image = cur_image->next) {
+
+ MvsTmdbImage *tmdb_image = create_tmdb_image (cur_image);
+ image_list = g_list_append (image_list, tmdb_image);
+ }
+ }
+ else {
+ value = xmlNodeGetContent (cur_node);
+ g_object_set (movie_info, cur_node->name, value, NULL);
+ g_free (value);
+ }
}
}
+
+ mvs_tmdb_movie_set_images (movie_info, image_list);
+
+ return movie_info;
}
-static void
-iterate_list (xmlNodeSetPtr node_set)
+static GList*
+generate_list (xmlNodeSetPtr node_set)
{
int i = 0;
+ GList *list = NULL;
for (i = 0; i < node_set->nodeNr; i++) {
xmlNodePtr node = node_set->nodeTab[i];
if (node->type == XML_ELEMENT_NODE) {
- display_movie_info (node->children);
+ MvsTmdbMovie *movie_info =
+ create_tmdb_movie (node->children);
+ if (movie_info)
+ list = g_list_prepend (list, movie_info);
}
}
+
+ if (list)
+ list = g_list_reverse (list);
+
+ return list;
}
-static void
+static GList*
parse_xml (const char *xml_data, goffset length)
{
+ GList *list = NULL;
xmlDocPtr document = xmlReadMemory (xml_data, length,
NULL,
NULL,
XML_PARSE_NOBLANKS | XML_PARSE_RECOVER);
- g_return_if_fail (document);
+ g_return_val_if_fail (document, NULL);
xmlXPathContextPtr context_ptr = xmlXPathNewContext (document);
xmlNodeSetPtr nodeset = xpath_obj->nodesetval;
if (nodeset->nodeNr > 0) {
- iterate_list (nodeset);
+ list = generate_list (nodeset);
}
- xmlXPathFreeNodeSetList (xpath_obj);
+ xmlXPathFreeObject (xpath_obj);
xmlXPathFreeContext (context_ptr);
xmlFreeDoc (document);
+
+ return list;
+}
+
+static GList *
+parse_json (const char *json_data, goffset length)
+{
+ JsonParser *parser = NULL;
+ JsonNode *root = NULL;
+ GError *error = NULL;
+ GList *list = NULL;
+
+ parser = json_parser_new ();
+
+ json_parser_load_from_data (parser, json_data, length, &error);
+ if (error)
+ {
+ g_warning ("Unable to parse data '%s': %s\n",
+ json_data, error->message);
+ g_error_free (error);
+ g_object_unref (parser);
+ return list;
+ }
+
+ /* Don't free */
+ root = json_parser_get_root (parser);
+ JsonArray *response = json_node_get_array (root);
+
+ /* The response is expected with the following format:
+ * [ SEARCH_TERM ,[ SEARCH_RESULT_1, SEARCH_RESULT_N]] */
+
+ if (json_array_get_length (response) != 2) {
+
+ g_warning ("Wrong response format: %s\n", json_data);
+
+ g_object_unref (parser);
+ return list;
+ }
+
+ const gchar *search_term = json_array_get_string_element (response, 0);
+ g_message ("Searched for: %s\n", search_term);
+
+ JsonArray *results = json_array_get_array_element (response, 1);
+ int i;
+ int array_length = json_array_get_length (results);
+
+ for (i = 0; i < array_length; i++) {
+ const gchar *result =
+ json_array_get_string_element (results, i);
+ MvsWatcMovie *watc_movie = mvs_watc_movie_new (result);
+ list = g_list_prepend (list, watc_movie);
+ }
+
+ g_object_unref (parser);
+
+ if (list)
+ list = g_list_reverse (list);
+
+ return list;
}
static void
-response_callback (SoupSession *session, SoupMessage *message,
+process_response_cb (SoupSession *session, SoupMessage *message,
gpointer user_data)
{
MvsMInfoProvider *self = MVS_MINFO_PROVIDER (user_data);
const gchar *mime = NULL;
+ GList *list = NULL;
+ guint service;
if (!SOUP_STATUS_IS_SUCCESSFUL (message->status_code) ||
message->response_body->length <= 0) {
mime = soup_message_headers_get_content_type
(message->response_headers, NULL);
+ g_message ("Mime type: %s\n", mime);
- parse_xml (message->response_body->data,
- message->response_body->length);
+ if (g_strcmp0 (mime, "text/xml") == 0) {
+ list = parse_xml (message->response_body->data,
+ message->response_body->length);
+ service = MVS_SERVICE_TMDB;
+ }
+ else if (g_strcmp0 (mime, "application/json") == 0) {
+ list = parse_json (message->response_body->data,
+ message->response_body->length);
+ service = MVS_SERVICE_WATC;
+ }
}
- g_signal_emit (self, signals[RESPONSE_RECEIVED], 0);
+ g_signal_emit (self, signals[RESPONSE_RECEIVED], 0, service, list);
}
static gchar *
get_query_uri (MvsMInfoProvider *self, const char *query)
{
- /* METHOD/LANGUAGE/FORMAT/APIKEY/MOVIENAME */
- gchar *uri = g_strdup_printf (TMDB_BASE_URL, TMDB_METHOD,
- TMDB_LANGUAGE,
- self->priv->format,
- TMDB_API_KEY,
- query);
+ gchar *uri = NULL;
+
+ if (self->priv->service == MVS_SERVICE_TMDB) {
+ /* METHOD/LANGUAGE/FORMAT/APIKEY/MOVIENAME */
+ uri = g_strdup_printf (TMDB_BASE_URL, TMDB_METHOD,
+ TMDB_LANGUAGE,
+ self->priv->format,
+ TMDB_API_KEY,
+ query);
+ }
+ else if (self->priv->service == MVS_SERVICE_WATC) {
+ /* WATCBASE_URL/ACTION/FORMAT/QUERY */
+ uri = g_strdup_printf (WATC_BASE_URL,
+ WATC_ACTION,
+ WATC_FORMAT,
+ query);
+ }
+ else {
+ g_warning ("Service unsupported\n");
+ }
+
+ g_message ("%s", uri);
return uri;
}
gboolean
-mvs_minfo_provider_query (MvsMInfoProvider *self,
+mvs_minfo_provider_query (MvsMInfoProvider *self, MvsService service,
const gchar *query)
{
g_return_val_if_fail (MVS_IS_MINFO_PROVIDER (self), FALSE);
+ self->priv->service = service;
+
SoupSession *session = NULL;
SoupMessage *message = NULL;
gboolean message_queued = FALSE;
if (message) {
soup_session_queue_message (session, message,
- response_callback, self);
+ process_response_cb, self);
message_queued = TRUE;
}