~ubuntu-branches/ubuntu/karmic/gxine/karmic

« back to all changes in this revision

Viewing changes to src/player.c

  • Committer: Bazaar Package Importer
  • Author(s): Reinhard Tartler
  • Date: 2008-03-21 11:24:59 UTC
  • mfrom: (1.1.8 upstream)
  • Revision ID: james.westby@ubuntu.com-20080321112459-igb0jy01nytpdrzt
Tags: 0.5.901-1ubuntu1
* merge debian changes for hardy PPA. Remaining changes:
  - debian/control: added Xb-Npp-xxx tags accordingly to "firefox distro
    add-on suport" spec,
    (https://blueprints.launchpad.net/ubuntu/+spec/firefox-distro-addon-support)
* Feature Freeze exception granted in LP: #204563
* New upstream release fixes playing DVDs. LP: #128864
* mime.default: add "x-content/video-dvd;x-content/video-vcd;x-content/video-svcd;"
  to get it listed as a player for dvd and video cds in nautilus. Thanks to
  Sebastien Bacher for the hint.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
 
 * Copyright (C) 2004-2006 the xine-project
 
2
 * Copyright (C) 2004-2007 the xine-project
3
3
 *
4
4
 * This program is free software; you can redistribute it and/or
5
5
 * modify it under the terms of the GNU General Public License as
16
16
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301
17
17
 * USA
18
18
 *
19
 
 * $Id: player.c,v 1.86 2006/04/08 21:34:50 dsalt Exp $
20
 
 *
21
19
 * player object
22
20
 */
23
21
 
57
55
 * always start xine engine from a seperate thread so the gui stays responsive
58
56
 */
59
57
 
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;
63
61
 
 
62
static gboolean demuxer_for_logo = TRUE;
 
63
 
 
64
static int play_exec_error_suppress = 0;
 
65
 
 
66
void play_exec_error_suppress_next (void)
 
67
{
 
68
  ++play_exec_error_suppress;
 
69
}
 
70
 
 
71
static void play_exec_error (void)
 
72
{
 
73
  if (play_exec_error_suppress)
 
74
  {
 
75
#ifdef XINE_PARAM_GAPLESS_SWITCH
 
76
    xine_set_param (stream, XINE_PARAM_GAPLESS_SWITCH, 0);
 
77
#endif
 
78
    --play_exec_error_suppress;
 
79
    return;
 
80
  }
 
81
 
 
82
  int error;
 
83
  switch (error = xine_get_error (stream))
 
84
  {
 
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."));
 
90
    break;
 
91
 
 
92
  case XINE_ERROR_NO_DEMUX_PLUGIN:
 
93
    if (playlist_showing_logo ())
 
94
    {
 
95
      g_idle_add (infobar_show_metadata, infobars);
 
96
      if (demuxer_for_logo)
 
97
      {
 
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."));
 
102
      }
 
103
    }
 
104
    else
 
105
      display_error (FROM_XINE, _("The xine engine failed to start."),
 
106
                     _("No demuxer found - stream format not recognised."));
 
107
    break;
 
108
 
 
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."));
 
113
    break;
 
114
 
 
115
  case XINE_ERROR_MALFORMED_MRL:
 
116
    display_error (FROM_XINE, _("The xine engine failed to start."),
 
117
                   _("The MRL is malformed."));
 
118
    break;
 
119
 
 
120
  case XINE_ERROR_INPUT_FAILED:
 
121
    display_error (FROM_XINE, _("The xine engine failed to start."),
 
122
                   _("The stream could not be opened."));
 
123
    break;
 
124
 
 
125
 
 
126
  default:
 
127
    display_error (FROM_XINE, _("The xine engine failed to start."),
 
128
                   _("Unknown error (code %d)"), error);
 
129
  }
 
130
 
 
131
#ifdef XINE_PARAM_GAPLESS_SWITCH
 
132
  xine_set_param (stream, XINE_PARAM_GAPLESS_SWITCH, 0);
 
133
#endif
 
134
 
 
135
  if (!playlist_showing_logo ())
 
136
    g_idle_add ((GSourceFunc)playlist_logo, NULL);
 
137
}
 
138
 
64
139
static __attribute__ ((noreturn)) void *play_exec (void *data)
65
140
{
66
141
  xine_cfg_entry_t entry;
67
142
  char *hash, *mrl = NULL;
68
143
 
 
144
  pthread_setcancelstate (PTHREAD_CANCEL_ENABLE, NULL);
 
145
  pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
 
146
 
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);
72
152
 
73
153
  gxineinfo_clear (infobars);
74
154
  gxineinfo_update_line (infobars, 0, "%s", _("opening..."));
132
212
    }
133
213
  }
134
214
 
135
 
  gdk_threads_leave ();
136
 
  if (!xine_open (stream, mrl ? : cur_mrl))
137
 
  {
138
 
    int error;
139
 
    gdk_threads_enter ();
140
 
    switch (error = xine_get_error (stream))
141
 
    {
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."));
147
 
      break;
148
 
 
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."));
155
 
      break;
156
 
 
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."));
161
 
      break;
162
 
 
163
 
    case XINE_ERROR_MALFORMED_MRL:
164
 
      display_error (FROM_XINE, _("The xine engine failed to start."),
165
 
                     _("The MRL is malformed."));
166
 
      break;
167
 
 
168
 
    case XINE_ERROR_INPUT_FAILED:
169
 
      display_error (FROM_XINE, _("The xine engine failed to start."),
170
 
                     _("The stream could not be opened."));
171
 
      break;
172
 
 
173
 
 
174
 
    default:
175
 
      display_error (FROM_XINE, _("The xine engine failed to start."),
176
 
                     _("Unknown error (code %d)"), error);
177
 
    }
178
 
 
179
 
    if (!playlist_showing_logo ())
180
 
      g_idle_add ((GSourceFunc)playlist_logo, NULL);
181
 
    goto done; /* will call gdk_threads_leave */
182
 
  }
183
 
 
184
 
  gdk_threads_enter ();
185
 
  ui_set_status (playlist_showing_logo () ? UI_STOP : UI_PLAY);
186
 
  infobar_show_metadata (infobars);
187
 
  gdk_threads_leave ();
188
 
 
189
 
  xine_play (stream, goto_pos, goto_time);
190
 
  goto_pos = 0;
191
 
  goto_time = 0;
192
 
 
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 ();
198
 
 
199
 
done:
 
215
  pthread_cleanup_pop (TRUE);
 
216
  int ret = xine_open (stream, mrl ? : cur_mrl);
 
217
 
 
218
  if (ret)
 
219
  {
 
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);
 
225
 
 
226
//    xine_play (stream, 0, 0);
 
227
    xine_play (stream, goto_pos, goto_time);
 
228
    gtk_video_set_end_time (gtv, end_time);
 
229
    goto_pos = 0;
 
230
    goto_time = 0;
 
231
    end_time = 0;
 
232
 
 
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);
 
240
  }
 
241
  else
 
242
  {
 
243
    gdk_threads_enter ();
 
244
    pthread_cleanup_push (gdk_threads_leave, NULL);
 
245
    play_exec_error ();
 
246
    pthread_cleanup_pop (TRUE);
 
247
  }
 
248
 
200
249
  free (mrl);
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);
205
253
}
206
254
 
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)
208
257
{
209
258
  int err;
210
259
  pthread_attr_t attr;
211
260
 
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);
215
265
  free (cur_mrl);
216
266
  cur_title = title && !playlist_showing_logo () ? strdup (title) : NULL;
218
268
 
219
269
  gtk_video_unblank_screen ((GtkVideo *)gtv);
220
270
 
 
271
  if (!demuxer_for_logo && playlist_showing_logo ())
 
272
    return;
 
273
 
221
274
  /* start separate thread, so xine_open will not block ui */
222
275
  pthread_attr_init (&attr);
223
276
  pthread_attr_setstacksize (&attr, 256 * 1024); /* probably overkill */
239
292
  pthread_join (play_thread, NULL);
240
293
}
241
294
 
 
295
void player_stop (void)
 
296
{
 
297
  pthread_cancel (play_thread);
 
298
  xine_stop (stream);
 
299
}
 
300
 
242
301
static void set_mute (int mute)
243
302
{
244
303
  ui_set_status (mute ? UI_AUDIO_MUTE : UI_AUDIO_UNMUTE);
289
348
  xine_set_param (stream, XINE_PARAM_VO_ZOOM_Y, zoom);
290
349
}
291
350
 
292
 
#define ACTION_SET(Func) \
293
 
  static void set_##Func (int v) \
294
 
  { \
295
 
    if (gtk_toggle_action_get_active (action_items.Func) != v) \
296
 
      gtk_action_activate (GTK_ACTION(action_items.Func)); \
297
 
  }
298
 
 
299
 
ACTION_SET(fullscreen)
300
 
static void get_fullscreen (se_prop_t *prop, se_prop_read_t *value)
301
 
{
302
 
  value->i = gtk_video_is_fullscreen ((GtkVideo *)gtv);
303
 
}
304
 
 
305
 
ACTION_SET(deinterlace)
306
 
static void get_deinterlace (se_prop_t *prop, se_prop_read_t *value)
307
 
{
308
 
  value->i = gtk_video_get_use_post_plugins_deinterlace ((GtkVideo *)gtv);
309
 
}
310
 
 
311
351
static void set_subtitles (int sub)
312
352
{
313
353
  if (sub >= -2 && sub <= GXINE_MAX_SPU_CHANNEL)
314
354
  {
315
355
    GSList *menuitem = action_items.subtitles;
316
 
    int count = g_slist_length (menuitem) - 3;
317
 
    if (count >= sub)
 
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)
 
359
     */
 
360
    if (count > sub + 3)
318
361
    {
 
362
      if (sub < 0)
 
363
        count = 1; /* for None, Auto */
319
364
      while (menuitem && --count > sub)
320
365
        menuitem = menuitem->next;
321
366
      if (menuitem)
325
370
      }
326
371
    }
327
372
    /* not in menu */
328
 
    gtk_action_activate (g_slist_last (action_items.subtitles)->data);
 
373
    gtk_action_activate (action_items.subtitles->data);
329
374
    xine_set_param (stream, XINE_PARAM_SPU_CHANNEL, sub);
330
375
  }
331
376
}
344
389
    gtk_action_activate (menuitem->data);
345
390
}
346
391
 
347
 
ACTION_SET(auto_resize)
348
 
static void get_auto_resize (se_prop_t *prop, se_prop_read_t *value)
349
 
{
350
 
  value->i = gtk_video_get_auto_resize ((GtkVideo *)gtv);
351
 
}
352
 
 
353
 
ACTION_SET(auto_rescale)
354
 
static void get_auto_rescale (se_prop_t *prop, se_prop_read_t *value)
355
 
{
356
 
  value->i = gtk_video_get_auto_rescale ((GtkVideo *)gtv);
357
 
}
358
 
 
359
 
ACTION_SET(vo_postproc)
360
 
static void get_vo_postproc (se_prop_t *prop, se_prop_read_t *value)
361
 
{
362
 
  value->i = gtk_video_get_use_post_plugins_video ((GtkVideo *)gtv);
363
 
}
364
 
 
365
 
ACTION_SET(ao_postproc)
366
 
static void get_ao_postproc (se_prop_t *prop, se_prop_read_t *value)
367
 
{
368
 
  value->i = gtk_video_get_use_post_plugins_audio ((GtkVideo *)gtv);
369
 
}
370
 
 
371
 
ACTION_SET(wm_unblank)
372
 
static void get_wm_unblank (se_prop_t *prop, se_prop_read_t *value)
373
 
{
374
 
  value->i = gtk_video_get_windowed_unblank ((GtkVideo *)gtv);
375
 
}
376
 
 
377
392
static void update_postproc_chain (const char *pref, const char *value)
378
393
{
379
394
  xine_cfg_entry_t entry;
402
417
                             cx, obj, argc, argv, rval);
403
418
}
404
419
 
 
420
static JSBool set_deint_postproc_chain (JSContext *cx, JSObject *obj,
 
421
                                        uintN argc, jsval *argv, jsval *rval)
 
422
{
 
423
  return set_postproc_chain ("vo_deinterlace.set_chain", "gui.post_plugins.deinterlace",
 
424
                             cx, obj, argc, argv, rval);
 
425
}
 
426
 
405
427
static JSBool set_ao_postproc_chain (JSContext *cx, JSObject *obj,
406
428
                                     uintN argc, jsval *argv, jsval *rval)
407
429
{
426
448
  return JS_TRUE;
427
449
}
428
450
 
429
 
#ifdef WITH_DEPRECATED
 
451
static JSBool get_pos (JSContext *cx, JSObject *obj, uintN argc,
 
452
                       jsval *argv, jsval *rval)
 
453
{
 
454
  int pos, pos_time, len;
 
455
  se_log_fncall ("get_pos");
 
456
  xine_get_pos_length (stream, &pos, &pos_time, &len);
 
457
 
 
458
  jsdouble *pos_percent = JS_NewDouble (cx, pos / 655.35);
 
459
  *rval = DOUBLE_TO_JSVAL (pos_percent);
 
460
  return JS_TRUE;
 
461
}
 
462
 
 
463
static JSBool has_time (JSContext *cx, JSObject *obj, uintN argc,
 
464
                        jsval *argv, jsval *rval)
 
465
{
 
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);
 
470
  return JS_TRUE;
 
471
}
 
472
 
 
473
#ifdef WITH_OBSOLETE
430
474
 
431
475
static JSBool js_get_speed (JSContext *cx, JSObject *obj, uintN argc,
432
476
                            jsval *argv, jsval *rval)
433
477
{
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);
438
482
  return JS_TRUE;
443
487
{
444
488
  /* se_t *se = (se_t *) JS_GetContextPrivate(cx); */
445
489
  int   volume;
446
 
  se_log_fncall_deprecated ("get_volume");
 
490
  se_log_fncall_obsolete ("get_volume");
447
491
  volume = xine_get_param (stream, XINE_PARAM_AUDIO_VOLUME);
448
492
  *rval = INT_TO_JSVAL (volume);
449
493
  return JS_TRUE;
454
498
{
455
499
  /* se_t *se = (se_t *) JS_GetContextPrivate(cx); */
456
500
  int mute;
457
 
  se_log_fncall_deprecated ("get_mute");
 
501
  se_log_fncall_obsolete ("get_mute");
458
502
  mute = xine_get_param (stream, XINE_PARAM_AUDIO_MUTE);
459
503
  *rval = BOOLEAN_TO_JSVAL (mute);
460
504
  return JS_TRUE;
465
509
{
466
510
  /* se_t *se = (se_t *) JS_GetContextPrivate(cx); */
467
511
  int   zoom;
468
 
  se_log_fncall_deprecated ("get_zoom");
 
512
  se_log_fncall_obsolete ("get_zoom");
469
513
  zoom = xine_get_param (stream, XINE_PARAM_VO_ZOOM_X);
470
514
  *rval = INT_TO_JSVAL (zoom);
471
515
  return JS_TRUE;
472
516
}
473
517
 
474
 
#endif /* WITH_DEPRECATED */
 
518
#endif /* WITH_OBSOLETE */
475
519
 
476
520
static JSBool controls_pause (JSContext *cx, JSObject *obj, uintN argc,
477
521
                              jsval *argv, jsval *rval)
509
553
                             jsval *argv, jsval *rval)
510
554
{
511
555
  se_log_fncall_checkinit ("stop");
512
 
  xine_stop (stream);
 
556
  player_stop ();
513
557
  playlist_logo (NULL);
514
558
  ui_set_control_adjustment (Control_SEEKER, 0);
515
559
  return JS_TRUE;
520
564
{
521
565
  se_log_fncall_checkinit ("eject");
522
566
  if (xine_get_status (stream) == XINE_STATUS_PLAY)
523
 
    xine_stop (stream);
 
567
    player_stop ();
524
568
  gdk_threads_leave (); /* need to do this to allow play_exec() to proceed */
525
569
  playlist_logo (cx); /* doesn't matter so long as it's not NULL */
526
570
  gdk_threads_enter ();
530
574
  return JS_TRUE;
531
575
}
532
576
 
533
 
#ifdef WITH_DEPRECATED
 
577
#ifdef WITH_OBSOLETE
534
578
 
535
579
static JSBool js_set_speed (JSContext *cx, JSObject *obj, uintN argc,
536
580
                            jsval *argv, jsval *rval)
537
581
{
538
582
  int32 speed;
539
583
 
540
 
  se_log_fncall_deprecated ("set_speed");
 
584
  se_log_fncall_obsolete ("set_speed");
541
585
 
542
586
  se_argc_check (1, "set_speed");
543
587
  se_arg_is_int (0, "set_speed");
556
600
{
557
601
  int32 volume;
558
602
 
559
 
  se_log_fncall_deprecated ("set_volume");
 
603
  se_log_fncall_obsolete ("set_volume");
560
604
  se_argc_check (1, "set_volume");
561
605
  se_arg_is_int (0, "set_volume");
562
606
 
575
619
{
576
620
  JSBool mute;
577
621
 
578
 
  se_log_fncall_deprecated ("set_mute");
 
622
  se_log_fncall_obsolete ("set_mute");
579
623
  se_argc_check_max (1, "set_mute");
580
624
 
581
625
  if (argc == 1)
596
640
{
597
641
  int32 zoom;
598
642
 
599
 
  se_log_fncall_deprecated ("set_zoom");
 
643
  se_log_fncall_obsolete ("set_zoom");
600
644
  se_argc_check (1, "set_zoom");
601
645
  se_arg_is_int (0, "set_zoom");
602
646
 
606
650
  return JS_TRUE;
607
651
}
608
652
 
609
 
#endif /* WITH_DEPRECATED */
 
653
#endif /* WITH_OBSOLETE */
610
654
 
611
655
static int zoomcb, zoomcb_id = 0;
612
656
 
674
718
  else
675
719
    fs = !gtk_video_is_fullscreen ((GtkVideo *)gtv);
676
720
 
677
 
  set_fullscreen (fs);
 
721
  if (gtk_toggle_action_get_active (action_items.fullscreen) != fs)
 
722
    gtk_action_activate (GTK_ACTION (action_items.fullscreen));
 
723
 
678
724
  return JS_TRUE;
679
725
}
680
726
 
 
727
#ifdef WITH_OBSOLETE
 
728
 
681
729
static JSBool js_set_deinterlace (JSContext *cx, JSObject *obj, uintN argc,
682
730
                                 jsval *argv, jsval *rval)
683
731
{
684
732
  int32 di;
685
733
 
686
 
  se_log_fncall_deprecated ("set_deinterlace");
 
734
  se_log_fncall_obsolete ("set_deinterlace");
687
735
  se_argc_check_max (1, "set_deinterlace");
688
736
 
689
737
  if (argc == 1)
704
752
  se_t *se = (se_t *) JS_GetContextPrivate(cx);
705
753
  int32 di;
706
754
 
707
 
  se_log_fncall_deprecated ("set_postproc_video");
 
755
  se_log_fncall_obsolete ("set_postproc_video");
708
756
  se_argc_check_max (1, "set_postproc_video");
709
757
 
710
758
  if (argc == 1)
733
781
  se_t *se = (se_t *) JS_GetContextPrivate(cx);
734
782
  int32 di;
735
783
 
736
 
  se_log_fncall_deprecated ("set_postproc_audio");
 
784
  se_log_fncall_obsolete ("set_postproc_audio");
737
785
  se_argc_check_max (1, "set_postproc_audio");
738
786
 
739
787
  if (argc == 1)
761
809
{
762
810
  int32 ar;
763
811
 
764
 
  se_log_fncall_deprecated ("set_auto_resize");
 
812
  se_log_fncall_obsolete ("set_auto_resize");
765
813
  se_argc_check_max (1, "set_auto_resize");
766
814
 
767
815
  if (argc == 1)
781
829
{
782
830
  int32 ar;
783
831
 
784
 
  se_log_fncall_deprecated ("set_auto_rescale");
 
832
  se_log_fncall_obsolete ("set_auto_rescale");
785
833
  se_argc_check_max (1, "set_auto_rescale");
786
834
 
787
835
  if (argc == 1)
801
849
{
802
850
  int32 aspect;
803
851
 
804
 
  se_log_fncall_deprecated ("set_aspect");
 
852
  se_log_fncall_obsolete ("set_aspect");
805
853
  se_argc_check_max (1, "set_aspect");
806
854
 
807
855
  if (argc==1)
816
864
  return JS_TRUE;
817
865
}
818
866
 
 
867
#endif /* WITH_OBSOLETE */
819
868
#endif /* WITH_DEPRECATED */
820
869
 
821
870
static JSBool js_snapshot (JSContext *cx, JSObject *obj, uintN argc,
876
925
 
877
926
  case 2:
878
927
    {
879
 
      se_arg_is_int (0, "play");
 
928
      se_arg_is_number (0, "play");
880
929
      se_arg_is_int (1, "play");
881
930
 
882
 
      JS_ValueToInt32 (cx, argv[0], &pos);
 
931
      jsdouble *posv = JS_NewDouble (cx, 0); /* when is this freed? */
 
932
      JS_ValueToNumber (cx, argv[0], posv);
 
933
      pos = (*posv >= 0 && *posv < 100) ? *posv * 655.35 : -1;
883
934
      JS_ValueToInt32 (cx, argv[1], &pos_time);
884
935
      mrl = NULL;
885
936
      se_log ("playing from %d, %d\n", pos, pos_time);
888
939
 
889
940
  case 3:
890
941
    {
891
 
      JSString *str;
892
942
      se_arg_is_string (0, "play");
893
 
      se_arg_is_int (1, "play");
 
943
      se_arg_is_number (1, "play");
894
944
      se_arg_is_int (2, "play");
895
945
 
896
 
      str = JS_ValueToString (cx, argv[0]);
897
 
      JS_ValueToInt32 (cx, argv[1], &pos);
 
946
      JSString *str = JS_ValueToString (cx, argv[0]);
 
947
      jsdouble *posv = JS_NewDouble (cx, 0); /* when is this freed? */
 
948
      JS_ValueToNumber (cx, argv[1], posv);
 
949
      pos = (*posv >= 0 && *posv < 100) ? *posv * 655.35 : -1;
898
950
      JS_ValueToInt32 (cx, argv[2], &pos_time);
899
951
      mrl = JS_GetStringBytes (str);
900
952
      se_log ("playing '%s' from %d, %d\n", mrl, pos, pos_time);
902
954
    break;
903
955
  }
904
956
 
905
 
  if (pos > 0)
906
 
    pos *= 655;
907
 
 
908
957
  if (mrl)
909
958
    playlist_play_from (playlist_add_mrl (mrl, -1), pos, pos_time);
910
959
  else
913
962
 
914
963
    if (item)
915
964
    {
916
 
      switch (xine_get_status (stream))
 
965
      switch (playlist_showing_logo () ? XINE_STATUS_IDLE : xine_get_status (stream))
917
966
      {
918
967
      case XINE_STATUS_STOP:
919
968
      case XINE_STATUS_IDLE:
932
981
    } else
933
982
      logprintf (_("script_engine: error: no valid play item available\n"));
934
983
  }
935
 
 
936
 
  if (xine_get_param (stream, XINE_PARAM_SPEED) != XINE_SPEED_NORMAL)
937
 
    set_speed (XINE_SPEED_NORMAL);
 
984
  set_speed (XINE_SPEED_NORMAL);
938
985
 
939
986
  return JS_TRUE;
940
987
}
1000
1047
{
1001
1048
  xine_audio_port_t      *audio_port;
1002
1049
 
 
1050
  char **choices = get_driver_ids (xine_list_audio_output_plugins (xine));
 
1051
  /* try to init audio with stored information */
 
1052
  int i = xine_config_register_enum (xine,
 
1053
                                     "audio.driver", 0, choices,
 
1054
                                     _("audio driver to use"),
 
1055
                                     NULL, 10, gtk_true, NULL);
1003
1056
  if (!audio_driver_id)
1004
 
  {
1005
 
    char **choices = get_driver_ids (xine_list_audio_output_plugins (xine));
1006
 
    /* try to init audio with stored information */
1007
 
    int i = xine_config_register_enum (xine,
1008
 
                                   "audio.driver", 0,
1009
 
                                   choices,
1010
 
                                   _("audio driver to use"),
1011
 
                                   NULL, 10, gtk_true, NULL);
1012
1057
    audio_driver_id = choices[i];
1013
 
  }
1014
1058
 
1015
1059
  if (!strcmp (audio_driver_id, "null"))
1016
1060
    return NULL;
1020
1064
    audio_port = xine_open_audio_driver (xine, audio_driver_id, NULL);
1021
1065
    if (audio_port)
1022
1066
      return audio_port;
1023
 
    else
1024
 
      g_printerr (_("audio driver %s failed\n"), audio_driver_id);
 
1067
 
 
1068
    g_printerr (_("audio driver %s failed\n"), audio_driver_id);
1025
1069
  }
1026
1070
 
1027
1071
  /* autoprobe */
1028
 
  return xine_open_audio_driver (xine, NULL, NULL);
 
1072
  audio_port = xine_open_audio_driver (xine, NULL, NULL);
 
1073
  if (audio_port)
 
1074
    return audio_port;
 
1075
 
 
1076
  g_printerr (_("audio driver %s failed\n"), "auto");
 
1077
  return xine_open_audio_driver (xine, "none", NULL);
1029
1078
}
1030
1079
 
1031
1080
/* Properties */
1032
1081
 
 
1082
static void add_chain_funcs (const char *prop, const char *config,
 
1083
                             JSBool (*set_chain) (JSContext *, JSObject *,
 
1084
                                                  uintN, jsval *, jsval *))
 
1085
{
 
1086
  se_o_t *obj = se_find_object (gse, NULL, prop);
 
1087
  if (set_chain)
 
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);
 
1092
}
 
1093
 
1033
1094
void player_init (void)
1034
1095
{
1035
1096
/*
1041
1102
  /* load drivers, create xine stream */
1042
1103
 
1043
1104
  audio_port = load_audio_out_driver ();
 
1105
  if (!audio_port)
 
1106
  {
 
1107
    display_error_modal (FROM_GXINE, _("Fatal error"),
 
1108
                         _("No audio output driver could be loaded."));
 
1109
    exit (2);
 
1110
  }
 
1111
 
1044
1112
  video_port = xine_open_video_driver (xine, "none", 0, NULL);
1045
1113
 
1046
1114
  stream = xine_stream_new (xine, audio_port, video_port);
 
1115
#ifdef XINE_PARAM_EARLY_FINISHED_EVENT
 
1116
  xine_set_param (stream, XINE_PARAM_EARLY_FINISHED_EVENT, 1);
 
1117
#endif
1047
1118
 
1048
1119
  /*
1049
1120
   * set up script engine objects and functions
1063
1134
       *     VARIABLE[=TYPE] or METHOD([PARAMETER TYPE,...])
1064
1135
       *   To the right, descriptive text
1065
1136
       */
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), 
 
1139
       XINE_SPEED_PAUSE, 
 
1140
       XINE_SPEED_FAST_4, 
 
1141
       FALSE, 
 
1142
       { listen_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 },
1070
1146
      { NULL }
1071
1147
    };
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) },
1081
1157
      { NULL }
1082
1158
    };
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 },
 
1162
      { NULL }
 
1163
    };
 
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) },
1086
1166
      { NULL }
1087
1167
    };
1088
1168
 
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"),
1092
1172
                          SE_TYPE_INT);
 
1173
    ui_create_properties (fs_subprops, se_find_object (gse, NULL, "vo_fullscreen"),
 
1174
                          SE_TYPE_BOOL);
1093
1175
  }
1094
1176
 
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");
1102
 
 
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);
1109
1181
 
1110
1182
  /*
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,
1135
1211
        SE_GROUP_PROPERTIES, N_("int"), NULL },
1136
1212
 
1137
1213
#ifdef WITH_DEPRECATED
 
1214
#ifdef WITH_OBSOLETE
1138
1215
      { "set_speed", js_set_speed, 0, 0,
1139
1216
        SE_GROUP_HIDDEN, NULL, NULL },
1140
1217
      { "get_speed", js_get_speed, 0, 0,
1151
1228
        SE_GROUP_HIDDEN, NULL, NULL },
1152
1229
      { "get_zoom", js_get_zoom, 0, 0,
1153
1230
        SE_GROUP_HIDDEN, NULL, NULL },
 
1231
#endif /* WITH_OBSOLETE */
1154
1232
      { "set_fullscreen", js_set_fullscreen, 0, 0,
1155
1233
        SE_GROUP_HIDDEN, NULL, NULL },
 
1234
#ifdef WITH_OBSOLETE
1156
1235
      { "set_aspect", js_set_aspect, 0, 0,
1157
1236
        SE_GROUP_HIDDEN, NULL, NULL },
1158
1237
      { "set_deinterlace", js_set_deinterlace, 0, 0,
1165
1244
        SE_GROUP_HIDDEN, NULL, NULL },
1166
1245
      { "set_auto_rescale", js_set_auto_rescale, 0, 0,
1167
1246
        SE_GROUP_HIDDEN, NULL, NULL },
 
1247
#endif /* WITH_OBSOLETE */
1168
1248
#endif /* WITH_DEPRECATED */
1169
1249
 
1170
1250
      { "is_live_stream", js_is_live_stream, 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."),
1191
 
       0, gtk_true, NULL);
 
1271
       0, gtk_true, NULL);       
 
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."),
 
1277
       0, NULL, NULL);
1192
1278
    xine_config_register_bool
1193
1279
      (xine, "gui.subtitle_autoload", 1,
1194
1280
       _("Subtitle autoloading"),