summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--DOCS/man/en/changes.rst26
-rw-r--r--DOCS/man/en/input.rst7
-rw-r--r--demux/demux.h7
-rw-r--r--etc/input.conf6
-rw-r--r--input/cmd_list.c10
-rw-r--r--input/cmd_list.h11
-rw-r--r--player/command.c260
-rw-r--r--player/loadfile.c15
-rw-r--r--player/main.c1
-rw-r--r--stream/stream.h20
-rw-r--r--stream/stream_dvb.c20
-rw-r--r--stream/stream_pvr.c25
-rw-r--r--stream/tv.c54
-rw-r--r--stream/tv.h4
14 files changed, 259 insertions, 207 deletions
diff --git a/DOCS/man/en/changes.rst b/DOCS/man/en/changes.rst
index a60cced3e6..1387d03372 100644
--- a/DOCS/man/en/changes.rst
+++ b/DOCS/man/en/changes.rst
@@ -274,6 +274,32 @@ input.conf and Slave Commands
+--------------------------------+----------------------------------------+
| ``af_switch``, ``af_add``, ... | ``af set|add|...`` |
+--------------------------------+----------------------------------------+
+ | ``tv_start_scan`` | ``set tv-scan yes`` |
+ +--------------------------------+----------------------------------------+
+ | ``tv_set_channel <val>`` | ``set tv-channel <val>`` |
+ +--------------------------------+----------------------------------------+
+ | ``tv_step_channel`` | ``cycle tv-channel`` |
+ +--------------------------------+----------------------------------------+
+ | ``dvb_set_channel <v1> <v2>`` | ``set dvb-channel <v1>-<v2>`` |
+ +--------------------------------+----------------------------------------+
+ | ``dvb_step_channel`` | ``cycle dvb-channel`` |
+ +--------------------------------+----------------------------------------+
+ | ``tv_set_freq <val>`` | ``set tv-freq <val>`` |
+ +--------------------------------+----------------------------------------+
+ | ``tv_step_freq`` | ``cycle tv-freq`` |
+ +--------------------------------+----------------------------------------+
+ | ``tv_set_norm <norm>`` | ``set tv-norm <norm>`` |
+ +--------------------------------+----------------------------------------+
+ | ``tv_step_norm`` | ``cycle tv-norm`` |
+ +--------------------------------+----------------------------------------+
+
+ .. note::
+
+ Due to lack of hardware and users using the TV/DVB/PVR features, and
+ due to the need to cleanup the related command code, it's possible
+ that the new commands are buggy or behave worse. This can be improved
+ if testers are available. Otherwise, some of the TV code will be
+ removed at some point.
Slave mode
~~~~~~~~~~
diff --git a/DOCS/man/en/input.rst b/DOCS/man/en/input.rst
index a482437818..d2ad209701 100644
--- a/DOCS/man/en/input.rst
+++ b/DOCS/man/en/input.rst
@@ -493,11 +493,8 @@ Input Commands that are Possibly Subject to Change
be used in input.conf to reassign such bindings.)
-Undocumented commands: ``tv_start_scan``, ``tv_step_channel``, ``tv_step_norm``,
-``tv_step_chanlist``, ``tv_set_channel``, ``tv_last_channel``, ``tv_set_freq``,
-``tv_step_freq``, ``tv_set_norm``, ``dvb_set_channel`` (all of these
-should be replaced by properties), ``stop`` (questionable use), ``get_property``
-(?), ``vo_cmdline`` (experimental).
+Undocumented commands: ``tv_last_channel`` (TV/DVB only), ``stop`` (questionable
+use), ``get_property`` (?), ``vo_cmdline`` (experimental).
Input Command Prefixes
----------------------
diff --git a/demux/demux.h b/demux/demux.h
index 81568b96b9..2bcfc241c1 100644
--- a/demux/demux.h
+++ b/demux/demux.h
@@ -56,6 +56,13 @@ enum demux_ctrl {
DEMUXER_CTRL_GET_START_TIME,
DEMUXER_CTRL_RESYNC,
DEMUXER_CTRL_IDENTIFY_PROGRAM,
+ DEMUXER_CTRL_STREAM_CTRL, // stupid workaround for legacy TV code
+};
+
+struct demux_ctrl_stream_ctrl {
+ int ctrl;
+ void *arg;
+ int res;
};
#define SEEK_ABSOLUTE (1 << 0)
diff --git a/etc/input.conf b/etc/input.conf
index 321ba71423..fbadd7f0a1 100644
--- a/etc/input.conf
+++ b/etc/input.conf
@@ -156,12 +156,6 @@
#l cycle quvi-format 1
#L cycle quvi-format -1
-# TV
-#h tv_step_channel 1
-#k tv_step_channel -1
-#n tv_step_norm
-#u tv_step_chanlist
-
# Apple Remote section
#AR_PLAY cycle pause
#AR_PLAY_HOLD quit
diff --git a/input/cmd_list.c b/input/cmd_list.c
index 24ef6e7a0e..1096e83d63 100644
--- a/input/cmd_list.c
+++ b/input/cmd_list.c
@@ -93,17 +93,7 @@ const struct mp_cmd_def mp_cmds[] = {
{ MP_CMD_SUB_REMOVE, "sub_remove", { OARG_INT(-1) } },
{ MP_CMD_SUB_RELOAD, "sub_reload", { OARG_INT(-1) } },
- { MP_CMD_TV_START_SCAN, "tv_start_scan", },
- { MP_CMD_TV_STEP_CHANNEL, "tv_step_channel", { ARG_INT } },
- { MP_CMD_TV_STEP_NORM, "tv_step_norm", },
- { MP_CMD_TV_STEP_CHANNEL_LIST, "tv_step_chanlist", },
- { MP_CMD_TV_SET_CHANNEL, "tv_set_channel", { ARG_STRING } },
{ MP_CMD_TV_LAST_CHANNEL, "tv_last_channel", },
- { MP_CMD_TV_SET_FREQ, "tv_set_freq", { ARG_FLOAT } },
- { MP_CMD_TV_STEP_FREQ, "tv_step_freq", { ARG_FLOAT } },
- { MP_CMD_TV_SET_NORM, "tv_set_norm", { ARG_STRING } },
-
- { MP_CMD_DVB_SET_CHANNEL, "dvb_set_channel", { ARG_INT, ARG_INT } },
{ MP_CMD_SCREENSHOT, "screenshot", {
OARG_CHOICE(2, ({"video", 0},
diff --git a/input/cmd_list.h b/input/cmd_list.h
index f061814f23..ada1932f8d 100644
--- a/input/cmd_list.h
+++ b/input/cmd_list.h
@@ -46,9 +46,6 @@ enum mp_command_type {
MP_CMD_PLAYLIST_NEXT,
MP_CMD_PLAYLIST_PREV,
MP_CMD_OSD,
- MP_CMD_TV_STEP_CHANNEL,
- MP_CMD_TV_STEP_NORM,
- MP_CMD_TV_STEP_CHANNEL_LIST,
MP_CMD_SCREENSHOT,
MP_CMD_SCREENSHOT_TO_FILE,
MP_CMD_LOADFILE,
@@ -58,10 +55,7 @@ enum mp_command_type {
MP_CMD_PLAYLIST_MOVE,
MP_CMD_SUB_STEP,
MP_CMD_SUB_SEEK,
- MP_CMD_TV_SET_CHANNEL,
MP_CMD_TV_LAST_CHANNEL,
- MP_CMD_TV_SET_FREQ,
- MP_CMD_TV_SET_NORM,
MP_CMD_FRAME_STEP,
MP_CMD_FRAME_BACK_STEP,
MP_CMD_RUN,
@@ -77,8 +71,6 @@ enum mp_command_type {
MP_CMD_CYCLE,
MP_CMD_MULTIPLY,
MP_CMD_CYCLE_VALUES,
- MP_CMD_TV_STEP_FREQ,
- MP_CMD_TV_START_SCAN,
MP_CMD_STOP,
MP_CMD_ENABLE_INPUT_SECTION,
@@ -86,9 +78,6 @@ enum mp_command_type {
MP_CMD_DISCNAV,
- /// DVB commands
- MP_CMD_DVB_SET_CHANNEL,
-
/// Audio Filter commands
MP_CMD_AF,
diff --git a/player/command.c b/player/command.c
index e2788b76be..315013b0e8 100644
--- a/player/command.c
+++ b/player/command.c
@@ -59,11 +59,6 @@
#include "video/decode/dec_video.h"
#include "audio/decode/dec_audio.h"
#include "options/path.h"
-#include "stream/tv.h"
-#include "stream/pvr.h"
-#if HAVE_DVBIN
-#include "stream/dvbin.h"
-#endif
#include "screenshot.h"
#if HAVE_SYS_MMAN_H
#include <sys/mman.h>
@@ -2102,33 +2097,120 @@ static int mp_property_sub_pos(m_option_t *prop, int action, void *arg,
return property_osd_helper(prop, action, arg, mpctx);
}
-#if HAVE_TV
+static int demux_stream_control(struct MPContext *mpctx, int ctrl, void *arg)
+{
+ int r = STREAM_UNSUPPORTED;
+ if (mpctx->stream)
+ r = stream_control(mpctx->stream, ctrl, arg);
+ if (r == STREAM_UNSUPPORTED && mpctx->demuxer) {
+ struct demux_ctrl_stream_ctrl c = {ctrl, arg, STREAM_UNSUPPORTED};
+ demux_control(mpctx->demuxer, DEMUXER_CTRL_STREAM_CTRL, &c);
+ r = c.res;
+ }
+ return r;
+}
-static tvi_handle_t *get_tvh(struct MPContext *mpctx)
+static int prop_stream_ctrl(struct MPContext *mpctx, int ctrl, void *arg)
{
- if (!(mpctx->master_demuxer && mpctx->master_demuxer->type == DEMUXER_TYPE_TV))
- return NULL;
- return mpctx->master_demuxer->priv;
+ int r = demux_stream_control(mpctx, ctrl, arg);
+ switch (r) {
+ case STREAM_OK: return M_PROPERTY_OK;
+ case STREAM_UNSUPPORTED: return M_PROPERTY_UNAVAILABLE;
+ default: return M_PROPERTY_ERROR;
+ }
+}
+
+static int mp_property_tv_norm(m_option_t *prop, int action, void *arg,
+ MPContext *mpctx)
+{
+ switch (action) {
+ case M_PROPERTY_SET:
+ return prop_stream_ctrl(mpctx, STREAM_CTRL_TV_SET_NORM, *(char **)arg);
+ case M_PROPERTY_SWITCH:
+ return prop_stream_ctrl(mpctx, STREAM_CTRL_TV_STEP_NORM, NULL);
+ }
+ return M_PROPERTY_NOT_IMPLEMENTED;
+}
+
+static int mp_property_tv_scan(m_option_t *prop, int action, void *arg,
+ MPContext *mpctx)
+{
+ switch (action) {
+ case M_PROPERTY_SET:
+ return prop_stream_ctrl(mpctx, STREAM_CTRL_TV_SET_SCAN, arg);
+ }
+ return M_PROPERTY_NOT_IMPLEMENTED;
}
/// TV color settings (RW)
static int mp_property_tv_color(m_option_t *prop, int action, void *arg,
MPContext *mpctx)
{
- tvi_handle_t *tvh = get_tvh(mpctx);
- if (!tvh)
- return M_PROPERTY_UNAVAILABLE;
+ int req[2] = {prop->offset};
+ switch (action) {
+ case M_PROPERTY_SET:
+ req[1] = *(int *)arg;
+ return prop_stream_ctrl(mpctx, STREAM_CTRL_SET_TV_COLORS, req);
+ case M_PROPERTY_GET: {
+ int r = prop_stream_ctrl(mpctx, STREAM_CTRL_GET_TV_COLORS, req);
+ if (r == M_PROPERTY_OK)
+ *(int *)arg = req[1];
+ return r;
+ }
+ }
+ return M_PROPERTY_NOT_IMPLEMENTED;
+}
+static int mp_property_tv_freq(m_option_t *prop, int action, void *arg,
+ MPContext *mpctx)
+{
switch (action) {
case M_PROPERTY_SET:
- return tv_set_color_options(tvh, prop->offset, *(int *) arg);
+ return prop_stream_ctrl(mpctx, STREAM_CTRL_SET_TV_FREQ, arg);
case M_PROPERTY_GET:
- return tv_get_color_options(tvh, prop->offset, arg);
+ return prop_stream_ctrl(mpctx, STREAM_CTRL_GET_TV_FREQ, arg);
}
return M_PROPERTY_NOT_IMPLEMENTED;
}
-#endif
+static int mp_property_tv_channel(m_option_t *prop, int action, void *arg,
+ MPContext *mpctx)
+{
+ switch (action) {
+ case M_PROPERTY_SET:
+ return prop_stream_ctrl(mpctx, STREAM_CTRL_TV_SET_CHAN, *(char **)arg);
+ case M_PROPERTY_SWITCH: {
+ struct m_property_switch_arg *sa = arg;
+ int dir = sa->inc >= 0 ? 1 : -1;
+ return prop_stream_ctrl(mpctx, STREAM_CTRL_TV_STEP_CHAN, &dir);
+ }
+ }
+ return M_PROPERTY_NOT_IMPLEMENTED;
+}
+
+static int mp_property_dvb_channel(m_option_t *prop, int action, void *arg,
+ MPContext *mpctx)
+{
+ int r;
+ switch (action) {
+ case M_PROPERTY_SET:
+ mpctx->last_dvb_step = 1;
+ r = prop_stream_ctrl(mpctx, STREAM_CTRL_DVB_SET_CHANNEL, arg);
+ if (r == M_PROPERTY_OK)
+ mpctx->stop_play = PT_RELOAD_DEMUXER;
+ return r;
+ case M_PROPERTY_SWITCH: {
+ struct m_property_switch_arg *sa = arg;
+ int dir = sa->inc >= 0 ? 1 : -1;
+ mpctx->last_dvb_step = dir;
+ r = prop_stream_ctrl(mpctx, STREAM_CTRL_DVB_STEP_CHANNEL, &dir);
+ if (r == M_PROPERTY_OK)
+ mpctx->stop_play = PT_RELOAD_DEMUXER;
+ return r;
+ }
+ }
+ return M_PROPERTY_NOT_IMPLEMENTED;
+}
static int mp_property_playlist_pos(m_option_t *prop, int action, void *arg,
MPContext *mpctx)
@@ -2490,7 +2572,6 @@ static const m_option_t mp_properties[] = {
M_OPTION_PROPERTY_CUSTOM("vf", mp_property_vf),
M_OPTION_PROPERTY_CUSTOM("af", mp_property_af),
-#if HAVE_TV
{ "tv-brightness", mp_property_tv_color, CONF_TYPE_INT,
M_OPT_RANGE, -100, 100, .offset = TV_COLOR_BRIGHTNESS },
{ "tv-contrast", mp_property_tv_color, CONF_TYPE_INT,
@@ -2499,7 +2580,12 @@ static const m_option_t mp_properties[] = {
M_OPT_RANGE, -100, 100, .offset = TV_COLOR_SATURATION },
{ "tv-hue", mp_property_tv_color, CONF_TYPE_INT,
M_OPT_RANGE, -100, 100, .offset = TV_COLOR_HUE },
-#endif
+ { "tv-freq", mp_property_tv_freq, CONF_TYPE_FLOAT, },
+ { "tv-norm", mp_property_tv_norm, CONF_TYPE_STRING, },
+ { "tv-scan", mp_property_tv_scan, CONF_TYPE_FLAG,
+ M_OPT_RANGE, 0, 1 },
+ { "tv-channel", mp_property_tv_channel, CONF_TYPE_STRING, },
+ { "dvb-channel", mp_property_dvb_channel, &m_option_type_intpair, },
M_PROPERTY_ALIAS("video", "vid"),
M_PROPERTY_ALIAS("audio", "aid"),
@@ -3432,142 +3518,10 @@ int run_command(MPContext *mpctx, mp_cmd_t *cmd)
(bar_osd ? OSD_SEEK_INFO_BAR : 0);
break;
-#if HAVE_TV
- case MP_CMD_TV_START_SCAN:
- if (get_tvh(mpctx))
- tv_start_scan(get_tvh(mpctx), 1);
- break;
- case MP_CMD_TV_SET_FREQ:
- if (get_tvh(mpctx))
- tv_set_freq(get_tvh(mpctx), cmd->args[0].v.f * 16.0);
-#if HAVE_PVR
- else if (mpctx->stream && mpctx->stream->type == STREAMTYPE_PVR) {
- pvr_set_freq(mpctx->stream, ROUND(cmd->args[0].v.f));
- set_osd_msg(mpctx, osdl, osd_duration, "%s: %s",
- pvr_get_current_channelname(mpctx->stream),
- pvr_get_current_stationname(mpctx->stream));
- }
-#endif /* HAVE_PVR */
- break;
-
- case MP_CMD_TV_STEP_FREQ:
- if (get_tvh(mpctx))
- tv_step_freq(get_tvh(mpctx), cmd->args[0].v.f * 16.0);
-#if HAVE_PVR
- else if (mpctx->stream && mpctx->stream->type == STREAMTYPE_PVR) {
- pvr_force_freq_step(mpctx->stream, ROUND(cmd->args[0].v.f));
- set_osd_msg(mpctx, osdl, osd_duration, "%s: f %d",
- pvr_get_current_channelname(mpctx->stream),
- pvr_get_current_frequency(mpctx->stream));
- }
-#endif /* HAVE_PVR */
- break;
-
- case MP_CMD_TV_SET_NORM:
- if (get_tvh(mpctx))
- tv_set_norm(get_tvh(mpctx), cmd->args[0].v.s);
- break;
-
- case MP_CMD_TV_STEP_CHANNEL:
- if (get_tvh(mpctx)) {
- int v = cmd->args[0].v.i;
- if (v > 0) {
- tv_step_channel(get_tvh(mpctx), TV_CHANNEL_HIGHER);
- } else {
- tv_step_channel(get_tvh(mpctx), TV_CHANNEL_LOWER);
- }
- if (tv_channel_list) {
- set_osd_msg(mpctx, osdl, osd_duration,
- "Channel: %s", tv_channel_current->name);
- }
- }
-#if HAVE_PVR
- else if (mpctx->stream &&
- mpctx->stream->type == STREAMTYPE_PVR) {
- pvr_set_channel_step(mpctx->stream, cmd->args[0].v.i);
- set_osd_msg(mpctx, osdl, osd_duration, "%s: %s",
- pvr_get_current_channelname(mpctx->stream),
- pvr_get_current_stationname(mpctx->stream));
- }
-#endif /* HAVE_PVR */
-#if HAVE_DVBIN
- if (mpctx->stream && mpctx->stream->type == STREAMTYPE_DVB) {
- int dir;
- int v = cmd->args[0].v.i;
-
- mpctx->last_dvb_step = v;
- if (v > 0)
- dir = DVB_CHANNEL_HIGHER;
- else
- dir = DVB_CHANNEL_LOWER;
-
-
- if (dvb_step_channel(mpctx->stream, dir)) {
- mpctx->stop_play = PT_RELOAD_DEMUXER;
- }
- }
-#endif /* HAVE_DVBIN */
- break;
-
- case MP_CMD_TV_SET_CHANNEL:
- if (get_tvh(mpctx)) {
- tv_set_channel(get_tvh(mpctx), cmd->args[0].v.s);
- if (tv_channel_list) {
- set_osd_msg(mpctx, osdl, osd_duration,
- "Channel: %s", tv_channel_current->name);
- }
- }
-#if HAVE_PVR
- else if (mpctx->stream && mpctx->stream->type == STREAMTYPE_PVR) {
- pvr_set_channel(mpctx->stream, cmd->args[0].v.s);
- set_osd_msg(mpctx, osdl, osd_duration, "%s: %s",
- pvr_get_current_channelname(mpctx->stream),
- pvr_get_current_stationname(mpctx->stream));
- }
-#endif /* HAVE_PVR */
- break;
-
-#if HAVE_DVBIN
- case MP_CMD_DVB_SET_CHANNEL:
- if (mpctx->stream && mpctx->stream->type == STREAMTYPE_DVB) {
- mpctx->last_dvb_step = 1;
-
- if (dvb_set_channel(mpctx->stream, cmd->args[1].v.i,
- cmd->args[0].v.i)) {
- mpctx->stop_play = PT_RELOAD_DEMUXER;
- }
- }
- break;
-#endif /* HAVE_DVBIN */
-
- case MP_CMD_TV_LAST_CHANNEL:
- if (get_tvh(mpctx)) {
- tv_last_channel(get_tvh(mpctx));
- if (tv_channel_list) {
- set_osd_msg(mpctx, osdl, osd_duration,
- "Channel: %s", tv_channel_current->name);
- }
- }
-#if HAVE_PVR
- else if (mpctx->stream && mpctx->stream->type == STREAMTYPE_PVR) {
- pvr_set_lastchannel(mpctx->stream);
- set_osd_msg(mpctx, osdl, osd_duration, "%s: %s",
- pvr_get_current_channelname(mpctx->stream),
- pvr_get_current_stationname(mpctx->stream));
- }
-#endif /* HAVE_PVR */
- break;
-
- case MP_CMD_TV_STEP_NORM:
- if (get_tvh(mpctx))
- tv_step_norm(get_tvh(mpctx));
+ case MP_CMD_TV_LAST_CHANNEL: {
+ demux_stream_control(mpctx, STREAM_CTRL_TV_LAST_CHAN, NULL);
break;
-
- case MP_CMD_TV_STEP_CHANNEL_LIST:
- if (get_tvh(mpctx))
- tv_step_chanlist(get_tvh(mpctx));
- break;
-#endif /* HAVE_TV */
+ }
case MP_CMD_SUB_ADD: {
struct track *sub = mp_add_subtitles(mpctx, cmd->args[0].v.s);
diff --git a/player/loadfile.c b/player/loadfile.c
index cc65aedd6d..26f6c3a0c5 100644
--- a/player/loadfile.c
+++ b/player/loadfile.c
@@ -1257,20 +1257,13 @@ goto_reopen_demuxer: ;
//==================== START PLAYING =======================
if (!mpctx->d_video && !mpctx->d_audio) {
+ struct stream *s = mpctx->stream;
MP_FATAL(mpctx, "No video or audio streams selected.\n");
-#if HAVE_DVBIN
- if (mpctx->stream->type == STREAMTYPE_DVB) {
- int dir;
- int v = mpctx->last_dvb_step;
- if (v > 0)
- dir = DVB_CHANNEL_HIGHER;
- else
- dir = DVB_CHANNEL_LOWER;
-
- if (dvb_step_channel(mpctx->stream, dir))
+ if (s->uncached_type == STREAMTYPE_DVB) {
+ int dir = mpctx->last_dvb_step;
+ if (stream_control(s, STREAM_CTRL_DVB_STEP_CHANNEL, &dir) > 0)
mpctx->stop_play = PT_RELOAD_DEMUXER;
}
-#endif
goto terminate_playback;
}
diff --git a/player/main.c b/player/main.c
index d7b34e0ef8..19c24c036b 100644
--- a/player/main.c
+++ b/player/main.c
@@ -303,7 +303,6 @@ struct MPContext *mp_create(void)
struct MPContext *mpctx = talloc(NULL, MPContext);
*mpctx = (struct MPContext){
- .last_dvb_step = 1,
.last_chapter = -2,
.term_osd_contents = talloc_strdup(mpctx, ""),
.osd_progbar = { .type = -1 },
diff --git a/stream/stream.h b/stream/stream.h
index ec0059e451..ba3f6a4fe0 100644
--- a/stream/stream.h
+++ b/stream/stream.h
@@ -92,7 +92,19 @@ enum stream_ctrl {
STREAM_CTRL_GET_BASE_FILENAME,
STREAM_CTRL_GET_NAV_EVENT, // struct mp_nav_event**
STREAM_CTRL_NAV_CMD, // struct mp_nav_cmd*
- STREAM_CTRL_GET_DISC_NAME
+ STREAM_CTRL_GET_DISC_NAME,
+ STREAM_CTRL_TV_SET_SCAN,
+ STREAM_CTRL_SET_TV_FREQ,
+ STREAM_CTRL_GET_TV_FREQ,
+ STREAM_CTRL_SET_TV_COLORS,
+ STREAM_CTRL_GET_TV_COLORS,
+ STREAM_CTRL_TV_SET_NORM,
+ STREAM_CTRL_TV_STEP_NORM,
+ STREAM_CTRL_TV_SET_CHAN,
+ STREAM_CTRL_TV_STEP_CHAN,
+ STREAM_CTRL_TV_LAST_CHAN,
+ STREAM_CTRL_DVB_SET_CHANNEL,
+ STREAM_CTRL_DVB_STEP_CHANNEL,
};
struct stream_lang_req {
@@ -106,6 +118,12 @@ struct stream_dvd_info_req {
int num_subs;
};
+// for STREAM_CTRL_SET_TV_COLORS
+#define TV_COLOR_BRIGHTNESS 1
+#define TV_COLOR_HUE 2
+#define TV_COLOR_SATURATION 3
+#define TV_COLOR_CONTRAST 4
+
struct stream;
typedef struct stream_info_st {
const char *name;
diff --git a/stream/stream_dvb.c b/stream/stream_dvb.c
index cdf282d3ac..c1697ddebd 100644
--- a/stream/stream_dvb.c
+++ b/stream/stream_dvb.c
@@ -550,13 +550,26 @@ int dvb_step_channel(stream_t *stream, int dir)
return 0;
}
- new_current = (list->NUM_CHANNELS + list->current + (dir == DVB_CHANNEL_HIGHER ? 1 : -1)) % list->NUM_CHANNELS;
+ new_current = (list->NUM_CHANNELS + list->current + (dir >= 0 ? 1 : -1)) % list->NUM_CHANNELS;
return dvb_set_channel(stream, priv->card, new_current);
}
-
-
+static int dvbin_stream_control(struct stream *s, int cmd, void *arg)
+{
+ int r;
+ switch (cmd) {
+ case STREAM_CTRL_DVB_SET_CHANNEL: {
+ int *iarg = arg;
+ r = dvb_set_channel(s, iarg[1], iarg[0]);
+ return r ? STREAM_OK : STREAM_ERROR;
+ }
+ case STREAM_CTRL_DVB_STEP_CHANNEL:
+ r = dvb_step_channel(s, *(int *)arg);
+ return r ? STREAM_OK : STREAM_ERROR;
+ }
+ return STREAM_UNSUPPORTED;
+}
static void dvbin_close(stream_t *stream)
{
@@ -692,6 +705,7 @@ static int dvb_open(stream_t *stream)
stream->type = STREAMTYPE_DVB;
stream->fill_buffer = dvb_streaming_read;
stream->close = dvbin_close;
+ stream->control = dvbin_stream_control;
stream->demuxer = "lavf";
stream->lavf_type = "mpegts";
diff --git a/stream/stream_pvr.c b/stream/stream_pvr.c
index e45c9005a1..c19e9f05cb 100644
--- a/stream/stream_pvr.c
+++ b/stream/stream_pvr.c
@@ -142,6 +142,8 @@ struct pvr_t {
int stream_type;
};
+static int pvr_stream_control(struct stream *s, int cmd, void *arg);
+
static struct pvr_t *
pvr_init (void)
{
@@ -1608,6 +1610,7 @@ pvr_stream_open (stream_t *stream)
stream->type = STREAMTYPE_PVR;
stream->fill_buffer = pvr_stream_read;
stream->close = pvr_stream_close;
+ stream->control = pvr_stream_control;
return STREAM_OK;
}
@@ -1698,6 +1701,28 @@ pvr_force_freq_step (stream_t *stream, int step)
return force_freq_step (pvr, step);
}
+static int pvr_stream_control(struct stream *s, int cmd, void *arg)
+{
+ switch (cmd) {
+ case STREAM_CTRL_SET_TV_FREQ:
+ pvr_set_freq(s, (int)(*(float *)arg + 0.5f));
+ return STREAM_OK;
+ case STREAM_CTRL_GET_TV_FREQ:
+ *(float *)arg = pvr_get_current_frequency(s);
+ return STREAM_OK;
+ case STREAM_CTRL_TV_SET_CHAN:
+ pvr_set_channel(s, (char *)arg);
+ return STREAM_OK;
+ case STREAM_CTRL_TV_STEP_CHAN:
+ pvr_set_channel_step(s, *(int *)arg);
+ return STREAM_OK;
+ case STREAM_CTRL_TV_LAST_CHAN:
+ pvr_set_lastchannel(s);
+ return STREAM_OK;
+ }
+ return STREAM_UNSUPPORTED;
+}
+
const stream_info_t stream_info_pvr = {
.name = "pvr",
.open = pvr_stream_open,
diff --git a/stream/tv.c b/stream/tv.c
index c7017f4471..c42a81fde1 100644
--- a/stream/tv.c
+++ b/stream/tv.c
@@ -1087,9 +1087,58 @@ int tv_step_norm(tvi_handle_t *tvh)
return 1;
}
-int tv_step_chanlist(tvi_handle_t *tvh)
+static int tv_stream_control(tvi_handle_t *tvh, int cmd, void *arg)
{
- return 1;
+ switch (cmd) {
+ case STREAM_CTRL_TV_SET_SCAN:
+ tv_start_scan(tvh, *(int *)arg);
+ return STREAM_OK;
+ case STREAM_CTRL_SET_TV_FREQ:
+ tv_set_freq(tvh, *(float *)arg * 16.0f);
+ return STREAM_OK;
+ case STREAM_CTRL_GET_TV_FREQ: {
+ unsigned long tmp = 0;
+ tv_get_freq(tvh, &tmp);
+ *(float *)arg = tmp / 16.0f;
+ return STREAM_OK;
+ }
+ case STREAM_CTRL_SET_TV_COLORS:
+ tv_set_color_options(tvh, ((int *)arg)[0], ((int *)arg)[1]);
+ return STREAM_OK;
+ case STREAM_CTRL_GET_TV_COLORS:
+ tv_get_color_options(tvh, ((int *)arg)[0], &((int *)arg)[1]);
+ return STREAM_OK;
+ case STREAM_CTRL_TV_SET_NORM:
+ tv_set_norm(tvh, (char *)arg);
+ return STREAM_OK;
+ case STREAM_CTRL_TV_STEP_NORM:
+ tv_step_norm(tvh);
+ return STREAM_OK;
+ case STREAM_CTRL_TV_SET_CHAN:
+ tv_set_channel(tvh, (char *)arg);
+ return STREAM_OK;
+ case STREAM_CTRL_TV_STEP_CHAN:
+ if (*(int *)arg >= 0) {
+ tv_step_channel(tvh, TV_CHANNEL_HIGHER);
+ } else {
+ tv_step_channel(tvh, TV_CHANNEL_LOWER);
+ }
+ return STREAM_OK;
+ case STREAM_CTRL_TV_LAST_CHAN:
+ tv_last_channel(tvh);
+ return STREAM_OK;
+ }
+ return STREAM_UNSUPPORTED;
+}
+
+static int demux_tv_control(demuxer_t *demuxer, int cmd, void *arg)
+{
+ tvi_handle_t *tvh=(tvi_handle_t*)(demuxer->priv);
+ if (cmd != DEMUXER_CTRL_STREAM_CTRL)
+ return DEMUXER_CTRL_NOTIMPL;
+ struct demux_ctrl_stream_ctrl *ctrl = arg;
+ ctrl->res = tv_stream_control(tvh, ctrl->ctrl, ctrl->arg);
+ return DEMUXER_CTRL_OK;
}
demuxer_desc_t demuxer_desc_tv = {
@@ -1097,6 +1146,7 @@ demuxer_desc_t demuxer_desc_tv = {
.desc = "TV card demuxer",
.type = DEMUXER_TYPE_TV,
.fill_buffer = demux_tv_fill_buffer,
+ .control = demux_tv_control,
.open = demux_open_tv,
.close = demux_close_tv,
};
diff --git a/stream/tv.h b/stream/tv.h
index 4323762139..c5e8aba91f 100644
--- a/stream/tv.h
+++ b/stream/tv.h
@@ -201,10 +201,6 @@ typedef struct {
int tv_set_color_options(tvi_handle_t *tvh, int opt, int val);
int tv_get_color_options(tvi_handle_t *tvh, int opt, int* val);
-#define TV_COLOR_BRIGHTNESS 1
-#define TV_COLOR_HUE 2
-#define TV_COLOR_SATURATION 3
-#define TV_COLOR_CONTRAST 4
int tv_step_channel_real(tvi_handle_t *tvh, int direction);
int tv_step_channel(tvi_handle_t *tvh, int direction);