#!/usr/bin/perl
#__        __   _                             _
#\ \      / /__| |__   ___ __ _ _ __ ___   __| |
# \ \ /\ / / _ \ '_ \ / __/ _` | '_ ` _ \ / _` |
#  \ V  V /  __/ |_) | (_| (_| | | | | | | (_| |
#   \_/\_/ \___|_.__/ \___\__,_|_| |_| |_|\__,_|
#
#webcamd v0.7.5
#
#diff : Petite version temporaire, dsactivation possible de la date ds le fichier de conf (pour eviter un bug actuel
#
#
#Ce code est distribu sous license GPL <http://www.gnu.org>
#Dbut de code par Pierre Dinh-van <pierre@tuxfamily.org> http://www.bill2tux.org le 03/07/2001  04h21 :-)
#
#last modif : 23/02/2002 par Pierre Dinh-van
#
#Ce code necessite :
#        *perl (5.0 minimum je pense)
#        *video4linux (specialement le programme v4lctl)
#        *un serveur web install (optionel)
#        *une webcam peut etre bien utile :-)
#        *perlmagick (module ImageMagick pour perl)
#
#note : code en construction :)
#N'oubliez pas d'editer le fichier de configuration et les templates HTML !


#######
#Code inutile a modifier pour la configuration (en principe)
#
#You needn't to change anything before this line, edit config file
#

$home=$ENV{'HOME'};

if (!(-e "$home/.webcamd"))
  {
    mkdir("$home/.webcamd");
    print("First run of webcamd !\n");
  }

if (-e "$home/.webcamd/webcamd.conf")
  {
    open(CONFIG,"$home/.webcamd/webcamd.conf");
    @config = <CONFIG>;
    close(CONFIG);
    print("Configuration file found\n");
  }

#elsif (-e "/etc/webcamd.conf")
#  {
#    open(CONFIG,"/etc/webcamd.conf");
#    @config = <CONFIG>;
#    close(CONFIG);
#    print("Using /etc/webcamd.conf configuration file\n");
#  }

####</test de localisation du fichier de conf>

####<test d'existence des templates>

if (-e "$home/.webcamd/index_up.html")
  {
    open(UP,"$home/.webcamd/index_up.html");
    @index_up = <UP>;
    close(UP);
  }

else
  {
  print("RTFM, missing template ($home/.webcamd/index_up.html)\n");
  exit;
  }

if (-e "$home/.webcamd/index_down.html")
  {
    open(DOWN,"$home/.webcamd/index_down.html");
    @index_down = <DOWN>;
    close(DOWN);
  }

else
  {
    print("RTFM, missing template ($home/.webcamd/index_down.html)\n");
    exit;
  }

####</test d'existence des templates>

##</test d'existence des templates et du fichier de conf>

#</tests de base>

#<Analyse et utilisation du fichier de conf>

if (@config == 0)
  {
    die("No configuration file was found. Unable to continue.");
  }

else
  {
    %config =  &analyse_config();
    #section common
    $inter = $config{'inter'};
    $www_path = $config{'www_path'};
    $enable_ftp = $config{'enable_ftp'};
    $cam_res = $config{'webcam_resolution'};
    $device = $config{'device'};
    #section picture
    $put_date = $config{'put_date'};
    $font = $config{'font'};
    $fontsize = $config{'fontsize'};
    $fontcolor = $config{'fontcolor'};
    $disp_box = $config{'disp_box'};
    $boxcolor = $config{'boxcolor'};
    $border = $config{'border'};
    $bordercolor = $config{'bordercolor'};
    #section ftp
    $host = $config{'host'};
    $user = $config{'user'};
    $port = $config{'port'};
    $password = $config{'password'};
    $directory = $config{'directory'};
  }

#</Analyse et utilisation du fichier de conf>

#<gestion du soft>

##<Analyse des arguments>

$action = $ARGV[0];

if ($action eq "")
  {
    die("Usage : {start|stop|refresh|(away)}\n");
  }
elsif ($ARGV[1] ne "")
 {
    die("Too many args\n");
 }

##</Analyse des arguments>

