All of lore.kernel.org
 help / color / mirror / Atom feed
From: Yufei Yuan <yfyuan@gmail.com>
To: Manu Abraham <abraham.manu@gmail.com>
Cc: Linux Media Mailing List <linux-media@vger.kernel.org>
Subject: Re: [Patch] New utility program atsc_epg added to dvb-apps utility suite.
Date: Sat, 20 Jun 2009 08:30:41 -0500	[thread overview]
Message-ID: <1245504647.15347.3.camel@core2duo.localdomain> (raw)
In-Reply-To: <1a297b360906200030y1322de83j296ced63e713ef66@mail.gmail.com>

Thanks for the feedback. Will fix the coding style, and send in a new one 
against the tip.

Regards,

On Sat, 2009-06-20 at 11:30 +0400, Manu Abraham wrote:
> On Fri, Jun 19, 2009 at 5:55 AM, Yufei Yuan<yfyuan@gmail.com> wrote:
> > Not sure how to make it look right in gmail, but the inline patch does
> > not look right to my eyes. I have the patch attached behind as a
> > backup.
> 
> You can attach the patch, no worries.
> 
> I have applied the patch, but the CodingStyle is not very nice, mostly
> the wrapping to 80 cols is done in a bad way. It makes the code not
> easy to read.
> 
> Also have made some comments inline from your patch. Please do fix the
> mentioned ones against the dvb-apps head
> 
> 
> 
> 
> diff -uprN dvb-apps/util/atsc_epg/atsc_epg.c
> dvb-apps_new/util/atsc_epg/atsc_epg.c
> --- dvb-apps/util/atsc_epg/atsc_epg.c	1969-12-31 18:00:00.000000000 -0600
> +++ dvb-apps_new/util/atsc_epg/atsc_epg.c	2009-06-18 20:17:24.527925142 -0500
> @@ -0,0 +1,1249 @@
> +/*
> + * atsc_epg utility
> + *
> + * Copyright (C) 2009 Yufei Yuan <yfyuan@gmail.com>
> + * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
> + */
> +
> +#include <stdio.h>
> +#include <stdlib.h>
> +#include <unistd.h>
> +#include <string.h>
> +#include <time.h>
> +#include <signal.h>
> +#include <sys/types.h>
> +#include <sys/stat.h>
> +#include <fcntl.h>
> +#include <sys/ioctl.h>
> +#include <sys/poll.h>
> +#include <errno.h>
> +#include <getopt.h>
> +#include <stdarg.h>
> +#include <libdvbapi/dvbfe.h>
> +#include <libdvbapi/dvbdemux.h>
> +#include <libucsi/dvb/section.h>
> +#include <libucsi/atsc/section.h>
> +#include <libucsi/atsc/types.h>
> +
> +#define TIMEOUT				60
> +#define RRT_TIMEOUT			60
> +#define MAX_NUM_EVENT_TABLES		128
> +#define TITLE_BUFFER_LEN		4096
> +#define MESSAGE_BUFFER_LEN		(16 * 1024)
> +#define MAX_NUM_CHANNELS		16
> +#define MAX_NUM_EVENTS_PER_CHANNEL	(4 * 24 * 7)
> +
> +static int atsc_scan_table(int dmxfd, uint16_t pid, enum atsc_section_tag tag,
> +	void **table_section);
> +
> +static const char *program;
> +static int adapter = 0;
> +static int period = 12; /* hours */
> +static int frequency;
> +static int enable_ett = 0;
> +static int ctrl_c = 0;
> +static const char *modulation = NULL;
> +static char separator[80];
> +void (*old_handler)(int);
> +
> +struct atsc_string_buffer {
> +	int buf_len;
> +	int buf_pos;
> +	char *string;
> +};
> +
> +struct atsc_event_info {
> +	uint16_t id;
> +	struct tm start;
> +	struct tm end;
> +	int title_pos;
> +	int title_len;
> +	int msg_pos;
> +	int msg_len;
> +};
> +
> +struct atsc_eit_section_info {
> +	uint8_t section_num;
> +	uint8_t num_events;
> +	uint8_t num_etms;
> +	uint8_t num_received_etms;
> +	struct atsc_event_info **events;
> +};
> +
> +struct atsc_eit_info {
> +	int num_eit_sections;
> +	struct atsc_eit_section_info *section;
> +};
> +
> +struct atsc_channel_info {
> +	uint8_t num_eits;
> +	uint8_t service_type;
> +	char short_name[8];
> +	uint16_t major_num;
> +	uint16_t minor_num;
> +	uint16_t tsid;
> +	uint16_t prog_num;
> +	uint16_t src_id;
> +	struct atsc_eit_info *eit;
> +	struct atsc_event_info *last_event;
> +	int event_info_index;
> +	struct atsc_event_info e[MAX_NUM_EVENTS_PER_CHANNEL];
> +	struct atsc_string_buffer title_buf;
> +	struct atsc_string_buffer msg_buf;
> +};
> +
> +struct atsc_virtual_channels_info {
> +	int num_channels;
> +	uint16_t eit_pid[MAX_NUM_EVENT_TABLES];
> +	uint16_t ett_pid[MAX_NUM_EVENT_TABLES];
> +	struct atsc_channel_info ch[MAX_NUM_CHANNELS];
> +} guide;
> +
> +struct mgt_table_name {
> +	uint16_t range;
> +	const char *string;
> +};
> +
> +struct mgt_table_name mgt_tab_name_array[] = {
> +	{0x0000, "terrestrial VCT with current_next_indictor=1"},
> +	{0x0001, "terrestrial VCT with current_next_indictor=0"},
> +	{0x0002, "cable VCT with current_next_indictor=1"},
> +	{0x0003, "cable VCT with current_next_indictor=0"},
> +	{0x0004, "channel ETT"},
> +	{0x0005, "DCCSCT"},
> +	{0x00FF, "reserved for future ATSC use"},
> +	{0x017F, "EIT"},
> +	{0x01FF, "reserved for future ATSC use"},
> +	{0x027F, "event ETT"},
> +	{0x02FF, "reserved for future ATSC use"}, /* FIXME */
> +	{0x03FF, "RRT with rating region"},
> +	{0x0FFF, "user private"},
> +	{0x13FF, "reserved for future ATSC use"},
> +	{0x14FF, "DCCT with dcc_id"},
> +	{0xFFFF, "reserved for future ATSC use"}
> +};
> +
> +const char *channel_modulation_mode[] = {
> +	"",
> +	"analog",
> +	"SCTE mode 1",
> +	"SCTE mode 2",
> +	"ATSC 8VSB",
> +	"ATSC 16VSB"
> +};
> +
> +const char *channel_service_type[] = {
> +	"",
> +	"analog TV",
> +	"ATSC digital TV",
> +	"ATSC audio",
> +	"ATSC data-only"
> +};
> +
> +void *(*table_callback[16])(struct atsc_section_psip *) =
> +{
> +	NULL, NULL, NULL, NULL, NULL, NULL, NULL,
> +	(void *(*)(struct atsc_section_psip *))atsc_mgt_section_codec,
> +	(void *(*)(struct atsc_section_psip *))atsc_tvct_section_codec,
> +	(void *(*)(struct atsc_section_psip *))atsc_cvct_section_codec,
> +	(void *(*)(struct atsc_section_psip *))atsc_rrt_section_codec,
> +	(void *(*)(struct atsc_section_psip *))atsc_eit_section_codec,
> +	(void *(*)(struct atsc_section_psip *))atsc_ett_section_codec,
> +	(void *(*)(struct atsc_section_psip *))atsc_stt_section_codec,
> +	NULL, NULL
> +};
> +
> +static void int_handler(int sig_num)
> +{
> +	if(SIGINT != sig_num) {
> +		return;
> +	}
> +	ctrl_c = 1;
> +}
> +
> +/* shamelessly stolen from dvbsnoop, but almost not modified */
> +static uint32_t get_bits(const uint8_t *buf, int startbit, int bitlen)
> +{
> +	const uint8_t *b;
> +	uint32_t mask,tmp_long;
> +	int bitHigh,i;
> +
> +	b = &buf[startbit / 8];
> +	startbit %= 8;
> +
> +	bitHigh = 8;
> +	tmp_long = b[0];
> +	for (i = 0; i < ((bitlen-1) >> 3); i++) {
> +		tmp_long <<= 8;
> +		tmp_long  |= b[i+1];
> +		bitHigh   += 8;
> +	}
> +
> +	startbit = bitHigh - startbit - bitlen;
> +	tmp_long = tmp_long >> startbit;
> +	mask     = (1ULL << bitlen) - 1;
> +	return tmp_long & mask;
> +}
> +
> +static void usage(void)
> +{
> +	fprintf(stderr, "usage: %s [-a <n>] -f <frequency> [-p <period>]"
> +		" [-m <modulation>] [-t] [-h]\n", program);
> +}
> +
> +static void help(void)
> +{
> +	fprintf(stderr,
> +	"\nhelp:\n"
> +	"%s [-a <n>] -f <frequency> [-p <period>] [-m <modulation>] [-t] [-h]\n"
> +	"  -a: adapter index to use, (default 0)\n"
> +	"  -f: tuning frequency\n"
> +	"  -p: period in hours, (default 12)\n"
> +	"  -m: modulation ATSC vsb_8|vsb_16 (default vsb_8)\n"
> +	"  -t: enable ETT to receive program details, if available\n"
> +	"  -h: display this message\n", program);
> +}
> +
> +static int close_frontend(struct dvbfe_handle *fe)
> +{
> +	if(NULL == fe) {
> +		fprintf(stderr, "%s(): NULL pointer detected\n", __FUNCTION__);
> +	}
> 
> 
> We don't emphasise much on kernel Coding style in the application
> suite, but nevertheless following a CodingStyle helps to improve the
> readability of the code involved therewith.
> 
> Please do use a space after the keyword, before and after the braces.
> if, for, while etc are keywords.
> 
> For a single line conditionality check, You can omit the brace,
> involves lesser typing and looks lesser noise in the code.
> 
> 
> +
> +	dvbfe_close(fe);
> +
> +	return 0;
> +}
> +
> +static int open_frontend(struct dvbfe_handle **fe)
> +{
> +	struct dvbfe_info fe_info;
> +
> +	if(NULL == (*fe = dvbfe_open(adapter, 0, 0))) {
> +		fprintf(stderr, "%s(): error calling dvbfe_open()\n",
> +			__FUNCTION__);
> +		return -1;
> +	}
> +	dvbfe_get_info(*fe, 0, &fe_info, DVBFE_INFO_QUERYTYPE_IMMEDIATE, 0);
> +	if(DVBFE_TYPE_ATSC != fe_info.type) {
> +		fprintf(stderr, "%s(): only ATSC frontend supported currently\n",
> +			__FUNCTION__);
> +		return -1;
> +	}
> +	fe_info.feparams.frequency = frequency;
> +	fe_info.feparams.inversion = DVBFE_INVERSION_AUTO;
> +	fe_info.feparams.u.atsc.modulation = DVBFE_ATSC_MOD_VSB_8;
> +	fprintf(stdout, "tuning to %d Hz, please wait...\n", frequency);
> +	if(dvbfe_set(*fe, &fe_info.feparams, TIMEOUT * 1000)) {
> +		fprintf(stderr, "%s(): cannot lock to %d Hz in %d seconds\n",
> +			__FUNCTION__, frequency, TIMEOUT);
> +		return -1;
> +	}
> +	fprintf(stdout, "tuner locked.\n");
> +
> +	return 0;
> +}
> +
> +#if ENABLE_RRT
> +/* this is untested as since this part of the library is broken */
> +static int parse_rrt(int dmxfd)
> +{
> +	const enum atsc_section_tag tag = stag_atsc_rating_region;
> +	struct atsc_rrt_section *rrt;
> +	struct atsc_text *region_name;
> +	struct atsc_text_string *atsc_str;
> +	int i, j, ret;
> +
> +	i = 0;
> +	fprintf(stdout, "waiting for RRT: ");
> +	fflush(stdout);
> +	while(i < RRT_TIMEOUT) {
> +		ret = atsc_scan_table(dmxfd, ATSC_BASE_PID, tag, (void **)&rrt);
> +		if(0 > ret) {
> +			fprintf(stderr, "%s(): error calling atsc_scan_table()\n",
> +				__FUNCTION__);
> +			return -1;
> +		}
> +		if(0 == ret) {
> +			if(RRT_TIMEOUT > i) {
> +				fprintf(stdout, ".");
> +				fflush(stdout);
> +			} else {
> +				fprintf(stdout, "\nno RRT in %d seconds\n",
> +					RRT_TIMEOUT);
> +				return 0;
> +			}
> +			i += TIMEOUT;
> +		} else {
> +			fprintf(stdout, "\n");
> +			fflush(stdout);
> +			break;
> +		}
> +	}
> +
> +	region_name = atsc_rrt_section_rating_region_name_text(rrt);
> +	atsc_text_strings_for_each(region_name, atsc_str, i) {
> +		struct atsc_text_string_segment *seg;
> +
> +		atsc_text_string_segments_for_each(atsc_str, seg, j) {
> +			const char *c;
> +			int k;
> +			if(seg->mode < 0x3E) {
> +				fprintf(stderr, "%s(): text mode of 0x%02X "
> +					"not supported yet\n",
> +					__FUNCTION__, seg->mode);
> +				return -1;
> +			}
> +			c = (const char *)atsc_text_string_segment_bytes(seg);
> +			for(k = 0; k < seg->number_bytes; k++) {
> +				fprintf(stdout, "%c", c[k]);
> +			}
> +		}
> +	}
> +
> +	return 0;
> +}
> +#endif
> +
> +static int parse_stt(int dmxfd)
> +{
> +	const enum atsc_section_tag tag = stag_atsc_system_time;
> +	const struct atsc_stt_section *stt;
> +	time_t rx_time;
> +	time_t sys_time;
> +	int ret;
> +
> +	ret = atsc_scan_table(dmxfd, ATSC_BASE_PID, tag, (void **)&stt);
> +	if(0 > ret) {
> +		fprintf(stderr, "%s(): error calling atsc_scan_table()\n",
> +			__FUNCTION__);
> +		return -1;
> +	}
> +	if(0 == ret) {
> +		fprintf(stdout, "no STT in %d seconds\n", TIMEOUT);
> +		return 0;
> +	}
> +
> +	rx_time = atsctime_to_unixtime(stt->system_time);
> +	time(&sys_time);
> +	fprintf(stdout, "system time: %s", ctime(&sys_time));
> +	fprintf(stdout, "TS STT time: %s", ctime(&rx_time));
> +
> +	return 0;
> +}
> +
> +static int parse_tvct(int dmxfd)
> +{
> +	int num_sections;
> +	uint32_t section_pattern;
> +	const enum atsc_section_tag tag = stag_atsc_terrestrial_virtual_channel;
> +	struct atsc_tvct_section *tvct;
> +	struct atsc_tvct_channel *ch;
> +	struct atsc_channel_info *curr_info;
> +	int i, k, ret;
> +
> +	section_pattern = 0;
> +	num_sections = -1;
> +
> +	do {
> +		ret = atsc_scan_table(dmxfd, ATSC_BASE_PID, tag, (void **)&tvct);
> +		if(0 > ret) {
> +			fprintf(stderr, "%s(): error calling atsc_scan_table()\n",
> +			__FUNCTION__);
> +			return -1;
> +		}
> +		if(0 == ret) {
> +			fprintf(stdout, "no TVCT in %d seconds\n", TIMEOUT);
> +			return 0;
> +		}
> +
> +		if(-1 == num_sections) {
> +			num_sections = 1 + tvct->head.ext_head.last_section_number;
> +			if(32 < num_sections) {
> +				fprintf(stderr, "%s(): no support yet for "
> +					"tables having more than 32 sections\n",
> +					__FUNCTION__);
> +				return -1;
> +			}
> +		} else {
> +			if(num_sections !=
> +				1 + tvct->head.ext_head.last_section_number) {
> +				fprintf(stderr,
> +					"%s(): last section number does not match\n",
> +					__FUNCTION__);
> +				return -1;
> +			}
> +		}
> +		if(section_pattern & (1 << tvct->head.ext_head.section_number)) {
> +			continue;
> +		}
> +		section_pattern |= 1 << tvct->head.ext_head.section_number;
> +
> +		if(MAX_NUM_CHANNELS < guide.num_channels +
> +			tvct->num_channels_in_section) {
> +			fprintf(stderr, "%s(): no support for more than %d "
> +				"virtual channels in a pyhsical channel\n",
> +				__FUNCTION__, MAX_NUM_CHANNELS);
> +			return -1;
> +		}
> +		curr_info = &guide.ch[guide.num_channels];
> +		guide.num_channels += tvct->num_channels_in_section;
> +
> +	atsc_tvct_section_channels_for_each(tvct, ch, i) {
> +		/* initialize the curr_info structure */
> +		/* each EIT covers 3 hours */
> +		curr_info->num_eits = (period / 3) + !!(period % 3);
> +		while (curr_info->num_eits &&
> +			(0xFFFF == guide.eit_pid[curr_info->num_eits - 1])) {
> +			curr_info->num_eits -= 1;
> +		}
> +		if(curr_info->eit) {
> +			fprintf(stderr, "%s(): non-NULL pointer detected "
> +				"during initialization", __FUNCTION__);
> +			return -1;
> +		}
> +		if(NULL == (curr_info->eit = calloc(curr_info->num_eits,
> +			sizeof(struct atsc_eit_info)))) {
> +			fprintf(stderr, "%s(): error calling calloc()\n",
> +				__FUNCTION__);
> +			return -1;
> +		}
> +		if(NULL == (curr_info->title_buf.string = calloc(TITLE_BUFFER_LEN,
> +			sizeof(char)))) {
> +			fprintf(stderr, "%s(): error calling calloc()\n",
> +				__FUNCTION__);
> +			return -1;
> +		}
> +		curr_info->title_buf.buf_len = TITLE_BUFFER_LEN;
> +		curr_info->title_buf.buf_pos = 0;
> +
> +		if(NULL == (curr_info->msg_buf.string = calloc(MESSAGE_BUFFER_LEN,
> +			sizeof(char)))) {
> +			fprintf(stderr, "%s(): error calling calloc()\n",
> +				__FUNCTION__);
> +			return -1;
> +		}
> +		curr_info->msg_buf.buf_len = MESSAGE_BUFFER_LEN;
> +		curr_info->msg_buf.buf_pos = 0;
> +
> +		for(k = 0; k < 7; k++) {
> +			curr_info->short_name[k] =
> +				get_bits((const uint8_t *)ch->short_name,
> +				k * 16, 16);
> +		}
> +		curr_info->service_type = ch->service_type;
> +		curr_info->major_num = ch->major_channel_number;
> +		curr_info->minor_num = ch->minor_channel_number;
> +		curr_info->tsid = ch->channel_TSID;
> +		curr_info->prog_num = ch->program_number;
> +		curr_info->src_id = ch->source_id;
> +		curr_info++;
> +		}
> +	} while(section_pattern != (uint32_t)((1 << num_sections) - 1));
> +
> +	return 0;
> +}
> +
> +static int match_event(struct atsc_eit_info *eit, uint16_t event_id,
> +	struct atsc_event_info **event, uint8_t *curr_index)
> +{
> +	int j, k;
> +	struct atsc_eit_section_info *section;
> +
> +	if(NULL == eit || NULL == event || NULL == curr_index) {
> +		fprintf(stderr, "%s(): NULL pointer detected\n", __FUNCTION__);
> +		return -1;
> +	}
> +
> +	for(j = 0; j < eit->num_eit_sections; j++) {
> +		section = &eit->section[j];
> +
> +		for(k = 0; k < section->num_events; k++) {
> +			if(section->events[k] && section->events[k]->id ==
> +				event_id) {
> +				*event = section->events[k];
> +				break;
> +			}
> +		}
> +		if(*event) {
> +			*curr_index = j;
> +			break;
> +		}
> +	}
> +
> +	return 0;
> +}
> +
> +static int parse_message(struct atsc_channel_info *channel,
> +	struct atsc_ett_section *ett, struct atsc_event_info *event)
> +{
> +	int i, j;
> +	struct atsc_text *text;
> +	struct atsc_text_string *str;
> +
> +	if(NULL == ett || NULL == event || NULL == channel) {
> +		fprintf(stderr, "%s(): NULL pointer detected\n", __FUNCTION__);
> +		return -1;
> +	}
> +
> +	text = atsc_ett_section_extended_text_message(ett);
> +	atsc_text_strings_for_each(text, str, i) {
> +		struct atsc_text_string_segment *seg;
> +
> +		atsc_text_string_segments_for_each(str, seg, j) {
> +			event->msg_pos = channel->msg_buf.buf_pos;
> +			if(0 > atsc_text_segment_decode(seg,
> +				(uint8_t **)&channel->msg_buf.string,
> +				(size_t *)&channel->msg_buf.buf_len,
> +				(size_t *)&channel->msg_buf.buf_pos)) {
> +				fprintf(stderr, "%s(): error calling "
> +					"atsc_text_segment_decode()\n",
> +					__FUNCTION__);
> +				return -1;
> +			}
> +			event->msg_len = 1 + channel->msg_buf.buf_pos -
> +				event->msg_pos;
> +		}
> +	}
> +
> +	return 0;
> +}
> +
> +static int parse_ett(int dmxfd, int index, uint16_t pid)
> +{
> +	uint8_t curr_index;
> +	uint32_t section_pattern;
> +	const enum atsc_section_tag tag = stag_atsc_extended_text;
> +	struct atsc_eit_info *eit;
> +	struct atsc_ett_section *ett;
> +	struct atsc_channel_info *channel;
> +	struct atsc_event_info *event;
> +	struct atsc_eit_section_info *section;
> +	uint16_t source_id, event_id;
> +	int c, ret;
> +
> +	if(0xFFFF == guide.ett_pid[index]) {
> +		return 0;
> +	}
> +
> +	for(c = 0; c < guide.num_channels; c++) {
> +		channel = &guide.ch[c];
> +		eit = &channel->eit[index];
> +
> +		section_pattern = 0;
> +		while(section_pattern !=
> +			(uint32_t)((1 << eit->num_eit_sections) - 1)) {
> +			if(ctrl_c) {
> +				return 0;
> +			}
> +			ret = atsc_scan_table(dmxfd, pid, tag, (void **)&ett);
> +			fprintf(stdout, ".");
> +			fflush(stdout);
> +			if(0 > ret) {
> +				fprintf(stderr, "%s(): error calling "
> +					"atsc_scan_table()\n", __FUNCTION__);
> +				return -1;
> +			}
> +			if(0 == ret) {
> +				fprintf(stdout, "no ETT %d in %d seconds\n",
> +					index, TIMEOUT);
> +				return 0;
> +			}
> +
> +			source_id = ett->ETM_source_id;
> +			event_id = ett->ETM_sub_id;
> +			if(source_id != channel->src_id) {
> +				continue;
> +			}
> +
> +			event = NULL;
> +			if(match_event(eit, event_id, &event, &curr_index)) {
> +				fprintf(stderr, "%s(): error calling "
> +					"match_event()\n", __FUNCTION__);
> +				return -1;
> +			}
> +			if(NULL == event) {
> +				continue;
> +			}
> +			if(section_pattern & (1 << curr_index)) {
> +				/* the section has been filled, so skip,
> +				 * not consider version yet
> +				 */
> +				continue;
> +			}
> +			if(event->msg_len) {
> +				/* the message has been filled */
> +				continue;
> +			}
> +
> +			if(parse_message(channel, ett, event)) {
> +				fprintf(stderr, "%s(): error calling "
> +					"parse_message()\n", __FUNCTION__);
> +				return -1;
> +			}
> +			section = &eit->section[curr_index];
> +			if(++section->num_received_etms == section->num_etms) {
> +				section_pattern |= 1 << curr_index;
> +			}
> +		}
> +	}
> +
> +	return 0;
> +}
> +
> +static int parse_events(struct atsc_channel_info *curr_info,
> +	struct atsc_eit_section *eit, struct atsc_eit_section_info *section)
> +{
> +	int i, j, k;
> +	struct atsc_eit_event *e;
> +	time_t start_time, end_time;
> +
> +	if(NULL == curr_info || NULL == eit) {
> +		fprintf(stderr, "%s(): NULL pointer detected\n", __FUNCTION__);
> +		return -1;
> +	}
> +
> +	atsc_eit_section_events_for_each(eit, e, i) {
> +		struct atsc_text *title;
> +		struct atsc_text_string *str;
> +		struct atsc_event_info *e_info =
> +			&curr_info->e[curr_info->event_info_index];
> +
> +		if(0 == i && curr_info->last_event) {
> +			if(e->event_id == curr_info->last_event->id) {
> +				section->events[i] = NULL;
> +				/* skip if it's the same event spanning
> +				 * over sections
> +				 */
> +				continue;
> +			}
> +		}
> +		curr_info->event_info_index += 1;
> +		section->events[i] = e_info;
> +		e_info->id = e->event_id;
> +		start_time = atsctime_to_unixtime(e->start_time);
> +		end_time = start_time + e->length_in_seconds;
> +		localtime_r(&start_time, &e_info->start);
> +		localtime_r(&end_time, &e_info->end);
> +		if(0 != e->ETM_location && 3 != e->ETM_location) {
> +			/* FIXME assume 1 and 2 is interchangable as of now */
> +			section->num_etms++;
> +		}
> +
> +		title = atsc_eit_event_name_title_text(e);
> +		atsc_text_strings_for_each(title, str, j) {
> +			struct atsc_text_string_segment *seg;
> +
> +			atsc_text_string_segments_for_each(str, seg, k) {
> +				e_info->title_pos = curr_info->title_buf.buf_pos;
> +				if(0 > atsc_text_segment_decode(seg,
> +					(uint8_t **)&curr_info->title_buf.string,
> +					(size_t *)&curr_info->title_buf.buf_len,
> +					(size_t *)&curr_info->title_buf.buf_pos)) {
> +					fprintf(stderr, "%s(): error calling "
> +						"atsc_text_segment_decode()\n",
> +						__FUNCTION__);
> 
> 
> 
> Please don't wrap lines like this. It makes the code readability very
> bad. There is not much of a restriction to limit the no. of cols to
> 80, though at some points of times that helps in some ways.
> 
> Here but it really shows out that the wrapping to 80 cols makes it
> really bad. A very good example.
> 
> 
> +					return -1;
> +				}
> +				e_info->title_len = curr_info->title_buf.buf_pos -
> +					e_info->title_pos + 1;
> +			}
> +		}
> +	}
> +
> +	return 0;
> +}
> +
> +static int parse_eit(int dmxfd, int index, uint16_t pid)
> +{
> +	int num_sections;
> +	uint8_t section_num;
> +	uint8_t curr_channel_index;
> +	uint32_t section_pattern;
> +	const enum atsc_section_tag tag = stag_atsc_event_information;
> +	struct atsc_eit_section *eit;
> +	struct atsc_channel_info *curr_info;
> +	struct atsc_eit_info *eit_info;
> +	struct atsc_eit_section_info *section;
> +	uint16_t source_id;
> +	uint32_t eit_instance_pattern = 0;
> +	int i, k, ret;
> +
> +	while(eit_instance_pattern !=
> +		(uint32_t)((1 << guide.num_channels) - 1)) {
> +		source_id = 0xFFFF;
> +		section_pattern = 0;
> +		num_sections = -1;
> +
> +		do {
> +			ret = atsc_scan_table(dmxfd, pid, tag, (void **)&eit);
> +			fprintf(stdout, ".");
> +			fflush(stdout);
> +			if(0 > ret) {
> +				fprintf(stderr, "%s(): error calling "
> +					"atsc_scan_table()\n", __FUNCTION__);
> +				return -1;
> +			}
> +			if(0 == ret) {
> +				fprintf(stdout, "no EIT %d in %d seconds\n",
> +					index, TIMEOUT);
> +				return 0;
> +			}
> +
> +			if(0xFFFF == source_id) {
> +			source_id = atsc_eit_section_source_id(eit);
> +			for(k = 0; k < guide.num_channels; k++) {
> +				if(source_id == guide.ch[k].src_id) {
> +					curr_info = &guide.ch[k];
> +					curr_channel_index = k;
> +					if(0 == index) {
> +						curr_info->last_event = NULL;
> +					}
> +					break;
> +				}
> +			}
> +			if(k == guide.num_channels) {
> +				fprintf(stderr, "%s(): cannot find source_id "
> +					"0x%04X in the EIT\n",
> +					__FUNCTION__, source_id);
> +				return -1;
> +			}
> +			} else {
> +				if(source_id !=
> +					atsc_eit_section_source_id(eit)) {
> +					continue;
> +				}
> +			}
> +			if(eit_instance_pattern & (1 << curr_channel_index)) {
> +				/* we have received this instance,
> +				 * so quit quick
> +				 */
> +				break;
> +			}
> +
> +			if(-1 == num_sections) {
> +				num_sections = 1 +
> +					eit->head.ext_head.last_section_number;
> +				if(32 < num_sections) {
> +					fprintf(stderr,
> +						"%s(): no support yet for "
> +						"tables having more than "
> +						"32 sections\n", __FUNCTION__);
> +					return -1;
> +				}
> +			} else {
> +				if(num_sections != 1 +
> +					eit->head.ext_head.last_section_number) {
> +					fprintf(stderr,
> +						"%s(): last section number "
> +						"does not match\n",
> +						__FUNCTION__);
> +					return -1;
> +				}
> +			}
> +			if(section_pattern &
> +				(1 << eit->head.ext_head.section_number)) {
> +				continue;
> +			}
> +			section_pattern |= 1 << eit->head.ext_head.section_number;
> +
> +			eit_info = &curr_info->eit[index];
> +			if(NULL == (eit_info->section =
> +				realloc(eit_info->section,
> +				(eit_info->num_eit_sections + 1) *
> +				sizeof(struct atsc_eit_section_info)))) {
> +				fprintf(stderr,
> +					"%s(): error calling realloc()\n",
> +					__FUNCTION__);
> +				return -1;
> +			}
> +			section_num = eit->head.ext_head.section_number;
> +			if(0 == eit_info->num_eit_sections) {
> +				eit_info->num_eit_sections = 1;
> +				section = eit_info->section;
> +			} else {
> +				/* have to sort it into section order
> +				 * (temporal order)
> +				 */
> +				for(i = 0; i < eit_info->num_eit_sections; i++) {
> +					if(eit_info->section[i].section_num >
> +						section_num) {
> +						break;
> +					}
> +				}
> +				memmove(&eit_info->section[i + 1],
> +					&eit_info->section[i],
> +					(eit_info->num_eit_sections - i) *
> +					sizeof(struct atsc_eit_section_info));
> +				section = &eit_info->section[i - 1];
> +				section = &eit_info->section[i];
> +				eit_info->num_eit_sections += 1;
> +			}
> +
> +			section->section_num = section_num;
> +			section->num_events = eit->num_events_in_section;
> +			section->num_etms = 0;
> +			section->num_received_etms = 0;
> +			if(NULL == (section->events = calloc(section->num_events,
> +				sizeof(struct atsc_event_info *)))) {
> +				fprintf(stderr, "%s(): error calling calloc()\n",
> +					__FUNCTION__);
> +				return -1;
> +			}
> +			if(parse_events(curr_info, eit, section)) {
> +				fprintf(stderr, "%s(): error calling "
> +					"parse_events()\n", __FUNCTION__);
> +				return -1;
> +			}
> +		} while(section_pattern != (uint32_t)((1 << num_sections) - 1));
> +		eit_instance_pattern |= 1 << curr_channel_index;
> +	}
> +
> +	for(i = 0; i < guide.num_channels; i++) {
> +		struct atsc_channel_info *channel = &guide.ch[i];
> +		struct atsc_eit_info *ei = &channel->eit[index];
> +		struct atsc_eit_section_info *s;
> +
> +		if(0 == ei->num_eit_sections) {
> +			channel->last_event = NULL;
> +			continue;
> +		}
> +		s = &ei->section[ei->num_eit_sections - 1];
> +		/* BUG: it's incorrect when last section has no event */
> +		if(0 == s->num_events) {
> +			channel->last_event = NULL;
> +			continue;
> +		}
> +		channel->last_event = s->events[s->num_events - 1];
> +	}
> +
> +	return 0;
> +}
> +
> +static int parse_mgt(int dmxfd)
> +{
> +	const enum atsc_section_tag tag = stag_atsc_master_guide;
> +	struct atsc_mgt_section *mgt;
> +	struct atsc_mgt_table *t;
> +	int i, j, ret;
> +
> +	ret = atsc_scan_table(dmxfd, ATSC_BASE_PID, tag, (void **)&mgt);
> +	if(0 > ret) {
> +		fprintf(stderr, "%s(): error calling atsc_scan_table()\n",
> +			__FUNCTION__);
> +		return -1;
> +	}
> +	if(0 == ret) {
> +		fprintf(stdout, "no MGT in %d seconds\n", TIMEOUT);
> +		return 0;
> +	}
> +
> +	fprintf(stdout, "MGT table:\n");
> +	atsc_mgt_section_tables_for_each(mgt, t, i) {
> +		struct mgt_table_name table;
> +
> +	for(j = 0; j < (int)(sizeof(mgt_tab_name_array) /
> +		sizeof(struct mgt_table_name)); j++) {
> +		if(t->table_type > mgt_tab_name_array[j].range) {
> +			continue;
> +		}
> +		table = mgt_tab_name_array[j];
> +		if(0 == j || mgt_tab_name_array[j - 1].range + 1 ==
> +			mgt_tab_name_array[j].range) {
> +			j = -1;
> +		} else {
> +			j = t->table_type - mgt_tab_name_array[j - 1].range - 1;
> +			if(0x017F == table.range) {
> +				guide.eit_pid[j] = t->table_type_PID;
> +			} else if (0x027F == table.range) {
> +				guide.ett_pid[j] = t->table_type_PID;
> +			}
> +		}
> +		break;
> +	}
> +
> +		fprintf(stdout, "  %2d: type = 0x%04X, PID = 0x%04X, %s", i,
> +		    t->table_type, t->table_type_PID, table.string);
> +		if(-1 != j) {
> +		    fprintf(stdout, " %d", j);
> +		}
> +		fprintf(stdout, "\n");
> +	}
> +
> +	return 0;
> +}
> +
> +static int cleanup_guide(void)
> +{
> +	int i, j, k;
> +
> +	for(i = 0; i < guide.num_channels; i++) {
> +		struct atsc_channel_info *channel = &guide.ch[i];
> +
> +		if(channel->title_buf.string) {
> +			free(channel->title_buf.string);
> +		}
> +		if(channel->msg_buf.string) {
> +			free(channel->msg_buf.string);
> +		}
> +		for(j = 0; j < channel->num_eits; j++) {
> +			struct atsc_eit_info *eit = &channel->eit[j];
> +
> +			for(k = 0; k < eit->num_eit_sections; k++) {
> +				struct atsc_eit_section_info *section =
> +					&eit->section[k];
> +				if(section->num_events) {
> +					free(section->events);
> +				}
> +			}
> +			if(k) {
> +				free(eit->section);
> +			}
> +		}
> +		if(j) {
> +			free(channel->eit);
> +		}
> +	}
> +
> +	return 0;
> +}
> +
> +static int print_events(struct atsc_channel_info *channel,
> +	struct atsc_eit_section_info *section)
> +{
> +	int m;
> +	char line[256];
> +
> +	if(NULL == section) {
> +		fprintf(stderr, "%s(): NULL pointer detected", __FUNCTION__);
> +		return -1;
> +	}
> +	for(m = 0; m < section->num_events; m++) {
> +		struct atsc_event_info *event =
> +			section->events[m];
> +
> +		if(NULL == event) {
> +			continue;
> +		}
> +		fprintf(stdout, "|%02d:%02d--%02d:%02d| ",
> +			event->start.tm_hour, event->start.tm_min,
> +			event->end.tm_hour, event->end.tm_min);
> +		snprintf(line, event->title_len, "%s",
> +			&channel->title_buf.string[event->title_pos]);
> +		line[event->title_len] = '\0';
> +		fprintf(stdout, "%s\n", line);
> +		if(event->msg_len) {
> +			int len = event->msg_len;
> +			int pos = event->msg_pos;
> +			size_t part;
> +
> +			do {
> +				part = len > 255 ? 255 : len;
> +				snprintf(line, part, "%s",
> +					&channel->msg_buf.string[pos]);
> +				line[part] = '\0';
> +				fprintf(stdout, "%s", line);
> +				len -= part;
> +				pos += part;
> +			} while(0 < len);
> +			fprintf(stdout, "\n");
> +		}
> +	}
> +	return 0;
> +}
> +
> +static int print_guide(void)
> +{
> +	int i, j, k;
> +
> +	fprintf(stdout, "%s\n", separator);
> +	for(i = 0; i < guide.num_channels; i++) {
> +		struct atsc_channel_info *channel = &guide.ch[i];
> +
> +		fprintf(stdout, "%d.%d  %s\n", channel->major_num,
> +			channel->minor_num, channel->short_name);
> +		for(j = 0; j < channel->num_eits; j++) {
> +			struct atsc_eit_info *eit = &channel->eit[j];
> +
> +			for(k = 0; k < eit->num_eit_sections; k++) {
> +				struct atsc_eit_section_info *section =
> +					&eit->section[k];
> +				if(print_events(channel, section)) {
> +					fprintf(stderr, "%s(): error calling "
> +						"print_events()\n", __FUNCTION__);
> +					return -1;
> +				}
> +			}
> +		}
> +		fprintf(stdout, "%s\n", separator);
> +	}
> +
> +	return 0;
> +}
> +
> +static int open_demux(int *dmxfd)
> +{
> +	if((*dmxfd = dvbdemux_open_demux(adapter, 0, 0)) < 0) {
> +		fprintf(stderr, "%s(): error calling dvbdemux_open_demux()\n",
> +			__FUNCTION__);
> +		return -1;
> +	}
> +	return 0;
> +}
> +
> +static int close_demux(int dmxfd)
> +{
> +	if(dvbdemux_stop(dmxfd)) {
> +		fprintf(stderr, "%s(): error calling dvbdemux_stop()\n",
> +			__FUNCTION__);
> +		return -1;
> +	}
> +	return 0;
> +}
> +
> +/* used other utilities as template and generalized here */
> +static int atsc_scan_table(int dmxfd, uint16_t pid, enum atsc_section_tag tag,
> +	void **table_section)
> +{
> +	uint8_t filter[18];
> +	uint8_t mask[18];
> +	unsigned char sibuf[4096];
> +	int size;
> +	int ret;
> +	struct pollfd pollfd;
> +	struct section *section;
> +	struct section_ext *section_ext;
> +	struct atsc_section_psip *psip;
> +
> +	/* create a section filter for the table */
> +	memset(filter, 0, sizeof(filter));
> +	memset(mask, 0, sizeof(mask));
> +	filter[0] = tag;
> +	mask[0] = 0xFF;
> +	if(dvbdemux_set_section_filter(dmxfd, pid, filter, mask, 1, 1)) {
> +		fprintf(stderr, "%s(): error calling atsc_scan_table()\n",
> +			__FUNCTION__);
> +		return -1;
> +	}
> +
> +	/* poll for data */
> +	pollfd.fd = dmxfd;
> +	pollfd.events = POLLIN | POLLERR |POLLPRI;
> +	if((ret = poll(&pollfd, 1, TIMEOUT * 1000)) < 0) {
> +		if(ctrl_c) {
> +			return 0;
> +		}
> +		fprintf(stderr, "%s(): error calling poll()\n", __FUNCTION__);
> +		return -1;
> +	}
> +
> +	if(0 == ret) {
> +		return 0;
> +	}
> +
> +	/* read it */
> +	if((size = read(dmxfd, sibuf, sizeof(sibuf))) < 0) {
> +		fprintf(stderr, "%s(): error calling read()\n", __FUNCTION__);
> +		return -1;
> +	}
> +
> +	/* parse section */
> +	section = section_codec(sibuf, size);
> +	if(NULL == section) {
> +		fprintf(stderr, "%s(): error calling section_codec()\n",
> +			__FUNCTION__);
> +		return -1;
> +	}
> +
> +	section_ext = section_ext_decode(section, 0);
> +	if(NULL == section_ext) {
> +		fprintf(stderr, "%s(): error calling section_ext_decode()\n",
> +			__FUNCTION__);
> +		return -1;
> +	}
> +
> +	psip = atsc_section_psip_decode(section_ext);
> +	if(NULL == psip) {
> +		fprintf(stderr,
> +			"%s(): error calling atsc_section_psip_decode()\n",
> +			__FUNCTION__);
> +		return -1;
> +	}
> +
> +	*table_section = table_callback[tag & 0x0F](psip);
> +	if(NULL == *table_section) {
> +		fprintf(stderr, "%s(): error decode table section\n",
> +			__FUNCTION__);
> +		return -1;
> +	}
> +
> +	return 1;
> +}
> +
> +int main(int argc, char *argv[])
> +{
> +	int i, dmxfd;
> +	struct dvbfe_handle *fe;
> +
> +	program = argv[0];
> +
> +	if(1 == argc) {
> +		usage();
> +		exit(-1);
> +	}
> +
> +	for( ; ; ) {
> +		char c;
> +
> +		if(-1 == (c = getopt(argc, argv, "a:f:p:m:th"))) {
> +			break;
> +		}
> +
> +		switch(c) {
> +		case 'a':
> +			adapter = strtoll(optarg, NULL, 0);
> +			break;
> +
> +		case 'f':
> +			frequency = strtol(optarg, NULL, 0);
> +			break;
> +
> +		case 'p':
> +			period = strtol(optarg, NULL, 0);
> +			/* each table covers 3 hours */
> +			if((3 * MAX_NUM_EVENT_TABLES) < period) {
> +				period = 3 * MAX_NUM_EVENT_TABLES;
> +			}
> +			break;
> +
> +		case 'm':
> +			/* just stub, so far ATSC only has VSB_8 */
> +			modulation = optarg;
> +			break;
> +
> +		case 't':
> +			enable_ett = 1;
> +			break;
> +
> +		case 'h':
> +			help();
> +			exit(0);
> +
> +		default:
> +			usage();
> +			exit(-1);
> +		}
> +	}
> +
> +	memset(separator, '-', sizeof(separator));
> +	separator[79] = '\0';
> +	memset(&guide, 0, sizeof(struct atsc_virtual_channels_info));
> +	memset(guide.eit_pid, 0xFF, MAX_NUM_EVENT_TABLES * sizeof(uint16_t));
> +	memset(guide.ett_pid, 0xFF, MAX_NUM_EVENT_TABLES * sizeof(uint16_t));
> +
> +	if(open_frontend(&fe)) {
> +		fprintf(stderr, "%s(): error calling open_frontend()\n",
> +			__FUNCTION__);
> +		return -1;
> +	}
> +
> +	if(open_demux(&dmxfd)) {
> +		fprintf(stderr, "%s(): error calling open_demux()\n",
> +			__FUNCTION__);
> +		return -1;
> +	}
> +
> +	if(parse_stt(dmxfd)) {
> +		fprintf(stderr, "%s(): error calling parse_stt()\n",
> +			__FUNCTION__);
> +		return -1;
> +	}
> +
> +	if(parse_mgt(dmxfd)) {
> +		fprintf(stderr, "%s(): error calling parse_mgt()\n",
> +			__FUNCTION__);
> +		return -1;
> +	}
> +
> +	if(parse_tvct(dmxfd)) {
> +		fprintf(stderr, "%s(): error calling parse_tvct()\n",
> +			__FUNCTION__);
> +		return -1;
> +	}
> +
> +#ifdef ENABLE_RRT
> +	if(parse_rrt(dmxfd)) {
> +		fprintf(stderr, "%s(): error calling parse_rrt()\n",
> +			__FUNCTION__);
> +		return -1;
> +	}
> +#endif
> +
> +	fprintf(stdout, "receiving EIT ");
> +	for(i = 0; i < guide.ch[0].num_eits; i++) {
> +		if(parse_eit(dmxfd, i, guide.eit_pid[i])) {
> +			fprintf(stderr, "%s(): error calling parse_eit()\n",
> +				__FUNCTION__);
> +			return -1;
> +		}
> +	}
> +	fprintf(stdout, "\n");
> +
> +	old_handler = signal(SIGINT, int_handler);
> +	if(enable_ett) {
> +		fprintf(stdout, "receiving ETT ");
> +		for(i = 0; i < guide.ch[0].num_eits; i++) {
> +			if(0xFFFF != guide.ett_pid[i]) {
> +				if(parse_ett(dmxfd, i, guide.ett_pid[i])) {
> +					fprintf(stderr, "%s(): error calling "
> +						"parse_eit()\n", __FUNCTION__);
> +					return -1;
> +				}
> +			}
> +			if(ctrl_c) {
> +				break;
> +			}
> +		}
> +		fprintf(stdout, "\n");
> +	}
> +	signal(SIGINT, old_handler);
> +
> +	if(print_guide()) {
> +		fprintf(stderr, "%s(): error calling print_guide()\n",
> +			__FUNCTION__);
> +		return -1;
> +	}
> +
> +	if(cleanup_guide()) {
> +		fprintf(stderr, "%s(): error calling cleanup_guide()\n",
> +			__FUNCTION__);
> +		return -1;
> +	}
> +
> +	if(close_demux(dmxfd)) {
> +		fprintf(stderr, "%s(): error calling close_demux()\n",
> +			__FUNCTION__);
> +		return -1;
> +	}
> +
> +	if(close_frontend(fe)) {
> +		fprintf(stderr, "%s(): error calling close_demux()\n",
> +			__FUNCTION__);
> +		return -1;
> +	}
> +
> +	return 0;
> +}
> diff -uprN dvb-apps/util/atsc_epg/Makefile dvb-apps_new/util/atsc_epg/Makefile
> --- dvb-apps/util/atsc_epg/Makefile	1969-12-31 18:00:00.000000000 -0600
> +++ dvb-apps_new/util/atsc_epg/Makefile	2009-06-18 20:11:58.362985962 -0500
> @@ -0,0 +1,16 @@
> +# Makefile for linuxtv.org dvb-apps/util/atsc_epg
> +
> +binaries = atsc_epg
> +
> +inst_bin = $(binaries)
> +
> +CPPFLAGS += -I../../lib -std=c99 -D_POSIX_SOURCE
> +#LDFLAGS  += -static -L../../lib/libdvbapi -L../../lib/libucsi
> +LDFLAGS  += -L../../lib/libdvbapi -L../../lib/libucsi
> +LDLIBS   += -ldvbapi -lucsi
> +
> +.PHONY: all
> +
> +all: $(binaries)
> +
> +include ../../Make.rules
> diff -uprN dvb-apps/util/atsc_epg/README dvb-apps_new/util/atsc_epg/README
> --- dvb-apps/util/atsc_epg/README	1969-12-31 18:00:00.000000000 -0600
> +++ dvb-apps_new/util/atsc_epg/README	2009-06-18 20:33:47.836924378 -0500
> @@ -0,0 +1,12 @@
> +Hi there,
> +
> +atsc_epg is a small utility for obtaining information such as programs, EPG
> +(electronic program guide) from an ATSC channel.
> +
> +Pulling the detailed information, i.e., option '-t', may take fairly long
> +time, or never ending, which is a bug of the PSIP generator. Ctrl+C can be
> +used to abort and the received parts will be printed.
> +
> +Enjoy,
> +Yufei
> +
> diff -uprN dvb-apps/util/Makefile dvb-apps_new/util/Makefile
> --- dvb-apps/util/Makefile	2009-06-18 19:43:30.034986539 -0500
> +++ dvb-apps_new/util/Makefile	2009-06-18 20:11:41.169986806 -0500
> @@ -3,6 +3,7 @@
>  .PHONY: all clean install
> 
>  all clean install:
> +	$(MAKE) -C atsc_epg $@
>  	$(MAKE) -C av7110_loadkeys $@
>  	$(MAKE) -C dib3000-watch $@
>  	$(MAKE) -C dst-utils $@
> 
> 
> Regards,
> Manu


  reply	other threads:[~2009-06-20 13:36 UTC|newest]

