Skip to content

Commit 52441af

Browse files
committed
Add doc, update build scripts.
1 parent ca42aa5 commit 52441af

File tree

198 files changed

+76487
-67
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

198 files changed

+76487
-67
lines changed

docker/Dockerfile.alpine-ci

+4-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
FROM alpine:edge
1+
FROM alpine:edge AS base
22

33
ENTRYPOINT bash
44

@@ -68,3 +68,6 @@ RUN \
6868
RUN eval $(opam config env) && \
6969
cat PACKAGES.default | while read i; do ( echo $EXCLUDED_PACKAGES | grep -q `echo $i | cut -d'-' -f 2` ) || echo "$i"; done > PACKAGES && \
7070
make
71+
72+
FROM alpine:edge
73+
COPY --from=base / /

docker/Dockerfile.ci

+6-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
ARG BASE_IMAGE
2-
FROM $BASE_IMAGE
2+
FROM $BASE_IMAGE AS base
33

44
ENTRYPOINT bash
55

@@ -24,9 +24,9 @@ RUN if [ "$OS" = "debian" ]; then \
2424
fi
2525

2626
# We need an up-to date ffmpeg on bookworm
27-
RUN if [ "$DISTRIBUTION" = "bookworm" ]; then \
27+
RUN if [ "$DISTRIBUTION" = "bookworm" -o "$DISTRIBUTION" = "trixie" ]; then \
2828
apt-get update && apt install -y ca-certificates && \
29-
echo "deb https://www.deb-multimedia.org bookworm main non-free" >> /etc/apt/sources.list && \
29+
echo "deb https://www.deb-multimedia.org $DISTRIBUTION main non-free" >> /etc/apt/sources.list && \
3030
apt-get update -oAcquire::AllowInsecureRepositories=true && \
3131
apt-get install -y --allow-unauthenticated deb-multimedia-keyring; \
3232
fi
@@ -100,3 +100,6 @@ RUN eval $(opam config env) && \
100100
cd website && \
101101
git pull && \
102102
make dist
103+
104+
FROM $BASE_IMAGE
105+
COPY --from=base / /

docker/Dockerfile.win32-deps

+20-10
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
ARG IMAGE
2-
FROM $IMAGE
2+
FROM $IMAGE AS base
33

4-
ENV OPAM_MXE_DEPS=ao-windows,camomile-windows,cry-windows,dtools-windows,duppy-windows,ffmpeg-windows,menhir-windows,mm-windows,ocurl-windows,pcre-windows,portaudio-windows,samplerate-windows,sedlex-windows,ssl-windows,srt-windows,taglib-windows,winsvc-windows
4+
USER opam
55

6-
ENV OPAM_NATIVE_DEPS=pcre
6+
ENV OPAM_MXE_DEPS=ao-windows,camomile-windows,cry-windows,dtools-windows,duppy-windows,ffmpeg-windows,menhir-windows,mm-windows,ocurl-windows,re-windows,portaudio-windows,samplerate-windows,sedlex-windows,ssl-windows,srt-windows,taglib-windows,winsvc-windows
77

8-
RUN git config --global user.email "toots@rastageeks.org" && git config --global user.name "Romain Beauxis"
8+
RUN git config --global user.email "savonet@rastageeks.org" && git config --global user.name "Romain Beauxis"
99

1010
RUN eval `opam config env` && opam repository remove windows --all && \
1111
cd /home/opam/ && rm -rf opam-cross-windows && \
@@ -16,21 +16,31 @@ RUN eval `opam config env` && opam repository remove windows --all && \
1616

1717
USER root
1818

19+
RUN apt-get -y update && apt-get -y install python3-mako
20+
1921
# This is until all cherry-picks below are removed.
20-
RUN cd /usr/src/mxe/ && git config --global user.email "toots@rastageeks.org" && git config --global user.name "Romain Beauxis" && git remote add savonet https://github.com/savonet/mxe.git && git fetch savonet
22+
RUN cd /usr/src/mxe/ && git config --global user.email "savonet@rastageeks.org" && git config --global user.name "Romain Beauxis" && git remote add savonet https://github.com/savonet/mxe.git && git fetch savonet
2123

