1 /*
2  * Copyright (C) 2000-2019 the xine project
3  *
4  * This file is part of xine, a unix video player.
5  *
6  * xine 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 2 of the License, or
9  * (at your option) any later version.
10  *
11  * xine 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.
15  *
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 Street, Fifth Floor, Boston, MA 02110, USA
19  *
20  */
21 
22 #ifndef __COMMON_H__
23 #define __COMMON_H__
24 
25 #ifdef HAVE_CONFIG_H
26 #include "config.h"
27 #endif
28 
29 #include <stdio.h>
30 
31 #include <xine.h>
32 #include <xine/xineutils.h>
33 
34 #include "Imlib-light/Imlib.h"
35 
36 typedef struct gGui_st gGui_t;
37 
38 #include "xitk.h"
39 
40 #include "kbindings.h"
41 #include "videowin.h"
42 #include "mediamark.h"
43 #include "actions.h"
44 #include "config_wrapper.h"
45 #include "control.h"
46 #include "errors.h"
47 #include "event.h"
48 #include "event_sender.h"
49 #include "help.h"
50 #include "i18n.h"
51 #include "lang.h"
52 #ifdef HAVE_LIRC
53 #include "lirc.h"
54 #endif
55 #include "stdctl.h"
56 #include "menus.h"
57 #include "mrl_browser.h"
58 #include "network.h"
59 #include "panel.h"
60 #include "playlist.h"
61 #include "session.h"
62 #include "setup.h"
63 #include "skins.h"
64 #include "snapshot.h"
65 #include "splash.h"
66 #include "stream_infos.h"
67 #include "tvset.h"
68 #include "viewlog.h"
69 #include "download.h"
70 #include "osd.h"
71 #include "file_browser.h"
72 #include "post.h"
73 #include "tvout.h"
74 
75 #include "libcommon.h"
76 #include "globals.h"
77 #include "dump.h"
78 
79 #ifdef HAVE_ORBIT
80 #include "../corba/xine-server.h"
81 #endif
82 
83 #ifdef HAVE_LIRC
84 #include <lirc/lirc_client.h>
85 #endif
86 
87 /*
88  * config related constants
89  */
90 #define CONFIG_LEVEL_BEG         0 /* => beginner */
91 #define CONFIG_LEVEL_ADV        10 /* advanced user */
92 #define CONFIG_LEVEL_EXP        20 /* expert */
93 #define CONFIG_LEVEL_MAS        30 /* motku */
94 #define CONFIG_LEVEL_DEB        40 /* debugger (only available in debug mode) */
95 
96 #define CONFIG_NO_DESC          NULL
97 #define CONFIG_NO_HELP          NULL
98 #define CONFIG_NO_CB            NULL
99 #define CONFIG_NO_DATA          NULL
100 
101 /* Sound mixer capabilities */
102 #define MIXER_CAP_NOTHING       0x00000000
103 #define MIXER_CAP_VOL           0x00000001
104 #define MIXER_CAP_MUTE          0x00000002
105 
106 /* mixer control method */
107 #define SOUND_CARD_MIXER        0
108 #define SOFTWARE_MIXER          1
109 
110 /* Playlist loop modes */
111 #define PLAYLIST_LOOP_NO_LOOP   0 /* no loop (default) */
112 #define PLAYLIST_LOOP_LOOP      1 /* loop the whole playlist */
113 #define PLAYLIST_LOOP_REPEAT    2 /* loop the current mrl */
114 #define PLAYLIST_LOOP_SHUFFLE   3 /* random selection in playlist */
115 #define PLAYLIST_LOOP_SHUF_PLUS 4 /* random selection in playlist, never ending */
116 #define PLAYLIST_LOOP_MODES_NUM 5
117 
118 #define PLAYLIST_CONTROL_STOP         0x00000001 /* Don't start next entry in playlist */
119 #define PLAYLIST_CONTROL_STOP_PERSIST 0x00000002 /* Don't automatically reset PLAYLIST_CONTROL_STOP */
120 #define PLAYLIST_CONTROL_IGNORE       0x00000004 /* Ignore some playlist adding action */
121 
122 #define SAFE_FREE(x)            do {           \
123                                     free((x)); \
124                                     x = NULL;  \
125                                 } while(0)
126 
127 #define ABORT_IF_NULL(p)                                                                      \
128   do {                                                                                        \
129     if((p) == NULL) {                                                                         \
130       fprintf(stderr, "%s(%d): '%s' is NULL. Aborting.\n",  __XINE_FUNCTION__, __LINE__, #p); \
131       abort();                                                                                \
132     }                                                                                         \
133   } while(0)
134 
135 /* Duplicate s to d timeval values */
136 #define timercpy(s, d) do {                                                   \
137       (d)->tv_sec = (s)->tv_sec;                                              \
138       (d)->tv_usec = (s)->tv_usec;                                            \
139 } while(0)
140 
141 #ifndef timersub
142 #define timersub(a, b, result)                                                \
143   do {                                                                        \
144     (result)->tv_sec = (a)->tv_sec - (b)->tv_sec;                             \
145     (result)->tv_usec = (a)->tv_usec - (b)->tv_usec;                          \
146     if ((result)->tv_usec < 0) {                                              \
147       --(result)->tv_sec;                                                     \
148       (result)->tv_usec += 1000000;                                           \
149     }                                                                         \
150   } while (0)
151 #endif
152 
153 
154 /* Our default location for skin downloads */
155 #define SKIN_SERVER_URL         "http://xine.sourceforge.net/skins/skins.slx"
156 
157 #define fontname       "-*-helvetica-medium-r-*-*-11-*-*-*-*-*-*-*"
158 #define boldfontname   "-*-helvetica-bold-r-*-*-11-*-*-*-*-*-*-*"
159 #define hboldfontname  "-*-helvetica-bold-r-*-*-12-*-*-*-*-*-*-*"
160 #define lfontname      "-*-helvetica-bold-r-*-*-11-*-*-*-*-*-*-*"
161 #define tabsfontname   "-*-helvetica-bold-r-*-*-12-*-*-*-*-*-*-*"
162 #define br_fontname    "-misc-fixed-medium-r-normal-*-11-*-*-*-*-*-*-*"
163 #define btnfontname    "-*-helvetica-bold-r-*-*-12-*-*-*-*-*-*-*"
164 
165 /* easy pseudo widgets for *_toggle_* calls. not all windows support them yet. */
166 #define XUI_W_TOGGLE NULL
167 #define XUI_W_ON ((xitk_widget_t *)1)
168 #define XUI_W_OFF ((xitk_widget_t *)2)
169 
170 struct gGui_st {
171   xine_t                   *xine;
172   xine_video_port_t        *vo_port;
173   xine_video_port_t        *vo_none;
174   xine_audio_port_t        *ao_none;
175 
176   tvout_t                  *tvout;
177 
178   post_element_t          **post_video_elements;
179   int                       post_video_elements_num;
180   int                       post_video_enable;
181   post_element_t          **post_audio_elements;
182   int                       post_audio_elements_num;
183   int                       post_audio_enable;
184 
185   char                     *deinterlace_plugin;
186   post_element_t          **deinterlace_elements;
187   int                       deinterlace_elements_num;
188   int                       deinterlace_enable;
189 
190   xine_audio_port_t        *ao_port;
191 
192   xine_stream_t            *stream;
193 
194   struct {
195     int                     pos;
196     int                     time;
197     int                     length;
198   } stream_length;
199 
200   int                       subtitle_autoload;
201   xine_stream_t            *spu_stream;
202 
203   int                       broadcast_port;
204 
205   /* Seek through xine_play () may be slow. We defer it to a separate thread. */
206   pthread_mutex_t           seek_mutex;
207   /* 0 = no, 1 = yes, 2 = shutdown */
208   int                       seek_running;
209   int                       seek_pos;
210   int                       seek_timestep;
211 
212   xine_event_queue_t       *event_queue;
213 
214   int                       smart_mode;
215 
216   /* Visual stuff (like animation in video window while audio only playback) */
217   struct {
218     xine_stream_t          *stream;
219     xine_event_queue_t     *event_queue;
220     int                     running;
221     int                     current;
222     int                     enabled; /* 0, 1:vpost, 2:vanim */
223 
224     int                     num_mrls;
225     char                  **mrls;
226 
227     int                     post_plugin_num;
228     int                     post_changed;
229     post_element_t          post_output_element;
230   } visual_anim;
231 
232   struct {
233     int                     enabled;
234     int                     use_unscaled;
235     int                     unscaled_available;
236     int                     timeout;
237 
238     osd_object_t            sinfo;
239     osd_object_t            bar;
240     osd_object_t            status;
241     osd_object_t            info;
242 
243   } osd;
244 
245   int                       experience_level;
246 
247   int                       logo_mode;
248   const char               *logo_mrl;
249   pthread_mutex_t           logo_mutex;
250   int                       logo_has_changed;
251   int                       display_logo;
252 
253   /* stuff like ACTID_x */
254 #define MAX_ACTIONS_ON_START 32
255   action_id_t               actions_on_start[MAX_ACTIONS_ON_START+1];
256   char                     *autoscan_plugin;
257 
258   /* basic X11 stuff */
259   void                    (*x_lock_display) (Display *display);
260   void                    (*x_unlock_display) (Display *display);
261   Display                  *display;
262   int                       screen;
263   int		            depth;
264   Visual	           *visual;
265   XColor                    black;
266   Pixmap                    icon;
267   Colormap                  colormap;
268   double                    pixel_aspect;
269 
270   VisualID	            prefered_visual_id;
271   int		            prefered_visual_class;
272   int		            install_colormap;
273 
274   xitk_skin_config_t       *skin_config;
275   char                     *skin_server_url;
276 
277   ImlibData                *imlib_data;
278 
279   Display                  *video_display;
280   int                       video_screen;
281   Window                    video_window;
282   int                       cursor_visible;
283   int                       cursor_grabbed;
284 
285   Window                    panel_window;
286 
287   uint32_t                  debug_level;
288 
289   int                       is_display_mrl;
290 
291   int                       mrl_overrided;
292 
293   /* Current mediamark */
294   mediamark_t               mmk;
295   /* Recursive mutex, protecting .mmk and .playlist. */
296   pthread_mutex_t           mmk_mutex;
297 
298   /* playlist */
299   struct {
300     mediamark_t           **mmk;
301 
302     int                     num;                   /* number of entries in playlist */
303     int                     cur;                   /* current entry in playlist */
304     int                     ref_append;            /* append mrl reference entry to this position */
305     int                     loop;                  /* current loop mode (see PLAYLIST_LOOP_* */
306     int                     control;               /* see PLAYLIST_CONTROL_* */
307   } playlist;
308 
309 
310   int                       on_quit;
311   int                       running;
312   int                       ignore_next;
313 
314   int                       stdctl_enable;
315 
316 #ifdef HAVE_XF86VIDMODE
317   int                       XF86VidMode_fullscreen;
318 #endif
319 
320   struct {
321     int                     caps; /* MIXER_CAP_x */
322     int                     volume_level;
323     int                     mute;
324     int                     amp_level;
325     int                     method;
326   } mixer;
327 
328   xitk_register_key_t       widget_key;
329 
330   int                       layer_above;
331   int                       always_layer_above;
332 
333   int                       network;
334   int                       network_port;
335 
336   int                       use_root_window;
337 
338   int                       ssaver_enabled;
339   int                       ssaver_timeout;
340 
341   int                       skip_by_chapter;
342 
343   int                       auto_vo_visibility;
344   int                       auto_panel_visibility;
345 
346   const char               *snapshot_location;
347 
348   char                      *keymap_file;
349   kbinding_t                *kbindings;
350   int                        shortcut_style;
351   int                        kbindings_enabled;
352 
353   /* event handling */
354   struct {
355     int                      set;
356     int                      arg;
357   } numeric;
358   struct {
359     int                      set;
360     char                    *arg;
361   } alphanum;
362   int                        event_reject;
363   int                        event_pending;
364   pthread_mutex_t            event_mutex;
365   pthread_cond_t             event_safe;
366 
367   int                        eventer_sticky;
368   int                        stream_info_auto_update;
369 
370   char                       curdir[XITK_PATH_MAX];
371 
372   int                        play_anyway;
373 
374   int                        splash;
375 
376   pthread_mutex_t            download_mutex;
377 
378   FILE                      *report;
379 
380   int                        no_gui;
381 
382   int                        no_mouse;
383   int                        wid;
384 
385   void                     (*nongui_error_msg)(const char *text);
386 
387   FILE                      *orig_stdout; /* original stdout at startup        */
388                                           /* before an evtl. later redirection */
389 
390   /* suspend event messages */
391   struct {
392     pthread_mutex_t          mutex;
393     struct timeval           until;
394     int                      level;
395   } no_messages;
396 
397   xui_panel_t               *panel;
398   xui_vwin_t                *vwin;
399   xui_setup_t               *setup;
400   xui_mrlb_t                *mrlb;
401   xui_vctrl_t               *vctrl;
402 
403   /* actions.c */
404   filebrowser_t             *load_stream;
405   filebrowser_t             *load_sub;
406   int                        last_playback_speed;
407 
408   /* main.c */
409   char                     **video_driver_ids;
410   char                     **audio_driver_ids;
411   window_attributes_t        window_attribute;
412 };
413 
414 extern gGui_t *gGui;
415 
416 void set_window_states_start(Window window);
417 #define set_window_states_start(window)                                   \
418   do {                                                                    \
419     if(!video_window_is_visible(gGui->vwin))                              \
420       xitk_set_wm_window_type((window), WINDOW_TYPE_NORMAL);              \
421     else                                                                  \
422       xitk_unset_wm_window_type((window), WINDOW_TYPE_NORMAL);            \
423     change_class_name((window));                                          \
424     change_icon((window));                                                \
425   } while(0)
426 
427 void reparent_window(Window window);
428 #define reparent_window(window)                                                          \
429   do {                                                                                   \
430     if((!(video_window_get_fullscreen_mode(gGui->vwin) & WINDOWED_MODE)) && !wm_not_ewmh_only()) { \
431       XLockDisplay(gGui->display);                                                       \
432       /* Don't unmap this window, because on re-mapping, it will not be visible until    \
433 	 its ancestor, the video window, is visible. That's not what's intended.         \
434          XUnmapWindow(gGui->display, (window));                                          \
435       */								                 \
436       if(!video_window_is_visible(gGui->vwin))                                           \
437         xitk_set_wm_window_type((window), WINDOW_TYPE_NORMAL);                           \
438       else                                                                               \
439         xitk_unset_wm_window_type((window), WINDOW_TYPE_NORMAL);                         \
440       XRaiseWindow(gGui->display, (window));                                             \
441       XMapWindow(gGui->display, (window));                                               \
442       try_to_set_input_focus((window));                                                  \
443       if(!gGui->use_root_window && gGui->video_display == gGui->display)                 \
444         XSetTransientForHint (gGui->display, (window), gGui->video_window);              \
445       XUnlockDisplay(gGui->display);                                                     \
446     }                                                                                    \
447     else {                                                                               \
448       XLockDisplay(gGui->display);                                                       \
449       XRaiseWindow(gGui->display, window);                                               \
450       XMapWindow(gGui->display, window);                                                 \
451       if(!gGui->use_root_window && gGui->video_display == gGui->display)                 \
452         XSetTransientForHint (gGui->display, window, gGui->video_window);                \
453       XUnlockDisplay(gGui->display);                                                     \
454       layer_above_video(window);                                                         \
455     }                                                                                    \
456   } while(0)
457 
458 void change_class_name(Window window);
459 #define change_class_name(window)                                         \
460   do {                                                                    \
461     XClassHint  xclasshint;                                               \
462     XLockDisplay (gGui->display);                                         \
463     if((XGetClassHint(gGui->display, (window), &xclasshint)) != 0) {      \
464       XClassHint   nxclasshint;                                           \
465       nxclasshint.res_name = xclasshint.res_name;                         \
466       nxclasshint.res_class = "xine";                                     \
467       XSetClassHint(gGui->display, window, &nxclasshint);                 \
468       XFree(xclasshint.res_name);                                         \
469       XFree(xclasshint.res_class);                                        \
470     }                                                                     \
471     XUnlockDisplay (gGui->display);                                       \
472   } while(0)
473 
474 void change_icon(Window window);
475 #define change_icon(window)                                               \
476   do {                                                                    \
477     XWMHints *wmhints;                                                    \
478     XLockDisplay(gGui->display);                                          \
479     if((wmhints = XAllocWMHints())) {                                     \
480       wmhints->icon_pixmap   = gGui->icon;                                \
481       wmhints->flags         = IconPixmapHint;                            \
482       XSetWMHints(gGui->display, (window), wmhints);                      \
483       XFree(wmhints);                                                     \
484     }                                                                     \
485     XUnlockDisplay(gGui->display);                                        \
486   } while(0)
487 
488 #ifdef HAVE_XML_PARSER_REENTRANT
489 # define xml_parser_init_R(X,D,L,M) X = xml_parser_init_r ((D), (L), (M))
490 # define xml_parser_build_tree_R(X,T) xml_parser_build_tree_r ((X), (T))
491 # define xml_parser_finalize_R(X) xml_parser_finalize_r ((X))
492 #else
493 # define xml_parser_init_R(X,D,L,M) xml_parser_init ((D), (L), (M))
494 # define xml_parser_build_tree_R(X,T) xml_parser_build_tree ((T))
495 # define xml_parser_finalize_R(X) do {} while (0)
496 #endif
497 
498 #endif
499