/*
 * $Header: /cvsroot/bsdbktr_tvtune/bsdbktr_tvtune.c,v 1.6 2004/01/05 23:09:39 mina Exp $
 *
 * This is a commandline / console TV channel tuner for Brooktree-based TV capture cards
 * running under FreeBSD using the bktr driver
 *
 * It does not require any other utilities (fxtv/xawtv) and does NOT require XFree86
 *
 * Adapted from ftp://ftp.sohara.org/pub/bsdbktr_tvtune.c
 * By Mina Naguib <webmaster@topfx.com>
 * http://www.topfx.com
 * on January 4th, 2003
 *
 */

#define VERSION "0.02"

#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <machine/ioctl_meteor.h>
#include <machine/ioctl_bt848.h>

/*
 * CONFIGURATION *********************************************************
 */

/*
 * List of available channelsets (almost verbatim from machine/ioctl_bt848.h)
 */
struct {
	char *name;
	char *description;
	int value;
} AVAILABLE_CHANNELSETS[] = {
	{"NABCST",		"North American Broadcast",	CHNLSET_NABCST},
	{"CABLEIRC",	"Cable IRC",						CHNLSET_CABLEIRC},
	{"CABLEHRC",	"Cable HRC",						CHNLSET_CABLEHRC},
	{"WEUROPE",		"Western Europe",					CHNLSET_WEUROPE},
	{"JPNBCST",		"Japan Broadcast",				CHNLSET_JPNBCST},
	{"JPNCABLE",	"Japan Cable",						CHNLSET_JPNCABLE},
	{"XUSSR",		"Russia",							CHNLSET_XUSSR},
	{"AUSTRALIA",	"Australia",						CHNLSET_AUSTRALIA},
	{"FRANCE",		"France",							CHNLSET_FRANCE},
	{NULL, 			NULL,									0}
};


/*
 * Our defaults if commandline option not given
 */
#define DEFAULT_DEVICE "/dev/tuner0"
#define DEFAULT_CHANNELSET CHNLSET_NABCST

/*
 * END OF CONFIGURATION *********************************************************
 */

/*
 * Function prototypes
 */
void show_usage(char *programname);
void show_channelsets(void);

/*
 * Functions
 */
int main(int argc, char **argv) {
	char				*devicename = DEFAULT_DEVICE;
	unsigned int	channelset = DEFAULT_CHANNELSET;
	unsigned int	channel = 0;
	int				fd;
	int            opt;
	int            i;
	int            found;

	/*
	 * Parse options and override defaults if supplied
	 */
	if (argc <1) {
		show_usage("bsdbktr_tvtune");
	}
	while ((opt = getopt(argc, argv, "vhld:s:c:")) != -1) {
		switch (opt) {
			case 'd':
				devicename = optarg;
				break;
			case 's':
				i = 0;
				found = 0;
				while (AVAILABLE_CHANNELSETS[i].name) {
					if (strcmp(AVAILABLE_CHANNELSETS[i].name, optarg) == 0) {
						channelset = AVAILABLE_CHANNELSETS[i].value;
						found = 1;
						break;
					}
					i++;
				}
				if (!found) {
					perror("Invalid channelset (-s) - Check possible values with -l");
					exit(1);
				}
				break;
			case 'c':
				channel = atoi(optarg);
				break;
			case 'l':
				show_channelsets();
				break;
			case 'v':
				printf("bsdbktr_tvtune version %s, by Mina Naguib <webmaster@topfx.com> http://www.topfx.com\n", VERSION);
				exit(1);
				break;
			case '?':
				printf("\nUnknown command line argument\n");
			case 'h':
			default:
				show_usage(argv[0]);
		}
	}

	/*
	 * Some sanity checking
	 */
	if (channel <= 0) {
		printf("\nYou must supply which channel to tune to with the -c option\n");
		show_usage(argv[0]);
	}

	fd = open(devicename, O_RDWR);
	if (fd < 0) {
		perror(devicename);
		exit(1);
	}

	/*
	 * Now actually set the ioctls
	 */
	if (ioctl(fd, TVTUNER_SETTYPE, &channelset) < 0) {
		perror("Tuning (TVTUNER_SETTYPE) failed");
		exit(1);
	}

	if (ioctl(fd, TVTUNER_SETCHNL, &channel) < 0) {
		perror("Tuning (TVTUNER_SETCHNL) failed");
		exit(1);
	}

	close (fd);

	/*
	 * All is well. tuner should be set
	 */
	return(0);
}

/*
 * Shows propper utility usage then exits
 */
void show_usage(char *programname) {
	printf("\n"\
"\n"\
"Usage:\n"\
"	%s [-d TVTUNERDEVICE] [-s CHANNELSET] -c CHANNEL\n"\
"	%s -h\n"\
"	%s -l\n"\
"	%s -v\n"\
"\n"\
"Where:\n"\
"\n"\
"	-c\n"\
"		The channel to tune to\n"\
"\n"\
"	-d\n"\
"		The device to open for tuning.  If unspecified defaults to /dev/tuner0\n"\
"\n"\
"	-h\n"\
"		This help you're seeing\n"\
"\n"\
"	-l\n"\
"		List all valid CHANNELSETs you could pass to the -s option\n"\
"\n"\
"	-s\n"\
"		The channel set configuration to use.  If unspecified defaults to NABCST\n"\
"\n"\
"	-v\n"\
"		Show program version\n"\
"\n", programname, programname, programname, programname);
	exit(1);
}

/*
 * Shows all available channelsets then exits
 */
void show_channelsets(void) {
	int i;

	printf("\n\nAll available CHANNELSETs you could pass to the -s option:\n\n");
	i=0;
	while (AVAILABLE_CHANNELSETS[i].name) {
		printf("\t%s\n", AVAILABLE_CHANNELSETS[i].name);
		printf("\t\t%s\n", AVAILABLE_CHANNELSETS[i].description);
		printf("\n");
		i++;
	}
	exit(1);
}

