<?php

function _l($str) { return $str; }


/* Compute size and aspect for a video from its parameters (sx,sy, dar, par  ...) 
 * Returns an array with sx,sy and aspect (string as "x:y")
 */ 
function getsizeandaspect($me) {
  // 1. too much MORE than 16/9 : add black borders on top and bottom
  if ($me["DAR"]>1.82) {
    return array($me["vx"], (intval(9*$me["vx"]/16)), "16:9");
  }
  // 2. "almost" proper 16:9 : just remember it's 16:9 
  if ($me["DAR"]<=1.82 && $me["DAR"]>=1.73) { 
    return array($me["vx"], $me["vy"], "16:9");
  }
  // 3. too much LESS than 16:9 will be croped to 4:3 with black borders : 
  if ($me["DAR"]<1.73 && $me["DAR"]>1.37) {
    return array($me["vx"], (intval(3*$me["vx"]/4)), "4:3");
  }
  // 4. "almost" proper 4:3  : just remember it's 4:3 
  if ($me["DAR"]<=1.37 && $me["DAR"]>=1.30) {
    return array($me["vx"], $me["vy"], "4:3");
  }
  // 5. too much LESS than 4:3 (strange) will be croped to 4:3 with black border on left/right : 
  if ($me["DAR"]<1.30) {
    return array( (intval($me["vy"]*4/3)), $me["vy"], "4:3");
  }
}

/* From the actual size of a video (vx/vy) and its aspect ratio, tell the X and Y size for BIG size and SMALL size encoding
 * Returns an array with (smallx,smally,bigx,bigy)
 */
function getEncodeSizes($aspect,$vx,$vy) {
  if ($aspect=="4:3") {
    $smallx="432"; $smally="320";
    if ($vx>=1000) {
      $bigx="1024"; $bigy="768";
    } else {
      $bigx="640"; $bigy="480";
    }      
  } else {      // 16:9
    $smallx="480"; $smally="272";
    if ($vx>=1000) {
      $bigx="1024"; $bigy="576";
    } else {
      $bigx="640"; $bigy="360";
    }
  }
  return array($smallx,$smally,$bigx,$bigy);
}