else
  {
    if ($action eq "start")
    {
      if (!(-e "$home/.webcamd/webcamd.pid"))  #si le soft ne tourne pas encore
	{
	  write_index();
	  print("webcamd run, pictures are taken every $inter secondes\n");
	  if (-e "$home/.webcamd/webcamd.stop") {`rm $home/.webcamd/webcamd.stop`}; #suppression si fichier de stop avant lancement
	  open(PID,">$home/.webcamd/webcamd.pid");    #creation du fichier de pid (temoin du lancement du soft)
	  close(PID);
	  fork && exit;       #rend la main
	  while(1)
	    {
	      getshot();
	      if($put_date eq "yes")
	      {
		  addtime();
	      }
	       else 
 	      {
 		  system("mv $home/.webcamd/pre-webcam.jpg $home/.webcamd/webcam.jpg");
 	      }
	      move_file();
	      last if (-e "$home/.webcamd/webcamd.stop");  #boucle s'arrete si fichier d'arret present
	      sleep($inter);
	    }
	  system("rm -f $home/.webcamd/webcamd.stop");     #suppression du fichier d'arret en cas d'arret
	}
      else                      #si le fichier de pid existe
	{
	  print("Webcamd is already running\n");
	}
    }
  elsif ($action eq "stop")
    {
      if (!(-e "$home/.webcamd/webcamd.stop"))  #si le fichier de stop n'existe pas encore
	{
	  if (-e "$home/.webcamd/webcamd.pid")  #et si le fichier de pid existe
	    {
	      open(STOP,">$home/.webcamd/webcamd.stop");  #creation du fichier de stop
	      close(STOP);
	      system("rm -f $home/.webcamd/webcamd.pid &");  #suppression du pid
	      print("Shutting down webcamd...\n");
	      write_index();  #ecriture de l'index cam offline
	    }
	  else
	    {
	      print ("Webcamd is not running !\n"); #si le pid n'existe pas
	      exit;
	    }
	}
      else
	{
	  print("You have already ask webcamd to be stopped. Please wait...\n"); #si le stop existe deja
	}
    }
  elsif ($action eq "refresh")
    {
      getshot();
       if($put_date eq "yes")
       {
	  addtime();
       }
       else 
       {
 	  system("mv $home/.webcamd/pre-webcam.jpg $home/.webcamd/webcam.jpg");
       }
       move_file();
      print("Smile ! We are taking a shot ! :-)\n");  #prise d'image anticipe
    }
  else
    {
      print("I don't know this\n");
    }
}
#
#fin du code
####

#<Definition des fonctions>

##<fonction d'ecriture de l'index>

sub write_index()
  {
    %hash=(INTER_REFRESH, $inter);

    sub parse_template()
      {
	my ($template, $key_list) = @_;
	$template =~ s{__(.*?)__}{exists($key_list->{$1}) ? $key_list->{$1} : ""}gsex;
	return $template;
      }

    open(INDEX,">$home/.webcamd/index.html");
    if ($action eq "start")
      {
	foreach (@index_up)
	  {
	    $temp = &parse_template($_, \%hash);
	    print INDEX $temp;
	  }
      }
    else
      {
	foreach (@index_down)
	  {
	    print INDEX $_;
	  }
      }
    close(INDEX);
    if ($enable_ftp eq "yes")
      {
	$filename = "$home/.webcamd/index.html";
	$trans_mode = "A";
	&upload($filename,$trans_mode);
      }
    else
      {
	system("mv $home/.webcamd/index.html $www_path/index.html");
      }
  }


##</fonction d'ecriture de l'index>

##<fonction d'aquisition de l'image>

sub getshot()
  {
      system("/usr/bin/v4lctl -c /dev/$device snap jpeg $cam_res $home/.webcamd/pre-webcam.jpg&");
  }

##</fonction d'aquisition de l'image>

##<fonction de rajout de l'heure>

sub addtime()
{
    #On utilise ImageMagick
    use Image::Magick;

    #On ouvre le fichier
    my $image = Image::Magick->new(magick=>'GIF',font=>$font);
    open(DATA, "$home/.webcamd/pre-webcam.jpg");
    $image->Read(file=>DATA);
    close(DATA);
    
    #on choppe le temps local
    my $time=localtime();

    #On ajoute une bordure pour faire zoli
    $image->Border(width=>$border, height=>$border, fill=>$bordercolor);

    #On ajoute le text
    
#$image->Annotate( box=>$boxcolor, fill=>$fontcolor, pointsize=>$fontsize, stroke=>'black', text=>$time, gravity=>South, y=>$fontsize);
    if($disp_box eq "yes")
    {
	$image->Annotate( box=>$boxcolor, fill=>$fontcolor, pointsize=>$fontsize, stroke=>'black', text=>$time, gravity=>South, y=>'0');
    }
    else
    {
	$image->Annotate(fill=>$fontcolor, pointsize=>$fontsize, text=>$time, gravity=>South, y=>'0');
    }


    #On crit le fichier
    my $filename = "$home/.webcamd/webcam.jpg";
    open(DATA, ">$filename") or die "can't open $filename\n";
         $image->Write(file=>DATA, filename=>$filename); 
    close(DATA);
}