22-
# We fail to build with those.
23-
RUN cd /usr/src/mxe/ && git cherry-pick 076849a53efda0710f69fe06bf601d99a4451e8b
24+
RUN cd /usr/src/mxe/ && git reset --hard 5b255aa669ac479aebfd00377eb5ef95c1c6622f
2425

2526
RUN cd /usr/src/mxe/ && \
2627
cat /home/opam/mxe-deps | xargs make curl fdk-aac
2728

28-
USER opam
29+
FROM base AS build
30+
31+
USER root
2932

30-
RUN opam reinstall -y $OPAM_NATIVE_DEPS
33+
RUN apt-get install -y wine64
34+
35+
USER opam
3136

3237
ENV CC ""
3338

3439
ENV PKG_CONFIG_PATH /usr/src/mxe/usr/x86_64-w64-mingw32.static/lib/pkgconfig
3540

36-
RUN export OPAMSOLVERTIMEOUT=320 && eval `opam config env` && opam update && opam reinstall -y --verbose pandoc `echo $OPAM_MXE_DEPS | sed -e 's#,# #g'`
41+
ENV TOOLPREF64=/usr/src/mxe/usr/bin/x86_64-w64-mingw32.static-
42+
43+
RUN export OPAMSOLVERTIMEOUT=320 && eval `opam config env` && opam update && opam reinstall -y --verbose pandoc `echo $OPAM_MXE_DEPS | sed -e 's#,# #g' | sed -e 's#ffmpeg-windows##' | sed -e 's#ocurl-windows##' | sed -e 's#src-windows##'`
44+
45+
FROM $IMAGE
46+
COPY --from=build / /

docker/build-alpine-ci.sh

+3-25
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,6 @@
11
#!/bin/sh -e
22

3-
IS_ARMHF_BUILD=$1
4-
5-
if [ -n "${IS_ARMHF_BUILD}" ]; then
6-
ARCHITECTURE=armhf
7-
DOCKER_PLATFORM="--platform linux/arm/v7"
8-
BUILDX=buildx
9-
else
10-
ARCHITECTURE=`dpkg --print-architecture`
11-
DOCKER_PLATFORM=
12-
BUILDX=
13-
fi
14-
15-
TAG=alpine_$ARCHITECTURE
16-
BUILD_IMAGE=savonet/liquidsoap-ci-with-history:${TAG}
17-
EXPORTED_IMAGE=savonet/liquidsoap-ci:${TAG}
18-
19-
docker ${BUILDX} build ${DOCKER_PLATFORM} -f Dockerfile.alpine-ci . -t ${BUILD_IMAGE}
20-
21-
id=$(docker create ${BUILD_IMAGE})
22-
23-
docker export $id | docker import - ${EXPORTED_IMAGE}
24-
25-
docker rm -v $id
26-
27-
docker push ${EXPORTED_IMAGE}
3+
TAG=alpine
4+
BUILD_IMAGE=savonet/liquidsoap-ci:${TAG}
285

6+
depot build --push --platform linux/amd64,linux/arm64 -f Dockerfile.alpine-ci . -t ${BUILD_IMAGE}

docker/build-ci.sh

+3-25
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,13 @@
11
#!/bin/sh -e
22

33
export BASE_IMAGE=$1
4-
IS_ARMHF_BUILD=$2
54

65
if test -z "${BASE_IMAGE}"; then
76
BASE_IMAGE=debian:testing
87
fi
98

