You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1114 lines
32 KiB
1114 lines
32 KiB
/*****************************************************************************
|
|
* player.c : remote control stdin/stdout module for vlc
|
|
*****************************************************************************
|
|
* Copyright (C) 2004-2009 the VideoLAN team
|
|
*
|
|
* Author: Peter Surda <shurdeek@panorama.sth.ac.at>
|
|
* Jean-Paul Saman <jpsaman #_at_# m2x _replaceWith#dot_ nl>
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
|
|
*****************************************************************************/
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
# include "config.h"
|
|
#endif
|
|
|
|
#include <assert.h>
|
|
#include <math.h>
|
|
|
|
#include <vlc_common.h>
|
|
#include <vlc_interface.h>
|
|
#include <vlc_aout.h>
|
|
#include <vlc_vout.h>
|
|
#include <vlc_player.h>
|
|
|
|
#include "cli.h"
|
|
|
|
struct player_cli {
|
|
intf_thread_t *intf;
|
|
vlc_player_listener_id *player_listener;
|
|
vlc_player_aout_listener_id *player_aout_listener;
|
|
long position;
|
|
bool input_buffering;
|
|
bool show_position;
|
|
};
|
|
|
|
/********************************************************************
|
|
* Status callback routines
|
|
********************************************************************/
|
|
|
|
static void
|
|
player_on_media_changed(vlc_player_t *player, input_item_t *item, void *data)
|
|
{
|
|
struct player_cli *pc = data;
|
|
intf_thread_t *p_intf = pc->intf;
|
|
|
|
(void) player;
|
|
|
|
if (item != NULL)
|
|
{
|
|
vlc_mutex_lock(&item->lock);
|
|
msg_rc(STATUS_CHANGE "( new input: %s )", item->psz_uri);
|
|
vlc_mutex_unlock(&item->lock);
|
|
}
|
|
}
|
|
|
|
static void
|
|
player_on_state_changed(vlc_player_t *player,
|
|
enum vlc_player_state state, void *data)
|
|
{ VLC_UNUSED(player);
|
|
struct player_cli *pc = data;
|
|
intf_thread_t *p_intf = pc->intf;
|
|
|
|
char const *psz_cmd;
|
|
switch (state)
|
|
{
|
|
case VLC_PLAYER_STATE_STOPPING:
|
|
case VLC_PLAYER_STATE_STOPPED:
|
|
psz_cmd = "stop";
|
|
break;
|
|
case VLC_PLAYER_STATE_PLAYING:
|
|
psz_cmd = "play";
|
|
break;
|
|
case VLC_PLAYER_STATE_PAUSED:
|
|
psz_cmd = "pause";
|
|
break;
|
|
default:
|
|
psz_cmd = "";
|
|
break;
|
|
}
|
|
|
|
msg_rc(STATUS_CHANGE "( %s state: %d )", psz_cmd, state);
|
|
}
|
|
|
|
static void
|
|
player_on_buffering_changed(vlc_player_t *player,
|
|
float new_buffering, void *data)
|
|
{ VLC_UNUSED(player); VLC_UNUSED(new_buffering);
|
|
struct player_cli *pc = data;
|
|
|
|
pc->input_buffering = true;
|
|
}
|
|
|
|
static void
|
|
player_on_rate_changed(vlc_player_t *player, float new_rate, void *data)
|
|
{ VLC_UNUSED(player);
|
|
struct player_cli *pc = data;
|
|
intf_thread_t *p_intf = pc->intf;
|
|
|
|
msg_rc(STATUS_CHANGE "( new rate: %.3f )", new_rate);
|
|
}
|
|
|
|
static void
|
|
player_on_position_changed(vlc_player_t *player,
|
|
vlc_tick_t new_time, float new_pos, void *data)
|
|
{ VLC_UNUSED(player); VLC_UNUSED(new_pos);
|
|
struct player_cli *pc = data;
|
|
intf_thread_t *p_intf = pc->intf;
|
|
|
|
if (pc->input_buffering)
|
|
{
|
|
msg_rc(STATUS_CHANGE "( time: %"PRId64"s )",
|
|
SEC_FROM_VLC_TICK(new_time));
|
|
pc->input_buffering = false;
|
|
}
|
|
|
|
long position = lroundf(new_pos * 100.f);
|
|
|
|
if (pc->show_position && position != pc->position)
|
|
{
|
|
pc->position = position;
|
|
msg_rc("pos: %ld%%", pc->position);
|
|
}
|
|
}
|
|
|
|
static const struct vlc_player_cbs player_cbs =
|
|
{
|
|
.on_current_media_changed = player_on_media_changed,
|
|
.on_state_changed = player_on_state_changed,
|
|
.on_buffering_changed = player_on_buffering_changed,
|
|
.on_rate_changed = player_on_rate_changed,
|
|
.on_position_changed = player_on_position_changed,
|
|
};
|
|
|
|
static void
|
|
player_aout_on_volume_changed(audio_output_t *aout, float volume, void *data)
|
|
{ VLC_UNUSED(aout);
|
|
struct player_cli *pc = data;
|
|
intf_thread_t *p_intf = pc->intf;
|
|
|
|
msg_rc(STATUS_CHANGE "( audio volume: %f )", volume);
|
|
}
|
|
|
|
static const struct vlc_player_aout_cbs player_aout_cbs =
|
|
{
|
|
.on_volume_changed = player_aout_on_volume_changed,
|
|
};
|
|
|
|
static int PlayerDoVoid(intf_thread_t *intf, void (*cb)(vlc_player_t *))
|
|
{
|
|
vlc_playlist_t *playlist = intf->p_sys->playlist;
|
|
vlc_player_t *player = vlc_playlist_GetPlayer(playlist);
|
|
|
|
vlc_player_Lock(player);
|
|
cb(player);
|
|
vlc_player_Unlock(player);
|
|
return 0;
|
|
}
|
|
|
|
static int PlayerDoFloat(intf_thread_t *intf, const char *const *args,
|
|
size_t count,
|
|
void (*setter)(vlc_player_t *, float),
|
|
float (*getter)(vlc_player_t *))
|
|
{
|
|
vlc_playlist_t *playlist = intf->p_sys->playlist;
|
|
vlc_player_t *player = vlc_playlist_GetPlayer(playlist);
|
|
int ret = 0;
|
|
|
|
vlc_player_Lock(player);
|
|
switch (count)
|
|
{
|
|
case 1:
|
|
msg_print(intf, "%f", getter(player));
|
|
break;
|
|
case 2:
|
|
setter(player, atof(args[1]));
|
|
break;
|
|
default:
|
|
ret = VLC_EGENERIC; /* EINVAL */
|
|
}
|
|
vlc_player_Unlock(player);
|
|
return ret;
|
|
}
|
|
|
|
static int PlayerPause(intf_thread_t *intf, const char *const *args,
|
|
size_t count)
|
|
{
|
|
(void) args; (void) count;
|
|
return PlayerDoVoid(intf, vlc_player_TogglePause);
|
|
}
|
|
|
|
static int PlayerFastForward(intf_thread_t *intf, const char *const *args,
|
|
size_t count)
|
|
{
|
|
vlc_playlist_t *playlist = intf->p_sys->playlist;
|
|
vlc_player_t *player = vlc_playlist_GetPlayer(playlist);
|
|
|
|
vlc_player_Lock(player);
|
|
if (vlc_player_CanChangeRate(player))
|
|
{
|
|
float rate = vlc_player_GetRate(player);
|
|
vlc_player_ChangeRate(player,
|
|
isgreater(rate, 0.f) ? rate * 2.f : -rate);
|
|
}
|
|
else
|
|
{
|
|
int secs = var_InheritInteger(intf, "extrashort-jump-size");
|
|
vlc_tick_t t = vlc_player_GetTime(player) + vlc_tick_from_sec(secs);
|
|
|
|
vlc_player_SetTime(player, t);
|
|
}
|
|
vlc_player_Unlock(player);
|
|
(void) args; (void) count;
|
|
return 0;
|
|
}
|
|
|
|
static int PlayerRewind(intf_thread_t *intf, const char *const *args,
|
|
size_t count)
|
|
{
|
|
vlc_playlist_t *playlist = intf->p_sys->playlist;
|
|
vlc_player_t *player = vlc_playlist_GetPlayer(playlist);
|
|
|
|
vlc_player_Lock(player);
|
|
if (vlc_player_CanRewind(player))
|
|
{
|
|
float rate = vlc_player_GetRate(player);
|
|
vlc_player_ChangeRate(player, isless(rate, 0.f) ? rate * 2.f : -rate);
|
|
}
|
|
else
|
|
{
|
|
int secs = var_InheritInteger(intf, "extrashort-jump-size");
|
|
vlc_tick_t t = vlc_player_GetTime(player) - vlc_tick_from_sec(secs);
|
|
|
|
vlc_player_SetTime(player, t);
|
|
}
|
|
vlc_player_Unlock(player);
|
|
(void) args; (void) count;
|
|
return 0;
|
|
}
|
|
|
|
static int PlayerFaster(intf_thread_t *intf, const char *const *args,
|
|
size_t count)
|
|
{
|
|
(void) args; (void) count;
|
|
return PlayerDoVoid(intf, vlc_player_IncrementRate);
|
|
}
|
|
|
|
static int PlayerSlower(intf_thread_t *intf, const char *const *args,
|
|
size_t count)
|
|
{
|
|
(void) args; (void) count;
|
|
return PlayerDoVoid(intf, vlc_player_DecrementRate);
|
|
}
|
|
|
|
static void PlayerDoNormal(vlc_player_t *player)
|
|
{
|
|
vlc_player_ChangeRate(player, 1.f);
|
|
}
|
|
|
|
static int PlayerNormal(intf_thread_t *intf, const char *const *args,
|
|
size_t count)
|
|
{
|
|
(void) args; (void) count;
|
|
return PlayerDoVoid(intf, PlayerDoNormal);
|
|
}
|
|
|
|
static int PlayerRate(intf_thread_t *intf, const char *const *args, size_t n)
|
|
{
|
|
return PlayerDoFloat(intf, args, n, vlc_player_ChangeRate,
|
|
vlc_player_GetRate);
|
|
}
|
|
|
|
static int PlayerFrame(intf_thread_t *intf, const char *const *args,
|
|
size_t count)
|
|
{
|
|
(void) args; (void) count;
|
|
return PlayerDoVoid(intf, vlc_player_NextVideoFrame);
|
|
}
|
|
|
|
static int PlayerChapterPrev(intf_thread_t *intf, const char *const *args,
|
|
size_t count)
|
|
{
|
|
(void) args; (void) count;
|
|
return PlayerDoVoid(intf, vlc_player_SelectPrevChapter);
|
|
}
|
|
|
|
static int PlayerChapterNext(intf_thread_t *intf, const char *const *args,
|
|
size_t count)
|
|
{
|
|
(void) args; (void) count;
|
|
return PlayerDoVoid(intf, vlc_player_SelectNextChapter);
|
|
}
|
|
|
|
static int PlayerTitlePrev(intf_thread_t *intf, const char *const *args,
|
|
size_t count)
|
|
{
|
|
(void) args; (void) count;
|
|
return PlayerDoVoid(intf, vlc_player_SelectPrevTitle);
|
|
}
|
|
|
|
static int PlayerTitleNext(intf_thread_t *intf, const char *const *args,
|
|
size_t count)
|
|
{
|
|
(void) args; (void) count;
|
|
return PlayerDoVoid(intf, vlc_player_SelectNextTitle);
|
|
}
|
|
|
|
static int PlayerSeek(intf_thread_t *intf, const char *const *args,
|
|
size_t count)
|
|
{
|
|
vlc_player_t *player = vlc_playlist_GetPlayer(intf->p_sys->playlist);
|
|
|
|
if (count != 2)
|
|
{
|
|
msg_print(intf, "%s expects one parameter", args[0]);
|
|
return VLC_EGENERIC; /* EINVAL */
|
|
}
|
|
|
|
char *end;
|
|
double value = strtod(args[1], &end);
|
|
bool relative = args[1][0] == '-' || args[1][0] == '+';
|
|
bool pct = *end == '%';
|
|
|
|
vlc_player_Lock(player);
|
|
if (relative)
|
|
{
|
|
if (pct)
|
|
value += vlc_player_GetPosition(player) * 100.;
|
|
else
|
|
value += secf_from_vlc_tick(vlc_player_GetTime(player));
|
|
}
|
|
|
|
if (pct)
|
|
vlc_player_SetPosition(player, value / 100.);
|
|
else
|
|
vlc_player_SetTime(player, vlc_tick_from_sec(value));
|
|
vlc_player_Unlock(player);
|
|
return 0;
|
|
}
|
|
|
|
static int PlayerSetChapter(intf_thread_t *intf, const char *const *args,
|
|
size_t count)
|
|
{
|
|
vlc_player_t *player = vlc_playlist_GetPlayer(intf->p_sys->playlist);
|
|
int ret = 0;
|
|
|
|
vlc_player_Lock(player);
|
|
|
|
if (count > 1)
|
|
vlc_player_SelectChapterIdx(player, atoi(args[1]));
|
|
else
|
|
{
|
|
struct vlc_player_title const *title = vlc_player_GetSelectedTitle(player);
|
|
ssize_t chapter = -1;
|
|
if (title != NULL)
|
|
chapter = vlc_player_GetSelectedChapterIdx(player);
|
|
if (chapter != -1)
|
|
msg_print(intf, "Currently playing chapter %zd/%zu.",
|
|
chapter, title->chapter_count);
|
|
else
|
|
{
|
|
msg_print(intf, "No chapter selected.");
|
|
ret = VLC_ENOITEM;
|
|
}
|
|
}
|
|
vlc_player_Unlock(player);
|
|
return ret;
|
|
}
|
|
|
|
static int PlayerSetTitle(intf_thread_t *intf, const char *const *args,
|
|
size_t count)
|
|
{
|
|
vlc_player_t *player = vlc_playlist_GetPlayer(intf->p_sys->playlist);
|
|
int ret = 0;
|
|
|
|
vlc_player_Lock(player);
|
|
|
|
if (count > 1)
|
|
{
|
|
int idx = atoi(args[1]);
|
|
if (idx >= 0)
|
|
vlc_player_SelectTitleIdx(player, (size_t)idx);
|
|
}
|
|
else
|
|
{
|
|
ssize_t title = vlc_player_GetSelectedTitleIdx(player);
|
|
vlc_player_title_list *titles =
|
|
vlc_player_GetTitleList(player);
|
|
size_t title_count = 0;
|
|
if (titles != NULL)
|
|
title_count = vlc_player_title_list_GetCount(titles);
|
|
if (title != -1 && title_count != 0)
|
|
msg_print(intf, "Currently playing title %zd/%zu.", title,
|
|
title_count);
|
|
else
|
|
{
|
|
msg_print(intf, "No title selected.");
|
|
ret = VLC_ENOITEM;
|
|
}
|
|
}
|
|
vlc_player_Unlock(player);
|
|
return ret;
|
|
}
|
|
|
|
static int PlayerSetTrack(intf_thread_t *intf, const char *const *args,
|
|
size_t count)
|
|
{
|
|
vlc_player_t *player = vlc_playlist_GetPlayer(intf->p_sys->playlist);
|
|
const char *psz_cmd = args[0];
|
|
enum es_format_category_e cat;
|
|
int ret = VLC_EGENERIC; /* EINVAL */
|
|
|
|
switch (psz_cmd[0])
|
|
{
|
|
case 'a':
|
|
cat = AUDIO_ES;
|
|
break;
|
|
case 'v':
|
|
cat = VIDEO_ES;
|
|
break;
|
|
default:
|
|
cat = SPU_ES;
|
|
}
|
|
|
|
vlc_player_Lock(player);
|
|
|
|
if (count > 1)
|
|
{
|
|
int idx = atoi(args[1]);
|
|
if (idx < 0)
|
|
goto out;
|
|
|
|
size_t track_count = vlc_player_GetTrackCount(player, cat);
|
|
if ((unsigned)idx >= track_count)
|
|
goto out;
|
|
|
|
struct vlc_player_track const *track =
|
|
vlc_player_GetTrackAt(player, cat, (size_t)idx);
|
|
if (track != NULL)
|
|
{
|
|
vlc_player_SelectTrack(player, track, VLC_PLAYER_SELECT_EXCLUSIVE);
|
|
ret = 0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
struct vlc_player_track const *cur_track =
|
|
vlc_player_GetSelectedTrack(player, cat);
|
|
char const *name = cur_track ? cur_track->name : psz_cmd;
|
|
size_t track_count = vlc_player_GetTrackCount(player, cat);
|
|
|
|
msg_print(intf, "+----[ %s ]", name);
|
|
for (size_t i = 0; i < track_count; ++i)
|
|
{
|
|
struct vlc_player_track const *track =
|
|
vlc_player_GetTrackAt(player, cat, i);
|
|
msg_print(intf, "| %zu - %s%s",
|
|
i, track->name, track == cur_track ? " *" : "");
|
|
}
|
|
msg_print(intf, "+----[ end of %s ]", name);
|
|
ret = 0;
|
|
}
|
|
out:
|
|
vlc_player_Unlock(player);
|
|
return ret;
|
|
}
|
|
|
|
static int PlayerRecord(intf_thread_t *intf, const char *const *args,
|
|
size_t count)
|
|
{
|
|
vlc_player_t *player = vlc_playlist_GetPlayer(intf->p_sys->playlist);
|
|
|
|
vlc_player_Lock(player);
|
|
|
|
bool cur_value = vlc_player_IsRecording(player);
|
|
bool new_value = !cur_value;
|
|
|
|
if (count > 1)
|
|
{
|
|
if (strcmp(args[1], "on") == 0)
|
|
new_value = true;
|
|
if (strcmp(args[1], "off") == 0)
|
|
new_value = false;
|
|
}
|
|
|
|
if (cur_value != new_value)
|
|
vlc_player_SetRecordingEnabled(player, new_value);
|
|
vlc_player_Unlock(player);
|
|
return 0;
|
|
}
|
|
|
|
static int PlayerItemInfo(intf_thread_t *intf, const char *const *args,
|
|
size_t count)
|
|
{
|
|
vlc_player_t *player = vlc_playlist_GetPlayer(intf->p_sys->playlist);
|
|
input_item_t *item;
|
|
|
|
vlc_player_Lock(player);
|
|
item = vlc_player_GetCurrentMedia(player);
|
|
|
|
if (item != NULL)
|
|
{
|
|
vlc_mutex_lock(&item->lock);
|
|
for (int i = 0; i < item->i_categories; i++)
|
|
{
|
|
info_category_t *category = item->pp_categories[i];
|
|
info_t *info;
|
|
|
|
msg_print(intf, "+----[ %s ]", category->psz_name);
|
|
msg_print(intf, "| ");
|
|
info_foreach(info, &category->infos)
|
|
msg_print(intf, "| %s: %s", info->psz_name,
|
|
info->psz_value);
|
|
msg_print(intf, "| ");
|
|
}
|
|
msg_print(intf, "+----[ end of stream info ]");
|
|
vlc_mutex_unlock(&item->lock);
|
|
}
|
|
else
|
|
msg_print(intf, "no input");
|
|
vlc_player_Unlock(player);
|
|
(void) args; (void) count;
|
|
return (item != NULL) ? 0 : VLC_ENOITEM;
|
|
}
|
|
|
|
static int PlayerGetTime(intf_thread_t *intf, const char *const *args,
|
|
size_t count)
|
|
{
|
|
vlc_player_t *player = vlc_playlist_GetPlayer(intf->p_sys->playlist);
|
|
vlc_tick_t t;
|
|
|
|
vlc_player_Lock(player);
|
|
t = vlc_player_GetTime(player);
|
|
vlc_player_Unlock(player);
|
|
if (t == VLC_TICK_INVALID)
|
|
return VLC_ENOITEM;
|
|
|
|
msg_print(intf, "%"PRIu64, SEC_FROM_VLC_TICK(t));
|
|
(void) args; (void) count;
|
|
return 0;
|
|
}
|
|
|
|
static int PlayerGetLength(intf_thread_t *intf, const char *const *args,
|
|
size_t count)
|
|
{
|
|
vlc_player_t *player = vlc_playlist_GetPlayer(intf->p_sys->playlist);
|
|
vlc_tick_t l;
|
|
|
|
vlc_player_Lock(player);
|
|
l = vlc_player_GetLength(player);
|
|
vlc_player_Unlock(player);
|
|
|
|
if (l == VLC_TICK_INVALID)
|
|
return VLC_ENOITEM;
|
|
|
|
msg_print(intf, "%"PRIu64, SEC_FROM_VLC_TICK(l));
|
|
(void) args; (void) count;
|
|
return 0;
|
|
}
|
|
|
|
static int PlayerGetTitle(intf_thread_t *intf, const char *const *args,
|
|
size_t count)
|
|
{
|
|
vlc_player_t *player = vlc_playlist_GetPlayer(intf->p_sys->playlist);
|
|
const struct vlc_player_title *title;
|
|
|
|
vlc_player_Lock(player);
|
|
title = vlc_player_GetSelectedTitle(player);
|
|
msg_print(intf, "%s", (title != NULL) ? title->name : "");
|
|
vlc_player_Unlock(player);
|
|
(void) args; (void) count;
|
|
return (title != NULL) ? 0 : VLC_ENOITEM;
|
|
}
|
|
|
|
static int PlayerVoutSnapshot(intf_thread_t *intf, const char *const *args,
|
|
size_t count)
|
|
{
|
|
(void) args; (void) count;
|
|
return PlayerDoVoid(intf, vlc_player_vout_Snapshot);
|
|
}
|
|
|
|
static int PlayerFullscreen(intf_thread_t *intf, const char *const *args,
|
|
size_t count)
|
|
{
|
|
vlc_player_t *player = vlc_playlist_GetPlayer(intf->p_sys->playlist);
|
|
bool fs = !vlc_player_vout_IsFullscreen(player);
|
|
|
|
if (count > 1)
|
|
{
|
|
if (strncasecmp(args[1], "on", 2) == 0)
|
|
fs = true;
|
|
if (strncasecmp(args[1], "off", 3) == 0)
|
|
fs = false;
|
|
}
|
|
|
|
vlc_player_vout_SetFullscreen(player, fs);
|
|
return 0;
|
|
}
|
|
|
|
static int Volume(intf_thread_t *intf, const char *const *args, size_t count)
|
|
{
|
|
vlc_player_t *player = vlc_playlist_GetPlayer(intf->p_sys->playlist);
|
|
|
|
vlc_player_Lock(player);
|
|
if (count == 2)
|
|
{
|
|
/* NOTE: For unfortunate hysterical raisins, integer value above 1 are
|
|
* interpreted in a scale of 256 parts. Floating point values are taken
|
|
* as ratio as usual in the VLC code.
|
|
* Yes, this sucks (hopefully nobody uses volume 1/256).
|
|
*/
|
|
char *end;
|
|
unsigned long ul = strtoul(args[1], &end, 10);
|
|
float volume;
|
|
|
|
static_assert ((AOUT_VOLUME_DEFAULT & (AOUT_VOLUME_DEFAULT - 1)) == 0,
|
|
"AOUT_VOLUME_DEFAULT must be a power of two.");
|
|
|
|
if (*end == '\0' && ul > 1 && ul <= AOUT_VOLUME_MAX)
|
|
volume = ldexpf(ul, -ctz(AOUT_VOLUME_DEFAULT));
|
|
else
|
|
volume = atof(args[1]);
|
|
|
|
vlc_player_aout_SetVolume(player, volume);
|
|
}
|
|
else
|
|
msg_print(intf, STATUS_CHANGE "( audio volume: %f )",
|
|
vlc_player_aout_GetVolume(player));
|
|
vlc_player_Unlock(player);
|
|
return 0;
|
|
}
|
|
|
|
static int VolumeMove(intf_thread_t *intf, const char *const *args,
|
|
size_t count)
|
|
{
|
|
vlc_player_t *player = vlc_playlist_GetPlayer(intf->p_sys->playlist);
|
|
const char *psz_cmd = args[0];
|
|
const char *arg = count > 1 ? args[1] : "";
|
|
|
|
float volume;
|
|
int i_nb_steps = atoi(arg);
|
|
|
|
if( !strcmp(psz_cmd, "voldown") )
|
|
i_nb_steps *= -1;
|
|
|
|
vlc_player_Lock(player);
|
|
vlc_player_aout_IncrementVolume(player, i_nb_steps, &volume);
|
|
vlc_player_Unlock(player);
|
|
return 0;
|
|
}
|
|
|
|
static int VideoConfig(intf_thread_t *intf, const char *const *args,
|
|
size_t n_args)
|
|
{
|
|
vlc_player_t *player = vlc_playlist_GetPlayer(intf->p_sys->playlist);
|
|
vout_thread_t *p_vout = vlc_player_vout_Hold(player);
|
|
const char * psz_variable = NULL;
|
|
const char *psz_cmd = args[0];
|
|
const char *arg = n_args > 1 ? args[1] : "";
|
|
|
|
if( !strcmp( psz_cmd, "vcrop" ) )
|
|
psz_variable = "crop";
|
|
else if( !strcmp( psz_cmd, "vratio" ) )
|
|
psz_variable = "aspect-ratio";
|
|
else if( !strcmp( psz_cmd, "vzoom" ) )
|
|
psz_variable = "zoom";
|
|
else
|
|
/* This case can't happen */
|
|
vlc_assert_unreachable();
|
|
|
|
if (n_args > 1)
|
|
{
|
|
/* set */
|
|
if( !strcmp( psz_variable, "zoom" ) )
|
|
{
|
|
float f_float = atof( arg );
|
|
var_SetFloat( p_vout, psz_variable, f_float );
|
|
}
|
|
else
|
|
var_SetString( p_vout, psz_variable, arg );
|
|
}
|
|
else
|
|
{
|
|
/* get */
|
|
char *name;
|
|
vlc_value_t *val;
|
|
char **text;
|
|
float f_value = 0.;
|
|
char *psz_value = NULL;
|
|
size_t count;
|
|
|
|
if( !strcmp( psz_variable, "zoom" ) )
|
|
f_value = var_GetFloat( p_vout, "zoom" );
|
|
else
|
|
{
|
|
psz_value = var_GetString( p_vout, psz_variable );
|
|
if( psz_value == NULL )
|
|
{
|
|
vout_Release(p_vout);
|
|
return VLC_ENOVAR;
|
|
}
|
|
}
|
|
|
|
if ( var_Change( p_vout, psz_variable, VLC_VAR_GETCHOICES,
|
|
&count, &val, &text ) < 0 )
|
|
{
|
|
vout_Release(p_vout);
|
|
free( psz_value );
|
|
return VLC_ENOMEM;
|
|
}
|
|
|
|
/* Get the descriptive name of the variable */
|
|
var_Change( p_vout, psz_variable, VLC_VAR_GETTEXT, &name );
|
|
if( !name ) name = strdup(psz_variable);
|
|
|
|
msg_print(intf, "+----[ %s ]", name);
|
|
if( !strcmp( psz_variable, "zoom" ) )
|
|
{
|
|
for ( size_t i = 0; i < count; i++ )
|
|
{
|
|
const char *fmt = "| %f - %s";
|
|
|
|
if (f_value == val[i].f_float)
|
|
fmt = "| %f - %s*";
|
|
|
|
msg_print(intf, fmt, val[i].f_float, text[i]);
|
|
free(text[i]);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for ( size_t i = 0; i < count; i++ )
|
|
{
|
|
const char *fmt = "| %s - %s";
|
|
|
|
if (strcmp(psz_value, val[i].psz_string) == 0)
|
|
fmt = "| %s - %s*";
|
|
|
|
msg_print(intf, fmt, val[i].psz_string, text[i]);
|
|
free(text[i]);
|
|
free(val[i].psz_string);
|
|
}
|
|
free( psz_value );
|
|
}
|
|
free(text);
|
|
free(val);
|
|
msg_print(intf, "+----[ end of %s ]", name);
|
|
|
|
free( name );
|
|
}
|
|
vout_Release(p_vout);
|
|
return 0;
|
|
}
|
|
|
|
static int AudioDevice(intf_thread_t *intf, const char *const *args,
|
|
size_t count)
|
|
{
|
|
const char *cmd = args[0];
|
|
const char *arg = count > 1 ? args[1] : "";
|
|
vlc_player_t *player = vlc_playlist_GetPlayer(intf->p_sys->playlist);
|
|
audio_output_t *aout = vlc_player_aout_Hold(player);
|
|
int ret = 0;
|
|
|
|
if (aout == NULL)
|
|
return VLC_ENOOBJ;
|
|
|
|
char **ids, **names;
|
|
int n = aout_DevicesList(aout, &ids, &names);
|
|
if (n < 0)
|
|
{
|
|
ret = VLC_ENOMEM;
|
|
goto out;
|
|
}
|
|
|
|
bool setdev = count > 1;
|
|
if (setdev)
|
|
aout_DeviceSet(aout, arg);
|
|
|
|
if (setdev)
|
|
{
|
|
for (int i = 0; i < n; ++i)
|
|
{
|
|
if (!strcmp(arg, ids[i]))
|
|
vlc_player_osd_Message(player,
|
|
_("Audio device: %s"), names[i]);
|
|
|
|
free(names[i]);
|
|
free(ids[i]);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
char *dev = aout_DeviceGet(aout);
|
|
const char *devstr = (dev != NULL) ? dev : "";
|
|
|
|
msg_print(intf, "+----[ %s ]", cmd);
|
|
for ( int i = 0; i < n; i++ )
|
|
{
|
|
const char *fmt = "| %s - %s";
|
|
|
|
if( !strcmp(devstr, ids[i]) )
|
|
fmt = "| %s - %s *";
|
|
msg_print(intf, fmt, ids[i], names[i]);
|
|
free( names[i] );
|
|
free( ids[i] );
|
|
}
|
|
msg_print(intf, "+----[ end of %s ]", cmd);
|
|
|
|
free( dev );
|
|
}
|
|
|
|
free(ids);
|
|
free(names);
|
|
out:
|
|
aout_Release(aout);
|
|
return ret;
|
|
}
|
|
|
|
static int AudioChannel(intf_thread_t *intf, const char *const *args,
|
|
size_t n_args)
|
|
{
|
|
const char *cmd = args[0];
|
|
const char *arg = n_args > 1 ? args[1] : "";
|
|
vlc_player_t *player = vlc_playlist_GetPlayer(intf->p_sys->playlist);
|
|
audio_output_t *p_aout = vlc_player_aout_Hold(player);
|
|
int ret = 0;
|
|
|
|
if ( p_aout == NULL )
|
|
return VLC_ENOOBJ;
|
|
|
|
if ( !*arg )
|
|
{
|
|
/* Retrieve all registered ***. */
|
|
vlc_value_t *val;
|
|
char **text;
|
|
size_t count;
|
|
|
|
if ( var_Change( p_aout, "stereo-mode", VLC_VAR_GETCHOICES,
|
|
&count, &val, &text ) < 0 )
|
|
{
|
|
ret = VLC_ENOVAR;
|
|
goto out;
|
|
}
|
|
|
|
int i_value = var_GetInteger( p_aout, "stereo-mode" );
|
|
|
|
msg_print(intf, "+----[ %s ]", cmd);
|
|
for ( size_t i = 0; i < count; i++ )
|
|
{
|
|
const char *fmt = "| %"PRId64" - %s";
|
|
|
|
if (i_value == val[i].i_int)
|
|
fmt = "| %"PRId64" - %s*";
|
|
|
|
msg_print(intf, fmt, val[i].i_int, text[i]);
|
|
free(text[i]);
|
|
}
|
|
free(text);
|
|
free(val);
|
|
msg_print(intf, "+----[ end of %s ]", cmd);
|
|
}
|
|
else
|
|
var_SetInteger(p_aout, "stereo-mode", atoi(arg));
|
|
out:
|
|
aout_Release(p_aout);
|
|
return ret;
|
|
}
|
|
|
|
static int Statistics(intf_thread_t *intf, const char *const *args,
|
|
size_t count)
|
|
{
|
|
vlc_player_t *player = vlc_playlist_GetPlayer(intf->p_sys->playlist);
|
|
input_item_t *item;
|
|
|
|
vlc_player_Lock(player);
|
|
item = vlc_player_GetCurrentMedia(player);
|
|
|
|
if (item != NULL)
|
|
{
|
|
msg_print(intf, "+----[ begin of statistical info ]");
|
|
vlc_mutex_lock(&item->lock);
|
|
|
|
/* Input */
|
|
msg_print(intf, _("+-[Incoming]"));
|
|
msg_print(intf, _("| input bytes read : %8.0f KiB"),
|
|
(float)(item->p_stats->i_read_bytes) / 1024.f);
|
|
msg_print(intf, _("| input bitrate : %6.0f kb/s"),
|
|
(float)(item->p_stats->f_input_bitrate) * 8000.f);
|
|
msg_print(intf, _("| demux bytes read : %8.0f KiB"),
|
|
(float)(item->p_stats->i_demux_read_bytes) / 1024.f);
|
|
msg_print(intf, _("| demux bitrate : %6.0f kb/s"),
|
|
(float)(item->p_stats->f_demux_bitrate) * 8000.f);
|
|
msg_print(intf, _("| demux corrupted : %5"PRIi64),
|
|
item->p_stats->i_demux_corrupted);
|
|
msg_print(intf, _("| discontinuities : %5"PRIi64),
|
|
item->p_stats->i_demux_discontinuity);
|
|
msg_print(intf, "|");
|
|
|
|
/* Video */
|
|
msg_print(intf, _("+-[Video Decoding]"));
|
|
msg_print(intf, _("| video decoded : %5"PRIi64),
|
|
item->p_stats->i_decoded_video);
|
|
msg_print(intf, _("| frames displayed : %5"PRIi64),
|
|
item->p_stats->i_displayed_pictures);
|
|
msg_print(intf, _("| frames late : %5"PRIi64),
|
|
item->p_stats->i_late_pictures);
|
|
msg_print(intf, _("| frames lost : %5"PRIi64),
|
|
item->p_stats->i_lost_pictures);
|
|
msg_print(intf, "|");
|
|
|
|
/* Audio*/
|
|
msg_print(intf, "%s", _("+-[Audio Decoding]"));
|
|
msg_print(intf, _("| audio decoded : %5"PRIi64),
|
|
item->p_stats->i_decoded_audio);
|
|
msg_print(intf, _("| buffers played : %5"PRIi64),
|
|
item->p_stats->i_played_abuffers);
|
|
msg_print(intf, _("| buffers lost : %5"PRIi64),
|
|
item->p_stats->i_lost_abuffers);
|
|
msg_print(intf, "|");
|
|
|
|
vlc_mutex_unlock(&item->lock);
|
|
msg_print(intf, "+----[ end of statistical info ]" );
|
|
}
|
|
vlc_player_Unlock(player);
|
|
(void) args; (void) count;
|
|
return (item != NULL) ? 0 : VLC_ENOITEM;
|
|
}
|
|
|
|
static int IsPlaying(intf_thread_t *intf, const char *const *args,
|
|
size_t count)
|
|
{
|
|
intf_sys_t *sys = intf->p_sys;
|
|
vlc_player_t *player = vlc_playlist_GetPlayer(sys->playlist);
|
|
enum vlc_player_state state;
|
|
|
|
vlc_player_Lock(player);
|
|
state = vlc_player_GetState(player);
|
|
msg_print(intf, "%d", state == VLC_PLAYER_STATE_PLAYING
|
|
|| state == VLC_PLAYER_STATE_PAUSED);
|
|
vlc_player_Unlock(player);
|
|
(void) args; (void) count;
|
|
return 0;
|
|
}
|
|
|
|
static int PlayerStatus(intf_thread_t *intf, const char *const *args,
|
|
size_t count)
|
|
{
|
|
vlc_playlist_t *playlist = intf->p_sys->playlist;
|
|
vlc_player_t *player = vlc_playlist_GetPlayer(playlist);
|
|
|
|
vlc_playlist_Lock(playlist);
|
|
|
|
input_item_t *item = vlc_player_GetCurrentMedia(player);
|
|
if (item != NULL)
|
|
{
|
|
char *uri = input_item_GetURI(item);
|
|
if (likely(uri != NULL))
|
|
{
|
|
msg_print(intf, STATUS_CHANGE "( new input: %s )", uri);
|
|
free(uri);
|
|
}
|
|
}
|
|
|
|
float volume = vlc_player_aout_GetVolume(player);
|
|
if (isgreaterequal(volume, 0.f))
|
|
msg_print(intf, STATUS_CHANGE "( audio volume: %ld )",
|
|
lroundf(volume * 100.f));
|
|
|
|
enum vlc_player_state state = vlc_player_GetState(player);
|
|
|
|
vlc_playlist_Unlock(playlist);
|
|
|
|
int stnum = -1;
|
|
const char *stname = "unknown";
|
|
|
|
switch (state)
|
|
{
|
|
case VLC_PLAYER_STATE_STOPPING:
|
|
case VLC_PLAYER_STATE_STOPPED:
|
|
stnum = 5;
|
|
stname = "stop";
|
|
break;
|
|
case VLC_PLAYER_STATE_PLAYING:
|
|
stnum = 3;
|
|
stname = "play";
|
|
break;
|
|
case VLC_PLAYER_STATE_PAUSED:
|
|
stnum = 4;
|
|
stname = "pause";
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
msg_print(intf, STATUS_CHANGE "( %s state: %u )", stname, stnum);
|
|
(void) args; (void) count;
|
|
return 0;
|
|
}
|
|
|
|
static const struct cli_handler cmds[] =
|
|
{
|
|
{ "pause", PlayerPause },
|
|
{ "title_n", PlayerTitleNext },
|
|
{ "title_p", PlayerTitlePrev },
|
|
{ "chapter_n", PlayerChapterNext },
|
|
{ "chapter_p", PlayerChapterPrev },
|
|
{ "fastforward", PlayerFastForward },
|
|
{ "rewind", PlayerRewind },
|
|
{ "faster", PlayerFaster },
|
|
{ "slower", PlayerSlower },
|
|
{ "normal", PlayerNormal },
|
|
{ "rate", PlayerRate },
|
|
{ "frame", PlayerFrame },
|
|
{ "info", PlayerItemInfo },
|
|
{ "get_time", PlayerGetTime },
|
|
{ "get_length", PlayerGetLength },
|
|
{ "get_title", PlayerGetTitle },
|
|
{ "snapshot", PlayerVoutSnapshot },
|
|
|
|
{ "is_playing", IsPlaying },
|
|
{ "status", PlayerStatus },
|
|
{ "stats", Statistics },
|
|
|
|
/* DVD commands */
|
|
{ "seek", PlayerSeek },
|
|
{ "title", PlayerSetTitle },
|
|
{ "chapter", PlayerSetChapter },
|
|
|
|
{ "atrack", PlayerSetTrack },
|
|
{ "vtrack", PlayerSetTrack },
|
|
{ "strack", PlayerSetTrack },
|
|
{ "record", PlayerRecord },
|
|
{ "f", PlayerFullscreen },
|
|
{ "fs", PlayerFullscreen },
|
|
{ "fullscreen", PlayerFullscreen },
|
|
|
|
/* video commands */
|
|
{ "vratio", VideoConfig },
|
|
{ "vcrop", VideoConfig },
|
|
{ "vzoom", VideoConfig },
|
|
|
|
/* audio commands */
|
|
{ "volume", Volume },
|
|
{ "volup", VolumeMove },
|
|
{ "voldown", VolumeMove },
|
|
{ "adev", AudioDevice },
|
|
{ "achan", AudioChannel },
|
|
};
|
|
|
|
void *RegisterPlayer(intf_thread_t *intf)
|
|
{
|
|
vlc_playlist_t *playlist = vlc_intf_GetMainPlaylist(intf);;
|
|
vlc_player_t *player = vlc_playlist_GetPlayer(playlist);
|
|
struct player_cli *pc = malloc(sizeof (*pc));
|
|
|
|
if (unlikely(pc == NULL))
|
|
return NULL;
|
|
|
|
pc->intf = intf;
|
|
pc->position = -1.;
|
|
pc->input_buffering = false;
|
|
pc->show_position = var_InheritBool(intf, "rc-show-pos");
|
|
|
|
RegisterHandlers(intf, cmds, ARRAY_SIZE(cmds));
|
|
|
|
vlc_player_Lock(player);
|
|
pc->player_listener = vlc_player_AddListener(player, &player_cbs, pc);
|
|
|
|
if (unlikely(pc->player_listener == NULL))
|
|
goto error;
|
|
|
|
pc->player_aout_listener =
|
|
vlc_player_aout_AddListener(player, &player_aout_cbs, pc);
|
|
|
|
if (pc->player_aout_listener == NULL)
|
|
{
|
|
vlc_player_RemoveListener(player, pc->player_listener);
|
|
goto error;
|
|
}
|
|
|
|
player_on_state_changed(player, vlc_player_GetState(player), pc);
|
|
vlc_player_Unlock(player);
|
|
return pc;
|
|
|
|
error:
|
|
vlc_player_Unlock(player);
|
|
free(pc);
|
|
return NULL;
|
|
}
|
|
|
|
void DeregisterPlayer(intf_thread_t *intf, void *data)
|
|
{
|
|
vlc_playlist_t *playlist = vlc_intf_GetMainPlaylist(intf);;
|
|
vlc_player_t *player = vlc_playlist_GetPlayer(playlist);
|
|
struct player_cli *pc = data;
|
|
|
|
vlc_player_Lock(player);
|
|
vlc_player_aout_RemoveListener(player, pc->player_aout_listener);
|
|
vlc_player_RemoveListener(player, pc->player_listener);
|
|
vlc_player_Unlock(player);
|
|
free(pc);
|
|
(void) intf;
|
|
}
|
|
|