1 /*
2  * This file is part of bino, a 3D video player.
3  *
4  * Copyright (C) 2010, 2011, 2012, 2013, 2015
5  * Martin Lambers <marlam@marlam.de>
6  * Joe <cuchac@email.cz>
7  * Binocle <http://binocle.com> (author: Olivier Letz <oletz@binocle.com>)
8  * Frédéric Bour <frederic.bour@lakaban.net>
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 3 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
22  */
23 
24 #ifndef DISPATCH_H
25 #define DISPATCH_H
26 
27 #include <string>
28 #include <sstream>
29 #include <stdint.h>
30 
31 #include "base/ser.h"
32 #include "base/pth.h"
33 
34 #include "media_data.h"
35 
36 class gui;
37 class audio_output;
38 class video_output;
39 class media_input;
40 class player;
41 
42 
43 /* The open_init_data class contains everything that is needed to open
44  * a media input. */
45 
46 class open_input_data : public serializable
47 {
48 public:
49     device_request dev_request;    // Request for input device settings
50     std::vector<std::string> urls; // Input media objects
51     parameters params;             // Initial per-video output parameters
52                                    // (other parameter fields are ignored)
53 public:
54     open_input_data();
55 
56     // Serialization
57     void save(std::ostream &os) const;
58     void load(std::istream &is);
59 };
60 
61 
62 /* A controller can send commands to the dispatch (e.g. "pause", "seek",
63  * "adjust colors", ...). The dispatch then reacts on this command, and sends
64  * a notification to all controllers afterwards. The controllers may react
65  * on the notification or ignore it.
66  *
67  * For example, the video output controller may notice that the user pressed the
68  * 'p' key to pause the video. So it sends the "pause" command to the dispatch.
69  * The dipatch updates its state accordingly, and notifies all controllers that
70  * the video is now paused. The video output could use this notification to display
71  * a pause symbol on screen, and the audio output controller may play a pause jingle
72  * (however, in the case of pause, both currently simply ignore the notification).
73  */
74 
75 // A command that can be sent to the dispatch by a controller.
76 
77 class command
78 {
79 public:
80     enum type
81     {
82         noop,                           // no parameters
83         quit,                           // no parameters
84         // Play state
85         open,                           // open_input_data
86         close,                          // no parameters
87         toggle_play,                    // no parameters
88         toggle_pause,                   // no parameters
89         step,                           // no parameters
90         seek,                           // float (relative adjustment)
91         set_pos,                        // float (absolute position)
92         // Per-Session parameters
93         set_audio_device,               // int
94         set_quality,                    // int
95         set_stereo_mode,                // parameters::stereo_mode
96         set_stereo_mode_swap,           // bool
97         toggle_stereo_mode_swap,        // no parameters
98         set_crosstalk,                  // 3 floats (absolute values)
99         set_fullscreen_screens,         // int
100         set_fullscreen_flip_left,       // bool
101         set_fullscreen_flop_left,       // bool
102         set_fullscreen_flip_right,      // bool
103         set_fullscreen_flop_right,      // bool
104         set_fullscreen_inhibit_screensaver,     // bool
105         set_fullscreen_3d_ready_sync,   // bool
106         set_contrast,                   // float (absolute value)
107         adjust_contrast,                // float (relative adjustment)
108         set_brightness,                 // float (absolute value)
109         adjust_brightness,              // float (relative adjustment)
110         set_hue,                        // float (absolute value)
111         adjust_hue,                     // float (relative adjustment)
112         set_saturation,                 // float (absolute value)
113         adjust_saturation,              // float (relative adjustment)
114         set_zoom,                       // float (absolute value)
115         adjust_zoom,                    // float (relative adjustment)
116         set_loop_mode,                  // parameters::loop_mode_t
117         set_audio_delay,                // int64_t (absolute value, in microseconds)
118         set_subtitle_encoding,          // string (encoding name)
119         set_subtitle_font,              // string (font name)
120         set_subtitle_size,              // int
121         set_subtitle_scale,             // float
122         set_subtitle_color,             // uint64_t
123         set_subtitle_shadow,            // int
124 #if HAVE_LIBXNVCTRL
125         set_sdi_output_format,          // int
126         set_sdi_output_left_stereo_mode,  // parameters::stereo_mode_t
127         set_sdi_output_right_stereo_mode, // parameters::stereo_mode_t
128 #endif // HAVE_LIBXNVCTRL
129         // Per-Video parameters
130         set_video_stream,               // int
131         cycle_video_stream,             // no parameters
132         set_audio_stream,               // int
133         cycle_audio_stream,             // no parameters
134         set_subtitle_stream,            // int
135         cycle_subtitle_stream,          // no parameters
136         set_stereo_layout,              // video_frame::stereo_layout
137         set_stereo_layout_swap,         // bool
138         set_crop_aspect_ratio,          // float
139         set_source_aspect_ratio,        // float
140         set_parallax,                   // float (absolute value)
141         adjust_parallax,                // float (relative adjustment)
142         set_ghostbust,                  // float (absolute value)
143         adjust_ghostbust,               // float (relative adjustment)
144         set_subtitle_parallax,          // float (absolute value)
145         adjust_subtitle_parallax,       // float (relative adjustment)
146         // Volatile parameters
147         toggle_fullscreen,              // no parameters
148         center,                         // no parameters
149         set_audio_volume,               // float (absolute value)
150         adjust_audio_volume,            // float (relative adjustment)
151         toggle_audio_mute,              // no parameters
152         update_display_pos,             // no parameters
153     };
154 
155     type type;
156     std::string param;
157 
command()158     command() :
159         type(noop)
160     {
161     }
162 
command(enum type t)163     command(enum type t) :
164         type(t)
165     {
166     }
167 
command(enum type t,int p)168     command(enum type t, int p) :
169         type(t)
170     {
171         std::ostringstream oss;
172         s11n::save(oss, p);
173         param = oss.str();
174     }
175 
command(enum type t,float p)176     command(enum type t, float p) :
177         type(t)
178     {
179         std::ostringstream oss;
180         s11n::save(oss, p);
181         param = oss.str();
182     }
183 
command(enum type t,int64_t p)184     command(enum type t, int64_t p) :
185         type(t)
186     {
187         std::ostringstream oss;
188         s11n::save(oss, p);
189         param = oss.str();
190     }
191 
command(enum type t,uint64_t p)192     command(enum type t, uint64_t p) :
193         type(t)
194     {
195         std::ostringstream oss;
196         s11n::save(oss, p);
197         param = oss.str();
198     }
199 
command(enum type t,const std::string & p)200     command(enum type t, const std::string &p) :
201         type(t), param(p)
202     {
203     }
204 };
205 
206 // A notification that can be sent to controllers by the dispatch.
207 // It signals that the corresponding value has changed.
208 
209 class notification
210 {
211 public:
212     enum type
213     {
214         noop,
215         quit,
216         // Play state
217         open,
218         play,
219         pause,
220         pos,
221         // Per-Session parameters
222         audio_device,
223         quality,
224         stereo_mode,
225         stereo_mode_swap,
226         crosstalk,
227         fullscreen_screens,
228         fullscreen_flip_left,
229         fullscreen_flop_left,
230         fullscreen_flip_right,
231         fullscreen_flop_right,
232         fullscreen_inhibit_screensaver,
233         fullscreen_3d_ready_sync,
234         contrast,
235         brightness,
236         hue,
237         saturation,
238         zoom,
239         loop_mode,
240         audio_delay,
241         subtitle_encoding,
242         subtitle_font,
243         subtitle_size,
244         subtitle_scale,
245         subtitle_color,
246         subtitle_shadow,
247 #if HAVE_LIBXNVCTRL
248         sdi_output_format,
249         sdi_output_left_stereo_mode,
250         sdi_output_right_stereo_mode,
251 #endif // HAVE_LIBXNVCTRL
252         // Per-Video parameters
253         video_stream,
254         audio_stream,
255         subtitle_stream,
256         stereo_layout,
257         stereo_layout_swap,
258         crop_aspect_ratio,
259         source_aspect_ratio,
260         parallax,
261         ghostbust,
262         subtitle_parallax,
263         // Volatile parameters
264         fullscreen,
265         center,
266         audio_volume,
267         audio_mute,
268         display_pos,
269     };
270 
271     const enum type type;
272 
273 public:
notification(enum type t)274     notification(enum type t) : type(t)
275     {
276     }
277 };
278 
279 // The controller interface.
280 
281 class controller
282 {
283 public:
284     controller() throw ();
285     virtual ~controller();
286 
287     /* The controller uses this function to send a command to the player. */
288     static void send_cmd(const command& cmd);
289     // Convenience wrappers:
send_cmd(enum command::type t)290     static void send_cmd(enum command::type t) { send_cmd(command(t)); }
send_cmd(enum command::type t,int p)291     static void send_cmd(enum command::type t, int p) { send_cmd(command(t, p)); }
send_cmd(enum command::type t,float p)292     static void send_cmd(enum command::type t, float p) { send_cmd(command(t, p)); }
send_cmd(enum command::type t,int64_t p)293     static void send_cmd(enum command::type t, int64_t p) { send_cmd(command(t, p)); }
send_cmd(enum command::type t,uint64_t p)294     static void send_cmd(enum command::type t, uint64_t p) { send_cmd(command(t, p)); }
send_cmd(enum command::type t,const std::string & p)295     static void send_cmd(enum command::type t, const std::string& p) { send_cmd(command(t, p)); }
296 
297     /* The controller receives notifications via this function. The default
298      * implementation simply ignores the notification. */
299     virtual void receive_notification(const notification& note);
300 
301     /* The controller is asked to process events via this function. The default
302      * implementation simply does nothing. */
303     virtual void process_events();
304 
305     /* The controller can prevent Bino from exiting when there is no video
306      * to play. In this case, the following function should return 'false'.
307      * This is intended to be used for controllers that might send another
308      * 'open' command in the future. */
309     virtual bool allow_early_quit();
310 };
311 
312 // The dispatch (singleton).
313 
314 class dispatch
315 {
316 private:
317     int* _argc;
318     char** _argv;
319     const bool _eq;
320     const bool _eq_3d;
321     const bool _eq_slave_node;
322     const bool _gui_mode;
323     const bool _have_display;
324     // Objects
325     class gui* _gui;
326     class audio_output* _audio_output;
327     class video_output* _video_output;
328     class media_input* _media_input;
329     class player* _player;
330     std::vector<controller*> _controllers;
331     unsigned int _controllers_version;
332     mutex _controllers_mutex;
333     // Parameters
334     open_input_data _input_data;
335     class parameters _parameters;
336     // State
337     bool _playing;
338     bool _pausing;
339     float _position;
340 
341     void stop_player();
342     void force_stop(bool reopen_media_input = true);
343 
344     bool early_quit_is_allowed() const;
345     void visit_all_controllers(int action, const notification& note) const;
346     void notify_all(const notification& note);
347 
348 public:
349     dispatch(int* argc, char** argv,
350             bool equalizer, bool equalizer_3d, bool equalizer_slave_node,
351             bool gui, bool have_display, msg::level_t log_level,
352             bool benchmark, int swap_interval) throw ();
353     virtual ~dispatch();
354 
355     void register_controller(controller* c);
356     void deregister_controller(controller* c);
357 
358     void init(const open_input_data& input_data);
359     void deinit();
360 
361     static void step();
362 
363     /* Process events for all controllers */
364     static void process_all_events();
365 
366     /* Access parameters and state (read-only) */
367     static const class parameters& parameters();
368     static const class audio_output* audio_output();    // NULL if not available
369     static const class video_output* video_output();    // NULL if not available
370     static const class media_input* media_input();      // NULL if no input is opened
371     static bool playing();
372     static bool pausing();
373     static float position();
374 
375     /* Receive a command from a controller. */
376     void receive_cmd(const command& cmd);
377 
378     /* Interface for the player. TODO: remove this! */
379     class audio_output* get_audio_output(); // NULL if not available
380     class video_output* get_video_output(); // NULL if not available
381     class media_input* get_media_input();   // NULL if not available
382     void set_playing(bool p);
383     void set_pausing(bool p);
384     void set_position(float pos);
385 
386     /* Interface for Equalizer. */
387     class open_input_data* get_input_data();
388     std::string save_state() const;
389     void load_state(const std::string& s);
stop_eq_player()390     void stop_eq_player() { stop_player(); }
391 
392     /* Helper function for text-based controllers: parse a command from a string.
393      * Return false if this fails, otherwise store the command in c. */
394     static bool parse_command(const std::string& s, command* c);
395 };
396 
397 #endif
398