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