liquidsoap-prettier 1.8.2 → 1.8.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/check-formatting.yml +32 -0
- package/README.md +31 -5
- package/package.json +1 -1
- package/src/cli.js +104 -9
- package/tests/liq/audio.liq +460 -0
- package/tests/liq/autocue.liq +1081 -0
- package/tests/liq/clock.liq +14 -0
- package/tests/liq/cron.liq +74 -0
- package/tests/liq/error.liq +48 -0
- package/tests/liq/extra/audio.liq +677 -0
- package/tests/liq/extra/audioscrobbler.liq +482 -0
- package/tests/liq/extra/deprecations.liq +976 -0
- package/tests/liq/extra/externals.liq +196 -0
- package/tests/liq/extra/fades.liq +260 -0
- package/tests/liq/extra/file.liq +66 -0
- package/tests/liq/extra/http.liq +160 -0
- package/tests/liq/extra/interactive.liq +917 -0
- package/tests/liq/extra/metadata.liq +75 -0
- package/tests/liq/extra/native.liq +201 -0
- package/tests/liq/extra/openai.liq +150 -0
- package/tests/liq/extra/server.liq +177 -0
- package/tests/liq/extra/source.liq +476 -0
- package/tests/liq/extra/spinitron.liq +272 -0
- package/tests/liq/extra/telnet.liq +266 -0
- package/tests/liq/extra/video.liq +59 -0
- package/tests/liq/extra/visualization.liq +68 -0
- package/tests/liq/fades.liq +941 -0
- package/tests/liq/ffmpeg.liq +605 -0
- package/tests/liq/file.liq +387 -0
- package/tests/liq/getter.liq +74 -0
- package/tests/liq/hls.liq +329 -0
- package/tests/liq/http.liq +1048 -0
- package/tests/liq/http_codes.liq +447 -0
- package/tests/liq/icecast.liq +58 -0
- package/tests/liq/io.liq +106 -0
- package/tests/liq/liquidsoap.liq +31 -0
- package/tests/liq/list.liq +440 -0
- package/tests/liq/log.liq +47 -0
- package/tests/liq/lufs.liq +295 -0
- package/tests/liq/math.liq +23 -0
- package/tests/liq/medialib.liq +752 -0
- package/tests/liq/metadata.liq +253 -0
- package/tests/liq/nfo.liq +258 -0
- package/tests/liq/null.liq +71 -0
- package/tests/liq/playlist.liq +1347 -0
- package/tests/liq/predicate.liq +106 -0
- package/tests/liq/process.liq +93 -0
- package/tests/liq/profiler.liq +5 -0
- package/tests/liq/protocols.liq +1139 -0
- package/tests/liq/ref.liq +28 -0
- package/tests/liq/replaygain.liq +135 -0
- package/tests/liq/request.liq +467 -0
- package/tests/liq/resolvers.liq +33 -0
- package/tests/liq/runtime.liq +70 -0
- package/tests/liq/server.liq +99 -0
- package/tests/liq/settings.liq +41 -0
- package/tests/liq/socket.liq +33 -0
- package/tests/liq/source.liq +362 -0
- package/tests/liq/sqlite.liq +161 -0
- package/tests/liq/stdlib.liq +172 -0
- package/tests/liq/string.liq +476 -0
- package/tests/liq/switches.liq +197 -0
- package/tests/liq/testing.liq +37 -0
- package/tests/liq/thread.liq +161 -0
- package/tests/liq/tracks.liq +100 -0
- package/tests/liq/utils.liq +81 -0
- package/tests/liq/video.liq +918 -0
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
%ifdef sqlite
|
|
2
|
+
# @docof sqlite
|
|
3
|
+
def replaces sqlite(file) =
|
|
4
|
+
db = sqlite(file)
|
|
5
|
+
|
|
6
|
+
# Insert a list of key / value pairs, where all the values are
|
|
7
|
+
# strings.
|
|
8
|
+
def db.insert.list(~table, entries) =
|
|
9
|
+
let (columns, values) =
|
|
10
|
+
list.fold(
|
|
11
|
+
fun (result, entry) ->
|
|
12
|
+
begin
|
|
13
|
+
let (columns, values) = result
|
|
14
|
+
let (column, value) = entry
|
|
15
|
+
([...columns, column], [...values, sqlite.escape(value)])
|
|
16
|
+
end,
|
|
17
|
+
([], []),
|
|
18
|
+
entries
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
columns =
|
|
22
|
+
string.concat(
|
|
23
|
+
separator=", ",
|
|
24
|
+
columns
|
|
25
|
+
)
|
|
26
|
+
values =
|
|
27
|
+
string.concat(
|
|
28
|
+
separator=", ",
|
|
29
|
+
values
|
|
30
|
+
)
|
|
31
|
+
sql =
|
|
32
|
+
"INSERT INTO #{sqlite.escape(table)} (#{columns}) VALUES (#{values})"
|
|
33
|
+
|
|
34
|
+
db.exec(sql)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def db.select(~table, what="*", ~where="", ~limit=null) =
|
|
38
|
+
where =
|
|
39
|
+
if
|
|
40
|
+
where == ""
|
|
41
|
+
then
|
|
42
|
+
""
|
|
43
|
+
else
|
|
44
|
+
" WHERE #{where}"
|
|
45
|
+
end
|
|
46
|
+
limit =
|
|
47
|
+
if
|
|
48
|
+
null.defined(limit)
|
|
49
|
+
then
|
|
50
|
+
" LIMIT #{null.get(limit)}"
|
|
51
|
+
else
|
|
52
|
+
""
|
|
53
|
+
end
|
|
54
|
+
db.query(
|
|
55
|
+
"SELECT #{what} FROM #{table}#{where}#{limit}"
|
|
56
|
+
)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def db.select.iter(f, ~table, what="*", ~where="") =
|
|
60
|
+
where =
|
|
61
|
+
if
|
|
62
|
+
where == ""
|
|
63
|
+
then
|
|
64
|
+
""
|
|
65
|
+
else
|
|
66
|
+
" WHERE #{where}"
|
|
67
|
+
end
|
|
68
|
+
db.iter(
|
|
69
|
+
f,
|
|
70
|
+
"SELECT #{what} FROM #{table}#{where}"
|
|
71
|
+
)
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def db.delete(~table, ~where="") =
|
|
75
|
+
where =
|
|
76
|
+
if
|
|
77
|
+
where == ""
|
|
78
|
+
then
|
|
79
|
+
""
|
|
80
|
+
else
|
|
81
|
+
" WHERE #{where}"
|
|
82
|
+
end
|
|
83
|
+
db.exec(
|
|
84
|
+
"DELETE FROM #{table}#{where}"
|
|
85
|
+
)
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
# Count the number of items matching a condition.
|
|
89
|
+
def db.count(~table, ~where="") =
|
|
90
|
+
where =
|
|
91
|
+
if
|
|
92
|
+
where == ""
|
|
93
|
+
then
|
|
94
|
+
""
|
|
95
|
+
else
|
|
96
|
+
" WHERE " ^
|
|
97
|
+
where
|
|
98
|
+
end
|
|
99
|
+
let sqlite.query ([{count}] : [{count: int}]) =
|
|
100
|
+
db.query(
|
|
101
|
+
"SELECT COUNT(*) AS count FROM #{table}#{where}"
|
|
102
|
+
)
|
|
103
|
+
count
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
# Operations on tables.
|
|
107
|
+
let db.table = ()
|
|
108
|
+
|
|
109
|
+
def db.table.drop(table, ~existing=true) =
|
|
110
|
+
existing =
|
|
111
|
+
if
|
|
112
|
+
existing
|
|
113
|
+
then
|
|
114
|
+
" IF EXISTS"
|
|
115
|
+
else
|
|
116
|
+
""
|
|
117
|
+
end
|
|
118
|
+
db.exec(
|
|
119
|
+
"DROP TABLE#{existing} #{table}"
|
|
120
|
+
)
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
# Create a table with given fields.
|
|
124
|
+
# @param ~preserve Preserve previous table if one already exists under the same name.
|
|
125
|
+
def db.table.create(table, ~preserve=false, fields) =
|
|
126
|
+
preserve =
|
|
127
|
+
if
|
|
128
|
+
preserve
|
|
129
|
+
then
|
|
130
|
+
" IF NOT EXISTS"
|
|
131
|
+
else
|
|
132
|
+
""
|
|
133
|
+
end
|
|
134
|
+
fields =
|
|
135
|
+
string.concat(
|
|
136
|
+
separator=", ",
|
|
137
|
+
list.map(
|
|
138
|
+
fun (lt) ->
|
|
139
|
+
"#{fst(lt)} #{snd(lt)}",
|
|
140
|
+
fields
|
|
141
|
+
)
|
|
142
|
+
)
|
|
143
|
+
db.exec(
|
|
144
|
+
"CREATE TABLE#{preserve} #{table} (#{fields})"
|
|
145
|
+
)
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
# Check whether a table exists.
|
|
149
|
+
def db.table.exists(name) =
|
|
150
|
+
let sqlite.query ([{name}] : [{name: string}]) =
|
|
151
|
+
db.query(
|
|
152
|
+
"SELECT name FROM sqlite_master WHERE type='table' AND name=#{
|
|
153
|
+
sqlite.escape(name)
|
|
154
|
+
}"
|
|
155
|
+
)
|
|
156
|
+
name
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
db
|
|
160
|
+
end
|
|
161
|
+
%endif
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
%include "error.liq"
|
|
2
|
+
%include "null.liq"
|
|
3
|
+
%include "ref.liq"
|
|
4
|
+
%include "list.liq"
|
|
5
|
+
%include "math.liq"
|
|
6
|
+
%include "getter.liq"
|
|
7
|
+
%include "predicate.liq"
|
|
8
|
+
%include "settings.liq"
|
|
9
|
+
%include "log.liq"
|
|
10
|
+
%include "thread.liq"
|
|
11
|
+
%include "process.liq"
|
|
12
|
+
%include "string.liq"
|
|
13
|
+
%include "socket.liq"
|
|
14
|
+
%include "cron.liq"
|
|
15
|
+
%include "file.liq"
|
|
16
|
+
%include "switches.liq"
|
|
17
|
+
%include "utils.liq"
|
|
18
|
+
%include "clock.liq"
|
|
19
|
+
%include "metadata.liq"
|
|
20
|
+
%include "nfo.liq"
|
|
21
|
+
%include "playlist.liq"
|
|
22
|
+
%include "source.liq"
|
|
23
|
+
%include "tracks.liq"
|
|
24
|
+
%include "request.liq"
|
|
25
|
+
%include "audio.liq"
|
|
26
|
+
%include "fades.liq"
|
|
27
|
+
%include "autocue.liq"
|
|
28
|
+
%include "replaygain.liq"
|
|
29
|
+
%include "lufs.liq"
|
|
30
|
+
%include "http_codes.liq"
|
|
31
|
+
%include "http.liq"
|
|
32
|
+
%include "protocols.liq"
|
|
33
|
+
%include "resolvers.liq"
|
|
34
|
+
%include "icecast.liq"
|
|
35
|
+
%include "hls.liq"
|
|
36
|
+
%include "video.liq"
|
|
37
|
+
%include "ffmpeg.liq"
|
|
38
|
+
%include "profiler.liq"
|
|
39
|
+
%include "io.liq"
|
|
40
|
+
%include "sqlite.liq"
|
|
41
|
+
%include "medialib.liq"
|
|
42
|
+
%include "runtime.liq"
|
|
43
|
+
%include "server.liq"
|
|
44
|
+
%include "sqlite.liq"
|
|
45
|
+
%include "testing.liq"
|
|
46
|
+
%include "liquidsoap.liq"
|
|
47
|
+
|
|
48
|
+
%include_extra "extra/file.liq"
|
|
49
|
+
%include_extra "extra/native.liq"
|
|
50
|
+
%include_extra "extra/audio.liq"
|
|
51
|
+
%include_extra "extra/source.liq"
|
|
52
|
+
%include_extra "extra/http.liq"
|
|
53
|
+
%include_extra "extra/externals.liq"
|
|
54
|
+
%include_extra "extra/audioscrobbler.liq"
|
|
55
|
+
%include_extra "extra/server.liq"
|
|
56
|
+
%include_extra "extra/telnet.liq"
|
|
57
|
+
%include_extra "extra/interactive.liq"
|
|
58
|
+
%include_extra "extra/visualization.liq"
|
|
59
|
+
%include_extra "extra/openai.liq"
|
|
60
|
+
%include_extra "extra/spinitron.liq"
|
|
61
|
+
%include_extra "extra/metadata.liq"
|
|
62
|
+
%include_extra "extra/fades.liq"
|
|
63
|
+
%include_extra "extra/video.liq"
|
|
64
|
+
|
|
65
|
+
set_settings_ref(settings)
|
|
66
|
+
|
|
67
|
+
# Default on_select for both file and live composition profiles. When `ending`
|
|
68
|
+
# is non-null (the ending source was preempted mid-track), fades it out (up to
|
|
69
|
+
# 1s or remaining time). When `replay_metadata` is true, replays the latest
|
|
70
|
+
# metadata on the starting source.
|
|
71
|
+
def source.composition.default_on_select({starting, ending, replay_metadata}) =
|
|
72
|
+
let {id, insert_metadata, last_metadata} = source.methods(starting)
|
|
73
|
+
|
|
74
|
+
# starting can be an active source to insert metadata when the
|
|
75
|
+
# source is about to be used.
|
|
76
|
+
def starting() =
|
|
77
|
+
if
|
|
78
|
+
replay_metadata
|
|
79
|
+
then
|
|
80
|
+
last_metadata = last_metadata()
|
|
81
|
+
if
|
|
82
|
+
null.defined(last_metadata)
|
|
83
|
+
then
|
|
84
|
+
log.important(
|
|
85
|
+
label=id(),
|
|
86
|
+
"Switching to #{id()}: inserting latest metadata"
|
|
87
|
+
)
|
|
88
|
+
insert_metadata(null.get(last_metadata))
|
|
89
|
+
else
|
|
90
|
+
log.important(
|
|
91
|
+
label=id(),
|
|
92
|
+
"Switching to #{id()}: no latest metadata to insert"
|
|
93
|
+
)
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
starting
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
if
|
|
100
|
+
null.defined(ending)
|
|
101
|
+
then
|
|
102
|
+
leaving = null.get(ending)
|
|
103
|
+
|
|
104
|
+
let {id} = source.methods(leaving)
|
|
105
|
+
|
|
106
|
+
max_fade = 1.
|
|
107
|
+
rem = source.remaining(leaving)
|
|
108
|
+
if
|
|
109
|
+
rem == 0.
|
|
110
|
+
then
|
|
111
|
+
starting()
|
|
112
|
+
else
|
|
113
|
+
effective_fade = if rem >= 0. then min(rem, max_fade) else max_fade end
|
|
114
|
+
log.important(
|
|
115
|
+
label=id(),
|
|
116
|
+
"Ending #{id()} with a effective_fade #{effective_fade} fade out.."
|
|
117
|
+
)
|
|
118
|
+
|
|
119
|
+
leaving =
|
|
120
|
+
fade.out(
|
|
121
|
+
duration=effective_fade,
|
|
122
|
+
max_duration(effective_fade, sequence([leaving, switch([])]))
|
|
123
|
+
)
|
|
124
|
+
|
|
125
|
+
count = ref(0)
|
|
126
|
+
def next() =
|
|
127
|
+
c = count()
|
|
128
|
+
ref.incr(count)
|
|
129
|
+
if c == 0 then leaving elsif c == 1 then starting() else null end
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
source.dynamic(track_sensitive=true, next)
|
|
133
|
+
end
|
|
134
|
+
else
|
|
135
|
+
starting()
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
source.composition.file(
|
|
140
|
+
{
|
|
141
|
+
on_leave =
|
|
142
|
+
# skip the source when it is preempted mid-track (track_sensitive=false),
|
|
143
|
+
# so it starts fresh on next selection. When switching at a track
|
|
144
|
+
# boundary (track_sensitive=true), the source has finished naturally and
|
|
145
|
+
# no skip is needed.
|
|
146
|
+
|
|
147
|
+
fun ({source = s, track_sensitive}) ->
|
|
148
|
+
if
|
|
149
|
+
not track_sensitive
|
|
150
|
+
then
|
|
151
|
+
log.important(
|
|
152
|
+
label=source.id(s),
|
|
153
|
+
"Source left in the middle of a track: skipping current track"
|
|
154
|
+
)
|
|
155
|
+
let {skip, clear_last_metadata} = source.methods(s)
|
|
156
|
+
clear_last_metadata()
|
|
157
|
+
skip()
|
|
158
|
+
end,
|
|
159
|
+
on_select = source.composition.default_on_select,
|
|
160
|
+
track_sensitive = true,
|
|
161
|
+
replay_metadata = true
|
|
162
|
+
}
|
|
163
|
+
)
|
|
164
|
+
|
|
165
|
+
source.composition.live(
|
|
166
|
+
{
|
|
167
|
+
on_leave = fun (_) -> (),
|
|
168
|
+
on_select = source.composition.default_on_select,
|
|
169
|
+
track_sensitive = false,
|
|
170
|
+
replay_metadata = true
|
|
171
|
+
}
|
|
172
|
+
)
|