sub move_file()
{
    if($enable_ftp eq "yes")
    {
	$filename = "$home/.webcamd/webcam.jpg";
	$trans_mode = "I";
	&upload($filename,$trans_mode);
    }
    else
    {
	system("mv $home/.webcamd/webcam.jpg $www_path/webcam.jpg");
    }
}

##<fonction d'upload par ftp>

sub upload($filename,$trans_mode)
  {
    #on utilise le protocole ftp
    use Net::FTP;
    $ftp = Net::FTP->new("$host",Port => $port, Passive => 1) or die "Can't connect: $@\n";
    $ftp->login($user, $password) or die "Couldn't login\n";
    $ftp->cwd($directory) or die "Couldn't change directory\n";
    $ftp->type($trans_mode);
    $ftp->put($filename) or die "Couldn't put $filename\n";
  }

##</fonction d'upload par ftp>

##</fonction de rajout de l'heure>

##<fonction d'analyse du fichier de config>

sub analyse_config()
  {
    my $i=$j=$k=0;
###<rappatriage des donnes du fichier de conf>

  LINE:
    foreach $line (@config)
      {
	$line =~ s/^\s*|\s*\n$//g;
	if(($line =~ /^\#/) || ($line eq ""))
	  {
	    next LINE;
	  }
	if($line =~ /^</)
	  {
	    if ($line eq "<common>")
	      {
		$section = "common";
		next LINE;
	      }
	    elsif($line eq "<picture>")
	      {
		$section = "picture";
		next LINE;
	      }
	    elsif($line eq "<ftp>")
	      {
		$section = "ftp";
		next LINE;
	      }
	    elsif($line eq "<away_mode>")
	      {
		print("Fonction away not yet implanted\n");
		next LINE;
	      }
	    else
	      {
		die("Config file not regular (section inconnue)\n");
	      }
	  }
	
	if($section eq "common")
	  {
	    if(!(($line =~ /^</)||($line eq "")))
	      {
		$common_line[$i] = $line;
		$i++;
		next LINE;
	      }
	  }		
	if($section eq "picture")
	  {
	    if(!(($line =~ /^</)||($line eq "")))
	      {
		$picture_line[$j] = $line;
		$j++;
		next LINE;
	      }
	  }
	if($section eq "ftp")
	  {
	    if(!(($line =~ /^</)||($line eq "")))
	      {
		$ftp_line[$k] = $line;
		$k++;
		next LINE;
	      }
	  }
	else
	  {			
	    print("section non valide !\n");
	  }
      }

###</rappatriage des donnes du fichier de conf>

###<Analyse de la section common>

    if(@common_line == 0)
      {
	print("No instructions found in config file for section <common>\n");
      }

    if(@picture_line == 0)
      {
	print("No instructions found in config file for section <picture>\n");
      }

    if(@ftp_line == 0)
      {
	print("No instructions found in config file for section <ftp>\n");
      }
    else
      {
	foreach (@common_line)
	  {
	    @temp = "";
	    @temp = split(/\s*=\s*/,$_);
	    if (@temp != 2)
	      {
		print ("Trop de parametres pour la variable $temp[0] !");
	      }
	    else
	      {
		$common{$temp[0]} = $temp[1];
	      }
	  }
	
	foreach (@picture_line)
	  {
	    @temp = "";
	    @temp = split(/\s*=\s*/,$_);
	    if (@temp != 2)
	      {
		print ("Trop de parametres pour la variable $temp[0] !");
	      }
	    else
	      {
		$picture{$temp[0]} = $temp[1];
	      }
	  }
	
	foreach (@ftp_line)
	  {
	    @temp = "";
	    @temp = split(/\s*=\s*/,$_);
	    if (@temp != 2)
	      {
		print ("Trop de parametres pour la variable $temp[0] !");
	      }
	    else
	      {
		$ftp{$temp[0]} = $temp[1];
	      }
	  }
	return %config = (%common,%ftp,%picture);
      }
  }
###</Analyse de la section common>


##</fonction d'analyse du fichier de config>

#</Definition des fonctions>