function getVideoFormat($file,$debug=0,$quick=false) {
  $values=array();

  if (!$quick) {
    $out=array();
    exec('ffmpeg -i '.escapeshellarg($file).' -f null -an -r 25 -y - 2>&1 | tail -2 |head -1 | sed -e "s/^.*frame= *\([^ ]*\) .*$/\1/"',$out);
    $values["duration"]=intval($out[0])/25;
    if ($debug>0) echo  "  Frames         : ".$values["duration"]."\n";
  }
    
  $out=array();
  exec("ffmpeg -i ".escapeshellarg($file)." 2>&1",$out);
  print_r($out);
  $values["filename"]=$file;
  $values["size"]=filesize($file);
  $values["mtime"]=filemtime($file);
  /*
    Stream #0.0: Video: mjpeg, yuvj422p, 160x120, 15.00 tb(r)
    Stream #0.1: Audio: pcm_u8, 11024 Hz, mono, 88 kb/s
  */
  if ($debug>0) echo  "Filename         : ".$file."\n";
  foreach($out as $l) {
    unset($mat);
    if (preg_match("/^  Duration: ([^,]*),/",$l,$mat)) {
      if (preg_match("/([0-9][0-9]):([0-9][0-9]):([0-9][0-9])\.([0-9][0-9])/",$mat[1],$mat2)) {
	$values["duration"]=$mat2[1]*3600+$mat2[2]*60+$mat2[3];
      }
    }
    if (preg_match("/Stream \#/",$l)) {
      unset($mat);
      if (preg_match("/: Video: ([^,]*), ([^,]*), ([^,]*), ([^ ]*)/",$l,$mat)) {
	if ($debug>0) echo  "Video\n";
	if ($debug>0) echo  "  Codec          : ".$mat[1]."\n";
	$values["vcodec"]=strtolower(trim($mat[1]));
	if ($debug>0) echo  "  Pixel Format   : ".$mat[2]."\n";
	$values["vpixfmt"]=strtolower(trim($mat[2]));
	if ($debug>0) echo  "  Width x Height : ".$mat[3]."\n";
	unset($mat2);
	preg_match("/([0-9]+)x([0-9]+)/",$mat[3],$mat2);
	$values["vx"]=$mat2[1];
	$values["vy"]=$mat2[2];
	unset($mat2);
	if (preg_match("/DAR ([0-9]+):([0-9]+)/",$mat[3],$mat2)) {
	  $values["DAR"]=floatval($mat2[1])/floatval($mat2[2]);
	} else if (preg_match("/DAR ([0-9]+):([0-9]+)/",$mat[4],$mat2)) {
	  $values["DAR"]=floatval($mat2[1])/floatval($mat2[2]);
	} else {
	  $values["DAR"]=floatval($values["vx"])/floatval($values["vy"]);
	}
	// In case of funny aspect ratios (DAR) we round them up or down to 16:9 or 4:3
	if ($values["DAR"]>=1.73 && $values["DAR"]<=1.82) {
	  $values["DAR"]=16/9;
	}
	if ($values["DAR"]>=1.30 && $values["DAR"]<=1.37) {
	  $values["DAR"]=4/3;
	}
	unset($mat2); 
	if (preg_match("/PAR ([0-9]+):([0-9]+)/",$mat[3],$mat2)) {
	  $values["PAR"]=floatval($mat2[1])/floatval($mat2[2]);
	} else if (preg_match("/DAR ([0-9]+):([0-9]+)/",$mat[4],$mat2)) {
	  $values["PAR"]=floatval($mat2[1])/floatval($mat2[2]);
	} else {
	  $values["PAR"]=1; // Unknown = Square Pixels (video/broadcast guys DO tell their PAR/DAR ;) ) 
	}
	if ($debug>0) echo  "  Framerate      : ".$mat[4]."\n";
	$values["vfps"]=doubleval($mat[4]);
	$videofound=true;
      }
# Stream #0.0(eng): Video: Motion JPEG OpenDML, 320x240, 15.00 fps(r)                                                                                                           
    if (!$videofound && preg_match("/: Video: ([^,]*), ([^,]*), ([^ ]*)/",$l,$mat)) {
      if ($debug>0) echo  "Video\n";
      if ($debug>0) echo  "  Codec          : ".$mat[1]."\n";
      $values["vcodec"]=strtolower(trim($mat[1]));
      if ($debug>0) echo  "  Pixel Format   : N/A\n";
      if ($debug>0) echo  "  Width x Height : ".$mat[2]."\n";
      unset($mat2);
      preg_match("/([0-9]+)x([0-9]+)/",$mat[2],$mat2);
      $values["vx"]=$mat2[1];
      $values["vy"]=$mat2[2];
      if ($debug>0) echo  "  Framerate      : ".$mat[3]."\n";
      $values["vfps"]=doubleval($mat[3]);
      $videofound=true;
    }

    # Stream #0.1: Audio: pcm_u8, 11024 Hz, mono, 88 kb/s
    if (preg_match("/: Audio: ([^,]*), ([^,]*), ([^,]*), ([^ ]*)/",$l,$mat)) {
      if ($debug>0) echo  "Audio\n";
      if ($debug>0) echo  "  Codec          : ".$mat[1]."\n";
      $values["acodec"]=strtolower(trim($mat[1]));
      if ($debug>0) echo  "  Sample Rate    : ".$mat[2]."\n";
      $values["arate"]=intval(trim(str_replace("Hz","",$mat[2])));
      if ($debug>0) echo  "  Channels       : ".$mat[3]."\n";
      if ($mat[3]=="mono") $values["achannels"]=1;
      if ($mat[3]=="stereo") $values["achannels"]=2;
      if ($debug>0) echo  "  Bitrate        : ".$mat[4]."\n";
      $values["abitrate"]=doubleval($mat[4]);
      $audiofound=true;
    }
    # Case : no bitrate
    if (!$audiofound && preg_match("/: Audio: ([^,]*), ([^,]*), ([^,]*)/",$l,$mat)) {
      if ($debug>0) echo  "Audio\n";
      if ($debug>0) echo  "  Codec          : ".$mat[1]."\n";
      $values["acodec"]=strtolower(trim($mat[1]));
      if ($debug>0) echo  "  Sample Rate    : ".$mat[2]."\n";
      $values["arate"]=intval(trim(str_replace("Hz","",$mat[2])));
      if ($debug>0) echo  "  Channels       : ".$mat[3]."\n";
      if ($mat[3]=="mono") $values["achannels"]=1;
      if ($mat[3]=="stereo") $values["achannels"]=2;
      if ($debug>0) echo  "  Bitrate        : N/A\n";
      $audiofound=true;
    }
    }
  }
  if (!$videofound) {
    if ($debug>0) echo  "Video\n";
    if ($debug>0) echo  "  No Video Track Found\n";
  }
  if (!$audiofound) {
    if ($debug>0) echo  "Audio\n";
    if ($debug>0) echo  "  No Audio Track Found\n";
  }
  return $values;
  }


