57
55
* always start xine engine from a seperate thread so the gui stays responsive
60
static int goto_pos, goto_time;
58
static int goto_pos, goto_time, end_time;
61
59
static pthread_t play_thread;
62
60
static char *cur_mrl = NULL, *cur_title = NULL;
62
static gboolean demuxer_for_logo = TRUE;
64
static int play_exec_error_suppress = 0;
66
void play_exec_error_suppress_next (void)
68
++play_exec_error_suppress;
71
static void play_exec_error (void)
73
if (play_exec_error_suppress)
75
#ifdef XINE_PARAM_GAPLESS_SWITCH
76
xine_set_param (stream, XINE_PARAM_GAPLESS_SWITCH, 0);
78
--play_exec_error_suppress;
83
switch (error = xine_get_error (stream))
85
case XINE_ERROR_NO_INPUT_PLUGIN:
86
display_error (FROM_XINE, _("The xine engine failed to start."),
87
_("No input plugin was found.\n"
88
"Maybe the file does not exist or cannot be accessed, "
89
"or there is an error in the URL."));
92
case XINE_ERROR_NO_DEMUX_PLUGIN:
93
if (playlist_showing_logo ())
95
g_idle_add (infobar_show_metadata, infobars);
98
demuxer_for_logo = FALSE;
99
display_error (FROM_XINE,
100
_("Whoops. You seem to have a broken xine-lib."),
101
_("No demuxer found - stream format not recognised."));
105
display_error (FROM_XINE, _("The xine engine failed to start."),
106
_("No demuxer found - stream format not recognised."));
109
case XINE_ERROR_DEMUX_FAILED:
110
display_error (FROM_XINE, _("The xine engine failed to start."),
111
_("Demuxing failed.\n"
112
"Maybe the stream is corrupt or of an unexpected type."));
115
case XINE_ERROR_MALFORMED_MRL:
116
display_error (FROM_XINE, _("The xine engine failed to start."),
117
_("The MRL is malformed."));
120
case XINE_ERROR_INPUT_FAILED:
121
display_error (FROM_XINE, _("The xine engine failed to start."),
122
_("The stream could not be opened."));
127
display_error (FROM_XINE, _("The xine engine failed to start."),
128
_("Unknown error (code %d)"), error);
131
#ifdef XINE_PARAM_GAPLESS_SWITCH
132
xine_set_param (stream, XINE_PARAM_GAPLESS_SWITCH, 0);
135
if (!playlist_showing_logo ())
136
g_idle_add ((GSourceFunc)playlist_logo, NULL);
64
139
static __attribute__ ((noreturn)) void *play_exec (void *data)
66
141
xine_cfg_entry_t entry;
67
142
char *hash, *mrl = NULL;
144
pthread_setcancelstate (PTHREAD_CANCEL_ENABLE, NULL);
145
pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
69
147
/*pthread_mutex_lock (&engine_lock);*/
70
148
pthread_mutex_lock (&widgets_update_lock);
149
pthread_cleanup_push (pthread_mutex_unlock, &widgets_update_lock);
71
150
gdk_threads_enter();
151
pthread_cleanup_push (gdk_threads_leave, NULL);
73
153
gxineinfo_clear (infobars);
74
154
gxineinfo_update_line (infobars, 0, "%s", _("opening..."));
135
gdk_threads_leave ();
136
if (!xine_open (stream, mrl ? : cur_mrl))
139
gdk_threads_enter ();
140
switch (error = xine_get_error (stream))
142
case XINE_ERROR_NO_INPUT_PLUGIN:
143
display_error (FROM_XINE, _("The xine engine failed to start."),
144
_("No input plugin was found.\n"
145
"Maybe the file does not exist or cannot be accessed, "
146
"or there is an error in the URL."));
149
case XINE_ERROR_NO_DEMUX_PLUGIN:
150
display_error (FROM_XINE,
151
playlist_showing_logo ()
152
? _("Whoops. You seem to have a broken xine-lib.")
153
: _("The xine engine failed to start."),
154
_("No demuxer found - stream format not recognised."));
157
case XINE_ERROR_DEMUX_FAILED:
158
display_error (FROM_XINE, _("The xine engine failed to start."),
159
_("Demuxing failed.\n"
160
"Maybe the stream is corrupt or of an unexpected type."));
163
case XINE_ERROR_MALFORMED_MRL:
164
display_error (FROM_XINE, _("The xine engine failed to start."),
165
_("The MRL is malformed."));
168
case XINE_ERROR_INPUT_FAILED:
169
display_error (FROM_XINE, _("The xine engine failed to start."),
170
_("The stream could not be opened."));
175
display_error (FROM_XINE, _("The xine engine failed to start."),
176
_("Unknown error (code %d)"), error);
179
if (!playlist_showing_logo ())
180
g_idle_add ((GSourceFunc)playlist_logo, NULL);
181
goto done; /* will call gdk_threads_leave */
184
gdk_threads_enter ();
185
ui_set_status (playlist_showing_logo () ? UI_STOP : UI_PLAY);
186
infobar_show_metadata (infobars);
187
gdk_threads_leave ();
189
xine_play (stream, goto_pos, goto_time);
193
/* correct for possible stream changes */
194
gdk_threads_enter ();
195
ui_set_status (playlist_showing_logo () ? UI_STOP : UI_PLAY);
196
infobar_show_metadata (infobars);
197
playlist_check_set_title ();
215
pthread_cleanup_pop (TRUE);
216
int ret = xine_open (stream, mrl ? : cur_mrl);
220
gdk_threads_enter ();
221
pthread_cleanup_push (gdk_threads_leave, NULL);
222
ui_set_status (playlist_showing_logo () ? UI_STOP : UI_PLAY);
223
infobar_show_metadata (infobars);
224
pthread_cleanup_pop (TRUE);
226
// xine_play (stream, 0, 0);
227
xine_play (stream, goto_pos, goto_time);
228
gtk_video_set_end_time (gtv, end_time);
233
/* correct for possible stream changes */
234
gdk_threads_enter ();
235
pthread_cleanup_push (gdk_threads_leave, NULL);
236
ui_set_status (playlist_showing_logo () ? UI_STOP : UI_PLAY);
237
infobar_show_metadata (infobars);
238
playlist_check_set_title ();
239
pthread_cleanup_pop (TRUE);
243
gdk_threads_enter ();
244
pthread_cleanup_push (gdk_threads_leave, NULL);
246
pthread_cleanup_pop (TRUE);
201
gdk_threads_leave ();
202
pthread_mutex_unlock (&widgets_update_lock);
250
pthread_cleanup_pop (TRUE);
203
251
/*pthread_mutex_unlock (&engine_lock);*/
204
252
pthread_exit (NULL);
207
void player_launch (const char *title, const char *mrl, int pos, int pos_time)
255
void player_launch (const char *title, const char *mrl,
256
int pos, int pos_time, int duration)
210
259
pthread_attr_t attr;
212
261
goto_pos = pos < 0 ? 0 : pos;
213
262
goto_time = pos_time < 0 ? 0 : pos_time;
263
end_time = duration <= 0 ? 0: pos_time + duration;
214
264
free (cur_title);
216
266
cur_title = title && !playlist_showing_logo () ? strdup (title) : NULL;
289
348
xine_set_param (stream, XINE_PARAM_VO_ZOOM_Y, zoom);
292
#define ACTION_SET(Func) \
293
static void set_##Func (int v) \
295
if (gtk_toggle_action_get_active (action_items.Func) != v) \
296
gtk_action_activate (GTK_ACTION(action_items.Func)); \
299
ACTION_SET(fullscreen)
300
static void get_fullscreen (se_prop_t *prop, se_prop_read_t *value)
302
value->i = gtk_video_is_fullscreen ((GtkVideo *)gtv);
305
ACTION_SET(deinterlace)
306
static void get_deinterlace (se_prop_t *prop, se_prop_read_t *value)
308
value->i = gtk_video_get_use_post_plugins_deinterlace ((GtkVideo *)gtv);
311
351
static void set_subtitles (int sub)
313
353
if (sub >= -2 && sub <= GXINE_MAX_SPU_CHANNEL)
315
355
GSList *menuitem = action_items.subtitles;
316
int count = g_slist_length (menuitem) - 3;
356
int count = g_slist_length (menuitem);
357
/* last three menu items (in definition order, not menu display order):
358
* None (-2), Auto (-1), Other (>= 16, hidden)
363
count = 1; /* for None, Auto */
319
364
while (menuitem && --count > sub)
320
365
menuitem = menuitem->next;
429
#ifdef WITH_DEPRECATED
451
static JSBool get_pos (JSContext *cx, JSObject *obj, uintN argc,
452
jsval *argv, jsval *rval)
454
int pos, pos_time, len;
455
se_log_fncall ("get_pos");
456
xine_get_pos_length (stream, &pos, &pos_time, &len);
458
jsdouble *pos_percent = JS_NewDouble (cx, pos / 655.35);
459
*rval = DOUBLE_TO_JSVAL (pos_percent);
463
static JSBool has_time (JSContext *cx, JSObject *obj, uintN argc,
464
jsval *argv, jsval *rval)
466
int pos, pos_time, len;
467
se_log_fncall ("has_time");
468
xine_get_pos_length (stream, &pos, &pos_time, &len);
469
*rval = BOOLEAN_TO_JSVAL (len != 0);
431
475
static JSBool js_get_speed (JSContext *cx, JSObject *obj, uintN argc,
432
476
jsval *argv, jsval *rval)
434
478
se_prop_read_t speed;
435
se_log_fncall_deprecated ("get_speed");
479
se_log_fncall_obsolete ("get_speed");
436
480
get_speed (NULL, &speed);
437
481
*rval = INT_TO_JSVAL (speed.i);
1020
1064
audio_port = xine_open_audio_driver (xine, audio_driver_id, NULL);
1021
1065
if (audio_port)
1022
1066
return audio_port;
1024
g_printerr (_("audio driver %s failed\n"), audio_driver_id);
1068
g_printerr (_("audio driver %s failed\n"), audio_driver_id);
1027
1071
/* autoprobe */
1028
return xine_open_audio_driver (xine, NULL, NULL);
1072
audio_port = xine_open_audio_driver (xine, NULL, NULL);
1076
g_printerr (_("audio driver %s failed\n"), "auto");
1077
return xine_open_audio_driver (xine, "none", NULL);
1031
1080
/* Properties */
1082
static void add_chain_funcs (const char *prop, const char *config,
1083
JSBool (*set_chain) (JSContext *, JSObject *,
1084
uintN, jsval *, jsval *))
1086
se_o_t *obj = se_find_object (gse, NULL, prop);
1088
se_defun (gse, obj, "set_chain", set_chain, 0, 0, SE_GROUP_HIDDEN, NULL, NULL);
1089
se_prop_create_xine_id (gse, obj, "chain", config);
1090
se_prop_add_listener (gse, obj, "chain",
1091
listen_postproc_chain, config);
1033
1094
void player_init (void)
1063
1134
* VARIABLE[=TYPE] or METHOD([PARAMETER TYPE,...])
1064
1135
* To the right, descriptive text
1066
{ "av_speed", N_("v=int, min, max; playback speed"), 0, get_speed, set_speed, XINE_SPEED_PAUSE, XINE_SPEED_FAST_4, FALSE, { listen_speed } },
1067
{ "vo_aspect", N_("v=int; aspect ratio"), XINE_PARAM_VO_ASPECT_RATIO, NULL, set_aspect, 0, XINE_VO_ASPECT_NUM_RATIOS - 1, TRUE },
1068
{ "vo_subtitle", N_("v=int, min, max; subtitle channel"), XINE_PARAM_SPU_CHANNEL, NULL, set_subtitles, -2, GXINE_MAX_SPU_CHANNEL },
1069
{ "vo_zoom", N_("v=int, min, max; video zoom (within window)"), XINE_PARAM_VO_ZOOM_X, NULL, set_zoom, XINE_VO_ZOOM_MIN, XINE_VO_ZOOM_MAX },
1137
{ "av_speed", N_("v=int, min, max; playback speed"),
1138
UI_CUSTOM (get_speed, set_speed),
1143
{ "vo_aspect", N_("v=int; aspect ratio"), UI_XINE_PARAM (XINE_PARAM_VO_ASPECT_RATIO, set_aspect), 0, XINE_VO_ASPECT_NUM_RATIOS - 1, TRUE },
1144
{ "vo_subtitle", N_("v=int, min, max; subtitle channel"), UI_XINE_PARAM (XINE_PARAM_SPU_CHANNEL, set_subtitles), -2, GXINE_MAX_SPU_CHANNEL },
1145
{ "vo_zoom", N_("v=int, min, max; video zoom (within window)"), UI_XINE_PARAM (XINE_PARAM_VO_ZOOM_X, set_zoom), XINE_VO_ZOOM_MIN, XINE_VO_ZOOM_MAX },
1072
1148
static const ui_property_t bool_props[] = {
1073
{ "ao_mute", N_("v=bool, toggle(): audio mute"), XINE_PARAM_AUDIO_MUTE, NULL, set_mute },
1074
{ "vo_auto_resize", N_("v=bool, toggle(): auto-resize video on frame shape change"), 0, get_auto_resize, set_auto_resize },
1075
{ "vo_auto_rescale", N_("v=bool, toggle(): double size of low-resolution video"), 0, get_auto_rescale, set_auto_rescale },
1076
{ "vo_fullscreen", N_("v=bool, toggle(): full-screen mode"), 0, get_fullscreen, set_fullscreen },
1077
{ "vo_deinterlace", N_("v=bool, toggle(): enable deinterlacing"), 0, get_deinterlace, set_deinterlace },
1078
{ "ao_postproc", N_("v=bool, toggle(): audio post-processing; chain=string: plugin chain"), 0, get_ao_postproc, set_ao_postproc },
1079
{ "vo_postproc", N_("v=bool, toggle(): video post-processing; chain=string: plugin chain"), 0, get_vo_postproc, set_vo_postproc },
1080
{ "wm_unblank", N_("v=bool, toggle(): unblanking in windowed mode"), 0, get_wm_unblank, set_wm_unblank },
1149
{ "ao_mute", N_("v=bool, toggle(): audio mute"), UI_XINE_PARAM (XINE_PARAM_AUDIO_MUTE, set_mute) },
1150
{ "vo_auto_resize", N_("v=bool, toggle(): auto-resize video on frame shape change"), UI_GTK_VIDEO (auto_resize, gtk_video_get_auto_resize) },
1151
{ "vo_auto_rescale", N_("v=bool, toggle(): double size of low-resolution video"), UI_GTK_VIDEO (auto_rescale, gtk_video_get_auto_rescale) },
1152
{ "vo_fullscreen", N_("v=bool, toggle(): full-screen mode"), UI_GTK_VIDEO (fullscreen, gtk_video_is_fullscreen) },
1153
{ "vo_deinterlace", N_("v=bool, toggle(): enable deinterlacing"), UI_GTK_VIDEO (deinterlace, gtk_video_get_use_post_plugins_deinterlace) },
1154
{ "ao_postproc", N_("v=bool, toggle(): audio post-processing; chain=string: plugin chain"), UI_GTK_VIDEO (ao_postproc, gtk_video_get_use_post_plugins_audio) },
1155
{ "vo_postproc", N_("v=bool, toggle(): video post-processing; chain=string: plugin chain"), UI_GTK_VIDEO (vo_postproc, gtk_video_get_use_post_plugins_video) },
1156
{ "wm_unblank", N_("v=bool, toggle(): unblanking in windowed mode"), UI_GTK_VIDEO (wm_unblank, gtk_video_get_windowed_unblank) },
1083
1159
static const ui_property_t zoom_subprops[] = {
1084
{ "x", N_("v=int, min, max; video zoom (within window)"), XINE_PARAM_VO_ZOOM_X, NULL, NULL, XINE_VO_ZOOM_MIN, XINE_VO_ZOOM_MAX },
1085
{ "y", N_("v=int, min, max; video zoom (within window)"), XINE_PARAM_VO_ZOOM_Y, NULL, NULL, XINE_VO_ZOOM_MIN, XINE_VO_ZOOM_MAX },
1160
{ "x", N_("v=int, min, max; video zoom (within window)"), UI_XINE_PARAM (XINE_PARAM_VO_ZOOM_X, NULL), XINE_VO_ZOOM_MIN, XINE_VO_ZOOM_MAX },
1161
{ "y", N_("v=int, min, max; video zoom (within window)"), UI_XINE_PARAM (XINE_PARAM_VO_ZOOM_Y, NULL), XINE_VO_ZOOM_MIN, XINE_VO_ZOOM_MAX },
1164
static const ui_property_t fs_subprops[] = {
1165
{ "sticky", N_("v=bool, toggle(); forced stickiness in full-screen mode"), UI_BOOL (fs_sticky, fs_always_sticky, NULL) },
1090
1170
ui_create_properties (bool_props, NULL, SE_TYPE_BOOL);
1091
1171
ui_create_properties (zoom_subprops, se_find_object (gse, NULL, "vo_zoom"),
1173
ui_create_properties (fs_subprops, se_find_object (gse, NULL, "vo_fullscreen"),
1095
1177
/* a few extras - chain definition should be done via the GUI */
1096
se_o_t *obj = se_find_object (gse, NULL, "ao_postproc");
1097
se_defun (gse, obj, "set_chain",
1098
set_ao_postproc_chain, 0, 0, SE_GROUP_HIDDEN, NULL, NULL);
1099
se_prop_create_xine_id (gse, obj, "chain", "gui.post_plugins.audio");
1100
se_prop_add_listener (gse, obj, "chain",
1101
listen_postproc_chain, "gui.post_plugins.audio");
1103
obj = se_find_object (gse, NULL, "vo_postproc");
1104
se_defun (gse, obj, "set_chain",
1105
set_vo_postproc_chain, 0, 0, SE_GROUP_HIDDEN, NULL, NULL);
1106
se_prop_create_xine_id (gse, obj, "chain", "gui.post_plugins.video");
1107
se_prop_add_listener (gse, obj, "chain",
1108
listen_postproc_chain, "gui.post_plugins.video");
1178
add_chain_funcs ("ao_postproc", "gui.post_plugins.audio", set_ao_postproc_chain);
1179
add_chain_funcs ("vo_postproc", "gui.post_plugins.video", set_vo_postproc_chain);
1180
add_chain_funcs ("vo_deinterlace", "gui.post_plugins.deinterlace", set_deint_postproc_chain);
1111
1183
* hook up global xine functions for convenience
1118
1190
SE_GROUP_ENGINE, N_("[mrl] [, pos, time]"),
1119
1191
N_("time in milliseconds") },
1120
1192
{ "get_time", get_time, 0, 0,
1121
SE_GROUP_ENGINE, NULL, NULL },
1193
SE_GROUP_ENGINE, NULL, N_("stream time index") },
1194
{ "get_pos", get_pos, 0, 0,
1195
SE_GROUP_ENGINE, NULL, N_("stream position (%)") },
1196
{ "has_time", has_time, 0, 0,
1197
SE_GROUP_ENGINE, NULL, N_("whether the stream has a time index") },
1122
1198
{ "pause", controls_pause, 0, 0,
1123
1199
SE_GROUP_ENGINE, N_("[bool]"), NULL },
1124
1200
{ "stop", controls_stop, 0, 0,
1184
1264
_("The main window's default size"),
1185
1265
NULL, 0, NULL, NULL);
1186
1266
xine_config_register_bool
1187
(xine, "gui.magnify_lowres_video", 0,
1267
(xine, "gui.windowed_mode.magnify_lowres_video", CONFIG_VERSION_ATLEAST (0, 6, 0),
1188
1268
_("Double the size of small video streams"),
1189
1269
_("This affects video streams whose dimensions are at most ⅓ "
1190
1270
"of those of the display."),
1272
config_update_default ("gui.windowed_mode.magnify_lowres_video", 1);
1273
xine_config_register_bool
1274
(xine, "gui.windowed_mode.auto_resize", 1,
1275
_("Automatic video window resizing"),
1276
_("Whether the window is automatically resized on a stream format change."),
1192
1278
xine_config_register_bool
1193
1279
(xine, "gui.subtitle_autoload", 1,
1194
1280
_("Subtitle autoloading"),