Gnash  0.8.10
movie_root.h
Go to the documentation of this file.
00001 // 
00002 //   Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
00003 //   Free Software Foundation, Inc
00004 // 
00005 // This program is free software; you can redistribute it and/or modify
00006 // it under the terms of the GNU General Public License as published by
00007 // the Free Software Foundation; either version 3 of the License, or
00008 // (at your option) any later version.
00009 // 
00010 // This program is distributed in the hope that it will be useful,
00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013 // GNU General Public License for more details.
00014 // 
00015 // You should have received a copy of the GNU General Public License
00016 // along with this program; if not, write to the Free Software
00017 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00018 
00019 
00062 
00063 
00064 #ifndef GNASH_MOVIE_ROOT_H
00065 #define GNASH_MOVIE_ROOT_H
00066 
00067 #ifdef HAVE_CONFIG_H
00068 #include "gnashconfig.h" //USE_SWFTREE
00069 #endif
00070 
00071 #include <map>
00072 #include <string>
00073 #include <vector>
00074 #include <list>
00075 #include <set>
00076 #include <bitset>
00077 #include <boost/array.hpp>
00078 #include <boost/ptr_container/ptr_deque.hpp>
00079 #include <boost/noncopyable.hpp>
00080 #include <boost/any.hpp>
00081 #include <boost/optional.hpp>
00082 
00083 #include "dsodefs.h" // DSOEXPORT
00084 #include "MouseButtonState.h" // for composition
00085 #include "DragState.h" // for composition
00086 #include "GnashKey.h" // key::code
00087 #include "Movie.h"
00088 #include "GnashEnums.h" 
00089 #include "MovieClip.h"
00090 #include "SimpleBuffer.h" // for LoadCallback
00091 #include "MovieLoader.h"
00092 #include "ExternalInterface.h"
00093 #include "GC.h"
00094 #include "VM.h"
00095 #include "HostInterface.h"
00096 #include "log.h"
00097 
00098 #ifdef USE_SWFTREE
00099 # include "tree.hh"
00100 #endif
00101 
00102 // GNASH_PARANOIA_LEVEL:
00103 // 0 : (not unimplemented)
00104 // 1 : quick assertions
00105 // 2 : add testInvariant
00106 //
00107 #ifndef GNASH_PARANOIA_LEVEL
00108 # define GNASH_PARANOIA_LEVEL 1
00109 #endif
00110 
00111 // Forward declarations
00112 namespace gnash {
00113     class ExecutableCode; 
00114     class URL;
00115     class Timer;
00116     class MovieClip;
00117     class VirtualClock;
00118     class IOChannel;
00119     class RunResources;
00120     class Button;
00121     class VM;
00122 }
00123 
00124 namespace gnash {
00125 
00126 struct DepthComparator
00127 {
00128     typedef MovieClip* LevelMovie;
00129     bool operator()(const LevelMovie& d1, const LevelMovie& d2) const {
00130         return d1->get_depth() < d2->get_depth();
00131     }
00132 };
00133 
00135 //
00140 //
00143 //
00148 //
00150 class DSOEXPORT movie_root : public GcRoot, boost::noncopyable
00151 {
00152 public:
00153     
00154     class LoadCallback {
00155     public:
00156         LoadCallback(boost::shared_ptr<IOChannel> s, as_object* o)
00157             :
00158             _stream(s),
00159             _obj(o)
00160         {}
00161         bool processLoad();
00162         void setReachable() const;
00163     private:
00164         boost::shared_ptr<IOChannel> _stream;
00165         SimpleBuffer _buf;
00166         as_object* _obj;
00167     };
00168     typedef std::list<LoadCallback> LoadCallbacks;        
00169 
00170     typedef std::bitset<key::KEYCOUNT> Keys;
00171 
00173     //
00176     movie_root(VirtualClock& clock, const RunResources& runResources);
00177 
00178     ~movie_root();
00179 
00181     //
00183     // 
00189     Movie* init(movie_definition* def,
00190             const MovieClip::MovieVariables& variables);
00191 
00193     //
00197     MovieClip* getLevel(unsigned int num) const;
00198 
00200     //
00205     void setLevel(unsigned int num, Movie* movie);
00206 
00208     //
00216     void replaceLevel(unsigned int num, Movie* external_movie);
00217 
00219     //
00232     void swapLevels(MovieClip* sp, int depth);
00233 
00235     //
00243     void dropLevel(int depth);
00244 
00246     //
00249     //
00252     void setDimensions(size_t w, size_t h);
00253 
00255     size_t getStageWidth() const;
00256 
00258     size_t getStageHeight() const;
00259 
00261     //
00270     DSOEXPORT bool mouseMoved(boost::int32_t x, boost::int32_t y);
00271 
00273     //
00276     DSOEXPORT bool mouseClick(bool press);
00277 
00279     //
00284     DSOEXPORT bool mouseWheel(int delta);
00285 
00287     //
00291     DSOEXPORT bool keyEvent(key::code k, bool down);
00292 
00294     //
00296     std::pair<boost::int32_t, boost::int32_t> mousePosition() const;
00297 
00298     void setDragState(const DragState& st);
00299 
00301     //
00303     Movie& getRootMovie() {
00304         return *_rootMovie;
00305     }
00306 
00307     void stop_drag() {
00308         _dragState.reset();
00309     }
00310 
00312     //
00322     boost::uint32_t addIntervalTimer(std::auto_ptr<Timer> timer);
00323 
00325     //
00329     //
00331     //
00334     //
00337     //
00340     void addLoadableObject(as_object* obj, std::auto_ptr<IOChannel> str);
00341 
00342     void addAdvanceCallback(ActiveRelay* obj);
00343 
00344     void removeAdvanceCallback(ActiveRelay* obj);
00345 
00347     //
00349     bool clearIntervalTimer(boost::uint32_t x);
00350 
00351     void set_background_color(const rgba& color);
00352 
00353     void set_background_alpha(float alpha);
00354 
00356     VM& getVM() { return _vm; }
00357  
00360     //
00364     bool advance();
00365 
00369     //
00372     int timeToNextFrame() const;
00373 
00375     //
00385     void advanceMovie();
00386 
00387     void display();
00388 
00390     size_t nextUnnamedInstance() {
00391         return ++_unnamedInstance;
00392     }
00393 
00395     void registerButton(Button* listener);
00396 
00398     void removeButton(Button* listener);
00399 
00401     //
00407     DisplayObject* getFocus();
00408 
00410     //
00416     bool setFocus(DisplayObject* to);
00417     
00418     DSOEXPORT void add_invalidated_bounds(InvalidatedRanges& ranges,
00419             bool force);
00420     
00422     //
00429     DisplayObject* getActiveEntityUnderPointer() const;
00430 
00432     //
00436     const DisplayObject* getEntityUnderPointer() const;
00437 
00439     DisplayObject* getDraggingCharacter() const;
00440 
00441     bool testInvariant() const;
00442 
00444     enum DisplayState {
00445         DISPLAYSTATE_NORMAL,
00446         DISPLAYSTATE_FULLSCREEN
00447     };
00448 
00450     enum ScaleMode {
00451         SCALEMODE_SHOWALL,
00452         SCALEMODE_NOSCALE,
00453         SCALEMODE_EXACTFIT,
00454         SCALEMODE_NOBORDER
00455     };
00456 
00458     enum StageHorizontalAlign {
00459         STAGE_H_ALIGN_C,
00460         STAGE_H_ALIGN_L,
00461         STAGE_H_ALIGN_R
00462     };
00463 
00465     enum StageVerticalAlign {
00466         STAGE_V_ALIGN_C,
00467         STAGE_V_ALIGN_T,       
00468         STAGE_V_ALIGN_B
00469     };
00470 
00472     enum AlignMode {
00473         STAGE_ALIGN_L,
00474         STAGE_ALIGN_T,
00475         STAGE_ALIGN_R,
00476         STAGE_ALIGN_B
00477     };
00478 
00480     enum AllowScriptAccessMode {
00481         SCRIPT_ACCESS_NEVER,
00482         SCRIPT_ACCESS_SAME_DOMAIN,
00483         SCRIPT_ACCESS_ALWAYS
00484     };
00485 
00487     void setQuality(Quality q);
00488 
00490     Quality getQuality() const { return _quality; }
00491 
00494     void setStageAlignment(short s);
00495 
00498     void setAllowScriptAccess(AllowScriptAccessMode mode);
00499     
00501     AllowScriptAccessMode getAllowScriptAccess();
00502 
00503     typedef std::pair<StageHorizontalAlign, StageVerticalAlign> StageAlign;
00504 
00507     StageAlign getStageAlignment() const;
00508 
00511     bool getShowMenuState() const;
00512     
00515     void setShowMenuState(bool state);
00516 
00518     void setStageScaleMode(ScaleMode sm);
00519     
00521     ScaleMode getStageScaleMode() const { return _scaleMode; }
00522 
00523     // The string representation of the current align mode.
00524     std::string getStageAlignMode() const;
00525 
00527     DisplayState getStageDisplayState() const { return _displayState; }
00528 
00529     // The string representation of the current align mode.
00530     void setStageDisplayState(const DisplayState ds);
00531 
00533     enum ActionPriorityLevel {
00535         PRIORITY_INIT,
00537         PRIORITY_CONSTRUCT,
00539         PRIORITY_DOACTION,
00541         PRIORITY_SIZE
00542     };
00543 
00545     //
00549     typedef boost::array<boost::ptr_deque<ExecutableCode>, PRIORITY_SIZE>
00550         ActionQueue;
00551 
00553     void pushAction(std::auto_ptr<ExecutableCode> code, size_t lvl);
00554 
00556     void pushAction(const action_buffer& buf, DisplayObject* target);
00557 
00559     //
00568     void markReachableResources() const;
00569 
00573     //
00578     void addLiveChar(MovieClip* ch)
00579     {
00580         // Don't register the object in the list twice 
00581 #if GNASH_PARANOIA_LEVEL > 1
00582         assert(std::find(_liveChars.begin(), _liveChars.end(), ch) ==
00583             _liveChars.end());
00584 #endif
00585         _liveChars.push_front(ch);
00586     }
00587 
00589     void reset();
00590 
00592     //
00602     void disableScripts();
00603 
00605     bool scriptsDisabled() const { return _disableScripts; };
00606 
00609     //
00615     void flushHigherPriorityActionQueues();
00616 
00617     DisplayObject* findCharacterByTarget(const std::string& tgtstr) const;
00618 
00620     //
00624     //
00636     void loadMovie(const std::string& url, const std::string& target,
00637             const std::string& data, MovieClip::VariablesMethod method,
00638             as_object* handler=0)
00639     {
00640         _movieLoader.loadMovie(url, target, data, method, handler);
00641     }
00642 
00644     //
00648     //
00656     void getURL(const std::string& urlstr, const std::string& target,
00657             const std::string& data, MovieClip::VariablesMethod method);
00658 
00659 
00660     key::code lastKeyEvent() const {
00661         return _lastKeyEvent;
00662     }
00663 
00664     const Keys& unreleasedKeys() const {
00665         return _unreleasedKeys;
00666     }
00667 
00669     //
00673     void registerClass(const SWF::DefinitionTag* sprite, as_function* cls);
00674 
00676     //
00680     as_function* getRegisteredClass(const SWF::DefinitionTag* sprite) const;
00681 
00684     void setHostFD(int fd) {
00685         assert(fd >= 0);
00686         _hostfd = fd;
00687     }
00688 
00691     void setControlFD(int fd) {
00692         _controlfd = fd;
00693     }
00694 
00699     int getHostFD() const {
00700         return _hostfd;
00701     }
00702 
00703     int getControlFD() const {
00704         return _controlfd;
00705     }
00706 
00716     DSOEXPORT void registerFSCommandCallback(FsCallback* handler) {
00717         _fsCommandHandler = handler;
00718     }
00719 
00721     DSOEXPORT void handleFsCommand(const std::string& cmd,
00722             const std::string& arg) const;
00723     
00730     DSOEXPORT void registerEventCallback(HostInterface* handler) {
00731         _interfaceHandler = handler;
00732     }
00733 
00735     //
00737     void callInterface(const HostInterface::Message& e) const;
00738 
00740     //
00745     //
00748     template<typename T> T callInterface(const HostInterface::Message& e) const;
00749 
00754     //
00765     void setScriptLimits(boost::uint16_t recursion, boost::uint16_t timeout);
00766     
00769     boost::uint16_t getRecursionLimit() const {
00770         return _recursionLimit;
00771     }
00772 
00775     boost::uint16_t getTimeoutLimit() const
00776     {
00777         return _timeoutLimit;
00778     }
00779 
00780 #ifdef USE_SWFTREE
00781     typedef tree<std::pair<std::string, std::string> > InfoTree;
00782     void getMovieInfo(InfoTree& tr, InfoTree::iterator it);
00783     void getCharacterTree(InfoTree& tr, InfoTree::iterator it);
00784 #endif
00785 
00786     const RunResources& runResources() const { return _runResources; }
00787 
00789     void addExternalCallback(const std::string& name, as_object* callback);
00790 
00791     bool processInvoke(ExternalInterface::invoke_t *);
00792 
00793     std::string callExternalCallback(const std::string &name, 
00794                                      const std::vector<as_value>& args);
00795     
00796     std::string callExternalJavascript(const std::string &name, 
00797                                        const std::vector<as_value>& args);
00798 
00800     //
00805     void removeQueuedConstructor(MovieClip* target);
00806 
00807     GC& gc() {
00808         return _gc;
00809     }
00810 
00812     //
00815     bool queryInterface(const std::string& what) const;
00816 
00818     //
00822     //
00828     void setStreamBlock(int id, int block);
00829 
00831     //
00834     //
00836     void stopStream(int id);
00837 
00838 private:
00839 
00841     //
00863     void setRootMovie(Movie* movie);
00864 
00866     bool notify_mouse_listeners(const event_id& event);
00867     
00871     bool fire_mouse_event();
00872 
00874     void doMouseDrag();
00875 
00877     void executeAdvanceCallbacks();
00878     
00880     void executeTimers();
00881 
00883     void cleanupAndCollect();
00884 
00888     //
00900     InteractiveObject* getTopmostMouseEntity(boost::int32_t x,
00901             boost::int32_t y) const;
00902 
00905     void cleanupDisplayList();
00906 
00908     void advanceLiveChars();
00909 
00913     void setInvalidated() { _invalidated = true; }
00914 
00916     //
00919     void clearInvalidated() { _invalidated = false; }
00920 
00922     //
00929     bool isInvalidated() { return _invalidated; }
00930 
00932     //
00935     size_t minPopulatedPriorityQueue() const;
00936 
00940     size_t processActionQueue(size_t lvl);
00941 
00942     bool processingActions() const {
00943         return (_processingActionLevel < PRIORITY_SIZE);
00944     }
00945 
00946     const DisplayObject* findDropTarget(boost::int32_t x, boost::int32_t y,
00947             DisplayObject* dragging) const;
00948 
00949     void handleActionLimitHit(const std::string& ref);
00950 
00951     typedef std::list<Button*> ButtonListeners;
00952     ButtonListeners _buttonListeners;
00953 
00954     GC _gc;
00955 
00956     const RunResources& _runResources; 
00957 
00960     VM _vm;
00961 
00963     HostInterface* _interfaceHandler;
00964 
00966     FsCallback* _fsCommandHandler;
00967 
00969     //
00974     typedef std::list<MovieClip*> LiveChars;
00975 
00977     LiveChars _liveChars;
00978 
00979     ActionQueue _actionQueue;
00980 
00982     void processActionQueue();
00983 
00985     size_t _stageWidth;
00986     size_t _stageHeight;
00987 
00988     rgba m_background_color;
00989     bool m_background_color_set;
00990 
00991     boost::int32_t _mouseX;
00992     boost::int32_t _mouseY;
00993 
00994     MouseButtonState  _mouseButtonState;
00995 
00997     typedef std::set<ActiveRelay*> ObjectCallbacks;
00998     ObjectCallbacks _objectCallbacks;
00999 
01000     LoadCallbacks _loadCallbacks;
01001     
01002     typedef std::map<boost::uint32_t, boost::shared_ptr<Timer> > TimerMap;
01003 
01004     TimerMap _intervalTimers;
01005 
01006     size_t _lastTimerId;
01007 
01009     Keys _unreleasedKeys;   
01010 
01011     key::code _lastKeyEvent;
01012 
01014     DisplayObject* _currentFocus;
01015 
01017     boost::optional<DragState> _dragState;
01018 
01019     typedef std::map<int, MovieClip*> Levels;
01020 
01022     //
01026     Levels _movies;
01027 
01028     typedef std::map<const SWF::DefinitionTag*, as_function*> RegisteredClasses;
01029     RegisteredClasses _registeredClasses;
01030 
01034     Movie* _rootMovie;
01035 
01037     bool _invalidated;
01038 
01041     bool _disableScripts;
01042     int _processingActionLevel;
01043     
01045     //
01047     int _hostfd;
01048     int _controlfd;
01049 
01051     //
01054     Quality _quality;
01055 
01057     std::bitset<4u> _alignMode;
01058 
01059     AllowScriptAccessMode _allowScriptAccess;
01060 
01062     bool _showMenu;
01063 
01065     ScaleMode _scaleMode;
01066 
01068     DisplayState _displayState;
01069     
01070     // Maximum number of recursions set in the ScriptLimits tag.
01071     boost::uint16_t _recursionLimit;
01072 
01073     // Timeout in seconds for script execution, set in the ScriptLimits tag.
01074     boost::uint16_t _timeoutLimit;
01075 
01076     // delay between movie advancement, in milliseconds
01077     size_t _movieAdvancementDelay;
01078 
01079     // time of last movie advancement, in milliseconds
01080     size_t _lastMovieAdvancement;
01081 
01083     size_t _unnamedInstance;
01084 
01085     MovieLoader _movieLoader;
01086 
01087     struct SoundStream {
01088         SoundStream(int i, int b) : id(i), block(b) {}
01089         int id;
01090         int block;
01091     };
01092 
01093     boost::optional<SoundStream> _timelineSound;
01094 };
01095 
01097 //
01105 bool isLevelTarget(int version, const std::string& name, unsigned int& levelno);
01106 
01107 DSOEXPORT short stringToStageAlign(const std::string& s);
01108 
01109 template<typename T>
01110 T
01111 movie_root::callInterface(const HostInterface::Message& e) const
01112 {
01113     if (!_interfaceHandler) {
01114         log_error("Hosting application registered no callback for "
01115                 "messages, can't call %s(%s)");
01116         return T();
01117     }
01118 
01119     try {
01120         return boost::any_cast<T>(_interfaceHandler->call(e));
01121     }
01122     catch (const boost::bad_any_cast&) {
01123         log_error(_("Unexpected type from host interface when requesting "
01124                 "%1%"), e); 
01125         return T();
01126     }
01127 }
01128 
01129 } // namespace gnash
01130 
01131 #endif // GNASH_MOVIE_ROOT_H
01132 
01133 // Local Variables:
01134 // mode: C++
01135 // indent-tabs-mode: nil
01136 // End: