7 #include "input/input.h"
8 #include "stream/stream.h"
9 #include "libmpdemux/demuxer.h"
10 #include "libmpdemux/stheader.h"
12 #include "libvo/sub.h"
14 #include "m_property.h"
17 #include "libmpcodecs/mp_image.h"
18 #include "libmpcodecs/vf.h"
19 #include "libmpcodecs/vd.h"
20 #include "libvo/video_out.h"
22 #include "libao2/audio_out.h"
25 #include "libmpdemux/matroska.h"
26 #include "libmpcodecs/dec_video.h"
30 #include "stream/tv.h"
33 #include "stream/stream_radio.h"
35 #ifdef HAS_DVBIN_SUPPORT
36 #include "stream/dvbin.h"
39 #include "stream/stream_dvd.h"
42 #include "stream/stream_dvdnav.h"
45 #include "libass/ass.h"
46 #include "libass/ass_mp.h"
49 #include "Gui/interface.h"
54 #define ROUND(x) ((int)((x)<0 ? (x)-0.5 : (x)+0.5))
56 static void rescale_input_coordinates(int ix
, int iy
, double *dx
, double *dy
)
58 //remove the borders, if any, and rescale to the range [0,1],[0,1]
59 if (vo_fs
) { //we are in full-screen mode
60 if (vo_screenwidth
> vo_dwidth
) //there are borders along the x axis
61 ix
-= (vo_screenwidth
- vo_dwidth
) / 2;
62 if (vo_screenheight
> vo_dheight
) //there are borders along the y axis (usual way)
63 iy
-= (vo_screenheight
- vo_dheight
) / 2;
65 if (ix
< 0 || ix
> vo_dwidth
) {
68 } //we are on one of the borders
69 if (iy
< 0 || iy
> vo_dheight
) {
72 } //we are on one of the borders
75 *dx
= (double) ix
/ (double) vo_dwidth
;
76 *dy
= (double) iy
/ (double) vo_dheight
;
78 mp_msg(MSGT_CPLAYER
, MSGL_V
,
79 "\r\nrescaled coordinates: %.3lf, %.3lf, screen (%d x %d), vodisplay: (%d, %d), fullscreen: %d\r\n",
80 *dx
, *dy
, vo_screenwidth
, vo_screenheight
, vo_dwidth
,
84 static int sub_source(MPContext
* mpctx
)
89 for (i
= 0; i
< SUB_SOURCES
; i
++) {
90 int j
= mpctx
->global_sub_indices
[i
];
91 if ((j
>= 0) && (j
> top
) && (mpctx
->global_sub_pos
>= j
)) {
100 * \brief Log the currently displayed subtitle to a file
102 * Logs the current or last displayed subtitle together with filename
103 * and time information to ~/.mplayer/subtitle_log
105 * Intended purpose is to allow convenient marking of bogus subtitles
106 * which need to be fixed while watching the movie.
109 static void log_sub(void)
115 if (subdata
== NULL
|| vo_sub_last
== NULL
)
117 fname
= get_path("subtitle_log");
118 f
= fopen(fname
, "a");
121 fprintf(f
, "----------------------------------------------------------\n");
122 if (subdata
->sub_uses_time
) {
124 "N: %s S: %02ld:%02ld:%02ld.%02ld E: %02ld:%02ld:%02ld.%02ld\n",
125 filename
, vo_sub_last
->start
/ 360000,
126 (vo_sub_last
->start
/ 6000) % 60,
127 (vo_sub_last
->start
/ 100) % 60, vo_sub_last
->start
% 100,
128 vo_sub_last
->end
/ 360000, (vo_sub_last
->end
/ 6000) % 60,
129 (vo_sub_last
->end
/ 100) % 60, vo_sub_last
->end
% 100);
131 fprintf(f
, "N: %s S: %ld E: %ld\n", filename
, vo_sub_last
->start
,
134 for (i
= 0; i
< vo_sub_last
->lines
; i
++) {
135 fprintf(f
, "%s\n", vo_sub_last
->text
[i
]);
141 /// \defgroup Properties
144 /// \defgroup GeneralProperties General properties
145 /// \ingroup Properties
149 static int mp_property_osdlevel(m_option_t
* prop
, int action
, void *arg
,
152 return m_property_choice(prop
, action
, arg
, &osd_level
);
155 /// Playback speed (RW)
156 static int mp_property_playback_speed(m_option_t
* prop
, int action
,
157 void *arg
, MPContext
* mpctx
)
162 return M_PROPERTY_ERROR
;
163 M_PROPERTY_CLAMP(prop
, *(float *) arg
);
164 playback_speed
= *(float *) arg
;
165 build_afilter_chain(mpctx
->sh_audio
, &ao_data
);
166 return M_PROPERTY_OK
;
167 case M_PROPERTY_STEP_UP
:
168 case M_PROPERTY_STEP_DOWN
:
169 playback_speed
+= (arg
? *(float *) arg
: 0.1) *
170 (action
== M_PROPERTY_STEP_DOWN
? -1 : 1);
171 M_PROPERTY_CLAMP(prop
, playback_speed
);
172 build_afilter_chain(mpctx
->sh_audio
, &ao_data
);
173 return M_PROPERTY_OK
;
175 return m_property_float_range(prop
, action
, arg
, &playback_speed
);
178 /// filename with path (RO)
179 static int mp_property_path(m_option_t
* prop
, int action
, void *arg
,
182 return m_property_string_ro(prop
, action
, arg
, filename
);
185 /// filename without path (RO)
186 static int mp_property_filename(m_option_t
* prop
, int action
, void *arg
,
191 return M_PROPERTY_UNAVAILABLE
;
192 if (((f
= strrchr(filename
, '/')) || (f
= strrchr(filename
, '\\'))) && f
[1])
196 return m_property_string_ro(prop
, action
, arg
, f
);
199 /// Demuxer name (RO)
200 static int mp_property_demuxer(m_option_t
* prop
, int action
, void *arg
,
204 return M_PROPERTY_UNAVAILABLE
;
205 return m_property_string_ro(prop
, action
, arg
,
206 (char *) mpctx
->demuxer
->desc
->name
);
209 /// Position in the stream (RW)
210 static int mp_property_stream_pos(m_option_t
* prop
, int action
, void *arg
,
213 if (!mpctx
->demuxer
|| !mpctx
->demuxer
->stream
)
214 return M_PROPERTY_UNAVAILABLE
;
216 return M_PROPERTY_ERROR
;
219 *(off_t
*) arg
= stream_tell(mpctx
->demuxer
->stream
);
220 return M_PROPERTY_OK
;
222 M_PROPERTY_CLAMP(prop
, *(off_t
*) arg
);
223 stream_seek(mpctx
->demuxer
->stream
, *(off_t
*) arg
);
224 return M_PROPERTY_OK
;
226 return M_PROPERTY_NOT_IMPLEMENTED
;
229 /// Stream start offset (RO)
230 static int mp_property_stream_start(m_option_t
* prop
, int action
,
231 void *arg
, MPContext
* mpctx
)
233 if (!mpctx
->demuxer
|| !mpctx
->demuxer
->stream
)
234 return M_PROPERTY_UNAVAILABLE
;
237 *(off_t
*) arg
= mpctx
->demuxer
->stream
->start_pos
;
238 return M_PROPERTY_OK
;
240 return M_PROPERTY_NOT_IMPLEMENTED
;
243 /// Stream end offset (RO)
244 static int mp_property_stream_end(m_option_t
* prop
, int action
, void *arg
,
247 if (!mpctx
->demuxer
|| !mpctx
->demuxer
->stream
)
248 return M_PROPERTY_UNAVAILABLE
;
251 *(off_t
*) arg
= mpctx
->demuxer
->stream
->end_pos
;
252 return M_PROPERTY_OK
;
254 return M_PROPERTY_NOT_IMPLEMENTED
;
257 /// Stream length (RO)
258 static int mp_property_stream_length(m_option_t
* prop
, int action
,
259 void *arg
, MPContext
* mpctx
)
261 if (!mpctx
->demuxer
|| !mpctx
->demuxer
->stream
)
262 return M_PROPERTY_UNAVAILABLE
;
266 mpctx
->demuxer
->stream
->end_pos
- mpctx
->demuxer
->stream
->start_pos
;
267 return M_PROPERTY_OK
;
269 return M_PROPERTY_NOT_IMPLEMENTED
;
272 /// Media length in seconds (RO)
273 static int mp_property_length(m_option_t
* prop
, int action
, void *arg
,
278 if (!mpctx
->demuxer
||
279 !(int) (len
= demuxer_get_time_length(mpctx
->demuxer
)))
280 return M_PROPERTY_UNAVAILABLE
;
283 case M_PROPERTY_PRINT
:
285 return M_PROPERTY_ERROR
;
292 *(char **) arg
= malloc(20);
294 sprintf(*(char **) arg
, "%d:%02d:%02d", h
, m
, s
);
296 sprintf(*(char **) arg
, "%d:%02d", m
, s
);
298 sprintf(*(char **) arg
, "%d", s
);
299 return M_PROPERTY_OK
;
303 return m_property_double_ro(prop
, action
, arg
, len
);
308 /// \defgroup AudioProperties Audio properties
309 /// \ingroup Properties
313 static int mp_property_volume(m_option_t
* prop
, int action
, void *arg
,
317 if (!mpctx
->sh_audio
)
318 return M_PROPERTY_UNAVAILABLE
;
323 return M_PROPERTY_ERROR
;
324 mixer_getbothvolume(&mpctx
->mixer
, arg
);
325 return M_PROPERTY_OK
;
326 case M_PROPERTY_PRINT
:{
329 return M_PROPERTY_ERROR
;
330 mixer_getbothvolume(&mpctx
->mixer
, &vol
);
331 return m_property_float_range(prop
, action
, arg
, &vol
);
333 case M_PROPERTY_STEP_UP
:
334 case M_PROPERTY_STEP_DOWN
:
338 return M_PROPERTY_NOT_IMPLEMENTED
;
341 if (mpctx
->edl_muted
)
342 return M_PROPERTY_DISABLED
;
343 mpctx
->user_muted
= 0;
348 return M_PROPERTY_ERROR
;
349 M_PROPERTY_CLAMP(prop
, *(float *) arg
);
350 mixer_setvolume(&mpctx
->mixer
, *(float *) arg
, *(float *) arg
);
351 return M_PROPERTY_OK
;
352 case M_PROPERTY_STEP_UP
:
353 if (arg
&& *(float *) arg
<= 0)
354 mixer_decvolume(&mpctx
->mixer
);
356 mixer_incvolume(&mpctx
->mixer
);
357 return M_PROPERTY_OK
;
358 case M_PROPERTY_STEP_DOWN
:
359 if (arg
&& *(float *) arg
<= 0)
360 mixer_incvolume(&mpctx
->mixer
);
362 mixer_decvolume(&mpctx
->mixer
);
363 return M_PROPERTY_OK
;
365 return M_PROPERTY_NOT_IMPLEMENTED
;
369 static int mp_property_mute(m_option_t
* prop
, int action
, void *arg
,
373 if (!mpctx
->sh_audio
)
374 return M_PROPERTY_UNAVAILABLE
;
378 if (mpctx
->edl_muted
)
379 return M_PROPERTY_DISABLED
;
381 return M_PROPERTY_ERROR
;
382 if ((!!*(int *) arg
) != mpctx
->mixer
.muted
)
383 mixer_mute(&mpctx
->mixer
);
384 mpctx
->user_muted
= mpctx
->mixer
.muted
;
385 return M_PROPERTY_OK
;
386 case M_PROPERTY_STEP_UP
:
387 case M_PROPERTY_STEP_DOWN
:
388 if (mpctx
->edl_muted
)
389 return M_PROPERTY_DISABLED
;
390 mixer_mute(&mpctx
->mixer
);
391 mpctx
->user_muted
= mpctx
->mixer
.muted
;
392 return M_PROPERTY_OK
;
393 case M_PROPERTY_PRINT
:
395 return M_PROPERTY_ERROR
;
396 if (mpctx
->edl_muted
) {
397 *(char **) arg
= strdup(MSGTR_EnabledEdl
);
398 return M_PROPERTY_OK
;
401 return m_property_flag(prop
, action
, arg
, &mpctx
->mixer
.muted
);
407 static int mp_property_audio_delay(m_option_t
* prop
, int action
,
408 void *arg
, MPContext
* mpctx
)
410 if (!(mpctx
->sh_audio
&& mpctx
->sh_video
))
411 return M_PROPERTY_UNAVAILABLE
;
414 case M_PROPERTY_STEP_UP
:
415 case M_PROPERTY_STEP_DOWN
:
417 return M_PROPERTY_ERROR
;
419 float delay
= audio_delay
;
420 m_property_delay(prop
, action
, arg
, &audio_delay
);
422 mpctx
->delay
-= audio_delay
- delay
;
424 return M_PROPERTY_OK
;
426 return m_property_delay(prop
, action
, arg
, &audio_delay
);
430 /// Audio codec tag (RO)
431 static int mp_property_audio_format(m_option_t
* prop
, int action
,
432 void *arg
, MPContext
* mpctx
)
434 if (!mpctx
->sh_audio
)
435 return M_PROPERTY_UNAVAILABLE
;
436 return m_property_int_ro(prop
, action
, arg
, mpctx
->sh_audio
->format
);
439 /// Audio bitrate (RO)
440 static int mp_property_audio_bitrate(m_option_t
* prop
, int action
,
441 void *arg
, MPContext
* mpctx
)
443 if (!mpctx
->sh_audio
)
444 return M_PROPERTY_UNAVAILABLE
;
445 return m_property_int_ro(prop
, action
, arg
, mpctx
->sh_audio
->i_bps
);
449 static int mp_property_samplerate(m_option_t
* prop
, int action
, void *arg
,
452 if (!mpctx
->sh_audio
)
453 return M_PROPERTY_UNAVAILABLE
;
454 return m_property_int_ro(prop
, action
, arg
, mpctx
->sh_audio
->samplerate
);
457 /// Number of channels (RO)
458 static int mp_property_channels(m_option_t
* prop
, int action
, void *arg
,
461 if (!mpctx
->sh_audio
)
462 return M_PROPERTY_UNAVAILABLE
;
464 case M_PROPERTY_PRINT
:
466 return M_PROPERTY_ERROR
;
467 switch (mpctx
->sh_audio
->channels
) {
469 *(char **) arg
= strdup("mono");
472 *(char **) arg
= strdup("stereo");
475 *(char **) arg
= malloc(32);
476 sprintf(*(char **) arg
, "%d channels", mpctx
->sh_audio
->channels
);
478 return M_PROPERTY_OK
;
480 return m_property_int_ro(prop
, action
, arg
, mpctx
->sh_audio
->channels
);
483 /// Selected audio id (RW)
484 static int mp_property_audio(m_option_t
* prop
, int action
, void *arg
,
487 int current_id
= -1, tmp
;
491 if (!mpctx
->sh_audio
)
492 return M_PROPERTY_UNAVAILABLE
;
494 return M_PROPERTY_ERROR
;
495 *(int *) arg
= audio_id
;
496 return M_PROPERTY_OK
;
497 case M_PROPERTY_PRINT
:
498 if (!mpctx
->sh_audio
)
499 return M_PROPERTY_UNAVAILABLE
;
501 return M_PROPERTY_ERROR
;
504 *(char **) arg
= strdup(MSGTR_Disabled
);
506 char lang
[40] = MSGTR_Unknown
;
507 if (mpctx
->demuxer
->type
== DEMUXER_TYPE_MATROSKA
)
508 demux_mkv_get_audio_lang(mpctx
->demuxer
, audio_id
, lang
, 9);
510 else if (mpctx
->stream
->type
== STREAMTYPE_DVD
) {
511 int code
= dvd_lang_from_aid(mpctx
->stream
, audio_id
);
521 else if (mpctx
->stream
->type
== STREAMTYPE_DVDNAV
)
522 dvdnav_lang_from_aid(mpctx
->stream
, audio_id
, lang
);
524 *(char **) arg
= malloc(64);
525 snprintf(*(char **) arg
, 64, "(%d) %s", audio_id
, lang
);
527 return M_PROPERTY_OK
;
529 case M_PROPERTY_STEP_UP
:
531 if (action
== M_PROPERTY_SET
&& arg
)
532 tmp
= *((int *) arg
);
535 current_id
= mpctx
->demuxer
->audio
->id
;
536 audio_id
= demuxer_switch_audio(mpctx
->demuxer
, tmp
);
539 && mpctx
->demuxer
->audio
->id
!= current_id
&& current_id
!= -2))
540 uninit_player(INITED_AO
| INITED_ACODEC
);
541 if (audio_id
> -1 && mpctx
->demuxer
->audio
->id
!= current_id
) {
543 sh2
= mpctx
->demuxer
->a_streams
[mpctx
->demuxer
->audio
->id
];
545 sh2
->ds
= mpctx
->demuxer
->audio
;
546 mpctx
->sh_audio
= sh2
;
547 reinit_audio_chain();
550 mp_msg(MSGT_IDENTIFY
, MSGL_INFO
, "ID_AUDIO_TRACK=%d\n", audio_id
);
551 return M_PROPERTY_OK
;
553 return M_PROPERTY_NOT_IMPLEMENTED
;
558 /// Selected video id (RW)
559 static int mp_property_video(m_option_t
* prop
, int action
, void *arg
,
562 int current_id
= -1, tmp
;
566 if (!mpctx
->sh_video
)
567 return M_PROPERTY_UNAVAILABLE
;
569 return M_PROPERTY_ERROR
;
570 *(int *) arg
= video_id
;
571 return M_PROPERTY_OK
;
572 case M_PROPERTY_PRINT
:
573 if (!mpctx
->sh_video
)
574 return M_PROPERTY_UNAVAILABLE
;
576 return M_PROPERTY_ERROR
;
579 *(char **) arg
= strdup(MSGTR_Disabled
);
581 char lang
[40] = MSGTR_Unknown
;
582 *(char **) arg
= malloc(64);
583 snprintf(*(char **) arg
, 64, "(%d) %s", video_id
, lang
);
585 return M_PROPERTY_OK
;
587 case M_PROPERTY_STEP_UP
:
589 current_id
= mpctx
->demuxer
->video
->id
;
590 if (action
== M_PROPERTY_SET
&& arg
)
591 tmp
= *((int *) arg
);
594 video_id
= demuxer_switch_video(mpctx
->demuxer
, tmp
);
596 || (video_id
> -1 && mpctx
->demuxer
->video
->id
!= current_id
597 && current_id
!= -2))
598 uninit_player(INITED_VCODEC
|
599 (fixed_vo
&& video_id
!= -2 ? 0 : INITED_VO
));
600 if (video_id
> -1 && mpctx
->demuxer
->video
->id
!= current_id
) {
602 sh2
= mpctx
->demuxer
->v_streams
[mpctx
->demuxer
->video
->id
];
604 sh2
->ds
= mpctx
->demuxer
->video
;
605 mpctx
->sh_video
= sh2
;
606 reinit_video_chain();
609 mp_msg(MSGT_IDENTIFY
, MSGL_INFO
, "ID_VIDEO_TRACK=%d\n", video_id
);
610 return M_PROPERTY_OK
;
613 return M_PROPERTY_NOT_IMPLEMENTED
;
617 static int mp_property_program(m_option_t
* prop
, int action
, void *arg
,
620 demux_program_t prog
;
623 case M_PROPERTY_STEP_UP
:
625 if (action
== M_PROPERTY_SET
&& arg
)
626 prog
.progid
= *((int *) arg
);
630 (mpctx
->demuxer
, DEMUXER_CTRL_IDENTIFY_PROGRAM
,
631 &prog
) == DEMUXER_CTRL_NOTIMPL
)
632 return M_PROPERTY_ERROR
;
634 mp_property_do("switch_audio", M_PROPERTY_SET
, &prog
.aid
, mpctx
);
635 mp_property_do("switch_video", M_PROPERTY_SET
, &prog
.vid
, mpctx
);
636 return M_PROPERTY_OK
;
639 return M_PROPERTY_NOT_IMPLEMENTED
;
645 /// \defgroup VideoProperties Video properties
646 /// \ingroup Properties
649 /// Fullscreen state (RW)
650 static int mp_property_fullscreen(m_option_t
* prop
, int action
, void *arg
,
654 if (!mpctx
->video_out
)
655 return M_PROPERTY_UNAVAILABLE
;
660 return M_PROPERTY_ERROR
;
661 M_PROPERTY_CLAMP(prop
, *(int *) arg
);
662 if (vo_fs
== !!*(int *) arg
)
663 return M_PROPERTY_OK
;
664 case M_PROPERTY_STEP_UP
:
665 case M_PROPERTY_STEP_DOWN
:
668 guiGetEvent(guiIEvent
, (char *) MP_CMD_GUI_FULLSCREEN
);
672 mpctx
->video_out
->control(VOCTRL_FULLSCREEN
, 0);
673 return M_PROPERTY_OK
;
675 return m_property_flag(prop
, action
, arg
, &vo_fs
);
679 static int mp_property_deinterlace(m_option_t
* prop
, int action
,
680 void *arg
, MPContext
* mpctx
)
684 if (!mpctx
->sh_video
|| !mpctx
->sh_video
->vfilter
)
685 return M_PROPERTY_UNAVAILABLE
;
686 vf
= mpctx
->sh_video
->vfilter
;
690 return M_PROPERTY_ERROR
;
691 vf
->control(vf
, VFCTRL_GET_DEINTERLACE
, arg
);
692 return M_PROPERTY_OK
;
695 return M_PROPERTY_ERROR
;
696 M_PROPERTY_CLAMP(prop
, *(int *) arg
);
697 vf
->control(vf
, VFCTRL_SET_DEINTERLACE
, arg
);
698 return M_PROPERTY_OK
;
699 case M_PROPERTY_STEP_UP
:
700 case M_PROPERTY_STEP_DOWN
:
701 vf
->control(vf
, VFCTRL_GET_DEINTERLACE
, &deinterlace
);
702 deinterlace
= !deinterlace
;
703 vf
->control(vf
, VFCTRL_SET_DEINTERLACE
, &deinterlace
);
704 return M_PROPERTY_OK
;
706 return M_PROPERTY_NOT_IMPLEMENTED
;
710 static int mp_property_panscan(m_option_t
* prop
, int action
, void *arg
,
714 if (!mpctx
->video_out
715 || mpctx
->video_out
->control(VOCTRL_GET_PANSCAN
, NULL
) != VO_TRUE
)
716 return M_PROPERTY_UNAVAILABLE
;
721 return M_PROPERTY_ERROR
;
722 M_PROPERTY_CLAMP(prop
, *(float *) arg
);
723 vo_panscan
= *(float *) arg
;
724 mpctx
->video_out
->control(VOCTRL_SET_PANSCAN
, NULL
);
725 return M_PROPERTY_OK
;
726 case M_PROPERTY_STEP_UP
:
727 case M_PROPERTY_STEP_DOWN
:
728 vo_panscan
+= (arg
? *(float *) arg
: 0.1) *
729 (action
== M_PROPERTY_STEP_DOWN
? -1 : 1);
732 else if (vo_panscan
< 0)
734 mpctx
->video_out
->control(VOCTRL_SET_PANSCAN
, NULL
);
735 return M_PROPERTY_OK
;
737 return m_property_float_range(prop
, action
, arg
, &vo_panscan
);
741 /// Helper to set vo flags.
742 /** \ingroup PropertyImplHelper
744 static int mp_property_vo_flag(m_option_t
* prop
, int action
, void *arg
,
745 int vo_ctrl
, int *vo_var
, MPContext
* mpctx
)
748 if (!mpctx
->video_out
)
749 return M_PROPERTY_UNAVAILABLE
;
754 return M_PROPERTY_ERROR
;
755 M_PROPERTY_CLAMP(prop
, *(int *) arg
);
756 if (*vo_var
== !!*(int *) arg
)
757 return M_PROPERTY_OK
;
758 case M_PROPERTY_STEP_UP
:
759 case M_PROPERTY_STEP_DOWN
:
761 mpctx
->video_out
->control(vo_ctrl
, 0);
762 return M_PROPERTY_OK
;
764 return m_property_flag(prop
, action
, arg
, vo_var
);
768 /// Window always on top (RW)
769 static int mp_property_ontop(m_option_t
* prop
, int action
, void *arg
,
772 return mp_property_vo_flag(prop
, action
, arg
, VOCTRL_ONTOP
, &vo_ontop
,
776 /// Display in the root window (RW)
777 static int mp_property_rootwin(m_option_t
* prop
, int action
, void *arg
,
780 return mp_property_vo_flag(prop
, action
, arg
, VOCTRL_ROOTWIN
,
784 /// Show window borders (RW)
785 static int mp_property_border(m_option_t
* prop
, int action
, void *arg
,
788 return mp_property_vo_flag(prop
, action
, arg
, VOCTRL_BORDER
,
792 /// Framedropping state (RW)
793 static int mp_property_framedropping(m_option_t
* prop
, int action
,
794 void *arg
, MPContext
* mpctx
)
797 if (!mpctx
->sh_video
)
798 return M_PROPERTY_UNAVAILABLE
;
801 case M_PROPERTY_PRINT
:
803 return M_PROPERTY_ERROR
;
804 *(char **) arg
= strdup(frame_dropping
== 1 ? MSGTR_Enabled
:
805 (frame_dropping
== 2 ? MSGTR_HardFrameDrop
:
807 return M_PROPERTY_OK
;
809 return m_property_choice(prop
, action
, arg
, &frame_dropping
);
813 /// Color settings, try to use vf/vo then fall back on TV. (RW)
814 static int mp_property_gamma(m_option_t
* prop
, int action
, void *arg
,
817 int *gamma
= prop
->priv
, r
;
819 if (!mpctx
->sh_video
)
820 return M_PROPERTY_UNAVAILABLE
;
822 if (gamma
[0] == 1000) {
824 get_video_colors(mpctx
->sh_video
, prop
->name
, gamma
);
830 return M_PROPERTY_ERROR
;
831 M_PROPERTY_CLAMP(prop
, *(int *) arg
);
832 *gamma
= *(int *) arg
;
833 r
= set_video_colors(mpctx
->sh_video
, prop
->name
, *gamma
);
839 return M_PROPERTY_ERROR
;
840 r
= get_video_colors(mpctx
->sh_video
, prop
->name
, arg
);
844 case M_PROPERTY_STEP_UP
:
845 case M_PROPERTY_STEP_DOWN
:
846 *gamma
+= (arg
? *(int *) arg
: 1) *
847 (action
== M_PROPERTY_STEP_DOWN
? -1 : 1);
848 M_PROPERTY_CLAMP(prop
, *gamma
);
849 r
= set_video_colors(mpctx
->sh_video
, prop
->name
, *gamma
);
854 return M_PROPERTY_NOT_IMPLEMENTED
;
858 if (mpctx
->demuxer
->type
== DEMUXER_TYPE_TV
) {
859 int l
= strlen(prop
->name
);
860 char tv_prop
[3 + l
+ 1];
861 sprintf(tv_prop
, "tv_%s", prop
->name
);
862 return mp_property_do(tv_prop
, action
, arg
, mpctx
);
866 return M_PROPERTY_UNAVAILABLE
;
870 static int mp_property_vsync(m_option_t
* prop
, int action
, void *arg
,
873 return m_property_flag(prop
, action
, arg
, &vo_vsync
);
876 /// Video codec tag (RO)
877 static int mp_property_video_format(m_option_t
* prop
, int action
,
878 void *arg
, MPContext
* mpctx
)
880 if (!mpctx
->sh_video
)
881 return M_PROPERTY_UNAVAILABLE
;
882 return m_property_int_ro(prop
, action
, arg
, mpctx
->sh_video
->format
);
885 /// Video bitrate (RO)
886 static int mp_property_video_bitrate(m_option_t
* prop
, int action
,
887 void *arg
, MPContext
* mpctx
)
889 if (!mpctx
->sh_video
)
890 return M_PROPERTY_UNAVAILABLE
;
891 return m_property_int_ro(prop
, action
, arg
, mpctx
->sh_video
->i_bps
);
894 /// Video display width (RO)
895 static int mp_property_width(m_option_t
* prop
, int action
, void *arg
,
898 if (!mpctx
->sh_video
)
899 return M_PROPERTY_UNAVAILABLE
;
900 return m_property_int_ro(prop
, action
, arg
, mpctx
->sh_video
->disp_w
);
903 /// Video display height (RO)
904 static int mp_property_height(m_option_t
* prop
, int action
, void *arg
,
907 if (!mpctx
->sh_video
)
908 return M_PROPERTY_UNAVAILABLE
;
909 return m_property_int_ro(prop
, action
, arg
, mpctx
->sh_video
->disp_h
);
913 static int mp_property_fps(m_option_t
* prop
, int action
, void *arg
,
916 if (!mpctx
->sh_video
)
917 return M_PROPERTY_UNAVAILABLE
;
918 return m_property_float_ro(prop
, action
, arg
, mpctx
->sh_video
->fps
);
921 /// Video aspect (RO)
922 static int mp_property_aspect(m_option_t
* prop
, int action
, void *arg
,
925 if (!mpctx
->sh_video
)
926 return M_PROPERTY_UNAVAILABLE
;
927 return m_property_float_ro(prop
, action
, arg
, mpctx
->sh_video
->aspect
);
932 /// \defgroup SubProprties Subtitles properties
933 /// \ingroup Properties
936 /// Text subtitle position (RW)
937 static int mp_property_sub_pos(m_option_t
* prop
, int action
, void *arg
,
940 if (!mpctx
->sh_video
)
941 return M_PROPERTY_UNAVAILABLE
;
946 return M_PROPERTY_ERROR
;
947 case M_PROPERTY_STEP_UP
:
948 case M_PROPERTY_STEP_DOWN
:
949 vo_osd_changed(OSDTYPE_SUBTITLE
);
951 return m_property_int_range(prop
, action
, arg
, &sub_pos
);
955 /// Selected subtitles (RW)
956 static int mp_property_sub(m_option_t
* prop
, int action
, void *arg
,
959 demux_stream_t
*const d_sub
= mpctx
->d_sub
;
960 const int global_sub_size
= mpctx
->global_sub_size
;
961 int source
= -1, reset_spu
= 0;
964 if (global_sub_size
<= 0)
965 return M_PROPERTY_UNAVAILABLE
;
970 return M_PROPERTY_ERROR
;
971 *(int *) arg
= mpctx
->global_sub_pos
;
972 return M_PROPERTY_OK
;
973 case M_PROPERTY_PRINT
:
975 return M_PROPERTY_ERROR
;
976 *(char **) arg
= malloc(64);
977 (*(char **) arg
)[63] = 0;
980 sub_name
= subdata
->filename
;
982 if (ass_track
&& ass_track
->name
)
983 sub_name
= ass_track
->name
;
988 if ((tmp2
= strrchr(tmp
, '/')))
991 snprintf(*(char **) arg
, 63, "(%d) %s%s",
992 mpctx
->set_of_sub_pos
+ 1,
993 strlen(tmp
) < 20 ? "" : "...",
994 strlen(tmp
) < 20 ? tmp
: tmp
+ strlen(tmp
) - 19);
995 return M_PROPERTY_OK
;
998 if (mpctx
->stream
->type
== STREAMTYPE_DVDNAV
) {
999 if (vo_spudec
&& dvdsub_id
>= 0) {
1000 unsigned char lang
[3];
1001 if (dvdnav_lang_from_sid(mpctx
->stream
, dvdsub_id
, lang
)) {
1002 snprintf(*(char **) arg
, 63, "(%d) %s", dvdsub_id
, lang
);
1003 return M_PROPERTY_OK
;
1009 if (mpctx
->demuxer
->type
== DEMUXER_TYPE_MATROSKA
&& dvdsub_id
>= 0) {
1010 char lang
[40] = MSGTR_Unknown
;
1011 demux_mkv_get_sub_lang(mpctx
->demuxer
, dvdsub_id
, lang
, 9);
1012 snprintf(*(char **) arg
, 63, "(%d) %s", dvdsub_id
, lang
);
1013 return M_PROPERTY_OK
;
1015 #ifdef HAVE_OGGVORBIS
1016 if (mpctx
->demuxer
->type
== DEMUXER_TYPE_OGG
&& d_sub
&& dvdsub_id
>= 0) {
1017 char *lang
= demux_ogg_sub_lang(mpctx
->demuxer
, dvdsub_id
);
1019 lang
= MSGTR_Unknown
;
1020 snprintf(*(char **) arg
, 63, "(%d) %s", dvdsub_id
, lang
);
1021 return M_PROPERTY_OK
;
1024 if (vo_vobsub
&& vobsub_id
>= 0) {
1025 const char *language
= MSGTR_Unknown
;
1026 language
= vobsub_get_id(vo_vobsub
, (unsigned int) vobsub_id
);
1027 snprintf(*(char **) arg
, 63, "(%d) %s",
1028 vobsub_id
, language
? language
: MSGTR_Unknown
);
1029 return M_PROPERTY_OK
;
1032 if (vo_spudec
&& mpctx
->stream
->type
== STREAMTYPE_DVD
1033 && dvdsub_id
>= 0) {
1035 int code
= dvd_lang_from_sid(mpctx
->stream
, dvdsub_id
);
1036 lang
[0] = code
>> 8;
1039 snprintf(*(char **) arg
, 63, "(%d) %s", dvdsub_id
, lang
);
1040 return M_PROPERTY_OK
;
1043 if (dvdsub_id
>= 0) {
1044 snprintf(*(char **) arg
, 63, "(%d) %s", dvdsub_id
, MSGTR_Unknown
);
1045 return M_PROPERTY_OK
;
1047 snprintf(*(char **) arg
, 63, MSGTR_Disabled
);
1048 return M_PROPERTY_OK
;
1050 case M_PROPERTY_SET
:
1052 return M_PROPERTY_ERROR
;
1053 if (*(int *) arg
< -1)
1055 else if (*(int *) arg
>= global_sub_size
)
1056 *(int *) arg
= global_sub_size
- 1;
1057 mpctx
->global_sub_pos
= *(int *) arg
;
1059 case M_PROPERTY_STEP_UP
:
1060 mpctx
->global_sub_pos
+= 2;
1061 mpctx
->global_sub_pos
=
1062 (mpctx
->global_sub_pos
% (global_sub_size
+ 1)) - 1;
1064 case M_PROPERTY_STEP_DOWN
:
1065 mpctx
->global_sub_pos
+= global_sub_size
+ 1;
1066 mpctx
->global_sub_pos
=
1067 (mpctx
->global_sub_pos
% (global_sub_size
+ 1)) - 1;
1070 return M_PROPERTY_NOT_IMPLEMENTED
;
1073 if (mpctx
->global_sub_pos
>= 0)
1074 source
= sub_source(mpctx
);
1076 mp_msg(MSGT_CPLAYER
, MSGL_DBG3
,
1077 "subtitles: %d subs, (v@%d s@%d d@%d), @%d, source @%d\n",
1079 mpctx
->global_sub_indices
[SUB_SOURCE_VOBSUB
],
1080 mpctx
->global_sub_indices
[SUB_SOURCE_SUBS
],
1081 mpctx
->global_sub_indices
[SUB_SOURCE_DEMUX
],
1082 mpctx
->global_sub_pos
, source
);
1084 mpctx
->set_of_sub_pos
= -1;
1086 vo_sub_last
= vo_sub
= NULL
;
1099 if (source
== SUB_SOURCE_VOBSUB
) {
1101 mpctx
->global_sub_pos
-
1102 mpctx
->global_sub_indices
[SUB_SOURCE_VOBSUB
];
1103 } else if (source
== SUB_SOURCE_SUBS
) {
1104 mpctx
->set_of_sub_pos
=
1105 mpctx
->global_sub_pos
- mpctx
->global_sub_indices
[SUB_SOURCE_SUBS
];
1107 if (ass_enabled
&& mpctx
->set_of_ass_tracks
[mpctx
->set_of_sub_pos
])
1108 ass_track
= mpctx
->set_of_ass_tracks
[mpctx
->set_of_sub_pos
];
1112 subdata
= mpctx
->set_of_subtitles
[mpctx
->set_of_sub_pos
];
1113 vo_osd_changed(OSDTYPE_SUBTITLE
);
1115 } else if (source
== SUB_SOURCE_DEMUX
) {
1117 mpctx
->global_sub_pos
- mpctx
->global_sub_indices
[SUB_SOURCE_DEMUX
];
1120 if (vo_spudec
&& mpctx
->stream
->type
== STREAMTYPE_DVD
) {
1121 d_sub
->id
= dvdsub_id
;
1126 if (vo_spudec
&& mpctx
->stream
->type
== STREAMTYPE_DVDNAV
) {
1127 d_sub
->id
= dvdsub_id
;
1130 if (mpctx
->stream
->type
!= STREAMTYPE_DVD
1131 && mpctx
->stream
->type
!= STREAMTYPE_DVDNAV
) {
1133 for (d_sub
->id
= 0; d_sub
->id
< MAX_S_STREAMS
; d_sub
->id
++) {
1134 if (mpctx
->demuxer
->s_streams
[d_sub
->id
]) {
1140 d_sub
->sh
= mpctx
->demuxer
->s_streams
[d_sub
->id
];
1142 if (mpctx
->demuxer
->type
== DEMUXER_TYPE_MATROSKA
)
1143 d_sub
->id
= demux_mkv_change_subs(mpctx
->demuxer
, dvdsub_id
);
1144 if (d_sub
->sh
&& d_sub
->id
>= 0) {
1145 sh_sub_t
*sh
= d_sub
->sh
;
1146 if (sh
->type
== 'v')
1149 else if (ass_enabled
&& sh
->type
== 'a')
1150 ass_track
= sh
->ass_track
;
1157 && (mpctx
->stream
->type
== STREAMTYPE_DVD
1158 || mpctx
->stream
->type
== STREAMTYPE_DVDNAV
)
1159 && dvdsub_id
< 0 && reset_spu
) {
1161 d_sub
->id
= dvdsub_id
;
1164 update_subtitles(mpctx
->sh_video
, d_sub
, 1);
1166 return M_PROPERTY_OK
;
1169 /// Subtitle delay (RW)
1170 static int mp_property_sub_delay(m_option_t
* prop
, int action
, void *arg
,
1173 if (!mpctx
->sh_video
)
1174 return M_PROPERTY_UNAVAILABLE
;
1175 return m_property_delay(prop
, action
, arg
, &sub_delay
);
1178 /// Alignment of text subtitles (RW)
1179 static int mp_property_sub_alignment(m_option_t
* prop
, int action
,
1180 void *arg
, MPContext
* mpctx
)
1182 char *name
[] = { MSGTR_Top
, MSGTR_Center
, MSGTR_Bottom
};
1184 if (!mpctx
->sh_video
|| mpctx
->global_sub_pos
< 0
1185 || sub_source(mpctx
) != SUB_SOURCE_SUBS
)
1186 return M_PROPERTY_UNAVAILABLE
;
1189 case M_PROPERTY_PRINT
:
1191 return M_PROPERTY_ERROR
;
1192 M_PROPERTY_CLAMP(prop
, sub_alignment
);
1193 *(char **) arg
= strdup(name
[sub_alignment
]);
1194 return M_PROPERTY_OK
;
1195 case M_PROPERTY_SET
:
1197 return M_PROPERTY_ERROR
;
1198 case M_PROPERTY_STEP_UP
:
1199 case M_PROPERTY_STEP_DOWN
:
1200 vo_osd_changed(OSDTYPE_SUBTITLE
);
1202 return m_property_choice(prop
, action
, arg
, &sub_alignment
);
1206 /// Subtitle visibility (RW)
1207 static int mp_property_sub_visibility(m_option_t
* prop
, int action
,
1208 void *arg
, MPContext
* mpctx
)
1210 if (!mpctx
->sh_video
)
1211 return M_PROPERTY_UNAVAILABLE
;
1214 case M_PROPERTY_SET
:
1216 return M_PROPERTY_ERROR
;
1217 case M_PROPERTY_STEP_UP
:
1218 case M_PROPERTY_STEP_DOWN
:
1219 vo_osd_changed(OSDTYPE_SUBTITLE
);
1221 vo_osd_changed(OSDTYPE_SPU
);
1223 return m_property_flag(prop
, action
, arg
, &sub_visibility
);
1227 /// Show only forced subtitles (RW)
1228 static int mp_property_sub_forced_only(m_option_t
* prop
, int action
,
1229 void *arg
, MPContext
* mpctx
)
1232 return M_PROPERTY_UNAVAILABLE
;
1235 case M_PROPERTY_SET
:
1237 return M_PROPERTY_ERROR
;
1238 case M_PROPERTY_STEP_UP
:
1239 case M_PROPERTY_STEP_DOWN
:
1240 m_property_flag(prop
, action
, arg
, &forced_subs_only
);
1241 spudec_set_forced_subs_only(vo_spudec
, forced_subs_only
);
1242 return M_PROPERTY_OK
;
1244 return m_property_flag(prop
, action
, arg
, &forced_subs_only
);
1251 /// \defgroup TVProperties TV properties
1252 /// \ingroup Properties
1257 /// TV color settings (RW)
1258 static int mp_property_tv_color(m_option_t
* prop
, int action
, void *arg
,
1262 tvi_handle_t
*tvh
= mpctx
->demuxer
->priv
;
1263 if (mpctx
->demuxer
->type
!= DEMUXER_TYPE_TV
|| !tvh
)
1264 return M_PROPERTY_UNAVAILABLE
;
1267 case M_PROPERTY_SET
:
1269 return M_PROPERTY_ERROR
;
1270 M_PROPERTY_CLAMP(prop
, *(int *) arg
);
1271 return tv_set_color_options(tvh
, (int) prop
->priv
, *(int *) arg
);
1272 case M_PROPERTY_GET
:
1273 return tv_get_color_options(tvh
, (int) prop
->priv
, arg
);
1274 case M_PROPERTY_STEP_UP
:
1275 case M_PROPERTY_STEP_DOWN
:
1276 if ((r
= tv_get_color_options(tvh
, (int) prop
->priv
, &val
)) >= 0) {
1278 return M_PROPERTY_ERROR
;
1279 val
+= (arg
? *(int *) arg
: 1) *
1280 (action
== M_PROPERTY_STEP_DOWN
? -1 : 1);
1281 M_PROPERTY_CLAMP(prop
, val
);
1282 return tv_set_color_options(tvh
, (int) prop
->priv
, val
);
1284 return M_PROPERTY_ERROR
;
1286 return M_PROPERTY_NOT_IMPLEMENTED
;
1293 /// All properties available in MPlayer.
1294 /** \ingroup Properties
1296 static m_option_t mp_properties
[] = {
1298 { "osdlevel", mp_property_osdlevel
, CONF_TYPE_INT
,
1299 M_OPT_RANGE
, 0, 3, NULL
},
1300 { "speed", mp_property_playback_speed
, CONF_TYPE_FLOAT
,
1301 M_OPT_RANGE
, 0.01, 100.0, NULL
},
1302 { "filename", mp_property_filename
, CONF_TYPE_STRING
,
1304 { "path", mp_property_path
, CONF_TYPE_STRING
,
1306 { "demuxer", mp_property_demuxer
, CONF_TYPE_STRING
,
1308 { "stream_pos", mp_property_stream_pos
, CONF_TYPE_POSITION
,
1309 M_OPT_MIN
, 0, 0, NULL
},
1310 { "stream_start", mp_property_stream_start
, CONF_TYPE_POSITION
,
1311 M_OPT_MIN
, 0, 0, NULL
},
1312 { "stream_end", mp_property_stream_end
, CONF_TYPE_POSITION
,
1313 M_OPT_MIN
, 0, 0, NULL
},
1314 { "stream_length", mp_property_stream_length
, CONF_TYPE_POSITION
,
1315 M_OPT_MIN
, 0, 0, NULL
},
1316 { "length", mp_property_length
, CONF_TYPE_DOUBLE
,
1320 { "volume", mp_property_volume
, CONF_TYPE_FLOAT
,
1321 M_OPT_RANGE
, 0, 100, NULL
},
1322 { "mute", mp_property_mute
, CONF_TYPE_FLAG
,
1323 M_OPT_RANGE
, 0, 1, NULL
},
1324 { "audio_delay", mp_property_audio_delay
, CONF_TYPE_FLOAT
,
1325 M_OPT_RANGE
, -100, 100, NULL
},
1326 { "audio_format", mp_property_audio_format
, CONF_TYPE_INT
,
1328 { "audio_bitrate", mp_property_audio_bitrate
, CONF_TYPE_INT
,
1330 { "samplerate", mp_property_samplerate
, CONF_TYPE_INT
,
1332 { "channels", mp_property_channels
, CONF_TYPE_INT
,
1334 { "switch_audio", mp_property_audio
, CONF_TYPE_INT
,
1335 CONF_RANGE
, -2, MAX_A_STREAMS
- 1, NULL
},
1338 { "fullscreen", mp_property_fullscreen
, CONF_TYPE_FLAG
,
1339 M_OPT_RANGE
, 0, 1, NULL
},
1340 { "deinterlace", mp_property_deinterlace
, CONF_TYPE_FLAG
,
1341 M_OPT_RANGE
, 0, 1, NULL
},
1342 { "ontop", mp_property_ontop
, CONF_TYPE_FLAG
,
1343 M_OPT_RANGE
, 0, 1, NULL
},
1344 { "rootwin", mp_property_rootwin
, CONF_TYPE_FLAG
,
1345 M_OPT_RANGE
, 0, 1, NULL
},
1346 { "border", mp_property_border
, CONF_TYPE_FLAG
,
1347 M_OPT_RANGE
, 0, 1, NULL
},
1348 { "framedropping", mp_property_framedropping
, CONF_TYPE_INT
,
1349 M_OPT_RANGE
, 0, 2, NULL
},
1350 { "gamma", mp_property_gamma
, CONF_TYPE_INT
,
1351 M_OPT_RANGE
, -100, 100, &vo_gamma_gamma
},
1352 { "brightness", mp_property_gamma
, CONF_TYPE_INT
,
1353 M_OPT_RANGE
, -100, 100, &vo_gamma_brightness
},
1354 { "contrast", mp_property_gamma
, CONF_TYPE_INT
,
1355 M_OPT_RANGE
, -100, 100, &vo_gamma_contrast
},
1356 { "saturation", mp_property_gamma
, CONF_TYPE_INT
,
1357 M_OPT_RANGE
, -100, 100, &vo_gamma_saturation
},
1358 { "hue", mp_property_gamma
, CONF_TYPE_INT
,
1359 M_OPT_RANGE
, -100, 100, &vo_gamma_hue
},
1360 { "panscan", mp_property_panscan
, CONF_TYPE_FLOAT
,
1361 M_OPT_RANGE
, 0, 1, NULL
},
1362 { "vsync", mp_property_vsync
, CONF_TYPE_FLAG
,
1363 M_OPT_RANGE
, 0, 1, NULL
},
1364 { "video_format", mp_property_video_format
, CONF_TYPE_INT
,
1366 { "video_bitrate", mp_property_video_bitrate
, CONF_TYPE_INT
,
1368 { "width", mp_property_width
, CONF_TYPE_INT
,
1370 { "height", mp_property_height
, CONF_TYPE_INT
,
1372 { "fps", mp_property_fps
, CONF_TYPE_FLOAT
,
1374 { "aspect", mp_property_aspect
, CONF_TYPE_FLOAT
,
1376 { "switch_video", mp_property_video
, CONF_TYPE_INT
,
1377 CONF_RANGE
, -2, MAX_V_STREAMS
- 1, NULL
},
1378 { "switch_program", mp_property_program
, CONF_TYPE_INT
,
1379 CONF_RANGE
, -1, 65535, NULL
},
1382 { "sub", mp_property_sub
, CONF_TYPE_INT
,
1383 M_OPT_MIN
, -1, 0, NULL
},
1384 { "sub_delay", mp_property_sub_delay
, CONF_TYPE_FLOAT
,
1386 { "sub_pos", mp_property_sub_pos
, CONF_TYPE_INT
,
1387 M_OPT_RANGE
, 0, 100, NULL
},
1388 { "sub_alignment", mp_property_sub_alignment
, CONF_TYPE_INT
,
1389 M_OPT_RANGE
, 0, 2, NULL
},
1390 { "sub_visibility", mp_property_sub_visibility
, CONF_TYPE_FLAG
,
1391 M_OPT_RANGE
, 0, 1, NULL
},
1392 { "sub_forced_only", mp_property_sub_forced_only
, CONF_TYPE_FLAG
,
1393 M_OPT_RANGE
, 0, 1, NULL
},
1396 { "tv_brightness", mp_property_tv_color
, CONF_TYPE_INT
,
1397 M_OPT_RANGE
, -100, 100, (void *) TV_COLOR_BRIGHTNESS
},
1398 { "tv_contrast", mp_property_tv_color
, CONF_TYPE_INT
,
1399 M_OPT_RANGE
, -100, 100, (void *) TV_COLOR_CONTRAST
},
1400 { "tv_saturation", mp_property_tv_color
, CONF_TYPE_INT
,
1401 M_OPT_RANGE
, -100, 100, (void *) TV_COLOR_SATURATION
},
1402 { "tv_hue", mp_property_tv_color
, CONF_TYPE_INT
,
1403 M_OPT_RANGE
, -100, 100, (void *) TV_COLOR_HUE
},
1406 { NULL
, NULL
, NULL
, 0, 0, 0, NULL
}
1410 m_option_t
*mp_property_find(const char *name
)
1412 return m_option_list_find(mp_properties
, name
);
1415 int mp_property_do(const char *name
, int action
, void *val
, void *ctx
)
1417 m_option_t
*p
= mp_property_find(name
);
1419 return M_PROPERTY_UNAVAILABLE
;
1420 return m_property_do(p
, action
, val
, ctx
);
1423 char *property_expand_string(MPContext
* mpctx
, char *str
)
1425 return m_properties_expand_string(mp_properties
, str
, mpctx
);
1428 void property_print_help(void)
1430 m_properties_print_help_list(mp_properties
);
1439 * \defgroup Command2Property Command to property bridge
1441 * It is used to handle most commands that just set a property
1442 * and optionally display something on the OSD.
1443 * Two kinds of commands are handled: adjust or toggle.
1445 * Adjust commands take 1 or 2 parameters: <value> <abs>
1446 * If <abs> is non-zero the property is set to the given value
1447 * otherwise it is adjusted.
1449 * Toggle commands take 0 or 1 parameters. With no parameter
1450 * or a value less than the property minimum it just steps the
1451 * property to its next value. Otherwise it sets it to the given
1457 /// List of the commands that can be handled by setting a property.
1463 /// set/adjust or toggle command
1465 /// progressbar type
1467 /// osd msg id if it must be shared
1469 /// osd msg template
1470 const char *osd_msg
;
1471 } set_prop_cmd
[] = {
1473 { "volume", MP_CMD_VOLUME
, 0, OSD_VOLUME
, -1, MSGTR_Volume
},
1474 { "mute", MP_CMD_MUTE
, 1, 0, -1, MSGTR_MuteStatus
},
1475 { "audio_delay", MP_CMD_AUDIO_DELAY
, 0, 0, -1, MSGTR_AVDelayStatus
},
1476 { "switch_audio", MP_CMD_SWITCH_AUDIO
, 1, 0, -1, MSGTR_OSDAudio
},
1478 { "fullscreen", MP_CMD_VO_FULLSCREEN
, 1, 0, -1, NULL
},
1479 { "panscan", MP_CMD_PANSCAN
, 0, OSD_PANSCAN
, -1, MSGTR_Panscan
},
1480 { "ontop", MP_CMD_VO_ONTOP
, 1, 0, -1, MSGTR_OnTopStatus
},
1481 { "rootwin", MP_CMD_VO_ROOTWIN
, 1, 0, -1, MSGTR_RootwinStatus
},
1482 { "border", MP_CMD_VO_BORDER
, 1, 0, -1, MSGTR_BorderStatus
},
1483 { "framedropping", MP_CMD_FRAMEDROPPING
, 1, 0, -1, MSGTR_FramedroppingStatus
},
1484 { "gamma", MP_CMD_GAMMA
, 0, OSD_BRIGHTNESS
, -1, MSGTR_Gamma
},
1485 { "brightness", MP_CMD_BRIGHTNESS
, 0, OSD_BRIGHTNESS
, -1, MSGTR_Brightness
},
1486 { "contrast", MP_CMD_CONTRAST
, 0, OSD_CONTRAST
, -1, MSGTR_Contrast
},
1487 { "saturation", MP_CMD_SATURATION
, 0, OSD_SATURATION
, -1, MSGTR_Saturation
},
1488 { "hue", MP_CMD_HUE
, 0, OSD_HUE
, -1, MSGTR_Hue
},
1489 { "vsync", MP_CMD_SWITCH_VSYNC
, 1, 0, -1, MSGTR_VSyncStatus
},
1491 { "sub", MP_CMD_SUB_SELECT
, 1, 0, -1, MSGTR_SubSelectStatus
},
1492 { "sub_pos", MP_CMD_SUB_POS
, 0, 0, -1, MSGTR_SubPosStatus
},
1493 { "sub_alignment", MP_CMD_SUB_ALIGNMENT
, 1, 0, -1, MSGTR_SubAlignStatus
},
1494 { "sub_delay", MP_CMD_SUB_DELAY
, 0, 0, OSD_MSG_SUB_DELAY
, MSGTR_SubDelayStatus
},
1495 { "sub_visibility", MP_CMD_SUB_VISIBILITY
, 1, 0, -1, MSGTR_SubVisibleStatus
},
1496 { "sub_forced_only", MP_CMD_SUB_FORCED_ONLY
, 1, 0, -1, MSGTR_SubForcedOnlyStatus
},
1498 { "tv_brightness", MP_CMD_TV_SET_BRIGHTNESS
, 0, OSD_BRIGHTNESS
, -1, MSGTR_Brightness
},
1499 { "tv_hue", MP_CMD_TV_SET_HUE
, 0, OSD_HUE
, -1, MSGTR_Hue
},
1500 { "tv_saturation", MP_CMD_TV_SET_SATURATION
, 0, OSD_SATURATION
, -1, MSGTR_Saturation
},
1501 { "tv_contrast", MP_CMD_TV_SET_CONTRAST
, 0, OSD_CONTRAST
, -1, MSGTR_Contrast
},
1503 { NULL
, 0, 0, 0, -1, NULL
}
1507 /// Handle commands that set a property.
1508 static int set_property_command(MPContext
* mpctx
, mp_cmd_t
* cmd
)
1513 // look for the command
1514 for (i
= 0; set_prop_cmd
[i
].name
; i
++)
1515 if (set_prop_cmd
[i
].cmd
== cmd
->id
)
1517 if (!set_prop_cmd
[i
].name
)
1521 prop
= mp_property_find(set_prop_cmd
[i
].name
);
1526 if (set_prop_cmd
[i
].toggle
) {
1528 if (cmd
->nargs
> 0 && cmd
->args
[0].v
.i
>= prop
->min
)
1529 r
= m_property_do(prop
, M_PROPERTY_SET
, &cmd
->args
[0].v
.i
, mpctx
);
1531 r
= m_property_do(prop
, M_PROPERTY_STEP_UP
, NULL
, mpctx
);
1532 } else if (cmd
->args
[1].v
.i
) //set
1533 r
= m_property_do(prop
, M_PROPERTY_SET
, &cmd
->args
[0].v
, mpctx
);
1535 r
= m_property_do(prop
, M_PROPERTY_STEP_UP
, &cmd
->args
[0].v
, mpctx
);
1540 if (set_prop_cmd
[i
].osd_progbar
) {
1541 if (prop
->type
== CONF_TYPE_INT
) {
1542 if (m_property_do(prop
, M_PROPERTY_GET
, &r
, mpctx
) > 0)
1543 set_osd_bar(set_prop_cmd
[i
].osd_progbar
,
1544 set_prop_cmd
[i
].osd_msg
, prop
->min
, prop
->max
, r
);
1545 } else if (prop
->type
== CONF_TYPE_FLOAT
) {
1547 if (m_property_do(prop
, M_PROPERTY_GET
, &f
, mpctx
) > 0)
1548 set_osd_bar(set_prop_cmd
[i
].osd_progbar
,
1549 set_prop_cmd
[i
].osd_msg
, prop
->min
, prop
->max
, f
);
1551 mp_msg(MSGT_CPLAYER
, MSGL_ERR
,
1552 "Property use an unsupported type.\n");
1556 if (set_prop_cmd
[i
].osd_msg
) {
1557 char *val
= m_property_print(prop
, mpctx
);
1559 set_osd_msg(set_prop_cmd
[i
].osd_id
>=
1560 0 ? set_prop_cmd
[i
].osd_id
: OSD_MSG_PROPERTY
+ i
,
1561 1, osd_duration
, set_prop_cmd
[i
].osd_msg
, val
);
1569 int run_command(MPContext
* mpctx
, mp_cmd_t
* cmd
)
1571 sh_audio_t
* const sh_audio
= mpctx
->sh_audio
;
1572 sh_video_t
* const sh_video
= mpctx
->sh_video
;
1574 if (!set_property_command(mpctx
, cmd
))
1580 mpctx
->osd_show_percentage
= sh_video
->fps
;
1581 v
= cmd
->args
[0].v
.f
;
1582 abs
= (cmd
->nargs
> 1) ? cmd
->args
[1].v
.i
: 0;
1583 if (abs
== 2) { /* Absolute seek to a specific timestamp in seconds */
1586 mpctx
->osd_function
=
1587 (v
> sh_video
->pts
) ? OSD_FFW
: OSD_REW
;
1589 } else if (abs
) { /* Absolute seek by percentage */
1592 mpctx
->osd_function
= OSD_FFW
; // Direction isn't set correctly
1593 rel_seek_secs
= v
/ 100.0;
1596 mpctx
->osd_function
= (v
> 0) ? OSD_FFW
: OSD_REW
;
1602 case MP_CMD_SET_PROPERTY
:{
1603 m_option_t
*prop
= mp_property_find(cmd
->args
[0].v
.s
);
1605 mp_msg(MSGT_CPLAYER
, MSGL_WARN
,
1606 "Unknown property: '%s'\n", cmd
->args
[0].v
.s
);
1607 else if (m_property_parse(prop
, cmd
->args
[1].v
.s
, mpctx
) <= 0)
1608 mp_msg(MSGT_CPLAYER
, MSGL_WARN
,
1609 "Failed to set property '%s' to '%s'.\n",
1610 cmd
->args
[0].v
.s
, cmd
->args
[1].v
.s
);
1614 case MP_CMD_STEP_PROPERTY
:{
1615 m_option_t
*prop
= mp_property_find(cmd
->args
[0].v
.s
);
1616 float arg
= cmd
->args
[1].v
.f
;
1618 mp_msg(MSGT_CPLAYER
, MSGL_WARN
,
1619 "Unknown property: '%s'\n", cmd
->args
[0].v
.s
);
1620 else if (m_property_do
1621 (prop
, M_PROPERTY_STEP_UP
,
1622 arg
? &arg
: NULL
, mpctx
) <= 0)
1623 mp_msg(MSGT_CPLAYER
, MSGL_WARN
,
1624 "Failed to increment property '%s' by %f.\n",
1625 cmd
->args
[0].v
.s
, arg
);
1629 case MP_CMD_GET_PROPERTY
:{
1633 prop
= mp_property_find(cmd
->args
[0].v
.s
);
1635 mp_msg(MSGT_CPLAYER
, MSGL_WARN
,
1636 "Unknown property: '%s'\n", cmd
->args
[0].v
.s
);
1639 /* Use m_option_print directly to get easily parseable values. */
1640 val
= calloc(1, prop
->type
->size
);
1641 if (m_property_do(prop
, M_PROPERTY_GET
, val
, mpctx
) <= 0) {
1642 mp_msg(MSGT_CPLAYER
, MSGL_WARN
,
1643 "Failed to get value of property '%s'.\n",
1647 tmp
= m_option_print(prop
, val
);
1648 if (!tmp
|| tmp
== (char *) -1) {
1649 mp_msg(MSGT_CPLAYER
, MSGL_WARN
,
1650 "Failed to print value of property '%s'.\n",
1654 mp_msg(MSGT_GLOBAL
, MSGL_INFO
, "ANS_%s=%s\n",
1655 cmd
->args
[0].v
.s
, tmp
);
1660 case MP_CMD_EDL_MARK
:
1662 float v
= sh_video
? sh_video
->pts
:
1663 playing_audio_pts(sh_audio
, mpctx
->d_audio
,
1666 if (mpctx
->begin_skip
== MP_NOPTS_VALUE
) {
1667 mpctx
->begin_skip
= v
;
1668 mp_msg(MSGT_CPLAYER
, MSGL_INFO
, MSGTR_EdloutStartSkip
);
1670 if (mpctx
->begin_skip
> v
)
1671 mp_msg(MSGT_CPLAYER
, MSGL_WARN
, MSGTR_EdloutBadStop
);
1673 fprintf(edl_fd
, "%f %f %d\n", mpctx
->begin_skip
, v
, 0);
1674 mp_msg(MSGT_CPLAYER
, MSGL_INFO
, MSGTR_EdloutEndSkip
);
1676 mpctx
->begin_skip
= MP_NOPTS_VALUE
;
1681 case MP_CMD_SWITCH_RATIO
:
1682 if (cmd
->nargs
== 0 || cmd
->args
[0].v
.f
== -1)
1683 movie_aspect
= (float) sh_video
->disp_w
/ sh_video
->disp_h
;
1685 movie_aspect
= cmd
->args
[0].v
.f
;
1686 mpcodecs_config_vo(sh_video
, sh_video
->disp_w
, sh_video
->disp_h
, 0);
1689 case MP_CMD_SPEED_INCR
:{
1690 float v
= cmd
->args
[0].v
.f
;
1691 playback_speed
+= v
;
1692 build_afilter_chain(sh_audio
, &ao_data
);
1693 set_osd_msg(OSD_MSG_SPEED
, 1, osd_duration
, MSGTR_OSDSpeed
,
1697 case MP_CMD_SPEED_MULT
:{
1698 float v
= cmd
->args
[0].v
.f
;
1699 playback_speed
*= v
;
1700 build_afilter_chain(sh_audio
, &ao_data
);
1701 set_osd_msg(OSD_MSG_SPEED
, 1, osd_duration
, MSGTR_OSDSpeed
,
1705 case MP_CMD_SPEED_SET
:{
1706 float v
= cmd
->args
[0].v
.f
;
1708 build_afilter_chain(sh_audio
, &ao_data
);
1709 set_osd_msg(OSD_MSG_SPEED
, 1, osd_duration
, MSGTR_OSDSpeed
,
1713 case MP_CMD_FRAME_STEP
:
1719 case MP_CMD_FILE_FILTER
:
1720 file_filter
= cmd
->args
[0].v
.i
;
1724 exit_player_with_rc(MSGTR_Exit_quit
,
1725 (cmd
->nargs
> 0) ? cmd
->args
[0].v
.i
: 0);
1727 case MP_CMD_PLAY_TREE_STEP
:{
1728 int n
= cmd
->args
[0].v
.i
== 0 ? 1 : cmd
->args
[0].v
.i
;
1729 int force
= cmd
->args
[1].v
.i
;
1735 for (i
= 0; i
< n
; i
++)
1738 for (i
= 0; i
< -1 * n
; i
++)
1743 if (!force
&& mpctx
->playtree_iter
) {
1744 play_tree_iter_t
*i
=
1745 play_tree_iter_new_copy(mpctx
->playtree_iter
);
1746 if (play_tree_iter_step(i
, n
, 0) ==
1747 PLAY_TREE_ITER_ENTRY
)
1749 (n
> 0) ? PT_NEXT_ENTRY
: PT_PREV_ENTRY
;
1750 play_tree_iter_free(i
);
1752 mpctx
->eof
= (n
> 0) ? PT_NEXT_ENTRY
: PT_PREV_ENTRY
;
1754 mpctx
->play_tree_step
= n
;
1760 case MP_CMD_PLAY_TREE_UP_STEP
:{
1761 int n
= cmd
->args
[0].v
.i
> 0 ? 1 : -1;
1762 int force
= cmd
->args
[1].v
.i
;
1764 if (!force
&& mpctx
->playtree_iter
) {
1765 play_tree_iter_t
*i
=
1766 play_tree_iter_new_copy(mpctx
->playtree_iter
);
1767 if (play_tree_iter_up_step(i
, n
, 0) == PLAY_TREE_ITER_ENTRY
)
1768 mpctx
->eof
= (n
> 0) ? PT_UP_NEXT
: PT_UP_PREV
;
1769 play_tree_iter_free(i
);
1771 mpctx
->eof
= (n
> 0) ? PT_UP_NEXT
: PT_UP_PREV
;
1776 case MP_CMD_PLAY_ALT_SRC_STEP
:
1777 if (mpctx
->playtree_iter
&& mpctx
->playtree_iter
->num_files
> 1) {
1778 int v
= cmd
->args
[0].v
.i
;
1780 && mpctx
->playtree_iter
->file
<
1781 mpctx
->playtree_iter
->num_files
)
1782 mpctx
->eof
= PT_NEXT_SRC
;
1783 else if (v
< 0 && mpctx
->playtree_iter
->file
> 1)
1784 mpctx
->eof
= PT_PREV_SRC
;
1789 case MP_CMD_SUB_STEP
:
1791 int movement
= cmd
->args
[0].v
.i
;
1792 step_sub(subdata
, sh_video
->pts
, movement
);
1796 ass_step_sub(ass_track
,
1798 sub_delay
) * 1000 + .5, movement
) / 1000.;
1800 set_osd_msg(OSD_MSG_SUB_DELAY
, 1, osd_duration
,
1801 MSGTR_OSDSubDelay
, ROUND(sub_delay
* 1000));
1805 case MP_CMD_SUB_LOG
:
1810 int v
= cmd
->args
[0].v
.i
;
1812 && !sh_video
) ? MAX_TERM_OSD_LEVEL
: MAX_OSD_LEVEL
;
1813 if (osd_level
> max
)
1816 osd_level
= (osd_level
+ 1) % (max
+ 1);
1818 osd_level
= v
> max
? max
: v
;
1819 /* Show OSD state when disabled, but not when an explicit
1820 argument is given to the OSD command, i.e. in slave mode. */
1821 if (v
== -1 && osd_level
<= 1)
1822 set_osd_msg(OSD_MSG_OSD_STATUS
, 0, osd_duration
,
1824 osd_level
? MSGTR_OSDenabled
:
1827 rm_osd_msg(OSD_MSG_OSD_STATUS
);
1831 case MP_CMD_OSD_SHOW_TEXT
:
1832 set_osd_msg(OSD_MSG_TEXT
, cmd
->args
[2].v
.i
,
1834 0 ? osd_duration
: cmd
->args
[1].v
.i
),
1835 "%-.63s", cmd
->args
[0].v
.s
);
1838 case MP_CMD_OSD_SHOW_PROPERTY_TEXT
:{
1839 char *txt
= m_properties_expand_string(mp_properties
,
1842 /* if no argument supplied take default osd_duration, else <arg> ms. */
1844 set_osd_msg(OSD_MSG_TEXT
, cmd
->args
[2].v
.i
,
1846 0 ? osd_duration
: cmd
->args
[1].v
.i
),
1853 case MP_CMD_LOADFILE
:{
1854 play_tree_t
*e
= play_tree_new();
1855 play_tree_add_file(e
, cmd
->args
[0].v
.s
);
1857 if (cmd
->args
[1].v
.i
) // append
1858 play_tree_append_entry(mpctx
->playtree
, e
);
1860 // Go back to the starting point.
1861 while (play_tree_iter_up_step
1862 (mpctx
->playtree_iter
, 0, 1) != PLAY_TREE_ITER_END
)
1864 play_tree_free_list(mpctx
->playtree
->child
, 1);
1865 play_tree_set_child(mpctx
->playtree
, e
);
1866 play_tree_iter_step(mpctx
->playtree_iter
, 0, 0);
1867 mpctx
->eof
= PT_NEXT_SRC
;
1873 case MP_CMD_LOADLIST
:{
1874 play_tree_t
*e
= parse_playlist_file(cmd
->args
[0].v
.s
);
1876 mp_msg(MSGT_CPLAYER
, MSGL_ERR
,
1877 MSGTR_PlaylistLoadUnable
, cmd
->args
[0].v
.s
);
1879 if (cmd
->args
[1].v
.i
) // append
1880 play_tree_append_entry(mpctx
->playtree
, e
);
1882 // Go back to the starting point.
1883 while (play_tree_iter_up_step
1884 (mpctx
->playtree_iter
, 0, 1)
1885 != PLAY_TREE_ITER_END
)
1887 play_tree_free_list(mpctx
->playtree
->child
, 1);
1888 play_tree_set_child(mpctx
->playtree
, e
);
1889 play_tree_iter_step(mpctx
->playtree_iter
, 0, 0);
1890 mpctx
->eof
= PT_NEXT_SRC
;
1898 case MP_CMD_RADIO_STEP_CHANNEL
:
1899 if (mpctx
->demuxer
->stream
->type
== STREAMTYPE_RADIO
) {
1900 int v
= cmd
->args
[0].v
.i
;
1902 radio_step_channel(mpctx
->demuxer
->stream
,
1903 RADIO_CHANNEL_HIGHER
);
1905 radio_step_channel(mpctx
->demuxer
->stream
,
1906 RADIO_CHANNEL_LOWER
);
1907 if (radio_get_channel_name(mpctx
->demuxer
->stream
)) {
1908 set_osd_msg(OSD_MSG_RADIO_CHANNEL
, 1, osd_duration
,
1910 radio_get_channel_name(mpctx
->demuxer
->stream
));
1915 case MP_CMD_RADIO_SET_CHANNEL
:
1916 if (mpctx
->demuxer
->stream
->type
== STREAMTYPE_RADIO
) {
1917 radio_set_channel(mpctx
->demuxer
->stream
, cmd
->args
[0].v
.s
);
1918 if (radio_get_channel_name(mpctx
->demuxer
->stream
)) {
1919 set_osd_msg(OSD_MSG_RADIO_CHANNEL
, 1, osd_duration
,
1921 radio_get_channel_name(mpctx
->demuxer
->stream
));
1926 case MP_CMD_RADIO_SET_FREQ
:
1927 if (mpctx
->demuxer
->stream
->type
== STREAMTYPE_RADIO
)
1928 radio_set_freq(mpctx
->demuxer
->stream
, cmd
->args
[0].v
.f
);
1931 case MP_CMD_RADIO_STEP_FREQ
:
1932 if (mpctx
->demuxer
->stream
->type
== STREAMTYPE_RADIO
)
1933 radio_step_freq(mpctx
->demuxer
->stream
, cmd
->args
[0].v
.f
);
1938 case MP_CMD_TV_SET_FREQ
:
1939 if (mpctx
->file_format
== DEMUXER_TYPE_TV
)
1940 tv_set_freq((tvi_handle_t
*) (mpctx
->demuxer
->priv
),
1941 cmd
->args
[0].v
.f
* 16.0);
1944 case MP_CMD_TV_STEP_FREQ
:
1945 if (mpctx
->file_format
== DEMUXER_TYPE_TV
)
1946 tv_step_freq((tvi_handle_t
*) (mpctx
->demuxer
->priv
),
1947 cmd
->args
[0].v
.f
* 16.0);
1950 case MP_CMD_TV_SET_NORM
:
1951 if (mpctx
->file_format
== DEMUXER_TYPE_TV
)
1952 tv_set_norm((tvi_handle_t
*) (mpctx
->demuxer
->priv
),
1956 case MP_CMD_TV_STEP_CHANNEL
:{
1957 if (mpctx
->file_format
== DEMUXER_TYPE_TV
) {
1958 int v
= cmd
->args
[0].v
.i
;
1960 tv_step_channel((tvi_handle_t
*) (mpctx
->
1964 tv_step_channel((tvi_handle_t
*) (mpctx
->
1968 if (tv_channel_list
) {
1969 set_osd_msg(OSD_MSG_TV_CHANNEL
, 1, osd_duration
,
1970 MSGTR_OSDChannel
, tv_channel_current
->name
);
1971 //vo_osd_changed(OSDTYPE_SUBTITLE);
1975 #ifdef HAS_DVBIN_SUPPORT
1976 if ((mpctx
->stream
->type
== STREAMTYPE_DVB
)
1977 && mpctx
->stream
->priv
) {
1978 dvb_priv_t
*priv
= (dvb_priv_t
*) mpctx
->stream
->priv
;
1981 int v
= cmd
->args
[0].v
.i
;
1983 mpctx
->last_dvb_step
= v
;
1985 dir
= DVB_CHANNEL_HIGHER
;
1987 dir
= DVB_CHANNEL_LOWER
;
1990 if (dvb_step_channel(priv
, dir
))
1991 mpctx
->eof
= mpctx
->dvbin_reopen
= 1;
1994 #endif /* HAS_DVBIN_SUPPORT */
1997 case MP_CMD_TV_SET_CHANNEL
:
1998 if (mpctx
->file_format
== DEMUXER_TYPE_TV
) {
1999 tv_set_channel((tvi_handle_t
*) (mpctx
->demuxer
->priv
),
2001 if (tv_channel_list
) {
2002 set_osd_msg(OSD_MSG_TV_CHANNEL
, 1, osd_duration
,
2003 MSGTR_OSDChannel
, tv_channel_current
->name
);
2004 //vo_osd_changed(OSDTYPE_SUBTITLE);
2009 #ifdef HAS_DVBIN_SUPPORT
2010 case MP_CMD_DVB_SET_CHANNEL
:
2011 if ((mpctx
->stream
->type
== STREAMTYPE_DVB
)
2012 && mpctx
->stream
->priv
) {
2013 dvb_priv_t
*priv
= (dvb_priv_t
*) mpctx
->stream
->priv
;
2015 if (priv
->list
->current
<= cmd
->args
[0].v
.i
)
2016 mpctx
->last_dvb_step
= 1;
2018 mpctx
->last_dvb_step
= -1;
2021 (priv
, cmd
->args
[1].v
.i
, cmd
->args
[0].v
.i
))
2022 mpctx
->eof
= mpctx
->dvbin_reopen
= 1;
2026 #endif /* HAS_DVBIN_SUPPORT */
2028 case MP_CMD_TV_LAST_CHANNEL
:
2029 if (mpctx
->file_format
== DEMUXER_TYPE_TV
) {
2030 tv_last_channel((tvi_handle_t
*) (mpctx
->demuxer
->priv
));
2031 if (tv_channel_list
) {
2032 set_osd_msg(OSD_MSG_TV_CHANNEL
, 1, osd_duration
,
2033 MSGTR_OSDChannel
, tv_channel_current
->name
);
2034 //vo_osd_changed(OSDTYPE_SUBTITLE);
2039 case MP_CMD_TV_STEP_NORM
:
2040 if (mpctx
->file_format
== DEMUXER_TYPE_TV
)
2041 tv_step_norm((tvi_handle_t
*) (mpctx
->demuxer
->priv
));
2044 case MP_CMD_TV_STEP_CHANNEL_LIST
:
2045 if (mpctx
->file_format
== DEMUXER_TYPE_TV
)
2046 tv_step_chanlist((tvi_handle_t
*) (mpctx
->demuxer
->priv
));
2050 case MP_CMD_SUB_LOAD
:
2052 int n
= mpctx
->set_of_sub_size
;
2053 add_subtitles(cmd
->args
[0].v
.s
, sh_video
->fps
, 0);
2054 if (n
!= mpctx
->set_of_sub_size
) {
2055 if (mpctx
->global_sub_indices
[SUB_SOURCE_SUBS
] < 0)
2056 mpctx
->global_sub_indices
[SUB_SOURCE_SUBS
] =
2057 mpctx
->global_sub_size
;
2058 ++mpctx
->global_sub_size
;
2063 case MP_CMD_SUB_REMOVE
:
2065 int v
= cmd
->args
[0].v
.i
;
2068 for (v
= 0; v
< mpctx
->set_of_sub_size
; ++v
) {
2069 subd
= mpctx
->set_of_subtitles
[v
];
2070 mp_msg(MSGT_CPLAYER
, MSGL_STATUS
,
2071 MSGTR_RemovedSubtitleFile
, v
+ 1,
2072 filename_recode(subd
->filename
));
2074 mpctx
->set_of_subtitles
[v
] = NULL
;
2076 mpctx
->global_sub_indices
[SUB_SOURCE_SUBS
] = -1;
2077 mpctx
->global_sub_size
-= mpctx
->set_of_sub_size
;
2078 mpctx
->set_of_sub_size
= 0;
2079 if (mpctx
->set_of_sub_pos
>= 0) {
2080 mpctx
->global_sub_pos
= -2;
2081 vo_sub_last
= vo_sub
= NULL
;
2082 vo_osd_changed(OSDTYPE_SUBTITLE
);
2083 vo_update_osd(sh_video
->disp_w
, sh_video
->disp_h
);
2084 mp_input_queue_cmd(mp_input_parse_cmd("sub_select"));
2086 } else if (v
< mpctx
->set_of_sub_size
) {
2087 subd
= mpctx
->set_of_subtitles
[v
];
2088 mp_msg(MSGT_CPLAYER
, MSGL_STATUS
,
2089 MSGTR_RemovedSubtitleFile
, v
+ 1,
2090 filename_recode(subd
->filename
));
2092 if (mpctx
->set_of_sub_pos
== v
) {
2093 mpctx
->global_sub_pos
= -2;
2094 vo_sub_last
= vo_sub
= NULL
;
2095 vo_osd_changed(OSDTYPE_SUBTITLE
);
2096 vo_update_osd(sh_video
->disp_w
, sh_video
->disp_h
);
2097 mp_input_queue_cmd(mp_input_parse_cmd("sub_select"));
2098 } else if (mpctx
->set_of_sub_pos
> v
) {
2099 --mpctx
->set_of_sub_pos
;
2100 --mpctx
->global_sub_pos
;
2102 while (++v
< mpctx
->set_of_sub_size
)
2103 mpctx
->set_of_subtitles
[v
- 1] =
2104 mpctx
->set_of_subtitles
[v
];
2105 --mpctx
->set_of_sub_size
;
2106 --mpctx
->global_sub_size
;
2107 if (mpctx
->set_of_sub_size
<= 0)
2108 mpctx
->global_sub_indices
[SUB_SOURCE_SUBS
] = -1;
2109 mpctx
->set_of_subtitles
[mpctx
->set_of_sub_size
] = NULL
;
2114 case MP_CMD_GET_SUB_VISIBILITY
:
2116 mp_msg(MSGT_GLOBAL
, MSGL_INFO
,
2117 "ANS_SUB_VISIBILITY=%d\n", sub_visibility
);
2121 case MP_CMD_SCREENSHOT
:
2122 if (vo_config_count
) {
2123 mp_msg(MSGT_CPLAYER
, MSGL_INFO
, "sending VFCTRL_SCREENSHOT!\n");
2125 ((vf_instance_t
*) sh_video
->vfilter
)->
2126 control(sh_video
->vfilter
, VFCTRL_SCREENSHOT
,
2128 mpctx
->video_out
->control(VOCTRL_SCREENSHOT
, NULL
);
2132 case MP_CMD_VF_CHANGE_RECTANGLE
:
2133 set_rectangle(sh_video
, cmd
->args
[0].v
.i
, cmd
->args
[1].v
.i
);
2136 case MP_CMD_GET_TIME_LENGTH
:{
2137 mp_msg(MSGT_GLOBAL
, MSGL_INFO
, "ANS_LENGTH=%.2lf\n",
2138 demuxer_get_time_length(mpctx
->demuxer
));
2142 case MP_CMD_GET_FILENAME
:{
2143 mp_msg(MSGT_GLOBAL
, MSGL_INFO
, "ANS_FILENAME='%s'\n",
2144 get_metadata(META_NAME
));
2148 case MP_CMD_GET_VIDEO_CODEC
:{
2149 char *inf
= get_metadata(META_VIDEO_CODEC
);
2152 mp_msg(MSGT_GLOBAL
, MSGL_INFO
, "ANS_VIDEO_CODEC='%s'\n", inf
);
2157 case MP_CMD_GET_VIDEO_BITRATE
:{
2158 char *inf
= get_metadata(META_VIDEO_BITRATE
);
2161 mp_msg(MSGT_GLOBAL
, MSGL_INFO
, "ANS_VIDEO_BITRATE='%s'\n", inf
);
2166 case MP_CMD_GET_VIDEO_RESOLUTION
:{
2167 char *inf
= get_metadata(META_VIDEO_RESOLUTION
);
2170 mp_msg(MSGT_GLOBAL
, MSGL_INFO
,
2171 "ANS_VIDEO_RESOLUTION='%s'\n", inf
);
2176 case MP_CMD_GET_AUDIO_CODEC
:{
2177 char *inf
= get_metadata(META_AUDIO_CODEC
);
2180 mp_msg(MSGT_GLOBAL
, MSGL_INFO
, "ANS_AUDIO_CODEC='%s'\n", inf
);
2185 case MP_CMD_GET_AUDIO_BITRATE
:{
2186 char *inf
= get_metadata(META_AUDIO_BITRATE
);
2189 mp_msg(MSGT_GLOBAL
, MSGL_INFO
, "ANS_AUDIO_BITRATE='%s'\n", inf
);
2194 case MP_CMD_GET_AUDIO_SAMPLES
:{
2195 char *inf
= get_metadata(META_AUDIO_SAMPLES
);
2198 mp_msg(MSGT_GLOBAL
, MSGL_INFO
, "ANS_AUDIO_SAMPLES='%s'\n", inf
);
2203 case MP_CMD_GET_META_TITLE
:{
2204 char *inf
= get_metadata(META_INFO_TITLE
);
2207 mp_msg(MSGT_GLOBAL
, MSGL_INFO
, "ANS_META_TITLE='%s'\n", inf
);
2212 case MP_CMD_GET_META_ARTIST
:{
2213 char *inf
= get_metadata(META_INFO_ARTIST
);
2216 mp_msg(MSGT_GLOBAL
, MSGL_INFO
, "ANS_META_ARTIST='%s'\n", inf
);
2221 case MP_CMD_GET_META_ALBUM
:{
2222 char *inf
= get_metadata(META_INFO_ALBUM
);
2225 mp_msg(MSGT_GLOBAL
, MSGL_INFO
, "ANS_META_ALBUM='%s'\n", inf
);
2230 case MP_CMD_GET_META_YEAR
:{
2231 char *inf
= get_metadata(META_INFO_YEAR
);
2234 mp_msg(MSGT_GLOBAL
, MSGL_INFO
, "ANS_META_YEAR='%s'\n", inf
);
2239 case MP_CMD_GET_META_COMMENT
:{
2240 char *inf
= get_metadata(META_INFO_COMMENT
);
2243 mp_msg(MSGT_GLOBAL
, MSGL_INFO
, "ANS_META_COMMENT='%s'\n", inf
);
2248 case MP_CMD_GET_META_TRACK
:{
2249 char *inf
= get_metadata(META_INFO_TRACK
);
2252 mp_msg(MSGT_GLOBAL
, MSGL_INFO
, "ANS_META_TRACK='%s'\n", inf
);
2257 case MP_CMD_GET_META_GENRE
:{
2258 char *inf
= get_metadata(META_INFO_GENRE
);
2261 mp_msg(MSGT_GLOBAL
, MSGL_INFO
, "ANS_META_GENRE='%s'\n", inf
);
2266 case MP_CMD_GET_VO_FULLSCREEN
:
2267 if (mpctx
->video_out
&& vo_config_count
)
2268 mp_msg(MSGT_GLOBAL
, MSGL_INFO
, "ANS_VO_FULLSCREEN=%d\n", vo_fs
);
2271 case MP_CMD_GET_PERCENT_POS
:
2272 mp_msg(MSGT_GLOBAL
, MSGL_INFO
, "ANS_PERCENT_POSITION=%d\n",
2273 demuxer_get_percent_pos(mpctx
->demuxer
));
2276 case MP_CMD_GET_TIME_POS
:{
2279 pos
= sh_video
->pts
;
2280 else if (sh_audio
&& mpctx
->audio_out
)
2282 playing_audio_pts(sh_audio
, mpctx
->d_audio
,
2284 mp_msg(MSGT_GLOBAL
, MSGL_INFO
, "ANS_TIME_POSITION=%.1f\n", pos
);
2291 execl("/bin/sh", "sh", "-c", cmd
->args
[0].v
.s
, NULL
);
2297 case MP_CMD_KEYDOWN_EVENTS
:
2298 mplayer_put_key(cmd
->args
[0].v
.i
);
2301 case MP_CMD_SEEK_CHAPTER
:{
2302 int seek
= cmd
->args
[0].v
.i
;
2303 int abs
= (cmd
->nargs
> 1) ? cmd
->args
[1].v
.i
: 0;
2312 demuxer_seek_chapter(mpctx
->demuxer
, seek
, abs
,
2313 &next_pts
, &num_chapters
,
2316 if (next_pts
> -1.0) {
2318 rel_seek_secs
= next_pts
;
2321 set_osd_msg(OSD_MSG_TEXT
, 1, osd_duration
,
2322 MSGTR_OSDChapter
, chap
+ 1, chapter_name
);
2327 rel_seek_secs
= 1000000000.;
2329 set_osd_msg(OSD_MSG_TEXT
, 1, osd_duration
,
2330 MSGTR_OSDChapter
, 0, MSGTR_Unknown
);
2336 case MP_CMD_SET_MOUSE_POS
:{
2337 int button
= -1, pointer_x
, pointer_y
;
2339 pointer_x
= cmd
->args
[0].v
.i
;
2340 pointer_y
= cmd
->args
[1].v
.i
;
2341 rescale_input_coordinates(pointer_x
, pointer_y
, &dx
, &dy
);
2343 if (mpctx
->stream
->type
== STREAMTYPE_DVDNAV
2344 && dx
> 0.0 && dy
> 0.0) {
2345 pointer_x
= (int) (dx
* (double) sh_video
->disp_w
);
2346 pointer_y
= (int) (dy
* (double) sh_video
->disp_h
);
2347 mp_dvdnav_update_mouse_pos(mpctx
->stream
,
2348 pointer_x
, pointer_y
, &button
);
2350 set_osd_msg(OSD_MSG_TEXT
, 1, osd_duration
,
2351 "Selected button number %d", button
);
2358 case MP_CMD_DVDNAV
:{
2360 if (mpctx
->stream
->type
!= STREAMTYPE_DVDNAV
)
2363 if (mp_dvdnav_handle_input
2364 (mpctx
->stream
, cmd
->args
[0].v
.i
, &button
)) {
2365 uninit_player(INITED_ALL
- (INITED_STREAM
| INITED_INPUT
|
2366 (fixed_vo
? INITED_VO
: 0)));
2368 } else if (button
> 0)
2369 set_osd_msg(OSD_MSG_TEXT
, 1, osd_duration
,
2370 "Selected button number %d", button
);
2377 if ((use_gui
) && (cmd
->id
> MP_CMD_GUI_EVENTS
))
2378 guiGetEvent(guiIEvent
, (char *) cmd
->id
);
2381 mp_msg(MSGT_CPLAYER
, MSGL_V
,
2382 "Received unknown cmd %s\n", cmd
->name
);
2385 switch (cmd
->pausing
) {
2386 case 1: // "pausing"
2387 mpctx
->osd_function
= OSD_PAUSE
;
2389 case 3: // "pausing_toggle"
2390 mpctx
->was_paused
= !mpctx
->was_paused
;
2392 case 2: // "pausing_keep"
2393 if (mpctx
->was_paused
)
2394 mpctx
->osd_function
= OSD_PAUSE
;