#!/usr/bin/perl
# $Id: changesource.pl,v 1.4 2005/07/02 08:46:10 bd Exp $
# Usage options:
#   --channel=FREQ      FREQ is the TV channel frequency in MHz (e.g. 599.25)
#   --video=[tv|rca]    "tv" for tuner, "rca" for composite video input
#   --audio=[tv|rca]    "tv" for tuner, "rca" for preamp line input (stereo)
#   --mode=[pal|ntsc]	"pal" for the PAL tuner (default), "ntsc" for NTSC

use Fcntl;
use Getopt::Long;

my ($CHAN,$VIDEO,$AUDIO,$MODE);
GetOptions('channel=s' => \$CHAN, 'video=s' => \$VIDEO, 'audio=s' => \$AUDIO, 'mode=s' => \$MODE);
$MODE = "pal" unless $MODE;
	   
my $fifo = "/tmp/usbreplay.fifo";
my @urblist = ();

if ($CHAN) {
    my $b = 0x30;
    my ($mhz,$val);
    if ($CHAN =~ m/^(\d+\.\d+)/) {
	$mhz = $1;
    } else {
	die "Unsupported channel specification";
    }
    if ($MODE eq "pal") {
	$val = int(622 + 16*$mhz + 0.5);
	if ($mhz < 464) { $b = 0x90; }
	push @urblist, [0x08, 0x61, 0x04, $val>>8, $val&0xff, 0xce,
			$b, 0x81, 0xaf, 0x55, 0x4f];
    } elsif ($MODE eq "ntsc") {
	$val = int(732 + 16*$mhz + 0.5);
	if ($mhz < 146) { $b = 0x01; }
	if ($mhz > 464) { $b = 0x04; }
	push @urblist, [0x08, 0x61, 0x04, 0xce, $b, $val>>8, $val&0xff,
			0x80, 0x70, 0xdc, 0x77];
    }
}

if ($VIDEO) {
    if ($VIDEO =~ m/^tv$/i) {
	push @urblist, [map {hex}
			qw(0c 21 02 02 02 84 09 53 80 3a e3 81 94 dc df 81
			   1c 63 4f 80 38 f5 7c f8 d0 c0 d9 ef 0a 00 00 00
			   75 86 53 80 00 00 00 00 20 12 df 81 00 00 00 00
			   e4 c0 d9 ef 38 f5 7c f8 d4 42 53 80 02 9d dd 81)];
    } elsif ($VIDEO =~ m/^(rca|composite)$/i) {
	push @urblist, [map {hex}
			qw(0c 21 02 02 02 85 09 56 cc 76 e2 81 80 30 4d ef
			   cc 76 e2 81 00 58 52 80 00 00 00 00 01 00 00 00
			   00 00 00 00 01 00 00 00 06 00 00 00 c4 30 4d ef
			   38 14 5a 80 08 f0 aa e1 00 00 00 00 f5 17 5a 80)];
    }
}

if ($AUDIO) {
    if ($AUDIO =~ m/^tv$/i) {
	push @urblist, [map {hex} qw(08 40 05 12 00 0a 01 20)];
    } elsif ($AUDIO =~ m/^rca$/i) {
	push @urblist, [map {hex} qw(08 40 05 12 00 13 0c 00)];
	push @urblist, [map {hex} qw(08 40 05 12 00 0a 02 20)];
    }
    # Trigger sound standard detection
    push @urblist, [map {hex} qw(08 40 05 10 00 20 00 01)];
}

eval {
    local $SIG{ALRM} = sub { die "alarm\n" };
    alarm(1);

    sysopen(FIFO, $fifo, O_WRONLY) or die "Couldn't open $fifo for writing: $!";
    foreach (@urblist) {
	my @urb = @$_;
	unshift @urb, 1;	# Number of bytes for usbreplay to read back after the write.
	my $urb = pack("C*", scalar(@urb), @urb);
	syswrite(FIFO, $urb);
    }
    syswrite(FIFO, pack("C", 0));	# End insertion sequence with a zero-length block.
    close(FIFO);

    alarm(0);
};
if ($@) {
    die unless $@ eq "alarm\n";
    print STDERR "** Did usbreplay die? Fifo write timed out...\n";
}

1;
