[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Gnash-commit] /srv/bzr/gnash/trunk r11615: Centralize movie loading wit
From: |
Sandro Santilli |
Subject: |
[Gnash-commit] /srv/bzr/gnash/trunk r11615: Centralize movie loading with the movie_root service. |
Date: |
Tue, 10 Nov 2009 02:00:48 +0100 |
User-agent: |
Bazaar (1.16.1) |
------------------------------------------------------------
revno: 11615 [merge]
committer: Sandro Santilli <address@hidden>
branch nick: trunk
timestamp: Tue 2009-11-10 02:00:48 +0100
message:
Centralize movie loading with the movie_root service.
Should now be easier to work on the async load.
modified:
libcore/DisplayObject.cpp
libcore/DisplayObject.h
libcore/MovieClip.cpp
libcore/MovieClip.h
libcore/asobj/MovieClipLoader.cpp
libcore/asobj/flash/display/MovieClip_as.cpp
libcore/movie_root.cpp
libcore/movie_root.h
libcore/vm/ExecutableCode.h
testsuite/swfdec/PASSING
=== modified file 'libcore/DisplayObject.cpp'
--- a/libcore/DisplayObject.cpp 2009-11-06 09:07:36 +0000
+++ b/libcore/DisplayObject.cpp 2009-11-09 23:07:58 +0000
@@ -113,6 +113,19 @@
return _object;
}
+void
+DisplayObject::getLoadedMovie(Movie* extern_movie)
+{
+ LOG_ONCE(
+ log_unimpl("loadMovie against a %s DisplayObject", typeName(*this))
+ );
+
+ // TODO: look at the MovieClip implementation, but most importantly
+ // test all the event handlers copies etc..
+
+ UNUSED(extern_movie);
+}
+
std::string
DisplayObject::getNextUnnamedInstanceName()
{
=== modified file 'libcore/DisplayObject.h'
--- a/libcore/DisplayObject.h 2009-11-06 23:18:38 +0000
+++ b/libcore/DisplayObject.h 2009-11-08 13:13:45 +0000
@@ -809,6 +809,9 @@
///
virtual bool unload();
+ /// Accept a loaded Movie
+ virtual void getLoadedMovie(Movie* newMovie);
+
/// Return true if this DisplayObject was unloaded from the stage
bool unloaded() const { return _unloaded; }
=== modified file 'libcore/MovieClip.cpp'
--- a/libcore/MovieClip.cpp 2009-11-06 09:07:36 +0000
+++ b/libcore/MovieClip.cpp 2009-11-09 21:58:54 +0000
@@ -395,10 +395,6 @@
assert(_swf);
assert(object);
- if (!isAS3(getVM(*object)) && !get_parent()) {
- object->init_member("$version", getVM(*object).getPlayerVersion(), 0);
- }
-
_environment.set_target(this);
}
@@ -1921,6 +1917,10 @@
getTarget());
#endif
+ if (!isAS3(getVM(*getObject(this))) && !get_parent()) {
+ getObject(this)->init_member("$version",
getVM(*getObject(this)).getPlayerVersion(), 0);
+ }
+
bool eventHandlersInvoked = false;
do {
@@ -2031,6 +2031,52 @@
return shouldKeepAlive;
}
+void
+MovieClip::getLoadedMovie(Movie* extern_movie)
+{
+ DisplayObject* parent = get_parent();
+ if (parent)
+ {
+ extern_movie->set_parent(parent);
+
+ // Copy own lockroot value
+ extern_movie->setLockRoot(getLockRoot());
+
+ // Copy own event handlers
+ // see testsuite/misc-ming.all/loadMovieTest.swf
+ const Events& clipEvs = get_event_handlers();
+ // top-level movies can't have clip events, right ?
+ assert (extern_movie->get_event_handlers().empty());
+ extern_movie->set_event_handlers(clipEvs);
+
+ // Copy own name
+ // TODO: check empty != none...
+ const std::string& name = get_name();
+ if( !name.empty() ) extern_movie->set_name(name);
+
+ // Copy own clip depth (TODO: check this)
+ extern_movie->set_clip_depth(get_clip_depth());
+
+ // Replace ourselves in parent
+ // TODO: don't pretend our parent is a MovieClip,
+ // could as well be a button I guess...
+ // At most we should require it to be a
+ // DisplayObjectContainer and log an error if it's not.
+ MovieClip* parent_sp = parent->to_movie();
+ assert(parent_sp);
+ parent_sp->replace_display_object(extern_movie, get_depth(),
+ true, true);
+
+ }
+ else
+ {
+ // replaceLevel will set depth for us
+ stage().replaceLevel(get_depth() - DisplayObject::staticDepthOffset,
+ extern_movie);
+ }
+}
+
+
bool
MovieClip::loadMovie(const URL& url, const std::string* postdata)
=== modified file 'libcore/MovieClip.h'
--- a/libcore/MovieClip.h 2009-11-06 08:44:44 +0000
+++ b/libcore/MovieClip.h 2009-11-08 13:13:45 +0000
@@ -474,8 +474,16 @@
/// IF not NULL, use as the POST body for HTTP requests
///
/// Return: true if it succeeded, false otherwise
+ ///
+ /// @deprecated use movie_root::loadMovie instead to queue
+ /// a load and getLoadedMovie to have objects of
+ /// this class receive a loaded external movie
+ ///
bool loadMovie(const URL& url, const std::string* postdata=NULL);
+ // See dox in DisplayObject.h
+ virtual void getLoadedMovie(Movie* newMovie);
+
/// \brief
/// Load url-encoded variables from the given url, optionally
/// sending variables from this timeline too.
=== modified file 'libcore/asobj/MovieClipLoader.cpp'
--- a/libcore/asobj/MovieClipLoader.cpp 2009-11-04 13:37:17 +0000
+++ b/libcore/asobj/MovieClipLoader.cpp 2009-11-10 00:59:35 +0000
@@ -58,64 +58,6 @@
void attachMovieClipLoaderInterface(as_object& o);
}
-/// This class is used to queue a function call action
-//
-/// Exact use is to queue onLoadInit, which should be invoked
-/// after actions of in first frame of a loaded movie are executed.
-/// Since those actions are queued the only way to execute something
-/// after them is to queue the function call as well.
-///
-/// The class might be made more general and accessible outside
-/// of the MovieClipLoader class. For now it only works for
-/// calling a function with a two argument.
-///
-class DelayedFunctionCall : public ExecutableCode
-{
-
-public:
-
- DelayedFunctionCall(as_object* target, string_table::key name,
- const as_value& arg1, const as_value& arg2)
- :
- _target(target),
- _name(name),
- _arg1(arg1),
- _arg2(arg2)
- {}
-
-
- ExecutableCode* clone() const
- {
- return new DelayedFunctionCall(*this);
- }
-
- virtual void execute()
- {
- _target->callMethod(_name, _arg1, _arg2);
- }
-
-#ifdef GNASH_USE_GC
- /// Mark reachable resources (for the GC)
- //
- /// Reachable resources are:
- /// - the action target (_target)
- ///
- virtual void markReachableResources() const
- {
- _target->setReachable();
- _arg1.setReachable();
- _arg2.setReachable();
- }
-#endif // GNASH_USE_GC
-
-private:
-
- as_object* _target;
- string_table::key _name;
- as_value _arg1, _arg2;
-
-};
-
void
registerMovieClipLoaderNative(as_object& global)
{
@@ -181,11 +123,14 @@
const std::string& str_url = fn.arg(0).to_string();
as_value tgt_arg = fn.arg(1);
-
- std::string tgt_str = tgt_arg.to_string();
+ const std::string& tgt_str = tgt_arg.to_string();
+
+ movie_root& mr = getRoot(*ptr);
+
+ // TODO: check if this logic can be generic to movie_root::loadMovie
DisplayObject* target = fn.env().find_target(tgt_str);
-
- if (!target) {
+ unsigned int junk;
+ if (!target && ! mr.isLevelTarget(tgt_str, junk) ) {
IF_VERBOSE_ASCODING_ERRORS(
log_aserror(_("Could not find target %s (evaluated from %s)"),
tgt_str, tgt_arg);
@@ -193,72 +138,9 @@
return as_value(false);
}
- MovieClip* sprite = target->to_movie();
- if (!sprite) {
- IF_VERBOSE_ASCODING_ERRORS(
- log_aserror(_("Target %s is not a sprite instance (%s)"),
- target->getTarget(), typeName(*target));
- );
- return as_value(false);
- }
-
- as_value targetVal(getObject(sprite));
-
- movie_root& mr = getRoot(*ptr);
- URL url(str_url, mr.runResources().baseURL());
-
- bool ret = sprite->loadMovie(url);
- if (!ret) {
-
- // FIXME: docs suggest the string can be either "URLNotFound" or
- // "LoadNeverCompleted". This is neither of them:
- as_value arg1("Failed to load movie or jpeg");
-
- // FIXME: The last argument is HTTP status, or 0 if no
connection
- // was attempted (sandbox) or no status information is available
- // (supposedly the Adobe mozilla plugin).
- as_value arg2(0.0);
- ptr->callMethod(NSV::PROP_BROADCAST_MESSAGE, "onLoadError",
- getObject(sprite), arg1, arg2);
-
- return as_value(true);
- }
-
- // this is to resolve the soft ref
- MovieClip* newChar = targetVal.to_sprite();
- if (!newChar) {
- // We could assert, but let's try to be nicer...
- log_error("MovieClip::loadMovie destroyed self without
replacing?");
- return as_value(true);
- }
-
- // Dispatch onLoadStart
- ptr->callMethod(NSV::PROP_BROADCAST_MESSAGE, "onLoadStart", targetVal);
-
- // Dispatch onLoadProgress
- size_t bytesLoaded = newChar->get_bytes_loaded();
- size_t bytesTotal = newChar->get_bytes_total();
- ptr->callMethod(NSV::PROP_BROADCAST_MESSAGE, "onLoadProgress",
targetVal,
- bytesLoaded, bytesTotal);
-
- // Dispatch onLoadComplete
- ptr->callMethod(NSV::PROP_BROADCAST_MESSAGE, "onLoadComplete",
targetVal,
- as_value(0.0)); // TODO: find semantic of last arg
-
- /// This event must be dispatched when actions
- /// in first frame of loaded clip have been executed.
- ///
- /// Since MovieClip::loadMovie above will invoke stagePlacementCallback
- /// and thus queue all actions in first frame, we'll queue the
- /// onLoadInit call next, so it happens after the former.
- std::auto_ptr<ExecutableCode> code(
- new DelayedFunctionCall(ptr, NSV::PROP_BROADCAST_MESSAGE,
- "onLoadInit", targetVal));
-
- getRoot(*ptr).pushAction(code, movie_root::apDOACTION);
-
- return as_value(true);
-
+ // TODO: return code is based on target validity if I'm not wrong
+ mr.loadMovie(str_url, tgt_str, "", MovieClip::METHOD_NONE, ptr);
+ return as_value(true);
}
as_value
=== modified file 'libcore/asobj/flash/display/MovieClip_as.cpp'
--- a/libcore/asobj/flash/display/MovieClip_as.cpp 2009-11-04 16:55:59
+0000
+++ b/libcore/asobj/flash/display/MovieClip_as.cpp 2009-11-09 23:07:58
+0000
@@ -901,13 +901,13 @@
as_value
movieclip_loadMovie(const fn_call& fn)
{
- MovieClip* movieclip = ensure<IsDisplayObject<MovieClip> >(fn);
+ DisplayObject* dobj = ensure<IsDisplayObject<> >(fn);
as_value val;
if (fn.nargs > 1) {
- val = getObject(movieclip)->callMethod(NSV::PROP_METH, fn.arg(1));
+ val = getObject(dobj)->callMethod(NSV::PROP_METH, fn.arg(1));
}
- else val = getObject(movieclip)->callMethod(NSV::PROP_METH);
+ else val = getObject(dobj)->callMethod(NSV::PROP_METH);
if (fn.nargs < 1) // url
{
@@ -933,7 +933,7 @@
}
movie_root& mr = getRoot(fn);
- std::string target = movieclip->getTarget();
+ std::string target = dobj->getTarget();
// TODO: if GET/POST should send variables of *this* movie,
// no matter if the target will be replaced by another movie !!
@@ -945,7 +945,7 @@
// This is just an optimization if we aren't going
// to send the data anyway. It might be wrong, though.
if (method != MovieClip::METHOD_NONE) {
- getURLEncodedVars(*getObject(movieclip), data);
+ getURLEncodedVars(*getObject(dobj), data);
}
mr.loadMovie(urlstr, target, data, method);
=== modified file 'libcore/movie_root.cpp'
--- a/libcore/movie_root.cpp 2009-11-06 07:54:33 +0000
+++ b/libcore/movie_root.cpp 2009-11-10 00:59:35 +0000
@@ -186,10 +186,22 @@
_intervalTimers.clear();
}
+void
+movie_root::clearLoadMovieRequests()
+{
+ for (LoadMovieRequests::iterator it=_loadMovieRequests.begin(),
+ end = _loadMovieRequests.end(); it != end; ++it)
+ {
+ delete *it;
+ }
+ _loadMovieRequests.clear();
+}
+
movie_root::~movie_root()
{
clearActionQueue();
clearIntervalTimers();
+ clearLoadMovieRequests();
assert(testInvariant());
}
@@ -287,7 +299,7 @@
_movies[movie->get_depth()] = movie;
}
else
- {
+ {
// don't leak overloaded levels
LevelMovie lm = it->second;
@@ -479,6 +491,21 @@
return true;
}
+void
+movie_root::replaceLevel(unsigned int num, Movie* extern_movie)
+{
+ extern_movie->set_depth(num + DisplayObject::staticDepthOffset);
+ Levels::iterator it = _movies.find(extern_movie->get_depth());
+ if ( it == _movies.end() )
+ {
+ log_error("TESTME: loadMovie called on level %d which is not available
at load time, skipped placement for now");
+ return; // skip
+ }
+
+ // TODO: rework this to avoid the double scan
+ setLevel(num, extern_movie);
+}
+
Movie*
movie_root::getLevel(unsigned int num) const
{
@@ -520,6 +547,9 @@
// remove all intervals
clearIntervalTimers();
+ // remove all loadMovie requests
+ clearLoadMovieRequests();
+
// remove key/mouse listeners
m_key_listeners.clear();
m_mouse_listeners.clear();
@@ -1754,6 +1784,13 @@
i->obj->setReachable();
}
+ // Mark LoadMovieRequest handlers as reachable
+ for (LoadMovieRequests::const_iterator it=_loadMovieRequests.begin(),
+ end = _loadMovieRequests.end(); it != end; ++it)
+ {
+ (*it)->setReachable();
+ }
+
// Mark resources reachable by queued action code
for (int lvl=0; lvl<apSIZE; ++lvl)
{
@@ -2139,7 +2176,8 @@
void
movie_root::loadMovie(const std::string& urlstr, const std::string& target,
- const std::string& data, MovieClip::VariablesMethod method)
+ const std::string& data, MovieClip::VariablesMethod method,
+ as_object* handler)
{
/// URL security is checked in StreamProvider::getStream() down the
@@ -2159,53 +2197,167 @@
log_debug("movie_root::loadMovie(%s, %s)", url.str(), target);
- const std::string* postdata = NULL;
-
- /// POST: send variables using the POST method.
- if (method == MovieClip::METHOD_POST) postdata = &data;
- _loadMovieRequests.push_front(LoadMovieRequest(url, target, postdata));
+ const std::string* postdata = (method == MovieClip::METHOD_POST) ? &data
+ : 0;
+
+ _loadMovieRequests.push_front(
+ new LoadMovieRequest(url, target, postdata, handler)
+ );
+
+ // TODO: start thread
}
void
-movie_root::processLoadMovieRequest(const LoadMovieRequest& r)
-{
+movie_root::processLoadMovieRequest(LoadMovieRequest& r)
+{
+ const URL& url = r.getURL();
+ bool usePost = r.usePost();
+ const std::string* postdata = usePost ? &(r.getPostData()) : 0;
+
+ // TODO: make this load asyncronous !!
+ boost::intrusive_ptr<movie_definition> md (
+ MovieFactory::makeMovie(url, _runResources, NULL, true, postdata));
+ r.setCompleted(md);
+
+ bool completed = processCompletedLoadMovieRequest(r);
+ assert(completed);
+}
+
+/* private */
+bool
+movie_root::processCompletedLoadMovieRequest(const LoadMovieRequest& r)
+{
+ GNASH_REPORT_FUNCTION;
+
+ boost::intrusive_ptr<movie_definition> md;
+ if ( ! r.getCompleted(md) ) return false; // not completed yet
+
const std::string& target = r.getTarget();
+ DisplayObject* targetDO = findCharacterByTarget(target);
+ as_object* handler = r.getHandler();
+
+ if ( ! md )
+ {
+
+ if ( targetDO && handler )
+ {
+ // Signal load error
+ // Tested not to happen if target isn't found at time of loading
+ //
+
+ as_value arg1(getObject(targetDO));
+
+ // FIXME: docs suggest the string can be either "URLNotFound" or
+ // "LoadNeverCompleted". This is neither of them:
+ as_value arg2("Failed to load movie or jpeg");
+
+ // FIXME: The last argument is HTTP status, or 0 if no connection
+ // was attempted (sandbox) or no status information is available
+ // (supposedly the Adobe mozilla plugin).
+ as_value arg3(0.0);
+
+ handler->callMethod(NSV::PROP_BROADCAST_MESSAGE, "onLoadError",
+ arg1, arg2, arg3);
+ }
+ return true; // nothing to do, but completed
+ }
+
const URL& url = r.getURL();
- bool usePost = r.usePost();
- const std::string& postData = r.getPostData();
-
- if (target.compare(0, 6, "_level") == 0 &&
- target.find_first_not_of("0123456789", 7) == std::string::npos)
- {
- unsigned int levelno = std::strtoul(target.c_str() + 6, NULL, 0);
- log_debug(_("processLoadMovieRequest: Testing _level loading "
+
+ Movie* extern_movie = md->createMovie(*_vm.getGlobal());
+ if (!extern_movie)
+ {
+ log_error(_("Can't create Movie instance "
+ "for definition loaded from %s"), url);
+ return true; // completed in any case...
+ }
+
+ // Parse query string
+ MovieClip::MovieVariables vars;
+ url.parse_querystring(url.querystring(), vars);
+ extern_movie->setVariables(vars);
+
+ if (targetDO)
+ {
+ targetDO->getLoadedMovie(extern_movie);
+ }
+ else
+ {
+ unsigned int levelno;
+ if (isLevelTarget(target, levelno))
+ {
+ log_debug(_("processCompletedLoadMovieRequest: _level loading "
"(level %u)"), levelno);
- loadLevel(levelno, url);
- return;
- }
-
- DisplayObject* ch = findCharacterByTarget(target);
- if (!ch)
- {
- log_debug("Target %s of a loadMovie request doesn't exist at "
- "processing time", target);
- return;
- }
-
- MovieClip* sp = ch->to_movie();
- if (!sp)
- {
- log_unimpl("loadMovie against a %s DisplayObject", typeName(*ch));
- return;
- }
-
- if ( usePost )
- {
- sp->loadMovie(url, &postData);
- }
- else
- {
- sp->loadMovie(url);
+ extern_movie->set_depth(levelno +
DisplayObject::staticDepthOffset);
+ setLevel(levelno, extern_movie);
+ }
+ else
+ {
+ log_debug("Target %s of a loadMovie request doesn't exist at "
+ "load complete time", target);
+ return true;
+ }
+ }
+
+ if (handler && targetDO)
+ {
+ // Dispatch onLoadStart
+ // FIXME: should be signalled before starting to load
+ // (0/-1 bytes loaded/total) but still with *new*
+ // display object as target (ie: the target won't
+ // contain members set either before or after loadClip.
+ handler->callMethod(NSV::PROP_BROADCAST_MESSAGE, "onLoadStart",
+ getObject(targetDO));
+
+ // Dispatch onLoadProgress
+ // FIXME: should be signalled every 65535 bytes ?
+ size_t bytesLoaded = md->get_bytes_loaded();
+ size_t bytesTotal = md->get_bytes_total();
+ handler->callMethod(NSV::PROP_BROADCAST_MESSAGE, "onLoadProgress",
+ getObject(targetDO), bytesLoaded, bytesTotal);
+
+ // Dispatch onLoadComplete
+ // FIXME: find semantic of last arg
+ handler->callMethod(NSV::PROP_BROADCAST_MESSAGE, "onLoadComplete",
+ getObject(targetDO), as_value(0.0));
+
+
+ // Displatch onLoadInit
+
+ // This event must be dispatched when actions
+ // in first frame of loaded clip have been executed.
+ //
+ // Since getLoadedMovie or setLevel above will invoke
+ // stagePlacementCallback and thus queue all actions in first
+ // frame, we'll queue the
+ // onLoadInit call next, so it happens after the former.
+ //
+ std::auto_ptr<ExecutableCode> code(
+ new DelayedFunctionCall(handler, NSV::PROP_BROADCAST_MESSAGE,
+ "onLoadInit", getObject(targetDO)));
+
+ getRoot(*handler).pushAction(code, movie_root::apDOACTION);
+ }
+
+ return true;
+
+}
+
+/* private */
+void
+movie_root::processCompletedLoadMovieRequests()
+{
+ GNASH_REPORT_FUNCTION;
+
+ for (LoadMovieRequests::iterator it=_loadMovieRequests.begin();
+ it != _loadMovieRequests.end(); )
+ {
+ const LoadMovieRequest* lr=*it;
+ if ( processCompletedLoadMovieRequest(*lr) )
+ {
+ it = _loadMovieRequests.erase(it);
+ delete lr;
+ }
}
}
@@ -2218,9 +2370,10 @@
for (LoadMovieRequests::iterator it=_loadMovieRequests.begin();
it != _loadMovieRequests.end(); )
{
- const LoadMovieRequest& lr=*it;
- processLoadMovieRequest(lr);
+ LoadMovieRequest* lr=*it;
+ processLoadMovieRequest(*lr);
it = _loadMovieRequests.erase(it);
+ delete lr;
}
}
=== modified file 'libcore/movie_root.h'
--- a/libcore/movie_root.h 2009-11-06 07:39:15 +0000
+++ b/libcore/movie_root.h 2009-11-10 00:07:05 +0000
@@ -100,6 +100,7 @@
#include <set>
#include <bitset>
#include <boost/noncopyable.hpp>
+#include <boost/thread/thread.hpp>
// Forward declarations
namespace gnash {
@@ -201,6 +202,17 @@
///
bool loadLevel(unsigned int num, const URL& url);
+ /// Replace an existing level with a new movie
+ //
+ /// Depth will be assigned to external_movie by this function.
+ /// If the give level number doesn't exist an error is logged
+ /// and nothing else happens.
+ ///
+ /// This method is intended for use by xxx.loadMovie(yyy)
+ /// when 'xxx' is a top-level movie.
+ ///
+ void replaceLevel(unsigned int num, Movie* external_movie);
+
/// Swap depth of a level (or two)
//
/// Character's depths are updated.
@@ -705,8 +717,13 @@
/// key/value pairs
/// @param method The VariablesMethod to use for sending the data. If
/// MovieClip::METHOD_NONE, no data will be sent.
+ /// @param handler An object which will be signalled of load
+ /// events (onLoadStart, onLoadComplete, onLoadInit,
+ /// onLoadError). Can be null if caller doesn't care.
+ ///
void loadMovie(const std::string& url, const std::string& target,
- const std::string& data, MovieClip::VariablesMethod method);
+ const std::string& data, MovieClip::VariablesMethod method,
+ as_object* handler=0);
/// Send a request to the hosting application (e.g. browser).
//
@@ -936,17 +953,21 @@
AbstractFsCallback* _fsCommandHandler;
/// A load movie request
- class LoadMovieRequest {
+ class LoadMovieRequest : boost::noncopyable {
public:
/// @param postdata
/// If not null POST method will be used for HTTP.
///
LoadMovieRequest(const URL& u, const std::string& t,
- const std::string* postdata)
+ const std::string* postdata, as_object* handler)
:
_target(t),
_url(u),
- _usePost(false)
+ _usePost(false),
+ _mdef(0),
+ _completed(false),
+ _mutex(),
+ _handler(handler)
{
if ( postdata )
{
@@ -959,23 +980,74 @@
const URL& getURL() const { return _url; }
const std::string& getPostData() const { return _postData; }
bool usePost() const { return _usePost; }
+ as_object* getHandler() const { return _handler; }
+ void setReachable() const {
+ if (_handler) _handler->setReachable();
+ }
+
+ /// Get the loaded movie definition, if any
+ //
+ /// @param md the loaded movie_definition is copied here
+ /// if it was impossible to create one.
+ ///
+ /// @return true if the request was completed, false otherwise.
+ ///
+ /// RULE: if return is FALSE param 'md' will be set to 0.
+ /// RULE: if return is TRUE param 'md' may be set to 0 or non 0.
+ /// RULE: if parameter 'md' is set to non 0, TRUE must be returned.
+ ///
+ /// locks _mutex
+ ///
+ bool getCompleted(boost::intrusive_ptr<movie_definition>& md) const
+ {
+ boost::mutex::scoped_lock lock(_mutex);
+ md = _mdef;
+ return _completed;
+ }
+
+ /// Complete the request
+ //
+ /// @param md the loaded movie_definition, or 0 if
+ /// it was impossible to create one.
+ ///
+ /// locks _mutex
+ ///
+ void setCompleted(boost::intrusive_ptr<movie_definition> md)
+ {
+ boost::mutex::scoped_lock lock(_mutex);
+ _mdef = md;
+ _completed = true;
+ }
private:
std::string _target;
URL _url;
bool _usePost;
std::string _postData;
+ boost::intrusive_ptr<movie_definition> _mdef;
+ bool _completed;
+ mutable boost::mutex _mutex;
+ as_object* _handler;
};
/// Load movie requests
- typedef std::list<LoadMovieRequest> LoadMovieRequests;
+ typedef std::list<LoadMovieRequest*> LoadMovieRequests;
LoadMovieRequests _loadMovieRequests;
/// Process all load movie requests
void processLoadMovieRequests();
/// Process a single load movie request
- void processLoadMovieRequest(const LoadMovieRequest& r);
+ void processLoadMovieRequest(LoadMovieRequest& r);
+
+ /// Check a LoadMovieRequest and process if completed.
+ //
+ /// @return true if the request was completely processed.
+ ///
+ bool processCompletedLoadMovieRequest(const LoadMovieRequest& r);
+
+ /// Process all completed loadMovie requests.
+ void processCompletedLoadMovieRequests();
/// Listeners container
typedef std::list<DisplayObject*> CharacterList;
@@ -993,6 +1065,9 @@
/// Delete all elements on the timers list
void clearIntervalTimers();
+ /// Delete all LoadMovieRequests
+ void clearLoadMovieRequests();
+
/// Execute expired timers
void executeAdvanceCallbacks();
=== modified file 'libcore/vm/ExecutableCode.h'
--- a/libcore/vm/ExecutableCode.h 2009-10-27 09:44:54 +0000
+++ b/libcore/vm/ExecutableCode.h 2009-11-09 23:57:39 +0000
@@ -254,6 +254,64 @@
DisplayObject* target;
};
+/// This class is used to queue a function call action
+//
+/// Exact use is to queue onLoadInit, which should be invoked
+/// after actions of in first frame of a loaded movie are executed.
+/// Since those actions are queued the only way to execute something
+/// after them is to queue the function call as well.
+///
+/// The class might be made more general and accessible outside
+/// of the MovieClipLoader class. For now it only works for
+/// calling a function with a two argument.
+///
+class DelayedFunctionCall : public ExecutableCode
+{
+
+public:
+
+ DelayedFunctionCall(as_object* target, string_table::key name,
+ const as_value& arg1, const as_value& arg2)
+ :
+ _target(target),
+ _name(name),
+ _arg1(arg1),
+ _arg2(arg2)
+ {}
+
+
+ ExecutableCode* clone() const
+ {
+ return new DelayedFunctionCall(*this);
+ }
+
+ virtual void execute()
+ {
+ _target->callMethod(_name, _arg1, _arg2);
+ }
+
+#ifdef GNASH_USE_GC
+ /// Mark reachable resources (for the GC)
+ //
+ /// Reachable resources are:
+ /// - the action target (_target)
+ ///
+ virtual void markReachableResources() const
+ {
+ _target->setReachable();
+ _arg1.setReachable();
+ _arg2.setReachable();
+ }
+#endif // GNASH_USE_GC
+
+private:
+
+ as_object* _target;
+ string_table::key _name;
+ as_value _arg1, _arg2;
+
+};
+
} // namespace gnash
=== modified file 'testsuite/swfdec/PASSING'
--- a/testsuite/swfdec/PASSING 2009-11-03 22:43:22 +0000
+++ b/testsuite/swfdec/PASSING 2009-11-10 00:59:35 +0000
@@ -776,6 +776,8 @@
moviecliploader-known-image-size-8.swf:32aaecb1e0735b6c94e980d21753e698
moviecliploader-level-5.swf:fa26ae6da1ec573daae0ce5357a419c5
moviecliploader-level-6.swf:cd9f65f627a47a906c4d140e8e518160
+moviecliploader-level-7.swf:b0ec6ee5047d1d5f49ccb9c22fc29b30
+moviecliploader-level-8.swf:18f7d36c66a71113613afc3b937d536e
moviecliploader-properties-6.swf:85084f5ae86539dfedf525b204762dbf
moviecliploader-properties-7.swf:f10fa0e2b443f46af6780465633ceb75
moviecliploader-properties-8.swf:78fa86752025a314051eae11806c1498
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Gnash-commit] /srv/bzr/gnash/trunk r11615: Centralize movie loading with the movie_root service.,
Sandro Santilli <=