/* AddSlashes contextuel : ne fait addslashes que si magic-quotes est OFF */
if (get_magic_quotes_gpc()) {
	function asl($str) {
		return $str;
	}
} else {
	function asl($str) {
		return addslashes($str);
	}
}


if (get_magic_quotes_gpc()) {
	function nasl($str) {
		return addslashes($str);
	}
} else {
	function nasl($str) {
		return $str;
	}
}

function stripslashes_deep($value) {
  $value = is_array($value) ? array_map('stripslashes_deep', $value) : stripslashes($value);
  return $value;
}

/* StripSlashes contextuel : ne fait stripslashes que si magic-quotes est ON */
if (get_magic_quotes_gpc()) {
  function sts($str) {
    return stripslashes_deep($str);
  }
} else {
  function sts($str) {
    return $str;
  }
}


/* Convertit une datetime MySQL en date française jj/mm/aaaa */
function date_my2fr($my,$long=0) {
  $mois=array("Janvier","Février","Mars","Avril","Mai","Juin","Juillet","Aout","Septembre","Octobre","Novembre","Décembre");
  if ($long==2 && $my) {
    return substr($my,8,2)." ".$mois[substr($my,5,2)-1]." ".substr($my,0,4);    
  } elseif ($long==1 && $my) {
    return substr($my,8,2)."/".substr($my,5,2)."/".substr($my,0,4).
      " ".substr($my,11,5);
  } 
  if ($my!=0) {
    return substr($my,8,2)."/".substr($my,5,2)."/".substr($my,2,2);
  } else return "";
}

function sec2date($sec) {
  if ($sec>60) {
    if ($sec>3600) {
      return intval($sec/3600)."h ".intval(($sec-3600*intval($sec/3600))/60)."m ".($sec%60)."s";
    } else {
      return intval($sec/60)."m ".($sec%60)."s";
    }
  } else {
    return $sec."s";
  }
}

  /* Retourne une taille de fichier sous forme texte à partir de sa taille en octets.
   * La forme texte est de la forme "x o", "x Ko", "x Mo", "x Go"
   */
function format_size($size) {
  // Retourne une taille formattée en Octets, Kilo-octets, Méga-octets ou Giga-Octets, avec 2 décimales.
  $size=(float)$size;
  if ($size<1024) {
    $r=$size;
    $r.="&nbsp;o";
  } else {
    $size=$size/1024;
    if ($size<1024) {
      $r=round($size,1)."&nbsp;Ko";
    } else {
      $size=$size/1024;
      if ($size<1024) {
        $r=round($size,1)."&nbsp;Mo";
      } else {
        $size=$size/1024;
        if ($size<1024) {
          $r=round($size,1)."&nbsp;Go";
        } else {
          $r=round($size/1024,2)."&nbsp;To";
        }
      }
    }
  }
  return $r;
}


/* select_values($arr,$cur) echo des <option> du tableau $values ou de la table sql $values
   selectionne $current par defaut. Par defaut prends les champs 0 comme id et 1 comme 
   donnees pour la table. sinon utilise $info[0] et $info[1].
*/
function eoption($values,$cur,$info="") {
  if (is_array($values)) {
    foreach ($values as $k=>$v) {
      echo "<option value=\"$k\"";
      if ($k==$cur) echo " selected=\"selected\"";
      echo ">".$v."</option>";
    }
  } else {
    if (is_array($info)) {
      $r=mqlist("SELECT ".$info[0].", ".$info[1]." FROM $values ORDER BY ".$info[0].";");
    } else {
      $r=mqlist("SELECT * FROM $values ORDER BY 2;");
    }

    foreach ($r as $c) {
      echo "<option value=\"".$c[0]."\"";
      if ($c[0]==$cur) echo " selected=\"selected\"";
      echo ">".sts($c[1])."</option>";
    }
  }
}


/* select_values($arr,$cur) echo des <option> du tableau $values ou de la table sql $values
   selectionne $current par defaut. Par defaut prends les champs 0 comme id et 1 comme 
   donnees pour la table. sinon utilise $info[0] et $info[1].
*/
function eradio($values,$cur,$info="",$name) {
  if (is_array($values)) {
    foreach ($values as $k=>$v) {
      echo "<label><input type=\"radio\" name=\"$name\" value=\"$k\"";
      if ($k==$cur) echo " checked=\"checked\"";
      echo ">&nbsp;".$v."</label><br />";
    }
  } else {
    if (is_array($info)) {
      $r=mqlist("SELECT ".$info[0].", ".$info[1]." FROM $values ORDER BY ".$info[0].";");
    } else {
      $r=mqlist("SELECT * FROM $values ORDER BY 2;");
    }

    foreach ($r as $c) {
      echo "<label><input type=\"radio\" name=\"$name\" value=\"".$c[0]."\"";
      if ($c[0]==$cur) echo " checked=\"checked\"";
      echo ">&nbsp;".sts($c[1])."</label><br />";
    }
  }
}





