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  * gui initialization and top-level event handling stuff
21  *
22  */
23 #ifdef HAVE_CONFIG_H
24 #include "config.h"
25 #endif
26 
27 #include <stdio.h>
28 #include <sys/time.h>
29 #include <X11/Xlib.h>
30 #include <X11/Xutil.h>
31 #include <X11/keysym.h>
32 #include <X11/Xmd.h>
33 
34 #include <errno.h>
35 #include <pthread.h>
36 #include <signal.h>
37 #include <limits.h>
38 #include <zlib.h>
39 #include <sys/wait.h>
40 #include <time.h>
41 #include <stdlib.h>
42 #include <pthread.h>
43 
44 /* input_pvr functionality needs this */
45 #define XINE_ENABLE_EXPERIMENTAL_FEATURES
46 
47 #include "common.h"
48 #include "oxine/oxine.h"
49 
50 /*
51  * global variables
52  */
53 static pid_t            xine_pid;
54 
55 /* Icon data */
56 static const unsigned char icon_datas[] = {
57    0x11, 0x00, 0x00, 0x00, 0x88, 0x11, 0x00, 0x00, 0x00, 0x88, 0xff, 0xff,
58    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf1, 0xff, 0xff, 0xff,
59    0x8f, 0xf1, 0xff, 0xff, 0xff, 0x8f, 0x1f, 0x00, 0x00, 0x00, 0xf8, 0x1f,
60    0x00, 0x00, 0x00, 0xf8, 0x11, 0x00, 0x00, 0x00, 0x88, 0x11, 0x00, 0x00,
61    0x00, 0x88, 0x1f, 0x00, 0x00, 0x00, 0xf8, 0x1f, 0x00, 0x00, 0x00, 0xf8,
62    0x11, 0x00, 0x00, 0x00, 0x88, 0x11, 0x00, 0x00, 0x00, 0x88, 0x1f, 0x00,
63    0x00, 0x00, 0xf8, 0x1f, 0x00, 0x00, 0x00, 0xf8, 0x11, 0x00, 0x00, 0x00,
64    0x88, 0x11, 0x91, 0x79, 0xf8, 0x88, 0x1f, 0x9b, 0x99, 0x0c, 0xf8, 0x1f,
65    0x8e, 0x99, 0x7d, 0xf8, 0x11, 0x8e, 0x99, 0x7d, 0x88, 0x11, 0x9b, 0x99,
66    0x0d, 0x88, 0x1f, 0x91, 0x99, 0xf9, 0xf8, 0x1f, 0x00, 0x00, 0x00, 0xf8,
67    0x11, 0x00, 0x00, 0x00, 0x88, 0x11, 0x00, 0x00, 0x00, 0x88, 0x1f, 0x00,
68    0x00, 0x00, 0xf8, 0x1f, 0x00, 0x00, 0x00, 0xf8, 0x11, 0x00, 0x00, 0x00,
69    0x88, 0x11, 0x00, 0x00, 0x00, 0x88, 0x1f, 0x00, 0x00, 0x00, 0xf8, 0x1f,
70    0x00, 0x00, 0x00, 0xf8, 0xf1, 0xff, 0xff, 0xff, 0x8f, 0xf1, 0xff, 0xff,
71    0xff, 0x8f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
72    0x11, 0x00, 0x00, 0x00, 0x88, 0x11, 0x00, 0x00, 0x00, 0x88, 0x1f, 0x00,
73    0x00, 0x00, 0xf8, 0x1f, 0x00, 0x00, 0x00, 0xf8
74 };
75 
76 static const char *const exp_levels[] = {
77   "Beginner",
78   "Advanced",
79   "Expert",
80   "Master of the known universe",
81 #ifdef DEBUG
82   "Debugger",
83 #else
84   NULL,
85 #endif
86   NULL
87 };
88 
89 static const char *const visual_anim_style[] = {
90   "None",
91   "Post Plugin",
92   "Stream Animation",
93   NULL
94 };
95 
96 static const char *const mixer_control_method[] = {
97   "Sound card",
98   "Software",
99   NULL
100 };
101 
102 static const char *const shortcut_style[] = {
103   "Windows style",
104   "Emacs style",
105   NULL
106 };
107 
hidden_file_cb(int action,int value)108 int hidden_file_cb(int action, int value) {
109   xine_cfg_entry_t  cfg_entry;
110   int               retval = 0;
111 
112   if(xine_config_lookup_entry (gGui->xine, "media.files.show_hidden_files", &cfg_entry)) {
113     if(action)
114       config_update_bool("media.files.show_hidden_files", value);
115     else
116       retval = cfg_entry.num_value;
117   }
118 
119   return retval;
120 }
121 
dummy_config_cb(void * data,xine_cfg_entry_t * cfg)122 void dummy_config_cb(void *data, xine_cfg_entry_t *cfg) {
123   /* It exist to avoid "restart" window message in setup window */
124   (void)data;
125   (void)cfg;
126 }
auto_vo_visibility_cb(void * data,xine_cfg_entry_t * cfg)127 static void auto_vo_visibility_cb(void *data, xine_cfg_entry_t *cfg) {
128   gGui_t *gui = data;
129   gui->auto_vo_visibility = cfg->num_value;
130 }
auto_panel_visibility_cb(void * data,xine_cfg_entry_t * cfg)131 static void auto_panel_visibility_cb(void *data, xine_cfg_entry_t *cfg) {
132   gGui_t *gui = data;
133   gui->auto_panel_visibility = cfg->num_value;
134 }
skip_by_chapter_cb(void * data,xine_cfg_entry_t * cfg)135 static void skip_by_chapter_cb(void *data, xine_cfg_entry_t *cfg) {
136   gGui_t *gui = data;
137   gui->skip_by_chapter = cfg->num_value;
138   panel_update_nextprev_tips (gui->panel);
139 }
ssaver_timeout_cb(void * data,xine_cfg_entry_t * cfg)140 static void ssaver_timeout_cb(void *data, xine_cfg_entry_t *cfg) {
141   gGui_t *gui = data;
142   gui->ssaver_timeout = cfg->num_value;
143 }
144 
visual_anim_cb(void * data,xine_cfg_entry_t * cfg)145 static void visual_anim_cb(void *data, xine_cfg_entry_t *cfg) {
146   gGui_t *gui = data;
147 
148   if(gui->visual_anim.enabled == cfg->num_value)
149     return;
150 
151   if((gui->visual_anim.enabled) && (cfg->num_value == 0) && gui->visual_anim.running)
152     visual_anim_stop();
153 
154   if(gui->visual_anim.enabled && gui->visual_anim.running) {
155     if((gui->visual_anim.enabled == 1) && (cfg->num_value != 1)) {
156       if(post_rewire_audio_port_to_stream(gui->stream))
157 	gui->visual_anim.running = 0;
158     }
159     if((gui->visual_anim.enabled == 2) && (cfg->num_value != 2)) {
160       visual_anim_stop();
161       gui->visual_anim.running = 0;
162     }
163   }
164 
165   gui->visual_anim.enabled = cfg->num_value;
166 
167   if(gui->visual_anim.enabled) {
168     int  has_video = xine_get_stream_info(gui->stream, XINE_STREAM_INFO_HAS_VIDEO);
169 
170     if(has_video)
171       has_video = !xine_get_stream_info(gui->stream, XINE_STREAM_INFO_IGNORE_VIDEO);
172 
173     if(!has_video && !gui->visual_anim.running) {
174       if(gui->visual_anim.enabled == 1) {
175 	if(gui->visual_anim.post_output_element.post) {
176 	  if(post_rewire_audio_post_to_stream(gui->stream))
177 	    gui->visual_anim.running = 1;
178 	}
179       }
180       else if(gui->visual_anim.enabled == 2) {
181 	visual_anim_play();
182 	gui->visual_anim.running = 1;
183       }
184     }
185   }
186 }
187 
stream_info_auto_update_cb(void * data,xine_cfg_entry_t * cfg)188 static void stream_info_auto_update_cb(void *data, xine_cfg_entry_t *cfg) {
189   gGui_t *gui = data;
190   gui->stream_info_auto_update = cfg->num_value;
191   stream_infos_toggle_auto_update();
192 }
193 
194 /*
195  * Layer above callbacks
196  */
layer_above_cb(void * data,xine_cfg_entry_t * cfg)197 static void layer_above_cb(void *data, xine_cfg_entry_t *cfg) {
198   gGui_t *gui = data;
199   gui->layer_above = cfg->num_value;
200 }
always_layer_above_cb(void * data,xine_cfg_entry_t * cfg)201 static void always_layer_above_cb(void *data, xine_cfg_entry_t *cfg) {
202   gGui_t *gui = data;
203   gui->always_layer_above = cfg->num_value;
204 }
205 
206 /*
207  * Callback for snapshots saving location.
208  */
snapshot_loc_cb(void * data,xine_cfg_entry_t * cfg)209 static void snapshot_loc_cb(void *data, xine_cfg_entry_t *cfg) {
210   gGui_t *gui = data;
211   gui->snapshot_location = cfg->str_value;
212 }
213 
214 /*
215  * Callback for skin server
216  */
skin_server_url_cb(void * data,xine_cfg_entry_t * cfg)217 static void skin_server_url_cb(void *data, xine_cfg_entry_t *cfg) {
218   gGui_t *gui = data;
219   gui->skin_server_url = cfg->str_value;
220 }
221 
222 /*
223  * OSD cbs
224  */
osd_enabled_cb(void * data,xine_cfg_entry_t * cfg)225 static void osd_enabled_cb(void *data, xine_cfg_entry_t *cfg) {
226   gGui_t *gui = data;
227   gui->osd.enabled = cfg->num_value;
228 }
osd_use_unscaled_cb(void * data,xine_cfg_entry_t * cfg)229 static void osd_use_unscaled_cb(void *data, xine_cfg_entry_t *cfg) {
230   gGui_t *gui = data;
231   gui->osd.use_unscaled = cfg->num_value;
232 }
osd_timeout_cb(void * data,xine_cfg_entry_t * cfg)233 static void osd_timeout_cb(void *data, xine_cfg_entry_t *cfg) {
234   gGui_t *gui = data;
235   gui->osd.timeout = cfg->num_value;
236 }
237 
smart_mode_cb(void * data,xine_cfg_entry_t * cfg)238 static void smart_mode_cb(void *data, xine_cfg_entry_t *cfg) {
239   gGui_t *gui = data;
240   gui->smart_mode = cfg->num_value;
241 }
242 
play_anyway_cb(void * data,xine_cfg_entry_t * cfg)243 static void play_anyway_cb(void *data, xine_cfg_entry_t *cfg) {
244   gGui_t *gui = data;
245   gui->play_anyway = cfg->num_value;
246 }
247 
exp_level_cb(void * data,xine_cfg_entry_t * cfg)248 static void exp_level_cb(void *data, xine_cfg_entry_t *cfg) {
249   gGui_t *gui = data;
250   gui->experience_level = (cfg->num_value * 10);
251 }
252 
audio_mixer_method_cb(void * data,xine_cfg_entry_t * cfg)253 static void audio_mixer_method_cb(void *data, xine_cfg_entry_t *cfg) {
254   gGui_t *gui = data;
255   gui->mixer.method = cfg->num_value;
256   panel_update_mixer_display (gui->panel);
257 }
258 
shortcut_style_cb(void * data,xine_cfg_entry_t * cfg)259 static void shortcut_style_cb(void *data, xine_cfg_entry_t *cfg) {
260   gGui_t *gui = data;
261   gui->shortcut_style = cfg->num_value;
262 }
263 
wm_not_ewmh_only(void)264 int wm_not_ewmh_only(void) {
265   int wm_type = xitk_get_wm_type();
266 
267   if((wm_type & WM_TYPE_GNOME_COMP) && !(wm_type & WM_TYPE_EWMH_COMP))
268     return 0;
269   else if(wm_type & WM_TYPE_EWMH_COMP)
270     return 1;
271 
272   return 0;
273 }
274 
actions_on_start(action_id_t actions[],action_id_t a)275 int actions_on_start(action_id_t actions[], action_id_t a) {
276   int i = 0, num = 0;
277   while(actions[i] != ACTID_NOKEY) {
278     if(actions[i] == a)
279       num++;
280     i++;
281   }
282   return num;
283 }
284 
285 /*
286  *
287  */
dummy_sighandler(int dummy)288 static void dummy_sighandler(int dummy) {
289   (void)dummy;
290 }
291 
gui_signal_handler(int sig,void * data)292 static void gui_signal_handler (int sig, void *data) {
293   pid_t     cur_pid = getppid();
294 
295   (void)data;
296   switch (sig) {
297 
298   case SIGHUP:
299     if(cur_pid == xine_pid) {
300       printf("SIGHUP received: re-read config file\n");
301       xine_config_reset (gGui->xine);
302       xine_config_load (gGui->xine, __xineui_global_config_file);
303     }
304     break;
305 
306   case SIGUSR1:
307     if(cur_pid == xine_pid) {
308       printf("SIGUSR1 received\n");
309     }
310     break;
311 
312   case SIGUSR2:
313     if(cur_pid == xine_pid) {
314       printf("SIGUSR2 received\n");
315     }
316     break;
317 
318   case SIGINT:
319   case SIGTERM:
320     if(cur_pid == xine_pid) {
321       struct sigaction action;
322 
323       xine_config_save (gGui->xine, __xineui_global_config_file);
324 
325       action.sa_handler = dummy_sighandler;
326       sigemptyset(&(action.sa_mask));
327       action.sa_flags = 0;
328       if(sigaction(SIGALRM, &action, NULL) != 0) {
329 	fprintf(stderr, "sigaction(SIGALRM) failed: %s\n", strerror(errno));
330       }
331       alarm(5);
332 
333       /* We should call xine_stop() here, but since the */
334       /* xine functions are not signal-safe, we cant.   */
335 
336       /*xine_stop(gui->stream);*/
337     }
338     break;
339   }
340 
341 }
342 
343 
344 /*
345  * convert pts value to string
346  */
pts2str(int64_t pts)347 static const char *pts2str(int64_t pts) {
348   static char  buf[40];
349   int64_t      min;
350   double       sec;
351   int          ds;
352   int          sign;
353 
354   if((sign = (pts < 0)) != 0)
355     pts = -pts;
356 
357   min = pts / (90000 * 60);
358   sec = (double)pts / 90000 - 60 * min;
359   ds  = sec / 10;
360   sec -= 10 * ds;
361 
362   snprintf(buf, sizeof(buf), "%s%02" PRIi64 ":%d%.2f (%" PRIi64 " pts)", sign ? "-" : "", min, ds, sec, pts);
363 
364   return buf;
365 }
366 
367 
368 /*
369  *
370  */
gui_execute_action_id(gGui_t * gui,action_id_t action)371 void gui_execute_action_id (gGui_t *gui, action_id_t action) {
372   xine_event_t   xine_event;
373   int narg = -1;
374   char *sarg = NULL;
375 
376   if (gui->event_reject)
377     return;
378 
379   pthread_mutex_lock (&gui->event_mutex);
380 
381   if (gui->event_reject) {
382     pthread_mutex_unlock (&gui->event_mutex);
383     return;
384   }
385 
386   gui->event_pending++;
387 
388   if(action & ACTID_IS_INPUT_EVENT) {
389 
390     /* Note: In the following overflow checks, we must test against INT_MAX */
391     /* carefully. Otherwise, the comparison term may overflow itself and    */
392     /* detecting the overflow condition will fail (never true or true by    */
393     /* chance, depending on expression and rearranging by the compiler).    */
394 
395     if((action >= ACTID_EVENT_NUMBER_0) && (action <= ACTID_EVENT_NUMBER_9)) {
396       int n = action - ACTID_EVENT_NUMBER_0;
397 
398       if (!gui->numeric.set) {
399         gui->numeric.set = 1;
400         gui->numeric.arg = n;
401       }
402       else if (gui->numeric.arg <= ((INT_MAX - n) / 10)) {
403         gui->numeric.arg *= 10;
404         gui->numeric.arg += n;
405       }
406       else
407         fprintf (stderr, "xine-ui: Input number overflow, using %d\n", gui->numeric.arg);
408 
409     }
410     else if(action == ACTID_EVENT_NUMBER_10_ADD) {
411 
412       if (!gui->numeric.set) {
413         gui->numeric.set = 1;
414         gui->numeric.arg = 10;
415       }
416       else if (gui->numeric.arg <= (INT_MAX - 10))
417         gui->numeric.arg += 10;
418       else
419         fprintf (stderr, "xine-ui: Input number overflow, using %d\n", gui->numeric.arg);
420 
421     }
422     else {
423       gui->numeric.set = 0;
424       gui->numeric.arg = 0;
425     }
426 
427     pthread_mutex_unlock (&gui->event_mutex);
428 
429     /* check if osd menu like this event */
430     if (oxine_action_event (action & ~ACTID_IS_INPUT_EVENT)) {
431       pthread_mutex_lock (&gui->event_mutex);
432       gui->event_pending--;
433       if ((gui->event_pending <= 0) && gui->event_reject)
434         pthread_cond_signal (&gui->event_safe);
435       pthread_mutex_unlock (&gui->event_mutex);
436       return;
437     }
438 
439     /* events for advanced input plugins. */
440     xine_event.type        = action & ~ACTID_IS_INPUT_EVENT;
441     xine_event.data_length = 0;
442     xine_event.data        = NULL;
443     xine_event.stream      = gui->stream;
444     gettimeofday(&xine_event.tv, NULL);
445 
446     xine_event_send(gui->stream, &xine_event);
447     pthread_mutex_lock (&gui->event_mutex);
448     gui->event_pending--;
449     if ((gui->event_pending <= 0) && gui->event_reject)
450       pthread_cond_signal (&gui->event_safe);
451     pthread_mutex_unlock (&gui->event_mutex);
452     return;
453   }
454 
455   if (gui->numeric.set)
456     narg = gui->numeric.arg;
457   gui->numeric.set = 0;
458   gui->numeric.arg = 0;
459 
460   if (gui->alphanum.set) {
461     if ((action == ACTID_OSD_WTEXT) || (action == ACTID_PVR_SETNAME) || (action == ACTID_PLAYLIST_OPEN))
462       sarg = strdup (gui->alphanum.arg ? gui->alphanum.arg : "");
463   }
464   gui->alphanum.set = 0;
465   gui->alphanum.arg = "";
466 
467   pthread_mutex_unlock (&gui->event_mutex);
468 
469   switch(action) {
470 
471   case ACTID_WINDOWREDUCE:
472     {
473       int	output_width, output_height;
474 
475       /* Limit size to a practical minimum.                         */
476       /* Too small window is hard to view or to hit with the mouse. */
477 
478       video_window_get_output_size (gui->vwin, &output_width, &output_height);
479       if(output_width > 50 && output_height > 50) {
480 	float	xmag, ymag;
481 
482         video_window_get_mag (gui->vwin, &xmag, &ymag);
483         video_window_set_mag (gui->vwin, xmag * (1/1.2f), ymag * (1/1.2f));
484       }
485     }
486     break;
487 
488   case ACTID_WINDOWENLARGE:
489     {
490       int	output_width, output_height, window_width, window_height;
491 
492       /* Limit size to a practical maximum.                                        */
493       /* Too large window can grab system resources up to a virtual dead lock.     */
494       /* Compare output size to window size as a WM (like fvwm) can be configured  */
495       /* to impose limits on window size which may not be reflected back to output */
496       /* size (no further ConfigureNotify after size limit is exceeded),           */
497       /* so we'll not end up in endless magnification.                             */
498 
499       video_window_get_output_size (gui->vwin, &output_width, &output_height);
500       xitk_get_window_position(gui->video_display, gui->video_window,
501 			       NULL, NULL, &window_width, &window_height);
502       if(output_width < 5000 && output_height < 5000 &&
503 	 output_width <= window_width && output_height <= window_height) {
504 	float	xmag, ymag;
505 
506         video_window_get_mag (gui->vwin, &xmag, &ymag);
507         video_window_set_mag (gui->vwin, xmag * 1.2f, ymag * 1.2f);
508       }
509     }
510     break;
511 
512   case ACTID_ZOOM_1_1:
513   case ACTID_WINDOW100:
514     if (video_window_set_mag (gui->vwin, 1.0f, 1.0f))
515       osd_display_info(_("Zoom: 1:1"));
516     break;
517 
518   case ACTID_WINDOW200:
519     if (video_window_set_mag (gui->vwin, 2.0f, 2.0f))
520       osd_display_info(_("Zoom: 200%%"));
521     break;
522 
523   case ACTID_WINDOW50:
524     if (video_window_set_mag (gui->vwin, 0.5f, 0.5f))
525       osd_display_info(_("Zoom: 50%%"));
526     break;
527 
528   case ACTID_SPU_NEXT:
529     if (narg < 0)
530       gui_change_spu_channel(NULL, (void*)GUI_NEXT);
531     else
532       gui_direct_change_spu_channel (NULL, (void*)GUI_NEXT, narg);
533     break;
534 
535   case ACTID_SPU_PRIOR:
536     if (narg < 0)
537       gui_change_spu_channel(NULL, (void*)GUI_PREV);
538     else
539       gui_direct_change_spu_channel (NULL, (void*)GUI_PREV, narg);
540     break;
541 
542   case ACTID_CONTROLSHOW:
543     gui_control_show (NULL, gui->vctrl);
544     break;
545 
546   case ACTID_TOGGLE_WINOUT_VISIBLITY:
547     gui_toggle_visibility (NULL, gui);
548     break;
549 
550   case ACTID_TOGGLE_WINOUT_BORDER:
551     gui_toggle_border (NULL, gui);
552     break;
553 
554   case ACTID_AUDIOCHAN_NEXT:
555     if (narg < 0)
556       gui_change_audio_channel(NULL, (void*)GUI_NEXT);
557     else
558       gui_direct_change_audio_channel (NULL, gui, narg);
559     break;
560 
561   case ACTID_AUDIOCHAN_PRIOR:
562     if (narg < 0)
563       gui_change_audio_channel(NULL, (void*)GUI_PREV);
564     else
565       gui_direct_change_audio_channel (NULL, gui, narg);
566     break;
567 
568   case ACTID_PAUSE:
569     gui_pause (NULL, gui, 0);
570     break;
571 
572   case ACTID_PLAYLIST:
573     gui_playlist_show(NULL, NULL);
574     break;
575 
576   case ACTID_TOGGLE_VISIBLITY:
577     panel_toggle_visibility (NULL, gui->panel);
578     break;
579 
580   case ACTID_TOGGLE_FULLSCREEN:
581     if (narg >= 0) {
582       int fullscreen = video_window_get_fullscreen_mode (gui->vwin) & FULLSCR_MODE;
583       if ((narg && !fullscreen) || (!narg && fullscreen))
584         gui_set_fullscreen_mode (NULL, gui);
585     } else
586       gui_set_fullscreen_mode (NULL, gui);
587     break;
588 
589 #ifdef HAVE_XINERAMA
590   case ACTID_TOGGLE_XINERAMA_FULLSCREEN:
591     gui_set_xinerama_fullscreen_mode();
592     break;
593 #endif
594 
595   case ACTID_TOGGLE_ASPECT_RATIO:
596     if (narg < 0)
597       gui_toggle_aspect(-1);
598     else
599       gui_toggle_aspect (narg);
600     break;
601 
602   case ACTID_STREAM_INFOS:
603     gui_stream_infos_show(NULL, NULL);
604     break;
605 
606   case ACTID_TOGGLE_INTERLEAVE:
607     gui_toggle_interlaced();
608     break;
609 
610   case ACTID_QUIT:
611     pthread_mutex_lock (&gui->event_mutex);
612     gui->event_pending--;
613     if ((gui->event_pending <= 0) && gui->event_reject)
614       pthread_cond_signal (&gui->event_safe);
615     pthread_mutex_unlock (&gui->event_mutex);
616     gui_exit (NULL, gui);
617     break;
618 
619   case ACTID_PLAY:
620     gui_play (NULL, gui);
621     break;
622 
623   case ACTID_STOP:
624     gui_stop (NULL, gui);
625     break;
626 
627   case ACTID_CLOSE:
628     gui_close (NULL, gui);
629     break;
630 
631   case ACTID_EVENT_SENDER:
632     gui_event_sender_show(NULL, NULL);
633     break;
634 
635   case ACTID_MRL_NEXT:
636     if (narg < 0)
637       gui_nextprev(NULL, (void*)GUI_NEXT);
638     else
639       gui_direct_nextprev (NULL, (void*)GUI_NEXT, narg);
640     break;
641 
642   case ACTID_MRL_PRIOR:
643     if (narg < 0)
644       gui_nextprev(NULL, (void*)GUI_PREV);
645     else
646       gui_direct_nextprev (NULL, (void*)GUI_PREV, narg);
647     break;
648 
649   case ACTID_MRL_SELECT:
650     if (narg < 0)
651       gui_playlist_play (gui, 0);
652     else
653       gui_playlist_play (gui, narg);
654     break;
655 
656   case ACTID_SETUP:
657     gui_setup_show(NULL, NULL);
658     break;
659 
660   case ACTID_EJECT:
661     gui_eject (NULL, gui);
662     break;
663 
664   case ACTID_SET_CURPOS:
665     if (narg >= 0) {
666       /* Number is a percentage, range [0..100] */
667       if (narg > 100)
668         narg = 100;
669       gui_set_current_position ((65535 * narg) / 100);
670     }
671     break;
672 
673   case ACTID_SET_CURPOS_0:
674     gui_set_current_position (0);
675     break;
676 
677   case ACTID_SET_CURPOS_10:
678     gui_set_current_position (6553);
679     break;
680 
681   case ACTID_SET_CURPOS_20:
682     gui_set_current_position (13107);
683     break;
684 
685   case ACTID_SET_CURPOS_30:
686     gui_set_current_position (19660);
687     break;
688 
689   case ACTID_SET_CURPOS_40:
690     gui_set_current_position (26214);
691     break;
692 
693   case ACTID_SET_CURPOS_50:
694     gui_set_current_position (32767);
695     break;
696 
697   case ACTID_SET_CURPOS_60:
698     gui_set_current_position (39321);
699     break;
700 
701   case ACTID_SET_CURPOS_70:
702     gui_set_current_position (45874);
703     break;
704 
705   case ACTID_SET_CURPOS_80:
706     gui_set_current_position (52428);
707     break;
708 
709   case ACTID_SET_CURPOS_90:
710     gui_set_current_position (58981);
711     break;
712 
713   case ACTID_SET_CURPOS_100:
714     gui_set_current_position (65535);
715     break;
716 
717   case ACTID_SEEK_REL_m:
718     if (narg >= 0) {
719       gui_seek_relative (-narg);
720     }
721     break;
722 
723   case ACTID_SEEK_REL_p:
724     if (narg >= 0)
725       gui_seek_relative (narg);
726     break;
727 
728   case ACTID_SEEK_REL_m60:
729     gui_seek_relative (-60);
730     break;
731 
732   case ACTID_SEEK_REL_m15:
733     gui_seek_relative (-15);
734     break;
735 
736   case ACTID_SEEK_REL_p60:
737     gui_seek_relative (60);
738     break;
739 
740   case ACTID_SEEK_REL_p15:
741     gui_seek_relative (15);
742     break;
743 
744   case ACTID_SEEK_REL_m30:
745     gui_seek_relative (-30);
746     break;
747 
748   case ACTID_SEEK_REL_m7:
749     gui_seek_relative (-7);
750     break;
751 
752   case ACTID_SEEK_REL_p30:
753     gui_seek_relative (30);
754     break;
755 
756   case ACTID_SEEK_REL_p7:
757     gui_seek_relative (7);
758     break;
759 
760   case ACTID_MRLBROWSER:
761     gui_mrlbrowser_show(NULL, NULL);
762     break;
763 
764   case ACTID_MUTE:
765     panel_toggle_audio_mute (NULL, gui->panel, !gui->mixer.mute);
766     break;
767 
768   case ACTID_AV_SYNC_m3600:
769     {
770       int av_offset = (xine_get_param(gui->stream, XINE_PARAM_AV_OFFSET) - 3600);
771 
772       pthread_mutex_lock (&gui->event_mutex);
773       gui->mmk.av_offset = av_offset;
774       if (gui->playlist.num && gui->playlist.cur >= 0 && gui->playlist.mmk &&
775 	  gui->playlist.mmk[gui->playlist.cur])
776 	if (gui->playlist.cur < gui->playlist.num)
777 	  gui->playlist.mmk[gui->playlist.cur]->av_offset = av_offset;
778       pthread_mutex_unlock (&gui->event_mutex);
779       xine_set_param(gui->stream, XINE_PARAM_AV_OFFSET, av_offset);
780       osd_display_info(_("A/V offset: %s"), pts2str(av_offset));
781     }
782     break;
783 
784   case ACTID_AV_SYNC_p3600:
785     {
786       int av_offset = (xine_get_param(gui->stream, XINE_PARAM_AV_OFFSET) + 3600);
787 
788       pthread_mutex_lock (&gui->event_mutex);
789       gui->mmk.av_offset = av_offset;
790       if (gui->playlist.num && gui->playlist.cur >= 0 && gui->playlist.mmk &&
791 	  gui->playlist.mmk[gui->playlist.cur])
792 	if (gui->playlist.cur < gui->playlist.num)
793 	  gui->playlist.mmk[gui->playlist.cur]->av_offset = av_offset;
794       pthread_mutex_unlock (&gui->event_mutex);
795       xine_set_param(gui->stream, XINE_PARAM_AV_OFFSET, av_offset);
796       osd_display_info(_("A/V offset: %s"), pts2str(av_offset));
797     }
798     break;
799 
800   case ACTID_AV_SYNC_RESET:
801     pthread_mutex_lock (&gui->event_mutex);
802     gui->mmk.av_offset = 0;
803     if (gui->playlist.num && gui->playlist.cur >= 0 && gui->playlist.mmk &&
804 	gui->playlist.mmk[gui->playlist.cur])
805       if (gui->playlist.cur < gui->playlist.num)
806 	gui->playlist.mmk[gui->playlist.cur]->av_offset = 0;
807     pthread_mutex_unlock (&gui->event_mutex);
808     xine_set_param(gui->stream, XINE_PARAM_AV_OFFSET, 0);
809     osd_display_info(_("A/V Offset: reset."));
810     break;
811 
812   case ACTID_SV_SYNC_p:
813     {
814       int spu_offset = xine_get_param(gui->stream, XINE_PARAM_SPU_OFFSET) + 3600;
815 
816       xine_set_param(gui->stream, XINE_PARAM_SPU_OFFSET, spu_offset);
817 
818       osd_display_info(_("SPU Offset: %s"), pts2str(spu_offset));
819     }
820     break;
821 
822   case ACTID_SV_SYNC_m:
823     {
824       int spu_offset = xine_get_param(gui->stream, XINE_PARAM_SPU_OFFSET) - 3600;
825 
826       xine_set_param(gui->stream, XINE_PARAM_SPU_OFFSET, spu_offset);
827 
828       osd_display_info(_("SPU Offset: %s"), pts2str(spu_offset));
829     }
830     break;
831 
832   case ACTID_SV_SYNC_RESET:
833     xine_set_param(gui->stream, XINE_PARAM_SPU_OFFSET, 0);
834     osd_display_info(_("SPU Offset: reset."));
835     break;
836 
837   case ACTID_SPEED_FAST:
838     gui_change_speed_playback(NULL, (void*)GUI_PREV);
839     break;
840 
841   case ACTID_SPEED_SLOW:
842     gui_change_speed_playback(NULL, (void*)GUI_NEXT);
843     break;
844 
845   case ACTID_SPEED_RESET:
846     gui_change_speed_playback(NULL, (void*)GUI_RESET);
847     break;
848 
849   case ACTID_pVOLUME:
850     gui_increase_audio_volume();
851     break;
852 
853   case ACTID_mVOLUME:
854     gui_decrease_audio_volume();
855     break;
856 
857   case ACTID_APP:
858     gui_app_show(NULL, NULL);
859     break;
860 
861   case ACTID_APP_ENABLE:
862     gui_app_enable();
863     break;
864 
865   case ACTID_pAMP:
866     gui_increase_amp_level();
867     break;
868 
869   case ACTID_mAMP:
870     gui_decrease_amp_level();
871     break;
872 
873   case ACTID_AMP_RESET:
874     gui_reset_amp_level();
875     break;
876 
877   case ACTID_SNAPSHOT:
878     panel_snapshot (NULL, gui->panel);
879     break;
880 
881   case ACTID_ZOOM_IN:
882     gui_change_zoom(1,1);
883     break;
884 
885   case ACTID_ZOOM_OUT:
886     gui_change_zoom(-1,-1);
887     break;
888 
889   case ACTID_ZOOM_X_IN:
890     gui_change_zoom(1,0);
891     break;
892 
893   case ACTID_ZOOM_X_OUT:
894     gui_change_zoom(-1,0);
895     break;
896 
897   case ACTID_ZOOM_Y_IN:
898     gui_change_zoom(0,1);
899     break;
900 
901   case ACTID_ZOOM_Y_OUT:
902     gui_change_zoom(0,-1);
903     break;
904 
905   case ACTID_ZOOM_RESET:
906     gui_reset_zoom();
907     break;
908 
909   case ACTID_GRAB_POINTER:
910     if(!gui->cursor_grabbed) {
911       if (!panel_is_visible (gui->panel)) {
912 	gui->x_lock_display (gui->video_display);
913 	XGrabPointer(gui->video_display, gui->video_window, 1, None,
914 		     GrabModeAsync, GrabModeAsync, gui->video_window, None, CurrentTime);
915 	gui->x_unlock_display (gui->video_display);
916       }
917 
918       gui->cursor_grabbed = 1;
919     }
920     else {
921       gui->x_lock_display (gui->display);
922       XUngrabPointer(gui->display, CurrentTime);
923       gui->x_unlock_display (gui->display);
924       gui->cursor_grabbed = 0;
925     }
926     break;
927 
928   case ACTID_TOGGLE_TVMODE:
929     gui_toggle_tvmode();
930     break;
931 
932   case ACTID_TVANALOG:
933     gui_tvset_show(NULL, NULL);
934     break;
935 
936   case ACTID_VIEWLOG:
937     gui_viewlog_show(NULL, NULL);
938     break;
939 
940   case ACTID_KBEDIT:
941     gui_kbedit_show(NULL, NULL);
942     break;
943 
944   case ACTID_KBENABLE:
945     if (narg >= 0)
946       gui->kbindings_enabled = narg;
947     else
948       gui->kbindings_enabled = 1;
949     break;
950 
951   case ACTID_DPMSSTANDBY:
952     xine_system(0, "xset dpms force standby");
953     break;
954 
955   case ACTID_MRLIDENTTOGGLE:
956     gui->is_display_mrl = !gui->is_display_mrl;
957     panel_update_mrl_display (gui->panel);
958     playlist_mrlident_toggle();
959     break;
960 
961   case ACTID_SCANPLAYLIST:
962     playlist_scan_for_infos();
963     break;
964 
965   case ACTID_MMKEDITOR:
966     playlist_mmk_editor();
967     break;
968 
969   case ACTID_SUBSELECT:
970     gui_select_sub();
971     break;
972 
973   case ACTID_LOOPMODE:
974     if (narg < 0)
975       gui->playlist.loop++;
976     else
977       gui->playlist.loop = narg;
978     if(gui->playlist.loop >= PLAYLIST_LOOP_MODES_NUM ||
979        gui->playlist.loop <  PLAYLIST_LOOP_NO_LOOP)
980       gui->playlist.loop = PLAYLIST_LOOP_NO_LOOP;
981 
982     switch(gui->playlist.loop) {
983     case PLAYLIST_LOOP_NO_LOOP:
984       osd_display_info(_("Playlist: no loop."));
985       break;
986     case PLAYLIST_LOOP_LOOP:
987       osd_display_info(_("Playlist: loop."));
988       break;
989     case PLAYLIST_LOOP_REPEAT:
990       osd_display_info(_("Playlist: entry repeat."));
991       break;
992     case PLAYLIST_LOOP_SHUFFLE:
993       osd_display_info(_("Playlist: shuffle."));
994       break;
995     case PLAYLIST_LOOP_SHUF_PLUS:
996       osd_display_info(_("Playlist: shuffle forever."));
997       break;
998     }
999     break;
1000 
1001   case ACTID_ADDMEDIAMARK:
1002     gui_add_mediamark();
1003     break;
1004 
1005 #ifdef HAVE_TAR
1006   case ACTID_SKINDOWNLOAD:
1007     download_skin(gui->skin_server_url);
1008     break;
1009 #endif
1010 
1011   case ACTID_OSD_SINFOS:
1012     osd_stream_infos();
1013     break;
1014 
1015   case ACTID_OSD_WTEXT:
1016     if (sarg) {
1017       osd_display_info ("%s", sarg);
1018     } else {
1019       osd_display_info(_("No text to display!"));
1020     }
1021     break;
1022 
1023   case ACTID_OSD_MENU:
1024     oxine_menu();
1025     break;
1026 
1027   case ACTID_FILESELECTOR:
1028     gui_file_selector();
1029     break;
1030 
1031   case ACTID_HUECONTROLp:
1032     control_inc_image_prop (gui->vctrl, XINE_PARAM_VO_HUE);
1033     break;
1034   case ACTID_HUECONTROLm:
1035     control_dec_image_prop (gui->vctrl, XINE_PARAM_VO_HUE);
1036     break;
1037 
1038   case ACTID_SATURATIONCONTROLp:
1039     control_inc_image_prop (gui->vctrl, XINE_PARAM_VO_SATURATION);
1040     break;
1041   case ACTID_SATURATIONCONTROLm:
1042     control_dec_image_prop (gui->vctrl, XINE_PARAM_VO_SATURATION);
1043     break;
1044 
1045   case ACTID_BRIGHTNESSCONTROLp:
1046     control_inc_image_prop (gui->vctrl, XINE_PARAM_VO_BRIGHTNESS);
1047     break;
1048   case ACTID_BRIGHTNESSCONTROLm:
1049     control_dec_image_prop (gui->vctrl, XINE_PARAM_VO_BRIGHTNESS);
1050     break;
1051 
1052   case ACTID_CONTRASTCONTROLp:
1053     control_inc_image_prop (gui->vctrl, XINE_PARAM_VO_CONTRAST);
1054     break;
1055   case ACTID_CONTRASTCONTROLm:
1056     control_dec_image_prop (gui->vctrl, XINE_PARAM_VO_CONTRAST);
1057     break;
1058 
1059   case ACTID_GAMMACONTROLp:
1060 #ifdef XINE_PARAM_VO_GAMMA
1061     control_inc_image_prop (gui->vctrl, XINE_PARAM_VO_GAMMA);
1062 #endif
1063     break;
1064   case ACTID_GAMMACONTROLm:
1065 #ifdef XINE_PARAM_VO_GAMMA
1066     control_dec_image_prop (gui->vctrl, XINE_PARAM_VO_GAMMA);
1067 #endif
1068     break;
1069 
1070   case ACTID_SHARPNESSCONTROLp:
1071 #ifdef XINE_PARAM_VO_SHARPNESS
1072     control_inc_image_prop (gui->vctrl, XINE_PARAM_VO_SHARPNESS);
1073 #endif
1074     break;
1075   case ACTID_SHARPNESSCONTROLm:
1076 #ifdef XINE_PARAM_VO_SHARPNESS
1077     control_dec_image_prop (gui->vctrl, XINE_PARAM_VO_SHARPNESS);
1078 #endif
1079     break;
1080 
1081   case ACTID_NOISEREDUCTIONCONTROLp:
1082 #ifdef XINE_PARAM_VO_NOISE_REDUCTION
1083     control_inc_image_prop (gui->vctrl, XINE_PARAM_VO_NOISE_REDUCTION);
1084 #endif
1085     break;
1086   case ACTID_NOISEREDUCTIONCONTROLm:
1087 #ifdef XINE_PARAM_VO_NOISE_REDUCTION
1088     control_dec_image_prop (gui->vctrl, XINE_PARAM_VO_NOISE_REDUCTION);
1089 #endif
1090     break;
1091 
1092   case ACTID_VPP:
1093     gui_vpp_show(NULL, NULL);
1094     break;
1095 
1096   case ACTID_VPP_ENABLE:
1097     gui_vpp_enable();
1098     break;
1099 
1100   case ACTID_HELP_SHOW:
1101     gui_help_show(NULL, NULL);
1102     break;
1103 
1104   case ACTID_PLAYLIST_STOP:
1105     if (narg < 0) {
1106       gui->playlist.control ^= PLAYLIST_CONTROL_STOP;
1107       gui->playlist.control &= ~PLAYLIST_CONTROL_STOP_PERSIST;
1108     }
1109     else {
1110       if (narg == 0)
1111 	gui->playlist.control &= ~PLAYLIST_CONTROL_STOP;
1112       else
1113 	gui->playlist.control |= PLAYLIST_CONTROL_STOP;
1114       gui->playlist.control |= PLAYLIST_CONTROL_STOP_PERSIST;
1115     }
1116     osd_display_info(_("Playlist: %s"),
1117 		     (gui->playlist.control & PLAYLIST_CONTROL_STOP) ?
1118 		     (gui->playlist.control & PLAYLIST_CONTROL_STOP_PERSIST) ?
1119 		     _("Stop (persistent)") :
1120 		     _("Stop") :
1121 		     _("Continue"));
1122     break;
1123 
1124   case ACTID_PVR_SETINPUT:
1125 
1126     /* Parameter (integer, required): input
1127     */
1128     if (narg >= 0) {
1129       xine_event_t         xine_event;
1130       xine_set_v4l2_data_t ev_data;
1131 
1132       /* set input */
1133       ev_data.input = narg;
1134 
1135       /* do not change tuning */
1136       ev_data.channel = -1;
1137       ev_data.frequency = -1;
1138 
1139       /* do not set session id */
1140       ev_data.session_id = -1;
1141 
1142       /* send event */
1143       xine_event.type = XINE_EVENT_SET_V4L2;
1144       xine_event.data_length = sizeof(xine_set_v4l2_data_t);
1145       xine_event.data = &ev_data;
1146       xine_event.stream = gui->stream;
1147       xine_event_send(gui->stream, &xine_event);
1148     }
1149     break;
1150 
1151   case ACTID_PVR_SETFREQUENCY:
1152 
1153     /* Parameter (integer, required): frequency
1154     */
1155     if (narg >= 0) {
1156       xine_event_t         xine_event;
1157       xine_set_v4l2_data_t ev_data;
1158 
1159       /* do not change input */
1160       ev_data.input = -1;
1161 
1162       /* change tuning */
1163       ev_data.channel = -1;
1164       ev_data.frequency = narg;
1165 
1166       /* do not set session id */
1167       ev_data.session_id = -1;
1168 
1169       /* send event */
1170       xine_event.type = XINE_EVENT_SET_V4L2;
1171       xine_event.data_length = sizeof(xine_set_v4l2_data_t);
1172       xine_event.data = &ev_data;
1173       xine_event.stream = gui->stream;
1174       xine_event_send(gui->stream, &xine_event);
1175     }
1176     break;
1177 
1178   case ACTID_PVR_SETMARK:
1179 
1180     /* Parameter (integer, required): session_id
1181 
1182        Mark the start of a section in the pvr stream for later saving
1183        The 'id' can be used to set different marks in the stream. If
1184        an existing mark is provided, then the mark for that section
1185        is moved to the current position.
1186     */
1187     if (narg >= 0) {
1188       xine_event_t         xine_event;
1189       xine_set_v4l2_data_t ev_data;
1190 
1191       /* do not change input */
1192       ev_data.input = -1;
1193 
1194       /* do not change tuning */
1195       ev_data.channel = -1;
1196       ev_data.frequency = -1;
1197 
1198       /* set session id */
1199       ev_data.session_id = narg;
1200 
1201       /* send event */
1202       xine_event.type = XINE_EVENT_SET_V4L2;
1203       xine_event.data_length = sizeof(xine_set_v4l2_data_t);
1204       xine_event.data = &ev_data;
1205       xine_event.stream = gui->stream;
1206       xine_event_send(gui->stream, &xine_event);
1207     }
1208     break;
1209 
1210   case ACTID_PVR_SETNAME:
1211 
1212     /* Parameter (string, required): name
1213 
1214        Set the name of the current section in the pvr stream. The name
1215        is used when the section is saved permanently.
1216     */
1217     if (sarg) {
1218       xine_event_t         xine_event;
1219       xine_pvr_save_data_t ev_data;
1220 
1221       /* only set name */
1222       ev_data.mode = -1;
1223       ev_data.id = -1;
1224 
1225       /* name of the show, max 255 is hardcoded in xine.h */
1226       strlcpy (ev_data.name, sarg, sizeof(ev_data.name));
1227 
1228       /* send event */
1229       xine_event.type = XINE_EVENT_PVR_SAVE;
1230       xine_event.data = &ev_data;
1231       xine_event.data_length = sizeof(xine_pvr_save_data_t);
1232       xine_event.stream = gui->stream;
1233       xine_event_send(gui->stream, &xine_event);
1234     }
1235     break;
1236 
1237   case ACTID_PVR_SAVE:
1238 
1239     /* Parameter (integer, required): mode
1240 
1241        Save the pvr stream with mode:
1242          mode = 0 : save from now on
1243          mode = 1 : save from last mark
1244          mode = 2 : save entire stream
1245     */
1246     if (narg >= 0) {
1247       xine_event_t         xine_event;
1248       xine_pvr_save_data_t ev_data;
1249       int                  mode = narg;
1250 
1251       /* set mode [0..2] */
1252       if(mode < 0)
1253 	mode = 0;
1254       if(mode > 2)
1255 	mode = 2;
1256       ev_data.mode = mode;
1257 
1258       /* do not set id and name */
1259       ev_data.id = 0;
1260       ev_data.name[0] = '\0';
1261 
1262       /* send event */
1263       xine_event.type = XINE_EVENT_PVR_SAVE;
1264       xine_event.data = &ev_data;
1265       xine_event.data_length = sizeof(xine_pvr_save_data_t);
1266       xine_event.stream = gui->stream;
1267       xine_event_send(gui->stream, &xine_event);
1268     }
1269     break;
1270 
1271   case ACTID_PLAYLIST_OPEN:
1272     if (sarg) {
1273         mediamark_load_mediamarks (sarg);
1274         gui_set_current_mmk(mediamark_get_current_mmk());
1275         playlist_update_playlist();
1276         if ((!is_playback_widgets_enabled (gui->panel)) && gui->playlist.num)
1277           enable_playback_controls (gui->panel, 1);
1278     }
1279     break;
1280 
1281   default:
1282     break;
1283   }
1284 
1285   free (sarg);
1286   pthread_mutex_lock (&gui->event_mutex);
1287   gui->event_pending--;
1288   if ((gui->event_pending <= 0) && gui->event_reject)
1289     pthread_cond_signal (&gui->event_safe);
1290   pthread_mutex_unlock (&gui->event_mutex);
1291 }
1292 
1293 /*
1294  * top-level event handler
1295  */
gui_handle_event(XEvent * event,void * data)1296 void gui_handle_event (XEvent *event, void *data) {
1297   gGui_t *gui = data;
1298 
1299   switch(event->type) {
1300 
1301   case MappingNotify:
1302     gui->x_lock_display (gui->display);
1303     XRefreshKeyboardMapping((XMappingEvent *) event);
1304     gui->x_unlock_display (gui->display);
1305     break;
1306 
1307   case DestroyNotify:
1308     if(event->xany.window == gui->panel_window
1309        || event->xany.window == gui->video_window) {
1310       xine_exit (gui->xine);
1311       gui->running = 0;
1312     }
1313     break;
1314 
1315   case ButtonPress: {
1316     XButtonEvent *bevent = (XButtonEvent *) event;
1317     /* printf ("ButtonPress\n"); */
1318 
1319     /* printf ("button: %d\n",bevent->button); */
1320 
1321     if ((bevent->button == 3) && (bevent->window == gui->video_window))
1322       panel_toggle_visibility (NULL, gui->panel);
1323 
1324   }
1325   break;
1326 
1327   case KeyPress:
1328     if(gui->stdctl_enable)
1329       stdctl_keypress(event->xkey);
1330     /* no break */
1331   case ButtonRelease:
1332     kbindings_handle_kbinding(gui->kbindings, event);
1333     break;
1334 
1335   case ConfigureNotify:
1336     break;
1337 
1338     /*
1339       default:
1340       printf("Got event: %i\n", event->type);
1341     */
1342   }
1343 
1344 }
1345 
1346 /*
1347  * Start playback of an entry in playlist
1348  */
gui_playlist_play(gGui_t * gui,int idx)1349 int gui_playlist_play (gGui_t *gui, int idx) {
1350   int ret = 1;
1351 
1352   osd_hide();
1353   panel_reset_slider (gui->panel);
1354 
1355   if(idx >= gui->playlist.num)
1356     return 0;
1357   gui_set_current_mmk_by_index(idx);
1358 
1359   pthread_mutex_lock(&gui->mmk_mutex);
1360   if(!gui_xine_open_and_play(gui->mmk.mrl, gui->mmk.sub, 0,
1361 			     gui->mmk.start, gui->mmk.av_offset, gui->mmk.spu_offset,
1362 			     !mediamark_have_alternates(&(gui->mmk))) &&
1363      (!mediamark_have_alternates(&(gui->mmk)) ||
1364       !gui_open_and_play_alternates(&(gui->mmk), gui->mmk.sub)))
1365     ret = 0;
1366   pthread_mutex_unlock(&gui->mmk_mutex);
1367   return ret;
1368 }
1369 
1370 /*
1371  * Start playback to next entry in playlist (or stop the engine, then display logo).
1372  */
gui_playlist_start_next(gGui_t * gui)1373 void gui_playlist_start_next (gGui_t *gui) {
1374 
1375   if (gui->ignore_next)
1376     return;
1377 
1378   osd_hide();
1379   panel_reset_slider (gui->panel);
1380 
1381   if(gui->playlist.control & PLAYLIST_CONTROL_STOP) {
1382     if(!(gui->playlist.control & PLAYLIST_CONTROL_STOP_PERSIST))
1383       gui->playlist.control &= ~PLAYLIST_CONTROL_STOP;
1384     gui_display_logo();
1385     return;
1386   }
1387 
1388   if (is_playback_widgets_enabled (gui->panel) && (!gui->playlist.num)) {
1389     gui_set_current_mmk(NULL);
1390     enable_playback_controls (gui->panel, 0);
1391     gui_display_logo();
1392     return;
1393   }
1394 
1395   switch(gui->playlist.loop) {
1396 
1397   case PLAYLIST_LOOP_NO_LOOP:
1398   case PLAYLIST_LOOP_LOOP:
1399     gui->playlist.cur++;
1400 
1401     if(gui->playlist.cur >= gui->playlist.num) {
1402       if(gui->playlist.loop == PLAYLIST_LOOP_NO_LOOP) {
1403 	gui->playlist.cur--;
1404 	mediamark_reset_played_state();
1405 
1406 	if(gui->actions_on_start[0] == ACTID_QUIT)
1407           gui_exit (NULL, gui);
1408 	else
1409 	  gui_display_logo();
1410 	return;
1411       }
1412       else if(gui->playlist.loop == PLAYLIST_LOOP_LOOP) {
1413 	gui->playlist.cur = 0;
1414       }
1415     }
1416     break;
1417 
1418   case PLAYLIST_LOOP_REPEAT:
1419     break;
1420 
1421   case PLAYLIST_LOOP_SHUFFLE:
1422   case PLAYLIST_LOOP_SHUF_PLUS:
1423     if(!mediamark_all_played()) {
1424 
1425     __shuffle_restart:
1426       gui->playlist.cur = mediamark_get_shuffle_next();
1427     }
1428     else {
1429       mediamark_reset_played_state();
1430 
1431       if(gui->playlist.loop == PLAYLIST_LOOP_SHUF_PLUS)
1432 	goto __shuffle_restart;
1433       else if(gui->actions_on_start[0] == ACTID_QUIT)
1434         gui_exit (NULL, gui);
1435       else
1436 	gui_display_logo();
1437       return;
1438     }
1439     break;
1440   }
1441 
1442   if (gui_playlist_play (gui, gui->playlist.cur))
1443     return;
1444 
1445   switch(gui->playlist.loop) {
1446 
1447   case PLAYLIST_LOOP_NO_LOOP:
1448     if(mediamark_all_played() && (gui->actions_on_start[0] == ACTID_QUIT)) {
1449       gui_exit (NULL, gui);
1450       return;
1451     }
1452     break;
1453 
1454   case PLAYLIST_LOOP_LOOP:
1455   case PLAYLIST_LOOP_REPEAT:
1456     break;
1457 
1458   case PLAYLIST_LOOP_SHUFFLE:
1459   case PLAYLIST_LOOP_SHUF_PLUS:
1460     if(!mediamark_all_played())
1461       goto __shuffle_restart;
1462     break;
1463   }
1464   gui_display_logo();
1465 }
1466 
gui_find_visual(Visual ** visual_return,int * depth_return)1467 static void gui_find_visual (Visual **visual_return, int *depth_return) {
1468   gGui_t *gui = gGui;
1469   XWindowAttributes  attribs;
1470   XVisualInfo	    *vinfo;
1471   XVisualInfo	     vinfo_tmpl;
1472   int		     num_visuals;
1473   int		     depth = 0;
1474   Visual	    *visual = NULL;
1475 
1476   if (gui->prefered_visual_id == None) {
1477     /*
1478      * List all available TrueColor visuals, pick the best one for xine.
1479      * We prefer visuals of depth 15/16 (fast).  Depth 24/32 may be OK,
1480      * but could be slow.
1481      */
1482     vinfo_tmpl.screen = gui->screen;
1483     vinfo_tmpl.class  = (gui->prefered_visual_class != -1
1484 			 ? gui->prefered_visual_class : TrueColor);
1485     vinfo = XGetVisualInfo(gui->display,
1486 			   VisualScreenMask | VisualClassMask,
1487 			   &vinfo_tmpl, &num_visuals);
1488     if (vinfo != NULL) {
1489       int i, pref;
1490       int best_visual_index = -1;
1491       int best_visual = -1;
1492 
1493       for (i = 0; i < num_visuals; i++) {
1494 	if (vinfo[i].depth == 15 || vinfo[i].depth == 16)
1495 	  pref = 3;
1496 	else if (vinfo[i].depth > 16)
1497 	  pref = 2;
1498 	else
1499 	  pref = 1;
1500 
1501 	if (pref > best_visual) {
1502 	  best_visual = pref;
1503 	  best_visual_index = i;
1504 	}
1505       }
1506 
1507       if (best_visual_index != -1) {
1508 	depth = vinfo[best_visual_index].depth;
1509 	visual = vinfo[best_visual_index].visual;
1510       }
1511 
1512       XFree(vinfo);
1513     }
1514   } else {
1515     /*
1516      * Use the visual specified by the user.
1517      */
1518     vinfo_tmpl.visualid = gui->prefered_visual_id;
1519     vinfo = XGetVisualInfo(gui->display,
1520 			   VisualIDMask, &vinfo_tmpl,
1521 			   &num_visuals);
1522     if (vinfo == NULL) {
1523       printf(_("gui_main: selected visual %#lx does not exist, trying default visual\n"),
1524 	     (long) gui->prefered_visual_id);
1525     } else {
1526       depth = vinfo[0].depth;
1527       visual = vinfo[0].visual;
1528       XFree(vinfo);
1529     }
1530   }
1531 
1532   if (depth == 0) {
1533     XVisualInfo vinfo;
1534 
1535     XGetWindowAttributes(gui->display, (DefaultRootWindow(gui->display)), &attribs);
1536 
1537     depth = attribs.depth;
1538 
1539     if (XMatchVisualInfo(gui->display, gui->screen, depth, TrueColor, &vinfo)) {
1540       visual = vinfo.visual;
1541     } else {
1542       printf (_("gui_main: couldn't find true color visual.\n"));
1543 
1544       depth = DefaultDepth (gui->display, gui->screen);
1545       visual = DefaultVisual (gui->display, gui->screen);
1546     }
1547   }
1548 
1549   if (depth_return != NULL)
1550     *depth_return = depth;
1551   if (visual_return != NULL)
1552     *visual_return = visual;
1553 }
1554 
gui_deinit(gGui_t * gui)1555 void gui_deinit (gGui_t *gui) {
1556 #ifdef HAVE_XINE_CONFIG_UNREGISTER_CALLBACKS
1557   xine_config_unregister_callbacks (gui->xine, NULL, NULL, gui, sizeof (*gui));
1558 #endif
1559   pthread_mutex_lock (&gui->event_mutex);
1560   gui->event_reject = 1;
1561   while (gui->event_pending > 0)
1562     pthread_cond_wait (&gui->event_safe, &gui->event_mutex);
1563   pthread_mutex_unlock (&gui->event_mutex);
1564 
1565   xitk_unregister_event_handler(&gui->widget_key);
1566 }
1567 
1568 /*
1569  * Initialize the GUI
1570  */
1571 
gui_dummy_un_lock_display(Display * display)1572 static void gui_dummy_un_lock_display (Display *display) {
1573   (void)display;
1574 }
1575 
gui_init(gGui_t * gui,int nfiles,char * filenames[],window_attributes_t * window_attribute)1576 void gui_init (gGui_t *gui, int nfiles, char *filenames[], window_attributes_t *window_attribute) {
1577   int    i;
1578   char  *server;
1579   char  *video_display_name;
1580   pthread_mutexattr_t attr;
1581 
1582   pthread_mutexattr_init(&attr);
1583   pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
1584   pthread_mutex_init (&gui->event_mutex, &attr);
1585   pthread_cond_init (&gui->event_safe, NULL);
1586 
1587   gui->event_reject = 1;
1588   gui->event_pending = 0;
1589 
1590   /*
1591    * init playlist
1592    */
1593   for (i = 0; i < nfiles; i++) {
1594     char *file = filenames[i];
1595 
1596     /* grab recursively all files from dir */
1597     if(is_a_dir(file)) {
1598 
1599       if(file[strlen(file) - 1] == '/')
1600 	file[strlen(file) - 1] = '\0';
1601 
1602       mediamark_collect_from_directory(file);
1603     }
1604     else {
1605 
1606       if(mrl_look_like_playlist(file))
1607 	(void) mediamark_concat_mediamarks(file);
1608       else {
1609 	char *sub = NULL;
1610 
1611 	if((sub = (char *)get_last_double_semicolon(file)) != NULL) {
1612 	  if(is_ipv6_last_double_semicolon(file))
1613 	    sub = NULL;
1614 	  else {
1615 	    *sub = 0;
1616 	    sub += 2;
1617 	  }
1618 	}
1619 
1620 	mediamark_append_entry((const char *)file, (const char *)file, sub, 0, -1, 0, 0);
1621       }
1622     }
1623   }
1624 
1625   gui->playlist.cur = gui->playlist.num ? 0 : -1;
1626 
1627   if((gui->playlist.loop == PLAYLIST_LOOP_SHUFFLE) ||
1628      (gui->playlist.loop == PLAYLIST_LOOP_SHUF_PLUS))
1629     gui->playlist.cur = mediamark_get_shuffle_next();
1630 
1631   gui->is_display_mrl = 0;
1632   gui->mrl_overrided  = 0;
1633   /* gui->new_pos        = -1; */
1634 
1635   /*
1636    * X / imlib stuff
1637    */
1638 
1639   if (xine_config_register_bool (gui->xine, "gui.use_XLockDisplay", 1,
1640         _("Enable extra XLib thread safety."),
1641         _("This is needed for some very old XLib/XCB versions.\n"
1642           "Otherwise, it may boost or brake performance - just try out."),
1643         CONFIG_LEVEL_ADV, NULL, NULL)) {
1644     gui->x_lock_display = XLockDisplay;
1645     gui->x_unlock_display = XUnlockDisplay;
1646   } else {
1647     gui->x_lock_display =
1648     gui->x_unlock_display = gui_dummy_un_lock_display;
1649   }
1650 
1651   if (!XInitThreads ()) {
1652     printf (_("\nXInitThreads failed - looks like you don't have a thread-safe xlib.\n"));
1653     exit(1);
1654   }
1655 
1656   if((gui->display = XOpenDisplay((getenv("DISPLAY")))) == NULL) {
1657     fprintf(stderr, _("Cannot open display\n"));
1658     exit(1);
1659   }
1660 
1661   video_display_name =
1662     (char *)xine_config_register_string (gui->xine, "gui.video_display",
1663 					 "",
1664 					 _("Name of video display"),
1665 					 _("Use this setting to configure to which "
1666                                            "display xine will show videos. When left blank, "
1667                                            "the main display will be used. Setting this "                  "option to something like ':0.1' or ':1' makes "
1668                                            "possible to display video and control on different "
1669                                            "screens (very useful for TV presentations)."),
1670 					 CONFIG_LEVEL_ADV,
1671 					 NULL,
1672 					 CONFIG_NO_DATA);
1673 
1674   gui->video_display = NULL;
1675   if ( strlen(video_display_name) ) {
1676 
1677     if ((gui->video_display = XOpenDisplay(video_display_name)) == NULL )
1678       fprintf(stderr, _("Cannot open display '%s' for video. Falling back to primary display.\n"),
1679               video_display_name);
1680   }
1681 
1682   if ( gui->video_display == NULL ) {
1683     gui->video_display = gui->display;
1684   }
1685 
1686   if (xine_config_register_bool (gui->xine, "gui.xsynchronize",
1687 				 0,
1688 				 _("Synchronized X protocol (debug)"),
1689 				 _("Do X transactions in synchronous mode. "
1690 				   "Very slow, use only for debugging!"),
1691 				 CONFIG_LEVEL_ADV,
1692 				 CONFIG_NO_CB,
1693 				 CONFIG_NO_DATA)) {
1694 
1695     gui->x_lock_display (gui->display);
1696     XSynchronize (gui->display, True);
1697     gui->x_unlock_display (gui->display);
1698     fprintf (stderr, _("Warning! Synchronized X activated - this is very slow...\n"));
1699   }
1700 
1701   gui->layer_above =
1702     xine_config_register_bool (gui->xine, "gui.layer_above", 0,
1703 			       _("Windows stacking"),
1704 			       _("Use WM layer property to place windows on top\n"
1705 				 "except for the video window in non-fullscreen mode."),
1706 			       CONFIG_LEVEL_ADV,
1707 			       layer_above_cb,
1708 			       gGui);
1709 
1710   gui->always_layer_above =
1711     xine_config_register_bool (gui->xine, "gui.always_layer_above", 0,
1712 			       _("Windows stacking (more)"),
1713 			       _("Use WM layer property to place windows on top\n"
1714 				 "for all windows (surpasses the 'layer_above' setting)."),
1715 			       CONFIG_LEVEL_ADV,
1716 			       always_layer_above_cb,
1717 			       gGui);
1718 
1719   gui->snapshot_location =
1720     (char *)xine_config_register_string (gui->xine, "gui.snapshotdir",
1721 					 (char *) (xine_get_homedir()),
1722 					 _("Snapshot location"),
1723 					 _("Where snapshots will be saved."),
1724 					 CONFIG_LEVEL_BEG,
1725 					 snapshot_loc_cb,
1726 					 gGui);
1727 
1728   gui->ssaver_timeout =
1729     xine_config_register_num (gui->xine, "gui.screensaver_timeout", 10,
1730 			      _("Screensaver reset interval (s)"),
1731 			      _("Time, in seconds, between two faked events to keep a screensaver quiet, 0 to disable."),
1732 			      CONFIG_LEVEL_ADV,
1733 			      ssaver_timeout_cb,
1734 			      gGui);
1735 
1736   gui->skip_by_chapter =
1737     xine_config_register_bool (gui->xine, "gui.skip_by_chapter", 1,
1738 			       _("Chapter hopping"),
1739 			       _("Play next|previous chapter instead of mrl (dvdnav)"),
1740 			       CONFIG_LEVEL_ADV,
1741 			       skip_by_chapter_cb,
1742 			       gGui);
1743 
1744   gui->auto_vo_visibility =
1745     xine_config_register_bool (gui->xine, "gui.auto_video_output_visibility", 0,
1746 			       _("Visibility behavior of output window"),
1747 			       _("Hide video output window if there is no video in the stream"),
1748 			       CONFIG_LEVEL_ADV,
1749 			       auto_vo_visibility_cb,
1750 			       gGui);
1751 
1752   gui->auto_panel_visibility =
1753     xine_config_register_bool (gui->xine, "gui.auto_panel_visibility", 0,
1754 			       _("Visiblility behavior of panel"),
1755 			       _("Automatically show/hide panel window, according to auto_video_output_visibility"),
1756 			       CONFIG_LEVEL_ADV,
1757 			       auto_panel_visibility_cb,
1758 			       gGui);
1759 
1760   gui->eventer_sticky =
1761     xine_config_register_bool (gui->xine, "gui.eventer_sticky",
1762 			      1,
1763 			      _("Event sender behavior"),
1764 			      _("Event sender window stick to main panel"),
1765 			      CONFIG_LEVEL_ADV,
1766 			      event_sender_sticky_cb,
1767 			      gGui);
1768 
1769   gui->visual_anim.enabled =
1770     xine_config_register_enum (gui->xine, "gui.visual_anim",
1771 			      1, /* Post plugin */
1772 			      (char**)visual_anim_style,
1773 			      _("Visual animation style"),
1774 			      _("Display some video animations when "
1775 				"current stream is audio only (eg: mp3)."),
1776 			      CONFIG_LEVEL_BEG,
1777 			      visual_anim_cb,
1778 			      gGui);
1779 
1780   gui->stream_info_auto_update =
1781     xine_config_register_bool (gui->xine, "gui.sinfo_auto_update",
1782 			      0,
1783 			      _("Stream information"),
1784 			      _("Update stream information (in stream info window) "
1785 				"each half seconds."),
1786 			      CONFIG_LEVEL_ADV,
1787 			      stream_info_auto_update_cb,
1788 			      gGui);
1789 
1790 
1791   server =
1792     (char *)xine_config_register_string (gui->xine, "gui.skin_server_url",
1793 					 SKIN_SERVER_URL,
1794 					 _("Skin Server Url"),
1795 					 _("From where we can get skins."),
1796 					 CONFIG_LEVEL_ADV,
1797 					 skin_server_url_cb,
1798 					 gGui);
1799 
1800   config_update_string("gui.skin_server_url",
1801 		       gui->skin_server_url ? gui->skin_server_url : server);
1802 
1803   gui->osd.enabled =
1804     xine_config_register_bool (gui->xine, "gui.osd_enabled",
1805 			      1,
1806 			      _("Enable OSD support"),
1807 			      _("Enabling OSD permit to display some status/informations "
1808 				"in output window."),
1809 			      CONFIG_LEVEL_BEG,
1810 			      osd_enabled_cb,
1811 			      gGui);
1812 
1813   gui->osd.use_unscaled =
1814     xine_config_register_bool (gui->xine, "gui.osd_use_unscaled",
1815 			      1,
1816 			      _("Use unscaled OSD"),
1817 			      _("Use unscaled (full screen resolution) OSD if possible"),
1818 			      CONFIG_LEVEL_ADV,
1819 			      osd_use_unscaled_cb,
1820 			      gGui);
1821 
1822   gui->osd.timeout =
1823     xine_config_register_num (gui->xine, "gui.osd_timeout",
1824 			      3,
1825 			      _("Dismiss OSD time (s)"),
1826 			      _("Persistence time of OSD visual, in seconds."),
1827 			      CONFIG_LEVEL_BEG,
1828 			      osd_timeout_cb,
1829 			      gGui);
1830 
1831   gui->smart_mode =
1832     xine_config_register_bool (gui->xine, "gui.smart_mode",
1833 			      1,
1834 			      _("Change xine's behavior for unexperienced user"),
1835 			      _("In this mode, xine take some decisions to simplify user's life."),
1836 			      CONFIG_LEVEL_BEG,
1837 			      smart_mode_cb,
1838 			      gGui);
1839 
1840   gui->play_anyway =
1841     xine_config_register_bool (gui->xine, "gui.play_anyway",
1842 			      0,
1843 			      _("Ask user for playback with unsupported codec"),
1844 			      _("If xine don't support audio or video codec of current stream "
1845 				"the user will be asked if the stream should be played or not"),
1846 			      CONFIG_LEVEL_BEG,
1847 			      play_anyway_cb,
1848 			      gGui);
1849 
1850   gui->experience_level =
1851     (xine_config_register_enum (gui->xine, "gui.experience_level",
1852 			       0, (char**)exp_levels,
1853 			       _("Configuration experience level"),
1854 			       _("Level of user's experience, this will show more or less "
1855 				 "configuration options."),
1856 			       CONFIG_LEVEL_BEG,
1857 			       exp_level_cb,
1858 			       gGui)) * 10;
1859 
1860   gui->mixer.amp_level = xine_config_register_range (gui->xine, "gui.amp_level",
1861 						     100, 0, 200,
1862 						     _("Amplification level"),
1863 						     NULL,
1864 						     CONFIG_LEVEL_DEB,
1865 						     dummy_config_cb,
1866 						     gGui);
1867 
1868   gui->splash =
1869     gui->splash ? (xine_config_register_bool (gui->xine, "gui.splash",
1870 					      1,
1871 					      _("Display splash screen"),
1872 					      _("If enabled, xine will display its splash screen"),
1873 					      CONFIG_LEVEL_BEG,
1874 					      dummy_config_cb,
1875 					      gGui)) : 0;
1876 
1877   gui->mixer.method =
1878     xine_config_register_enum (gui->xine, "gui.audio_mixer_method",
1879 			      SOUND_CARD_MIXER, (char**)mixer_control_method,
1880 			      _("Audio mixer control method"),
1881 			      _("Which method used to control audio volume."),
1882 			      CONFIG_LEVEL_ADV,
1883 			      audio_mixer_method_cb,
1884 			      gGui);
1885 
1886   gui->shortcut_style =
1887     xine_config_register_enum (gui->xine, "gui.shortcut_style",
1888 			      0, (char**)shortcut_style,
1889 			      _("Menu shortcut style"),
1890 			      _("Shortcut representation in menu, 'Ctrl,Alt' or 'C,M'."),
1891 			      CONFIG_LEVEL_ADV,
1892 			      shortcut_style_cb,
1893 			      gGui);
1894 
1895   gui->numeric.set = 0;
1896   gui->numeric.arg = 0;
1897   gui->alphanum.set = 0;
1898   gui->alphanum.arg = "";
1899 
1900   gui->x_lock_display (gui->display);
1901 
1902   gui->screen = DefaultScreen(gui->display);
1903 
1904   gui->x_lock_display (gui->video_display);
1905   gui->video_screen = DefaultScreen(gui->video_display);
1906   gui->x_unlock_display (gui->video_display);
1907 
1908 
1909 
1910   /* Some infos */
1911   if(__xineui_global_verbosity) {
1912     dump_host_info();
1913     dump_cpu_infos();
1914     dump_xfree_info(gui->display, gui->screen, (__xineui_global_verbosity >= XINE_VERBOSITY_DEBUG) ? 1 : 0);
1915   }
1916 
1917   gui_find_visual(&gui->visual, &gui->depth);
1918 
1919   gui_init_imlib (gui, gui->visual);
1920 
1921   gui->x_unlock_display (gui->display);
1922 
1923   /*
1924    * create and map panel and video window
1925    */
1926   xine_pid = getppid();
1927 
1928   xitk_init (gui->display, gui->black, gui->x_lock_display, gui->x_unlock_display, (__xineui_global_verbosity) ? 1 : 0);
1929 
1930   preinit_skins_support();
1931 
1932   if(gui->splash)
1933     splash_create();
1934 
1935   init_skins_support();
1936 
1937   gui->on_quit = 0;
1938   gui->running = 1;
1939 
1940   video_window_init (gui, window_attribute,
1941     ((actions_on_start(gui->actions_on_start, ACTID_TOGGLE_WINOUT_VISIBLITY)) ? 1 : 0));
1942 
1943   /* kbinding might open an error dialog (double keymapping), which produces a segfault,
1944    * when done before the video_window_init(). */
1945   gui->kbindings = kbindings_init_kbinding();
1946 
1947   gui_set_current_mmk(mediamark_get_current_mmk());
1948 
1949   panel_init (gui);
1950   gui->event_reject = 0;
1951 }
1952 
gui_init_imlib(gGui_t * gui,Visual * vis)1953 void gui_init_imlib (gGui_t *gui, Visual *vis) {
1954   XColor                dummy;
1955   ImlibInitParams	imlib_init;
1956 
1957   /*
1958    * This routine isn't re-entrant. I cannot find a Imlib_cleanup either.
1959    * However, we have to reinitialize Imlib if we have to change the visual.
1960    * This will be a (small) memory leak.
1961    */
1962   imlib_init.flags = PARAMS_VISUALID;
1963   imlib_init.visualid = vis->visualid;
1964   if (gui->install_colormap && (vis->class & 1)) {
1965       /*
1966        * We're using a visual with changable colors / colormaps
1967        * (According to the comment in X11/X.h, an odd display class
1968        * has changable colors), and the user requested to install a
1969        * private colormap for xine.  Allocate a fresh colormap for
1970        * Imlib and Xine.
1971        */
1972       Colormap cm;
1973       cm = XCreateColormap(gui->display,
1974 			   RootWindow(gui->display, gui->screen),
1975 			   vis, AllocNone);
1976 
1977       imlib_init.cmap = cm;
1978       imlib_init.flags |= PARAMS_COLORMAP;
1979   }
1980   gui->imlib_data = Imlib_init_with_params (gui->display, &imlib_init);
1981   if (gui->imlib_data == NULL) {
1982     fprintf(stderr, _("Unable to initialize Imlib\n"));
1983     exit(1);
1984   }
1985 
1986   gui->imlib_data->x.x_lock_display = gui->x_lock_display;
1987   gui->imlib_data->x.x_unlock_display = gui->x_unlock_display;
1988 
1989   gui->colormap = Imlib_get_colormap (gui->imlib_data);
1990 
1991   XAllocNamedColor(gui->display, gui->colormap,
1992 		   "black", &gui->black, &dummy);
1993 
1994   /*
1995    * create an icon pixmap
1996    */
1997 
1998   gui->icon = XCreateBitmapFromData (gui->display,
1999 				      gui->imlib_data->x.root,
2000 				      (const char *)icon_datas, 40, 40);
2001 }
2002 
2003 /*
2004  *
2005  */
2006 typedef struct {
2007   int      start;
2008   char   **session_opts;
2009 } _startup_t;
2010 
on_start(void * data)2011 static void on_start(void *data) {
2012   gGui_t *gui = gGui;
2013   _startup_t *startup = (_startup_t *) data;
2014 
2015   splash_destroy();
2016 
2017   if(!startup->start) {
2018 
2019     gui_display_logo();
2020 
2021     do {
2022       xine_usec_sleep(5000);
2023     } while(gui->logo_mode != 1);
2024 
2025   }
2026 
2027   if(startup->session_opts) {
2028     int i = 0;
2029     int dummy_session;
2030 
2031     while(startup->session_opts[i])
2032       (void) session_handle_subopt(startup->session_opts[i++], NULL, &dummy_session);
2033 
2034   }
2035 
2036   if(startup->start)
2037     gui_execute_action_id (gui, ACTID_PLAY);
2038 
2039 }
2040 
gui_run(char ** session_opts)2041 void gui_run(char **session_opts) {
2042   gGui_t *gui = gGui;
2043   _startup_t  startup;
2044   int         i, auto_start = 0;
2045 
2046   video_window_change_skins (gui->vwin, 0);
2047   panel_add_autoplay_buttons (gui->panel);
2048   panel_show_tips (gui->panel);
2049   panel_add_mixer_control (gui->panel);
2050   panel_update_channel_display (gui->panel);
2051   panel_update_mrl_display (gui->panel);
2052   panel_update_runtime_display (gui->panel);
2053 
2054   /* Register config entries related to video control settings */
2055   control_init (gui);
2056 
2057   /* autoscan playlist  */
2058   if(gui->autoscan_plugin != NULL) {
2059     const char *const *autoscan_plugins = xine_get_autoplay_input_plugin_ids (gui->xine);
2060     int         i;
2061 
2062     if(autoscan_plugins) {
2063 
2064       for(i = 0; autoscan_plugins[i] != NULL; ++i) {
2065 
2066 	if(!strcasecmp(autoscan_plugins[i], gui->autoscan_plugin)) {
2067 	  int    num_mrls, j;
2068 	  const char * const *autoplay_mrls = xine_get_autoplay_mrls (gui->xine,
2069 							 gui->autoscan_plugin,
2070 							 &num_mrls);
2071 
2072 	  if(autoplay_mrls) {
2073 	    for (j = 0; j < num_mrls; j++)
2074 	      mediamark_append_entry(autoplay_mrls[j],
2075 				     autoplay_mrls[j], NULL, 0, -1, 0, 0);
2076 
2077 	    gui->playlist.cur = 0;
2078 	    gui_set_current_mmk(mediamark_get_current_mmk());
2079 	  }
2080 	}
2081       }
2082     }
2083   }
2084 
2085   enable_playback_controls (gui->panel, (gui->playlist.num > 0));
2086 
2087   /* We can't handle signals here, xitk handle this, so
2088    * give a function callback for this.
2089    */
2090   xitk_register_signal_handler(gui_signal_handler, NULL);
2091 
2092   /*
2093    * event loop
2094    */
2095 
2096 #ifdef HAVE_LIRC
2097   if(__xineui_global_lirc_enable)
2098     lirc_start();
2099 #endif
2100 
2101   if(gui->stdctl_enable)
2102     stdctl_start();
2103 
2104   /*  global event handler */
2105   gui->widget_key = xitk_register_event_handler("NO WINDOW", None,
2106 						 gui_handle_event,
2107 						 gui,
2108 						 gui_dndcallback,
2109 						 NULL, NULL);
2110 
2111 #ifdef HAVE_READLINE
2112   start_remote_server();
2113 #endif
2114   init_session();
2115 
2116   if(gui->tvout) {
2117     int w, h;
2118 
2119     video_window_get_visible_size (gui->vwin, &w, &h);
2120     tvout_set_fullscreen_mode (gui->tvout,
2121       ((video_window_get_fullscreen_mode (gui->vwin) & WINDOWED_MODE) ? 0 : 1), w, h);
2122   }
2123 
2124   if(gui->actions_on_start[0] != ACTID_NOKEY) {
2125 
2126     /* Popup setup window if there is no config file */
2127     if(actions_on_start(gui->actions_on_start, ACTID_SETUP)) {
2128       xine_config_save (gui->xine, __xineui_global_config_file);
2129       gui_execute_action_id (gui, ACTID_SETUP);
2130     }
2131 
2132     /*  The user wants to hide video window  */
2133     if(actions_on_start(gui->actions_on_start, ACTID_TOGGLE_WINOUT_VISIBLITY)) {
2134       if (!panel_is_visible (gui->panel))
2135         gui_execute_action_id (gui, ACTID_TOGGLE_VISIBLITY);
2136 
2137       /* DXR3 case */
2138       if (video_window_is_visible (gui->vwin))
2139         video_window_set_visibility (gui->vwin, 0);
2140       else
2141 	xine_port_send_gui_data(gui->vo_port,
2142 			      XINE_GUI_SEND_VIDEOWIN_VISIBLE,
2143 			      (int *)0);
2144 
2145     }
2146 
2147     /* The user wants to see in fullscreen mode  */
2148     for (i = actions_on_start(gui->actions_on_start, ACTID_TOGGLE_FULLSCREEN); i > 0; i--)
2149       gui_execute_action_id (gui, ACTID_TOGGLE_FULLSCREEN);
2150 
2151 #ifdef HAVE_XINERAMA
2152     /* The user wants to see in xinerama fullscreen mode  */
2153     for (i = actions_on_start(gui->actions_on_start, ACTID_TOGGLE_XINERAMA_FULLSCREEN); i > 0; i--)
2154       gui_execute_action_id (gui, ACTID_TOGGLE_XINERAMA_FULLSCREEN);
2155 #endif
2156 
2157     /* User load a playlist on startup */
2158     if(actions_on_start(gui->actions_on_start, ACTID_PLAYLIST)) {
2159       gui_set_current_mmk(mediamark_get_current_mmk());
2160 
2161       if(gui->playlist.num) {
2162 	gui->playlist.cur = 0;
2163         if (!is_playback_widgets_enabled (gui->panel))
2164           enable_playback_controls (gui->panel, 1);
2165       }
2166     }
2167 
2168     if(actions_on_start(gui->actions_on_start, ACTID_TOGGLE_INTERLEAVE))
2169       gui_toggle_interlaced();
2170 
2171     /*  The user request "play on start" */
2172     if(actions_on_start(gui->actions_on_start, ACTID_PLAY)) {
2173       if((mediamark_get_current_mrl()) != NULL) {
2174 	auto_start = 1;
2175       }
2176     }
2177 
2178     /* Flush actions on start */
2179     if(actions_on_start(gui->actions_on_start, ACTID_QUIT)) {
2180       gui->actions_on_start[0] = ACTID_QUIT;
2181       gui->actions_on_start[1] = ACTID_NOKEY;
2182     }
2183   }
2184 
2185   startup.start        = auto_start;
2186   startup.session_opts = session_opts;
2187 
2188   oxine_init();
2189 
2190   xitk_run(on_start, (void *)&startup);
2191 
2192   /* save playlist */
2193   if(gui->playlist.mmk && gui->playlist.num) {
2194     char buffer[XITK_PATH_MAX + XITK_NAME_MAX + 1];
2195 
2196     snprintf(buffer, sizeof(buffer), "%s/.xine/xine-ui_old_playlist.tox", xine_get_homedir());
2197     mediamark_save_mediamarks(buffer);
2198   }
2199 
2200   gui->running = 0;
2201   deinit_session();
2202 
2203   kbindings_save_kbinding(gui->kbindings);
2204   kbindings_free_kbinding(&gui->kbindings);
2205 }
2206 
2207