2 // Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010 Free Software
5 // This program is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation; either version 3 of the License, or
8 // (at your option) any later version.
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software
17 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
23 #include "gnashconfig.h"
26 #include <boost/intrusive_ptr.hpp>
27 #include <boost/scoped_ptr.hpp>
28 #include <boost/function.hpp>
33 #include "SWFRect.h" // for composition
34 #include "snappingrange.h" // for InvalidatedRanges
35 #include "ScreenShotter.h"
38 #include "VirtualClock.h"
39 #include "SystemClock.h"
40 #include "GnashEnums.h"
41 #include "movie_root.h"
44 #include "tree.hh" // for tree
47 // Define this to enable fps debugging without touching
49 //#define GNASH_FPS_DEBUG
51 /// Define this to disable region updates debugging altogether. If undefined,
52 /// debugging will be a runtime option. The flag and flag-setting functions
53 /// will not be disabled (too ugly).
55 /// This should go in gnashconfig.h
57 /// This has the side effect that all frames will be re-rendered completely
58 /// but in contrast to FORCE_REDRAW it won't re-render when no motion
59 /// has been detected in the movie (for example when the movie is stopped).
61 //#define DISABLE_REGION_UPDATES_DEBUGGING 1
64 /// Define this to support keyboard-based pointer movements
65 #define ENABLE_KEYBOARD_MOUSE_MOVEMENTS 1
67 // Forward declarations
73 class movie_definition
;
78 /// Enumerates mouse cursor types.
79 enum gnash_cursor_type
{
85 /// Parent class from which all GUI implementations will depend.
93 * Initialise the gui and the associated renderer.
95 * @param argc The commandline argument count.
96 * @param argv The commandline arguments.
97 * @return True on success; false on failure.
99 virtual bool init(int argc
, char **argv
[]) = 0;
101 /// Set main loop delay in milliseconds.
102 virtual void setInterval(unsigned int interval
) {
103 _interval
= interval
;
106 /// Instructs the Gui to monitor a file descriptor.
108 /// @param fd The file descriptor to monitor
109 /// @param callback The callback to fire
110 void setFDCallback(int fd
, boost::function
<void ()> callback
);
112 /// Calls the callback function registered for a file descriptor.
114 /// @param fd The file descriptor for which the registered callback should
116 void callCallback(int fd
);
118 /// Return the clock provided by this Gui.
120 /// The Gui clock will be paused when the gui is put
121 /// in pause mode and resumed when gui playback is resumed.
123 virtual VirtualClock
& getClock() { return _virtualClock
; }
125 /// Set the time in milliseconds after which the programme should exit.
126 virtual void setTimeout(unsigned int timeout
) = 0;
128 void setScreenShotter(std::auto_ptr
<ScreenShotter
> ss
);
131 * Create and display our window.
133 * @param title The window title.
134 * @param width The desired window width in pixels.
135 * @param height The desired window height in pixels.
136 * @param xPosition The desired window X position from the top left corner.
137 * @param yPosition The desired window Y position from the top left corner.
139 virtual bool createWindow(const char* title
, int width
, int height
,
140 int xPosition
= 0, int yPosition
= 0) = 0;
142 virtual void resizeWindow(int width
, int height
);
144 /// Start main rendering loop.
145 virtual bool run() = 0;
147 /// Always called on exit.
149 /// Handles any common functions, then calls virtual quitUI().
152 /// Render the current buffer.
153 /// For OpenGL, this means that the front and back buffers are swapped.
154 virtual void renderBuffer() = 0;
156 /// Gives the GUI a *hint* which region of the stage should be redrawn.
158 /// There is *no* restriction what the GUI might do with these coordinates.
159 /// Normally the GUI forwards the information to the renderer so that
160 /// it avoids rendering regions that did not change anyway. The GUI can
161 /// also alter the bounds before passing them to the renderer and it's
162 /// absolutely legal for the GUI to simply ignore the call.
164 /// Coordinates are in TWIPS!
166 /// Note this information is given to the GUI and not directly to the
167 /// renderer because both of them need to support this feature for
168 /// correct results. It is up to the GUI to forward this information to
171 // does not need to be implemented (optional feature),
172 // but still needs to be available.
174 virtual void setInvalidatedRegion(const SWFRect
& bounds
);
175 virtual void setInvalidatedRegions(const InvalidatedRanges
& ranges
);
177 // Called right before rendering anything (after setInvalidatedRegion).
179 virtual void beforeRendering() { /* nop */ };
181 // Should return TRUE when the GUI/Renderer combination supports multiple
182 // invalidated bounds regions.
183 virtual bool want_multiple_regions() { return false; }
185 /// Asks the GUI handler if the next frame should be redrawn completely.
187 /// For example, when the contents of the player window have been destroyed,
188 /// then want_redraw() should return true so that setInvalidatedRegion() is
189 /// called with the coordinates of the complete screen.
190 virtual bool want_redraw();
192 /// Sets the current mouse cursor for the Gui window.
193 virtual void setCursor(gnash_cursor_type newcursor
);
195 virtual void setClipboard(const std::string
& copy
);
197 // Information for System.capabilities to be reimplemented in
199 virtual double getPixelAspectRatio() const { return 0; }
201 virtual std::pair
<int, int> screenResolution() const {
202 return std::make_pair(0, 0);
205 virtual double getScreenDPI() const { return 0; }
207 /// Get the screen color type.
209 /// The choice is between "color" and something designating
210 /// monochrome (not sure what). If this isn't implemented in the
211 /// gui we return "color".
212 virtual std::string
getScreenColor() const {
216 /// @return Whether or not the movie should be looped indefinitely.
217 bool loops() const { return _loop
; }
219 /// @return Whether the movie is running fullscreen or not.
220 bool isFullscreen() const { return _fullscreen
; }
222 /// Mouse notification callback to be called when the mouse is moved.
224 /// @param x The mouse coordinate X component in user/window
225 /// coordinate space (pixels).
226 /// @param y The mouse coordinate Y component in user/window
227 /// coordinate space (pixels).
228 void notifyMouseMove(int x
, int y
);
230 /// Mouse notification callback to be called when the mouse is clicked.
232 /// @param mouse_pressed Determines whether the mouse button is being
233 /// pressed (true) or being released (false)
234 void notifyMouseClick(bool mouse_pressed
);
236 /// Send a mouse wheel event to the stage.
238 /// @param delta A number expressing the extent of the wheel scroll.
239 void notifyMouseWheel(int delta
);
241 /// Key event notification to be called when a key is pressed or depressed
243 /// @param k The key code.
245 /// Modifier key identifiers from gnash::key::modifier ORed together
247 /// Determines whether the key is being pressed (true)
248 /// or being released (false)
250 void notify_key_event(gnash::key::code k
, int modifier
, bool pressed
);
252 /// Resize the client area view and the window accordingly.
254 /// @param width The desired width in pixels.
255 /// @param height The desired height in pixels.
256 void resize_view(int width
, int height
);
258 /// Update stage SWFMatrix accordingly to window size and flash Stage
259 /// configuration (scaleMode, alignment)
261 /// This method should be called from the core lib when Stage configuration
262 /// change or is called by resize_view.
264 void updateStageMatrix();
267 /// Give movie an heart-beat.
269 /// This is to take place after the
270 /// interval specified in the call to setInterval().
272 /// Wheter or not this beat advanced the movie to the next frame
273 /// depends on elapsed time since last advancement.
275 /// @return true if this beat resulted in actual frame advancement.
279 /// Convenience static wrapper around advanceMovie for callbacks happiness.
281 /// NOTE: this function always return TRUE, for historical reasons.
282 /// TODO: bring code up-to-date to drop this legacy return code..
284 static bool advance_movie(Gui
* gui
) {
289 /// Force immediate redraw
293 /// Attempt to run in a fullscreen window both for plugin and
294 /// standalone player.
296 /// Use isFullscreen() to see if gnash thinks
297 /// it's running in fullscreen or not. The switch to fullscreen may
298 /// fail if, for instance, the window manager refuses to allow it, but
299 /// the flag will be set anyway.
300 virtual void setFullscreen();
302 /// Return from fullscreen to normal mode.
304 virtual void unsetFullscreen();
306 /// Hide the menu bar when using standalone player
308 virtual void hideMenu();
310 /// Sets whether the gui should show the system mouse pointer
312 /// @param show true if the mouse should be shown.
313 /// @return true if the state changed.
314 virtual bool showMouse(bool show
);
316 /// Sets whether the menus should be shown (for fscommand)
318 /// @param show true if the menu bar should be shown.
319 virtual void showMenu(bool show
);
321 /// Sets whether scaling should be allowed (for fscommand)
323 /// @param allow true if stage scaling should be allowed
324 virtual void allowScale(bool allow
);
326 // Toggle between fullscreen and normal mode
327 void toggleFullscreen();
329 /// Put the application in "stop" mode
331 /// When in stop mode the application won't be advanced.
335 /// Put the application in "play" mode
337 /// When in play mode the application will be advanced as usual.
341 /// Toggle between "stop" and "play" mode
343 /// See stop() and play()
349 /// This function will create an instance of the registered top-level
350 /// movie definition, set variables into it and place it to the stage.
354 /// See stop(), play() and pause()
355 bool isStopped() const { return _stopped
; }
357 /// Whether gnash is is running as a plugin
358 bool isPlugin() const { return ((_xid
)); }
360 /// Take a screenshot now!
361 void takeScreenShot();
363 /// Set the maximum number of frame advances before Gnash exits.
364 void setMaxAdvances(unsigned long ul
) { if (ul
) _maxAdvances
= ul
; }
366 void showUpdatedRegions(bool x
) { _showUpdatedRegions
= x
; }
367 bool showUpdatedRegions() const { return _showUpdatedRegions
; }
369 /// Instruct the core to restart the movie and
370 /// set state to play(). This does not change pause
374 /// Set rendering quality, if not locked by RC file..
375 void setQuality(Quality q
);
377 /// Get current rendering quality
378 Quality
getQuality() const;
380 /// Toggle sound state between muted and unmuted. If
381 /// there is no active sound handler this does nothing.
384 #ifdef GNASH_FPS_DEBUG
385 /// Set the interval between FPS debugging prints
387 /// See fpsCounterTick()
389 void setFpsTimerInterval(float interval
)
391 assert(interval
>= 0.0);
392 fps_timer_interval
= interval
;
394 #endif // def GNASH_FPS_DEBUG
398 /// Return a tree containing information about the movie playing.
399 std::auto_ptr
<movie_root::InfoTree
> getMovieInfo() const;
402 typedef std::map
<std::string
, std::string
> VariableMap
;
404 /// Add variables to set into instances of the top-level movie definition
405 void addFlashVars(VariableMap
& vars
);
407 /// Set the definition of top-level movie
408 void setMovieDefinition(movie_definition
* md
);
410 /// Set the stage to advance/display
411 void setStage(movie_root
* stage
);
413 /// Set the name of a file to dump audio to
414 void setAudioDump(const std::string
& fname
) {
418 /// The root movie, or "Stage"
419 movie_root
* getStage() { return _stage
; };
421 /// Handle error message from the core
423 /// @param msg The error message recieved
425 virtual void error(const std::string
& /*msg*/) {}
427 /// Prompt user with a question she can answer with yes/no
430 /// The question to ask user
433 /// true for YES, false for NO
435 /// The default implementation always returns true.
437 virtual bool yesno(const std::string
& question
);
439 /// Width of a window pixel, in stage pseudopixel units.
440 float getXScale() const { return _xscale
; };
442 /// Height of a window pixel, in stage pseudopixel units.
443 float getYScale() const { return _yscale
; };
447 /// Default constructor. Initialises members to safe defaults.
448 Gui(RunResources
& r
);
451 * Expanded constructor for more control over member values.
453 * @param xid The X11 Window ID to attach to. If this is argument is zero,
454 * a new window is created.
456 * @param scale The scale used to resize the window size, which has been
457 * established by extracting information from the SWF file.
459 * @param loop Defines whether or not the movie should be played once or
460 * looped indefinitely.
462 * @param depth Colour depth to be used in the client area of our window.
464 Gui(unsigned long xid
, float scale
, bool loop
, RunResources
& r
);
466 /// End main rendering loop calling GUI-specific exit functions.
468 /// Do not call this directly. Call quit() instead.
470 /// The default implementation calls exit(EXIT_SUCCESS), which isn't nice.
471 /// Please implement the proper main loop quitter in the subclasses.
472 virtual void quitUI() {
473 std::exit(EXIT_SUCCESS
);
476 /// Watch a file descriptor.
478 /// An implementing Gui should monitor the file descriptor in its main
479 /// loop. When the file descriptor is triggered, the implementation should
480 /// call callCallback().
482 /// @param fd The file descriptor to be watched
483 virtual bool watchFD(int /* fd */)
485 log_unimpl("This GUI does not implement FD watching.");
490 /// Determines if playback should restart after the movie ends.
493 /// The X Window ID to attach to. If zero, we create a new window.
496 // This would be 0,0,_width,_height, so maybe
497 // we should not duplicate the info with those
498 // explicit values too..
499 geometry::Range2d
<int> _validbounds
;
501 /// Desired window width.
504 /// Desired window height.
507 /// Per-run resources
508 RunResources
& _runResources
;
510 /// Main loop interval: the time between successive advance_movie calls.
511 unsigned int _interval
;
513 /// The handler which is called to update the client area of our window.
514 boost::shared_ptr
<Renderer
> _renderer
;
516 /// Signals that the next frame must be re-rendered completely because the
517 /// window size did change.
520 // True if Gnash is running in fullscreen
523 // True if mouse pointer is showing
526 // Maximum number of advances before exit; 0 for no limit.
527 unsigned long _maxAdvances
;
529 /// Counter to keep track of frame advances
530 unsigned long _advances
;
532 /// Name of a file to dump audio to
533 std::string _audioDump
;
535 /// Called by Gui::stop(). This can be used by GUIs to implement pause
536 /// widgets (so that resuming a stopped animation is more user-friendly)
537 virtual void stopHook() {}
539 /// Called by Gui::play().
540 virtual void playHook() {}
543 std::map
<int /* fd */, boost::function
<void ()> > _fd_callbacks
;
545 /// Width of a window pixel, in stage pseudopixel units.
548 /// Height of a window pixel, in stage pseudopixel units.
551 /// Window pixel X offset of stage origin
552 boost::int32_t _xoffset
;
554 /// Window pixel Y offset of stage origin
555 boost::int32_t _yoffset
;
557 bool display(movie_root
* m
);
559 #ifdef GNASH_FPS_DEBUG
560 unsigned int fps_counter
;
562 float fps_rate_min
, fps_rate_max
;
564 // Number of calls to fpsCounterTick, which is also
565 // the number of calls to movie_advance()
566 unsigned int fps_counter_total
;
568 boost::uint64_t fps_timer
, fps_start_timer
;
570 /// The time, in seconds, between prints (which also resets the fps counter).
572 /// interval must be >= 0
574 float fps_timer_interval
;
576 /// Number of frames rendering of which was dropped
577 unsigned int frames_dropped
;
580 /// Should be called on every frame advance (including inter-frames caused
581 /// by mouse events).
583 /// Based on fps-timer_interval. See setFpsTimerInterval.
585 void fpsCounterTick();
587 #endif // def GNASH_FPS_DEBUG
589 VariableMap _flashVars
;
591 boost::intrusive_ptr
<movie_definition
> _movieDef
;
593 /// The root movie, or "Stage"
596 /// True if the application has been put into "stop" mode
599 /// True if the application didn't start yet
602 /// If true, updated regions (invalidated ranges) are visibly outlined.
603 bool _showUpdatedRegions
;
605 SystemClock _systemClock
;
606 InterruptableVirtualClock _virtualClock
;
608 /// Checked on each advance for screenshot activity if it exists.
609 boost::scoped_ptr
<ScreenShotter
> _screenShotter
;
611 #ifdef ENABLE_KEYBOARD_MOUSE_MOVEMENTS
614 bool _keyboardMouseMovements
;
615 int _keyboardMouseMovementsStep
;
616 #endif // ENABLE_KEYBOARD_MOUSE_MOVEMENTS
619 /// Named constructors
620 std::auto_ptr
<Gui
> createGTKGui(unsigned long xid
, float scale
, bool loop
, RunResources
& r
);
621 std::auto_ptr
<Gui
> createKDEGui(unsigned long xid
, float scale
, bool loop
, RunResources
& r
);
622 std::auto_ptr
<Gui
> createKDE4Gui(unsigned long xid
, float scale
, bool loop
, RunResources
& r
);
623 std::auto_ptr
<Gui
> createSDLGui(unsigned long xid
, float scale
, bool loop
, RunResources
& r
);
624 std::auto_ptr
<Gui
> createFLTKGui(unsigned long xid
, float scale
, bool loop
, RunResources
& r
);
625 std::auto_ptr
<Gui
> createFBGui(unsigned long xid
, float scale
, bool loop
, RunResources
& r
);
626 std::auto_ptr
<Gui
> createAQUAGui(unsigned long xid
, float scale
, bool loop
, RunResources
& r
);
627 std::auto_ptr
<Gui
> createRISCOSGui(unsigned long xid
, float scale
, bool loop
, RunResources
& r
);
628 std::auto_ptr
<Gui
> createAOS4Gui(unsigned long xid
, float scale
, bool loop
, RunResources
& r
);
629 std::auto_ptr
<Gui
> createHaikuGui(unsigned long xid
, float scale
, bool loop
, RunResources
& r
);
630 std::auto_ptr
<Gui
> createDumpGui(unsigned long xid
, float scale
, bool loop
, RunResources
& r
);
633 } // end of gnash namespace
640 // indent-tabs-mode: nil