diff --git a/libcore/MovieLoader.cpp b/libcore/MovieLoader.cpp index e9f816e..d0ff6f6 100644 --- a/libcore/MovieLoader.cpp +++ b/libcore/MovieLoader.cpp @@ -346,6 +346,20 @@ MovieLoader::processCompletedRequests() boost::mutex::scoped_lock requestsLock(_requestsMutex); + // Start or wake up the loader thread + if (!_thread.get()) { + _killed=false; + _thread.reset(new boost::thread(boost::bind( + &MovieLoader::processRequests, this))); + _barrier.wait(); // let execution start before proceeding + continue; + } + else { + log_debug("processCompletedRequests: waking up existing thread"); + _wakeup.notify_all(); + } + + #ifdef GNASH_DEBUG_LOCKING log_debug("processCompletedRequests: lock on requests: obtained"); #endif @@ -450,18 +464,6 @@ MovieLoader::loadMovie(const std::string& urlstr, new Request(url, target, postdata, handler) ); - // Start or wake up the loader thread - if (!_thread.get()) { - _killed=false; - _thread.reset(new boost::thread(boost::bind( - &MovieLoader::processRequests, this))); - _barrier.wait(); // let execution start before proceeding - } - else { - log_debug("loadMovie: waking up existing thread"); - _wakeup.notify_all(); - } - #ifdef GNASH_DEBUG_LOCKING log_debug("loadMovie: lock on requests: release"); #endif diff --git a/libcore/SWFMovie.cpp b/libcore/SWFMovie.cpp index e97a540..39ba448 100644 --- a/libcore/SWFMovie.cpp +++ b/libcore/SWFMovie.cpp @@ -56,6 +56,8 @@ SWFMovie::construct(as_object* /*init*/) ); } + _def->ensure_bytes_loaded(std::min(65535, _def->get_bytes_total())); + // Invoke parent placement event handler MovieClip::construct(); } diff --git a/libcore/parser/SWFMovieDefinition.cpp b/libcore/parser/SWFMovieDefinition.cpp index beebe69..170068c 100644 --- a/libcore/parser/SWFMovieDefinition.cpp +++ b/libcore/parser/SWFMovieDefinition.cpp @@ -155,6 +155,7 @@ SWFMovieDefinition::SWFMovieDefinition(const RunResources& runResources) _frames_loaded(0u), _waiting_for_frame(0), _bytes_loaded(0), + _waiting_for_bytes(0), m_loading_sound_stream(-1), m_file_length(0), m_jpeg_in(0), @@ -394,6 +395,28 @@ SWFMovieDefinition::ensure_frame_loaded(size_t framenum) const return ( framenum <= _frames_loaded ); } +bool +SWFMovieDefinition::ensure_bytes_loaded(size_t numbytes) const +{ + boost::mutex::scoped_lock lock(_bytes_loaded_mutex); + +#ifndef LOAD_MOVIES_IN_A_SEPARATE_THREAD + return ( numbytes <= _bytes_loaded ); +#endif + + if ( numbytes <= _bytes_loaded ) return true; + + // TODO: verify the parser is still alive before waiting + // on a condition that will otherwise never arrive. + + _waiting_for_bytes = numbytes; + + // TODO: return false on timeout + _bytes_reached_condition.wait(lock); + + return ( numbytes <= _bytes_loaded ); +} + Movie* SWFMovieDefinition::createMovie(Global_as& gl, DisplayObject* parent) { @@ -516,6 +539,12 @@ SWFMovieDefinition::read_all_swf() // Notify any thread waiting on frame reached condition _frame_reached_condition.notify_all(); } + + // Notify any thread waiting on bytes loaded condition + { + boost::mutex::scoped_lock lock(_bytes_loaded_mutex); + _bytes_reached_condition.notify_all(); + } } size_t @@ -559,6 +588,22 @@ SWFMovieDefinition::incrementLoadedFrames() } void +SWFMovieDefinition:: setBytesLoaded(unsigned long bytes) +{ + boost::mutex::scoped_lock lock(_bytes_loaded_mutex); + _bytes_loaded=bytes; + + // signal load of bytes if anyone requested it + if (_waiting_for_bytes && _bytes_loaded >= _waiting_for_bytes ) + { + // or should we notify_one ? + // See: http://boost.org/doc/html/condition.html + _bytes_reached_condition.notify_all(); + } + +} + +void SWFMovieDefinition::registerExport(const std::string& symbol, boost::uint16_t id) { diff --git a/libcore/parser/SWFMovieDefinition.h b/libcore/parser/SWFMovieDefinition.h index 94f85e8..d61854e 100644 --- a/libcore/parser/SWFMovieDefinition.h +++ b/libcore/parser/SWFMovieDefinition.h @@ -338,6 +338,11 @@ public: /// has been loaded (load on demand). bool ensure_frame_loaded(size_t framenum) const; + /// \brief + /// Ensure that the given number of bytes + /// has been loaded (load on demand). + bool ensure_bytes_loaded(size_t numbytes) const; + /// Read and parse all the SWF stream (blocking until load is finished) // /// This function uses a private TagLoadersTable @@ -481,6 +486,15 @@ private: /// thread will read it. mutable boost::mutex _bytes_loaded_mutex; + /// A semaphore to signal load of a minimum number of bytes + mutable boost::condition _bytes_reached_condition; + + /// Set this to trigger signaling of reached amount of bytes loaded + // + /// Make sure you locked _bytes_loaded_mutex + /// when accessing this member ! + mutable size_t _waiting_for_bytes; + int m_loading_sound_stream; boost::uint32_t m_file_length; @@ -512,11 +526,7 @@ private: /// Set number of bytes loaded from input stream // /// NOTE: this method locks _bytes_loaded_mutex - void setBytesLoaded(unsigned long bytes) - { - boost::mutex::scoped_lock lock(_bytes_loaded_mutex); - _bytes_loaded=bytes; - } + void setBytesLoaded(unsigned long bytes); /// A flag set to true when load cancellation is requested bool _loadingCanceled; diff --git a/testsuite/misc-mtasc.all/level5.as b/testsuite/misc-mtasc.all/level5.as index 2cc2ee7..2241fe5 100644 --- a/testsuite/misc-mtasc.all/level5.as +++ b/testsuite/misc-mtasc.all/level5.as @@ -25,62 +25,62 @@ class Level5 { - static function main(mc) - { - check_equals(mc._currentframe, 1); + static function main(mc) + { + check_equals(mc._currentframe, 1); - check(_level0.frameno >= 1); + check(_level0.frameno >= 1); - // Check our depth - check_equals(mc.getDepth(), -16379); + // Check our depth + check_equals(mc.getDepth(), -16379); - // The ""+ is there to force conversion to a string - check_equals(""+mc, "_level5"); + // The ""+ is there to force conversion to a string + check_equals(""+mc, "_level5"); - // Mc level is _level0 ? why ? - check_equals(mc._level, _level0); + // Mc level is _level0 ? why ? + check_equals(mc._level, _level0); - // check that we can acess back to _level0 - check_equals(_level0.testvar, 1239); + // check that we can acess back to _level0 + check_equals(_level0.testvar, 1239); - // check that we can modify vars on our own level - check_equals(_level5.testvar, undefined); - _level5.testvar = 6789; - check_equals(_level5.testvar, 6789); + // check that we can modify vars on our own level + check_equals(_level5.testvar, undefined); + _level5.testvar = 6789; + check_equals(_level5.testvar, 6789); - // check that we can modify vars on _level0 - check_equals(_level0.testvar2, undefined); - _level0.testvar2 = true; - check_equals(_level0.testvar2, true); + // check that we can modify vars on _level0 + check_equals(_level0.testvar2, undefined); + _level0.testvar2 = true; + check_equals(_level0.testvar2, true); - _level5.onUnload = function() - { - check(false); // should not be executed - note("Unloading "+this); - } + _level5.onUnload = function() + { + check(false); // should not be executed + note("Unloading "+this); + } - mc.createEmptyMovieClip("ch", 1); - with(mc.ch) - { - lineStyle(1, 0x00000); - beginFill(0xFF0000, 80); - var x=200; - var y=200; - var width=100; - var height=100; - moveTo(x, y); - lineTo(x+width, y); - lineTo(x+width, y+height); - lineTo(x, y+height); - lineTo(x, y); - endFill(); - }; + mc.createEmptyMovieClip("ch", 1); + with(mc.ch) + { + lineStyle(1, 0x00000); + beginFill(0xFF0000, 80); + var x=200; + var y=200; + var width=100; + var height=100; + moveTo(x, y); + lineTo(x+width, y); + lineTo(x+width, y+height); + lineTo(x, y+height); + lineTo(x, y); + endFill(); + }; - check_equals(mc.ch._target, "_level5/ch"); + check_equals(mc.ch._target, "_level5/ch"); - // load yet another swf - getURL("level99.swf","_level"+99); + // load yet another swf + getURL("level99.swf","_level"+99); - getURL("level87.swf", "_level87"); - } + getURL("level87.swf", "_level87"); + } } diff --git a/testsuite/misc-mtasc.all/level87.as b/testsuite/misc-mtasc.all/level87.as index e5c2c57..7e1aa0f 100644 --- a/testsuite/misc-mtasc.all/level87.as +++ b/testsuite/misc-mtasc.all/level87.as @@ -25,52 +25,52 @@ class Level87 { - static function main(mc) - { - mc.createEmptyMovieClip("ch", 1); - with(mc.ch) - { - lineStyle(1, 0x00000); - beginFill(0xFFFF00, 80); - var x=220; - var y=170; - var width=100; - var height=100; - moveTo(x, y); - lineTo(x+width, y); - lineTo(x+width, y+height); - lineTo(x, y+height); - lineTo(x, y); - endFill(); - }; + static function main(mc) + { + mc.createEmptyMovieClip("ch", 1); + with(mc.ch) + { + lineStyle(1, 0x00000); + beginFill(0xFFFF00, 80); + var x=220; + var y=170; + var width=100; + var height=100; + moveTo(x, y); + lineTo(x+width, y); + lineTo(x+width, y+height); + lineTo(x, y+height); + lineTo(x, y); + endFill(); + }; - check_equals(mc._currentframe, 1); + check_equals(mc._currentframe, 1); - // Check our depth - check_equals(mc.getDepth(), -16297); + // Check our depth + check_equals(mc.getDepth(), -16297); - // The ""+ is there to force conversion to a string - check_equals(""+mc, "_level87"); + // The ""+ is there to force conversion to a string + check_equals(""+mc, "_level87"); - if (_level0.level87loaded ) - { - check(_level0.frameno >= 3); + if (_level0.level87loaded ) + { + check(_level0.frameno >= 3); - check_equals(typeof(_level5), 'undefined'); - return; - } + check_equals(typeof(_level5), 'undefined'); + return; + } - _level0.level87loaded = true; + _level0.level87loaded = true; - check(_level0.frameno >= 2); + check(_level0.frameno >= 2); - // This one fails because gnash is executing code - // in level99 before code in the first load of level87, - // probably because it is *loading* level99 before level87, - // which is in the order loads are requested rather then - // reverse of it as it's common... - check_equals(_level5._currentframe, 1); + // This one fails because gnash is executing code + // in level99 before code in the first load of level87, + // probably because it is *loading* level99 before level87, + // which is in the order loads are requested rather then + // reverse of it as it's common... + check_equals(_level5._currentframe, 1); - _level87.loadMovie("level87.swf"); - } + _level87.loadMovie("level87.swf"); + } } diff --git a/testsuite/misc-mtasc.all/levels.as b/testsuite/misc-mtasc.all/levels.as index 6ea7d34..f1a074d 100644 --- a/testsuite/misc-mtasc.all/levels.as +++ b/testsuite/misc-mtasc.all/levels.as @@ -25,28 +25,28 @@ class LevelsMain { - static function main(mc) - { - // create a var that other swfs can test - _level0.testvar = 1239; + static function main(mc) + { + // create a var that other swfs can test + _level0.testvar = 1239; - var test = new LevelsMain(); - test.run(); + var test = new LevelsMain(); + test.run(); - // Check our depth - check_equals(mc.getDepth(), -16384); + // Check our depth + check_equals(mc.getDepth(), -16384); - // The ""+ is there to force conversion to a string - check_equals(""+mc, "_level0"); + // The ""+ is there to force conversion to a string + check_equals(""+mc, "_level0"); - mc.onEnterFrame = function () - { - this.frameno++; - } - } + mc.onEnterFrame = function () + { + this.frameno++; + } + } - function run() { - trace("main class running"); - getURL("level5.swf","_level"+5); - } + function run() { + trace("main class running"); + getURL("level5.swf","_level"+5); + } }