#include "threadedChainImageLoader.h" #include threadedChainImageLoader::threadedChainImageLoader(){ nextID = 0; ofAddListener(ofEvents().update, this, &threadedChainImageLoader::update); ofAddListener(ofURLResponseEvent(),this,&threadedChainImageLoader::urlResponse); startThread(); lastUpdate = 0; } threadedChainImageLoader::~threadedChainImageLoader(){ images_to_load_from_disk.close(); images_to_update.close(); waitForThread(true); ofRemoveListener(ofEvents().update, this, &threadedChainImageLoader::update); ofRemoveListener(ofURLResponseEvent(),this,&threadedChainImageLoader::urlResponse); } // Load an image from disk. //-------------------------------------------------------------- void threadedChainImageLoader::loadFromDisk(chainImage& image, string filename) { nextID++; chainImageLoaderEntry entry(image); entry.filename = filename; entry.image->setUseTexture(false); entry.name = filename; images_to_load_from_disk.send(entry); } // Load an url asynchronously from an url. //-------------------------------------------------------------- void threadedChainImageLoader::loadFromURL(chainImage& image, string url) { nextID++; chainImageLoaderEntry entry(image); entry.url = url; entry.image->setUseTexture(false); entry.name = "image" + ofToString(nextID); images_async_loading[entry.name] = entry; ofLoadURLAsync(entry.url, entry.name); } // Reads from the queue and loads new images. //-------------------------------------------------------------- void threadedChainImageLoader::threadedFunction() { setThreadName("threadedChainImageLoader " + ofToString(thread.get_id())); chainImageLoaderEntry entry; while( images_to_load_from_disk.receive(entry) ) { if(entry.image->tload(entry.filename) ) { ofLogNotice() << "Loaded " << entry.image->filename; images_to_update.send(entry); }else{ ofLogError("threadedChainImageLoader") << "couldn't load file: \"" << entry.filename << "\""; } } ofLogVerbose("threadedChainImageLoader") << "finishing thread on closed queue"; } // When we receive an url response this method is called; // The loaded image is removed from the async_queue and added to the // update queue. The update queue is used to update the texture. //-------------------------------------------------------------- void threadedChainImageLoader::urlResponse(ofHttpResponse & response) { // this happens in the update thread so no need to lock to access // images_async_loading entry_iterator it = images_async_loading.find(response.request.name); if(response.status == 200) { if(it != images_async_loading.end()) { it->second.image->load(response.data); images_to_update.send(it->second); } }else{ // log error. ofLogError("threadedChainImageLoader") << "couldn't load url, response status: " << response.status; ofRemoveURLRequest(response.request.getID()); } // remove the entry from the queue if(it != images_async_loading.end()) { images_async_loading.erase(it); } } // Check the update queue and update the texture //-------------------------------------------------------------- void threadedChainImageLoader::update(ofEventArgs & a){ // Load 1 image per update so we don't block the gl thread for too long chainImageLoaderEntry entry; if (images_to_update.tryReceive(entry)) { entry.image->setupTextures(); } }