Plug more leaks (in the test, not the core)
[gnash.git] / gui / gnash.cpp
blob16d5761bbc0ea54b5beb1c3a1f0bdb02c209d900
1 // gnash.cpp: Main routine for top-level SWF player, for Gnash.
2 //
3 // Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010 Free Software
4 // Foundation, Inc
5 //
6 // This program is free software; you can redistribute it and/or modify
7 // it under the terms of the GNU General Public License as published by
8 // the Free Software Foundation; either version 3 of the License, or
9 // (at your option) any later version.
10 //
11 // This program is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
16 // You should have received a copy of the GNU General Public License
17 // along with this program; if not, write to the Free Software
18 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21 #ifdef HAVE_CONFIG_H
22 #include "gnashconfig.h"
23 #endif
25 #include <string>
26 #include <iostream>
27 #include <iterator>
28 #include <ios>
29 #include <boost/format.hpp>
30 #include <boost/program_options.hpp>
31 #include <boost/algorithm/string/join.hpp>
32 #include <boost/algorithm/string/split.hpp>
33 #include <boost/algorithm/string/classification.hpp>
34 #include <boost/function.hpp>
35 #include <cstdlib>
36 #include <utility>
37 #include <functional>
38 #ifdef ENABLE_NLS
39 # include <clocale>
40 #endif
42 #include "Player.h"
43 #include "log.h"
44 #include "rc.h" // for use of rcfile
45 #include "GnashNumeric.h" // for clamp
46 #include "GnashException.h"
47 #include "revno.h"
48 #include "MediaHandler.h"
49 #include "utility.h"
50 #include "accumulator.h"
52 using std::endl;
53 using std::cout;
55 std::vector<std::string> infiles;
56 std::string url;
58 namespace gnash {
59 class Player;
62 namespace {
63 gnash::LogFile& dbglogfile = gnash::LogFile::getDefaultInstance();
64 gnash::RcInitFile& rcfile = gnash::RcInitFile::getDefaultInstance();
67 // Forward declarations
68 namespace {
69 namespace po = boost::program_options;
70 po::options_description getSupportedOptions(gnash::Player& p);
72 void setupSoundAndRendering(gnash::Player& p, int i);
73 void setupFlashVars(gnash::Player& p,
74 const std::vector<std::string>& params);
75 void setupFDs(gnash::Player& p, const std::string& fds);
77 void usage_gui_keys(std::ostream& os);
78 void usage(std::ostream& os, const po::options_description& opts);
79 void build_options(std::ostream& os);
80 void version_and_copyright(std::ostream& os);
83 int
84 main(int argc, char *argv[])
87 std::ios::sync_with_stdio(false);
89 // Enable native language support, i.e. internationalization
90 #ifdef ENABLE_NLS
91 std::setlocale (LC_ALL, "");
92 bindtextdomain (PACKAGE, LOCALEDIR);
93 textdomain (PACKAGE);
94 #endif
96 gnash::Player player;
98 po::options_description opts = getSupportedOptions(player);
100 // Add all positional arguments as input files.
101 po::positional_options_description files;
102 files.add("input-file", -1);
104 namespace cls = po::command_line_style;
106 po::variables_map vm;
107 try {
108 po::store(po::command_line_parser(argc, argv)
109 .options(opts)
110 .positional(files)
111 .style(cls::default_style ^ cls::allow_guessing)
112 .run(), vm);
114 catch (const po::error& e) {
115 std::cerr << boost::format(_("Error parsing options: %s\n"))
116 % e.what();
117 return EXIT_FAILURE;
120 po::notify(vm);
122 if (vm.count("help")) {
123 version_and_copyright(std::cout);
124 usage(std::cout, opts);
125 return EXIT_SUCCESS;
128 if (vm.count("version")) {
129 version_and_copyright(std::cout);
130 build_options(std::cout);
131 return EXIT_SUCCESS;
134 // Do some extra sanity checks on the options.
135 const bool plugin = vm.count("xid");
137 if (plugin && vm.count("height") && vm.count("width") &&
138 !player.getHeight() && !player.getWidth()) {
139 // We were given dimensions of 0x0 to render to (probably the plugin
140 // is playing an "invisible" movie. Disable video rendering.
141 player.setDoRender(false);
144 if (!vm.count("render-mode")) {
145 std::cerr << "Using rcfile\n";
146 if (plugin) {
147 player.setDoSound(rcfile.usePluginSound());
149 else {
150 player.setDoSound(rcfile.useSound());
154 // No file name was supplied
155 if (infiles.empty()) {
156 std::cerr << _("Error: no input file was specified. Exiting.\n");
157 usage(std::cerr, opts);
158 return EXIT_FAILURE;
161 // We only expect GnashExceptions here. No others should be thrown!
162 try {
163 player.run(argc, argv, infiles.front(), url);
165 catch (const gnash::GnashException& ex) {
166 std::cerr << "Error: " << ex.what() << "\n";
167 return EXIT_FAILURE;
169 return EXIT_SUCCESS;
172 namespace {
174 void
175 setupFlashVars(gnash::Player& p, const std::vector<std::string>& params)
177 for (std::vector<std::string>::const_iterator i = params.begin(),
178 e = params.end(); i != e; ++i) {
179 const std::string& param = *i;
180 const size_t eq = param.find("=");
181 if (eq == std::string::npos) {
182 p.setParam(param, "true");
183 return;
185 const std::string name = param.substr(0, eq);
186 const std::string value = param.substr(eq + 1);
187 p.setParam(name, value);
191 void
192 setupFDs(gnash::Player& p, const std::string& fds)
194 int hostfd = 0, controlfd = 0;
195 hostfd = std::strtol(fds.substr(0, fds.find(":")).c_str(), NULL, 0);
196 std::string csub = fds.substr(fds.find(":")+1, fds.size());
197 controlfd = strtol(csub.c_str(), 0, 0);
198 gnash::log_debug(_("Host FD #%d, Control FD #%d\n"),
199 hostfd, controlfd);
201 if (hostfd < 0) {
202 std::cerr << boost::format(_("Invalid host communication "
203 "filedescriptor %1%\n")) % hostfd;
204 std::exit(EXIT_FAILURE);
206 p.setHostFD(hostfd);
208 if (controlfd < 0) {
209 std::cerr << boost::format(_("Invalid control communication "
210 "filedescriptor %1%\n")) % controlfd;
211 std::exit(EXIT_FAILURE);
213 p.setControlFD(controlfd);
216 void
217 setupSoundAndRendering(gnash::Player& p, int i)
219 switch (i) {
220 case 0:
221 // Disable both
222 p.setDoRender(false);
223 p.setDoSound(false);
224 return;
225 case 1:
226 // Enable rendering, disable sound
227 p.setDoRender(true);
228 p.setDoSound(false);
229 return;
230 case 2:
231 // Enable sound, disable rendering
232 p.setDoRender(false);
233 p.setDoSound(true);
234 return;
235 case 3:
236 // Enable render & sound
237 p.setDoRender(true);
238 p.setDoSound(true);
239 return;
240 default:
241 gnash::log_error(_("ERROR: -r must be followed by "
242 "0, 1, 2 or 3 "));
246 po::options_description
247 getDebuggingOptions(gnash::Player& p)
249 #ifndef GNASH_FPS_DEBUG
250 UNUSED(p);
251 #endif
253 using gnash::Player;
254 using gnash::LogFile;
255 using gnash::RcInitFile;
257 po::options_description desc(_("Debugging options"));
259 desc.add_options()
261 ("verbose,v", accumulator<int>()
262 ->notifier(boost::bind(&LogFile::setVerbosity, &dbglogfile, _1)),
263 _("Produce verbose output"))
265 ("writelog,w", po::bool_switch()
266 ->notifier(boost::bind(&RcInitFile::useWriteLog, &rcfile, _1)),
267 _("Produce the disk based debug log"))
269 #if VERBOSE_ACTION
270 ("verbose-actions,a", po::bool_switch()
271 ->notifier(boost::bind(&LogFile::setActionDump, &dbglogfile, _1)),
272 _("Be (very) verbose about action execution"))
273 #endif
275 #if VERBOSE_PARSE
276 ("verbose-parsing,p", po::bool_switch()
277 ->notifier(boost::bind(&LogFile::setParserDump, &dbglogfile, _1)),
278 _("Be (very) verbose about parsing"))
279 #endif
281 #ifdef GNASH_FPS_DEBUG
282 ("debug-fps,f", po::value<float>()
283 ->notifier(boost::bind(&Player::setFpsPrintTime, &p, _1)),
284 _("Print FPS every num seconds"))
285 #endif
289 return desc;
292 po::options_description
293 getSupportedOptions(gnash::Player& p)
295 using std::string;
296 using gnash::Player;
297 using gnash::LogFile;
298 using gnash::RcInitFile;
300 std::vector<std::string> handlers;
301 gnash::media::MediaFactory::instance().listKeys(back_inserter(handlers));
303 std::vector<std::string> renderers;
304 boost::split(renderers, RENDERER_CONFIG,
305 boost::is_any_of(" "), boost::token_compress_on);
307 po::options_description desc(_("Options"));
309 desc.add_options()
311 ("help,h",
312 _("Print this help and exit"))
314 ("version,V",
315 _("Print version information and exit"))
317 ("scale,s", po::value<float>()
318 ->notifier(boost::bind(&Player::setScale, &p,
319 boost::bind(gnash::clamp<float>, _1, 0.01f, 100.f))),
320 _("Scale the movie by the specified factor"))
322 ("delay,d", po::value<int>()
323 ->notifier(boost::bind(&Player::setDelay, &p, _1)),
324 _("Number of milliseconds to delay in main loop"))
326 ("audio-dump,A", po::value<string>()
327 ->notifier(boost::bind(&Player::setAudioDumpfile, &p, _1)),
328 _("Audio dump file (wave format)"))
330 ("hwaccel", po::value<string>()
331 ->default_value("none")
332 ->notifier(boost::bind(&Player::setHWAccel, &p, _1)),
333 (string(_("Hardware Video Accelerator to use"))
334 + string("\nnone|vaapi")). c_str())
336 ("xid,x", po::value<long>()
337 ->notifier(boost::bind(&Player::setWindowId, &p, _1)),
338 _("X11 Window ID for display"))
340 ("width,j", po::value<int>()
341 ->notifier(boost::bind(&Player::setWidth, &p, _1)),
342 _("Set window width"))
344 ("height,k", po::value<int>()
345 ->notifier(boost::bind(&Player::setHeight, &p, _1)),
346 _("Set window height"))
348 ("x-pos,X", po::value<int>()
349 ->notifier(boost::bind(&Player::setXPosition, &p, _1)),
350 _("Set window x position"))
352 ("y-pos,Y", po::value<int>()
353 ->notifier(boost::bind(&Player::setYPosition, &p, _1)),
354 _("Set window y position"))
356 ("once,1", po::bool_switch()
357 ->notifier(boost::bind(&Player::setDoLoop, &p,
358 boost::bind(std::logical_not<bool>(), _1))),
359 _("Exit when/if movie reaches the last frame"))
361 ("render-mode,r", po::value<int>()
362 ->default_value(3)
363 ->notifier(boost::bind(&setupSoundAndRendering, boost::ref(p), _1)),
364 (string("0 ")
365 + string(_("disable rendering and sound"))
366 + string("\n1 ")
367 + string(_("enable rendering, disable sound"))
368 + string("\n2 ")
369 + string(_("enable sound, disable rendering"))
370 + string("\n3 ")
371 + string(_("enable rendering and sound"))
372 ).c_str())
374 ("media,M", po::value<string>()
375 ->default_value(handlers.front())
376 ->notifier(boost::bind(&Player::setMedia, &p, _1)),
377 (string(_("The media handler to use"))
378 + string("\n") + boost::join(handlers, "|")
379 ).c_str())
381 ("renderer,R", po::value<string>()
382 ->default_value("agg")
383 ->notifier(boost::bind(&Player::setRenderer, &p, _1)),
384 (string(_("The renderer to use"))
385 + string("\n") + boost::join(renderers, "|")
386 ).c_str())
388 ("timeout,t", po::value<float>()
389 ->notifier(boost::bind(&Player::setExitTimeout, &p, _1)),
390 _("Exit after the specified number of seconds"))
392 ("real-url,u", po::value<string>(&url),
393 _("Set \"real\" URL of the movie"))
395 ("base-url,U", po::value<string>()
396 ->notifier(boost::bind(&Player::setBaseUrl, &p, _1)),
397 _("Set \"base\" URL for resolving relative URLs"))
399 ("param,P", po::value<std::vector<std::string> >()
400 ->composing()
401 ->notifier(boost::bind(&setupFlashVars, boost::ref(p), _1)),
402 _("Set parameter (e.g. \"FlashVars=A=1&b=2\")"))
404 ("fd,F", po::value<string>()
405 ->notifier(boost::bind(&setupFDs, boost::ref(p), _1)),
406 (string(_("Filedescriptor to use for external communications"))
407 + string(" <fd>:<fd>")
408 ).c_str())
410 ("max-advances", po::value<size_t>()
411 ->notifier(boost::bind(&Player::setMaxAdvances, &p, _1)),
412 _("Exit after specified number of frame advances"))
414 ("fullscreen", po::bool_switch()
415 ->notifier(boost::bind(&Player::setStartFullscreen, &p, _1)),
416 _("Start in fullscreen mode"))
418 // TODO: move to GUIs actually implementing this
419 ("hide-menubar", po::bool_switch()
420 ->notifier(boost::bind(&Player::hideMenu, &p, _1)),
421 _("Start without displaying the menu bar"))
423 // TODO: do this in ScreenShotter class.
424 ("screenshot", po::value<string>()
425 ->notifier(boost::bind(&Player::setScreenShots, &p, _1)),
426 _("List of frames to save as screenshots"))
428 ("screenshot-file", po::value<string>()
429 ->notifier(boost::bind(&Player::setScreenShotFile, &p, _1)),
430 _("Filename pattern for screenshot images"))
432 ("screenshot-quality", po::value<size_t>()
433 ->notifier(boost::bind(&Player::setScreenShotQuality, &p, _1)),
434 _("Quality for screenshot output (not all formats)"))
436 ("input-file", po::value<std::vector<std::string> >(&infiles),
437 _("Input files"))
440 desc.add(getDebuggingOptions(p));
443 // Add gui-specific options
444 // TODO make this somehow cleaner, maybe add a signature
445 // for such function in each of the gui's mains
446 // like getGuiOptions()
447 #ifdef GUI_DUMP
448 po::options_description dumpOpts (_("Dump options"));
450 dumpOpts.add_options()
452 (",D", po::value<string>(),
453 _("Video dump file (raw format) and optional video FPS (@<num>)"))
454 (",S", po::value<string>(),
455 _("Number of milliseconds to sleep between advances"))
458 desc.add(dumpOpts);
459 #endif
461 return desc;
464 void
465 usage_gui_keys(std::ostream& os)
467 os << _("Keys:\n")
468 << " CTRL-Q, CTRL-W "
469 << _("Quit\n")
470 << " CTRL-F "
471 << _("Toggle fullscreen\n")
472 << " CTRL-P "
473 << _("Toggle pause\n")
474 << " CTRL-R "
475 << _("Restart the movie\n")
476 << " CTRL-O "
477 << _("Take a screenshot\n")
478 << " CTRL-L "
479 << _("Force immediate redraw\n");
482 void
483 usage(std::ostream& os, const po::options_description& opts)
485 os << _("Usage: gnash [options] movie_file.swf\n")
486 << _("Plays a SWF (Shockwave Flash) movie\n")
487 << opts << "\n";
489 // Add gui keys
490 // TODO: stop printing these in here ?
491 usage_gui_keys(os);
493 os << std::endl;
496 void
497 version_and_copyright(std::ostream& os)
499 os << "Gnash "
500 << VERSION " ("
501 << BRANCH_NICK << "-" << BRANCH_REVNO << "-" << COMMIT_ID
502 << ")" << endl << endl
503 << _("Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010 "
504 "Free Software Foundation, Inc.\n"
505 "Gnash comes with NO WARRANTY, to the extent permitted "
506 "by law.\nYou may redistribute copies of Gnash under the "
507 "terms of the GNU General\nPublic License. For more "
508 "information, see the file named COPYING.\n\n");
511 void
512 build_options(std::ostream& os)
514 os << _("Build options ") << endl
515 << _(" Renderers: ") << RENDERER_CONFIG << endl
516 << _(" Hardware Acceleration: ") << HWACCEL_CONFIG << endl
517 << _(" GUI: ") << GUI_CONFIG << endl
518 << _(" Media handlers: ") << MEDIA_CONFIG << endl
520 << _(" Configured with: ") << CONFIG_CONFIG << endl
521 << _(" CXXFLAGS: ") << CXXFLAGS << endl;
525 } // unnamed namespace