/* ehe($str) simplifie l'affichage des valeurs par défaut des formulaires (text et textarea). */
function ehe($str) { echo sts(htmlentities($str)); } 

/* eher($str) est comme ehe mais pour l'élement $_REQUEST[$str] s'il existe */
function eher($str) { if (isset($_REQUEST[$str])) echo sts(htmlentities($_REQUEST[$str],ENT_COMPAT,"UTF-8")); } 

/* ifcheck($str) simplifie l'affichage des valeur des checkboxes et radioboxes */
function ifcheck($str) { if ($str) echo " checked=\"checked\""; }

function ifselect($str) { if ($str) echo " selected=\"selected\""; }


/* Affiche un pager sous la forme suivante : 
  Page précédente 0 1 2 ... 16 17 18 19 20 ... 35 36 37 Page suivante
  Les arguments sont comme suit : 
  $offset = L'offset courant de la page.
  $count = Le nombre d'éléments affiché par page.
  $total = Le nombre total d'éléments dans l'ensemble
  $url = L'url à afficher. %%offset%% sera remplacé par le nouvel offset des pages.
  $before et $after sont le code HTML à afficher AVANT et APRES le pager SI CELUI CI DOIT ETRE AFFICHE ...
  TODO : ajouter un paramètre class pour les balises html A.
  */
function pager($offset,$count,$total,$url,$before="",$after="") {
  // On nettoie les variables hein ...
  //  echo "PAGER : offset:$offset, count:$count, total:$total, url:$url<br />";
  $offset=intval($offset); 
  $count=intval($count); 
  $total=intval($total); 
  if ($offset<=0) $offset="0";
  if ($count<=1) $count="1";
  if ($total<=0) $total="0";
  if ($total<$offset) $offset=max(0,$total-$count);

  if ($total<=$count) { // Cas où l'on n'a pas assez d'éléments pour afficher un pager :) 
    return true;
  }
  echo $before;
  // Doit-on afficher Page précédente ?
  if ($offset) {
    $o=max($offset-$count,0);
    echo "<a href=\"".str_replace("%%offset%%",$o,$url)."\" alt=\"(Ctl/Alt-p)\" title=\"(Alt-p)\" accesskey=\"p\">"._l("Précédente")."</a> ";
  } else {
    echo _l("Précédente")." ";
  }

  if ($total>(2*$count)) { // On n'affiche le pager central (0 1 2 ...) s'il y a au moins 2 pages.
    echo " - ";
    if (($total<($count*10)) && ($total>$count)) {  // moins de 10 pages : 
      for($i=0;$i<$total/$count;$i++) {
	$o=$i*$count;
	if ($offset==$o) {
	  echo $i." "; 
	} else {
	  echo "<a href=\"".str_replace("%%offset%%",$o,$url)."\">$i</a> ";
	}
      }
    } else { // Plus de 10 pages, on affiche 0 1 2 , 2 avant et 2 après la page courante, et les 3 dernieres
      for($i=0;$i<=2;$i++) {
	$o=$i*$count;
	if ($offset==$o) {
	  echo $i." "; 
	} else {
	  echo "<a href=\"".str_replace("%%offset%%",$o,$url)."\">$i</a> ";
	}
      }
      if ($offset>=$count && $offset<($total-2*$count)) { // On est entre les milieux ...
	// On affiche 2 avant jusque 2 après l'offset courant mais sans déborder sur les indices affichés autour
	$start=max(3,intval($offset/$count)-2);
	$end=min(intval($offset/$count)+3,intval($total/$count)-3);
	if ($start!=3) echo " ... ";
	for($i=$start;$i<$end;$i++) {
	  $o=$i*$count;
	  if ($offset==$o) {
	    echo $i." "; 
	  } else {
	    echo "<a href=\"".str_replace("%%offset%%",$o,$url)."\">$i</a> ";
	  }
	}
	if ($end!=intval($total/$count)-3) echo " ... ";
      } else {
	echo " ... ";
      }
      for($i=intval($total/$count)-3;$i<$total/$count;$i++) {
	$o=$i*$count;
	if ($offset==$o) {
	  echo $i." "; 
	} else {
	  echo "<a href=\"".str_replace("%%offset%%",$o,$url)."\">$i</a> ";
	}
      }
    echo " - ";
    } // PLUS de 10 Pages ? 
  }
  // Doit-on afficher Page suivante ? 
  if ($offset+$count<$total) {
    $o=$offset+$count;
    echo "<a href=\"".str_replace("%%offset%%",$o,$url)."\" alt=\"(Ctl/Alt-s)\" title=\"(Alt-s)\" accesskey=\"s\">"._l("Suivante")."</a> ";
  } else {
    echo _l("Suivante")." ";
  }
  echo $after;
}


