[MPlayer-dev-eng] PVR Channel Navigation (3rd rev)
Reimar Döffinger
Reimar.Doeffinger at stud.uni-karlsruhe.de
Sun Apr 29 17:40:22 CEST 2007
Hello,
On Sun, Apr 29, 2007 at 05:23:27AM -0600, Sven Gothel wrote:
> @@ -126,7 +151,14 @@
> pvr->saturation = 0;
> pvr->width = -1;
> pvr->height = -1;
> - pvr->freq = NULL;
> + pvr->freq = -1;
> + pvr->chanidx = -1;
> + pvr->chanidx_last = -1;
> + pvr->stationlist.name[0] = '\0';
> + pvr->stationlist.list = NULL;
> + pvr->stationlist.total = 0;
> + pvr->stationlist.used = 0;
> + pvr->stationlist.enabled = 0;
I'd suggest either memset or a clear_/init_stationlist function.
The same in the copycreate_stationlist.
> + if ( NULL!= pvr->stationlist.list )
> + free(pvr->stationlist.list);
Don't you notice or don't you mind the very varying way you use spaces,
especially in if statements?
Also, you sometimes write "NULL != ptr", sometimes "ptr != NULL" and
sometimes "!ptr".
I slightly prefer the "if (!ptr)"/"if (ptr)" way and that's used in the
existing code alread.
> +/**
> + * Copy Constructor for stationlist
> + *
> + * @see parse_setup_stationlist
> + */
The first line should be marked with @brief (or \brief, whichever).
Parameters and return values should be documented as well.
> +static int
> +copycreate_stationlist(struct pvr_t *pvr, int num)
I still do not see a point in passing "struct pvr_t *" instead of only
"struct STATIONLIST *". Similarly also for print_all_stations,
disable_all_stations, set_station and after that also
parse_setup_stationlist
[...]
> + if ( pvr->stationlist.list != NULL )
> + {
> + free ( pvr->stationlist.list );
> + pvr->stationlist.list = NULL;
> + }
note that this requires that stationlist _must_ be initialized before
calling this function. This needs to be documented.
Or IMO better just removed, because putting the free operation here
instead of a separate function makes it very likely that someone in the
future who adds more stuff that is alloced to the STATIONLIST struct
forgets to also adds free here.
> + (void) disable_all_stations(pvr);
Please don't do do that (void).
> + while (*channels)
> + {
> + char* tmp = *(channels++);
> + char* sep = strchr(tmp,'-');
> + int freq = -1;
> + int i;
unused.
> + if (!sep) continue; // Wrong syntax, but mplayer should not crash
It should not ignore it either.
> + strlcpy(station, sep + 1, STATIONNAMESZ);
> +
> + sep[0] = '\0';
I doubt you're allowed to modify tv_param_channels.
> + strlcpy(channel, tmp, STATIONNAMESZ);
> +
> + while ((sep=strchr(station, '_')))
> + {
> + sep[0] = ' ';
> + }
> +
> + // if channel number is a number and larger than 1000 threat it as frequency
"treat", not "threat".
> + // tmp still contain pointer to null-terminated string with channel number here
> + if (atoi(channel)>1000)
> + {
> + freq=atoi(channel);
> + }
freq = atoi(channel);
if (freq <= 1000) freq = 0;
else channel = NULL;
> + memset(&vf, 0, sizeof(vf));
[...]
> + vf.type = 0;
That is really pointless unless you find a more descriptive name (e.g.
define) for this 0.
[...]
> + if (pvr->freq>0)
> + {
> + if ( get_v4l2_freq (pvr) == pvr->freq )
> + {
> + mp_msg (MSGT_OPEN, MSGL_STATUS,
> + "%s Frequency %d allready set.\n", LOG_LEVEL_V4L2, pvr->freq);
> + return 0;
> + }
s/allready/already/
Does this normally happen unless the user explicitly wants it? If not,
I'd say allow it, setting it twice might fix problems.
> + }
> +
> + if (pvr->dev_fd < 0)
> + return -1;
> +
> + if (0>=pvr->freq)
The second check for pvr->freq in that function. And by the time a
frequency value arrives here it has probably already been checked at 5 other
places anyway.
> + if (!vt.signal)
> + {
> + mp_msg (MSGT_OPEN, MSGL_ERR,
> + "%s NO SIGNAL at frequency %d (%d)\n", LOG_LEVEL_V4L2, pvr->freq, vf.frequency);
> + /* still return 0, since this is 'just informal' */
"informal"? Do you mean informational?
> +static int
> +set_station_by_channeloffset(struct pvr_t *pvr, int offset, int v4lAction)
Is an arbitrary offset instead of just +/-1 worth the extra complexity?
> + if ( pvr->stationlist.enabled>=abs(offset) )
> + {
> + int gotcha=0;
> + int chidx=pvr->chanidx + offset;
> +
> + while(!gotcha)
> + {
> + if ( chidx < 0 ) chidx += pvr->stationlist.used;
> + if ( chidx >= pvr->stationlist.used ) chidx -= pvr->stationlist.used;
chidx = (chidx + pvr->stationlist.used) % pvr->stationlist.used;
[...]
> + chidx += (offset>0)?1:-1;
FFSIGN(offset). Not sure that actually looks better though. Same about
abs() vs. FFABS().
> +static int
> +set_station_by_channelname(struct pvr_t *pvr, const char *channel, int v4lAction)
> +{
> + if (!pvr || !pvr->stationlist.list)
> + return -1;
> +
> + if ( pvr->stationlist.enabled>0 && channel )
Please check whether these checks really improve anything or actually
make a giant mess. At least the "pvr->stationlist.enabled>0" checks
leads to the weird inconsistency that switching to a disabled channel
causes only a warning if there is at least one enabled channel,
otherwise it fails without giving the user any clue why.
> + {
> + int i;
> +
> + /* select channel */
> + for (i = 0; i<pvr->stationlist.used ; i++)
> + {
> + if ( !strcasecmp(pvr->stationlist.list[i].name, channel))
> + {
> + if ( !pvr->stationlist.list[i].enabled )
> + {
> + mp_msg (MSGT_OPEN, MSGL_WARN,
> + "%s Switch disabled to user station channel: %8s - freq: %8d - station: %s\n", LOG_LEVEL_V4L2,
> + pvr->stationlist.list[i].name, pvr->stationlist.list[i].freq,
> + pvr->stationlist.list[i].station);
> +
> + return -1;
> + }
> + pvr->freq = pvr->stationlist.list[i].freq;
> + pvr->chanidx_last = pvr->chanidx;
> + pvr->chanidx = i;
> + break;
> + }
> + }
> +
> + if (i >= pvr->stationlist.used)
> + {
> + mp_msg (MSGT_OPEN, MSGL_WARN,
> + "%s unable to find channel %s\n", LOG_LEVEL_V4L2, channel);
> + } else {
> + mp_msg (MSGT_OPEN, MSGL_INFO,
> + "%s Switch to user station channel: %8s - freq: %8d - station: %s\n", LOG_LEVEL_V4L2,
> + pvr->stationlist.list[i].name, pvr->stationlist.list[i].freq,
> + pvr->stationlist.list[i].station);
> +
> + if(v4lAction)
> + {
> + return set_v4l2_freq (pvr);
> + }
> + return (pvr->freq>0)?0:-1;
Why the "pvr->freq>0" only after set_v4l2_freq, and is set_v4l2_freq
being called when the channel was not found really intended?
> +static int
> +set_station_by_freq(struct pvr_t *pvr, int freq, int v4lAction)
This is almost the same code, only one comparison and one message are
different. Merge those two functions.
> +static int
> +force_freq_offset (struct pvr_t *pvr, int offset)
This name is confusing. It steps the current frequency up or down, it
does not set an offset (an offset would remain when switching to a
different offset.
And I also think this could (and thus should) be put in a separate
patch since it is independent from the whole station stuff.
> +
> static int
> v4l2_list_capabilities (struct pvr_t *pvr)
> {
> @@ -916,13 +1573,14 @@
> "%s read (%d) bytes\n", LOG_LEVEL_PVR, pos);
> }
> }
> -
> +
> if (!pos)
> mp_msg (MSGT_OPEN, MSGL_ERR, "%s read %d bytes\n", LOG_LEVEL_PVR, pos);
>
> return pos;
> }
>
> +
> static int
> pvr_stream_open (stream_t *stream, int mode, void *opts, int *file_format)
> {
cosmetics.
> @@ -933,9 +1591,13 @@
> if (mode != STREAM_READ)
> return STREAM_UNSUPORTED;
>
> + if (strlen (stream->url) > 6 && stream->url[6] != '\0')
wtf?!?!?
> @@ -1029,12 +1691,129 @@
> return STREAM_OK;
> }
>
> +/* Public access */
> +
> +const char *
> +pvr_get_current_stationname (stream_t *stream)
> +{
> + struct pvr_t *pvr;
> +
> + if (!stream || stream->type != STREAMTYPE_PVR)
> + return NULL;
> +
> + pvr = (struct pvr_t *) stream->priv;
> +
> + if (NULL!=pvr->stationlist.list && pvr->stationlist.used>pvr->chanidx && pvr->chanidx>=0)
> + {
> + return pvr->stationlist.list[pvr->chanidx].station;
> + }
> + return NULL;
> +}
How long is the returned pointer valid?
> +const char *
> +pvr_get_current_channelname (stream_t *stream)
Same here. I don't think anything except returning a strdup'd string is
a good idea.
[...]
> case MP_CMD_TV_SET_FREQ:
> if (mpctx->file_format == DEMUXER_TYPE_TV)
> - tv_set_freq((tvi_handle_t *) (mpctx->demuxer->priv),
> - cmd->args[0].v.f * 16.0);
> + {
> + tv_set_freq((tvi_handle_t *) (mpctx->demuxer->priv),
> + cmd->args[0].v.f * 16.0);
> + }
Can't see a reason for these changes.
> +#ifdef HAVE_PVR
> + else if ( mpctx->stream!=NULL && STREAMTYPE_PVR == mpctx->stream->type )
> + {
> + pvr_set_freq (mpctx->stream, ROUND(cmd->args[0].v.f));
> + set_osd_msg(OSD_MSG_TV_CHANNEL, 1, 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 (mpctx->file_format == DEMUXER_TYPE_TV)
> - tv_step_freq((tvi_handle_t *) (mpctx->demuxer->priv),
> - cmd->args[0].v.f * 16.0);
> + {
> + tv_step_freq((tvi_handle_t *) (mpctx->demuxer->priv),
> + cmd->args[0].v.f * 16.0);
> + }
or these.
I think making that patch at least 20% smaller is a good and feasible
target.
Btw. I just noticed we have an official maintainer for stream_pvr.c
according to DOCS/tech/MAINTAINERS.
Greetings,
Reimar Döffinger
More information about the MPlayer-dev-eng
mailing list