Google backend: use libcurl, parse runtimes
authorPhilipp Zabel <philipp.zabel@gmail.com>
Fri, 16 Jul 2010 16:59:57 +0000 (18:59 +0200)
committerPhilipp Zabel <philipp.zabel@gmail.com>
Thu, 5 Aug 2010 19:04:59 +0000 (21:04 +0200)
Makefile.am
configure.ac
src/backends/google/curl-wrapper.vala [new file with mode: 0644]
src/backends/google/google-parser.vala

index 1c6e11c..508db9d 100644 (file)
@@ -206,16 +206,18 @@ src/plugins/moviepilot-plugin.c: ${libmoviepilot_plugin_la_VALASOURCES}
 
 cinaest_google_backend_SOURCES = \
        src/backends/google/google-backend.c \
+       src/backends/google/curl-wrapper.c \
        src/backends/google/google-parser.c
 
 cinaest_google_backend_VALASOURCES = \
        src/backends/google/google-backend.vala \
+       src/backends/google/curl-wrapper.vala \
        src/backends/google/google-parser.vala
 
-cinaest_google_backend_VALAFLAGS = --vapidir ./vapi --pkg dbus-glib-1 \
-       --pkg gconf-2.0 --pkg gee-1.0 --pkg gio-2.0 --pkg libxml-2.0
-cinaest_google_backend_CFLAGS = ${DBUS_CFLAGS} ${GCONF_CFLAGS} ${GEE_CFLAGS} ${GIO_CFLAGS} ${XML_CFLAGS}
-cinaest_google_backend_LDADD = ${DBUS_LIBS} ${GCONF_LIBS} ${GEE_LIBS} ${GIO_LIBS} ${XML_LIBS}
+cinaest_google_backend_VALAFLAGS = --thread --vapidir ./vapi --pkg dbus-glib-1 \
+       --pkg gconf-2.0 --pkg gee-1.0 --pkg gio-2.0 --pkg libcurl --pkg libxml-2.0
+cinaest_google_backend_CFLAGS = ${CURL_CFLAGS} ${DBUS_CFLAGS} ${GCONF_CFLAGS} ${GEE_CFLAGS} ${GIO_CFLAGS} ${GTHREAD_CFLAGS} ${XML_CFLAGS}
+cinaest_google_backend_LDADD = ${CURL_LIBS} ${DBUS_LIBS} ${GCONF_LIBS} ${GEE_LIBS} ${GIO_LIBS} ${GTHREAD_LIBS} ${XML_LIBS}
 
 src/backends/google/google-backend.c: ${cinaest_google_backend_VALASOURCES}
        ${VALAC} -C ${cinaest_google_backend_VALASOURCES} ${cinaest_google_backend_VALAFLAGS}
index cbd3215..1612dbb 100644 (file)
@@ -47,6 +47,10 @@ PKG_CHECK_MODULES(GDK, gdk-pixbuf-2.0)
 AC_SUBST(GDK_LIBS)
 AC_SUBST(GDK_CFLAGS)
 
+PKG_CHECK_MODULES(GTHREAD, gthread-2.0 >= 2.20.3)
+AC_SUBST(GTHREAD_LIBS)
+AC_SUBST(GTHREAD_CFLAGS)
+
 PKG_CHECK_MODULES(HILDON, hildon-1 >= 2.2.0)
 AC_SUBST(HILDON_LIBS)
 AC_SUBST(HILDON_CFLAGS)