/* Lance une requete mysql et loggue éventuellement l'erreur) */
function mq($query) {
  global $er;
  $r=@mysql_query($query);
  if (mysql_errno()) {
    // TODO : probleme lors du RAISE : il lance un "log" donc fait un mysql insert !!!
    //       echo "ERREUR MYSQL : ".mysql_error()."<br>QUERY: ".$query."<br>\n";
    //    $er->raise(1,mysql_error());
    //$er->log(ERROR_LEVEL_FPUT,"mqerr",array("query"=>$query,"ERROR"=>mysql_error()));
  } else {
    // Uncomment this to log every request : 
    //$er->log(ERROR_LEVEL_FPUT,"mqok",array("query"=>$query));
  }
  return $r;
}

/* Lance une requete mysql et loggue éventuellement l'erreur), et retourne la liste des résultats dans un tableau de tableaux associatifs */
function mqlist($query) {
  global $er;
  $r=mq($query);
  if (mysql_errno()) {
    //$er->raise(1,mysql_error()."Q:".$query);
    return false;
  }
  $res=array();
  while ($c=mysql_fetch_array($r)) {
    $res[]=$c;
  }
  return $res;
}

/* Lance une requete mysql et loggue éventuellement l'erreur), et retourne la liste des résultats dans un tableau associatif (champ unique) */
function mqlistone($query) {
  global $er;
  $r=mq($query);
  if (mysql_errno()) {
    //$er->raise(1,mysql_error()."Q:".$query);
    return false;
  }
  $res=array();
  while ($c=mysql_fetch_array($r)) {
    $res[]=$c[0];
  }
  return $res;
}


/* Lance une requete mysql et loggue éventuellement l'erreur), et retourne la liste des résultats dans un tableau associatif ou les clés sont le premier champ et les valeurs le second. */
function mqassoc($query) {
  global $er;
  $r=mq($query);
  if (mysql_errno()) {
    //$er->raise(1,mysql_error()."Q:".$query);
    return false;
  }
  $res=array();
  while ($c=mysql_fetch_array($r)) {
    $res[$c[0]]=$c[1];
  }
  return $res;
}


/* Lance une requete mysql et loggue éventuellement l'erreur), et retourne le résultat unique dans un tableau associatif */
function mqone($query) {
  global $er;
  $r=mq($query);
  if (mysql_errno()) {
    //$er->raise(1,mysql_error()."Q:".$query);
    return false;
  }
  return mysql_fetch_array($r);
}

/* Lance une requete mysql et loggue éventuellement l'erreur), et retourne le champ unique du résultat unique. */
function mqonefield($query) {
  global $er;
  $r=mq($query);
  if (mysql_errno()) {
    //$er->raise(1,mysql_error()."Q:".$query);
    return false;
  }
  if (list($res)=mysql_fetch_array($r)) 
    return $res;
  else 
    return false;
}


function xmle($str) {
  return str_replace(chr(146),"'",str_replace("<","&lt;",str_replace(">","&gt;",str_replace("&","&amp;",$str))));
}


function description_filter($str) {
  $str=trim($str);
  while (preg_match("#\[[0-9:]*\]#",$str,$mat,PREG_OFFSET_CAPTURE)) {
    $times=explode(":",substr($mat[0][0],1,strlen($mat[0][0])-2));
    $val=0;
    foreach($times as $tim) { $tim=intval($tim); $val*=60; $val+=$tim; }
    $str=substr($str,0,$mat[0][1]-1)." <a href=\"javascript:seekToTime($val)\">voir à ".substr($mat[0][0],1,strlen($mat[0][0])-2)."</a> ".substr($str,$mat[0][1]+strlen($mat[0][0]));
  }
  $str=nl2br(trim($str));
  return $str;
}

?>