#!/usr/bin/perl
#
#########################
#load required modules
#########################
use lib "/MUSIC/bin";
use strict;
use Term::ReadKey;
use POSIX qw(setsid);
use oggrec;
#########################
# set variables
#########################
my $return_val;
my %key_map;
my $char;
my $rec_pid;
my $STATUS_FILE = "/MUSIC/status/music.pid";
# my $std_out = $ARGV[0];
#########################
# Set Key Map
#########################
$key_map{'r'} = "\&start_record();";
$key_map{'m'} = "\&start_record(\"mk\");";
$key_map{'s'} = "\&stop_record;";
$key_map{'p'} = "\&kill_child(my \$pid, 'STOP');";
$key_map{'c'} = "\&kill_child(my \$pid, 'CONT');";
$key_map{'x'} = "\&exit_routine;";
#########################
# Set up Signal catching
#########################
$SIG{CHLD} = \&REAPER;
$SIG{USR1} = \&CATCH_USR1;
$SIG{USR2} = \&CATCH_USR2;
#########################
# flush the buffer
#########################
$| = 1;
##########################
# daemonize the program
##########################
&daemonize;
##########################
# Set the terminal to read 1 char at a time
##########################
ReadMode('cbreak');
##########################
# our infinite loop
##########################
while(1) {
##########################
# Read a character, using:
# -1 -> non-blocking
# 0 -> blocking
# >0 -> timed
##########################
$char = ReadKey(0);
##########################
# If the character has been mapped, eval the mapping
##########################
if($key_map{$char}) {
$return_val = eval($key_map{$char});
print "return = $return_val\n";
print STDERR $@;
} else {
print "Key \"$char\" not assigned.\n";
}
print "-----------------------\n";
}
sub exit_routine {
if($rec_pid) {
&stop_record;
}
ReadMode('normal');
close(STAT);
exit(0);
}
sub start_record {
print "Starting Recording...\n";
##########################
# Return if rec_pid exists
##########################
if($rec_pid) {
print "Already recording...\n";
return(1);
}
##########################
# Fork
##########################
defined(my $pid = fork) or die "Can't fork: $!";
##########################
# Return if parent
##########################
if($pid) {
$rec_pid = $pid;
print "rec_pid = $rec_pid\n";
return;
}
##########################
# I'm the child
# Set Session ID so the parent can kill
# all of the children together
##########################
setsid;
print "I'm the Child - $$\n";
# print " args = @_\n";
# my $time = "0:10";
# my $conf = "";
oggrec::oggrec(@_);
}
#########################
# Stop recording
#########################
sub stop_record {
if($rec_pid) {
&kill_child($rec_pid, 'TERM');
$rec_pid = "";
} else {
print "Not recording...\n";
}
}
#########################
# Send a kill signal to the sub
# kill_child(PID, SIGNAL);
#########################
sub kill_child {
my $proc;
my $sig;
($proc, $sig) = @_;
print "Killing Child - $proc with $sig\n";
#########################
# When we fork, we use setsid so that we can kill a process group
# by killing the "negative" process group parent
#########################
kill($sig, -$proc);
}
#########################
# Forks and exits
#########################
sub daemonize {
$| = 1;
chdir '/' or die "Can't chdir to /: $!";
umask 0;
#########################
# Open and lock status file
#########################
my $PID = `cat $STATUS_FILE`;
if($PID>0) {
my $STAT = `ps -ef | grep -v grep | grep $PID`;
if($STAT) {
print "STAT=$STAT";
exit(1);
}
}
open(STAT,">$STATUS_FILE") or die "Can't open $STATUS_FILE: $!";
flock(STAT, "1") or die "Can't lock $STATUS_FILE: $!";
print STAT "$$";
close(STAT);
# open(STDIN,'/dev/$std_out') or die "Can't read /dev/$std_out $!";
# open(STDOUT,'>/dev/$std_out') or die "Can't write /dev/$std_out $!";
# open(STDERR,'>/dev/$std_out') or die "Can't write /dev/$std_out $!";
# defined(my $pid = fork) or die "Can't fork: $!";
# exit if $pid;
# setsid or die "Can't start a new session: $!";
print "############################\n";
print "Starting Music Daemon\n";
print "############################\n";
}
sub REAPER {
my $waitedpid = wait;
# loathe sysV: it makes us not only reinstate
# the handler, but place it after the wait
$SIG{CHLD} = \&REAPER;
}
sub CATCH_USR1 {
print "someone told me to USR1\n";
#########################
# This is where we:
# - start recording
#########################
&start_record();
}
sub CATCH_USR2 {
print "someone told me to USR1\n";
#########################
# This is where we:
# - stop recording
#########################
&stop_record;
}