diff --git a/src/backends/google/curl-wrapper.vala b/src/backends/google/curl-wrapper.vala
new file mode 100644 (file)
index 0000000..9f640af
--- /dev/null
@@ -0,0 +1,55 @@
+public class CurlWrapper : Object {
+       private Curl.EasyHandle curl;
+       private string url = null;
+       private SourceFunc callback = null;
+       private StringBuilder result;
+
+       construct {
+               curl = new Curl.EasyHandle ();
+               // FIXME: Fremantle SDK doesn't come with certs
+               curl.setopt (Curl.Option.SSL_VERIFYPEER, 0);
+       //      curl.setopt (Curl.Option.VERBOSE, 1);
+       }
+
+       static construct {
+               Curl.global_init (Curl.GLOBAL_DEFAULT);
+       }
+
+       private void* download_thread () {
+               curl.setopt (Curl.Option.WRITEFUNCTION, write_callback);
+               curl.setopt (Curl.Option.WRITEDATA, this);
+               curl.setopt (Curl.Option.URL, url);
+               var res = curl.perform ();
+               if (res != Curl.Code.OK)
+                       print ("CURL: %d\n", res);
+
+               if (callback != null)
+                       Idle.add (callback);
+               callback = null;
+
+               return null;
+       }
+
+       [CCode (instance_pos = -1)]
+       private size_t write_callback (void *buffer, size_t size, size_t nmemb) {
+               result.append_len ((string) buffer, (ssize_t) (size * nmemb));
+
+               return size * nmemb;
+       }
+
+       public async unowned string http_get (string _url) {
+               url = _url;
+               callback = http_get.callback;
+               result = new StringBuilder ();
+                try {
+                        Thread.create(download_thread, false);
+                } catch (ThreadError e) {
+                        critical ("Failed to create download thread\n");
+                        return "";
+                }
+
+               yield;
+
+               return result.str;
+       }
+}
index 439c0a3..d8e51a1 100644 (file)
@@ -36,17 +36,28 @@ class GoogleParser : Object {
        public string location;
        string _title;
        PatternSpec pattern;
+       CurlWrapper curlwrapper;
+       Regex re_runtime;
 
        public delegate void ReceiveMovie (GoogleMovie movie);
        public ReceiveMovie _get_callback;
 
-       private Html.Doc* get_html_document (ref char[] buf) {
-               return Html.Doc.read_memory (buf, (int) buf.length,
+       construct {
+               curlwrapper = new CurlWrapper ();
+               try {
+                       re_runtime = new Regex ("([0-9]+)hr ([0-9]+)min");
+               } catch (RegexError e) {
+                       critical ("Failed to initialize regex: %s\n", e.message);
+               }
+       }
+
+       private Html.Doc* get_html_document (string buf) {
+               return Html.Doc.read_memory ((char[]) buf, (int) buf.length,
                                             "http://movies.google.de", null, Html.ParserOption.NOERROR | Html.ParserOption.NOWARNING);
        }
 
-       public int parse (ref char[] buf) throws Error {
-               var doc = get_html_document (ref buf);
+       public int parse (string buf) throws Error {
+               var doc = get_html_document (buf);
                if (doc == null) {
                        stderr.printf ("Error: parsing failed\n");
                        return 0;
@@ -161,9 +172,15 @@ class GoogleParser : Object {
 
        private void parse_movie_info (Xml.Node* i, GoogleMovie movie) {
                var text = i->children;
-               if (text != null && text->name == "text")
+               if (text != null && text->name == "text") {
+                       MatchInfo match;
                        print ("\t\"%s\"\n", text->content);
-                       //      movie.runtime
+                       if (re_runtime.match (text->content, 0, out match)) {
+                               movie.runtime = match.fetch (1).to_int () * 3600 +
+                                               match.fetch (2).to_int () * 60;
+                       }
+                       movie.fsk = text->content.str ("Rated ").replace (" - ", "");
+               }
                for (var n = text->next; n != null; n = n->next) {
                        if (n->name == "nobr") {
                                movie.rating = parse_rating (n);
@@ -181,8 +198,8 @@ class GoogleParser : Object {
                                        if (img->name == "img") {
                                                var alt = img->get_prop ("alt"); // "Rated 0.0 out of 5.0"
                                                if (alt != null && alt != "")    //        ^
-                                                       return (int) (10 * alt.offset (6).to_double ());
                                                        print ("\trating: %s - %f\n", alt, alt.offset (6).to_double ());
+                                                       return (int) (10 * alt.offset (6).to_double ());
                                        }
                                }
                        }
@@ -234,22 +251,8 @@ class GoogleParser : Object {
 
                        stdout.printf ("GET: %s\n", uri);
 
-                       File file = File.new_for_uri (uri);
-                       InputStream stream = yield file.read_async (Priority.DEFAULT_IDLE, null);
-
-                       char[] buf = new char[256*1024];
-                       size_t nread;
-                       size_t total = 0;
-                       while (total < 256*1024) {
-                               nread = yield stream.read_async ((char *)buf + total, 256*1024 - total, Priority.DEFAULT_IDLE, cancellable);
-                               total += nread;
-                               if (cancellable.is_cancelled ())
-                                       return 0;
-                               if (nread == 0)
-                                       break;
-                       }
-                       buf[total] = 0;
-                       return parse (ref buf);
+                       string buf = yield curlwrapper.http_get (uri);
+                       return parse (buf);
                } catch (Error e) {
                        stderr.printf ("Error: %s\n", e.message);
                }