www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Does std.net.curl: download have support for callbacks?

reply adnan338 <relay.dev.adnan protonmail.com> writes:
I would like to set a callback for the `download()` function but 
I do not seem to find a way to add a callback to the procedure.

Let's say, for example I have a GtkD Widget called "pb" (short 
for progressBar).

I want to download a file from a url and when done, I want a 
callback to access pb and increase by a certain number.

The GtkD progress bar API:
https://api.gtkd.org/gtk.ProgressBar.ProgressBar.setFraction.html

Normally, If it was dependent on a button, I would do something 
like:

     auto pb = new ProgressBar();
     auto more = new Button("go-next", GtkIconSize.BUTTON);
     more.addOnClicked(delegate void(Button _) {
         if (activityMode.getActive()) // ignore this if condition
             pb.pulse;
         else
             pb.setFraction(pb.getFraction + pb.getPulseStep);
     });

But how can I do this with `download()`?
Jun 10 2020
next sibling parent reply adnan338 <relay.dev.adnan protonmail.com> writes:
On Thursday, 11 June 2020 at 06:05:09 UTC, adnan338 wrote:
 I would like to set a callback for the `download()` function 
 but I do not seem to find a way to add a callback to the 
 procedure.

 [...]
I have also been told that Gtk is not thread safe. What does this mean and does it effect me on this scenario?
Jun 10 2020
next sibling parent Cogitri <oss cogitri.dev> writes:
On Thursday, 11 June 2020 at 06:13:59 UTC, adnan338 wrote:
 On Thursday, 11 June 2020 at 06:05:09 UTC, adnan338 wrote:
 I would like to set a callback for the `download()` function 
 but I do not seem to find a way to add a callback to the 
 procedure.

 [...]
I have also been told that Gtk is not thread safe. What does this mean and does it effect me on this scenario?
That means that you must not access GTK objects from anything but your mainthread, so e.g. spawning a new thread to listen for progress on the curl request and updating the thread directly from there wont work. You could use glib.Idle or glib.Timeout to listen for updates in your mainthread without blocking it. In case you need to do something heavier (e.g. decode a big response) you probably want to do that in a separate thread to not block your mainthread (and as such make your UI unresponsive while the decoding blocks the thread). In that case I'd recommend using message passing, meaning that you spawn a separate thread, do your decoding there and then send the result back to your mainthread and manipulate the GTK widget there.
Jun 11 2020
prev sibling parent reply dangbinghoo <dangbinghoo google-mail.com> writes:
On Thursday, 11 June 2020 at 06:13:59 UTC, adnan338 wrote:
 On Thursday, 11 June 2020 at 06:05:09 UTC, adnan338 wrote:
 I would like to set a callback for the `download()` function 
 but I do not seem to find a way to add a callback to the 
 procedure.

 [...]
I have also been told that Gtk is not thread safe. What does this mean and does it effect me on this scenario?
Don't worry, almost ALL GUI FRAMEWORK in the world IS NOT THREAD SAFE, the wellknow Qt and Gtk, and even morden Android and the java Swing. ---- binghoo dang
Jun 17 2020
parent IGotD- <nise nise.com> writes:
On Thursday, 18 June 2020 at 01:15:00 UTC, dangbinghoo wrote:
 Don't worry, almost ALL GUI FRAMEWORK in the world IS NOT 
 THREAD SAFE, the wellknow Qt and Gtk, and even morden Android 
 and the java Swing.


 ----
 binghoo dang
You can certainly download in another thread in Qt. However, you are only allowed to have the widget classes in the main thread. Qt is a large library that also spans non-GUI functionality and these can often be moved to separate threads, IO for example. In this case you could download in a separate thread, then send signals to the progress bar object to update it. Is it possible to implement a similar approach in Gtk?
Jun 21 2020
prev sibling parent evilrat <evilrat666 gmail.com> writes:
On Thursday, 11 June 2020 at 06:05:09 UTC, adnan338 wrote:
 I would like to set a callback for the `download()` function 
 but I do not seem to find a way to add a callback to the 
 procedure.

 Let's say, for example I have a GtkD Widget called "pb" (short 
 for progressBar).

 I want to download a file from a url and when done, I want a 
 callback to access pb and increase by a certain number.

 The GtkD progress bar API:
 https://api.gtkd.org/gtk.ProgressBar.ProgressBar.setFraction.html

 Normally, If it was dependent on a button, I would do something 
 like:

     auto pb = new ProgressBar();
     auto more = new Button("go-next", GtkIconSize.BUTTON);
     more.addOnClicked(delegate void(Button _) {
         if (activityMode.getActive()) // ignore this if 
 condition
             pb.pulse;
         else
             pb.setFraction(pb.getFraction + pb.getPulseStep);
     });

 But how can I do this with `download()`?
From the docs on download() method it has an optional connection reference https://dlang.org/phobos/std_net_curl.html#.download And connection has onProgress callback, you can add some global variable and update it using this callback. Now of course another problem left up to you, not thread safe means you should expect the worst if you try to use the library from multiple threads, this is especially true for UI libraries as some OS implies some restrictions on UI interactions as well. So you need to find relevant mechanism to do a event loop scheduling and update progress bar using it by feeding the values from somewhere else. See https://dlang.org/phobos/std_net_curl.html#.HTTP under "Tracking progress: " example. It turns out you might not need to use download() at all. Pseudocode: // some global vars to track it size_t bytesTotal; size_t bytesReceived; // in your downloader thread auto http = HTTP(); http.method = HTTP.Method.get; http.url = "http://upload.wikimedia.org/wikipedia/commons/" ~ "5/53/Wikipedia-logo-en-big.png"; http.onReceive = (ubyte[] data) { bytesTotal = 0; bytesReceived = 0; return data.length; }; http.onProgress = (size_t dltotal, size_t dlnow, size_t ultotal, size_t ulnow) { bytesTotal = dltotal; bytesReceived = dlnow; return 0; }; // somewhere in GTK do something like this, it is up to you to find out how to do this void check_dl_status() { // here we are using globals that updates on another thread auto progressPct = bytesTotal / bytesReceived; progresBar.setPercent (progressPct); if (progressPct < 1) event.publish (check_dl_status); }
Jun 11 2020