[MPlayer-dev-eng] TV watching, 2nd patch...

Stephane Jourdois mplayer-dev-eng at rubis.org
Sun Dec 22 12:39:28 CET 2002


Hello all,

Here is my next patch for watching TV using mplayer in a fine way.

In the following, I'll use "tech channel" for channel number (ie.
frequency, used by technicians) and "user channel" for the channel
number (the number you use on your TV, such as all normal users).  


My patch adds a new config option to the -tv option :
	channels=<number>-<name>,<number>-<name>,...

Where number is the "tech channel" and name the name of the channel.


That permits a number of improves :
 - The name of the channel is written on screen using OSD on change
 - The tv_step_channel input command now does what it is intended to do,
   ie. increase or decrease "user channels" number, not tech channels.


I also added one input command : tv_last_channel (pronounce "bonus"),
which change the current channel to the channel in use before.


Of course, if you (user) decide not to use that facility, everything
will just work as before... and You'll use tech channel numbers.


I'll try to explain at least one of the decisions I made during
hacking : I decided to not create a new config file, since there are
(IMHO) too much config-file parsers in mplayer.
The problem is that the -tv option has a length limit. But in fact
that's not a problem, since the -tv option can be split. I just added
the following line to my ~/.mplayer/config :

tv = "channels=25-TF1,22-France 2,28-France 3,K06-Canal+,30-France 5/Arte,33-M6"

and that works just great !


Now for the lircrc part, here is a part of my ~/.lircrc :
	begin
		prog   = mplayer
		button = 1
		config = tv_set_channel 1
	end
	begin
		prog   = mplayer
		button = 2
		config = tv_set_channel 2
	end
<snip>
	begin
		prog   = mplayer
		button = channel+
		config = tv_step_channel 1
	end
	begin
		prog   = mplayer
		button = channel-
		config = tv_step_channel -1
	end
	begin
		prog   = mplayer
		button = Chan_Last
		config = tv_last_channel
	end
Of course you'll have to modify the buttons numbers for your remote...


Sorry for my confusing words about "tech" and "user", but I had to name
them...

I'm ready for comments on my code, suggestions for improvement, and
ideas for what have to be done next.

I'm in contact with nxtvepg main developper to include nextview support
in mplayer (to print current and next program using OSD, jsut as xawtv
does).

Would anybody be interested in nagra{vision,udio} support for
mplayer ?


Thank you for reading.
Stéphane Jourdois


