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 * implementation of all the various actions for the gui (play, stop, open, pause...)
21 *
22 */
23
24 #ifdef HAVE_CONFIG_H
25 #include "config.h"
26 #endif
27
28 #include <stdio.h>
29 #include <sys/types.h>
30 #include <sys/stat.h>
31 #include <unistd.h>
32
33 #ifdef HAVE_ALLOCA_H
34 #include <alloca.h>
35 #endif
36 #include <X11/Xlib.h>
37 #include <xine/xineutils.h>
38 #include <pthread.h>
39
40 #include "common.h"
41 #include "oxine/oxine.h"
42
gui_messages_off(gGui_t * gui)43 static void gui_messages_off (gGui_t *gui) {
44 pthread_mutex_lock (&gui->no_messages.mutex);
45 ++gui->no_messages.level;
46 gui->no_messages.until.tv_sec = sizeof (gui->no_messages.until.tv_sec) > 4 ? ((~(uint64_t)0) >> 1) : 0x7fffffff;
47 pthread_mutex_unlock (&gui->no_messages.mutex);
48 }
49
gui_messages_on(gGui_t * gui)50 static void gui_messages_on (gGui_t *gui) {
51 pthread_mutex_lock (&gui->no_messages.mutex);
52 if (--gui->no_messages.level == 0)
53 gettimeofday (&gui->no_messages.until, NULL);
54 pthread_mutex_unlock (&gui->no_messages.mutex);
55 }
56
reparent_all_windows(void)57 void reparent_all_windows(void) {
58 gGui_t *gui = gGui;
59 int i;
60 static const struct {
61 int (*visible)(void);
62 void (*reparent)(void);
63 } _reparent[] = {
64 { playlist_is_visible, playlist_reparent },
65 { viewlog_is_visible, viewlog_reparent },
66 { kbedit_is_visible, kbedit_reparent },
67 { event_sender_is_visible, event_sender_reparent },
68 { stream_infos_is_visible, stream_infos_reparent },
69 { tvset_is_visible, tvset_reparent },
70 { vpplugin_is_visible, vpplugin_reparent },
71 { applugin_is_visible, applugin_reparent },
72 { help_is_visible, help_reparent },
73 { NULL, NULL}
74 };
75
76 if (panel_is_visible (gui->panel))
77 panel_reparent (gui->panel);
78 if (setup_is_visible (gui->setup))
79 setup_reparent (gui->setup);
80 if (mrl_browser_is_visible (gui->mrlb))
81 mrl_browser_reparent (gui->mrlb);
82 control_reparent (gui->vctrl);
83
84 for(i = 0; _reparent[i].visible; i++) {
85 if(_reparent[i].visible())
86 _reparent[i].reparent();
87 }
88
89 }
90
wait_for_window_visible(Display * display,Window window)91 void wait_for_window_visible(Display *display, Window window) {
92 int t = 0;
93
94 while((!xitk_is_window_visible(display, window)) && (++t < 3))
95 xine_usec_sleep(5000);
96 }
97
raise_window(Window window,int visible,int running)98 void raise_window(Window window, int visible, int running) {
99 if(window) {
100 if(visible && running) {
101 reparent_window(window);
102 layer_above_video(window);
103 }
104 }
105 }
106
toggle_window(Window window,xitk_widget_list_t * widget_list,int * visible,int running)107 void toggle_window(Window window, xitk_widget_list_t *widget_list, int *visible, int running) {
108 gGui_t *gui = gGui;
109 if(window && (*visible) && running) {
110
111 gui->x_lock_display (gui->display);
112 if(gui->use_root_window) {
113 if(xitk_is_window_visible(gui->display, window))
114 XIconifyWindow(gui->display, window, gui->screen);
115 else
116 XMapWindow(gui->display, window);
117 }
118 else if(!xitk_is_window_visible(gui->display, window)) {
119 /* Obviously user has iconified the window, let it be */
120 }
121 else {
122 *visible = 0;
123 gui->x_unlock_display (gui->display);
124 xitk_hide_widgets(widget_list);
125 gui->x_lock_display (gui->display);
126 XUnmapWindow(gui->display, window);
127 }
128 gui->x_unlock_display (gui->display);
129
130 }
131 else {
132 if(running) {
133 *visible = 1;
134 xitk_show_widgets(widget_list);
135
136 gui->x_lock_display (gui->display);
137 XRaiseWindow(gui->display, window);
138 XMapWindow(gui->display, window);
139 gui->x_unlock_display (gui->display);
140 video_window_set_transient_for (gui->vwin, window);
141
142 wait_for_window_visible(gui->display, window);
143 layer_above_video(window);
144 }
145 }
146 }
147
gui_xine_get_pos_length(xine_stream_t * stream,int * ppos,int * ptime,int * plength)148 int gui_xine_get_pos_length (xine_stream_t *stream, int *ppos, int *ptime, int *plength) {
149 gGui_t *gui = gGui;
150
151 do {
152
153 if (!stream)
154 break;
155
156 if (stream == gui->stream) {
157 pthread_mutex_lock (&gui->seek_mutex);
158 if (gui->seek_running) {
159 /* xine_play (), xine_get_* () etc. all grab stream frontend lock.
160 * Dont wait for seek thread, just use its values. */
161 if (ppos)
162 *ppos = gui->stream_length.pos;
163 if (ptime)
164 *ptime = gui->stream_length.time;
165 if (plength)
166 *plength = gui->stream_length.length;
167 pthread_mutex_unlock (&gui->seek_mutex);
168 return 1;
169 }
170 pthread_mutex_unlock (&gui->seek_mutex);
171 }
172
173 if (xine_get_status (stream) == XINE_STATUS_PLAY) {
174 int lpos = 0, ltime = 0, llength = 0;
175 int ret, t = 0;
176 while (((ret = xine_get_pos_length (stream, &lpos, <ime, &llength)) == 0) && (++t < 10) && (!gui->on_quit)) {
177 printf ("gui_xine_get_pos_length: wait 100 ms (%d).\n", t);
178 xine_usec_sleep (100000); /* wait before trying again */
179 }
180 if (ret == 0)
181 break;
182 if (stream == gui->stream) {
183 gui->stream_length.pos = lpos;
184 gui->stream_length.time = ltime;
185 gui->stream_length.length = llength;
186 }
187 if (ppos)
188 *ppos = lpos;
189 if (ptime)
190 *ptime = ltime;
191 if (plength)
192 *plength = llength;
193 return ret;
194 }
195 } while (0);
196
197 if (ppos)
198 *ppos = 0;
199 if (ptime)
200 *ptime = 0;
201 if (plength)
202 *plength = 0;
203 return 0;
204 }
205
206 /*
207 *
208 */
try_to_set_input_focus(Window window)209 void try_to_set_input_focus(Window window) {
210 gGui_t *gui = gGui;
211
212 wait_for_window_visible(gui->display, window);
213
214 if(xitk_is_window_visible(gui->display, window)) {
215 int retry = 0;
216 Window focused_win;
217
218 do {
219 int revert;
220
221 gui->x_lock_display (gui->display);
222 XSetInputFocus(gui->display, window, RevertToParent, CurrentTime);
223 XSync(gui->display, False);
224 gui->x_unlock_display (gui->display);
225
226 /* Retry until the WM was mercyful to give us the focus (but not indefinitely) */
227 xine_usec_sleep(5000);
228 gui->x_lock_display (gui->display);
229 XGetInputFocus(gui->display, &focused_win, &revert);
230 gui->x_unlock_display (gui->display);
231
232 } while((focused_win != window) && (retry++ < 30));
233 }
234 }
235
236 /*
237 *
238 */
gui_display_logo(void)239 void gui_display_logo(void) {
240 gGui_t *gui = gGui;
241
242 pthread_mutex_lock(&gui->logo_mutex);
243
244 gui->logo_mode = 2;
245
246 if(xine_get_status(gui->stream) == XINE_STATUS_PLAY) {
247 gui->ignore_next = 1;
248 xine_stop(gui->stream);
249 gui->ignore_next = 0;
250 }
251
252 if(gui->visual_anim.running)
253 visual_anim_stop();
254
255 xine_set_param(gui->stream, XINE_PARAM_AUDIO_CHANNEL_LOGICAL, -1);
256 xine_set_param(gui->stream, XINE_PARAM_SPU_CHANNEL, -1);
257 panel_update_channel_display (gui->panel);
258
259 if(gui->display_logo)
260 (void) gui_xine_open_and_play((char *)gui->logo_mrl, NULL, 0, 0, 0, 0, 1);
261
262 gui->logo_mode = 1;
263
264 panel_reset_slider (gui->panel);
265 if(stream_infos_is_visible())
266 stream_infos_update_infos();
267
268 pthread_mutex_unlock(&gui->logo_mutex);
269 }
270
_gui_xine_play(gGui_t * gui,xine_stream_t * stream,int start_pos,int start_ms,int update_mmk)271 static int _gui_xine_play (gGui_t *gui, xine_stream_t *stream, int start_pos, int start_ms, int update_mmk) {
272 int ret;
273 int has_video;
274 int already_playing = (gui->logo_mode == 0);
275
276 if(gui->visual_anim.post_changed && (xine_get_status(stream) == XINE_STATUS_STOP)) {
277 post_rewire_visual_anim();
278 gui->visual_anim.post_changed = 0;
279 }
280
281 has_video = xine_get_stream_info(stream, XINE_STREAM_INFO_HAS_VIDEO);
282 if (has_video)
283 has_video = !xine_get_stream_info(stream, XINE_STREAM_INFO_IGNORE_VIDEO);
284
285 if((has_video && gui->visual_anim.enabled == 1) && gui->visual_anim.running) {
286
287 if(post_rewire_audio_port_to_stream(stream))
288 gui->visual_anim.running = 0;
289
290 } else if (!has_video && (gui->visual_anim.enabled == 1) &&
291 (gui->visual_anim.running == 0) && gui->visual_anim.post_output_element.post) {
292
293 if(post_rewire_audio_post_to_stream(stream))
294 gui->visual_anim.running = 1;
295
296 }
297
298 if ((ret = xine_play (stream, start_pos, start_ms)) == 0)
299 gui_handle_xine_error(stream, NULL);
300 else {
301 char *ident;
302
303 pthread_mutex_lock(&gui->logo_mutex);
304 if(gui->logo_mode != 2)
305 gui->logo_mode = 0;
306 pthread_mutex_unlock(&gui->logo_mutex);
307
308 if(gui->logo_mode == 0) {
309
310 if(stream_infos_is_visible())
311 stream_infos_update_infos();
312
313 if(update_mmk && ((ident = stream_infos_get_ident_from_stream(stream)) != NULL)) {
314 pthread_mutex_lock (&gui->mmk_mutex);
315 free(gui->mmk.ident);
316 free(gui->playlist.mmk[gui->playlist.cur]->ident);
317
318 gui->mmk.ident = strdup(ident);
319 gui->playlist.mmk[gui->playlist.cur]->ident = strdup(ident);
320 pthread_mutex_unlock (&gui->mmk_mutex);
321
322 video_window_set_mrl (gui->vwin, ident);
323 playlist_mrlident_toggle();
324 panel_update_mrl_display (gui->panel);
325 free(ident);
326 }
327
328 if(has_video) {
329
330 if((gui->visual_anim.enabled == 2) && gui->visual_anim.running)
331 visual_anim_stop();
332
333 if(gui->auto_vo_visibility) {
334
335 if (!video_window_is_visible (gui->vwin))
336 video_window_set_visibility (gui->vwin, 1);
337
338 }
339
340 if (gui->auto_panel_visibility && video_window_is_visible (gui->vwin) &&
341 panel_is_visible (gui->panel))
342 panel_toggle_visibility (NULL, gui->panel);
343
344 }
345 else {
346
347 if(gui->auto_vo_visibility) {
348
349 if (!panel_is_visible (gui->panel))
350 panel_toggle_visibility (NULL, gui->panel);
351
352 if (video_window_is_visible (gui->vwin))
353 video_window_set_visibility (gui->vwin, 0);
354
355 }
356
357 if (gui->auto_panel_visibility && video_window_is_visible (gui->vwin) &&
358 !panel_is_visible (gui->panel))
359 panel_toggle_visibility (NULL, gui->panel);
360
361 if (video_window_is_visible (gui->vwin)) {
362 if(!gui->visual_anim.running)
363 visual_anim_play();
364 }
365 else
366 gui->visual_anim.running = 2;
367 }
368
369 xine_usec_sleep(100);
370 if(!already_playing)
371 osd_update_status();
372 }
373 }
374
375 return ret;
376 }
377
378 typedef struct {
379 xine_stream_t *stream;
380 int start_pos;
381 int start_time_in_secs;
382 int update_mmk;
383 int running;
384 } play_data_t;
385 static play_data_t play_data;
386
start_anyway_yesno(xitk_widget_t * w,void * data,int button)387 static void start_anyway_yesno(xitk_widget_t *w, void *data, int button) {
388 gGui_t *gui = data;
389 play_data.running = 0;
390
391 if(button == XITK_WINDOW_ANSWER_YES)
392 _gui_xine_play (gui, play_data.stream, play_data.start_pos, play_data.start_time_in_secs * 1000, play_data.update_mmk);
393 else
394 gui_playlist_start_next (gui);
395
396 }
397
set_mmk(mediamark_t * mmk)398 static void set_mmk(mediamark_t *mmk) {
399 gGui_t *gui = gGui;
400
401 pthread_mutex_lock (&gui->mmk_mutex);
402 free(gui->mmk.mrl);
403 free(gui->mmk.ident);
404 free(gui->mmk.sub);
405 if(mediamark_have_alternates(&(gui->mmk)))
406 mediamark_free_alternates(&(gui->mmk));
407
408 if(mmk) {
409 gui->mmk.mrl = strdup(mmk->mrl);
410 gui->mmk.ident = strdup(((mmk->ident) ? mmk->ident : mmk->mrl));
411 gui->mmk.sub = mmk->sub ? strdup(mmk->sub): NULL;
412 gui->mmk.start = mmk->start;
413 gui->mmk.end = mmk->end;
414 gui->mmk.av_offset = mmk->av_offset;
415 gui->mmk.spu_offset = mmk->spu_offset;
416 gui->mmk.got_alternate = mmk->got_alternate;
417 mediamark_duplicate_alternates(mmk, &(gui->mmk));
418 } else {
419 /* TRANSLATORS: only ASCII characters (skin) */
420 gui->mmk.mrl = strdup(pgettext("skin", "There is no MRL."));
421 gui->mmk.ident = strdup ("xine-ui version " VERSION);
422 gui->mmk.sub = NULL;
423 gui->mmk.start = 0;
424 gui->mmk.end = -1;
425 gui->mmk.av_offset = 0;
426 gui->mmk.spu_offset = 0;
427 gui->mmk.got_alternate = 0;
428 gui->mmk.alternates = NULL;
429 gui->mmk.cur_alt = NULL;
430 }
431 pthread_mutex_unlock (&gui->mmk_mutex);
432 }
433
mmk_set_update(void)434 static void mmk_set_update(void) {
435 gGui_t *gui = gGui;
436
437 video_window_set_mrl (gui->vwin, gui->mmk.ident);
438 event_sender_update_menu_buttons();
439 panel_update_mrl_display (gui->panel);
440 playlist_update_focused_entry();
441
442 gui->playlist.ref_append = gui->playlist.cur;
443 }
444
gui_xine_play(gGui_t * gui,xine_stream_t * stream,int start_pos,int start_time_in_secs,int update_mmk)445 int gui_xine_play (gGui_t *gui, xine_stream_t *stream, int start_pos, int start_time_in_secs, int update_mmk) {
446 int has_video, has_audio, v_unhandled = 0, a_unhandled = 0;
447 uint32_t video_handled, audio_handled;
448
449 if(play_data.running)
450 return 0;
451
452 has_video = xine_get_stream_info(stream, XINE_STREAM_INFO_HAS_VIDEO);
453 video_handled = xine_get_stream_info(stream, XINE_STREAM_INFO_VIDEO_HANDLED);
454 has_audio = xine_get_stream_info(stream, XINE_STREAM_INFO_HAS_AUDIO);
455 audio_handled = xine_get_stream_info(stream, XINE_STREAM_INFO_AUDIO_HANDLED);
456
457 if (has_video)
458 has_video = !xine_get_stream_info(stream, XINE_STREAM_INFO_IGNORE_VIDEO);
459 if (has_audio)
460 has_audio = !xine_get_stream_info(stream, XINE_STREAM_INFO_IGNORE_AUDIO);
461
462 v_unhandled = (has_video && (!video_handled));
463 a_unhandled = (has_audio && (!audio_handled));
464 if(v_unhandled || a_unhandled) {
465 char *buffer = NULL;
466 char *v_info = NULL;
467 char *a_info = NULL;
468
469 if(v_unhandled && a_unhandled) {
470 buffer = xitk_asprintf(_("The stream '%s' isn't supported by xine:\n\n"),
471 (stream == gui->stream) ? gui->mmk.mrl : gui->visual_anim.mrls[gui->visual_anim.current]);
472 }
473 else {
474 buffer = xitk_asprintf(_("The stream '%s' uses an unsupported codec:\n\n"),
475 (stream == gui->stream) ? gui->mmk.mrl : gui->visual_anim.mrls[gui->visual_anim.current]);
476 }
477
478 if(v_unhandled) {
479 const char *minfo;
480 uint32_t vfcc;
481 char tmp[8];
482
483 minfo = xine_get_meta_info(stream, XINE_META_INFO_VIDEOCODEC);
484 vfcc = xine_get_stream_info(stream, XINE_STREAM_INFO_VIDEO_FOURCC);
485 v_info = xitk_asprintf(_("Video Codec: %s (%s)\n"),
486 (minfo && strlen(minfo)) ? (char *) minfo : _("Unavailable"),
487 (get_fourcc_string(tmp, sizeof(tmp), vfcc)));
488 }
489
490 if(a_unhandled) {
491 const char *minfo;
492 uint32_t afcc;
493 char tmp[8];
494
495 minfo = xine_get_meta_info(stream, XINE_META_INFO_AUDIOCODEC);
496 afcc = xine_get_stream_info(stream, XINE_STREAM_INFO_AUDIO_FOURCC);
497 a_info = xitk_asprintf(_("Audio Codec: %s (%s)\n"),
498 (minfo && strlen(minfo)) ? (char *) minfo : _("Unavailable"),
499 (get_fourcc_string(tmp, sizeof(tmp), afcc)));
500 }
501
502
503 if(v_unhandled && a_unhandled) {
504 xine_error("%s%s%s", buffer ? buffer : "", v_info ? v_info : "", a_info ? a_info : "");
505 free(buffer); free(v_info); free(a_info);
506 return 0;
507 }
508
509 if(!gui->play_anyway) {
510 xitk_window_t *xw;
511
512 play_data.stream = stream;
513 play_data.start_pos = start_pos;
514 play_data.start_time_in_secs = start_time_in_secs;
515 play_data.update_mmk = update_mmk;
516 play_data.running = 1;
517
518 xw = xitk_window_dialog_yesno_with_width(gui->imlib_data, _("Start Playback ?"),
519 start_anyway_yesno, start_anyway_yesno,
520 gui, 400, ALIGN_CENTER,
521 "%s%s%s%s", buffer ? buffer : "",
522 v_info ? v_info : "", a_info ? a_info : "",
523 _("\nStart playback anyway ?\n"));
524 free(buffer); free(v_info); free(a_info);
525
526 gui->x_lock_display (gui->display);
527 XSync(gui->display, False);
528 gui->x_unlock_display (gui->display);
529 video_window_set_transient_for (gui->vwin, xitk_window_get_window (xw));
530 layer_above_video(xitk_window_get_window(xw));
531
532 /* Doesn't work so well yet
533 use play_data.running hack for a while
534 xitk_window_dialog_set_modal(xw);
535 */
536
537 return 1;
538 }
539
540 free(buffer); free(v_info); free(a_info);
541 }
542
543 return _gui_xine_play (gui, stream, start_pos, start_time_in_secs * 1000, update_mmk);
544 }
545
gui_xine_open_and_play(char * _mrl,char * _sub,int start_pos,int start_time,int av_offset,int spu_offset,int report_error)546 int gui_xine_open_and_play(char *_mrl, char *_sub, int start_pos,
547 int start_time, int av_offset, int spu_offset, int report_error) {
548 gGui_t *gui = gGui;
549 char *mrl = _mrl;
550 int ret;
551
552 if(__xineui_global_verbosity)
553 printf("%s():\n\tmrl: '%s',\n\tsub '%s',\n\tstart_pos %d, start_time %d, av_offset %d, spu_offset %d.\n",
554 __func__, _mrl, (_sub) ? _sub : "NONE", start_pos, start_time, av_offset, spu_offset);
555
556 if(!strncasecmp(mrl, "cfg:/", 5)) {
557 config_mrl(mrl);
558 gui_playlist_start_next (gui);
559 return 1;
560 }
561 else if(/*(!strncasecmp(mrl, "ftp://", 6)) ||*/ (!strncasecmp(mrl, "dload:/", 7))) {
562 char *url = mrl;
563 download_t download;
564
565 if(!strncasecmp(mrl, "dload:/", 7))
566 url = _mrl + 7;
567
568 download.buf = NULL;
569 download.error = NULL;
570 download.size = 0;
571 download.status = 0;
572
573 if((network_download(url, &download))) {
574 char *filename;
575
576 filename = strrchr(url, '/');
577 if(filename && filename[1]) { /* we have a filename */
578 char fullfilename[XITK_PATH_MAX + XITK_NAME_MAX + 2];
579 FILE *fd;
580
581 filename++;
582 snprintf(fullfilename, sizeof(fullfilename), "%s/%s", xine_get_homedir(), filename);
583
584 if((fd = fopen(fullfilename, "w+b")) != NULL) {
585 char *sub = NULL;
586 int start, end;
587
588 char *newmrl = strdup(fullfilename);
589 char *ident = strdup(gui->playlist.mmk[gui->playlist.cur]->ident);
590 if(gui->playlist.mmk[gui->playlist.cur]->sub)
591 sub = strdup(gui->playlist.mmk[gui->playlist.cur]->sub);
592 start = gui->playlist.mmk[gui->playlist.cur]->start;
593 end = gui->playlist.mmk[gui->playlist.cur]->end;
594
595 fwrite(download.buf, download.size, 1, fd);
596 fflush(fd);
597 fclose(fd);
598
599 mediamark_replace_entry(&gui->playlist.mmk[gui->playlist.cur],
600 newmrl, ident, sub, start, end, 0, 0);
601 gui_set_current_mmk(mediamark_get_current_mmk());
602 mrl = gui->mmk.mrl;
603
604 free(newmrl);
605 free(ident);
606 free(sub);
607 }
608 }
609 }
610
611 free(download.buf);
612 free(download.error);
613
614 }
615
616 if(mrl_look_like_playlist(mrl)) {
617 if(mediamark_concat_mediamarks(mrl)) {
618 gui_set_current_mmk(mediamark_get_current_mmk());
619 mrl = gui->mmk.mrl;
620 start_pos = 0;
621 start_time = gui->mmk.start;
622 av_offset = gui->mmk.av_offset;
623 spu_offset = gui->mmk.spu_offset;
624 playlist_update_playlist();
625 }
626 }
627
628 gui_messages_off (gui);
629 ret = xine_open(gui->stream, (const char *) mrl);
630 gui_messages_on (gui);
631 if (!ret) {
632
633 #ifdef XINE_PARAM_GAPLESS_SWITCH
634 if( xine_check_version(1,1,1) )
635 xine_set_param(gui->stream, XINE_PARAM_GAPLESS_SWITCH, 0);
636 #endif
637
638 if(!strcmp(mrl, gui->mmk.mrl))
639 gui->playlist.mmk[gui->playlist.cur]->played = 1;
640
641 if(report_error)
642 gui_handle_xine_error(gui->stream, mrl);
643 return 0;
644 }
645
646 if(_sub) {
647
648 gui_messages_off (gui);
649 ret = xine_open(gui->spu_stream, _sub);
650 gui_messages_on (gui);
651 if (ret)
652 xine_stream_master_slave(gui->stream,
653 gui->spu_stream, XINE_MASTER_SLAVE_PLAY | XINE_MASTER_SLAVE_STOP);
654 }
655 else
656 xine_close (gui->spu_stream);
657
658 xine_set_param(gui->stream, XINE_PARAM_AV_OFFSET, av_offset);
659 xine_set_param(gui->stream, XINE_PARAM_SPU_OFFSET, spu_offset);
660
661 if (!gui_xine_play (gui, gui->stream, start_pos, start_time, 1)) {
662 if(!strcmp(mrl, gui->mmk.mrl))
663 gui->playlist.mmk[gui->playlist.cur]->played = 1;
664 return 0;
665 }
666
667 if(!strcmp(mrl, gui->mmk.mrl))
668 gui->playlist.mmk[gui->playlist.cur]->played = 1;
669
670 gui_xine_get_pos_length(gui->stream, NULL, NULL, NULL);
671
672 if (gui->stdctl_enable)
673 stdctl_playing(mrl);
674
675 return 1;
676 }
677
gui_open_and_play_alternates(mediamark_t * mmk,const char * sub)678 int gui_open_and_play_alternates(mediamark_t *mmk, const char *sub) {
679 gGui_t *gui = gGui;
680 char *alt;
681
682 if(!(alt = mediamark_get_current_alternate_mrl(mmk)))
683 alt = mediamark_get_first_alternate_mrl(mmk);
684
685 do {
686
687 if(gui_xine_open_and_play(alt, gui->mmk.sub, 0, 0, 0, 0, 0))
688 return 1;
689
690 } while((alt = mediamark_get_next_alternate_mrl(&(gui->mmk))));
691 return 0;
692 }
693
694 /*
695 * Callback-functions for widget-button click
696 */
gui_exit(xitk_widget_t * w,void * data)697 void gui_exit (xitk_widget_t *w, void *data) {
698 gGui_t *gui = data;
699
700 oxine_exit();
701
702 if(xine_get_status(gui->stream) == XINE_STATUS_PLAY) {
703 gui->ignore_next = 1;
704
705 if(gui->visual_anim.running) {
706 xine_post_out_t * audio_source;
707
708 xine_stop(gui->visual_anim.stream);
709
710 while(xine_get_status(gui->visual_anim.stream) == XINE_STATUS_PLAY)
711 xine_usec_sleep(50000);
712
713 audio_source = xine_get_audio_source(gui->stream);
714 (void) xine_post_wire_audio_port(audio_source, gui->ao_port);
715 }
716
717 xine_stop (gui->stream);
718 while(xine_get_status(gui->stream) == XINE_STATUS_PLAY)
719 xine_usec_sleep(50000);
720
721 gui->ignore_next = 0;
722 }
723
724 gui->on_quit = 1;
725
726 /* shut down event queue threads */
727 /* do it first, events access gui elements ... */
728 xine_event_dispose_queue(gui->event_queue);
729 xine_event_dispose_queue(gui->visual_anim.event_queue);
730 gui->event_queue = gui->visual_anim.event_queue = NULL;
731
732 panel_deinit (gui->panel);
733 destroy_mrl_browser (gui->mrlb);
734 control_deinit (gui->vctrl);
735
736 gui_deinit (gui);
737
738 playlist_deinit();
739
740 setup_end (gui->setup);
741 viewlog_end();
742 kbedit_end();
743 event_sender_end();
744 stream_infos_end();
745 tvset_end();
746 vpplugin_end();
747 applugin_end();
748 help_end();
749 #ifdef HAVE_TAR
750 download_skin_end();
751 #endif
752
753 if (gui->load_stream) {
754 filebrowser_end (gui->load_stream);
755 gui->load_stream = NULL;
756 }
757 if (gui->load_sub) {
758 filebrowser_end (gui->load_sub);
759 gui->load_sub = NULL;
760 }
761
762 if (video_window_is_visible (gui->vwin))
763 video_window_set_visibility (gui->vwin, 0);
764
765 tvout_deinit(gui->tvout);
766
767 #ifdef HAVE_XF86VIDMODE
768 /* just in case a different modeline than the original one is running,
769 * toggle back to window mode which automatically causes a switch back to
770 * the original modeline
771 */
772 if(gui->XF86VidMode_fullscreen)
773 video_window_set_fullscreen_mode (gui->vwin, WINDOWED_MODE);
774 // gui_set_fullscreen_mode (NULL, gui);
775 #endif
776
777 osd_deinit();
778
779 config_update_num("gui.amp_level", gui->mixer.amp_level);
780 xine_config_save (gui->xine, __xineui_global_config_file);
781
782 xine_close(gui->stream);
783 xine_close(gui->visual_anim.stream);
784 xine_close (gui->spu_stream);
785
786 /* we are going to dispose this stream, so make sure slider_loop
787 * won't use it anymore (otherwise -> segfault on exit).
788 */
789 gui->running = 0;
790
791 if(gui->visual_anim.post_output_element.post)
792 xine_post_dispose (gui->xine, gui->visual_anim.post_output_element.post);
793 gui->visual_anim.post_output_element.post = NULL;
794
795 /* unwire post plugins before closing streams */
796 post_deinit ();
797 post_deinterlace_deinit ();
798
799 xine_dispose(gui->stream);
800 xine_dispose(gui->visual_anim.stream);
801 xine_dispose (gui->spu_stream);
802 gui->stream = gui->visual_anim.stream = gui->spu_stream = NULL;
803
804 if(gui->vo_port)
805 xine_close_video_driver (gui->xine, gui->vo_port);
806 if(gui->vo_none)
807 xine_close_video_driver (gui->xine, gui->vo_none);
808 gui->vo_port = gui->vo_none = NULL;
809
810 if(gui->ao_port)
811 xine_close_audio_driver (gui->xine, gui->ao_port);
812 if(gui->ao_none)
813 xine_close_audio_driver (gui->xine, gui->ao_none);
814 gui->ao_port = gui->ao_none = NULL;
815
816 video_window_exit (gui->vwin);
817
818 #ifdef HAVE_LIRC
819 if(__xineui_global_lirc_enable)
820 lirc_stop();
821 #endif
822
823 if(gui->stdctl_enable)
824 stdctl_stop();
825
826 /* this will prevent a race condition that may lead to a lock:
827 * xitk_stop() makes gui_run() in event.c return from xitk_run()
828 * and do some house cleaning which includes closing displays.
829 * However, we're not done using displays and we must prevent that
830 * from happening until we're finished.
831 */
832 gui->x_lock_display (gui->video_display);
833 if( gui->video_display != gui->display )
834 gui->x_lock_display (gui->display);
835 xitk_stop();
836 /*
837 * This prevent xine waiting till the end of time for an
838 * XEvent when lirc (and futur other control ways) is used to quit .
839 */
840 if( gui->video_display == gui->display )
841 gui_send_expose_to_window(gui->video_window);
842
843 xitk_skin_unload_config(gui->skin_config);
844 gui->x_unlock_display (gui->video_display);
845 if( gui->video_display != gui->display )
846 gui->x_unlock_display (gui->display);
847 }
848
gui_play(xitk_widget_t * w,void * data)849 void gui_play (xitk_widget_t *w, void *data) {
850 gGui_t *gui = data;
851
852 if((!gui->playlist.num) && (xine_get_status(gui->stream) != XINE_STATUS_PLAY))
853 return;
854
855 video_window_reset_ssaver (gui->vwin);
856
857 if(xine_get_status(gui->stream) == XINE_STATUS_PLAY) {
858 if(gui->logo_mode != 0) {
859 gui->ignore_next = 1;
860 xine_stop(gui->stream);
861 gui->ignore_next = 0;
862 }
863 }
864
865 if(xine_get_status(gui->stream) != XINE_STATUS_PLAY) {
866
867 if (!strncmp(gui->mmk.ident, "xine-ui version", 15)) {
868 xine_error (_("No MRL (input stream) specified"));
869 return;
870 }
871
872 if(!gui_xine_open_and_play(gui->mmk.mrl, gui->mmk.sub, 0,
873 gui->mmk.start, gui->mmk.av_offset, gui->mmk.spu_offset,
874 !mediamark_have_alternates(&(gui->mmk)))) {
875
876 if(!mediamark_have_alternates(&(gui->mmk)) ||
877 !gui_open_and_play_alternates(&(gui->mmk), gui->mmk.sub)) {
878
879 if(mediamark_all_played() && (gui->actions_on_start[0] == ACTID_QUIT)) {
880 gui_exit (NULL, gui);
881 return;
882 }
883 gui_display_logo();
884 }
885 }
886 }
887 else {
888 int oldspeed = xine_get_param(gui->stream, XINE_PARAM_SPEED);
889
890 xine_set_param(gui->stream, XINE_PARAM_SPEED, XINE_SPEED_NORMAL);
891 if(oldspeed != XINE_SPEED_NORMAL)
892 osd_update_status();
893 }
894
895 panel_check_pause (gui->panel);
896 }
897
gui_stop(xitk_widget_t * w,void * data)898 void gui_stop (xitk_widget_t *w, void *data) {
899 gGui_t *gui = data;
900
901 gui->ignore_next = 1;
902 xine_stop (gui->stream);
903 gui->ignore_next = 0;
904
905 if(!(gui->playlist.control & PLAYLIST_CONTROL_STOP_PERSIST))
906 gui->playlist.control &= ~PLAYLIST_CONTROL_STOP;
907
908 gui->stream_length.pos = gui->stream_length.time = gui->stream_length.length = 0;
909
910 mediamark_reset_played_state();
911 if(gui->visual_anim.running) {
912 xine_stop(gui->visual_anim.stream);
913 if(gui->visual_anim.enabled == 2)
914 gui->visual_anim.running = 0;
915 }
916
917 osd_hide_sinfo();
918 osd_hide_bar();
919 osd_hide_info();
920 osd_update_status();
921 panel_reset_slider (gui->panel);
922 panel_check_pause (gui->panel);
923 panel_update_runtime_display (gui->panel);
924
925 if (is_playback_widgets_enabled (gui->panel)) {
926 if(!gui->playlist.num) {
927 gui_set_current_mmk(NULL);
928 enable_playback_controls (gui->panel, 0);
929 }
930 else if(gui->playlist.num && (strcmp((mediamark_get_current_mrl()), gui->mmk.mrl))) {
931 gui_set_current_mmk(mediamark_get_current_mmk());
932 }
933 }
934 gui_display_logo();
935 }
936
gui_close(xitk_widget_t * w,void * data)937 void gui_close (xitk_widget_t *w, void *data) {
938 gGui_t *gui = data;
939
940 gui->ignore_next = 1;
941 xine_stop (gui->stream);
942 gui->ignore_next = 0;
943
944 if(!(gui->playlist.control & PLAYLIST_CONTROL_STOP_PERSIST))
945 gui->playlist.control &= ~PLAYLIST_CONTROL_STOP;
946
947 gui->stream_length.pos = gui->stream_length.time = gui->stream_length.length = 0;
948
949 mediamark_reset_played_state();
950 if(gui->visual_anim.running) {
951 xine_stop(gui->visual_anim.stream);
952 if(gui->visual_anim.enabled == 2)
953 gui->visual_anim.running = 0;
954 }
955
956 osd_hide_sinfo();
957 osd_hide_bar();
958 osd_hide_info();
959 osd_update_status();
960 panel_reset_slider (gui->panel);
961 panel_check_pause (gui->panel);
962 panel_update_runtime_display (gui->panel);
963
964 if (is_playback_widgets_enabled (gui->panel)) {
965 if(!gui->playlist.num) {
966 gui_set_current_mmk(NULL);
967 enable_playback_controls (gui->panel, 0);
968 }
969 else if(gui->playlist.num && (strcmp((mediamark_get_current_mrl()), gui->mmk.mrl))) {
970 gui_set_current_mmk(mediamark_get_current_mmk());
971 }
972 }
973 gui->ignore_next = 1;
974 xine_close (gui->stream);
975 gui->ignore_next = 0;
976 }
977
gui_pause(xitk_widget_t * w,void * data,int state)978 void gui_pause (xitk_widget_t *w, void *data, int state) {
979 gGui_t *gui = data;
980 int speed = xine_get_param(gui->stream, XINE_PARAM_SPEED);
981
982 if(speed != XINE_SPEED_PAUSE) {
983 gui->last_playback_speed = speed;
984 xine_set_param(gui->stream, XINE_PARAM_SPEED, XINE_SPEED_PAUSE);
985 panel_update_runtime_display (gui->panel);
986 }
987 else {
988 xine_set_param (gui->stream, XINE_PARAM_SPEED, gui->last_playback_speed);
989 video_window_reset_ssaver (gui->vwin);
990 }
991
992 panel_check_pause (gui->panel);
993 /* Give xine engine some time before updating OSD, otherwise the */
994 /* time disp may be empty when switching to XINE_SPEED_PAUSE. */
995 xine_usec_sleep(10000);
996 osd_update_status();
997 }
998
gui_eject(xitk_widget_t * w,void * data)999 void gui_eject (xitk_widget_t *w, void *data) {
1000 gGui_t *gui = data;
1001 int i;
1002
1003 if(xine_get_status(gui->stream) == XINE_STATUS_PLAY)
1004 gui_stop (NULL, gui);
1005
1006 if(xine_eject(gui->stream)) {
1007
1008 if(gui->playlist.num) {
1009 mediamark_t **mmk = NULL;
1010 char *mrl;
1011 size_t tok_len = 0;
1012 int new_num = 0;
1013
1014 const char *const cur_mrl = mediamark_get_current_mrl();
1015 /*
1016 * If it's an mrl (____://) remove all of them in playlist
1017 */
1018 if ( (mrl = strstr((cur_mrl), ":/")) )
1019 tok_len = (mrl - cur_mrl) + 2;
1020
1021 if(tok_len != 0) {
1022 /*
1023 * Store all of not maching entries
1024 */
1025 for(i = 0; i < gui->playlist.num; i++) {
1026 if(strncasecmp(gui->playlist.mmk[i]->mrl, cur_mrl, tok_len)) {
1027
1028 mmk = (mediamark_t **) realloc(mmk, sizeof(mediamark_t *) * (new_num + 2));
1029
1030 (void) mediamark_store_mmk(&mmk[new_num],
1031 gui->playlist.mmk[i]->mrl,
1032 gui->playlist.mmk[i]->ident,
1033 gui->playlist.mmk[i]->sub,
1034 gui->playlist.mmk[i]->start,
1035 gui->playlist.mmk[i]->end,
1036 gui->playlist.mmk[i]->av_offset,
1037 gui->playlist.mmk[i]->spu_offset);
1038 new_num++;
1039 }
1040 }
1041
1042 /*
1043 * flip playlists.
1044 */
1045 mediamark_free_mediamarks();
1046 if(mmk)
1047 gui->playlist.mmk = mmk;
1048
1049 if(!(gui->playlist.num = new_num))
1050 gui->playlist.cur = -1;
1051 else if(new_num)
1052 gui->playlist.cur = 0;
1053 }
1054 else {
1055 __remove_current_mrl:
1056 /*
1057 * Remove only the current MRL
1058 */
1059 mediamark_free_entry(gui->playlist.cur);
1060
1061 for(i = gui->playlist.cur; i < gui->playlist.num; i++)
1062 gui->playlist.mmk[i] = gui->playlist.mmk[i + 1];
1063
1064 gui->playlist.mmk = (mediamark_t **) realloc(gui->playlist.mmk, sizeof(mediamark_t *) * (gui->playlist.num + 2));
1065
1066 gui->playlist.mmk[gui->playlist.num] = NULL;
1067
1068 if(gui->playlist.cur)
1069 gui->playlist.cur--;
1070 }
1071
1072 if (is_playback_widgets_enabled (gui->panel) && (!gui->playlist.num))
1073 enable_playback_controls (gui->panel, 0);
1074
1075 }
1076
1077 gui_set_current_mmk(mediamark_get_current_mmk());
1078 playlist_update_playlist();
1079 }
1080 else {
1081 /* Remove current mrl */
1082 if(gui->playlist.num)
1083 goto __remove_current_mrl;
1084 }
1085
1086 if(!gui->playlist.num)
1087 gui->playlist.cur = -1;
1088
1089 }
1090
gui_toggle_visibility(xitk_widget_t * w,void * data)1091 void gui_toggle_visibility (xitk_widget_t *w, void *data) {
1092 gGui_t *gui = data;
1093
1094 if (panel_is_visible (gui->panel) && (!gui->use_root_window)) {
1095 int visible = !video_window_is_visible (gui->vwin);
1096
1097 video_window_set_visibility (gui->vwin, visible);
1098
1099
1100 /* We need to reparent all visible windows because of redirect tweaking */
1101 if(!visible) { /* Show the panel in taskbar */
1102 int x = 0, y = 0;
1103
1104 xitk_get_window_position(gui->display, gui->panel_window, &x, &y, NULL, NULL);
1105 gui->x_lock_display (gui->display);
1106 XReparentWindow(gui->display, gui->panel_window, gui->imlib_data->x.root, x, y);
1107 gui->x_unlock_display (gui->display);
1108 }
1109 reparent_all_windows();
1110
1111 /* (re)start/stop visual animation */
1112 if (video_window_is_visible (gui->vwin)) {
1113 layer_above_video(gui->panel_window);
1114
1115 if(gui->visual_anim.enabled && (gui->visual_anim.running == 2))
1116 visual_anim_play();
1117 }
1118 else {
1119
1120 if(gui->visual_anim.running) {
1121 visual_anim_stop();
1122 gui->visual_anim.running = 2;
1123 }
1124 }
1125 }
1126 }
1127
gui_toggle_border(xitk_widget_t * w,void * data)1128 void gui_toggle_border (xitk_widget_t *w, void *data) {
1129 gGui_t *gui = data;
1130 video_window_toggle_border (gui->vwin);
1131 }
1132
set_fullscreen_mode(int fullscreen_mode)1133 static void set_fullscreen_mode(int fullscreen_mode) {
1134 gGui_t *gui = gGui;
1135 int panel = panel_is_visible (gui->panel);
1136 int mrl_browser = mrl_browser_is_visible (gui->mrlb);
1137 int playlist = playlist_is_visible();
1138 int control = control_status (gui->vctrl) == 3;
1139 int setup = setup_is_visible (gui->setup);
1140 int viewlog = viewlog_is_visible();
1141 int kbedit = kbedit_is_visible();
1142 int event_sender = event_sender_is_visible();
1143 int stream_infos = stream_infos_is_visible();
1144 int tvset = tvset_is_visible();
1145 int vpplugin = vpplugin_is_visible();
1146 int applugin = applugin_is_visible();
1147 int help = help_is_visible();
1148
1149 if ((!(video_window_is_visible (gui->vwin))) || gui->use_root_window)
1150 return;
1151
1152 if(panel)
1153 panel_toggle_visibility (NULL, gui->panel);
1154 else {
1155 if(mrl_browser)
1156 mrl_browser_toggle_visibility (NULL, gui->mrlb);
1157 if(playlist)
1158 playlist_toggle_visibility(NULL, NULL);
1159 if(control)
1160 control_toggle_visibility (NULL, gui->vctrl);
1161 if(setup)
1162 setup_toggle_visibility (NULL, gui->setup);
1163 if(viewlog)
1164 viewlog_toggle_visibility(NULL, NULL);
1165 if(kbedit)
1166 kbedit_toggle_visibility(NULL, NULL);
1167 if(event_sender)
1168 event_sender_toggle_visibility(NULL, NULL);
1169 if(stream_infos)
1170 stream_infos_toggle_visibility(NULL, NULL);
1171 if(tvset)
1172 tvset_toggle_visibility(NULL, NULL);
1173 if(vpplugin)
1174 vpplugin_toggle_visibility(NULL, NULL);
1175 if(applugin)
1176 applugin_toggle_visibility(NULL, NULL);
1177 if(help)
1178 help_toggle_visibility(NULL, NULL);
1179 }
1180
1181 video_window_set_fullscreen_mode (gui->vwin, fullscreen_mode);
1182
1183 /* Drawable has changed, update cursor visiblity */
1184 if(!gui->cursor_visible)
1185 video_window_set_cursor_visibility (gui->vwin, gui->cursor_visible);
1186
1187 if(panel)
1188 panel_toggle_visibility (NULL, gui->panel);
1189 else {
1190 if(mrl_browser)
1191 mrl_browser_toggle_visibility (NULL, gui->mrlb);
1192 if(playlist)
1193 playlist_toggle_visibility(NULL, NULL);
1194 if(control)
1195 control_toggle_visibility (NULL, gui->vctrl);
1196 if(setup)
1197 setup_toggle_visibility (NULL, gui->setup);
1198 if(viewlog)
1199 viewlog_toggle_visibility(NULL, NULL);
1200 if(kbedit)
1201 kbedit_toggle_visibility(NULL, NULL);
1202 if(event_sender)
1203 event_sender_toggle_visibility(NULL, NULL);
1204 if(stream_infos)
1205 stream_infos_toggle_visibility(NULL, NULL);
1206 if(tvset)
1207 tvset_toggle_visibility(NULL, NULL);
1208 if(vpplugin)
1209 vpplugin_toggle_visibility(NULL, NULL);
1210 if(applugin)
1211 applugin_toggle_visibility(NULL, NULL);
1212 if(help)
1213 help_toggle_visibility(NULL, NULL);
1214 }
1215
1216 }
1217
gui_set_fullscreen_mode(xitk_widget_t * w,void * data)1218 void gui_set_fullscreen_mode (xitk_widget_t *w, void *data) {
1219 (void)data;
1220 set_fullscreen_mode(FULLSCR_MODE);
1221 }
1222
1223 #ifdef HAVE_XINERAMA
gui_set_xinerama_fullscreen_mode(void)1224 void gui_set_xinerama_fullscreen_mode(void) {
1225 set_fullscreen_mode(FULLSCR_XI_MODE);
1226 }
1227 #endif
1228
gui_toggle_aspect(int aspect)1229 void gui_toggle_aspect(int aspect) {
1230 gGui_t *gui = gGui;
1231 static const char * const ratios[XINE_VO_ASPECT_NUM_RATIOS + 1] = {
1232 "Auto",
1233 "Square",
1234 "4:3",
1235 "Anamorphic",
1236 "DVB",
1237 NULL
1238 };
1239
1240 if(aspect == -1)
1241 aspect = xine_get_param(gui->stream, XINE_PARAM_VO_ASPECT_RATIO) + 1;
1242
1243 xine_set_param(gui->stream, XINE_PARAM_VO_ASPECT_RATIO, aspect);
1244
1245 osd_display_info(_("Aspect ratio: %s"),
1246 ratios[xine_get_param(gui->stream, XINE_PARAM_VO_ASPECT_RATIO)]);
1247
1248 if (panel_is_visible (gui->panel)) {
1249 gui->x_lock_display (gui->display);
1250 XRaiseWindow(gui->display, gui->panel_window);
1251 gui->x_unlock_display (gui->display);
1252 video_window_set_transient_for (gui->vwin, gui->panel_window);
1253 }
1254 }
1255
gui_toggle_interlaced(void)1256 void gui_toggle_interlaced(void) {
1257 gGui_t *gui = gGui;
1258 gui->deinterlace_enable = !gui->deinterlace_enable;
1259 osd_display_info(_("Deinterlace: %s"), (gui->deinterlace_enable) ? _("enabled") : _("disabled"));
1260 post_deinterlace();
1261
1262 if (panel_is_visible (gui->panel)) {
1263 gui->x_lock_display (gui->display);
1264 XRaiseWindow(gui->display, gui->panel_window);
1265 gui->x_unlock_display (gui->display);
1266 video_window_set_transient_for (gui->vwin, gui->panel_window);
1267 }
1268 }
1269
gui_direct_change_audio_channel(xitk_widget_t * w,void * data,int value)1270 void gui_direct_change_audio_channel (xitk_widget_t *w, void *data, int value) {
1271 gGui_t *gui = data;
1272 xine_set_param(gui->stream, XINE_PARAM_AUDIO_CHANNEL_LOGICAL, value);
1273 panel_update_channel_display (gui->panel);
1274 osd_display_audio_lang();
1275 }
1276
gui_change_audio_channel(xitk_widget_t * w,void * data)1277 void gui_change_audio_channel(xitk_widget_t *w, void *data) {
1278 gGui_t *gui = gGui;
1279 int dir = (int)(intptr_t)data;
1280 int channel;
1281
1282 channel = xine_get_param(gui->stream, XINE_PARAM_AUDIO_CHANNEL_LOGICAL);
1283
1284 if(dir == GUI_NEXT)
1285 channel++;
1286 else if(dir == GUI_PREV)
1287 channel--;
1288
1289 gui_direct_change_audio_channel(w, gui, channel);
1290 }
1291
gui_direct_change_spu_channel(xitk_widget_t * w,void * data,int value)1292 void gui_direct_change_spu_channel(xitk_widget_t *w, void *data, int value) {
1293 gGui_t *gui = gGui;
1294 xine_set_param(gui->stream, XINE_PARAM_SPU_CHANNEL, value);
1295 panel_update_channel_display (gui->panel);
1296 osd_display_spu_lang();
1297 }
1298
gui_change_spu_channel(xitk_widget_t * w,void * data)1299 void gui_change_spu_channel(xitk_widget_t *w, void *data) {
1300 gGui_t *gui = gGui;
1301 int dir = (int)(intptr_t)data;
1302 int channel;
1303 int maxchannel;
1304
1305 channel = xine_get_param(gui->stream, XINE_PARAM_SPU_CHANNEL);
1306 maxchannel = xine_get_stream_info(gui->stream, XINE_STREAM_INFO_MAX_SPU_CHANNEL);
1307
1308 if (xine_get_status(gui->spu_stream) != XINE_STATUS_IDLE) /* if we have a slave SPU channel, take it into account */
1309 maxchannel += xine_get_stream_info(gui->spu_stream, XINE_STREAM_INFO_MAX_SPU_CHANNEL);
1310
1311 /* XINE_STREAM_INFO_MAX_SPU_CHANNEL actually returns the number of available spu channels, i.e.
1312 * 0 means no SPUs, 1 means 1 SPU channel, etc. */
1313 --maxchannel;
1314
1315 if(dir == GUI_NEXT)
1316 channel++;
1317 else if(dir == GUI_PREV)
1318 channel--;
1319
1320 if (channel > maxchannel)
1321 channel = -2; /* -2 == off, -1 == auto, 0 == 1st channel */
1322 else if (channel < -2)
1323 channel = maxchannel;
1324
1325 gui_direct_change_spu_channel(w, data, channel);
1326 }
1327
gui_change_speed_playback(xitk_widget_t * w,void * data)1328 void gui_change_speed_playback(xitk_widget_t *w, void *data) {
1329 gGui_t *gui = gGui;
1330 int speed = xine_get_param(gui->stream, XINE_PARAM_SPEED);
1331
1332 if(((intptr_t)data) == GUI_NEXT) {
1333 if (speed > XINE_SPEED_PAUSE) {
1334 xine_set_param(gui->stream, XINE_PARAM_SPEED, (speed /= 2));
1335 }
1336 #ifdef XINE_PARAM_VO_SINGLE_STEP
1337 else {
1338 xine_set_param (gui->stream, XINE_PARAM_VO_SINGLE_STEP, 1);
1339 panel_update_runtime_display (gui->panel);
1340 }
1341 #endif
1342 }
1343 else if(((intptr_t)data) == GUI_PREV) {
1344 if(speed < XINE_SPEED_FAST_4) {
1345 if(speed > XINE_SPEED_PAUSE)
1346 xine_set_param(gui->stream, XINE_PARAM_SPEED, (speed *= 2));
1347 else {
1348 xine_set_param(gui->stream, XINE_PARAM_SPEED, (speed = XINE_SPEED_SLOW_4));
1349 video_window_reset_ssaver (gui->vwin);
1350 }
1351 }
1352 }
1353 else if(((intptr_t)data) == GUI_RESET) {
1354 xine_set_param(gui->stream, XINE_PARAM_SPEED, (speed = XINE_SPEED_NORMAL));
1355 }
1356 if(speed != XINE_SPEED_PAUSE)
1357 gui->last_playback_speed = speed;
1358
1359 panel_check_pause (gui->panel);
1360 /* Give xine engine some time before updating OSD, otherwise the */
1361 /* time disp may be empty when switching to speeds < XINE_SPEED_NORMAL. */
1362 xine_usec_sleep(10000);
1363 osd_update_status();
1364 }
1365
gui_seek_thread(void * data)1366 static void *gui_seek_thread (void *data) {
1367 gGui_t *gui = data;
1368 int update_mmk = 0, ret;
1369
1370 pthread_detach (pthread_self ());
1371
1372 do {
1373 {
1374 const char *mrl = mediamark_get_current_mrl ();
1375 if (gui->logo_mode && mrl) {
1376 gui_messages_off (gui);
1377 ret = xine_open (gui->stream, mrl);
1378 gui_messages_on (gui);
1379 if (!ret) {
1380 gui_handle_xine_error (gui->stream, (char *)mrl);
1381 break;
1382 }
1383 }
1384 }
1385
1386 if (!xine_get_stream_info (gui->stream, XINE_STREAM_INFO_SEEKABLE) || (gui->ignore_next == 1))
1387 break;
1388
1389 if (xine_get_status (gui->stream) != XINE_STATUS_PLAY) {
1390 gui_messages_off (gui);
1391 xine_open (gui->stream, gui->mmk.mrl);
1392 gui_messages_on (gui);
1393
1394 if (gui->mmk.sub) {
1395 gui_messages_off (gui);
1396 ret = xine_open (gui->spu_stream, gui->mmk.sub);
1397 gui_messages_on (gui);
1398 if (ret)
1399 xine_stream_master_slave (gui->stream, gui->spu_stream, XINE_MASTER_SLAVE_PLAY | XINE_MASTER_SLAVE_STOP);
1400 } else {
1401 xine_close (gui->spu_stream);
1402 }
1403 }
1404
1405 gui->ignore_next = 1;
1406
1407 if ( gui->playlist.num &&
1408 (gui->playlist.cur >= 0) &&
1409 gui->playlist.mmk &&
1410 gui->playlist.mmk[gui->playlist.cur] &&
1411 !strcmp (gui->playlist.mmk[gui->playlist.cur]->mrl, gui->mmk.mrl))
1412 update_mmk = 1;
1413
1414 {
1415 int pos = -1;
1416
1417 while (1) {
1418 pthread_mutex_lock (&gui->seek_mutex);
1419 if ((pos == gui->seek_pos) && (gui->seek_timestep == 0)) {
1420 gui->seek_running = 0;
1421 gui->seek_pos = -1;
1422 pthread_mutex_unlock (&gui->seek_mutex);
1423 break;
1424 }
1425 if (pos != gui->seek_pos) {
1426
1427 pos = gui->seek_pos;
1428 pthread_mutex_unlock (&gui->seek_mutex);
1429 /* panel_update_slider (gui->panel, pos); */
1430 osd_stream_position (pos);
1431 _gui_xine_play (gui, gui->stream, pos, 0, update_mmk);
1432 xine_get_pos_length (gui->stream,
1433 &gui->stream_length.pos, &gui->stream_length.time, &gui->stream_length.length);
1434 panel_update_runtime_display (gui->panel);
1435
1436 } else {
1437
1438 int cur_time;
1439 int timestep = gui->seek_timestep;
1440 gui->seek_timestep = 0;
1441 pthread_mutex_unlock (&gui->seek_mutex);
1442 if ( xine_get_stream_info (gui->stream, XINE_STREAM_INFO_SEEKABLE) &&
1443 (xine_get_status (gui->stream) == XINE_STATUS_PLAY) &&
1444 xine_get_pos_length (gui->stream, NULL, &cur_time, NULL)) {
1445 gui->ignore_next = 1;
1446 cur_time += timestep;
1447 if (cur_time < 0)
1448 cur_time = 0;
1449 _gui_xine_play (gui, gui->stream, 0, cur_time, 1);
1450 if (xine_get_pos_length (gui->stream,
1451 &gui->stream_length.pos, &gui->stream_length.time, &gui->stream_length.length)) {
1452 panel_update_slider (gui->panel, gui->stream_length.pos);
1453 osd_stream_position (gui->stream_length.pos);
1454 }
1455 gui->ignore_next = 0;
1456 }
1457
1458 }
1459 }
1460 }
1461
1462 gui->ignore_next = 0;
1463 osd_hide_status ();
1464 panel_check_pause (gui->panel);
1465
1466 return NULL;
1467 } while (0);
1468
1469 pthread_mutex_lock (&gui->seek_mutex);
1470 gui->seek_running = 0;
1471 gui->seek_pos = -1;
1472 gui->seek_timestep = 0;
1473 pthread_mutex_unlock (&gui->seek_mutex);
1474 return NULL;
1475 }
1476
gui_set_current_position(int pos)1477 void gui_set_current_position (int pos) {
1478 gGui_t *gui = gGui;
1479
1480 pthread_mutex_lock (&gui->seek_mutex);
1481 if (gui->seek_running == 0) {
1482 pthread_t pth;
1483 int err;
1484 gui->seek_running = 1;
1485 gui->seek_pos = pos;
1486 pthread_mutex_unlock (&gui->seek_mutex);
1487 err = pthread_create (&pth, NULL, gui_seek_thread, gui);
1488 if (err) {
1489 printf (_("%s(): can't create new thread (%s)\n"), __XINE_FUNCTION__, strerror (err));
1490 pthread_mutex_lock (&gui->seek_mutex);
1491 gui->seek_running = 0;
1492 gui->seek_pos = -1;
1493 gui->seek_timestep = 0;
1494 pthread_mutex_unlock (&gui->seek_mutex);
1495 }
1496 } else {
1497 gui->seek_pos = pos;
1498 pthread_mutex_unlock (&gui->seek_mutex);
1499 }
1500 }
1501
gui_seek_relative(int off_sec)1502 void gui_seek_relative (int off_sec) {
1503 gGui_t *gui = gGui;
1504
1505 if (off_sec == 0)
1506 return;
1507
1508 pthread_mutex_lock (&gui->seek_mutex);
1509 if (gui->seek_running == 0) {
1510 pthread_t pth;
1511 int err;
1512 gui->seek_running = 1;
1513 gui->seek_timestep = off_sec * 1000;
1514 pthread_mutex_unlock (&gui->seek_mutex);
1515 err = pthread_create (&pth, NULL, gui_seek_thread, gui);
1516 if (err) {
1517 printf (_("%s(): can't create new thread (%s)\n"), __XINE_FUNCTION__, strerror (err));
1518 pthread_mutex_lock (&gui->seek_mutex);
1519 gui->seek_running = 0;
1520 gui->seek_pos = -1;
1521 gui->seek_timestep = 0;
1522 pthread_mutex_unlock (&gui->seek_mutex);
1523 }
1524 } else {
1525 gui->seek_timestep = off_sec * 1000;
1526 pthread_mutex_unlock (&gui->seek_mutex);
1527 }
1528 }
1529
gui_dndcallback(const char * filename)1530 void gui_dndcallback(const char *filename) {
1531 gGui_t *gui = gGui;
1532 int more_than_one = -2;
1533 char *mrl = filename ? strdup(filename) : NULL;
1534
1535 if(mrl) {
1536 char buffer[strlen(mrl) + 10];
1537 char buffer2[strlen(mrl) + 10];
1538 char *p;
1539
1540 memset(&buffer, 0, sizeof(buffer));
1541 memset(&buffer2, 0, sizeof(buffer2));
1542
1543 pthread_mutex_lock(&gui->mmk_mutex);
1544
1545 if((strlen(mrl) > 6) &&
1546 (!strncmp(mrl, "file:", 5))) {
1547
1548 if((p = strstr(mrl, ":/")) != NULL) {
1549 struct stat pstat;
1550
1551 p += 2;
1552
1553 if(*(p + 1) == '/')
1554 p++;
1555
1556 __second_stat:
1557
1558 if((stat(p, &pstat)) == 0) {
1559 if(is_a_dir(p)) {
1560 if(*(p + (strlen(p) - 1)) == '/')
1561 *(p + (strlen(p) - 1)) = '\0';
1562
1563 mediamark_collect_from_directory(p);
1564 more_than_one = gui->playlist.cur;
1565 goto __do_play;
1566 }
1567 else
1568 snprintf(buffer, sizeof(buffer), "file:/%s", p);
1569 }
1570 else {
1571 snprintf(buffer2, sizeof(buffer2), "/%s", p);
1572
1573 /* file don't exist, add it anyway */
1574 if((stat(buffer2, &pstat)) == -1)
1575 strlcpy(buffer, mrl, sizeof(buffer));
1576 else {
1577 if(is_a_dir(buffer2)) {
1578
1579 if(buffer2[strlen(buffer2) - 1] == '/')
1580 buffer2[strlen(buffer2) - 1] = '\0';
1581
1582 mediamark_collect_from_directory(buffer2);
1583 more_than_one = gui->playlist.cur;
1584 goto __do_play;
1585 }
1586 else
1587 snprintf(buffer, sizeof(buffer), "file:/%s", buffer2);
1588 }
1589
1590 }
1591 }
1592 else {
1593 p = mrl + 5;
1594 goto __second_stat;
1595 }
1596 }
1597 else
1598 strlcpy(buffer, mrl, sizeof(buffer));
1599
1600 if(is_a_dir(buffer)) {
1601 if(buffer[strlen(buffer) - 1] == '/')
1602 buffer[strlen(buffer) - 1] = '\0';
1603
1604 mediamark_collect_from_directory(buffer);
1605 more_than_one = gui->playlist.cur;
1606 }
1607 else {
1608 char *ident;
1609
1610 /* If possible, use only base name as identifier to better fit into the display */
1611 if((ident = strrchr(buffer, '/')) && ident[1])
1612 ident++;
1613 else
1614 ident = buffer;
1615
1616 if(mrl_look_like_playlist(buffer)) {
1617 int cur = gui->playlist.cur;
1618
1619 more_than_one = (gui->playlist.cur - 1);
1620 if(mediamark_concat_mediamarks(buffer))
1621 gui->playlist.cur = cur;
1622 else
1623 mediamark_append_entry(buffer, ident, NULL, 0, -1, 0, 0);
1624 }
1625 else
1626 mediamark_append_entry(buffer, ident, NULL, 0, -1, 0, 0);
1627
1628 }
1629
1630 __do_play:
1631
1632 playlist_update_playlist();
1633
1634 if(!(gui->playlist.control & PLAYLIST_CONTROL_IGNORE)) {
1635
1636 if((xine_get_status(gui->stream) == XINE_STATUS_STOP) || gui->logo_mode) {
1637 if((more_than_one > -2) && ((more_than_one + 1) < gui->playlist.num))
1638 gui->playlist.cur = more_than_one + 1;
1639 else
1640 gui->playlist.cur = gui->playlist.num - 1;
1641
1642 set_mmk(mediamark_get_current_mmk());
1643 mmk_set_update();
1644 if(gui->smart_mode)
1645 gui_play (NULL, gui);
1646
1647 }
1648 }
1649
1650 if ((!is_playback_widgets_enabled (gui->panel)) && gui->playlist.num)
1651 enable_playback_controls (gui->panel, 1);
1652
1653 pthread_mutex_unlock(&gui->mmk_mutex);
1654 }
1655
1656 free(mrl);
1657 }
1658
gui_direct_nextprev(xitk_widget_t * w,void * data,int value)1659 void gui_direct_nextprev(xitk_widget_t *w, void *data, int value) {
1660 gGui_t *gui = gGui;
1661 int i, by_chapter;
1662 mediamark_t *mmk = mediamark_get_current_mmk();
1663
1664 by_chapter = (gui->skip_by_chapter &&
1665 (xine_get_stream_info(gui->stream, XINE_STREAM_INFO_HAS_CHAPTERS))) ? 1 : 0;
1666
1667 if(mmk && mediamark_got_alternate(mmk))
1668 mediamark_unset_got_alternate(mmk);
1669
1670 if(((intptr_t)data) == GUI_NEXT) {
1671
1672 osd_hide();
1673
1674 if(by_chapter) {
1675
1676 for(i = 0; i < value; i++)
1677 gui_execute_action_id (gui, ACTID_EVENT_NEXT);
1678
1679 }
1680 else {
1681
1682 switch(gui->playlist.loop) {
1683
1684 case PLAYLIST_LOOP_SHUFFLE:
1685 case PLAYLIST_LOOP_SHUF_PLUS:
1686 gui->ignore_next = 0;
1687 gui_playlist_start_next (gui);
1688 break;
1689
1690 case PLAYLIST_LOOP_NO_LOOP:
1691 case PLAYLIST_LOOP_REPEAT:
1692 if((gui->playlist.cur + value) < gui->playlist.num) {
1693
1694 if(gui->playlist.loop == PLAYLIST_LOOP_NO_LOOP)
1695 gui->playlist.cur += (value - 1);
1696 else
1697 gui->playlist.cur += value;
1698
1699 gui->ignore_next = 0;
1700 gui_playlist_start_next (gui);
1701 }
1702 break;
1703
1704 case PLAYLIST_LOOP_LOOP:
1705 if((gui->playlist.cur + value) > gui->playlist.num) {
1706 int newcur = value - (gui->playlist.num - gui->playlist.cur);
1707
1708 gui->ignore_next = 1;
1709 gui->playlist.cur = newcur;
1710 gui_set_current_mmk(mediamark_get_current_mmk());
1711 if(!gui_xine_open_and_play(gui->mmk.mrl, gui->mmk.sub, 0,
1712 gui->mmk.start, gui->mmk.av_offset, gui->mmk.spu_offset, 1))
1713 gui_display_logo();
1714
1715 gui->ignore_next = 0;
1716 }
1717 else {
1718 gui->playlist.cur += (value - 1);
1719 gui->ignore_next = 0;
1720 gui_playlist_start_next (gui);
1721 }
1722 break;
1723 }
1724 }
1725 }
1726 else if(((intptr_t)data) == GUI_PREV) {
1727
1728 osd_hide();
1729
1730 if(by_chapter) {
1731
1732 for(i = 0; i < value; i++)
1733 gui_execute_action_id (gui, ACTID_EVENT_PRIOR);
1734
1735 }
1736 else {
1737
1738 switch(gui->playlist.loop) {
1739 case PLAYLIST_LOOP_SHUFFLE:
1740 case PLAYLIST_LOOP_SHUF_PLUS:
1741 gui->ignore_next = 0;
1742 gui_playlist_start_next (gui);
1743 break;
1744
1745 case PLAYLIST_LOOP_NO_LOOP:
1746 case PLAYLIST_LOOP_REPEAT:
1747 if((gui->playlist.cur - value) >= 0) {
1748
1749 gui->ignore_next = 1;
1750 gui->playlist.cur -= value;
1751
1752 if((gui->playlist.cur < gui->playlist.num)) {
1753 gui_set_current_mmk(mediamark_get_current_mmk());
1754 if(!gui_xine_open_and_play(gui->mmk.mrl, gui->mmk.sub, 0,
1755 gui->mmk.start, gui->mmk.av_offset, gui->mmk.spu_offset, 1))
1756 gui_display_logo();
1757
1758 }
1759 else
1760 gui->playlist.cur = 0;
1761
1762 gui->ignore_next = 0;
1763 }
1764 break;
1765
1766 case PLAYLIST_LOOP_LOOP:
1767 gui->ignore_next = 1;
1768
1769 if((gui->playlist.cur - value) >= 0) {
1770
1771 gui->playlist.cur -= value;
1772
1773 if((gui->playlist.cur < gui->playlist.num)) {
1774 gui_set_current_mmk(mediamark_get_current_mmk());
1775 if(!gui_xine_open_and_play(gui->mmk.mrl, gui->mmk.sub, 0,
1776 gui->mmk.start, gui->mmk.av_offset, gui->mmk.spu_offset, 1))
1777 gui_display_logo();
1778 }
1779 else
1780 gui->playlist.cur = 0;
1781
1782 }
1783 else {
1784 int newcur = (gui->playlist.cur - value) + gui->playlist.num;
1785
1786 gui->playlist.cur = newcur;
1787 gui_set_current_mmk(mediamark_get_current_mmk());
1788 if(!gui_xine_open_and_play(gui->mmk.mrl, gui->mmk.sub, 0,
1789 gui->mmk.start, gui->mmk.av_offset, gui->mmk.spu_offset, 1))
1790 gui_display_logo();
1791 }
1792
1793 gui->ignore_next = 0;
1794 break;
1795 }
1796 }
1797 }
1798
1799 panel_check_pause (gui->panel);
1800 }
1801
gui_nextprev(xitk_widget_t * w,void * data)1802 void gui_nextprev(xitk_widget_t *w, void *data) {
1803 gui_direct_nextprev(w, data, 1);
1804 }
1805
gui_playlist_show(xitk_widget_t * w,void * data)1806 void gui_playlist_show(xitk_widget_t *w, void *data) {
1807 gGui_t *gui = gGui;
1808
1809 if(!playlist_is_running()) {
1810 playlist_editor();
1811 }
1812 else {
1813 if(playlist_is_visible())
1814 if(gui->use_root_window)
1815 playlist_toggle_visibility(NULL, NULL);
1816 else
1817 playlist_exit(NULL, NULL);
1818 else
1819 playlist_toggle_visibility(NULL, NULL);
1820 }
1821
1822 }
1823
gui_mrlbrowser_show(xitk_widget_t * w,void * data)1824 void gui_mrlbrowser_show(xitk_widget_t *w, void *data) {
1825 gGui_t *gui = gGui;
1826
1827 gui->nongui_error_msg = NULL;
1828
1829 if (!mrl_browser_is_running (gui->mrlb)) {
1830 open_mrlbrowser (NULL, gui);
1831 }
1832 else {
1833
1834 if (!mrl_browser_is_visible (gui->mrlb)) {
1835 show_mrl_browser (gui->mrlb);
1836 if(!gui->use_root_window)
1837 set_mrl_browser_transient (gui->mrlb);
1838 }
1839 else {
1840 if(gui->use_root_window)
1841 show_mrl_browser (gui->mrlb);
1842 else
1843 destroy_mrl_browser (gui->mrlb);
1844 }
1845
1846 }
1847
1848 }
1849
gui_set_current_mmk(mediamark_t * mmk)1850 void gui_set_current_mmk(mediamark_t *mmk) {
1851 gGui_t *gui = gGui;
1852
1853 pthread_mutex_lock(&gui->mmk_mutex);
1854 set_mmk(mmk);
1855 pthread_mutex_unlock(&gui->mmk_mutex);
1856
1857 mmk_set_update();
1858 }
1859
gui_set_current_mmk_by_index(int idx)1860 void gui_set_current_mmk_by_index(int idx) {
1861 gGui_t *gui = gGui;
1862
1863 pthread_mutex_lock(&gui->mmk_mutex);
1864 set_mmk(mediamark_get_mmk_by_index(idx));
1865 gui->playlist.cur = idx;
1866 pthread_mutex_unlock(&gui->mmk_mutex);
1867
1868 mmk_set_update();
1869 }
1870
gui_control_show(xitk_widget_t * w,void * data)1871 void gui_control_show(xitk_widget_t *w, void *data) {
1872 gGui_t *gui = gGui;
1873
1874 control_toggle_window (w, gui->vctrl);
1875 }
1876
gui_setup_show(xitk_widget_t * w,void * data)1877 void gui_setup_show(xitk_widget_t *w, void *data) {
1878 gGui_t *gui = gGui;
1879
1880 if (setup_is_running (gui->setup) && !setup_is_visible (gui->setup))
1881 setup_toggle_visibility (NULL, gui->setup);
1882 else if (!setup_is_running (gui->setup))
1883 setup_panel (gui);
1884 else {
1885 if(gui->use_root_window)
1886 setup_toggle_visibility (NULL, gui->setup);
1887 else
1888 setup_end (gui->setup);
1889 }
1890 }
1891
gui_event_sender_show(xitk_widget_t * w,void * data)1892 void gui_event_sender_show(xitk_widget_t *w, void *data) {
1893 gGui_t *gui = gGui;
1894
1895 if (event_sender_is_running() && !event_sender_is_visible())
1896 event_sender_toggle_visibility(NULL, NULL);
1897 else if(!event_sender_is_running())
1898 event_sender_panel();
1899 else {
1900 if(gui->use_root_window)
1901 event_sender_toggle_visibility(NULL, NULL);
1902 else
1903 event_sender_end();
1904 }
1905 }
1906
gui_stream_infos_show(xitk_widget_t * w,void * data)1907 void gui_stream_infos_show(xitk_widget_t *w, void *data) {
1908 gGui_t *gui = gGui;
1909
1910 if (stream_infos_is_running() && !stream_infos_is_visible())
1911 stream_infos_toggle_visibility(NULL, NULL);
1912 else if(!stream_infos_is_running())
1913 stream_infos_panel();
1914 else {
1915 if(gui->use_root_window)
1916 stream_infos_toggle_visibility(NULL, NULL);
1917 else
1918 stream_infos_end();
1919 }
1920 }
1921
gui_tvset_show(xitk_widget_t * w,void * data)1922 void gui_tvset_show(xitk_widget_t *w, void *data) {
1923 gGui_t *gui = gGui;
1924
1925 if (tvset_is_running() && !tvset_is_visible())
1926 tvset_toggle_visibility(NULL, NULL);
1927 else if(!tvset_is_running())
1928 tvset_panel();
1929 else {
1930 if(gui->use_root_window)
1931 tvset_toggle_visibility(NULL, NULL);
1932 else
1933 tvset_end();
1934 }
1935 }
1936
gui_vpp_show(xitk_widget_t * w,void * data)1937 void gui_vpp_show(xitk_widget_t *w, void *data) {
1938 gGui_t *gui = gGui;
1939
1940 if (vpplugin_is_running() && !vpplugin_is_visible())
1941 vpplugin_toggle_visibility(NULL, NULL);
1942 else if(!vpplugin_is_running())
1943 vpplugin_panel();
1944 else {
1945 if(gui->use_root_window)
1946 vpplugin_toggle_visibility(NULL, NULL);
1947 else
1948 vpplugin_end();
1949 }
1950 }
1951
gui_vpp_enable(void)1952 void gui_vpp_enable(void) {
1953 gGui_t *gui = gGui;
1954
1955 if(vpplugin_is_post_selected()) {
1956 gui->post_video_enable = !gui->post_video_enable;
1957 osd_display_info(_("Video post plugins: %s."), (gui->post_video_enable) ? _("enabled") : _("disabled"));
1958 vpplugin_update_enable_button();
1959 if(vpplugin_is_visible())
1960 vpplugin_rewire_from_posts_window();
1961 else
1962 vpplugin_rewire_posts();
1963 }
1964 }
1965
gui_viewlog_show(xitk_widget_t * w,void * data)1966 void gui_viewlog_show(xitk_widget_t *w, void *data) {
1967 gGui_t *gui = gGui;
1968
1969 if (viewlog_is_running() && !viewlog_is_visible())
1970 viewlog_toggle_visibility(NULL, NULL);
1971 else if(!viewlog_is_running())
1972 viewlog_panel();
1973 else {
1974 if(gui->use_root_window)
1975 viewlog_toggle_visibility(NULL, NULL);
1976 else
1977 viewlog_end();
1978 }
1979 }
1980
gui_kbedit_show(xitk_widget_t * w,void * data)1981 void gui_kbedit_show(xitk_widget_t *w, void *data) {
1982 gGui_t *gui = gGui;
1983
1984 if (kbedit_is_running() && !kbedit_is_visible())
1985 kbedit_toggle_visibility(NULL, NULL);
1986 else if(!kbedit_is_running())
1987 kbedit_window();
1988 else {
1989 if(gui->use_root_window)
1990 kbedit_toggle_visibility(NULL, NULL);
1991 else
1992 kbedit_end();
1993 }
1994 }
1995
gui_help_show(xitk_widget_t * w,void * data)1996 void gui_help_show(xitk_widget_t *w, void *data) {
1997 gGui_t *gui = gGui;
1998
1999 if (help_is_running() && !help_is_visible())
2000 help_toggle_visibility(NULL, NULL);
2001 else if(!help_is_running())
2002 help_panel();
2003 else {
2004 if(gui->use_root_window)
2005 help_toggle_visibility(NULL, NULL);
2006 else
2007 help_end();
2008 }
2009 }
2010
2011 /*
2012 * Return 1 if layer should be set
2013 */
is_layer_above(void)2014 int is_layer_above(void) {
2015 gGui_t *gui = gGui;
2016
2017 return (gui->always_layer_above || gui->layer_above) ? 1 : 0;
2018 }
2019 /*
2020 * set window layer property to something above GNOME (and KDE?) panel
2021 * (reset to normal if do_raise == 0)
2022 */
layer_above_video(Window w)2023 void layer_above_video(Window w) {
2024 int layer = 10;
2025
2026 if(!(is_layer_above()))
2027 return;
2028
2029 if ((!(video_window_get_fullscreen_mode (gGui->vwin) & WINDOWED_MODE)) && video_window_is_visible (gGui->vwin)) {
2030 layer = xitk_get_layer_level();
2031 }
2032 else {
2033 if(is_layer_above())
2034 layer = xitk_get_layer_level();
2035 else
2036 layer = 4;
2037 }
2038
2039 xitk_set_window_layer(w, layer);
2040 }
2041
change_amp_vol(int value)2042 void change_amp_vol(int value) {
2043 gGui_t *gui = gGui;
2044 if(value < 0)
2045 value = 0;
2046 if(value > 200)
2047 value = 200;
2048 gui->mixer.amp_level = value;
2049 xine_set_param(gui->stream, XINE_PARAM_AUDIO_AMP_LEVEL, gui->mixer.amp_level);
2050 panel_update_mixer_display (gui->panel);
2051 osd_draw_bar(_("Amplification Level"), 0, 200, gui->mixer.amp_level, OSD_BAR_STEPPER);
2052 }
gui_increase_amp_level(void)2053 void gui_increase_amp_level(void) {
2054 gGui_t *gui = gGui;
2055 change_amp_vol((gui->mixer.amp_level + 1));
2056 }
gui_decrease_amp_level(void)2057 void gui_decrease_amp_level(void) {
2058 gGui_t *gui = gGui;
2059 change_amp_vol((gui->mixer.amp_level - 1));
2060 }
gui_reset_amp_level(void)2061 void gui_reset_amp_level(void) {
2062 change_amp_vol(100);
2063 }
2064
change_audio_vol(int value)2065 void change_audio_vol(int value) {
2066 gGui_t *gui = gGui;
2067 if(value < 0)
2068 value = 0;
2069 if(value > 100)
2070 value = 100;
2071 gui->mixer.volume_level = value;
2072 xine_set_param(gui->stream, XINE_PARAM_AUDIO_VOLUME, gui->mixer.volume_level);
2073 panel_update_mixer_display (gui->panel);
2074 osd_draw_bar(_("Audio Volume"), 0, 100, gui->mixer.volume_level, OSD_BAR_STEPPER);
2075 }
gui_increase_audio_volume(void)2076 void gui_increase_audio_volume(void) {
2077 gGui_t *gui = gGui;
2078 if((gui->mixer.method == SOUND_CARD_MIXER) && (gui->mixer.caps & MIXER_CAP_VOL))
2079 change_audio_vol((gui->mixer.volume_level + 1));
2080 else if(gui->mixer.method == SOFTWARE_MIXER)
2081 gui_increase_amp_level();
2082 }
gui_decrease_audio_volume(void)2083 void gui_decrease_audio_volume(void) {
2084 gGui_t *gui = gGui;
2085 if((gui->mixer.method == SOUND_CARD_MIXER) && (gui->mixer.caps & MIXER_CAP_VOL))
2086 change_audio_vol((gui->mixer.volume_level - 1));
2087 else if(gui->mixer.method == SOFTWARE_MIXER)
2088 gui_decrease_amp_level();
2089 }
2090
gui_app_show(xitk_widget_t * w,void * data)2091 void gui_app_show(xitk_widget_t *w, void *data) {
2092 gGui_t *gui = gGui;
2093
2094 if (applugin_is_running() && !applugin_is_visible())
2095 applugin_toggle_visibility(NULL, NULL);
2096 else if(!applugin_is_running())
2097 applugin_panel();
2098 else {
2099 if(gui->use_root_window)
2100 applugin_toggle_visibility(NULL, NULL);
2101 else
2102 applugin_end();
2103 }
2104 }
2105
gui_app_enable(void)2106 void gui_app_enable(void) {
2107 gGui_t *gui = gGui;
2108
2109 if(applugin_is_post_selected()) {
2110 gui->post_audio_enable = !gui->post_audio_enable;
2111 osd_display_info(_("Audio post plugins: %s."), (gui->post_audio_enable) ? _("enabled") : _("disabled"));
2112 applugin_update_enable_button();
2113 if(applugin_is_visible())
2114 applugin_rewire_from_posts_window();
2115 else
2116 applugin_rewire_posts();
2117 }
2118 }
2119
gui_change_zoom(int zoom_dx,int zoom_dy)2120 void gui_change_zoom(int zoom_dx, int zoom_dy) {
2121 gGui_t *gui = gGui;
2122
2123 xine_set_param(gui->stream, XINE_PARAM_VO_ZOOM_X,
2124 xine_get_param(gui->stream, XINE_PARAM_VO_ZOOM_X) + zoom_dx);
2125 xine_set_param(gui->stream, XINE_PARAM_VO_ZOOM_Y,
2126 xine_get_param(gui->stream, XINE_PARAM_VO_ZOOM_Y) + zoom_dy);
2127
2128 if (panel_is_visible (gui->panel)) {
2129 gui->x_lock_display (gui->display);
2130 XRaiseWindow(gui->display, gui->panel_window);
2131 gui->x_unlock_display (gui->display);
2132 video_window_set_transient_for (gui->vwin, gui->panel_window);
2133 }
2134 }
2135
2136 /*
2137 * Reset zooming by recall aspect ratio.
2138 */
gui_reset_zoom(void)2139 void gui_reset_zoom(void) {
2140 gGui_t *gui = gGui;
2141
2142 xine_set_param(gui->stream, XINE_PARAM_VO_ZOOM_X, 100);
2143 xine_set_param(gui->stream, XINE_PARAM_VO_ZOOM_Y, 100);
2144
2145 if (panel_is_visible (gui->panel)) {
2146 gui->x_lock_display (gui->display);
2147 XRaiseWindow(gui->display, gui->panel_window);
2148 gui->x_unlock_display (gui->display);
2149 video_window_set_transient_for (gui->vwin, gui->panel_window);
2150 }
2151 }
2152
2153 /*
2154 * Toggle TV Modes on the dxr3
2155 */
gui_toggle_tvmode(void)2156 void gui_toggle_tvmode(void) {
2157 gGui_t *gui = gGui;
2158
2159 xine_set_param(gui->stream, XINE_PARAM_VO_TVMODE,
2160 xine_get_param(gui->stream, XINE_PARAM_VO_TVMODE) + 1);
2161
2162 osd_display_info(_("TV Mode: %d"), xine_get_param(gui->stream, XINE_PARAM_VO_TVMODE));
2163 }
2164
2165 /*
2166 * Send an Expose event to given window.
2167 */
gui_send_expose_to_window(Window window)2168 void gui_send_expose_to_window(Window window) {
2169 gGui_t *gui = gGui;
2170 XEvent xev;
2171
2172 if(window == None)
2173 return;
2174
2175 xev.xany.type = Expose;
2176 xev.xexpose.type = Expose;
2177 xev.xexpose.send_event = True;
2178 xev.xexpose.display = gui->display;
2179 xev.xexpose.window = window;
2180 xev.xexpose.count = 0;
2181
2182 gui->x_lock_display (gui->display);
2183 if(!XSendEvent(gui->display, window, False, ExposureMask, &xev)) {
2184 fprintf(stderr, _("XSendEvent(display, 0x%x ...) failed.\n"), (unsigned int) window);
2185 }
2186 XSync(gui->display, False);
2187 gui->x_unlock_display (gui->display);
2188
2189 }
2190
gui_add_mediamark(void)2191 void gui_add_mediamark(void) {
2192 gGui_t *gui = gGui;
2193
2194 if((gui->logo_mode == 0) && (xine_get_status(gui->stream) == XINE_STATUS_PLAY)) {
2195 int secs;
2196
2197 if(gui_xine_get_pos_length(gui->stream, NULL, &secs, NULL)) {
2198 secs /= 1000;
2199
2200 mediamark_append_entry(gui->mmk.mrl, gui->mmk.ident,
2201 gui->mmk.sub, secs, -1, gui->mmk.av_offset, gui->mmk.spu_offset);
2202 playlist_update_playlist();
2203 }
2204 }
2205 }
2206
fileselector_cancel_callback(filebrowser_t * fb)2207 static void fileselector_cancel_callback(filebrowser_t *fb) {
2208 gGui_t *gui = gGui;
2209 char *cur_dir = filebrowser_get_current_dir(fb);
2210
2211 if (fb == gui->load_stream) {
2212 if(cur_dir && strlen(cur_dir)) {
2213 strlcpy(gui->curdir, cur_dir, sizeof(gui->curdir));
2214 config_update_string("media.files.origin_path", gui->curdir);
2215 }
2216 gui->load_stream = NULL;
2217 }
2218 else if (fb == gui->load_sub)
2219 gui->load_sub = NULL;
2220
2221 free(cur_dir);
2222 }
2223
2224
2225 /* Callback function for file select button or double-click in file browser.
2226 Append selected file to the current playlist */
fileselector_callback(filebrowser_t * fb)2227 static void fileselector_callback(filebrowser_t *fb) {
2228 gGui_t *gui = gGui;
2229 char *file;
2230 char *cur_dir = filebrowser_get_current_dir(fb);
2231
2232 /* Upate configuration with the selected directory path */
2233 if(cur_dir && strlen(cur_dir)) {
2234 strlcpy(gui->curdir, cur_dir, sizeof(gui->curdir));
2235 config_update_string("media.files.origin_path", gui->curdir);
2236 }
2237 free(cur_dir);
2238
2239 /* Get the file path/name */
2240 if(((file = filebrowser_get_full_filename(fb)) != NULL) && strlen(file)) {
2241 int first = gui->playlist.num;
2242 char *ident;
2243
2244 /* Get the name only to use as an identifier in the playlist display */
2245 ident = filebrowser_get_current_filename(fb);
2246
2247 /* If the file has an extension which could be a playlist, attempt to append
2248 it to the current list as a list; otherwise, append it as an ordinary file. */
2249 if(mrl_look_like_playlist(file)) {
2250 if(!mediamark_concat_mediamarks(file))
2251 mediamark_append_entry(file, ident, NULL, 0, -1, 0, 0);
2252 }
2253 else
2254 mediamark_append_entry(file, ident, NULL, 0, -1, 0, 0);
2255
2256 playlist_update_playlist();
2257 free(ident);
2258
2259 /* Enable controls on display */
2260 if ((!is_playback_widgets_enabled (gui->panel)) && gui->playlist.num)
2261 enable_playback_controls (gui->panel, 1);
2262
2263 /* If an MRL is not being played, select the first file appended. If in "smart mode" start
2264 playing the entry. If a an MRL is currently being played, let it continue normally */
2265 if((first != gui->playlist.num) &&
2266 (gui->logo_mode || (xine_get_status(gui->stream) == XINE_STATUS_STOP))) {
2267 gui->playlist.cur = first;
2268 if(gui->smart_mode) {
2269 gui_set_current_mmk(mediamark_get_current_mmk());
2270 gui_play (NULL, gui);
2271 }
2272 }
2273 } /* If valid file name */
2274
2275 free(file);
2276 gui->load_stream = NULL;
2277 }
2278
2279
2280 /* Callback function for "Select All" button in file browser. Append all files in the
2281 currently selected directory to the current playlist. */
fileselector_all_callback(filebrowser_t * fb)2282 static void fileselector_all_callback(filebrowser_t *fb) {
2283 gGui_t *gui = gGui;
2284 char **files;
2285 char *path = filebrowser_get_current_dir(fb);
2286
2287 /* Update the configuration with the current path */
2288 if(path && strlen(path)) {
2289 strlcpy(gui->curdir, path, sizeof(gui->curdir));
2290 config_update_string("media.files.origin_path", gui->curdir);
2291 }
2292
2293 /* Get all of the file names in the current directory as an array of pointers to strings */
2294 if((files = filebrowser_get_all_files(fb)) != NULL) {
2295 int i = 0;
2296
2297 if(path && strlen(path)) {
2298 char pathname[XITK_PATH_MAX + 1 + 1]; /* +1 for trailing '/' */
2299 char fullfilename[XITK_PATH_MAX + XITK_NAME_MAX + 2];
2300 int first = gui->playlist.num; /* current count of entries in playlist */
2301
2302 /* If the path is anything other than "/", append a slash to it so that it can
2303 be concatenated with the file name */
2304 if(strcasecmp(path, "/"))
2305 snprintf(pathname, sizeof(pathname), "%s/", path);
2306 else
2307 strlcpy(pathname, path, sizeof(pathname));
2308
2309 /* For each file, concatenate the path with the name and append it to the playlist */
2310 while(files[i]) {
2311 snprintf(fullfilename, sizeof(fullfilename), "%s%s", pathname, files[i]);
2312
2313 /* If the file has an extension which could be a playlist, attempt to append
2314 it to the current list as a list; otherwise, append it as an ordinary file. */
2315 if(mrl_look_like_playlist(fullfilename)) {
2316 if(!mediamark_concat_mediamarks(fullfilename))
2317 mediamark_append_entry(fullfilename, files[i], NULL, 0, -1, 0, 0);
2318 }
2319 else
2320 mediamark_append_entry(fullfilename, files[i], NULL, 0, -1, 0, 0);
2321
2322 i++;
2323 } /* End while */
2324
2325 playlist_update_playlist();
2326
2327 /* Enable playback controls on display */
2328 if ((!is_playback_widgets_enabled (gui->panel)) && gui->playlist.num)
2329 enable_playback_controls (gui->panel, 1);
2330
2331 /* If an MRL is not being played, select the first file appended. If in "smart mode" start
2332 playing the entry. If an MRL is currently being played, let it continue normally */
2333 if((first != gui->playlist.num) && (xine_get_status(gui->stream) == XINE_STATUS_STOP)) {
2334 gui->playlist.cur = first;
2335 if(gui->smart_mode) {
2336 gui_set_current_mmk(mediamark_get_current_mmk());
2337 gui_play (NULL, gui);
2338 }
2339 }
2340 } /* If valid path */
2341
2342 i = 0;
2343 while(files[i])
2344 free(files[i++]);
2345
2346 free(files);
2347 } /* If valid file list */
2348
2349 free(path);
2350
2351 gui->load_stream = NULL;
2352 }
2353
2354
gui_file_selector(void)2355 void gui_file_selector(void) {
2356 gGui_t *gui = gGui;
2357 filebrowser_callback_button_t cbb[3];
2358
2359 gui->nongui_error_msg = NULL;
2360
2361 if (gui->load_stream)
2362 filebrowser_raise_window (gui->load_stream);
2363 else {
2364 cbb[0].label = _("Select");
2365 cbb[0].callback = fileselector_callback;
2366 cbb[0].need_a_file = 0;
2367 cbb[1].label = _("Select all");
2368 cbb[1].callback = fileselector_all_callback;
2369 cbb[1].need_a_file = 0;
2370 cbb[2].callback = fileselector_cancel_callback;
2371 cbb[2].need_a_file = 0;
2372 gui->load_stream = create_filebrowser(_("Stream(s) Loading"), gui->curdir, hidden_file_cb, &cbb[0], &cbb[1], &cbb[2]);
2373 }
2374 }
2375
subselector_callback(filebrowser_t * fb)2376 static void subselector_callback(filebrowser_t *fb) {
2377 gGui_t *gui = gGui;
2378 char *file;
2379 int ret;
2380
2381 if((file = filebrowser_get_full_filename(fb)) != NULL) {
2382 if(file) {
2383 mediamark_t *mmk = mediamark_clone_mmk(mediamark_get_current_mmk());
2384
2385 if(mmk) {
2386 mediamark_replace_entry(&gui->playlist.mmk[gui->playlist.cur], mmk->mrl, mmk->ident,
2387 file, mmk->start, mmk->end, mmk->av_offset, mmk->spu_offset);
2388 mediamark_free_mmk(&mmk);
2389
2390 mmk = mediamark_get_current_mmk();
2391 gui_set_current_mmk(mmk);
2392
2393 playlist_mrlident_toggle();
2394
2395 if(xine_get_status(gui->stream) == XINE_STATUS_PLAY) {
2396 int curpos;
2397 xine_close (gui->spu_stream);
2398
2399 gui_messages_off (gui);
2400 ret = xine_open(gui->spu_stream, mmk->sub);
2401 gui_messages_on (gui);
2402 if (ret)
2403 xine_stream_master_slave(gui->stream,
2404 gui->spu_stream, XINE_MASTER_SLAVE_PLAY | XINE_MASTER_SLAVE_STOP);
2405
2406 if(gui_xine_get_pos_length(gui->stream, &curpos, NULL, NULL)) {
2407 xine_stop(gui->stream);
2408 gui_set_current_position(curpos);
2409 }
2410 }
2411 }
2412 }
2413 free(file);
2414 }
2415
2416 gui->load_sub = NULL;
2417 }
2418
gui_select_sub(void)2419 void gui_select_sub(void) {
2420 gGui_t *gui = gGui;
2421
2422 if(gui->playlist.num) {
2423 if (gui->load_sub)
2424 filebrowser_raise_window (gui->load_sub);
2425 else {
2426 filebrowser_callback_button_t cbb[2];
2427 mediamark_t *mmk;
2428
2429 mmk = mediamark_get_current_mmk();
2430
2431 if(mmk) {
2432 char *path, *open_path;
2433
2434 cbb[0].label = _("Select");
2435 cbb[0].callback = subselector_callback;
2436 cbb[0].need_a_file = 1;
2437 cbb[1].callback = fileselector_cancel_callback;
2438 cbb[1].need_a_file = 0;
2439
2440 path = mmk->sub ? mmk->sub : mmk->mrl;
2441
2442 if(mrl_look_like_file(path)) {
2443 char *p;
2444
2445 open_path = strdup(path);
2446
2447 if(!strncasecmp(path, "file:", 5))
2448 path += 5;
2449
2450 p = strrchr(open_path, '/');
2451 if (p && strlen(p))
2452 *p = '\0';
2453 }
2454 else
2455 open_path = strdup(gui->curdir);
2456
2457 gui->load_sub = create_filebrowser(_("Pick a subtitle file"), open_path, hidden_file_cb, &cbb[0], NULL, &cbb[1]);
2458 free(open_path);
2459 }
2460 }
2461 }
2462 }
2463
2464 /*
2465 *
2466 */
visual_anim_init(void)2467 void visual_anim_init(void) {
2468 gGui_t *gui = gGui;
2469 char *buffer;
2470
2471 buffer = xitk_asprintf("%s/%s", XINE_VISDIR, "default.mpv");
2472
2473 gui->visual_anim.mrls = (char **) malloc(sizeof(char *) * 3);
2474 gui->visual_anim.num_mrls = 0;
2475
2476 if (buffer) {
2477 gui->visual_anim.mrls[gui->visual_anim.num_mrls++] = buffer;
2478 gui->visual_anim.mrls[gui->visual_anim.num_mrls] = NULL;
2479 gui->visual_anim.mrls[gui->visual_anim.num_mrls + 1] = NULL;
2480 }
2481 }
visual_anim_done(void)2482 void visual_anim_done(void) {
2483 gGui_t *gui = gGui;
2484 int i;
2485
2486 for (i = 0; i < gui->visual_anim.num_mrls; i++) free(gui->visual_anim.mrls[i]);
2487 free(gui->visual_anim.mrls);
2488 }
visual_anim_add_animation(char * mrl)2489 void visual_anim_add_animation(char *mrl) {
2490 gGui_t *gui = gGui;
2491 gui->visual_anim.mrls = (char **) realloc(gui->visual_anim.mrls, sizeof(char *) *
2492 ((gui->visual_anim.num_mrls + 1) + 2));
2493
2494 gui->visual_anim.mrls[gui->visual_anim.num_mrls++] = strdup(mrl);
2495 gui->visual_anim.mrls[gui->visual_anim.num_mrls] = NULL;
2496 gui->visual_anim.mrls[gui->visual_anim.num_mrls + 1] = NULL;
2497 }
visual_anim_open_and_play(xine_stream_t * stream,const char * mrl)2498 static int visual_anim_open_and_play(xine_stream_t *stream, const char *mrl) {
2499 if((!xine_open(stream, mrl)) || (!xine_play(stream, 0, 0)))
2500 return 0;
2501
2502 return 1;
2503 }
visual_anim_play(void)2504 void visual_anim_play(void) {
2505 gGui_t *gui = gGui;
2506 if(gui->visual_anim.enabled == 2) {
2507 if(!visual_anim_open_and_play(gui->visual_anim.stream,
2508 gui->visual_anim.mrls[gui->visual_anim.current]))
2509 gui_handle_xine_error(gui->visual_anim.stream,
2510 gui->visual_anim.mrls[gui->visual_anim.current]);
2511 gui->visual_anim.running = 1;
2512 }
2513 }
visual_anim_play_next(void)2514 void visual_anim_play_next(void) {
2515 gGui_t *gui = gGui;
2516 if(gui->visual_anim.enabled == 2) {
2517 gui->visual_anim.current++;
2518 if(gui->visual_anim.mrls[gui->visual_anim.current] == NULL)
2519 gui->visual_anim.current = 0;
2520 visual_anim_play();
2521 }
2522 }
visual_anim_stop(void)2523 void visual_anim_stop(void) {
2524 gGui_t *gui = gGui;
2525 if(gui->visual_anim.enabled == 2) {
2526 xine_stop(gui->visual_anim.stream);
2527 gui->visual_anim.running = 0;
2528 }
2529 }
2530
2531