File: utils.liq

package info (click to toggle)
liquidsoap 2.1.3-2
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 12,924 kB
  • sloc: ml: 73,577; javascript: 24,836; sh: 3,440; makefile: 764; xml: 114; ansic: 96; lisp: 62; python: 35; perl: 8; ruby: 8
file content (120 lines) | stat: -rw-r--r-- 3,536 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
# Get the value associated to a variable in the process environment.
# Returns "" if the variable is not set.
# @category System
def getenv(~default="", s) =
  list.assoc(default=default, s, environment())
end

# Split the arguments of an url of the form `arg=bar&arg2=bar2` into
# `[("arg","bar"),("arg2","bar2")]`. The returned strings are decoded (see
# `url.decode`).
# @category String
# @param args Argument string to split.
def url.split_args(args) =
  def f(x) =
    ret = r/=/.split(x)
    arg = url.decode(list.nth(default="",ret,0))
    val = url.decode(list.nth(default="",ret,1))
    (arg,val)
  end
  l = r/&/.split(args)
  list.map(f,l)
end

# Split an url of the form `foo?arg=bar&arg2=bar2` into
# `("foo",[("arg","bar"),("arg2","bar2")])`. The returned strings are decoded
# (see `url.decode`).
# @category String
# @param uri Url to split.
def url.split(uri) =
  ret = r/([^\?]*)\?(.*)/.exec(uri)
  args = ret[2]
  if args != "" then
    (url.decode(ret[1]),url.split_args(ret[2]))
  else
    (url.decode(uri),[])
  end
end

let frame = ()

# Duration of a frame.
# @category Liquidsoap
def frame.duration =
  settings.frame.duration
end

# Keep a record of played files. This is primarily useful to know when a song
# was last played and avoid repetitions.
# @param ~duration Duration (in seconds) after which songs are forgotten. By default, songs are not forgotten which means that the playlog will contain all the songs ever played.
# @param ~hash Function to extract an identifier from the metadata. By default, the filename is used but we could return the artist to know when a song from a given artist was last played for instance.
# @param ~persistency Set a file name where the values are stored and loaded in case the script is restarted.
# @category Source / Track Processing
# @method add Record that file with given metadata has been played.
# @method last How long ago a file was played (in seconds), `infinity` is returned if the song has never been played.
def playlog(~duration=infinity, ~persistency=null(), ~hash=fun(m)->m["filename"])
  l = ref([])
  # Load from persistency file
  if null.defined(persistency) then
    if file.exists(null.get(persistency)) then
      let json.parse ( parsed : [(string * float)]? ) = file.contents(null.get(persistency))
      if null.defined(parsed) then
         l := null.get(parsed)
      end
    end
  end
  # Save into persistency file
  def save()
    if null.defined(persistency) then
      let json.stringify data = !l
      file.write(data=data, null.get(persistency))
    end
  end
  # Remove too old elements
  def prune()
    if duration != infinity then
      t = time()
      l := list.assoc.filter(fun(_, tf) -> t - tf <= duration, !l)
    end
  end
  # Add a new entry
  def add(m)
    prune()
    f = hash(m)
    l := (f, time()) :: !l
    save()
  end
  # Last time this entry was played
  def last(m)
    f = hash(m)
    time() - list.assoc(default = 0.-infinity, f, !l)
  end
  { add=add, last=last }
end

# Top-level init module for convenience
# @flag hidden
init = settings.init

# Memoize the result of a function,
# making sure it is only executed once.
def memoize(fn) =
  cached_result = ref([])
  fun () -> begin
    if !cached_result != [] then
      list.hd(!cached_result)
    else
      result = fn()
      cached_result := [result]
      result
    end
  end
end

# Set the current time zone. This is
# equivalent to setting the `TZ` environment
# variable.
# @category Liquidsoap
def time.zone.set(tz) =
  setenv("TZ", tz)
end