enable docbook, don't gzip man pages
[gnash.git] / gui / gnash.cpp
blob600ab1f132c2b3b77af658b1a506c3aac9ae325a
1 // gnash.cpp: Main routine for top-level SWF player, for Gnash.
2 //
3 // Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010,
4 // 2011 Free Software 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 <boost/bind.hpp>
36 #include <algorithm>
37 #include <cstdlib>
38 #include <utility>
39 #include <functional>
40 #ifdef ENABLE_NLS
41 # include <clocale>
42 #endif
44 #include "Player.h"
45 #include "log.h"
46 #include "rc.h" // for use of rcfile
47 #include "GnashNumeric.h" // for clamp
48 #include "GnashException.h"
49 #include "revno.h"
50 #include "MediaHandler.h"
51 #include "utility.h"
52 #include "accumulator.h"
54 using std::endl;
55 using std::cout;
57 std::vector<std::string> infiles;
58 std::string url;
60 namespace gnash {
61 class Player;
64 namespace {
65 gnash::LogFile& dbglogfile = gnash::LogFile::getDefaultInstance();
66 gnash::RcInitFile& rcfile = gnash::RcInitFile::getDefaultInstance();
69 // Forward declarations
70 namespace {
71 namespace po = boost::program_options;
72 po::options_description getSupportedOptions(gnash::Player& p);
74 void setupSoundAndRendering(gnash::Player& p, int i);
75 void setupFlashVars(gnash::Player& p,
76 const std::vector<std::string>& params);
77 void setupFDs(gnash::Player& p, const std::string& fds);
79 void usage_gui_keys(std::ostream& os);
80 void usage(std::ostream& os, const po::options_description& opts);
81 void build_options(std::ostream& os);
82 void version_and_copyright(std::ostream& os);
85 void
86 playFile(gnash::Player& player, int argc, char *argv[],
87 const std::string& filename)
89 gnash::Player newPlayer(player);
90 newPlayer.run(argc, argv, filename, url);
93 int
94 main(int argc, char *argv[])
97 std::ios::sync_with_stdio(false);
99 // Enable native language support, i.e. internationalization
100 #ifdef ENABLE_NLS
101 std::setlocale (LC_ALL, "");
102 bindtextdomain (PACKAGE, LOCALEDIR);
103 textdomain (PACKAGE);
104 #endif
106 gnash::Player player;
108 po::options_description opts = getSupportedOptions(player);
110 // Add all positional arguments as input files.
111 po::positional_options_description files;
112 files.add("input-file", -1);
114 namespace cls = po::command_line_style;
116 po::variables_map vm;
117 try {
118 po::store(po::command_line_parser(argc, argv)
119 .options(opts)
120 .positional(files)
121 .style(cls::default_style ^ cls::allow_guessing)
122 .run(), vm);
124 catch (const po::error& e) {
125 std::cerr << boost::format(_("Error parsing options: %s\n"))
126 % e.what();
127 return EXIT_FAILURE;
130 po::notify(vm);
132 if (vm.count("help")) {
133 version_and_copyright(std::cout);
134 usage(std::cout, opts);
135 return EXIT_SUCCESS;
138 if (vm.count("version")) {
139 version_and_copyright(std::cout);
140 build_options(std::cout);
141 return EXIT_SUCCESS;
144 // Do some extra sanity checks on the options.
145 const bool plugin = vm.count("xid");
147 if (plugin && vm.count("height") && vm.count("width") &&
148 !player.getHeight() && !player.getWidth()) {
149 // We were given dimensions of 0x0 to render to (probably the plugin
150 // is playing an "invisible" movie. Disable video rendering.
151 player.setDoRender(false);
154 if (!vm.count("render-mode")) {
155 std::cerr << "Using rcfile\n";
156 if (plugin) {
157 player.setDoSound(rcfile.usePluginSound());
159 else {
160 player.setDoSound(rcfile.useSound());
164 // No file name was supplied
165 if (infiles.empty()) {
166 std::cerr << _("Error: no input file was specified. Exiting.\n");
167 usage(std::cerr, opts);
168 return EXIT_FAILURE;
171 // We only expect GnashExceptions here. No others should be thrown!
172 try {
173 std::for_each(infiles.begin(), infiles.end(),
174 boost::bind(&playFile, boost::ref(player), argc, argv, _1));
176 catch (const gnash::GnashException& ex) {
177 std::cerr << "Error: " << ex.what() << "\n";
178 return EXIT_FAILURE;
180 return EXIT_SUCCESS;
183 namespace {
185 void
186 setupFlashVars(gnash::Player& p, const std::vector<std::string>& params)
188 for (std::vector<std::string>::const_iterator i = params.begin(),
189 e = params.end(); i != e; ++i) {
190 const std::string& param = *i;
191 const size_t eq = param.find("=");
192 if (eq == std::string::npos) {
193 p.setParam(param, "true");
194 return;
196 const std::string name = param.substr(0, eq);
197 const std::string value = param.substr(eq + 1);
198 p.setParam(name, value);
202 void
203 setupFDs(gnash::Player& p, const std::string& fds)
205 int hostfd = 0, controlfd = 0;
206 hostfd = std::strtol(fds.substr(0, fds.find(":")).c_str(), NULL, 0);
207 std::string csub = fds.substr(fds.find(":")+1, fds.size());
208 controlfd = strtol(csub.c_str(), 0, 0);
209 // gnash::log_debug("Host FD #%d, Control FD #%d\n", hostfd, controlfd);
211 if (hostfd < 0) {
212 std::cerr << boost::format(_("Invalid host communication "
213 "filedescriptor %1%\n")) % hostfd;
214 std::exit(EXIT_FAILURE);
216 p.setHostFD(hostfd);
218 if (controlfd < 0) {
219 std::cerr << boost::format(_("Invalid control communication "
220 "filedescriptor %1%\n")) % controlfd;
221 std::exit(EXIT_FAILURE);
223 p.setControlFD(controlfd);
226 void
227 setupSoundAndRendering(gnash::Player& p, int i)
229 switch (i) {
230 case 0:
231 // Disable both
232 p.setDoRender(false);
233 p.setDoSound(false);
234 return;
235 case 1:
236 // Enable rendering, disable sound
237 p.setDoRender(true);
238 p.setDoSound(false);
239 return;
240 case 2:
241 // Enable sound, disable rendering
242 p.setDoRender(false);
243 p.setDoSound(true);
244 return;
245 case 3:
246 // Enable render & sound
247 p.setDoRender(true);
248 p.setDoSound(true);
249 return;
250 default:
251 gnash::log_error(_("ERROR: -r must be followed by "
252 "0, 1, 2 or 3 "));
256 po::options_description
257 getDebuggingOptions(gnash::Player& p)
259 #ifndef GNASH_FPS_DEBUG
260 UNUSED(p);
261 #endif
263 using gnash::Player;
264 using gnash::LogFile;
265 using gnash::RcInitFile;
267 po::options_description desc(_("Debugging options"));
269 desc.add_options()
271 ("verbose,v", accumulator<int>()
272 ->notifier(boost::bind(&LogFile::setVerbosity, &dbglogfile, _1)),
273 _("Produce verbose output"))
275 // NB: if we use a bool_switch(), the default will be false. TODO:
276 // make a sensible process for handling command-line and rcfile options.
277 ("writelog,w", po::value<bool>()
278 ->zero_tokens()
279 ->notifier(boost::bind(&RcInitFile::useWriteLog, &rcfile, _1)),
280 _("Produce the disk based debug log"))
282 #if VERBOSE_ACTION
283 ("verbose-actions,a", po::bool_switch()
284 ->notifier(boost::bind(&LogFile::setActionDump, &dbglogfile, _1)),
285 _("Be (very) verbose about action execution"))
286 #endif
288 #if VERBOSE_PARSE
289 ("verbose-parsing,p", po::bool_switch()
290 ->notifier(boost::bind(&LogFile::setParserDump, &dbglogfile, _1)),
291 _("Be (very) verbose about parsing"))
292 #endif
294 #ifdef GNASH_FPS_DEBUG
295 ("debug-fps,f", po::value<float>()
296 ->notifier(boost::bind(&Player::setFpsPrintTime, &p, _1)),
297 _("Print FPS every num seconds"))
298 #endif
302 return desc;
305 po::options_description
306 getSupportedOptions(gnash::Player& p)
308 using std::string;
309 using gnash::Player;
310 using gnash::LogFile;
311 using gnash::RcInitFile;
313 std::vector<std::string> handlers;
314 gnash::media::MediaFactory::instance().listKeys(back_inserter(handlers));
316 std::vector<std::string> renderers;
317 boost::split(renderers, RENDERER_CONFIG,
318 boost::is_any_of(" "), boost::token_compress_on);
320 po::options_description desc(_("Options"));
322 desc.add_options()
324 ("help,h",
325 _("Print this help and exit"))
327 ("version,V",
328 _("Print version information and exit"))
330 ("scale,s", po::value<float>()
331 ->notifier(boost::bind(&Player::setScale, &p,
332 boost::bind(gnash::clamp<float>, _1, 0.01f, 100.f))),
333 _("Scale the movie by the specified factor"))
335 ("delay,d", po::value<int>()
336 ->notifier(boost::bind(&Player::setDelay, &p, _1)),
337 _("Number of milliseconds to delay in main loop"))
339 ("audio-dump,A", po::value<string>()
340 ->notifier(boost::bind(&Player::setAudioDumpfile, &p, _1)),
341 _("Audio dump file (wave format)"))
343 ("hwaccel", po::value<string>()
344 ->default_value("none")
345 ->notifier(boost::bind(&Player::setHWAccel, &p, _1)),
346 (string(_("Hardware Video Accelerator to use"))
347 + string("\nnone|vaapi")). c_str())
349 ("xid,x", po::value<long>()
350 ->notifier(boost::bind(&Player::setWindowId, &p, _1)),
351 _("X11 Window ID for display"))
353 ("width,j", po::value<int>()
354 ->notifier(boost::bind(&Player::setWidth, &p, _1)),
355 _("Set window width"))
357 ("height,k", po::value<int>()
358 ->notifier(boost::bind(&Player::setHeight, &p, _1)),
359 _("Set window height"))
361 ("x-pos,X", po::value<int>()
362 ->notifier(boost::bind(&Player::setXPosition, &p, _1)),
363 _("Set window x position"))
365 ("y-pos,Y", po::value<int>()
366 ->notifier(boost::bind(&Player::setYPosition, &p, _1)),
367 _("Set window y position"))
369 ("once,1", po::bool_switch()
370 ->notifier(boost::bind(&Player::setDoLoop, &p,
371 boost::bind(std::logical_not<bool>(), _1))),
372 _("Exit when/if movie reaches the last frame"))
374 ("render-mode,r", po::value<int>()
375 ->default_value(3)
376 ->notifier(boost::bind(&setupSoundAndRendering, boost::ref(p), _1)),
377 (string("0 ")
378 + string(_("disable rendering and sound"))
379 + string("\n1 ")
380 + string(_("enable rendering, disable sound"))
381 + string("\n2 ")
382 + string(_("enable sound, disable rendering"))
383 + string("\n3 ")
384 + string(_("enable rendering and sound"))
385 ).c_str())
387 ("media,M", po::value<string>()
388 ->default_value(rcfile.getMediaHandler().empty() ?
389 ( handlers.empty() ? "" : handlers.front() )
390 : rcfile.getMediaHandler() )
391 ->notifier(boost::bind(&Player::setMedia, &p, _1)),
392 (string(_("The media handler to use"))
393 + string("\n") + boost::join(handlers, "|")
394 ).c_str())
396 ("renderer,R", po::value<string>()
397 ->default_value(rcfile.getRenderer().empty() ? renderers.front()
398 : rcfile.getRenderer())
399 ->notifier(boost::bind(&Player::setRenderer, &p, _1)),
400 (string(_("The renderer to use"))
401 + string("\n") + boost::join(renderers, "|")
402 ).c_str())
404 ("timeout,t", po::value<float>()
405 ->notifier(boost::bind(&Player::setExitTimeout, &p, _1)),
406 _("Exit after the specified number of seconds"))
408 ("real-url,u", po::value<string>(&url),
409 _("Set \"real\" URL of the movie"))
411 ("base-url,U", po::value<string>()
412 ->notifier(boost::bind(&Player::setBaseUrl, &p, _1)),
413 _("Set \"base\" URL for resolving relative URLs"))
415 ("param,P", po::value<std::vector<std::string> >()
416 ->composing()
417 ->notifier(boost::bind(&setupFlashVars, boost::ref(p), _1)),
418 _("Set parameter (e.g. \"FlashVars=A=1&b=2\")"))
420 ("fd,F", po::value<string>()
421 ->notifier(boost::bind(&setupFDs, boost::ref(p), _1)),
422 (string(_("Filedescriptor to use for external communications"))
423 + string(" <fd>:<fd>")
424 ).c_str())
426 ("max-advances", po::value<size_t>()
427 ->notifier(boost::bind(&Player::setMaxAdvances, &p, _1)),
428 _("Exit after specified number of frame advances"))
430 ("fullscreen", po::bool_switch()
431 ->notifier(boost::bind(&Player::setStartFullscreen, &p, _1)),
432 _("Start in fullscreen mode"))
434 // TODO: move to GUIs actually implementing this
435 ("hide-menubar", po::bool_switch()
436 ->notifier(boost::bind(&Player::hideMenu, &p, _1)),
437 _("Start without displaying the menu bar"))
439 // TODO: do this in ScreenShotter class.
440 ("screenshot", po::value<string>()
441 ->notifier(boost::bind(&Player::setScreenShots, &p, _1)),
442 _("List of frames to save as screenshots"))
444 ("screenshot-file", po::value<string>()
445 ->notifier(boost::bind(&Player::setScreenShotFile, &p, _1)),
446 _("Filename pattern for screenshot images"))
448 ("screenshot-quality", po::value<size_t>()
449 ->notifier(boost::bind(&Player::setScreenShotQuality, &p, _1)),
450 _("Quality for screenshot output (not all formats)"))
452 ("input-file", po::value<std::vector<std::string> >(&infiles),
453 _("Input files"))
456 desc.add(getDebuggingOptions(p));
459 // Add gui-specific options
460 // TODO make this somehow cleaner, maybe add a signature
461 // for such function in each of the gui's mains
462 // like getGuiOptions()
463 #ifdef GUI_DUMP
464 po::options_description dumpOpts (_("Dump options"));
466 dumpOpts.add_options()
468 (",D", po::value<string>(),
469 _("Video dump file (raw format) and optional video FPS (@<num>)"))
470 (",S", po::value<string>(),
471 _("Number of milliseconds to sleep between advances"))
472 (",T", po::value<string>(),
473 _("Trigger expression to start dumping"))
476 desc.add(dumpOpts);
477 #endif
479 return desc;
482 void
483 usage_gui_keys(std::ostream& os)
485 os << _("Keys:\n")
486 << " CTRL-Q, CTRL-W "
487 << _("Quit\n")
488 << " CTRL-F "
489 << _("Toggle fullscreen\n")
490 << " CTRL-P "
491 << _("Toggle pause\n")
492 << " CTRL-R "
493 << _("Restart the movie\n")
494 << " CTRL-O "
495 << _("Take a screenshot\n")
496 << " CTRL-L "
497 << _("Force immediate redraw\n");
500 void
501 usage(std::ostream& os, const po::options_description& opts)
503 os << _("Usage: gnash [options] movie_file.swf\n")
504 << _("Plays a SWF (Shockwave Flash) movie\n")
505 << opts << "\n";
507 // Add gui keys
508 // TODO: stop printing these in here ?
509 usage_gui_keys(os);
511 os << std::endl;
514 void
515 version_and_copyright(std::ostream& os)
517 os << "Gnash "
518 << VERSION " ("
519 << BRANCH_NICK << "-" << BRANCH_REVNO << "-" << COMMIT_ID
520 << ")" << endl << endl
521 << _("Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011 "
522 "Free Software Foundation, Inc.\n"
523 "Gnash comes with NO WARRANTY, to the extent permitted "
524 "by law.\nYou may redistribute copies of Gnash under the "
525 "terms of the GNU General\nPublic License. For more "
526 "information, see the file named COPYING.\n\n");
529 void
530 build_options(std::ostream& os)
532 os << _("Build options ") << endl
533 << _(" Renderers: ") << RENDERER_CONFIG << endl
534 << _(" Hardware Acceleration: ") << HWACCEL_CONFIG << endl
535 << _(" GUI: ") << GUI_CONFIG << endl
536 << _(" Media handlers: ") << MEDIA_CONFIG << endl
538 << _(" Configured with: ") << CONFIG_CONFIG << endl
539 << _(" CXXFLAGS: ") << CXXFLAGS << endl;
543 } // unnamed namespace