10-
if [ -n "${IS_ARMHF_BUILD}" ]; then
11-
ARCHITECTURE=armhf
12-
DOCKER_PLATFORM="--platform linux/arm/v7"
13-
BUILDX=buildx
14-
else
15-
ARCHITECTURE=`dpkg --print-architecture`
16-
DOCKER_PLATFORM=
17-
BUILDX=
18-
fi
19-
20-
TAG=`echo ${BASE_IMAGE} | sed -e 's#/#_#g' | sed -e 's#:#_#g'`_$ARCHITECTURE
21-
BUILD_IMAGE=savonet/liquidsoap-ci-with-history:${TAG}
22-
EXPORTED_IMAGE=savonet/liquidsoap-ci:${TAG}
9+
TAG=`echo ${BASE_IMAGE} | sed -e 's#/#_#g' | sed -e 's#:#_#g'`
10+
BUILD_IMAGE=savonet/liquidsoap-ci:${TAG}
2311

2412
export OS=`echo ${BASE_IMAGE} | cut -d':' -f 1`
2513
export DISTRIBUTION=`echo ${BASE_IMAGE} | cut -d':' -f 2`
@@ -34,14 +22,4 @@ if [ "$BASE_IMAGE" = "ubuntu:groovy" ]; then
3422
export EXCLUDED_PACKAGES=srt
3523
fi
3624

37-
docker ${BUILDX} build -t ${BUILD_IMAGE} ${DOCKER_PLATFORM} --build-arg EXTRA_PACKAGES --build-arg EXCLUDED_PACKAGES --build-arg BASE_IMAGE --build-arg OS --build-arg ARCHITECTURE --build-arg DISTRIBUTION -f Dockerfile.ci .
38-
39-
id=$(docker create ${BUILD_IMAGE})
40-
41-
docker export $id | docker import - ${EXPORTED_IMAGE}
42-
43-
docker rm -v $id
44-
45-
docker push ${EXPORTED_IMAGE}
46-
47-
docker push savonet/liquidsoap-ci:${TAG}
25+
depot build -t ${BUILD_IMAGE} --platform linux/amd64,linux/arm64 --push --build-arg EXTRA_PACKAGES --build-arg EXCLUDED_PACKAGES --build-arg BASE_IMAGE --build-arg OS --build-arg ARCHITECTURE --build-arg DISTRIBUTION -f Dockerfile.ci .

docker/build-win32.sh

+4-1
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,11 @@ else
2727
HOST="i686-w64-mingw32.static"
2828
fi
2929

30-
docker build -f Dockerfile.win32-deps -t ${DEPS_IMAGE} \
30+
echo docker build -f Dockerfile.win32-deps -t ${DEPS_IMAGE} \
3131
--build-arg IMAGE=${BASE_IMAGE} .
32+
33+
exit 0
34+
3235
docker build -f Dockerfile.win32 -t ${IMAGE} --no-cache --build-arg RELEASE=${RELEASE} \
3336
--build-arg IMAGE=${DEPS_IMAGE} --build-arg HOST=${HOST} --build-arg BUILD=${BUILD} .
3437
id=$(docker create ${IMAGE})

docker/depot.json

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{"id":"wz546czd90"}

website/Makefile

+2-2
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ GENERATED_INTERPRETER_DIR := $(PWD)/../liquidsoap/_build/default/src/js
66
NODE := $(shell which node)
77

88
# Versions for which documentation should be built and included
9-
VERSIONS := dev 1.4.4 2.0.7 2.1.0 2.1.1 2.1.2 2.1.3 2.1.4 2.2.0 2.2.1 2.2.2 2.2.3 2.2.4 2.2.5
10-
DEFAULT_VERSION := 2.2.5
9+
VERSIONS := dev 1.4.4 2.1.4 2.2.0 2.2.1 2.2.2 2.2.3 2.2.4 2.2.5 2.3.0
10+
DEFAULT_VERSION := 2.3.0
1111
# DEFAULT_VERSION := dev
1212

1313
# Static content

website/content/doc-2.3.0/beets.md

