(* Wrapping of some low-level functions *)

open Unix
open Tk

(* for the tachymeter *)
let bytes_read = ref 0
and sample_read = ref 0

let get_bytes_read () = !bytes_read
and get_sample_read () = !sample_read

let read fd buf offs l =
  let n = Unix.read fd buf offs l in
    bytes_read := !bytes_read + n;
    sample_read := !sample_read + n;
    n

let pending_read = ref 0
and action = ref (fun _ -> ())

let add_fileinput fd f =
  incr pending_read;
  !action !pending_read;
  Fileevent.add_fileinput fd f

let remove_fileinput fd =
  decr pending_read;
  !action !pending_read;
  Fileevent.remove_fileinput fd

let busyf = ref (fun _ -> ())

(* We catch dead children here, to avoid large number of zombies.
   I know about SICHLD of course, but I hate interrupted syscalls
 *)

let fork () =
 begin try
  while 
    let p, s = Unix.waitpid [Unix.WNOHANG] 0 in 
      (*
      Printf.eprintf "%d\n" p;
      begin match s with
      	 WEXITED n -> Printf.eprintf "Exit %d\n" n
       | WSIGNALED(n,_) -> 
      	    Printf.eprintf "SIG %d\n" n
       | WSTOPPED n -> Printf.eprintf "Stopped %d\n" n
      end;
      flush Pervasives.stderr;
      *)
      p <> 0
 do () done
 with
  Unix.Unix_error(_,_,_) -> ()
 end;
 Unix.fork()

let busy f x =
  !busyf true;
  try 
    let v = f x in
    !busyf false; v
  with
    e -> !busyf false; raise e


let global_time = ref 0
let tasks = ref []

let rec refresh() =
  incr global_time;
  List.iter (fun f -> f ()) !tasks;
  Timer.add 500 refresh;
  ()

let add_task f = tasks := f :: !tasks

let init f g =
  refresh();
  action := f;
  busyf := g

