/// \brief Run, used to open a new flash file. Using previous initialization void Player::run(int argc, char* argv[], const std::string& infile, const std::string& url) { // Call this at run() time, so the caller has // a cache of setting some parameter before calling us... // (example: setDoSound(), setWindowId() etc.. ) init_logfile(); // gnash.cpp should check that a filename is supplied. assert (!infile.empty()); _infile = infile; // Work out base url if (_baseurl.empty()) { if (!url.empty()) _baseurl = url; else if (infile == "-") _baseurl = URL("./").str(); else _baseurl = infile; } // Set _root._url (either explicit of from infile) if (!url.empty()) { _url = url; } else { _url = infile; } // Parse player parameters. These are not passed to the SWF, but rather // control stage properties etc. // NOTE: it is intentional to force a trailing slash to "base" argument // as it was tested that the "base" argument is always considered // a directory! Params::const_iterator it = _params.find("base"); const URL baseURL = (it == _params.end()) ? _baseurl : URL(it->second+"/", _baseurl); /// The RunResources should be populated before parsing. _runResources.reset(new RunResources()); boost::shared_ptr<SWF::TagLoadersTable> loaders(new SWF::TagLoadersTable()); addDefaultLoaders(*loaders); _runResources->setTagLoaders(loaders); std::auto_ptr<NamingPolicy> np(new IncrementalRename(_baseurl)); /// The StreamProvider uses the actual URL of the loaded movie. boost::shared_ptr<StreamProvider> sp(new StreamProvider(_url, baseURL, np)); _runResources->setStreamProvider(sp); // Set the Hardware video decoding resources. none, vaapi, omap _runResources->setHWAccelBackend(_hwaccel); // Set the Renderer resource, opengl, openvg, agg, or cairo _runResources->setRenderBackend(_renderer); #ifdef USE_MEDIA _mediaHandler.reset(media::MediaFactory::instance().get(_media)); #endif if (!_media.empty() && !_mediaHandler.get()) { boost::format fmt = boost::format(_("Non-existent media handler %1% specified")) % _media; throw GnashException(fmt.str()); } _runResources->setMediaHandler(_mediaHandler); init_sound(); _runResources->setSoundHandler(_soundHandler); init_gui(); // Initialize gui (we need argc/argv for this) // note that this will also initialize the renderer // which is *required* during movie loading if (!_gui->init(argc, &argv)) { throw GnashException("Could not initialize GUI"); } // Parse querystring (before FlashVars, see // testsuite/misc-ming.all/FlashVarsTest*) setFlashVars(URL(_url).querystring()); // Add FlashVars. Params::const_iterator fv = _params.find("flashvars"); if (fv != _params.end()) { setFlashVars(fv->second); } // Load the actual movie. _movieDef = load_movie(); if (!_movieDef) { throw GnashException("Could not load movie!"); } // Get info about the width & height of the movie. const size_t movie_width = _movieDef->get_width_pixels(); const size_t movie_height = _movieDef->get_height_pixels(); if (! _width) { _width = static_cast<size_t>(movie_width * _scale); } if (! _height) { _height = static_cast<size_t>(movie_height * _scale); } if (!_width || !_height) { log_debug("Input movie has collapsed dimensions " "%d/%d. Setting to 1/1 and going on.", _width, _height); if (!_width) _width = 1; if (!_height) _height = 1; } // Register movie definition before creating the window _gui->setMovieDefinition(_movieDef.get()); // Now that we know about movie size, create gui window. _gui->createWindow(_url.c_str(), _width, _height, _xPosition, _yPosition); { // we construct movie_root in its own scope, to be sure it's destroyed // (bringing down the MovieLoader) before we clear the MovieLibrary movie_root root(_gui->getClock(), *_runResources); _callbacksHandler.reset(new CallbacksHandler(*_gui, *this)); // Register Player to receive events from the core (Mouse, Stage, // System etc) root.registerEventCallback(_callbacksHandler.get()); // Register Player to receive FsCommand events from the core. root.registerFSCommandCallback(_callbacksHandler.get()); // log_debug("Player Host FD #%d, Player Control FD #%d", _hostfd, _controlfd); // Set host requests fd (if any) if ( _hostfd != -1 ) { root.setHostFD(_hostfd); } if (_controlfd != -1) { root.setControlFD(_controlfd); } _gui->setStage(&root); // When startStopped is true, stop here after the stage has been // registered, but before the movie has started. Initial loading // and VM initialization have been done by this stage, but not // the complete parsing of the SWF. This is important because // the Gui accesses movie_root to get the sound_handler, but also // because the gui window should be properly set up by this point. RcInitFile& rcfile = RcInitFile::getDefaultInstance(); if (rcfile.startStopped()) { _gui->stop(); } // Start loader thread // NOTE: the loader thread might (in IMPORT tag parsing) // create new movies and register them to the MovieLibrary. // If MovieLibrary size exceeded, _movieDef might be // destroyed prematurely. movie_root might actually be // keeping it alive, as Gui might as well, but why relying // on luck ? So we made sure to keep _movieDef by // intrusive_ptr... _movieDef->completeLoad(); if (! _delay) { float fps = _movieDef->get_frame_rate(); // log_debug("Movie Frame Rate is %g, adjusting delay", fps); // FIXME: this value is arbitrary, and will make any movie with // less than 12 frames eat up more of the cpu. It should probably // be a much lower value, like 2. if (fps > 12) { _delay = static_cast<int>(1000/fps); } else { // 10ms per heart beat _delay = 10; } } // This is the time between the main loop waking up and processing // network messages, external calls, and displaying the next frame. _gui->setInterval(_delay); if (_exitTimeout) { _gui->setTimeout(static_cast<unsigned int>(_exitTimeout * 1000)); } if (!_windowID && _startFullscreen) { _gui->setFullscreen(); } if (!_windowID && _hideMenu) { _gui->hideMenu(); } // Now handle stage alignment and scale mode. This should be done after // the GUI is created, after its stage member is set, and after the // interface callbacks are registered. it = _params.find("salign"); if (it != _params.end()) { log_debug("Setting align"); const short align = stringToStageAlign(it->second); root.setStageAlignment(align); } it = _params.find("allowscriptaccess"); if (it != _params.end()) { StringNoCaseEqual noCaseCompare; const std::string& str = it->second; movie_root::AllowScriptAccessMode mode = movie_root::SCRIPT_ACCESS_SAME_DOMAIN; if (noCaseCompare(str, "never")) { mode = movie_root::SCRIPT_ACCESS_NEVER; } else if (noCaseCompare(str, "sameDomain")) { mode = movie_root::SCRIPT_ACCESS_SAME_DOMAIN; } else if (noCaseCompare(str, "always")) { mode = movie_root::SCRIPT_ACCESS_ALWAYS; } log_debug("Setting allowscriptaccess to %s", mode); root.setAllowScriptAccess(mode); } it = _params.find("scale"); if (it != _params.end()) { StringNoCaseEqual noCaseCompare; const std::string& str = it->second; movie_root::ScaleMode mode = movie_root::SCALEMODE_SHOWALL; if (noCaseCompare(str, "noScale")) { mode = movie_root::SCALEMODE_NOSCALE; } else if (noCaseCompare(str, "exactFit")) { mode = movie_root::SCALEMODE_EXACTFIT; } else if (noCaseCompare(str, "noBorder")) { mode = movie_root::SCALEMODE_NOBORDER; } log_debug("Setting scale mode"); root.setStageScaleMode(mode); } // Set up screenshots. if (!_screenshots.empty()) { std::istringstream is(_screenshots); std::string arg; bool last = false; ScreenShotter::FrameList v; while (std::getline(is, arg, ',')) { if (arg == "last") last = true; else try { const size_t frame = boost::lexical_cast<size_t>(arg); v.push_back(frame); } catch (const boost::bad_lexical_cast&) {} } // Use default if filename is empty. if (_screenshotFile.empty()) { URL url(_runResources->streamProvider().baseURL()); std::string::size_type p = url.path().rfind('/'); const std::string& name = (p == std::string::npos) ? url.path() : url.path().substr(p + 1); _screenshotFile = "screenshot-" + name + "-%f"; } if (!last && v.empty()) return; std::auto_ptr<ScreenShotter> ss(new ScreenShotter(_screenshotFile, _screenshotQuality)); if (last) ss->lastFrame(); ss->setFrames(v); _gui->setScreenShotter(ss); } _gui->run(); log_debug("Main loop ended, cleaning up"); } // Clean up the MovieLibrary so left-over SWFMovieDefinitions // get destroyed and join any loader thread MovieFactory::clear(); }