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