Add IMDb CLI downloader to test the IMDb downloader
[cinaest] / src / imdb / imdb-ftp-downloader.vala
1 class IMDbFtpDownloader {
2         Curl.EasyHandle curl;
3         private ZLib.InflateStream strm;
4         private int percent;
5         private char[] buf_out;
6         private uint have;
7         private LineParser parser;
8         private Cancellable cancellable;
9
10         [CCode (instance_pos = -1)]
11         size_t write_callback (void *buffer, size_t size, size_t nmemb) {
12                 if (cancellable != null && cancellable.is_cancelled ())
13                         return 0;
14                 strm.next_in = buffer;
15                 strm.avail_in = (uint) (size * nmemb);
16                 if (strm.avail_in == 0)
17                         return 0;
18
19                 do {
20                         strm.next_out = (char*) buf_out + have;
21                         strm.avail_out = buf_out.length - have;
22
23                         char* p = (char*) buf_out;
24
25                         var ret = strm.inflate (ZLib.Flush.NO_FLUSH);
26                         assert (ret != ZLib.Status.STREAM_ERROR);
27                         if (ret == ZLib.Status.NEED_DICT)
28                                 ret = ZLib.Status.DATA_ERROR;
29                         switch (ret) {
30                         case ZLib.Status.DATA_ERROR:
31                         case ZLib.Status.MEM_ERROR:
32                                 return ret;
33                         }
34
35                         have = buf_out.length - strm.avail_out;
36
37                         char* l = p;
38                         int j = 0;
39                         for (int i = 0; i < have; i++, j++) {
40                                 if (p[i] == '\n') {
41                                         p[i] = 0;
42                                         if (parser != null)
43                                                 parser.parse_line ((string) l);
44                                         j = -1;
45                                         l = p + i + 1;
46                                 }
47                         }
48                         if (j > 0) {
49                                 Memory.copy (p, l, j);
50                                 have = j;
51                         } else {
52                                 have = 0;
53                         }
54                 } while (strm.avail_out == 0);
55
56                 return size * nmemb;
57         }
58
59         int progress_callback (double dltotal, double dlnow, double ultotal, double ulnow) {
60                 if (cancellable != null && cancellable.is_cancelled ())
61                         return 1;
62                 if (dltotal > 0) {
63                         int p = (int) (100 * dlnow / dltotal);
64                         if (p > percent) {
65                                 percent = p;
66                                 progress_changed (p);
67                         }
68                 }
69                 return 0;
70         }
71
72         public IMDbFtpDownloader (Cancellable? _cancellable) {
73                 cancellable = _cancellable;
74                 curl = new Curl.EasyHandle ();
75                 curl.setopt (Curl.Option.WRITEFUNCTION, write_callback);
76                 curl.setopt (Curl.Option.WRITEDATA, this);
77                 curl.setopt (Curl.Option.NOPROGRESS, 0L);
78                 curl.setopt (Curl.Option.PROGRESSFUNCTION, progress_callback);
79                 curl.setopt (Curl.Option.PROGRESSDATA, this);
80                 buf_out = new char[16384];
81         }
82
83         public void download (string url, LineParser? _parser) throws IOError {
84                 curl.setopt (Curl.Option.URL, url);
85                 percent = 0;
86                 parser = _parser;
87                 have = 0;
88
89                 strm = ZLib.InflateStream.full (15 | 32);
90
91                 var res = curl.perform ();
92                 if (Curl.Code.ABORTED_BY_CALLBACK == res) {
93                                 throw new IOError.CANCELLED ("Download cancelled.");
94                 }
95         }
96
97         public signal void progress_changed (int percent);
98 }