Thread overview: 22+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-06-17 23:18 [Patch] New utility program atsc_epg added to dvb-apps utility suite Yufei Yuan
2009-06-17 23:51 ` hermann pitton
     [not found]   ` <ccdf9f470906171706gc36e43bq4e2092d948c1fbf5@mail.gmail.com>
     [not found]     ` <1245284055.8827.36.camel@pc07.localdom.local>
     [not found]       ` <ccdf9f470906171720i4076642dna483643c55a4a85f@mail.gmail.com>
2009-06-18  0:52         ` hermann pitton
     [not found]         ` <1245285015.10476.4.camel@pc07.localdom.local>
     [not found]           ` <ccdf9f470906171746k8e5ac37j9c0a48823f98ba87@mail.gmail.com>
2009-06-18  1:05             ` hermann pitton
2009-06-18  1:12               ` Yufei Yuan
2009-06-18  1:23                 ` hermann pitton
2009-06-18  8:32 ` Manu Abraham
2009-06-18  8:48   ` Manu Abraham
2009-06-18 13:06     ` Yufei Yuan
2009-06-19  0:52       ` Yufei Yuan
2009-06-19  1:39         ` Yufei Yuan
2009-06-20  0:41           ` hermann pitton
2009-06-20  1:00             ` Yufei Yuan
2009-06-20  1:28               ` hermann pitton
2009-06-20  2:38                 ` Yufei Yuan
2009-06-20  3:04                   ` hermann pitton
     [not found]           ` <ccdf9f470906181855m2d6c471cm12afea3f228fd57c@mail.gmail.com>
2009-06-20  7:30             ` Manu Abraham
2009-06-20 13:30               ` Yufei Yuan [this message]
2009-06-20 17:15               ` [Patch] dvb-apps: code cleanup and bug fix Yufei Yuan
2009-06-20 17:31                 ` Yufei Yuan
2009-06-22 23:43               ` [Patch] New utility program atsc_epg added to dvb-apps utility suite Yufei Yuan
2009-06-23  0:52                 ` hermann pitton

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1245504647.15347.3.camel@core2duo.localdomain \
    --to=yfyuan@gmail.com \
    --cc=abraham.manu@gmail.com \
    --cc=linux-media@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.