reorganize project

This commit is contained in:
jb-alvarado 2022-06-23 22:39:13 +02:00
parent 46ce7e2135
commit e7bc8fb096
9 changed files with 277 additions and 331 deletions

112
Cargo.lock generated
View File

@ -194,7 +194,7 @@ dependencies = [
"serde_urlencoded",
"smallvec",
"socket2",
"time 0.3.10",
"time 0.3.11",
"url",
]
@ -386,7 +386,7 @@ dependencies = [
"async-global-executor",
"async-io",
"async-lock",
"crossbeam-utils 0.8.9",
"crossbeam-utils 0.8.10",
"futures-channel",
"futures-core",
"futures-io",
@ -623,6 +623,17 @@ dependencies = [
"winapi 0.3.9",
]
[[package]]
name = "chrono"
version = "0.4.19"
source = "git+https://github.com/chronotope/chrono.git#b1d74aef688c27fccc738c64746535905903471a"
dependencies = [
"num-integer",
"num-traits",
"time 0.1.44",
"winapi 0.3.9",
]
[[package]]
name = "clap"
version = "3.2.6"
@ -706,7 +717,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94d4706de1b0fa5b132270cddffa8585166037822e260a944fe161acd137ca05"
dependencies = [
"percent-encoding",
"time 0.3.10",
"time 0.3.11",
"version_check",
]
@ -790,7 +801,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4c02a4d71819009c192cf4872265391563fd6a84c81ff2c0f2a7026ca4c1d85c"
dependencies = [
"cfg-if 1.0.0",
"crossbeam-utils 0.8.9",
"crossbeam-utils 0.8.10",
]
[[package]]
@ -837,7 +848,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1f25d8400f4a7a5778f0e4e52384a48cbd9b5c495d110786187fc750075277a2"
dependencies = [
"cfg-if 1.0.0",
"crossbeam-utils 0.8.9",
"crossbeam-utils 0.8.10",
]
[[package]]
@ -853,9 +864,9 @@ dependencies = [
[[package]]
name = "crossbeam-utils"
version = "0.8.9"
version = "0.8.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ff1f980957787286a554052d03c7aee98d99cc32e09f6d45f0a814133c87978"
checksum = "7d82ee10ce34d7bc12c2122495e7593a9c41347ecdd64185af4ecf72cb1a7f83"
dependencies = [
"cfg-if 1.0.0",
"once_cell",
@ -997,43 +1008,10 @@ dependencies = [
]
[[package]]
name = "ffplayout-api"
version = "0.3.0"
name = "ffplayout"
version = "0.10.0"
dependencies = [
"actix-multipart",
"actix-web",
"actix-web-grants",
"actix-web-httpauth",
"argon2",
"chrono 0.4.19 (registry+https://github.com/rust-lang/crates.io-index)",
"clap",
"derive_more",
"faccess",
"ffplayout-lib",
"ffprobe",
"futures-util",
"jsonwebtoken",
"log",
"once_cell",
"openssl",
"rand 0.8.5",
"rand_core 0.6.3",
"regex",
"relative-path",
"reqwest",
"sanitize-filename",
"serde",
"serde_json",
"serde_yaml",
"simplelog",
"sqlx",
]
[[package]]
name = "ffplayout-engine"
version = "0.9.9"
dependencies = [
"chrono 0.4.19 (git+https://github.com/sbrocket/chrono?branch=parse-error-kind-public)",
"chrono 0.4.19 (git+https://github.com/chronotope/chrono.git)",
"clap",
"crossbeam-channel 0.5.5",
"faccess",
@ -1054,11 +1032,43 @@ dependencies = [
"serde_yaml",
"shlex",
"simplelog",
"time 0.3.10",
"time 0.3.11",
"walkdir",
"zeromq",
]
[[package]]
name = "ffplayout-api"
version = "0.3.0"
dependencies = [
"actix-multipart",
"actix-web",
"actix-web-grants",
"actix-web-httpauth",
"argon2",
"chrono 0.4.19 (registry+https://github.com/rust-lang/crates.io-index)",
"clap",
"derive_more",
"faccess",
"ffplayout-lib",
"ffprobe",
"futures-util",
"jsonwebtoken",
"log",
"once_cell",
"rand 0.8.5",
"rand_core 0.6.3",
"regex",
"relative-path",
"reqwest",
"sanitize-filename",
"serde",
"serde_json",
"serde_yaml",
"simplelog",
"sqlx",
]
[[package]]
name = "ffplayout-lib"
version = "0.9.9"
@ -1083,7 +1093,7 @@ dependencies = [
"serde_yaml",
"shlex",
"simplelog",
"time 0.3.10",
"time 0.3.11",
"walkdir",
]
@ -2069,9 +2079,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf"
[[package]]
name = "openssl-src"
version = "111.20.0+1.1.1o"
version = "111.21.0+1.1.1p"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "92892c4f87d56e376e469ace79f1128fdaded07646ddf73aa0be4706ff712dec"
checksum = "6d0a8313729211913936f1b95ca47a5fc7f2e04cd658c115388287f8a8361008"
dependencies = [
"cc",
]
@ -2643,7 +2653,7 @@ dependencies = [
"num-bigint",
"num-traits",
"thiserror",
"time 0.3.10",
"time 0.3.11",
]
[[package]]
@ -2655,7 +2665,7 @@ dependencies = [
"log",
"paris",
"termcolor",
"time 0.3.10",
"time 0.3.11",
]
[[package]]
@ -2886,9 +2896,9 @@ dependencies = [
[[package]]
name = "time"
version = "0.3.10"
version = "0.3.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "82501a4c1c0330d640a6e176a3d6a204f5ec5237aca029029d21864a902e27b0"
checksum = "72c91f41dcb2f096c05f0873d667dceec1087ce5bcf984ec8ffb19acddbb3217"
dependencies = [
"itoa",
"libc",

View File

@ -10,58 +10,7 @@ while read -r name value; do
fi
done < ffplayout-engine/Cargo.toml
echo "Compile ffplayout-engine version is: \"$version\""
echo ""
for target in "${targets[@]}"; do
echo "compile static for $target"
echo ""
cargo build --release --target=$target --bin ffplayout
if [[ $target == "x86_64-pc-windows-gnu" ]]; then
if [[ -f "ffplayout-engine-v${version}_${target}.zip" ]]; then
rm -f "ffplayout-engine-v${version}_${target}.zip"
fi
cp ./target/${target}/release/ffplayout.exe .
zip -r "ffplayout-engine-v${version}_${target}.zip" assets docs LICENSE README.md ffplayout.exe -x *.db
rm -f ffplayout.exe
elif [[ $target == "x86_64-apple-darwin" ]] || [[ $target == "aarch64-apple-darwin" ]]; then
if [[ -f "ffplayout-engine-v${version}_${target}.tar.gz" ]]; then
rm -f "ffplayout-engine-v${version}_${target}.tar.gz"
fi
cp ./target/${target}/release/ffplayout .
tar -czvf "ffplayout-engine-v${version}_${target}.tar.gz" --exclude='*.db' assets docs LICENSE README.md ffplayout
rm -f ffplayout
else
if [[ -f "ffplayout-engine-v${version}_${target}.tar.gz" ]]; then
rm -f "ffplayout-engine-v${version}_${target}.tar.gz"
fi
cp ./target/${target}/release/ffplayout .
tar -czvf "ffplayout-engine-v${version}_${target}.tar.gz" --exclude='*.db' assets docs LICENSE README.md ffplayout
rm -f ffplayout
fi
echo ""
done
cargo deb --target=x86_64-unknown-linux-musl -p ffplayout-engine
mv ./target/x86_64-unknown-linux-musl/debian/ffplayout-engine_${version}_amd64.deb .
cargo generate-rpm --target=x86_64-unknown-linux-musl -p ffplayout-engine
mv ./target/x86_64-unknown-linux-musl/generate-rpm/ffplayout-engine-${version}-1.x86_64.rpm .
IFS="= "
while read -r name value; do
if [[ $name == "version" ]]; then
version=${value//\"/}
fi
done < ffplayout-api/Cargo.toml
echo "Compile ffplayout-api version is: \"$version\""
echo "Compile ffplayout version is: \"$version\""
echo ""
for target in "${targets[@]}"; do
@ -69,32 +18,43 @@ for target in "${targets[@]}"; do
echo ""
if [[ $target == "x86_64-pc-windows-gnu" ]]; then
if [[ -f "ffplayout-api-v${version}_${target}.zip" ]]; then
rm -f "ffplayout-api-v${version}_${target}.zip"
if [[ -f "ffplayout-v${version}_${target}.zip" ]]; then
rm -f "ffplayout-v${version}_${target}.zip"
fi
cargo build --release --target=$target --bin ffpapi
cargo build --release --target=$target
cp ./target/${target}/release/ffpapi.exe .
zip -r "ffplayout-api-v${version}_${target}.zip" assets docs LICENSE README.md ffpapi.exe -x *.db
rm -f ffpapi.exe
elif [[ $target == "x86_64-unknown-linux-musl" ]]; then
if [[ -f "ffplayout-api-v${version}_${target}.tar.gz" ]]; then
rm -f "ffplayout-api-v${version}_${target}.tar.gz"
cp ./target/${target}/release/ffplayout.exe .
zip -r "ffplayout-v${version}_${target}.zip" assets docs LICENSE README.md ffplayout.exe ffpapi.exe -x *.db
rm -f ffplayout.exe ffpapi.exe
elif [[ $target == "x86_64-apple-darwin" ]] || [[ $target == "aarch64-apple-darwin" ]]; then
if [[ -f "ffplayout-v${version}_${target}.tar.gz" ]]; then
rm -f "ffplayout-v${version}_${target}.tar.gz"
fi
cargo build --release --target=$target --bin ffpapi
cargo build --release --target=$target --bin ffplayout
cp ./target/${target}/release/ffplayout .
tar -czvf "ffplayout-v${version}_${target}.tar.gz" --exclude='*.db' assets docs LICENSE README.md ffplayout
rm -f ffplayout
else
if [[ -f "ffplayout-v${version}_${target}.tar.gz" ]]; then
rm -f "ffplayout-v${version}_${target}.tar.gz"
fi
cargo build --release --target=$target
cp ./target/${target}/release/ffpapi .
tar -czvf "ffplayout-api-v${version}_${target}.tar.gz" --exclude='*.db' assets docs LICENSE README.md ffpapi
rm -f ffpapi
cp ./target/${target}/release/ffplayout .
tar -czvf "ffplayout-v${version}_${target}.tar.gz" --exclude='*.db' assets docs LICENSE README.md ffplayout ffpapi
rm -f ffplayout ffpapi
fi
echo ""
done
cargo deb --target=x86_64-unknown-linux-musl -p ffplayout-api
mv ./target/x86_64-unknown-linux-musl/debian/ffplayout-api_${version}_amd64.deb .
cargo deb --target=x86_64-unknown-linux-musl -p ffplayout --manifest-path=ffplayout-engine/Cargo.toml -o ffplayout_${version}_amd64.deb
cargo generate-rpm --target=x86_64-unknown-linux-musl -p ffplayout-engine -o ffplayout-${version}-1.x86_64.rpm
cargo generate-rpm --target=x86_64-unknown-linux-musl -p ffplayout-api
mv ./target/x86_64-unknown-linux-musl/generate-rpm/ffplayout-api-${version}-1.x86_64.rpm .

171
docs/api.md Normal file
View File

@ -0,0 +1,171 @@
#### Possible endpoints
Run the API thru the systemd service, or like:
```BASH
ffpapi -l 127.0.0.1:8080
```
For all endpoints an (Bearer) authentication is required.\
`{id}` represent the channel id, and at default is 1.
#### Login is
- **POST** `/auth/login/`\
JSON Data: `{"username": "<USER>", "password": "<PASS>"}`\
JSON Response:
```JSON
{
"message": "login correct!",
"status": 200,
"data": {
"id": 1,
"email": "user@example.org",
"username": "user",
"token": "<TOKEN>"
}
}
```
From here on all request **must** contain the authorization header:\
`"Authorization: Bearer <TOKEN>"`
#### User
- **PUT** `/api/user/{user id}`\
JSON Data: `{"email": "<EMAIL>", "password": "<PASS>"}`
- **POST** `/api/user/`\
JSON Data:
```JSON
{
"email": "<EMAIL>",
"username": "<USER>",
"password": "<PASS>",
"role_id": 1
}
```
#### API Settings
- **GET** `/api/settings/{id}`\
HEADER:
Response is in JSON format
- **PATCH** `/api/settings/{id}`\
JSON Data:
```JSON
"id": 1,
"channel_name": "Channel 1",
"preview_url": "http://localhost/live/stream.m3u8",
"config_path": "/etc/ffplayout/ffplayout.yml",
"extra_extensions": ".jpg,.jpeg,.png"
```
#### Playout Config
- **GET** `/api/playout/config/{id}`\
Response is in JSON format
- **PUT** `/api/playout/config/{id}`\
JSON Data: `{ <CONFIG DATA> }`\
Response is in TEXT format
#### Text Presets
- **GET** `/api/presets/`\
Response is in JSON format
- **PUT** `/api/playout/presets/{id}`\
JSON Data:
```JSON
{
"name": "<PRESET NAME>",
"text": "<TEXT>",
"x": "<X>",
"y": "<Y>",
"fontsize": 24,
"line_spacing": 4,
"fontcolor": "#ffffff",
"box": 1,
"boxcolor": "#000000",
"boxborderw": 4,
"alpha": "<alpha>"
}
```
Response is in TEXT format
- **POST** `/api/playout/presets/`\
JSON Data: `{ <PRESET DATA> }`\
Response is in TEXT format
#### Playout Process Control
- **POST** `/api/control/{id}/text/`¸
JSON Data:
```JSON
{
"text": "Hello from ffplayout",
"x": "(w-text_w)/2",
"y": "(h-text_h)/2",
"fontsize": "24",
"line_spacing": "4",
"fontcolor": "#ffffff",
"box": "1",
"boxcolor": "#000000",
"boxborderw": "4",
"alpha": "1.0"
}
```
Response is in TEXT format
- **POST** `api/control/{id}/playout/next/`\
Response is in TEXT format
- **POST** `api/control/{id}/playout/back/`\
Response is in TEXT format
- **POST** `api/control/{id}/playout/reset/`\
Response is in TEXT format
- **GET** `/api/control/{id}/media/current/`\
Response is in JSON format
- **GET** `/api/control/{id}/media/next/`\
Response is in JSON format
- **GET** `/api/control/{id}/media/last/`\
Response is in JSON format
#### Playlist Operations
- **GET** `/api/playlist/{id}/2022-06-20`\
Response is in JSON format
- **POST** `/api/playlist/1/`\
JSON Data: `{ <PLAYLIST DATA> }`\
Response is in TEXT format
- **GET** `/api/playlist/{id}/generate/2022-06-20`\
Response is in JSON format
- **DELETE** `/api/playlist/{id}/2022-06-20`\
Response is in TEXT format
#### File Operations
- **GET** `/api/file/{id}/browse/`\
Response is in JSON format
- **POST** `/api/file/{id}/move/`\
JSON Data: `{"source": "<SOURCE>", "target": "<TARGET>"}`\
Response is in JSON format
- **DELETE** `/api/file/{id}/remove/`\
JSON Data: `{"source": "<SOURCE>"}`\
Response is in JSON format
- **POST** `/file/{id}/upload/`\
Multipart Form: `name=<TARGET PATH>, filename=<FILENAME>`\
Response is in TEXT format

View File

@ -38,42 +38,3 @@ sqlx = { version = "0.5", features = [
"runtime-actix-native-tls",
"sqlite"
] }
[target.x86_64-unknown-linux-musl.dependencies]
openssl = { version = "0.10", features = ["vendored"] }
[[bin]]
name = "ffpapi"
path = "src/main.rs"
# DEBIAN DEB PACKAGE
[package.metadata.deb]
name = "ffplayout-api"
priority = "optional"
section = "net"
license-file = ["../LICENSE", "0"]
depends = ""
suggests = "ffmpeg"
copyright = "Copyright (c) 2022, Jonathan Baecker. All rights reserved."
conf-files = ["/etc/ffplayout/ffplayout.yml"]
assets = [
[
"../target/x86_64-unknown-linux-musl/release/ffpapi",
"/usr/bin/ffpapi",
"755"
],
["README.md", "/usr/share/doc/ffplayout/README", "644"],
]
maintainer-scripts = "debian/"
systemd-units = { enable = false, unit-scripts = "unit" }
# REHL RPM PACKAGE
[package.metadata.generate-rpm]
name = "ffplayout-api"
license = "GPL-3.0"
assets = [
{ source = "../target/x86_64-unknown-linux-musl/release/ffpapi", dest = "/usr/bin/ffpapi", mode = "755" },
{ source = "unit/ffpapi.service", dest = "/lib/systemd/system/ffpapi.service", mode = "644" },
{ source = "README.md", dest = "/usr/share/doc/ffplayout/README", mode = "644", doc = true },
{ source = "../LICENSE", dest = "/usr/share/doc/ffplayout/LICENSE", mode = "644" },
]

View File

@ -1,7 +1,7 @@
**ffplayout-api**
================
ffplayout-api (ffpapi) is a on strict REST API for ffplayout. It makes it possible to control the engine, read and manipulate the config, save playlist, etc.
ffplayout-api (ffpapi) is a non strict REST API for ffplayout. It makes it possible to control the engine, read and manipulate the config, save playlist, etc.
To be able to use the API it is necessary to initialize the settings database first. To do that, run:
@ -21,168 +21,4 @@ Then run the API thru the systemd service, or like:
ffpapi -l 127.0.0.1:8080
```
### Possible endpoints
For all endpoints an (Bearer) authentication is required.\
`{id}` represent the channel id, and at default is 1.
#### Login is
- **POST** `/auth/login/`\
JSON Data: `{"username": "<USER>", "password": "<PASS>"}`\
JSON Response:
```JSON
{
"message": "login correct!",
"status": 200,
"data": {
"id": 1,
"email": "user@example.org",
"username": "user",
"token": "<TOKEN>"
}
}
```
From here on all request **must** contain the authorization header:\
`"Authorization: Bearer <TOKEN>"`
#### User
- **PUT** `/api/user/{user id}`\
JSON Data: `{"email": "<EMAIL>", "password": "<PASS>"}`
- **POST** `/api/user/`\
JSON Data:
```JSON
{
"email": "<EMAIL>",
"username": "<USER>",
"password": "<PASS>",
"role_id": 1
}
```
#### API Settings
- **GET** `/api/settings/{id}`\
HEADER:
Response is in JSON format
- **PATCH** `/api/settings/{id}`\
JSON Data:
```JSON
"id": 1,
"channel_name": "Channel 1",
"preview_url": "http://localhost/live/stream.m3u8",
"config_path": "/etc/ffplayout/ffplayout.yml",
"extra_extensions": ".jpg,.jpeg,.png"
```
#### Playout Config
- **GET** `/api/playout/config/{id}`\
Response is in JSON format
- **PUT** `/api/playout/config/{id}`\
JSON Data: `{ <CONFIG DATA> }`\
Response is in TEXT format
#### Text Presets
- **GET** `/api/presets/`\
Response is in JSON format
- **PUT** `/api/playout/presets/{id}`\
JSON Data:
```JSON
{
"name": "<PRESET NAME>",
"text": "<TEXT>",
"x": "<X>",
"y": "<Y>",
"fontsize": 24,
"line_spacing": 4,
"fontcolor": "#ffffff",
"box": 1,
"boxcolor": "#000000",
"boxborderw": 4,
"alpha": "<alpha>"
}
```
Response is in TEXT format
- **POST** `/api/playout/presets/`\
JSON Data: `{ <PRESET DATA> }`\
Response is in TEXT format
#### Playout Process Control
- **POST** `/api/control/{id}/text/`¸
JSON Data:
```JSON
{
"text": "Hello from ffplayout",
"x": "(w-text_w)/2",
"y": "(h-text_h)/2",
"fontsize": "24",
"line_spacing": "4",
"fontcolor": "#ffffff",
"box": "1",
"boxcolor": "#000000",
"boxborderw": "4",
"alpha": "1.0"
}
```
Response is in TEXT format
- **POST** `api/control/{id}/playout/next/`\
Response is in TEXT format
- **POST** `api/control/{id}/playout/back/`\
Response is in TEXT format
- **POST** `api/control/{id}/playout/reset/`\
Response is in TEXT format
- **GET** `/api/control/{id}/media/current/`\
Response is in JSON format
- **GET** `/api/control/{id}/media/next/`\
Response is in JSON format
- **GET** `/api/control/{id}/media/last/`\
Response is in JSON format
#### Playlist Operations
- **GET** `/api/playlist/{id}/2022-06-20`\
Response is in JSON format
- **POST** `/api/playlist/1/`\
JSON Data: `{ <PLAYLIST DATA> }`\
Response is in TEXT format
- **GET** `/api/playlist/{id}/generate/2022-06-20`\
Response is in JSON format
- **DELETE** `/api/playlist/{id}/2022-06-20`\
Response is in TEXT format
#### File Operations
- **GET** `/api/file/{id}/browse/`\
Response is in JSON format
- **POST** `/api/file/{id}/move/`\
JSON Data: `{"source": "<SOURCE>", "target": "<TARGET>"}`\
Response is in JSON format
- **DELETE** `/api/file/{id}/remove/`\
JSON Data: `{"source": "<SOURCE>"}`\
Response is in JSON format
- **POST** `/file/{id}/upload/`\
Multipart Form: `name=<TARGET PATH>, filename=<FILENAME>`\
Response is in TEXT format
**For possible endpoints read: [api endpoints](/docs/api.md)**

View File

@ -1,15 +1,15 @@
[package]
name = "ffplayout-engine"
name = "ffplayout"
description = "24/7 playout based on rust and ffmpeg"
license = "GPL-3.0"
authors = ["Jonathan Baecker jonbae77@gmail.com"]
readme = "README.md"
version = "0.9.9"
version = "0.10.0"
edition = "2021"
[dependencies]
ffplayout-lib = { path = "../lib" }
chrono = { git = "https://github.com/sbrocket/chrono", branch = "parse-error-kind-public" }
chrono = { git = "https://github.com/chronotope/chrono.git" }
clap = { version = "3.2", features = ["derive"] }
crossbeam-channel = "0.5"
faccess = "0.2"
@ -44,7 +44,7 @@ path = "src/main.rs"
# DEBIAN DEB PACKAGE
[package.metadata.deb]
name = "ffplayout-engine"
name = "ffplayout"
priority = "optional"
section = "net"
license-file = ["../LICENSE", "0"]
@ -53,26 +53,34 @@ suggests = "ffmpeg"
copyright = "Copyright (c) 2022, Jonathan Baecker. All rights reserved."
conf-files = ["/etc/ffplayout/ffplayout.yml"]
assets = [
[
"../target/x86_64-unknown-linux-musl/release/ffpapi",
"/usr/bin/ffpapi",
"755"
],
[
"../target/x86_64-unknown-linux-musl/release/ffplayout",
"/usr/bin/ffplayout",
"755"
],
["../assets/ffpapi.service", "/lib/systemd/system/ffpapi.service", "644"],
["../assets/ffplayout.yml", "/etc/ffplayout/ffplayout.yml", "644"],
["../assets/logo.png", "/usr/share/ffplayout/logo.png", "644"],
["../README.md", "/usr/share/doc/ffplayout/README", "644"],
]
maintainer-scripts = "debian/"
systemd-units = { enable = false, unit-scripts = "unit" }
maintainer-scripts = "../debian/"
systemd-units = { enable = false, unit-scripts = "../assets" }
# REHL RPM PACKAGE
[package.metadata.generate-rpm]
name = "ffplayout-engine"
name = "ffplayout"
license = "GPL-3.0"
assets = [
{ source = "../target/x86_64-unknown-linux-musl/release/ffpapi", dest = "/usr/bin/ffpapi", mode = "755" },
{ source = "../target/x86_64-unknown-linux-musl/release/ffplayout", dest = "/usr/bin/ffplayout", mode = "755" },
{ source = "../assets/ffplayout.yml", dest = "/etc/ffplayout/ffplayout.yml", mode = "644", config = true },
{ source = "unit/ffplayout.service", dest = "/lib/systemd/system/ffplayout.service", mode = "644" },
{ source = "../assets/ffpapi.service", dest = "/lib/systemd/system/ffpapi.service", mode = "644" },
{ source = "../assets/ffplayout.service", dest = "/lib/systemd/system/ffplayout.service", mode = "644" },
{ source = "../README.md", dest = "/usr/share/doc/ffplayout/README", mode = "644", doc = true },
{ source = "../LICENSE", dest = "/usr/share/doc/ffplayout/LICENSE", mode = "644" },
{ source = "../assets/logo.png", dest = "/usr/share/ffplayout/logo.png", mode = "644" },