From 756988534be7c3fb64a439a68a2e27eda2797ff5 Mon Sep 17 00:00:00 2001 From: arturo Date: Tue, 7 May 2013 14:34:44 +0200 Subject: [PATCH 1/4] urlFileDownloader: progress event + example (cherry picked from commit 6aae0f53ad46d02e6c71c6b6ca33818639d64b1b) --- .../urlFileLoaderExample/bin/data/.gitkeep | 1 + .../utils/urlFileLoaderExample/src/main.cpp | 16 +++ .../urlFileLoaderExample/src/testApp.cpp | 98 +++++++++++++++++++ .../utils/urlFileLoaderExample/src/testApp.h | 29 ++++++ 4 files changed, 144 insertions(+) create mode 100644 examples/utils/urlFileLoaderExample/bin/data/.gitkeep create mode 100644 examples/utils/urlFileLoaderExample/src/main.cpp create mode 100644 examples/utils/urlFileLoaderExample/src/testApp.cpp create mode 100644 examples/utils/urlFileLoaderExample/src/testApp.h diff --git a/examples/utils/urlFileLoaderExample/bin/data/.gitkeep b/examples/utils/urlFileLoaderExample/bin/data/.gitkeep new file mode 100644 index 000000000000..e28f0318d12b --- /dev/null +++ b/examples/utils/urlFileLoaderExample/bin/data/.gitkeep @@ -0,0 +1 @@ +kepp folder in git diff --git a/examples/utils/urlFileLoaderExample/src/main.cpp b/examples/utils/urlFileLoaderExample/src/main.cpp new file mode 100644 index 000000000000..6a32c6ae8bc8 --- /dev/null +++ b/examples/utils/urlFileLoaderExample/src/main.cpp @@ -0,0 +1,16 @@ +#include "ofMain.h" +#include "testApp.h" +#include "ofAppGlutWindow.h" + +//======================================================================== +int main( ){ + + ofAppGlutWindow window; + ofSetupOpenGL(&window, 1024,768, OF_WINDOW); // <-------- setup the GL context + + // this kicks off the running of my app + // can be OF_WINDOW or OF_FULLSCREEN + // pass in width and height too: + ofRunApp( new testApp()); + +} diff --git a/examples/utils/urlFileLoaderExample/src/testApp.cpp b/examples/utils/urlFileLoaderExample/src/testApp.cpp new file mode 100644 index 000000000000..9364c381f568 --- /dev/null +++ b/examples/utils/urlFileLoaderExample/src/testApp.cpp @@ -0,0 +1,98 @@ +#include "testApp.h" + +//-------------------------------------------------------------- +void testApp::setup(){ + progress = 0; + done = false; + + // synchronous loading + html = ofLoadURL("http://www.openframeworks.cc").data; + + // add listeners + asynchronous saving to disk + ofAddListener(ofURLProgressEvent(),this,&testApp::onProgress); + ofAddListener(ofURLResponseEvent(),this,&testApp::onFinished); + ofSaveURLAsync("http://www.openframeworks.cc/ofvideo.mov","ofvideo.mov"); +} + + +//-------------------------------------------------------------- +void testApp::onProgress(ofHttpResponse & response){ + progress = response.getProgressPct(); +} + +//-------------------------------------------------------------- +void testApp::onFinished(ofHttpResponse & response){ + done = true; + video.loadMovie(response.request.name); + video.play(); +} + +//-------------------------------------------------------------- +void testApp::update(){ + if(done) video.update(); +} + +//-------------------------------------------------------------- +void testApp::draw(){ + if(!done){ + if(progress>-1){ + ofNoFill(); + ofRect(20,20,100,20); + ofFill(); + ofRect(20,20,progress*100,20); + }else{ + ofDrawBitmapString("can't retrieve full size of download, downloading...", 20,20); + } + }else{ + ofDrawBitmapString("downloaded!", 20,20); + video.draw(20,40); + } + + + ofDrawBitmapString(html, 500,20); +} + +//-------------------------------------------------------------- +void testApp::keyPressed(int key){ + +} + +//-------------------------------------------------------------- +void testApp::keyReleased(int key){ + +} + +//-------------------------------------------------------------- +void testApp::mouseMoved(int x, int y ){ + +} + +//-------------------------------------------------------------- +void testApp::mouseDragged(int x, int y, int button){ + +} + +//-------------------------------------------------------------- +void testApp::mousePressed(int x, int y, int button){ + +} + +//-------------------------------------------------------------- +void testApp::mouseReleased(int x, int y, int button){ + +} + +//-------------------------------------------------------------- +void testApp::windowResized(int w, int h){ + +} + +//-------------------------------------------------------------- +void testApp::gotMessage(ofMessage msg){ + +} + +//-------------------------------------------------------------- +void testApp::dragEvent(ofDragInfo dragInfo){ + +} diff --git a/examples/utils/urlFileLoaderExample/src/testApp.h b/examples/utils/urlFileLoaderExample/src/testApp.h new file mode 100644 index 000000000000..b9d7eb6ed4f1 --- /dev/null +++ b/examples/utils/urlFileLoaderExample/src/testApp.h @@ -0,0 +1,29 @@ +#pragma once + +#include "ofMain.h" + +class testApp : public ofBaseApp{ + + public: + void setup(); + void update(); + void draw(); + + void keyPressed (int key); + void keyReleased(int key); + void mouseMoved(int x, int y ); + void mouseDragged(int x, int y, int button); + void mousePressed(int x, int y, int button); + void mouseReleased(int x, int y, int button); + void windowResized(int w, int h); + void dragEvent(ofDragInfo dragInfo); + void gotMessage(ofMessage msg); + + void onProgress(ofHttpResponse & response); + void onFinished(ofHttpResponse & response); + + float progress; + bool done; + string html; + ofVideoPlayer video; +}; From 49c02b44d40aa760bccea10b9c7a89027a179ffd Mon Sep 17 00:00:00 2001 From: Dan Rosser Date: Fri, 14 Aug 2026 03:37:14 +1000 Subject: [PATCH 2/4] Modernize URL transfer progress support --- .../utils/urlFileLoaderExample/src/main.cpp | 21 ++-- .../utils/urlFileLoaderExample/src/ofApp.cpp | 36 +++++++ .../utils/urlFileLoaderExample/src/ofApp.h | 17 ++++ .../urlFileLoaderExample/src/testApp.cpp | 98 ------------------- .../utils/urlFileLoaderExample/src/testApp.h | 29 ------ libs/openFrameworks/utils/ofURLFileLoader.cpp | 24 ++--- libs/openFrameworks/utils/ofURLFileLoader.h | 6 +- 7 files changed, 76 insertions(+), 155 deletions(-) create mode 100644 examples/utils/urlFileLoaderExample/src/ofApp.cpp create mode 100644 examples/utils/urlFileLoaderExample/src/ofApp.h delete mode 100644 examples/utils/urlFileLoaderExample/src/testApp.cpp delete mode 100644 examples/utils/urlFileLoaderExample/src/testApp.h diff --git a/examples/utils/urlFileLoaderExample/src/main.cpp b/examples/utils/urlFileLoaderExample/src/main.cpp index 6a32c6ae8bc8..946adb5c4081 100644 --- a/examples/utils/urlFileLoaderExample/src/main.cpp +++ b/examples/utils/urlFileLoaderExample/src/main.cpp @@ -1,16 +1,13 @@ #include "ofMain.h" -#include "testApp.h" -#include "ofAppGlutWindow.h" +#include "ofApp.h" //======================================================================== -int main( ){ - - ofAppGlutWindow window; - ofSetupOpenGL(&window, 1024,768, OF_WINDOW); // <-------- setup the GL context - - // this kicks off the running of my app - // can be OF_WINDOW or OF_FULLSCREEN - // pass in width and height too: - ofRunApp( new testApp()); - +int main() { + ofGLWindowSettings settings; + settings.setSize(720, 240); + settings.windowMode = OF_WINDOW; + + auto window = ofCreateWindow(settings); + ofRunApp(window, std::make_shared()); + ofRunMainLoop(); } diff --git a/examples/utils/urlFileLoaderExample/src/ofApp.cpp b/examples/utils/urlFileLoaderExample/src/ofApp.cpp new file mode 100644 index 000000000000..f95e6a8ad41e --- /dev/null +++ b/examples/utils/urlFileLoaderExample/src/ofApp.cpp @@ -0,0 +1,36 @@ +#include "ofApp.h" + +//-------------------------------------------------------------- +void ofApp::setup() { + ofSetWindowTitle("URL file loader progress"); + ofSetBackgroundColor(30); + + const std::string url = "https://github.com/openframeworks/openFrameworks/archive/refs/heads/master.zip"; + ofHttpRequest request(url, ofToDataPath("openFrameworks-master.zip"), true); + request.progressCallback = [this](const ofHttpRequest &, float value) { + progress.store(value); + }; + request.done = [this](const ofHttpResponse & response) { + status = response.status; + finished = true; + }; + loader.handleRequestAsync(request); +} + +//-------------------------------------------------------------- +void ofApp::draw() { + const float value = progress.load(); + const float width = ofGetWidth() - 80.0f; + + ofSetColor(90); + ofDrawRectangle(40, 100, width, 24); + ofSetColor(70, 180, 255); + ofDrawRectangle(40, 100, width * value, 24); + + ofSetColor(255); + ofDrawBitmapString("Downloading openFrameworks-master.zip", 40, 70); + ofDrawBitmapString(ofToString(value * 100.0f, 1) + "%", 40, 150); + if (finished) { + ofDrawBitmapString("Finished with HTTP status " + ofToString(status), 40, 185); + } +} diff --git a/examples/utils/urlFileLoaderExample/src/ofApp.h b/examples/utils/urlFileLoaderExample/src/ofApp.h new file mode 100644 index 000000000000..ba076b26a901 --- /dev/null +++ b/examples/utils/urlFileLoaderExample/src/ofApp.h @@ -0,0 +1,17 @@ +#pragma once + +#include "ofMain.h" + +#include + +class ofApp : public ofBaseApp { +public: + void setup() override; + void draw() override; + +private: + ofURLFileLoader loader; + std::atomic progress{ 0.0f }; + bool finished = false; + int status = 0; +}; diff --git a/examples/utils/urlFileLoaderExample/src/testApp.cpp b/examples/utils/urlFileLoaderExample/src/testApp.cpp deleted file mode 100644 index 9364c381f568..000000000000 --- a/examples/utils/urlFileLoaderExample/src/testApp.cpp +++ /dev/null @@ -1,98 +0,0 @@ -#include "testApp.h" - -//-------------------------------------------------------------- -void testApp::setup(){ - progress = 0; - done = false; - - // synchronous loading - html = ofLoadURL("http://www.openframeworks.cc").data; - - // add listeners + asynchronous saving to disk - ofAddListener(ofURLProgressEvent(),this,&testApp::onProgress); - ofAddListener(ofURLResponseEvent(),this,&testApp::onFinished); - ofSaveURLAsync("http://www.openframeworks.cc/ofvideo.mov","ofvideo.mov"); -} - - -//-------------------------------------------------------------- -void testApp::onProgress(ofHttpResponse & response){ - progress = response.getProgressPct(); -} - -//-------------------------------------------------------------- -void testApp::onFinished(ofHttpResponse & response){ - done = true; - video.loadMovie(response.request.name); - video.play(); -} - -//-------------------------------------------------------------- -void testApp::update(){ - if(done) video.update(); -} - -//-------------------------------------------------------------- -void testApp::draw(){ - if(!done){ - if(progress>-1){ - ofNoFill(); - ofRect(20,20,100,20); - ofFill(); - ofRect(20,20,progress*100,20); - }else{ - ofDrawBitmapString("can't retrieve full size of download, downloading...", 20,20); - } - }else{ - ofDrawBitmapString("downloaded!", 20,20); - video.draw(20,40); - } - - - ofDrawBitmapString(html, 500,20); -} - -//-------------------------------------------------------------- -void testApp::keyPressed(int key){ - -} - -//-------------------------------------------------------------- -void testApp::keyReleased(int key){ - -} - -//-------------------------------------------------------------- -void testApp::mouseMoved(int x, int y ){ - -} - -//-------------------------------------------------------------- -void testApp::mouseDragged(int x, int y, int button){ - -} - -//-------------------------------------------------------------- -void testApp::mousePressed(int x, int y, int button){ - -} - -//-------------------------------------------------------------- -void testApp::mouseReleased(int x, int y, int button){ - -} - -//-------------------------------------------------------------- -void testApp::windowResized(int w, int h){ - -} - -//-------------------------------------------------------------- -void testApp::gotMessage(ofMessage msg){ - -} - -//-------------------------------------------------------------- -void testApp::dragEvent(ofDragInfo dragInfo){ - -} diff --git a/examples/utils/urlFileLoaderExample/src/testApp.h b/examples/utils/urlFileLoaderExample/src/testApp.h deleted file mode 100644 index b9d7eb6ed4f1..000000000000 --- a/examples/utils/urlFileLoaderExample/src/testApp.h +++ /dev/null @@ -1,29 +0,0 @@ -#pragma once - -#include "ofMain.h" - -class testApp : public ofBaseApp{ - - public: - void setup(); - void update(); - void draw(); - - void keyPressed (int key); - void keyReleased(int key); - void mouseMoved(int x, int y ); - void mouseDragged(int x, int y, int button); - void mousePressed(int x, int y, int button); - void mouseReleased(int x, int y, int button); - void windowResized(int w, int h); - void dragEvent(ofDragInfo dragInfo); - void gotMessage(ofMessage msg); - - void onProgress(ofHttpResponse & response); - void onFinished(ofHttpResponse & response); - - float progress; - bool done; - string html; - ofVideoPlayer video; -}; diff --git a/libs/openFrameworks/utils/ofURLFileLoader.cpp b/libs/openFrameworks/utils/ofURLFileLoader.cpp index b35893abe832..297aafc40f2f 100644 --- a/libs/openFrameworks/utils/ofURLFileLoader.cpp +++ b/libs/openFrameworks/utils/ofURLFileLoader.cpp @@ -348,18 +348,12 @@ size_t readBody_cb(void * ptr, size_t size, size_t nmemb, void * userdata) { } return 0; /* no more data left to deliver */ } -int progress_cb(void* ptr, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow) { - auto & request = *static_cast(ptr); - if (request.progressCallback) { - float progress = 0.0f; - if (request.method == ofHttpRequest::GET && dltotal > 0) { - progress = (float)dlnow / (float)dltotal; - // note: we may want to support upload and download for POST - } else if ((request.method == ofHttpRequest::PUT || request.method == ofHttpRequest::POST) && ultotal > 0) { - progress = (float)ulnow / (float)ultotal; - } - - request.progressCallback(request, progress); +int transferProgress_cb(void * userdata, curl_off_t downloadTotal, curl_off_t downloaded, curl_off_t uploadTotal, curl_off_t uploaded) { + const auto & request = *static_cast(userdata); + if (request.method == ofHttpRequest::GET && downloadTotal > 0) { + request.progressCallback(request, static_cast(downloaded) / static_cast(downloadTotal)); + } else if ((request.method == ofHttpRequest::PUT || request.method == ofHttpRequest::POST) && uploadTotal > 0) { + request.progressCallback(request, static_cast(uploaded) / static_cast(uploadTotal)); } return 0; } @@ -536,13 +530,13 @@ ofHttpResponse ofURLFileLoaderImpl::handleRequest(const ofHttpRequest & request) // start request and receive response ofHttpResponse response(request, 0, ""); CURLcode err = CURLE_OK; - + if (request.progressCallback) { - curl_easy_setopt(curl.get(), CURLOPT_XFERINFOFUNCTION, progress_cb); + curl_easy_setopt(curl.get(), CURLOPT_XFERINFOFUNCTION, transferProgress_cb); curl_easy_setopt(curl.get(), CURLOPT_XFERINFODATA, &request); curl_easy_setopt(curl.get(), CURLOPT_NOPROGRESS, 0L); } - + if (request.saveTo) { ofFile saveTo(request.name, ofFile::WriteOnly, true); curl_easy_setopt(curl.get(), CURLOPT_WRITEDATA, &saveTo); diff --git a/libs/openFrameworks/utils/ofURLFileLoader.h b/libs/openFrameworks/utils/ofURLFileLoader.h index e32b2786ec87..bddad3437dea 100644 --- a/libs/openFrameworks/utils/ofURLFileLoader.h +++ b/libs/openFrameworks/utils/ofURLFileLoader.h @@ -23,7 +23,11 @@ class ofHttpRequest { std::string body; ///< POST body data std::string contentType; ///< POST data mime type std::function done; - std::function progressCallback = nullptr; ///< pass a function for progress of download + /// Called with transfer progress in the range [0, 1] when the total size is known. + /// For GET requests this reports download progress; for POST and PUT requests + /// it reports upload progress. Asynchronous requests invoke this callback from + /// the URL loader's worker thread. + std::function progressCallback; size_t timeoutSeconds = 0; bool headerOnly = false; From 681459a9789096800268d65dab1503c25ebf5059 Mon Sep 17 00:00:00 2001 From: Dan Rosser Date: Fri, 14 Aug 2026 03:53:23 +1000 Subject: [PATCH 3/4] Update for https://github.com/openframeworks/openFrameworks/pull/2043 urlFileLoader example --- .gitignore | 1 + examples/utils/urlFileLoaderExample/bin/data/.gitkeep | 1 - examples/utils/urlFileLoaderExample/src/ofApp.cpp | 6 +++--- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.gitignore b/.gitignore index c000a5911a5b..55a4eb0e31b3 100644 --- a/.gitignore +++ b/.gitignore @@ -194,3 +194,4 @@ scripts/templates/vs2019/emptyExample.vcxproj.user libs/openFrameworksCompiled/project/android/build-*/ +examples/utils/urlFileLoaderExample/bin/data diff --git a/examples/utils/urlFileLoaderExample/bin/data/.gitkeep b/examples/utils/urlFileLoaderExample/bin/data/.gitkeep index e28f0318d12b..e69de29bb2d1 100644 --- a/examples/utils/urlFileLoaderExample/bin/data/.gitkeep +++ b/examples/utils/urlFileLoaderExample/bin/data/.gitkeep @@ -1 +0,0 @@ -kepp folder in git diff --git a/examples/utils/urlFileLoaderExample/src/ofApp.cpp b/examples/utils/urlFileLoaderExample/src/ofApp.cpp index f95e6a8ad41e..29a19dae318f 100644 --- a/examples/utils/urlFileLoaderExample/src/ofApp.cpp +++ b/examples/utils/urlFileLoaderExample/src/ofApp.cpp @@ -5,8 +5,8 @@ void ofApp::setup() { ofSetWindowTitle("URL file loader progress"); ofSetBackgroundColor(30); - const std::string url = "https://github.com/openframeworks/openFrameworks/archive/refs/heads/master.zip"; - ofHttpRequest request(url, ofToDataPath("openFrameworks-master.zip"), true); + const std::string url = "https://raw.githubusercontent.com/openframeworks/openFrameworks/master/examples/graphics/fontShapesExample/bin/data/Batang.ttf"; + ofHttpRequest request(url, ofToDataPath("Batang.ttf"), true); request.progressCallback = [this](const ofHttpRequest &, float value) { progress.store(value); }; @@ -28,7 +28,7 @@ void ofApp::draw() { ofDrawRectangle(40, 100, width * value, 24); ofSetColor(255); - ofDrawBitmapString("Downloading openFrameworks-master.zip", 40, 70); + ofDrawBitmapString("Downloading Batang.ttf", 40, 70); ofDrawBitmapString(ofToString(value * 100.0f, 1) + "%", 40, 150); if (finished) { ofDrawBitmapString("Finished with HTTP status " + ofToString(status), 40, 185); From 92bce5c53e3deaaec41c76fa7ffdd4cbc360708d Mon Sep 17 00:00:00 2001 From: Dan Rosser Date: Fri, 14 Aug 2026 04:07:51 +1000 Subject: [PATCH 4/4] Refactor progressCallback initialization and comments Initialized progressCallback to nullptr and updated comments for clarity. --- libs/openFrameworks/utils/ofURLFileLoader.h | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/libs/openFrameworks/utils/ofURLFileLoader.h b/libs/openFrameworks/utils/ofURLFileLoader.h index bddad3437dea..0e637acdf3a5 100644 --- a/libs/openFrameworks/utils/ofURLFileLoader.h +++ b/libs/openFrameworks/utils/ofURLFileLoader.h @@ -23,11 +23,8 @@ class ofHttpRequest { std::string body; ///< POST body data std::string contentType; ///< POST data mime type std::function done; - /// Called with transfer progress in the range [0, 1] when the total size is known. - /// For GET requests this reports download progress; for POST and PUT requests - /// it reports upload progress. Asynchronous requests invoke this callback from - /// the URL loader's worker thread. - std::function progressCallback; + /// the URL loader's worker thread. range [0, 1] + std::function progressCallback = nullptr; // it reports upload/download progress. Asynchronous requests invoke this callback size_t timeoutSeconds = 0; bool headerOnly = false;