+138
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
# Integrating a music library: an example with Beets
2+
3+
Liquidsoap's native sources can read from files and folders,
4+
but if your radio uses an important music library
5+
(more than a thousand tracks)
6+
sorting by folders may not be enough.
7+
You will also need to adjust the playout gain per track (ReplayGain).
8+
In that case you would better have a music library
9+
queried by Liquidsoap.
10+
In this section we'll do this with [Beets](http://beets.io/).
11+
Beets holds your music catalog,
12+
cleans tracks' tags before importing,
13+
can compute each track's ReplayGain,
14+
and most importantly has a command-line interface we can leverage from Liquidsoap.
15+
The following examples may also inspire you to integrate another library or your own scripts.
16+
17+
After installing Beets,
18+
enable the `random` plug-in
19+
(see [Beets documentation on plug-ins](https://beets.readthedocs.io/en/stable/plugins/index.html#using-plugins)).
20+
To enable gain normalization, install and configure the
21+
[`replaygain`](https://beets.readthedocs.io/en/stable/plugins/replaygain.html) plug-in.
22+
To easily add single tracks to you library,
23+
you might also be interested in the
24+
[drop2beets](https://github.com/martinkirch/drop2beets#drop2beets) plug-in.
25+
The following examples suppose you defined a `BEET` constant,
26+
which contains the complete path to your `beet` executable (on UNIX systems, find it with `which beet`). For example:
27+
28+
```
29+
BEET = "/home/radio/.local/bin/beet"
30+
```
31+
32+
Before creating a Liquidsoap source,
33+
let's see why Beets queries are interesting for a radio.
34+
35+
## Beets queries
36+
37+
Queries are parameters that you usually provide to the `beet ls` command :
38+
Beets will find matching tracks.
39+
The `random` plug-in works the same, except that it returns only one track matching the query
40+
(see [the plug-in's documentation](https://beets.readthedocs.io/en/stable/plugins/random.html)).
41+
Once your library is imported,
42+
you can try the following queries on the command line
43+
by typing `beet ls [query]` or `beet random [query]`.
44+
To test quickly, add the `-t 60` option to `beet random`
45+
so it will select an hour worth of tracks matching your query.
46+
47+
Without selectors, queries search in a track’s title, artist, album name,
48+
album artist, genre and comments. Typing an artist name or a complete title
49+
usually match the exact track, and you could do a lovely playlist just by querying `love`.
50+
51+
But in a radio you'll usually query on other fields.
52+
You can select tracks by genre with the `genre:` selector.
53+
Be careful that `genre:Rock` also matches `Indie Rock`, `Punk Rock`, etc.
54+
To select songs having english lyrics, use `language:eng`.
55+
Or pick 80s songs with `year:1980..1990`.
56+
57+
Beets also holds internal meta-data, like `added`:
58+
the date and time when you imported each song.
59+
You can use it to query tracks inserted over the past month with `added:-1m..`.
60+
Or you can query track imported more than a year ago with `added:..-1y`.
61+
Beets also lets you
62+
[set your own tags](https://beets.readthedocs.io/en/stable/guides/advanced.html#store-any-data-you-like).
63+
64+
You can use the `info` plug-in to see everything Beets knows about title(s) matching a query
65+
by typing `beet info -l [query]`.
66+
See also [the Beets' documentation](https://beets.readthedocs.io/en/stable/reference/query.html)
67+
for more details on queries operators.
68+
All these options should allow you to create both general and specialized Liquidsoap sources.
69+
70+
## A source querying each next track from Beets
71+
72+
As of Liquidsoap 2.x we can create a function that creates a dynamic source,
73+
given its `id` and a Beet query.
74+
We rely on `request.dynamic` to call `beet random`
75+
(with `-f '$path'` option so beets only returns the matching track's path)
76+
every time the source must prepare a new track:
77+
78+
```{.liquidsoap include="beets-source.liq" from="BEGIN" to="END"}
79+
80+
```
81+
82+
Note that
83+
84+
- `query` can be empty, it will match all tracks in the library.
85+
- we set `retry_delay` to a second, to avoid looping on `beet` calls if something goes wrong.
86+
- The final type hint (`:source`) will avoid false typing errors when the source is integrated in complex operators.
87+
88+
## Applying ReplayGain
89+
90+
When the [`replaygain` plug-in](https://beets.readthedocs.io/en/stable/plugins/replaygain.html)
91+
is enabled, all tracks will have an additional metadata field called `replaygain_track_gain`.
92+
Check that Beet is configured to
93+
[write ID3 tags](https://beets.readthedocs.io/en/stable/reference/config.html#importer-options)
94+
so Liquidsoap will be able to read this metadata -
95+
your Beet configuration should include something like:
96+
97+
```
98+
import:
99+
write: yes
100+
```
101+
102+
Then we only need to add `amplify` to our source creation function. In the example below we also add `blank.eat`, to automatically cut silence at the beginning or end of tracks.
103+
104+
```{.liquidsoap include="beets-amplify.liq" from="BEGIN"}
105+
106+
```
107+
108+
This is the recommended Beets integration ;
109+
such source will provide music continuously,
110+
at a regular volume.
111+
112+
## Beets as a requests protocol
113+
114+
If you're queueing tracks with `request.queue`,
115+
you may prefer to integrate Beets as a protocol.
116+
In that case,
117+
the list of paths returned by `beet random -f '$path'` fits directly
118+
what's needed by protocol resolution:
119+
120+
```{.liquidsoap include="beets-protocol.liq" from="BEGIN"}
121+
122+
```
123+
124+
Once this is done,
125+
you can push a beets query from [the telnet server](server.html):
126+
if you created `request.queue(id="userrequested")`,
127+
the server command
128+
`userrequested.push beets:All along the watchtower`
129+
will push the Jimi Hendrix's song.
130+
131+
With this method, you can benefit from replay gain metadata too, by wrapping
132+
the recipient queue in an `amplify` operator, like
133+
134+
```liquidsoap
135+
userrequested = amplify(override="replaygain_track_gain", 1.0,
136+
request.queue(id="userrequested")
137+
)
138+
```

website/content/doc-2.3.0/blank.md

+38
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# Blank detection
2+
3+
[Liquidsoap](index.html) has three operators for dealing with blanks.
4+
5+
On GeekRadio, we play many files, some of which include bonus tracks, which
6+
means that they end with a very long blank and then a little extra music. It's
7+
annoying to get that on air. The `blank.skip` operator skips the
8+
current track when a too long blank is detected, which avoids that. The typical
9+
usage is simple:
10+
11+
```liquidsoap
12+
# Wrap it with a blank skipper
13+
s = blank.skip(s)
14+
```
15+
16+
At [RadioPi](http://www.radiopi.org/) they have another problem: sometimes they
17+
have technical problems, and while they think they are doing a live show,
18+
they're making noise only in the studio, while only blank is on air; sometimes,
19+
the staff has so much fun (or is it something else ?) doing live shows that they
20+
leave at the end of the show without thinking to turn off the live, and the
21+
listeners get some silence again. To avoid that problem we made the
22+
`blank.strip` operators which hides the stream when it's too blank
23+
(i.e. declare it as unavailable), which perfectly suits the typical setup used
24+
for live shows:
25+
26+
```{.liquidsoap include="blank-sorry.liq"}
27+
28+
```
29+
30+
If you don't get the difference between these two operators, you should learn
31+
more about liquidsoap's notion of [source](sources.html).
32+
33+
Finally, if you need to do some custom action when there's too much blank, we
34+
have `blank.detect`:
35+
36+
```{.liquidsoap include="blank-detect.liq" from="BEGIN" to="END"}
37+
38+
```

website/content/doc-2.3.0/book.md

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# The Liquidsoap book
2+
3+
Together with the release of Liquidsoap 2.0, we have written _the Liquidsoap
4+
book_ which covers in details the language and the process of building a
5+
radio. It complements the online documentation by providing a homogeneous and
6+
progressive presentation of Liquidsoap.
7+
8+
[![The Liquidsoap book](/assets/img/book.svg){height=600px}](https://www.amazon.com/dp/B095PVTYR3)
9+
10+
It can be [ordered from Amazon](https://www.amazon.com/dp/B095PVTYR3)
11+
(or [read online](http://www.liquidsoap.info/book/book.pdf)).

0 commit comments

Comments
 (0)