/*
    Copyright © 2005 Tyler Trafford <ttrafford@gmail.com>
    inspired by ptune.pl

    frequencies.{c,h} are © Nathan Laredo <laredo@broked.net>

    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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <asm/types.h>
#include <asm/fcntl.h>

#include <linux/videodev2.h>

#include <malloc.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>

#include "frequencies.h"
#include "cmdline.h"

int setfreq(char *device, int frequency);
int getfreqvalue(char *freqtable, char *channel);

int main(int argc, char *argv[])
{
	struct gengetopt_args_info opt;
	struct stat buf;
	FILE *fp = NULL;
	int i, j;
	
	char *homedir = getenv("HOME");
	char *config = (char*)malloc(strlen(homedir) + strlen("/.ivtv-tune") + 1);
	sprintf(config, "%s/.ivtv-tune", homedir);

	// create config file, if it doesn't already exist
	if (stat(config, &buf) != 0)
	{
		fp = fopen(config, "w");
		fprintf(fp, "device /dev/video0\nfreqtable us-cable\n");
		fclose(fp);
	}

	cmdline_parser(argc, argv, &opt);
	cmdline_parser_configfile(config, &opt, 0);

	// list all channels in current frequency table
	if (opt.list_channels_given && opt.freqtable_given)
	{
		printf("Channels for \'%s\':\n", opt.freqtable_arg);

		for (i = 0; (chanlists[i].name != NULL) && 
				strcmp(chanlists[i].name, opt.freqtable_arg) != 0; i++);

		for (j = 0; j < chanlists[i].count; j++)
		{
			printf("%s\t= %.3f MHz\n", chanlists[i].list[j].name,
					chanlists[i].list[j].freq/1000.0);
		}

		return 0;
	} 

	// list all available frequency tables
	if (opt.list_freqtable_given)
	{
		printf("Frequency Maps:\n");
		
		for (i = 0; chanlists[i].name != NULL; i++)
			printf("%s\n", chanlists[i].name);

		return 0;
	}

	// tune to user-supplied frequency
	if (opt.frequency_given && opt.device_given)
	{
		return setfreq(opt.device_arg, (int)(opt.frequency_arg*1000));
	}

	// tune to user-supplied channel
	if (opt.channel_given && opt.freqtable_given & opt.device_given)
	{
		i = getfreqvalue(opt.freqtable_arg, opt.channel_arg);

		if (!i)
		{
			printf("Invalid Channel for '%s'\n", opt.freqtable_arg);
			return 0;
		}
					
		return setfreq(opt.device_arg, i);
	}

	cmdline_parser_print_help();
	return 0;
}

int setfreq(char *device, int frequency)
{
	struct v4l2_frequency vf;
	int fd, result;

	if ((fd = open(device, O_RDWR)) < 0)
	{
		fprintf(stderr, "Failed to open %s\n", device);
		return 1;
	}

	vf.tuner = 0;
	vf.frequency = frequency;
	result = ioctl(fd, VIDIOC_S_FREQUENCY, &vf);
	close(fd);

	if (result < 0)
	{
		fprintf(stderr, "ioctl VIDIOC_S_FREQUENCY failed\n");
		return 1;
	}
	
	printf("%s: %.3f MHz\n", device, vf.frequency/1000.0);
	return 0;
}

int getfreqvalue(char *freqtable, char *channel)
{
	int i, j;

	for (i = 0; (chanlists[i].name != NULL) && 
			strcmp(chanlists[i].name, freqtable) != 0; i++);

	for (j = 0; (j < chanlists[i].count) &&
			strcmp(chanlists[i].list[j].name, channel) != 0; j++);

	if (j == chanlists[i].count)
		return 0;

	return chanlists[i].list[j].freq;
}
