diff options
author | voroshil <voroshil@b3059339-0415-0410-9bf9-f77b7e298cf2> | 2007-08-23 16:09:30 +0000 |
---|---|---|
committer | voroshil <voroshil@b3059339-0415-0410-9bf9-f77b7e298cf2> | 2007-08-23 16:09:30 +0000 |
commit | f1fbca4bdd35b7ceb636dac0b979fa1acca9e609 (patch) | |
tree | c04e7a27a93c5e0600527963875dc00590c177e3 | |
parent | ffac6ce7eba3dea5878f3eb482a11e9ab7606455 (diff) | |
download | mpv-f1fbca4bdd35b7ceb636dac0b979fa1acca9e609.tar.bz2 mpv-f1fbca4bdd35b7ceb636dac0b979fa1acca9e609.tar.xz |
Automatic TV channels scanning ability for MPlayer.
Code is based on patch from Otvos Attila oattila at chello dot hu
git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@24125 b3059339-0415-0410-9bf9-f77b7e298cf2
-rw-r--r-- | DOCS/man/en/mplayer.1 | 20 | ||||
-rw-r--r-- | DOCS/tech/slave.txt | 3 | ||||
-rw-r--r-- | cfg-mplayer.h | 13 | ||||
-rw-r--r-- | command.c | 4 | ||||
-rw-r--r-- | input/input.c | 1 | ||||
-rw-r--r-- | input/input.h | 1 | ||||
-rw-r--r-- | stream/stream_tv.c | 6 | ||||
-rw-r--r-- | stream/tv.c | 104 | ||||
-rw-r--r-- | stream/tv.h | 15 | ||||
-rw-r--r-- | stream/tvi_def.h | 3 | ||||
-rw-r--r-- | stream/tvi_v4l.c | 10 | ||||
-rw-r--r-- | stream/tvi_v4l2.c | 8 |
12 files changed, 187 insertions, 1 deletions
diff --git a/DOCS/man/en/mplayer.1 b/DOCS/man/en/mplayer.1 index 5a800e4731..a8f5339174 100644 --- a/DOCS/man/en/mplayer.1 +++ b/DOCS/man/en/mplayer.1 @@ -1899,6 +1899,26 @@ Specify initial TV teletext page number. .RE . .TP +.B \-tvscan <option1:option2:...> (TV and MPlayer only) +This option tunes various parameters for TV channel scanner. +MPlayer will also print value for "-tv channels=" option, +including existing and just found channels. +.sp 1 +Available suboptions are: +.RSs +.IPs autostart (default: not set) +Begin channel scanning immediately after MPlayer startup. +.IPs period=<0.1-2.0> (default: 0.5) +Specify delay in seconds before switching to next channel. +Lower values will cause faster scanning, but can detect +inactive TV channels as active. +.IPs threshold=<1-100> (default: 50) +Threshold value (in percent) for signal strength, reported by device. +Signal strength higher than this value will indicate that +currently scanning channel is active. +.RE +. +.TP .B \-user <username> (also see \-passwd) (network only) Specify username for HTTP authentication. . diff --git a/DOCS/tech/slave.txt b/DOCS/tech/slave.txt index ceef2086aa..6ede79b5ac 100644 --- a/DOCS/tech/slave.txt +++ b/DOCS/tech/slave.txt @@ -330,6 +330,9 @@ teletext_add_digit <value> - - Delete last digit from page number. (Backspace emulation, works only in page number editing mode.) +tv_start_scan + Start automatic tv channels scaning + tv_step_channel <channel> Select next/previous TV channel. diff --git a/cfg-mplayer.h b/cfg-mplayer.h index 502661559c..294e1ca743 100644 --- a/cfg-mplayer.h +++ b/cfg-mplayer.h @@ -114,6 +114,14 @@ m_option_t vd_conf[]={ {NULL, NULL, 0, 0, 0, 0, NULL} }; +#ifdef USE_TV +m_option_t tvscan_conf[]={ + {"autostart", &stream_tv_defaults.scan, CONF_TYPE_FLAG, 0, 0, 1, NULL}, + {"threshold", &stream_tv_defaults.scan_threshold, CONF_TYPE_INT, CONF_RANGE, 1, 100, NULL}, + {"period", &stream_tv_defaults.scan_period, CONF_TYPE_FLOAT, CONF_RANGE, 0.1, 2.0, NULL}, + {NULL, NULL, 0, 0, 0, 0, NULL} +}; +#endif /* * CONF_TYPE_FUNC_FULL : * allows own implementations for passing the params @@ -387,6 +395,11 @@ m_option_t mplayer_opts[]={ {"mouse-movements", &enable_mouse_movements, CONF_TYPE_FLAG, CONF_GLOBAL, 0, 1, NULL}, {"nomouse-movements", &enable_mouse_movements, CONF_TYPE_FLAG, CONF_GLOBAL, 1, 0, NULL}, {"doubleclick-time", &doubleclick_time, CONF_TYPE_INT, CONF_RANGE, 0, 1000, NULL}, +#ifdef USE_TV + {"tvscan", &tvscan_conf, CONF_TYPE_SUBCONFIG, 0, 0, 0, NULL}, +#else + {"tvscan", "MPlayer was compiled without TV interface support.\n", CONF_TYPE_PRINT, 0, 0, 0, NULL}, +#endif #define MAIN_CONF #include "cfg-common.h" @@ -2287,6 +2287,10 @@ int run_command(MPContext * mpctx, mp_cmd_t * cmd) #endif #ifdef USE_TV + case MP_CMD_TV_START_SCAN: + if (mpctx->file_format == DEMUXER_TYPE_TV) + tv_start_scan((tvi_handle_t *) (mpctx->demuxer->priv),1); + break; case MP_CMD_TV_SET_FREQ: if (mpctx->file_format == DEMUXER_TYPE_TV) tv_set_freq((tvi_handle_t *) (mpctx->demuxer->priv), diff --git a/input/input.c b/input/input.c index a14fe75edf..248f65fec2 100644 --- a/input/input.c +++ b/input/input.c @@ -111,6 +111,7 @@ static mp_cmd_t mp_cmds[] = { { MP_CMD_GET_META_GENRE, "get_meta_genre", 0, { {-1,{0}} } }, { MP_CMD_SWITCH_AUDIO, "switch_audio", 0, { { MP_CMD_ARG_INT,{-1} }, {-1,{0}} } }, #ifdef USE_TV + { MP_CMD_TV_START_SCAN, "tv_start_scan", 0, { {-1,{0}} }}, { MP_CMD_TV_STEP_CHANNEL, "tv_step_channel", 1, { { MP_CMD_ARG_INT ,{0}}, {-1,{0}} }}, { MP_CMD_TV_STEP_NORM, "tv_step_norm",0, { {-1,{0}} } }, { MP_CMD_TV_STEP_CHANNEL_LIST, "tv_step_chanlist", 0, { {-1,{0}} } }, diff --git a/input/input.h b/input/input.h index 9970207c4c..7e5b3e83d2 100644 --- a/input/input.h +++ b/input/input.h @@ -98,6 +98,7 @@ #define MP_CMD_SUB_SCALE 97 #define MP_CMD_TV_TELETEXT_ADD_DEC 98 #define MP_CMD_TV_TELETEXT_GO_LINK 99 +#define MP_CMD_TV_START_SCAN 100 #define MP_CMD_GUI_EVENTS 5000 #define MP_CMD_GUI_LOADFILE 5001 diff --git a/stream/stream_tv.c b/stream/stream_tv.c index 8332b07477..bbddac1aff 100644 --- a/stream/stream_tv.c +++ b/stream/stream_tv.c @@ -74,7 +74,11 @@ tv_param_t stream_tv_defaults = { 0, //saturation NULL, //tdevice 0, //tformat - 100 //tpage + 100, //tpage + + 0, //scan_autostart + 50, //scan_threshold + 0.5 //scan_period }; #define ST_OFF(f) M_ST_OFF(tv_param_t,f) diff --git a/stream/tv.c b/stream/tv.c index 12d23895b9..ce1622b468 100644 --- a/stream/tv.c +++ b/stream/tv.c @@ -30,6 +30,7 @@ #include "libaf/af_format.h" #include "libmpcodecs/img_format.h" #include "libavutil/avstring.h" +#include "osdep/timer.h" #include "tv.h" @@ -65,6 +66,92 @@ static const tvi_info_t* tvi_driver_list[]={ NULL }; +void tv_start_scan(tvi_handle_t *tvh, int start) +{ + mp_msg(MSGT_TV,MSGL_INFO,"start scan\n"); + tvh->tv_param->scan=start?1:0; +} + +static void tv_scan(tvi_handle_t *tvh) +{ + unsigned int now; + struct CHANLIST cl; + tv_channels_t *tv_channel_tmp=NULL; + tv_channels_t *tv_channel_add=NULL; + tv_scan_t* scan; + int found=0, index=1; + + scan = tvh->scan; + now=GetTimer(); + if (!scan) { + scan=calloc(1,sizeof(tv_scan_t)); + tvh->scan=scan; + cl = tvh->chanlist_s[scan->channel_num]; + tv_set_freq(tvh, (unsigned long)(((float)cl.freq/1000)*16)); + scan->scan_timer=now+1e6*tvh->tv_param->scan_period; + } + if(scan->scan_timer>now) + return; + + if (tv_get_signal(tvh)>tvh->tv_param->scan_threshold) { + cl = tvh->chanlist_s[scan->channel_num]; + tv_channel_tmp=tv_channel_list; + while (tv_channel_tmp) { + index++; + if (cl.freq==tv_channel_tmp->freq){ + found=1; + break; + } + tv_channel_add=tv_channel_tmp; + tv_channel_tmp=tv_channel_tmp->next; + } + if (!found) { + mp_msg(MSGT_TV, MSGL_INFO, "Found new channel: %s (#%d). \n",cl.name,index); + scan->new_channels++; + tv_channel_tmp = malloc(sizeof(tv_channels_t)); + tv_channel_tmp->index=index; + tv_channel_tmp->next=NULL; + tv_channel_tmp->prev=tv_channel_add; + tv_channel_tmp->freq=cl.freq; + snprintf(tv_channel_tmp->name,sizeof(tv_channel_tmp->name),"ch%d",index); + strncpy(tv_channel_tmp->number, cl.name, 5); + tv_channel_tmp->number[4]='\0'; + if (!tv_channel_list) + tv_channel_list=tv_channel_tmp; + else { + tv_channel_add->next=tv_channel_tmp; + tv_channel_list->prev=tv_channel_tmp; + } + }else + mp_msg(MSGT_TV, MSGL_INFO, "Found existing channel: %s-%s.\n", + tv_channel_tmp->number,tv_channel_tmp->name); + } + scan->channel_num++; + scan->scan_timer=now+1e6*tvh->tv_param->scan_period; + if (scan->channel_num>=chanlists[tvh->chanlist].count) { + tvh->tv_param->scan=0; + mp_msg(MSGT_TV, MSGL_INFO, "TV scan end. Found %d new channels.\n", scan->new_channels); + tv_channel_tmp=tv_channel_list; + if(tv_channel_tmp){ + mp_msg(MSGT_TV,MSGL_INFO,"channels="); + while(tv_channel_tmp){ + mp_msg(MSGT_TV,MSGL_INFO,"%s-%s",tv_channel_tmp->number,tv_channel_tmp->name); + if(tv_channel_tmp->next) + mp_msg(MSGT_TV,MSGL_INFO,","); + tv_channel_tmp=tv_channel_tmp->next; + } + } + if (!tv_channel_current) tv_channel_current=tv_channel_list; + if (tv_channel_current) + tv_set_freq(tvh, (unsigned long)(((float)tv_channel_current->freq/1000)*16)); + free(tvh->scan); + tvh->scan=NULL; + }else{ + cl = tvh->chanlist_s[scan->channel_num]; + tv_set_freq(tvh, (unsigned long)(((float)cl.freq/1000)*16)); + mp_msg(MSGT_TV, MSGL_INFO, "Trying: %s (%.2f). \n",cl.name,1e-3*cl.freq); + } +} /* ================== DEMUX_TV ===================== */ /* @@ -106,6 +193,7 @@ static int demux_tv_fill_buffer(demuxer_t *demux, demux_stream_t *ds) ds_add_packet(demux->video,dp); } + if (tvh->tv_param->scan) tv_scan(tvh); return 1; } @@ -738,6 +826,16 @@ int tv_set_freq(tvi_handle_t *tvh, unsigned long freq) return(1); } +int tv_get_signal(tvi_handle_t *tvh) +{ + int signal=0; + if (tvh->functions->control(tvh->priv, TVI_CONTROL_IS_TUNER, 0) != TVI_CONTROL_TRUE || + tvh->functions->control(tvh->priv, TVI_CONTROL_TUN_GET_SIGNAL, &signal)!=TVI_CONTROL_TRUE) + return 0; + + return signal; +} + /***************************************************************** * \brief tune current frequency by step_interval value * \parameter step_interval increment value in 1/16 MHz @@ -748,6 +846,7 @@ int tv_set_freq(tvi_handle_t *tvh, unsigned long freq) int tv_step_freq(tvi_handle_t* tvh, float step_interval){ unsigned long frequency; + tvh->tv_param->scan=0; tv_get_freq(tvh,&frequency); frequency+=step_interval; return tv_set_freq(tvh,frequency); @@ -757,6 +856,7 @@ int tv_step_channel_real(tvi_handle_t *tvh, int direction) { struct CHANLIST cl; + tvh->tv_param->scan=0; if (direction == TV_CHANNEL_LOWER) { if (tvh->channel-1 >= 0) @@ -784,6 +884,7 @@ int tv_step_channel_real(tvi_handle_t *tvh, int direction) } int tv_step_channel(tvi_handle_t *tvh, int direction) { + tvh->tv_param->scan=0; if (tv_channel_list) { if (direction == TV_CHANNEL_HIGHER) { tv_channel_last = tv_channel_current; @@ -814,6 +915,7 @@ int tv_set_channel_real(tvi_handle_t *tvh, char *channel) { int i; struct CHANLIST cl; + tvh->tv_param->scan=0; strcpy(tv_channel_last_real, tvh->chanlist_s[tvh->channel].name); for (i = 0; i < chanlists[tvh->chanlist].count; i++) { @@ -835,6 +937,7 @@ int tv_set_channel_real(tvi_handle_t *tvh, char *channel) { int tv_set_channel(tvi_handle_t *tvh, char *channel) { int i, channel_int; + tvh->tv_param->scan=0; if (tv_channel_list) { tv_channel_last = tv_channel_current; channel_int = atoi(channel); @@ -851,6 +954,7 @@ int tv_set_channel(tvi_handle_t *tvh, char *channel) { int tv_last_channel(tvi_handle_t *tvh) { + tvh->tv_param->scan=0; if (tv_channel_list) { tv_channels_t *tmp; diff --git a/stream/tv.h b/stream/tv.h index 415fa2c006..c61c4b6c87 100644 --- a/stream/tv.h +++ b/stream/tv.h @@ -50,6 +50,10 @@ typedef struct tv_param_s { char *tdevice; ///< teletext device int tformat; ///< teletext display format int tpage; ///< start teletext page + + int scan; + int scan_threshold; + float scan_period; } tv_param_t; extern tv_param_t stream_tv_defaults; @@ -86,6 +90,7 @@ typedef struct tvi_handle_s { const struct CHANLIST *chanlist_s; int channel; tv_param_t * tv_param; + void * scan; } tvi_handle_t; typedef struct tv_channels_s { @@ -101,6 +106,12 @@ extern tv_channels_t *tv_channel_list; extern tv_channels_t *tv_channel_current, *tv_channel_last; extern char *tv_channel_last_real; +typedef struct { + unsigned int scan_timer; + int channel_num; + int new_channels; +} tv_scan_t; + #define TVI_CONTROL_FALSE 0 #define TVI_CONTROL_TRUE 1 #define TVI_CONTROL_NA -1 @@ -147,6 +158,7 @@ extern char *tv_channel_last_real; #define TVI_CONTROL_TUN_SET_TUNER 0x204 /* update priv->tuner struct for used input */ #define TVI_CONTROL_TUN_GET_NORM 0x205 #define TVI_CONTROL_TUN_SET_NORM 0x206 +#define TVI_CONTROL_TUN_GET_SIGNAL 0x207 /* AUDIO controls */ #define TVI_CONTROL_AUD_GET_FORMAT 0x301 @@ -215,10 +227,13 @@ int tv_step_chanlist(tvi_handle_t *tvh); int tv_set_freq(tvi_handle_t *tvh, unsigned long freq); int tv_get_freq(tvi_handle_t *tvh, unsigned long *freq); +int tv_get_signal(tvi_handle_t *tvh); int tv_step_freq(tvi_handle_t *tvh, float step_interval); int tv_set_norm(tvi_handle_t *tvh, char* norm); +void tv_start_scan(tvi_handle_t *tvh, int start); + #define TV_NORM_PAL 1 #define TV_NORM_NTSC 2 #define TV_NORM_SECAM 3 diff --git a/stream/tvi_def.h b/stream/tvi_def.h index 6dff1c8924..c47b0dfe36 100644 --- a/stream/tvi_def.h +++ b/stream/tvi_def.h @@ -43,6 +43,7 @@ static tvi_handle_t *new_handle(void) h->chanlist_s = NULL; h->norm = -1; h->channel = -1; + h->scan = NULL; return(h); } @@ -51,6 +52,8 @@ static void free_handle(tvi_handle_t *h) if (h) { if (h->priv) free(h->priv); + if (h->scan) + free(h->scan); free(h); } } diff --git a/stream/tvi_v4l.c b/stream/tvi_v4l.c index bfcf62d916..adbdf927c7 100644 --- a/stream/tvi_v4l.c +++ b/stream/tvi_v4l.c @@ -1441,6 +1441,16 @@ static int control(priv_t *priv, int cmd, void *arg) return(TVI_CONTROL_TRUE); } + case TVI_CONTROL_TUN_GET_SIGNAL: + { + if (ioctl(priv->video_fd, VIDIOCGTUNER, &priv->tuner) == -1) + { + mp_msg(MSGT_TV, MSGL_ERR, "ioctl get tuner failed: %s\n", strerror(errno)); + return(TVI_CONTROL_FALSE); + } + *(int*)arg=100*(priv->tuner.signal>>8)/255; + return(TVI_CONTROL_TRUE); + } /* ========== AUDIO controls =========== */ case TVI_CONTROL_AUD_GET_FORMAT: diff --git a/stream/tvi_v4l2.c b/stream/tvi_v4l2.c index d808cc6838..10c92b3163 100644 --- a/stream/tvi_v4l2.c +++ b/stream/tvi_v4l2.c @@ -864,6 +864,14 @@ static int control(priv_t *priv, int cmd, void *arg) case TVI_CONTROL_TUN_GET_NORM: *(int *)arg = priv->standard.index; return TVI_CONTROL_TRUE; + case TVI_CONTROL_TUN_GET_SIGNAL: + if (ioctl(priv->video_fd, VIDIOC_G_TUNER, &priv->tuner) < 0) { + mp_msg(MSGT_TV, MSGL_ERR, "%s: ioctl get tuner failed: %s\n", + info.short_name, strerror(errno)); + return TVI_CONTROL_FALSE; + } + *(int*)arg=100*(priv->tuner.signal>>8)/255; + return TVI_CONTROL_TRUE; case TVI_CONTROL_TUN_SET_NORM: priv->standard.index = *(int *)arg; if (ioctl(priv->video_fd, VIDIOC_ENUMSTD, &priv->standard) < 0) { |