Hi all !

I've been working with interactive things, and I've looked at 
interactive_string.

The idea behind this is to let output files change depending on metadata (and 
hopefully tracks..)

I've worked around current implementation, and I've got a first working example.

The patches attached are:
add_interactive_string: adds interactive_string. var.list still show 
interactive strings as: 
name: float, I couldn't find out why..

interactive_rewrite_meta: implements interactive_string for rewrite_metadatas

interactive_vorbis: implements interactive_floats for vorbis output. I'm not 
sure at all 
if this patch is correct...

As it is touching core things, lang.ml etc, I of course do not commit until it 
has been review..

My two comments so far are:
* mixture of interactive floats and strings works well thourgh telnet interface
* interactive strings are shown as float by var.list. Current code s supposed 
to return object's 
   type so I couldn't find what to do..
* interactive vorbis does not look good in the way it modifies file_output.ml.. 
It should have 
   broke others file outputs.. !  However, it works quite ok with the test 
below..

With some more work (and a 'a -> fun), I'll be able to write a stream ripper 
using liq !!

Look at this:
---(snipet)---
def set_artist(l)
  artist = l["artist"]
  title = l["title"]
  system(list.hd(execute("var.set filename = /tmp/" ^ artist ^ " - " ^ title ^ 
".ogg")))
end

input = amplify(interactive_float("volume",1.),mksafe(dolebrai))

s = on_metadata(set_artist,input)

output = output.file.vorbis(reopen_on_metadata=true, 
        interactive_string("filename","/tmp/foo.mp3"), s)
---(snipet)---

This will rip dolebrai to /tmp !

I'm waiting for some input from you...

Romain
-- 
Could not recognize the faces standing over me;
They were all dressed in uniforms of brutality.
Index: trunk/liquidsoap/src/lang/lang.mli
===================================================================
--- trunk/liquidsoap/src/lang/lang.mli	(révision 4290)
+++ trunk/liquidsoap/src/lang/lang.mli	(copie de travail)
@@ -121,6 +121,7 @@
 val to_string : value -> string
 val to_float : value -> float
 val to_float_getter : value -> unit -> float
+val to_string_getter : value -> unit -> string
 val to_source : value -> Source.source
 val to_request : value -> Request.t option
 val to_int : value -> int
@@ -154,6 +155,7 @@
 (** A float getter. The argument is the number of the universal type parameter
   * (should be >= 1). *)
 val float_getter_t : int -> kind
+val string_getter_t : int -> kind
 
 val unit : value
 val int : int -> value
Index: trunk/liquidsoap/src/lang/lang_builtins.ml
===================================================================
--- trunk/liquidsoap/src/lang/lang_builtins.ml	(révision 4290)
+++ trunk/liquidsoap/src/lang/lang_builtins.ml	(copie de travail)
@@ -752,7 +752,7 @@
     let usage = "set <variable> = <value>" in
       Server.add ~ns ~usage "set"
         (fun s ->
-           let pat = "^([a-zA-Z_][a-zA-Z0-9_.]*) *= *([^ ]+)" in
+           let pat = "^([a-zA-Z_][a-zA-Z0-9_.]*) *= *(.+)" in
            try
              let sub = Pcre.exec ~pat s in
              let name = Pcre.get_substring sub 1 in
@@ -825,3 +825,36 @@
                  FFI ([],[], fun p -> Lang.Float !v)
             )
       }
+
+
+let () =
+  let kind =
+    Lang.fun_t
+      [
+        false,"",Lang.string_t;
+        false,"",Lang.string_t
+      ]
+      (Lang.fun_t [] Lang.string_t)
+  in
+    Lang.builtins#register "interactive_string"
+      ~doc:(mkdoc ~cat:Interaction
+              "Read a string from an interactive input." kind)
+      {
+        t = kind;
+        value =
+          FFI
+            (["",None;"",None],[],
+             fun p ->
+               let name = Lang.to_string (Lang.assoc "" 1 p) in
+               let v = Lang.to_string (Lang.assoc "" 2 p) in
+               let v = ref v in
+                 Var.add
+                   name
+                   Lang.float_t
+                   ~get:(fun () -> Printf.sprintf "%s" !v)
+                   ~set:(fun s -> v := s)
+                   ~validate:(fun s -> try let _ = s in () with _ -> raise (Var.Invalid_value (s ^ " is not a string")));
+                 FFI ([],[], fun p -> Lang.String !v)
+            )
+      }
+
Index: trunk/liquidsoap/src/lang/lang.ml
===================================================================
--- trunk/liquidsoap/src/lang/lang.ml	(révision 4290)
+++ trunk/liquidsoap/src/lang/lang.ml	(copie de travail)
@@ -146,6 +146,15 @@
            | _ -> assert false)
   | _ -> assert false
 
