#!/usr/bin/perl -w
#05/2013, adam at siroky.sk

use strict;
use IO::Socket;
use Event;
use Net::OpenSoundControl::Client;
use Data::Dumper;

my $osc_server = shift;
my $osc_port = shift;
if(!$osc_server or !$osc_port){
	die("Usage: $0 <server> <port>\n");
}

my $lirc = IO::Socket->new(
	Domain => &AF_UNIX,
	Type => SOCK_STREAM,
	Peer => "/var/run/lirc/lircd"
) or die "Cannot open lirc socket\n";

my $osc = Net::OpenSoundControl::Client->new(
	Host => $osc_server,
	Port => $osc_port
) or die "Cannot start OSC client: $@\n";

#-------------------------------------------------------------------------------------------
# auxiliary functions which generate osc messages for Resolume, to be assigned to remote control buttons
# ------------------------------------------------------------------------------------------
sub play_loop_cont {
	my $clip = shift;
	my @ref = ( ["$clip/connect", 'i', 1],
		#play forward
		["$clip/video/position/direction", 'i', '1'],
		#loop (1 = forwards, backwards, ..)
		["$clip/video/position/playmode", 'i', '0'],
		#continuous
		["$clip/video/position/playmodeaway", 'i', '1']);
	return \@ref;
}

sub effect_on {
	my $ef_number = shift;
	my @ref = ( ["/composition/video/effect$ef_number/bypassed", 'i', '0']);
	return \@ref;
}

sub effect_off {
	my $ef_number = shift;
	my @ref = ( ["/composition/video/effect$ef_number/bypassed", 'i', '1']);
	return \@ref;
}


#-----------------------------------------------------------------------------------------
# REMOTES
# structure that contains the mapping of button press to OSC messages
# it's a hash of hashes of array reference:
# 	{ "name of remote control" => { "button" => \[ "osc msg1", "osc msg2", ... ] } }
#-----------------------------------------------------------------------------------------
my %ir2osc = (
	"g4-1-toshiba" => {
		"1" => play_loop_cont('/layer2/clip1'),
		"2" => play_loop_cont('/layer2/clip2'),
		"3" => play_loop_cont('/layer2/clip3'),
		"4" => play_loop_cont('/layer2/clip4'),
		"5" => play_loop_cont('/layer2/clip5'),
		"6" => play_loop_cont('/layer2/clip6'),
		"7" => play_loop_cont('/layer2/clip7'),
		"8" => play_loop_cont('/layer2/clip8'),
		"9" => play_loop_cont('/layer2/clip9'),
		"0" => play_loop_cont('/layer2/clip0'),
		"TEXT_i" => effect_on(1),
		"TEXT_IN" => effect_on(2),
		"TEXT_OUT" => effect_on(3),
		"I/II" => effect_on(4),
		"TIME" => effect_off(1),
		"TEXT_QUESTION" => effect_off(2),
		"TEXT_X" => effect_off(3),
		"SCREEN_++" => effect_off(4)
	},
	"g3-grundig" => {
		"1" => play_loop_cont('/layer2/clip1'),
		"2" => play_loop_cont('/layer2/clip2'),
		"3" => play_loop_cont('/layer2/clip3'),
		"4" => play_loop_cont('/layer2/clip4'),
		"5" => play_loop_cont('/layer2/clip5'),
		"6" => play_loop_cont('/layer2/clip6'),
		"7" => play_loop_cont('/layer2/clip7'),
		"8" => play_loop_cont('/layer2/clip8'),
		"9" => play_loop_cont('/layer2/clip9'),
		"0" => play_loop_cont('/layer2/clip0')
	},

	"g2-1-sencor-black" => {
		"1" => play_loop_cont('/layer3/clip1'),
		"2" => play_loop_cont('/layer3/clip2'),
		"3" => play_loop_cont('/layer3/clip3'),
		"4" => play_loop_cont('/layer3/clip4'),
		"5" => play_loop_cont('/layer3/clip5'),
		"6" => play_loop_cont('/layer3/clip6'),
		"7" => play_loop_cont('/layer3/clip7'),
		"8" => play_loop_cont('/layer3/clip8'),
		"9" => play_loop_cont('/layer3/clip9'),
		"0" => play_loop_cont('/layer3/clip0'),
		"EDIT" => effect_on(1),
		"M/P" => effect_on(2),
		"PAUSE" => effect_on(3),
		"P_UP" => effect_on(4),
		"FAV" => effect_off(1),
		"AUDIO" => effect_off(2),
		"AV" => effect_off(3),
		"P_DOWN" => effect_off(4)

	},
	"g1-1-black-magic" => {
		"1" => play_loop_cont('/layer3/clip1'),
		"2" => play_loop_cont('/layer3/clip2'),
		"3" => play_loop_cont('/layer3/clip3'),
		"4" => play_loop_cont('/layer3/clip4'),
		"5" => play_loop_cont('/layer3/clip5'),
		"6" => play_loop_cont('/layer3/clip6'),
		"7" => play_loop_cont('/layer3/clip7'),
		"8" => play_loop_cont('/layer3/clip8'),
		"9" => play_loop_cont('/layer3/clip9'),
		"0" => play_loop_cont('/layer3/clip0')
	}
);


#---------------------------------------------------------------------------------
# main callback
# --------------------------------------------------------------------------------
sub process {
	my ($event) = @_;
	my $parent_watcher = $event->w;

	my $line = <$lirc>;
	chomp($line);

	#this comes from lircd:
	# 000000000000100d 00 MUTE g1-1-black-magic
	# 000000000000100e 00 PP g1-1-black-magic
	
	$line =~ /^[0-9a-fA-F]+ ([0-9a-fA-F]+) ([^ ]+) ([^\s]+)/;
	#print "$1 $2\n";
	my $repeat = $1;
	my $key = $2;
	my $remote = $3;

	#holding a button -> no action
	return if($repeat ne "00");

	my $ref = $ir2osc{$remote}{$key};
	if($ref){
		foreach my $message (@$ref){
			#print Dumper($message);
			$osc->send($message);
		}
	}
}

# here we go - assign the callback (event handler) to the lircd socket
Event->io(
	fd => $lirc,
	cb => \&process
);

Event::loop;
