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 * xine engine error handling/notification
21 *
22 */
23 #ifdef HAVE_CONFIG_H
24 #include "config.h"
25 #endif
26
27 #include <stdio.h>
28 #include <stdarg.h>
29
30 #include <X11/Xlib.h>
31 #include <X11/Xutil.h>
32 #include <X11/keysym.h>
33
34 #include "common.h"
35
36
37 /*
38 * Callback used to display the viewlog window.
39 */
_errors_display_log(xitk_widget_t * w,void * data,int state)40 static void _errors_display_log(xitk_widget_t *w, void *data, int state) {
41
42 if(viewlog_is_visible())
43 viewlog_raise_window();
44 else
45 viewlog_panel();
46 }
47
48 /*
49 * Create the real window.
50 */
errors_create_window(char * title,char * message)51 static void errors_create_window(char *title, char *message) {
52 xitk_window_t *xw;
53
54 if((title == NULL) || (message == NULL))
55 return;
56
57 dump_error(message);
58
59 if( gGui->nongui_error_msg ) {
60 gGui->nongui_error_msg( message );
61 return;
62 }
63
64 xw = xitk_window_dialog_two_buttons_with_width(gGui->imlib_data, title,
65 _("Done"), _("More..."),
66 NULL, _errors_display_log,
67 NULL, 400, ALIGN_CENTER,
68 "%s", message);
69
70 xitk_window_set_parent_window(xw, gGui->video_window);
71
72 if(!gGui->use_root_window && gGui->video_display == gGui->display) {
73 gGui->x_lock_display (gGui->display);
74 XSetTransientForHint(gGui->display, xitk_window_get_window(xw), gGui->video_window);
75 gGui->x_unlock_display (gGui->display);
76 }
77
78 layer_above_video(xitk_window_get_window(xw));
79 }
80
81 /*
82 * Display an error window.
83 */
xine_error(const char * message,...)84 void xine_error(const char *message, ...) {
85 va_list args;
86 char *buf;
87
88 va_start(args, message);
89 buf = xitk_vasprintf(message, args);
90 va_end(args);
91
92 if (!buf)
93 return;
94
95 if(gGui->stdctl_enable || !gGui->display) {
96 printf("%s\n", buf);
97 }
98 else {
99 dump_error(buf);
100
101 if( gGui->nongui_error_msg ) {
102 gGui->nongui_error_msg( buf );
103 } else {
104 xitk_window_t *xw;
105
106 xw = xitk_window_dialog_error(gGui->imlib_data, "%s", buf);
107
108 if(!gGui->use_root_window && gGui->video_display == gGui->display) {
109 gGui->x_lock_display (gGui->display);
110 XSetTransientForHint(gGui->display, xitk_window_get_window(xw), gGui->video_window);
111 gGui->x_unlock_display (gGui->display);
112 }
113 layer_above_video(xitk_window_get_window(xw));
114 }
115 }
116
117 free(buf);
118 }
119
120 /*
121 * Display an error window, with more button.
122 */
xine_error_with_more(const char * message,...)123 void xine_error_with_more(const char *message, ...) {
124 va_list args;
125 char *buf;
126
127 va_start(args, message);
128 buf = xitk_vasprintf(message, args);
129 va_end(args);
130
131 if (!buf)
132 return;
133
134 dump_error(buf);
135
136 if(gGui->stdctl_enable) {
137 printf("%s\n", buf);
138 }
139 else {
140 errors_create_window(_("Error"), buf);
141 }
142
143 free(buf);
144 }
145
146 /*
147 * Display an informative window.
148 */
xine_info(const char * message,...)149 void xine_info(const char *message, ...) {
150 va_list args;
151 char *buf;
152
153 va_start(args, message);
154 buf = xitk_vasprintf(message, args);
155 va_end(args);
156
157 if (!buf)
158 return;
159
160 dump_info(buf);
161
162 if(gGui->stdctl_enable) {
163 printf("%s\n", buf);
164 }
165 else {
166 if( gGui->nongui_error_msg ) {
167 gGui->nongui_error_msg( buf );
168 } else {
169 xitk_window_t *xw;
170
171 xw = xitk_window_dialog_info(gGui->imlib_data, "%s", buf);
172
173 if(!gGui->use_root_window && gGui->video_display == gGui->display) {
174 gGui->x_lock_display (gGui->display);
175 XSetTransientForHint(gGui->display, xitk_window_get_window(xw), gGui->video_window);
176 gGui->x_unlock_display (gGui->display);
177 }
178 layer_above_video(xitk_window_get_window(xw));
179 }
180 }
181
182 free(buf);
183 }
184
185 /*
186 * Display an error window error from a xine engine error.
187 */
gui_handle_xine_error(xine_stream_t * stream,const char * mrl)188 void gui_handle_xine_error(xine_stream_t *stream, const char *mrl) {
189 int err;
190 const char *_mrl = mrl;
191
192 if(_mrl == NULL)
193 _mrl = (stream == gGui->stream) ? gGui->mmk.mrl : gGui->visual_anim.mrls[gGui->visual_anim.current];
194
195 err = xine_get_error(stream);
196
197 switch(err) {
198
199 case XINE_ERROR_NONE:
200 dump_error("got XINE_ERROR_NONE.");
201 /* noop */
202 break;
203
204 case XINE_ERROR_NO_INPUT_PLUGIN:
205 dump_error("got XINE_ERROR_NO_INPUT_PLUGIN.");
206 xine_error_with_more(_("- xine engine error -\n\n"
207 "There is no input plugin available to handle '%s'.\n"
208 "Maybe MRL syntax is wrong or file/stream source doesn't exist."),
209 _mrl);
210 break;
211
212 case XINE_ERROR_NO_DEMUX_PLUGIN:
213 dump_error("got XINE_ERROR_NO_DEMUX_PLUGIN.");
214 xine_error_with_more(_("- xine engine error -\n\nThere is no demuxer plugin available "
215 "to handle '%s'.\n"
216 "Usually this means that the file format was not recognized."),
217 _mrl);
218 break;
219
220 case XINE_ERROR_DEMUX_FAILED:
221 dump_error("got XINE_ERROR_DEMUX_FAILED.");
222 xine_error_with_more(_("- xine engine error -\n\nDemuxer failed. "
223 "Maybe '%s' is a broken file?\n"), _mrl);
224 break;
225
226 case XINE_ERROR_MALFORMED_MRL:
227 dump_error("got XINE_ERROR_MALFORMED_MRL.");
228 xine_error_with_more(_("- xine engine error -\n\nMalformed mrl. "
229 "Mrl '%s' seems malformed/invalid.\n"), _mrl);
230 break;
231
232 case XINE_ERROR_INPUT_FAILED:
233 dump_error("got XINE_ERROR_INPUT_FAILED.");
234 xine_error_with_more(_("- xine engine error -\n\nInput plugin failed to open "
235 "mrl '%s'\n"), _mrl);
236 break;
237
238 default:
239 dump_error("got unhandle error.");
240 xine_error_with_more(_("- xine engine error -\n\n!! Unhandled error !!\n"));
241 break;
242 }
243
244 /* gGui->new_pos = -1; */
245 }
246
247
_dont_show_too_slow_again(xitk_widget_t * w,void * data,int state)248 static void _dont_show_too_slow_again(xitk_widget_t *w, void *data, int state) {
249 config_update_num ("gui.dropped_frames_warning", !state);
250 }
251
_learn_more_about_too_slow(xitk_widget_t * w,void * data,int state)252 static void _learn_more_about_too_slow(xitk_widget_t *w, void *data, int state) {
253 /*
254 * fixme: how to properly open the system browser?
255 * should we just make it configurable?
256 */
257 xine_info(_("Opening mozilla web browser, this might take a while..."));
258 system ("mozilla http://www.xine-project.org/faq#SPEEDUP");
259 }
260
261 /*
262 * Create the real window.
263 */
too_slow_window(void)264 void too_slow_window(void) {
265 xitk_window_t *xw;
266 char *title, *message;
267 int display_warning;
268 int checked = 0;
269
270 title = _("Warning");
271 message = _("The amount of dropped frame is too high, your system might be slow, not properly optimized or just too loaded.\n\nhttp://www.xine-project.org/faq#SPEEDUP");
272
273 dump_error(message);
274
275 display_warning = xine_config_register_bool (__xineui_global_xine_instance, "gui.dropped_frames_warning",
276 1,
277 _("Warn user when too much frames are dropped."),
278 CONFIG_NO_HELP,
279 CONFIG_LEVEL_ADV,
280 CONFIG_NO_CB,
281 CONFIG_NO_DATA);
282
283 if( !display_warning )
284 return;
285
286 if( gGui->nongui_error_msg || gGui->stdctl_enable )
287 return;
288
289 _dont_show_too_slow_again(NULL, NULL, checked);
290
291 xw = xitk_window_dialog_checkbox_two_buttons_with_width(gGui->imlib_data, title,
292 _("Done"), _("Learn More..."),
293 NULL, _learn_more_about_too_slow,
294 _("Disable this warning."),
295 checked, _dont_show_too_slow_again,
296 NULL, 500, ALIGN_CENTER,
297 "%s", message);
298 if(!gGui->use_root_window && gGui->video_display == gGui->display) {
299 gGui->x_lock_display (gGui->display);
300 XSetTransientForHint(gGui->display, xitk_window_get_window(xw), gGui->video_window);
301 gGui->x_unlock_display (gGui->display);
302 }
303 layer_above_video(xitk_window_get_window(xw));
304 }
305