+let to_string_getter t = match t.value with
+  | String s -> (fun () -> s)
+  | Fun _ | FFI _ ->
+      (fun () ->
+         match (apply t []).value with
+           | String s -> s
+           | _ -> assert false)
+  | _ -> assert false
+
 let to_source t = match t.value with
   | Source s -> s
   | _ -> assert false
@@ -200,6 +209,7 @@
 let univ_t ?(constraints=[]) i = T.make (T.UVar (i,constraints))
 let metadata_t = list_t (product_t string_t string_t)
 let float_getter_t n = univ_t ~constraints:[T.Getter T.Float] n
+let string_getter_t n = univ_t ~constraints:[T.Getter T.String] n
 
 let mk v = { t = T.dummy ; value = v }
 let unit = mk Unit
Index: trunk/liquidsoap/src/operators/rewrite_metadata.ml
===================================================================
--- trunk/liquidsoap/src/operators/rewrite_metadata.ml	(révision 4290)
+++ trunk/liquidsoap/src/operators/rewrite_metadata.ml	(copie de travail)
@@ -34,7 +34,7 @@
   method rewrite m =
     List.iter
       (fun (t,v) -> Hashtbl.replace m t v)
-      (List.map (fun (t,v) -> t, Utils.interpolate (Hashtbl.find m) v) patterns)
+      (List.map (fun (t,v) -> t, Utils.interpolate (Hashtbl.find m) (v ())) patterns)
 
   val mutable in_track = false
 
@@ -61,7 +61,7 @@
 
 let register =
   Lang.add_operator "rewrite_metadata"
-    [ "", Lang.list_t (Lang.product_t Lang.string_t Lang.string_t),
+    [ "", Lang.list_t (Lang.product_t Lang.string_t (Lang.string_getter_t 1)),
       None, Some "List of (target,value) rewriting rules." ;
       "insert_missing", Lang.bool_t, Some (Lang.bool true),
       Some "Treat track beginnings without metadata as having empty ones." ;
@@ -74,7 +74,7 @@
          List.map
            (fun x ->
               let (a,b) = Lang.to_product x in
-                Lang.to_string a, Lang.to_string b)
+                Lang.to_string a, Lang.to_string_getter b)
            (Lang.to_list (Lang.assoc "" 1 p))
        in
        let missing = Lang.to_bool (List.assoc "insert_missing" p) in
Index: trunk/liquidsoap/src/outputs/file_output.ml
===================================================================
--- trunk/liquidsoap/src/outputs/file_output.ml	(révision 4290)
+++ trunk/liquidsoap/src/outputs/file_output.ml	(copie de travail)
@@ -38,11 +38,12 @@
       Open_wronly::Open_creat::
       (if append then [Open_append] else [Open_trunc])
     in
-    let filename = Utils.strftime filename in
-    let filename = Utils.home_unrelate filename in
+    let real_filename = filename () in
+    let real_filename = Utils.strftime real_filename in
+    let real_filename = Utils.home_unrelate real_filename in
     let chan =
-      Utils.mkdir ~perm:dir_perm (Filename.dirname filename) ;
-      open_out_gen mode perm filename
+      Utils.mkdir ~perm:dir_perm (Filename.dirname real_filename) ;
+      open_out_gen mode perm real_filename
     in
       set_binary_mode_out chan true ;
       open_date <- Unix.gettimeofday () ;
@@ -114,7 +115,7 @@
   Some "When should the output file be re-opened." ;
 
   "",
-  Lang.string_t,
+  Lang.string_getter_t 1,
   None,
   Some ("Filename where to output the stream. "^
         "Some strftime conversion specifiers are available: %SMHdmY.") ;
Index: trunk/liquidsoap/src/outputs/vorbis_encoded.ml
===================================================================
--- trunk/liquidsoap/src/outputs/vorbis_encoded.ml	(révision 4290)
+++ trunk/liquidsoap/src/outputs/vorbis_encoded.ml	(copie de travail)
@@ -139,7 +139,7 @@
 object (self)
   inherit
     [Vorbis.Encoder.t] Output.encoded
-      ~name:filename ~kind:"output.file" ~autostart source
+      ~name:(filename ()) ~kind:"output.file" ~autostart source
   inherit File_output.to_file
             ~reload_delay ~reload_predicate ~reload_on_metadata
             ~append ~perm ~dir_perm filename as to_file
@@ -196,7 +196,7 @@
        let quality = e Lang.to_float "quality" in
        let vbr = e Lang.to_bool "vbr" in
        let freq = e Lang.to_int "samplerate" in
-       let name = Lang.to_string (Lang.assoc "" 1 p) in
+       let name = Lang.to_string_getter (Lang.assoc "" 1 p) in
        let append = Lang.to_bool (List.assoc "append" p) in
        let perm = Lang.to_int (List.assoc "perm" p) in
        let dir_perm = Lang.to_int (List.assoc "dir_perm" p) in

Répondre à