PS: does anyone knows why I need this patch ? after a few seconds of
watching tv, sh_video->fps gets to a very high value, and the osd never
disappears...
diff -u -r1.628 mplayer.c
--- mplayer.c	19 Dec 2002 10:09:27 -0000	1.628
+++ mplayer.c	20 Dec 2002 18:21:48 -0000
@@ -2076,7 +2077,7 @@
 	  
 #ifdef USE_OSD
       if(osd_level && sh_video){
-	osd_visible=sh_video->fps; // 1 sec
+	osd_visible=30; //sh_video->fps; // 1 sec
 	vo_osd_progbar_type=OSD_VOLUME;
 	vo_osd_progbar_value=(mixer_getbothvolume()*256.0)/100.0;
 	vo_osd_changed(OSDTYPE_PROGBAR);


PS2: Don't you think it would be time now to use indent ? Arpi could you
decide what are your prefered parameters for indent, and say it ? Anyone
will be able to reindent with other params for editing, and indent again
before submitting...

-- 
 ///  Stephane Jourdois        	/"\  ASCII RIBBON CAMPAIGN \\\
(((    Ingénieur développement 	\ /    AGAINST HTML MAIL    )))
 \\\   6, av. George V	         X                         ///
  \\\  75008  Paris             / \    +33 6 8643 3085    ///
-------------- next part --------------
diff -u -r1.69 cfg-common.h
--- cfg-common.h	5 Dec 2002 00:03:26 -0000	1.69
+++ cfg-common.h	20 Dec 2002 18:21:40 -0000
@@ -246,6 +246,7 @@
 	{"input", &tv_param_input, CONF_TYPE_INT, 0, 0, 20, NULL},
 	{"outfmt", &tv_param_outfmt, CONF_TYPE_STRING, 0, 0, 0, NULL},
 	{"fps", &tv_param_fps, CONF_TYPE_FLOAT, 0, 0, 100.0, NULL},
+	{"channels", &tv_param_channels, CONF_TYPE_STRING_LIST, 0, 0, 0, NULL},
 #ifdef HAVE_TV_V4L
 	{"amode", &tv_param_amode, CONF_TYPE_INT, CONF_RANGE, 0, 3, NULL},
 	{"volume", &tv_param_volume, CONF_TYPE_INT, CONF_RANGE, 0, 65535, NULL},
diff -u -r1.628 mplayer.c
--- mplayer.c	19 Dec 2002 10:09:27 -0000	1.628
+++ mplayer.c	20 Dec 2002 18:21:48 -0000
@@ -562,6 +562,7 @@
 int osd_show_sub_pos = 0;
 int osd_show_sub_visibility = 0;
 int osd_show_vobsub_changed = 0;
+int osd_show_tv_channel = 30;
 
 int rtc_fd=-1;
 
@@ -2282,15 +2283,44 @@
     case MP_CMD_TV_STEP_CHANNEL :  {
       if (tv_param_on == 1) {
 	int v = cmd->args[0].v.i;
-	if(v > 0)
+	if(v > 0) {
 	  tv_step_channel((tvi_handle_t*)(demuxer->priv), TV_CHANNEL_HIGHER);
-	else
+#ifdef USE_OSD
+	  if (tv_channel_list) {
+	    osd_show_tv_channel = 30;
+	    vo_osd_changed(OSDTYPE_SUBTITLE);
+	  }
+#endif
+	} else {
 	  tv_step_channel((tvi_handle_t*)(demuxer->priv), TV_CHANNEL_LOWER);
+#ifdef USE_OSD
+	  if (tv_channel_list) {
+	    osd_show_tv_channel = 30;
+	    vo_osd_changed(OSDTYPE_SUBTITLE);
+	  }
+#endif
+	}
       }
     } break;
     case MP_CMD_TV_SET_CHANNEL :  {
       if (tv_param_on == 1)
 	tv_set_channel((tvi_handle_t*)(demuxer->priv), cmd->args[0].v.s);
+#ifdef USE_OSD
+	if (tv_channel_list) {
+		osd_show_tv_channel = 30;
+		vo_osd_changed(OSDTYPE_SUBTITLE);
+	}
+#endif
+    } break;
+    case MP_CMD_TV_LAST_CHANNEL :  {
+      if (tv_param_on == 1)
+	tv_last_channel((tvi_handle_t*)(demuxer->priv));
+#ifdef USE_OSD
+	if (tv_channel_list) {
+		osd_show_tv_channel = 30;
+		vo_osd_changed(OSDTYPE_SUBTITLE);
+	}
+#endif
     } break;
     case MP_CMD_TV_STEP_NORM :  {
       if (tv_param_on == 1)
@@ -2733,6 +2763,12 @@
       if (osd_show_dvd_nav_delay) {
           sprintf(osd_text_tmp, "DVDNAV: %s", dvd_nav_text);
           osd_show_dvd_nav_delay--;
+      } else
+#endif
+#ifdef USE_TV
+      if (osd_show_tv_channel && tv_channel_list) {
+	  sprintf(osd_text_tmp, "Channel: %s", tv_channel_current->name);
+	  osd_show_tv_channel--;
       } else
 #endif
       if (osd_show_sub_visibility) {
diff -u -r1.282 mplayer.1
--- DOCS/mplayer.1	17 Dec 2002 00:04:11 -0000	1.282
+++ DOCS/mplayer.1	20 Dec 2002 18:21:50 -0000
@@ -646,6 +646,12 @@
 Set tuner to <value> channel.
 .IPs chanlist=<value>
 available: europe-east, europe-west, us-bcast, us-cable, etc
+.IPs channels=<channel>-<name>,<channel>-<name>,...
+Set names for channels. Quote the parameter using "" if you wan't spaces in names.
+The channel names will then be written using OSD, and the commands tv_step_channel,
+tv_set_channel and tv_last_channel will then be usable using a remote (see. lirc).
+Warning : The channel number will then be the position in the 'channels' list,
+beginning with 1. Ie. use tv://1, tv://2, tv_set_channel 1, tv_set_channel 2, etc.
 .IPs audiorate=<value>
 set audio capture bitrate
 .IPs forceaudio
diff -u -r1.63 input.c
--- input/input.c	19 Dec 2002 10:09:42 -0000	1.63
+++ input/input.c	20 Dec 2002 18:21:54 -0000
@@ -75,6 +75,7 @@
   { MP_CMD_TV_STEP_NORM, "tv_step_norm",0, { {-1,{0}} }  },
   { MP_CMD_TV_STEP_CHANNEL_LIST, "tv_step_chanlist", 0, { {-1,{0}} }  },
   { MP_CMD_TV_SET_CHANNEL, "tv_set_channel", 1, { { MP_CMD_ARG_STRING, {0}}, {-1,{0}}  }},
+  { MP_CMD_TV_LAST_CHANNEL, "tv_last_channel", 0, { {-1,{0}} } },
 #endif
   { MP_CMD_VO_FULLSCREEN, "vo_fullscreen", 0, { {-1,{0}} } },
   { MP_CMD_SCREENSHOT, "screenshot", 0, { {-1,{0}} } },
diff -u -r1.27 input.h
--- input/input.h	19 Dec 2002 10:09:42 -0000	1.27
+++ input/input.h	20 Dec 2002 18:21:54 -0000
@@ -20,6 +20,7 @@
 #define MP_CMD_TV_STEP_NORM 18
 #define MP_CMD_TV_STEP_CHANNEL_LIST 19
 #define MP_CMD_TV_SET_CHANNEL 37
+#define MP_CMD_TV_LAST_CHANNEL 38
 #define MP_CMD_VO_FULLSCREEN 20
 #define MP_CMD_SUB_POS 21
 #define MP_CMD_DVDNAV 22
diff -u -r1.44 tv.c
--- libmpdemux/tv.c	19 Dec 2002 10:09:43 -0000	1.44
+++ libmpdemux/tv.c	20 Dec 2002 18:21:57 -0000
@@ -52,6 +52,7 @@
 int tv_param_input = 0; /* used in v4l and bttv */
 char *tv_param_outfmt = "yv12";
 float tv_param_fps = -1.0;
+char **tv_param_channels = NULL;
 #ifdef HAVE_TV_V4L
 int tv_param_amode = -1;
 int tv_param_audio_id = 0;
@@ -233,6 +234,52 @@
 	goto done;
     }
 
+    /* Handle channels names */
+    if (tv_param_channels) {
+	mp_msg(MSGT_TV, MSGL_INFO, "TV Channels names detected.\n");
+	tv_channel_list = malloc(sizeof(tv_channels_t));
+	tv_channel_list->index=1;
+	tv_channel_list->next=NULL;
+	tv_channel_list->prev=NULL;
+	tv_channel_current = tv_channel_list;
+
+	while (*tv_param_channels) {
+		char* tmp = *(tv_param_channels++);
+		int i;
+		struct CHANLIST cl;
+
+		strcpy(tv_channel_current->name, strchr(tmp, '-') + 1);
+		strchr(tmp, '-')[0] = '\0';
+		strncpy(tv_channel_current->number, tmp, 4);
+
+		tv_channel_current->freq = 0;
+		for (i = 0; i < chanlists[tvh->chanlist].count; i++) {
+		    cl = tvh->chanlist_s[i];
+		    if (!strcasecmp(cl.name, tv_channel_current->number)) {
+			tv_channel_current->freq=cl.freq;
+			break;
+		    }
+		}
+	        if (tv_channel_current->freq == 0)
+		    mp_msg(MSGT_TV, MSGL_ERR, "Couldn't find frequency for channel %s (%s)\n",
+				    tv_channel_current->number, tv_channel_current->name);
+
+		/*mp_msg(MSGT_TV, MSGL_INFO, "-- Detected channel %s - %s (%5.3f)\n",
+				tv_channel_current->number, tv_channel_current->name,
+				(float)tv_channel_current->freq/1000);*/
+
+		tv_channel_current->next = malloc(sizeof(tv_channels_t));
+		tv_channel_current->next->index = tv_channel_current->index + 1;
+		tv_channel_current->next->prev = tv_channel_current;
+		tv_channel_current->next->next = NULL;
+		tv_channel_current = tv_channel_current->next;
+	}
+
+	tv_channel_current->prev->next = NULL;
+	free(tv_channel_current);
+    } else 
+	    tv_channel_last_real = malloc(sizeof(char)*5);
+
     /* we need to set frequency */
     if (tv_param_freq)
     {
@@ -246,23 +293,38 @@
 	    freq, (float)freq/16);
     }
 
-    if (tv_param_channel)
-    {
-	struct CHANLIST cl;
+    if (tv_param_channel) {
+	if (tv_channel_list) {
+		int i;
+		int channel;
+		channel = atoi(tv_param_channel);
+
+		tv_channel_current = tv_channel_list;
+		for (i = 1; i < channel; i++)
+			if (tv_channel_current->next)
+				tv_channel_current = tv_channel_current->next;
+		mp_msg(MSGT_TV, MSGL_INFO, "Selected channel: %s - %s (freq: %.3f)\n", tv_channel_current->number,
+				tv_channel_current->name, (float)tv_channel_current->freq/1000);
+		tv_set_freq(tvh, (unsigned long)(((float)tv_channel_current->freq/1000)*16));
+		tv_channel_last = tv_channel_current;
+	} else {
+	    struct CHANLIST cl;
 
-	mp_msg(MSGT_TV, MSGL_V, "Requested channel: %s\n", tv_param_channel);
-	for (i = 0; i < chanlists[tvh->chanlist].count; i++)
-	{
-	    cl = tvh->chanlist_s[i];
-//	    printf("count%d: name: %s, freq: %d\n",
-//		i, cl.name, cl.freq);
-	    if (!strcasecmp(cl.name, tv_param_channel))
+	    mp_msg(MSGT_TV, MSGL_V, "Requested channel: %s\n", tv_param_channel);
+	    for (i = 0; i < chanlists[tvh->chanlist].count; i++)
 	    {
-		tvh->channel = i;
-		mp_msg(MSGT_TV, MSGL_INFO, "Selected channel: %s (freq: %.3f)\n",
-		    cl.name, (float)cl.freq/1000);
-		tv_set_freq(tvh, (unsigned long)(((float)cl.freq/1000)*16));
-		break;
+	        cl = tvh->chanlist_s[i];
+	    //  printf("count%d: name: %s, freq: %d\n",
+	    //	i, cl.name, cl.freq);
+	        if (!strcasecmp(cl.name, tv_param_channel))
+	        {
+		strcpy(tv_channel_last_real, cl.name);
+	    	tvh->channel = i;
+	    	mp_msg(MSGT_TV, MSGL_INFO, "Selected channel: %s (freq: %.3f)\n",
+	    	    cl.name, (float)cl.freq/1000);
+	    	tv_set_freq(tvh, (unsigned long)(((float)cl.freq/1000)*16));
+	    	break;
+	        }
 	    }
 	}
     }
@@ -520,13 +582,14 @@
 	tvh->functions->control(tvh->priv, TVI_CONTROL_TUN_SET_FREQ, &freq);
 
 	tvh->functions->control(tvh->priv, TVI_CONTROL_TUN_GET_FREQ, &freq);
+
 	mp_msg(MSGT_TV, MSGL_V, "Current frequency: %lu (%.3f)\n",
 	    freq, (float)freq/16);
     }
     return(1);
 }
 
-int tv_step_channel(tvi_handle_t *tvh, int direction)
+int tv_step_channel_real(tvi_handle_t *tvh, int direction)
 {
     struct CHANLIST cl;
 
@@ -534,6 +597,7 @@
     {
 	if (tvh->channel-1 >= 0)
 	{
+	    strcpy(tv_channel_last_real, tvh->chanlist_s[tvh->channel].name);
 	    cl = tvh->chanlist_s[--tvh->channel];
 	    mp_msg(MSGT_TV, MSGL_INFO, "Selected channel: %s (freq: %.3f)\n",
 		cl.name, (float)cl.freq/1000);
@@ -545,6 +609,7 @@
     {
 	if (tvh->channel+1 < chanlists[tvh->chanlist].count)
 	{
+	    strcpy(tv_channel_last_real, tvh->chanlist_s[tvh->channel].name);
 	    cl = tvh->chanlist_s[++tvh->channel];
 	    mp_msg(MSGT_TV, MSGL_INFO, "Selected channel: %s (freq: %.3f)\n",
 		cl.name, (float)cl.freq/1000);
@@ -554,11 +619,35 @@
     return(1);
 }
 
-int tv_set_channel(tvi_handle_t *tvh, char *channel)
-{
+int tv_step_channel(tvi_handle_t *tvh, int direction) {
+	if (tv_channel_list) {
+		if (direction == TV_CHANNEL_HIGHER) {
+			if (tv_channel_current->next) {
+				tv_channel_last = tv_channel_current;
+				tv_channel_current = tv_channel_current->next;
+				tv_set_freq(tvh, (unsigned long)(((float)tv_channel_current->freq/1000)*16));
+				mp_msg(MSGT_TV, MSGL_INFO, "Selected channel: %s - %s (freq: %.3f)\n",
+			tv_channel_current->number, tv_channel_current->name, (float)tv_channel_current->freq/1000);
+			}
+		}
+		if (direction == TV_CHANNEL_LOWER) {
+			if (tv_channel_current->prev) {
+				tv_channel_last = tv_channel_current;
+				tv_channel_current = tv_channel_current->prev;
+				tv_set_freq(tvh, (unsigned long)(((float)tv_channel_current->freq/1000)*16));
+				mp_msg(MSGT_TV, MSGL_INFO, "Selected channel: %s - %s (freq: %.3f)\n",
+			tv_channel_current->number, tv_channel_current->name, (float)tv_channel_current->freq/1000);
+			}
+		}
+	} else tv_step_channel_real(tvh, direction);
+	return(1);
+}
+
+int tv_set_channel_real(tvi_handle_t *tvh, char *channel) {
 	int i;
 	struct CHANLIST cl;
 
+        strcpy(tv_channel_last_real, tvh->chanlist_s[tvh->channel].name);
 	for (i = 0; i < chanlists[tvh->chanlist].count; i++)
 	{
 	    cl = tvh->chanlist_s[i];
@@ -573,6 +662,57 @@
 		break;
 	    }
 	}
+	return(1);
+}
+
+int tv_set_channel(tvi_handle_t *tvh, char *channel) {
+	int i, channel_int;
+
+	if (tv_channel_list) {
+		tv_channel_last = tv_channel_current;
+		channel_int = atoi(channel);
+		tv_channel_current = tv_channel_list;
+		for (i = 1; i < channel_int; i++)
+			if (tv_channel_current->next)
+				tv_channel_current = tv_channel_current->next;
+		mp_msg(MSGT_TV, MSGL_INFO, "Selected channel: %s - %s (freq: %.3f)\n", tv_channel_current->number,
+				tv_channel_current->name, (float)tv_channel_current->freq/1000);
+		tv_set_freq(tvh, (unsigned long)(((float)tv_channel_current->freq/1000)*16));
+	} else tv_set_channel_real(tvh, channel);
+	return(1);
+}
+
+int tv_last_channel(tvi_handle_t *tvh) {
+
+	if (tv_channel_list) {
+		tv_channels_t *tmp;
+
+		tmp = tv_channel_last;
+		tv_channel_last = tv_channel_current;
+		tv_channel_current = tmp;
+
+		mp_msg(MSGT_TV, MSGL_INFO, "Selected channel: %s - %s (freq: %.3f)\n", tv_channel_current->number,
+				tv_channel_current->name, (float)tv_channel_current->freq/1000);
+		tv_set_freq(tvh, (unsigned long)(((float)tv_channel_current->freq/1000)*16));
+	} else {
+		int i;
+		struct CHANLIST cl;
+
+		for (i = 0; i < chanlists[tvh->chanlist].count; i++)
+		{
+		    cl = tvh->chanlist_s[i];
+		    if (!strcasecmp(cl.name, tv_channel_last_real))
+		    {
+			strcpy(tv_channel_last_real, tvh->chanlist_s[tvh->channel].name);
+			tvh->channel = i;
+			mp_msg(MSGT_TV, MSGL_INFO, "Selected channel: %s (freq: %.3f)\n",
+			    cl.name, (float)cl.freq/1000);
+			tv_set_freq(tvh, (unsigned long)(((float)cl.freq/1000)*16));
+			break;
+		    }
+		}
+	}
+	return(1);
 }
 
 int tv_step_norm(tvi_handle_t *tvh)
diff -u -r1.20 tv.h
--- libmpdemux/tv.h	19 Dec 2002 10:09:43 -0000	1.20
+++ libmpdemux/tv.h	20 Dec 2002 18:21:57 -0000
@@ -20,6 +20,7 @@
 extern int tv_param_input;
 extern char *tv_param_outfmt;
 extern float tv_param_fps;
+extern char **tv_param_channels;
 extern int tv_param_noaudio;
 extern int tv_param_immediate;
 extern int tv_param_audiorate;
@@ -75,6 +76,18 @@
     int			channel;
 } tvi_handle_t;
 
+typedef struct tv_channels_s {
+    int index;
+    char number[5];
+    char name[20];
+    int   freq;
+    struct tv_channels_s *next;
+    struct tv_channels_s *prev;
+} tv_channels_t;
+
+tv_channels_t *tv_channel_list;
+tv_channels_t *tv_channel_current, *tv_channel_last;
+char *tv_channel_last_real;
 
 #define TVI_CONTROL_FALSE		0
 #define TVI_CONTROL_TRUE		1
@@ -144,10 +157,14 @@
 #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);
 #define TV_CHANNEL_LOWER	1
 #define TV_CHANNEL_HIGHER	2
 
+int tv_last_channel(tvi_handle_t *tvh);
+
+int tv_set_channel_real(tvi_handle_t *tvh, char *channel);
 int tv_set_channel(tvi_handle_t *tvh, char *channel);
 
 int tv_step_norm(tvi_handle_t *tvh);


More information about the MPlayer-dev-eng mailing list