refractor code
This commit is contained in:
parent
529de7bba8
commit
07b1bd30ae
91
Cargo.lock
generated
91
Cargo.lock
generated
@ -315,9 +315,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "async-global-executor"
|
||||
version = "2.1.0"
|
||||
version = "2.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fd8b508d585e01084059b60f06ade4cb7415cd2e4084b71dd1cb44e7d3fb9880"
|
||||
checksum = "5262ed948da60dd8956c6c5aca4d4163593dddb7b32d73267c93dab7b2e98940"
|
||||
dependencies = [
|
||||
"async-channel",
|
||||
"async-executor",
|
||||
@ -325,6 +325,7 @@ dependencies = [
|
||||
"async-lock",
|
||||
"blocking",
|
||||
"futures-lite",
|
||||
"num_cpus",
|
||||
"once_cell",
|
||||
]
|
||||
|
||||
@ -588,6 +589,7 @@ dependencies = [
|
||||
"libc",
|
||||
"num-integer",
|
||||
"num-traits",
|
||||
"time 0.1.44",
|
||||
"winapi 0.3.9",
|
||||
]
|
||||
|
||||
@ -605,9 +607,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "3.2.5"
|
||||
version = "3.2.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d53da17d37dba964b9b3ecb5c5a1f193a2762c700e6829201e645b9381c99dc7"
|
||||
checksum = "9f1fe12880bae935d142c8702d500c63a4e8634b6c3c57ad72bf978fc7b6249a"
|
||||
dependencies = [
|
||||
"atty",
|
||||
"bitflags",
|
||||
@ -622,9 +624,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "clap_derive"
|
||||
version = "3.2.5"
|
||||
version = "3.2.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c11d40217d16aee8508cc8e5fde8b4ff24639758608e5374e731b53f85749fb9"
|
||||
checksum = "ed6db9e867166a43a53f7199b5e4d1f522a1e5bd626654be263c999ce59df39a"
|
||||
dependencies = [
|
||||
"heck",
|
||||
"proc-macro-error",
|
||||
@ -635,9 +637,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "clap_lex"
|
||||
version = "0.2.2"
|
||||
version = "0.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5538cd660450ebeb4234cfecf8f2284b844ffc4c50531e66d584ad5b91293613"
|
||||
checksum = "87eba3c8c7f42ef17f6c659fc7416d0f4758cd3e58861ee63c5fa4a4dde649e4"
|
||||
dependencies = [
|
||||
"os_str_bytes",
|
||||
]
|
||||
@ -977,26 +979,21 @@ dependencies = [
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ffplayout-engine"
|
||||
version = "0.9.9"
|
||||
name = "ffplayout-api"
|
||||
version = "0.3.0"
|
||||
dependencies = [
|
||||
"actix-web",
|
||||
"actix-web-grants",
|
||||
"actix-web-httpauth",
|
||||
"argon2",
|
||||
"chrono 0.4.19 (git+https://github.com/sbrocket/chrono?branch=parse-error-kind-public)",
|
||||
"chrono 0.4.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"clap",
|
||||
"crossbeam-channel 0.5.5",
|
||||
"derive_more",
|
||||
"faccess",
|
||||
"ffplayout-lib",
|
||||
"ffprobe",
|
||||
"file-rotate",
|
||||
"futures",
|
||||
"jsonrpc-http-server",
|
||||
"jsonwebtoken",
|
||||
"lettre",
|
||||
"log",
|
||||
"notify",
|
||||
"once_cell",
|
||||
"openssl",
|
||||
"rand 0.8.5",
|
||||
@ -1007,14 +1004,68 @@ dependencies = [
|
||||
"serde",
|
||||
"serde_json",
|
||||
"serde_yaml",
|
||||
"shlex",
|
||||
"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)",
|
||||
"clap",
|
||||
"crossbeam-channel 0.5.5",
|
||||
"faccess",
|
||||
"ffplayout-lib",
|
||||
"ffprobe",
|
||||
"file-rotate",
|
||||
"futures",
|
||||
"jsonrpc-http-server",
|
||||
"lettre",
|
||||
"log",
|
||||
"notify",
|
||||
"openssl",
|
||||
"rand 0.8.5",
|
||||
"regex",
|
||||
"reqwest",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"serde_yaml",
|
||||
"shlex",
|
||||
"simplelog",
|
||||
"time 0.3.10",
|
||||
"walkdir",
|
||||
"zeromq",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ffplayout-lib"
|
||||
version = "0.9.9"
|
||||
dependencies = [
|
||||
"chrono 0.4.19 (git+https://github.com/sbrocket/chrono?branch=parse-error-kind-public)",
|
||||
"crossbeam-channel 0.5.5",
|
||||
"faccess",
|
||||
"ffprobe",
|
||||
"file-rotate",
|
||||
"futures",
|
||||
"jsonrpc-http-server",
|
||||
"lettre",
|
||||
"log",
|
||||
"notify",
|
||||
"once_cell",
|
||||
"openssl",
|
||||
"rand 0.8.5",
|
||||
"regex",
|
||||
"reqwest",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"serde_yaml",
|
||||
"shlex",
|
||||
"simplelog",
|
||||
"time 0.3.10",
|
||||
"walkdir",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ffprobe"
|
||||
version = "0.3.2"
|
||||
@ -1474,9 +1525,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "1.9.0"
|
||||
version = "1.9.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6c6392766afd7964e2531940894cffe4bd8d7d17dbc3c1c4857040fd4b33bdb3"
|
||||
checksum = "10a35a97730320ffe8e2d410b5d3b69279b98d2c14bdb8b70ea89ecf7888d41e"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"hashbrown 0.12.1",
|
||||
|
108
Cargo.toml
108
Cargo.toml
@ -1,108 +1,12 @@
|
||||
[package]
|
||||
name = "ffplayout-engine"
|
||||
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"
|
||||
edition = "2021"
|
||||
default-run = "ffplayout"
|
||||
[workspace]
|
||||
|
||||
[dependencies]
|
||||
actix-web = "4"
|
||||
actix-web-grants = "3"
|
||||
actix-web-httpauth = "0.6"
|
||||
argon2 = "0.4"
|
||||
chrono = { git = "https://github.com/sbrocket/chrono", branch = "parse-error-kind-public" }
|
||||
clap = { version = "3.2", features = ["derive"] }
|
||||
crossbeam-channel = "0.5"
|
||||
derive_more = "0.99"
|
||||
faccess = "0.2"
|
||||
ffprobe = "0.3"
|
||||
file-rotate = { git = "https://github.com/Ploppz/file-rotate.git", branch = "timestamp-parse-fix" }
|
||||
futures = "0.3"
|
||||
jsonrpc-http-server = "18.0"
|
||||
jsonwebtoken = "8"
|
||||
lettre = "0.10.0-rc.7"
|
||||
log = "0.4"
|
||||
notify = "4.0"
|
||||
once_cell = "1.10"
|
||||
rand = "0.8"
|
||||
rand_core = { version = "0.6", features = ["std"] }
|
||||
relative-path = "1.6"
|
||||
regex = "1"
|
||||
reqwest = { version = "0.11", features = ["blocking", "json"] }
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_json = "1.0"
|
||||
serde_yaml = "0.8"
|
||||
shlex = "1.1"
|
||||
simplelog = { version = "^0.12", features = ["paris"] }
|
||||
sqlx = { version = "0.5", features = [
|
||||
"chrono",
|
||||
"runtime-actix-native-tls",
|
||||
"sqlite"
|
||||
] }
|
||||
time = { version = "0.3", features = ["formatting", "macros"] }
|
||||
walkdir = "2"
|
||||
zeromq = { git = "https://github.com/zeromq/zmq.rs.git", default-features = false, features = [
|
||||
"async-std-runtime",
|
||||
"tcp-transport"
|
||||
] }
|
||||
|
||||
[target.x86_64-unknown-linux-musl.dependencies]
|
||||
openssl = { version = "0.10", features = ["vendored"] }
|
||||
|
||||
[[bin]]
|
||||
name = "ffplayout"
|
||||
path = "src/main.rs"
|
||||
|
||||
[[bin]]
|
||||
name = "ffpapi"
|
||||
path = "src/bin/ffpapi.rs"
|
||||
members = [
|
||||
"ffplayout-api",
|
||||
"ffplayout-engine",
|
||||
"lib",
|
||||
]
|
||||
|
||||
[profile.release]
|
||||
opt-level = 3
|
||||
strip = true
|
||||
lto = true
|
||||
|
||||
# DEBIAN DEB PACKAGE
|
||||
[package.metadata.deb]
|
||||
name = "ffplayout-engine"
|
||||
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/ffplayout",
|
||||
"/usr/bin/ffplayout",
|
||||
"755"
|
||||
],
|
||||
[
|
||||
"target/x86_64-unknown-linux-musl/release/ffpapi",
|
||||
"/usr/bin/ffpapi",
|
||||
"755"
|
||||
],
|
||||
["assets/ffplayout.yml", "/etc/ffplayout/ffplayout.yml", "644"],
|
||||
["assets/logo.png", "/usr/share/ffplayout/logo.png", "644"],
|
||||
["README.md", "/usr/share/doc/ffplayout-engine/README", "644"],
|
||||
]
|
||||
maintainer-scripts = "debian/"
|
||||
systemd-units = { enable = false, unit-scripts = "assets" }
|
||||
|
||||
# REHL RPM PACKAGE
|
||||
[package.metadata.generate-rpm]
|
||||
name = "ffplayout-engine"
|
||||
license = "GPL-3.0"
|
||||
assets = [
|
||||
{ source = "target/x86_64-unknown-linux-musl/release/ffplayout", dest = "/usr/bin/ffplayout", mode = "755" },
|
||||
{ source = "target/x86_64-unknown-linux-musl/release/ffpapi", dest = "/usr/bin/ffpapi", mode = "755" },
|
||||
{ source = "assets/ffplayout.yml", dest = "/etc/ffplayout/ffplayout.yml", mode = "644", config = true },
|
||||
{ source = "assets/ffplayout-engine.service", dest = "/lib/systemd/system/ffplayout-engine.service", mode = "644" },
|
||||
{ source = "README.md", dest = "/usr/share/doc/ffplayout-engine/README", mode = "644", doc = true },
|
||||
{ source = "LICENSE", dest = "/usr/share/doc/ffplayout-engine/LICENSE", mode = "644" },
|
||||
{ source = "assets/logo.png", dest = "/usr/share/ffplayout/logo.png", mode = "644" },
|
||||
]
|
||||
|
100
build_all.sh
Executable file
100
build_all.sh
Executable file
@ -0,0 +1,100 @@
|
||||
#!/usr/bin/bash
|
||||
|
||||
|
||||
targets=("x86_64-unknown-linux-musl" "x86_64-pc-windows-gnu" "x86_64-apple-darwin" "aarch64-apple-darwin")
|
||||
|
||||
IFS="= "
|
||||
while read -r name value; do
|
||||
if [[ $name == "version" ]]; then
|
||||
version=${value//\"/}
|
||||
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 ""
|
||||
|
||||
for target in "${targets[@]}"; do
|
||||
echo "compile static for $target"
|
||||
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"
|
||||
fi
|
||||
|
||||
cargo build --release --target=$target --bin ffpapi
|
||||
|
||||
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"
|
||||
fi
|
||||
|
||||
cargo build --release --target=$target --bin ffpapi
|
||||
|
||||
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
|
||||
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 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 .
|
@ -1,56 +0,0 @@
|
||||
#!/usr/bin/bash
|
||||
|
||||
|
||||
targets=("x86_64-unknown-linux-musl" "x86_64-pc-windows-gnu" "x86_64-apple-darwin" "aarch64-apple-darwin")
|
||||
|
||||
IFS="= "
|
||||
while read -r name value; do
|
||||
if [[ $name == "version" ]]; then
|
||||
version=${value//\"/}
|
||||
fi
|
||||
done < 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
|
||||
|
||||
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 .
|
||||
cp ./target/${target}/release/ffpapi.exe .
|
||||
zip -r "ffplayout-engine-v${version}_${target}.zip" assets docs LICENSE README.md ffplayout.exe ffpapi.exe -x *.db
|
||||
rm -f ffplayout.exe ffpapi.exe
|
||||
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 .
|
||||
cp ./target/${target}/release/ffpapi .
|
||||
tar -czvf "ffplayout-engine-v${version}_${target}.tar.gz" --exclude='*.db' assets docs LICENSE README.md ffplayout ffpapi
|
||||
rm -f ffplayout ffpapi
|
||||
fi
|
||||
|
||||
echo ""
|
||||
done
|
||||
|
||||
echo "Create debian package"
|
||||
echo ""
|
||||
|
||||
cargo deb --target=x86_64-unknown-linux-musl
|
||||
mv ./target/x86_64-unknown-linux-musl/debian/ffplayout-engine_${version}_amd64.deb .
|
||||
|
||||
echo ""
|
||||
echo "Create rhel package"
|
||||
echo ""
|
||||
|
||||
cargo generate-rpm --target=x86_64-unknown-linux-musl
|
||||
mv ./target/x86_64-unknown-linux-musl/generate-rpm/ffplayout-engine-${version}-1.x86_64.rpm .
|
76
ffplayout-api/Cargo.toml
Normal file
76
ffplayout-api/Cargo.toml
Normal file
@ -0,0 +1,76 @@
|
||||
[package]
|
||||
name = "ffplayout-api"
|
||||
description = "Rest API for ffplayout"
|
||||
license = "GPL-3.0"
|
||||
authors = ["Jonathan Baecker jonbae77@gmail.com"]
|
||||
readme = "README.md"
|
||||
version = "0.3.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
ffplayout-lib = { path = "../lib" }
|
||||
actix-web = "4"
|
||||
actix-web-grants = "3"
|
||||
actix-web-httpauth = "0.6"
|
||||
argon2 = "0.4"
|
||||
chrono = "0.4"
|
||||
clap = { version = "3.2", features = ["derive"] }
|
||||
derive_more = "0.99"
|
||||
faccess = "0.2"
|
||||
ffprobe = "0.3"
|
||||
jsonwebtoken = "8"
|
||||
log = "0.4"
|
||||
once_cell = "1.10"
|
||||
rand = "0.8"
|
||||
rand_core = { version = "0.6", features = ["std"] }
|
||||
relative-path = "1.6"
|
||||
regex = "1"
|
||||
reqwest = { version = "0.11", features = ["blocking", "json"] }
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_json = "1.0"
|
||||
serde_yaml = "0.8"
|
||||
simplelog = { version = "^0.12", features = ["paris"] }
|
||||
sqlx = { version = "0.5", features = [
|
||||
"chrono",
|
||||
"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" },
|
||||
]
|
2
ffplayout-api/README.md
Normal file
2
ffplayout-api/README.md
Normal file
@ -0,0 +1,2 @@
|
||||
**ffplayout-api**
|
||||
================
|
@ -8,22 +8,23 @@ use actix_web_httpauth::middleware::HttpAuthentication;
|
||||
use clap::Parser;
|
||||
use simplelog::*;
|
||||
|
||||
use ffplayout_engine::{
|
||||
api::{
|
||||
args_parse::Args,
|
||||
auth,
|
||||
models::LoginUser,
|
||||
routes::{
|
||||
add_preset, add_user, del_playlist, file_browser, gen_playlist, get_playlist,
|
||||
get_playout_config, get_presets, get_settings, jump_to_last, jump_to_next, login,
|
||||
media_current, media_last, media_next, patch_settings, reset_playout, save_playlist,
|
||||
send_text_message, update_playout_config, update_preset, update_user,
|
||||
},
|
||||
utils::{db_path, init_config, run_args, Role},
|
||||
pub mod utils;
|
||||
|
||||
use utils::{
|
||||
args_parse::Args,
|
||||
auth, db_path, init_config,
|
||||
models::LoginUser,
|
||||
routes::{
|
||||
add_preset, add_user, del_playlist, file_browser, gen_playlist, get_playlist,
|
||||
get_playout_config, get_presets, get_settings, jump_to_last, jump_to_next, login,
|
||||
media_current, media_last, media_next, patch_settings, reset_playout, save_playlist,
|
||||
send_text_message, update_playout_config, update_preset, update_user,
|
||||
},
|
||||
utils::{init_logging, PlayoutConfig},
|
||||
run_args, Role,
|
||||
};
|
||||
|
||||
use ffplayout_lib::utils::{init_logging, PlayoutConfig};
|
||||
|
||||
async fn validator(req: ServiceRequest, credentials: BearerAuth) -> Result<ServiceRequest, Error> {
|
||||
// We just get permissions from JWT
|
||||
let claims = auth::decode_jwt(credentials.token()).await?;
|
@ -2,9 +2,7 @@ use clap::Parser;
|
||||
|
||||
#[derive(Parser, Debug, Clone)]
|
||||
#[clap(version,
|
||||
name = "ffpapi",
|
||||
version = "0.3.0",
|
||||
about = "ffplayout REST API",
|
||||
about = "REST API for ffplayout",
|
||||
long_about = None)]
|
||||
pub struct Args {
|
||||
#[clap(short, long, help = "Listen on IP:PORT, like: 127.0.0.1:8080")]
|
@ -4,7 +4,7 @@ use chrono::{Duration, Utc};
|
||||
use jsonwebtoken::{self, DecodingKey, EncodingKey, Header, Validation};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::api::utils::GlobalSettings;
|
||||
use crate::utils::GlobalSettings;
|
||||
|
||||
// Token lifetime
|
||||
const JWT_EXPIRATION_DAYS: i64 = 7;
|
@ -7,7 +7,7 @@ use reqwest::{
|
||||
use serde::{Deserialize, Serialize};
|
||||
use simplelog::*;
|
||||
|
||||
use crate::api::{errors::ServiceError, utils::playout_config};
|
||||
use crate::utils::{errors::ServiceError, playout_config};
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize, Clone)]
|
||||
struct RpcObj<T> {
|
@ -4,8 +4,8 @@ use std::{fs, path::PathBuf};
|
||||
|
||||
use simplelog::*;
|
||||
|
||||
use crate::api::{errors::ServiceError, utils::playout_config};
|
||||
use crate::utils::file_extension;
|
||||
use crate::utils::{errors::ServiceError, playout_config};
|
||||
use ffplayout_lib::utils::file_extension;
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize, Clone)]
|
||||
pub struct PathObject {
|
@ -7,10 +7,10 @@ use rand::{distributions::Alphanumeric, Rng};
|
||||
use simplelog::*;
|
||||
use sqlx::{migrate::MigrateDatabase, sqlite::SqliteQueryResult, Pool, Sqlite, SqlitePool};
|
||||
|
||||
use crate::api::utils::GlobalSettings;
|
||||
use crate::api::{
|
||||
use crate::utils::{
|
||||
db_path,
|
||||
models::{Settings, TextPreset, User},
|
||||
utils::db_path,
|
||||
GlobalSettings,
|
||||
};
|
||||
|
||||
#[derive(Debug, sqlx::FromRow)]
|
@ -4,13 +4,23 @@ use faccess::PathExt;
|
||||
use once_cell::sync::OnceCell;
|
||||
use simplelog::*;
|
||||
|
||||
use crate::api::{
|
||||
pub mod args_parse;
|
||||
pub mod auth;
|
||||
pub mod control;
|
||||
pub mod errors;
|
||||
pub mod files;
|
||||
pub mod handles;
|
||||
pub mod models;
|
||||
pub mod playlist;
|
||||
pub mod routes;
|
||||
|
||||
use crate::utils::{
|
||||
args_parse::Args,
|
||||
errors::ServiceError,
|
||||
handles::{db_add_user, db_get_settings, db_global, db_init},
|
||||
models::{Settings, User},
|
||||
};
|
||||
use crate::utils::PlayoutConfig;
|
||||
use ffplayout_lib::utils::PlayoutConfig;
|
||||
|
||||
#[derive(PartialEq, Clone)]
|
||||
pub enum Role {
|
@ -6,8 +6,8 @@ use std::{
|
||||
|
||||
use simplelog::*;
|
||||
|
||||
use crate::api::{errors::ServiceError, utils::playout_config};
|
||||
use crate::utils::{generate_playlist as playlist_generator, JsonPlaylist};
|
||||
use crate::utils::{errors::ServiceError, playout_config};
|
||||
use ffplayout_lib::utils::{generate_playlist as playlist_generator, JsonPlaylist};
|
||||
|
||||
fn json_reader(path: &PathBuf) -> Result<JsonPlaylist, Error> {
|
||||
let f = File::options().read(true).write(false).open(&path)?;
|
@ -9,22 +9,20 @@ use argon2::{
|
||||
use serde::Serialize;
|
||||
use simplelog::*;
|
||||
|
||||
use crate::{
|
||||
api::{
|
||||
auth::{create_jwt, Claims},
|
||||
control::{control_state, media_info, send_message},
|
||||
errors::ServiceError,
|
||||
files::{browser, PathObject},
|
||||
handles::{
|
||||
db_add_preset, db_add_user, db_get_presets, db_get_settings, db_login, db_role,
|
||||
db_update_preset, db_update_settings, db_update_user,
|
||||
},
|
||||
models::{LoginUser, Settings, TextPreset, User},
|
||||
playlist::{delete_playlist, generate_playlist, read_playlist, write_playlist},
|
||||
utils::{read_playout_config, Role},
|
||||
use crate::utils::{
|
||||
auth::{create_jwt, Claims},
|
||||
control::{control_state, media_info, send_message},
|
||||
errors::ServiceError,
|
||||
files::{browser, PathObject},
|
||||
handles::{
|
||||
db_add_preset, db_add_user, db_get_presets, db_get_settings, db_login, db_role,
|
||||
db_update_preset, db_update_settings, db_update_user,
|
||||
},
|
||||
utils::{JsonPlaylist, PlayoutConfig},
|
||||
models::{LoginUser, Settings, TextPreset, User},
|
||||
playlist::{delete_playlist, generate_playlist, read_playlist, write_playlist},
|
||||
read_playout_config, Role,
|
||||
};
|
||||
use ffplayout_lib::utils::{JsonPlaylist, PlayoutConfig};
|
||||
|
||||
#[derive(Serialize)]
|
||||
struct ResponseObj<T> {
|
79
ffplayout-engine/Cargo.toml
Normal file
79
ffplayout-engine/Cargo.toml
Normal file
@ -0,0 +1,79 @@
|
||||
[package]
|
||||
name = "ffplayout-engine"
|
||||
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"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
ffplayout-lib = { path = "../lib" }
|
||||
chrono = { git = "https://github.com/sbrocket/chrono", branch = "parse-error-kind-public" }
|
||||
clap = { version = "3.2", features = ["derive"] }
|
||||
crossbeam-channel = "0.5"
|
||||
faccess = "0.2"
|
||||
ffprobe = "0.3"
|
||||
file-rotate = { git = "https://github.com/Ploppz/file-rotate.git", branch = "timestamp-parse-fix" }
|
||||
futures = "0.3"
|
||||
jsonrpc-http-server = "18.0"
|
||||
lettre = "0.10.0-rc.7"
|
||||
log = "0.4"
|
||||
notify = "4.0"
|
||||
rand = "0.8"
|
||||
regex = "1"
|
||||
reqwest = { version = "0.11", features = ["blocking", "json"] }
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_json = "1.0"
|
||||
serde_yaml = "0.8"
|
||||
shlex = "1.1"
|
||||
simplelog = { version = "^0.12", features = ["paris"] }
|
||||
time = { version = "0.3", features = ["formatting", "macros"] }
|
||||
walkdir = "2"
|
||||
zeromq = { git = "https://github.com/zeromq/zmq.rs.git", default-features = false, features = [
|
||||
"async-std-runtime",
|
||||
"tcp-transport"
|
||||
] }
|
||||
|
||||
[target.x86_64-unknown-linux-musl.dependencies]
|
||||
openssl = { version = "0.10", features = ["vendored"] }
|
||||
|
||||
[[bin]]
|
||||
name = "ffplayout"
|
||||
path = "src/main.rs"
|
||||
|
||||
# DEBIAN DEB PACKAGE
|
||||
[package.metadata.deb]
|
||||
name = "ffplayout-engine"
|
||||
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/ffplayout",
|
||||
"/usr/bin/ffplayout",
|
||||
"755"
|
||||
],
|
||||
["../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" }
|
||||
|
||||
# REHL RPM PACKAGE
|
||||
[package.metadata.generate-rpm]
|
||||
name = "ffplayout-engine"
|
||||
license = "GPL-3.0"
|
||||
assets = [
|
||||
{ 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 = "../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" },
|
||||
]
|
2
ffplayout-engine/README.md
Normal file
2
ffplayout-engine/README.md
Normal file
@ -0,0 +1,2 @@
|
||||
**ffplayout-engine**
|
||||
================
|
76
ffplayout-engine/src/input/folder.rs
Normal file
76
ffplayout-engine/src/input/folder.rs
Normal file
@ -0,0 +1,76 @@
|
||||
use std::{
|
||||
path::Path,
|
||||
sync::{
|
||||
atomic::{AtomicBool, Ordering},
|
||||
mpsc::channel,
|
||||
{Arc, Mutex},
|
||||
},
|
||||
thread::sleep,
|
||||
time::Duration,
|
||||
};
|
||||
|
||||
use notify::{
|
||||
DebouncedEvent::{Create, Remove, Rename},
|
||||
{watcher, RecursiveMode, Watcher},
|
||||
};
|
||||
use simplelog::*;
|
||||
|
||||
use ffplayout_lib::utils::{Media, PlayoutConfig};
|
||||
|
||||
/// Create a watcher, which monitor file changes.
|
||||
/// When a change is register, update the current file list.
|
||||
/// This makes it possible, to play infinitely and and always new files to it.
|
||||
pub fn watchman(
|
||||
config: PlayoutConfig,
|
||||
is_terminated: Arc<AtomicBool>,
|
||||
sources: Arc<Mutex<Vec<Media>>>,
|
||||
) {
|
||||
let (tx, rx) = channel();
|
||||
|
||||
let path = config.storage.path;
|
||||
|
||||
if !Path::new(&path).exists() {
|
||||
error!("Folder path not exists: '{path}'");
|
||||
panic!("Folder path not exists: '{path}'");
|
||||
}
|
||||
|
||||
let mut watcher = watcher(tx, Duration::from_secs(1)).unwrap();
|
||||
watcher.watch(path, RecursiveMode::Recursive).unwrap();
|
||||
|
||||
while !is_terminated.load(Ordering::SeqCst) {
|
||||
if let Ok(res) = rx.try_recv() {
|
||||
match res {
|
||||
Create(new_path) => {
|
||||
let index = sources.lock().unwrap().len();
|
||||
let media = Media::new(index, new_path.display().to_string(), false);
|
||||
|
||||
sources.lock().unwrap().push(media);
|
||||
info!("Create new file: <b><magenta>{new_path:?}</></b>");
|
||||
}
|
||||
Remove(old_path) => {
|
||||
sources
|
||||
.lock()
|
||||
.unwrap()
|
||||
.retain(|x| x.source != old_path.display().to_string());
|
||||
info!("Remove file: <b><magenta>{old_path:?}</></b>");
|
||||
}
|
||||
Rename(old_path, new_path) => {
|
||||
let index = sources
|
||||
.lock()
|
||||
.unwrap()
|
||||
.iter()
|
||||
.position(|x| *x.source == old_path.display().to_string())
|
||||
.unwrap();
|
||||
|
||||
let media = Media::new(index, new_path.display().to_string(), false);
|
||||
sources.lock().unwrap()[index] = media;
|
||||
|
||||
info!("Rename file: <b><magenta>{old_path:?}</></b> to <b><magenta>{new_path:?}</></b>");
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
||||
sleep(Duration::from_secs(5));
|
||||
}
|
||||
}
|
@ -8,9 +8,9 @@ use std::{
|
||||
use crossbeam_channel::Sender;
|
||||
use simplelog::*;
|
||||
|
||||
use crate::filter::ingest_filter::filter_cmd;
|
||||
use crate::utils::{format_log_line, Ingest, PlayoutConfig, ProcessControl};
|
||||
use crate::vec_strings;
|
||||
use ffplayout_lib::filter::ingest_filter::filter_cmd;
|
||||
use ffplayout_lib::utils::{format_log_line, Ingest, PlayoutConfig, ProcessControl};
|
||||
use ffplayout_lib::vec_strings;
|
||||
|
||||
pub fn log_line(line: String, level: &str) {
|
||||
if line.contains("[info]") && level.to_lowercase() == "info" {
|
@ -9,16 +9,18 @@ use std::{
|
||||
|
||||
use simplelog::*;
|
||||
|
||||
use crate::utils::{Media, PlayoutConfig, PlayoutStatus};
|
||||
use ffplayout_lib::utils::{Media, PlayoutConfig, PlayoutStatus};
|
||||
|
||||
pub mod folder;
|
||||
pub mod ingest;
|
||||
pub mod playlist;
|
||||
|
||||
pub use folder::{watchman, FolderSource};
|
||||
pub use folder::watchman;
|
||||
pub use ingest::ingest_server;
|
||||
pub use playlist::CurrentProgram;
|
||||
|
||||
use ffplayout_lib::utils::folder::FolderSource;
|
||||
|
||||
/// Create a source iterator from playlist, or from folder.
|
||||
pub fn source_generator(
|
||||
config: PlayoutConfig,
|
@ -10,7 +10,7 @@ use std::{
|
||||
use serde_json::json;
|
||||
use simplelog::*;
|
||||
|
||||
use crate::utils::{
|
||||
use ffplayout_lib::utils::{
|
||||
check_sync, gen_dummy, get_delta, get_sec, is_close, is_remote, json_serializer::read_json,
|
||||
modified_time, seek_and_length, valid_source, Media, PlayoutConfig, PlayoutStatus, DUMMY_LEN,
|
||||
};
|
@ -10,13 +10,23 @@ use serde::{Deserialize, Serialize};
|
||||
use serde_json::json;
|
||||
use simplelog::*;
|
||||
|
||||
use ffplayout_engine::{
|
||||
pub mod input;
|
||||
pub mod output;
|
||||
pub mod rpc;
|
||||
// #[cfg(test)]
|
||||
// mod tests;
|
||||
pub mod utils;
|
||||
|
||||
use utils::{arg_parse::get_args, get_config};
|
||||
|
||||
use crate::{
|
||||
output::{player, write_hls},
|
||||
rpc::json_rpc_server,
|
||||
utils::{
|
||||
generate_playlist, get_args, init_logging, send_mail, validate_ffmpeg, PlayerControl,
|
||||
PlayoutConfig, PlayoutStatus, ProcessControl,
|
||||
},
|
||||
};
|
||||
|
||||
use ffplayout_lib::utils::{
|
||||
generate_playlist, init_logging, send_mail, validate_ffmpeg, PlayerControl, PlayoutStatus,
|
||||
ProcessControl,
|
||||
};
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
@ -59,7 +69,7 @@ fn status_file(stat_file: &str, playout_stat: &PlayoutStatus) {
|
||||
|
||||
fn main() {
|
||||
let args = get_args();
|
||||
let config = PlayoutConfig::new(Some(args));
|
||||
let config = get_config(args);
|
||||
let config_clone = config.clone();
|
||||
let play_control = PlayerControl::new();
|
||||
let playout_stat = PlayoutStatus::new();
|
@ -2,9 +2,9 @@ use std::process::{self, Command, Stdio};
|
||||
|
||||
use simplelog::*;
|
||||
|
||||
use crate::filter::v_drawtext;
|
||||
use crate::utils::{Media, PlayoutConfig};
|
||||
use crate::vec_strings;
|
||||
use ffplayout_lib::filter::v_drawtext;
|
||||
use ffplayout_lib::utils::{Media, PlayoutConfig};
|
||||
use ffplayout_lib::vec_strings;
|
||||
|
||||
/// Desktop Output
|
||||
///
|
@ -27,13 +27,13 @@ use std::{
|
||||
|
||||
use simplelog::*;
|
||||
|
||||
use crate::filter::ingest_filter::filter_cmd;
|
||||
use crate::input::{ingest::log_line, source_generator};
|
||||
use crate::utils::{
|
||||
use ffplayout_lib::filter::ingest_filter::filter_cmd;
|
||||
use ffplayout_lib::utils::{
|
||||
prepare_output_cmd, sec_to_time, stderr_reader, Decoder, Ingest, PlayerControl, PlayoutConfig,
|
||||
PlayoutStatus, ProcessControl,
|
||||
};
|
||||
use crate::vec_strings;
|
||||
use ffplayout_lib::vec_strings;
|
||||
|
||||
/// Ingest Server for HLS
|
||||
fn ingest_to_hls_server(
|
@ -16,11 +16,11 @@ mod stream;
|
||||
pub use hls::write_hls;
|
||||
|
||||
use crate::input::{ingest_server, source_generator};
|
||||
use crate::utils::{
|
||||
use ffplayout_lib::utils::{
|
||||
sec_to_time, stderr_reader, Decoder, PlayerControl, PlayoutConfig, PlayoutStatus,
|
||||
ProcessControl,
|
||||
};
|
||||
use crate::vec_strings;
|
||||
use ffplayout_lib::vec_strings;
|
||||
|
||||
/// Player
|
||||
///
|
@ -2,9 +2,9 @@ use std::process::{self, Command, Stdio};
|
||||
|
||||
use simplelog::*;
|
||||
|
||||
use crate::filter::v_drawtext;
|
||||
use crate::utils::{prepare_output_cmd, Media, PlayoutConfig};
|
||||
use crate::vec_strings;
|
||||
use ffplayout_lib::filter::v_drawtext;
|
||||
use ffplayout_lib::utils::{prepare_output_cmd, Media, PlayoutConfig};
|
||||
use ffplayout_lib::vec_strings;
|
||||
|
||||
/// Streaming Output
|
||||
///
|
@ -11,7 +11,7 @@ use jsonrpc_http_server::{
|
||||
use serde_json::{json, Map};
|
||||
use simplelog::*;
|
||||
|
||||
use crate::utils::{
|
||||
use ffplayout_lib::utils::{
|
||||
get_delta, get_filter_from_json, get_sec, sec_to_time, write_status, Media, PlayerControl,
|
||||
PlayoutConfig, PlayoutStatus, ProcessControl,
|
||||
};
|
@ -3,12 +3,10 @@ use std::{
|
||||
time::Duration,
|
||||
};
|
||||
|
||||
mod utils;
|
||||
|
||||
#[cfg(test)]
|
||||
use crate::output::player;
|
||||
#[cfg(test)]
|
||||
use crate::utils::*;
|
||||
use ffplayout_lib::utils::*;
|
||||
#[cfg(test)]
|
||||
use simplelog::*;
|
||||
|
64
ffplayout-engine/src/utils/mod.rs
Normal file
64
ffplayout-engine/src/utils/mod.rs
Normal file
@ -0,0 +1,64 @@
|
||||
use std::path::Path;
|
||||
|
||||
pub mod arg_parse;
|
||||
|
||||
pub use arg_parse::Args;
|
||||
use ffplayout_lib::utils::{time_to_sec, PlayoutConfig};
|
||||
|
||||
pub fn get_config(args: Args) -> PlayoutConfig {
|
||||
let mut config = PlayoutConfig::new(args.config);
|
||||
|
||||
if let Some(gen) = args.generate {
|
||||
config.general.generate = Some(gen);
|
||||
}
|
||||
|
||||
if let Some(log_path) = args.log {
|
||||
if Path::new(&log_path).is_dir() {
|
||||
config.logging.log_to_file = true;
|
||||
}
|
||||
config.logging.log_path = log_path;
|
||||
}
|
||||
|
||||
if let Some(playlist) = args.playlist {
|
||||
config.playlist.path = playlist;
|
||||
}
|
||||
|
||||
if let Some(mode) = args.play_mode {
|
||||
config.processing.mode = mode;
|
||||
}
|
||||
|
||||
if let Some(folder) = args.folder {
|
||||
config.storage.path = folder;
|
||||
config.processing.mode = "folder".into();
|
||||
}
|
||||
|
||||
if let Some(start) = args.start {
|
||||
config.playlist.day_start = start.clone();
|
||||
config.playlist.start_sec = Some(time_to_sec(&start));
|
||||
}
|
||||
|
||||
if let Some(length) = args.length {
|
||||
config.playlist.length = length.clone();
|
||||
|
||||
if length.contains(':') {
|
||||
config.playlist.length_sec = Some(time_to_sec(&length));
|
||||
} else {
|
||||
config.playlist.length_sec = Some(86400.0);
|
||||
}
|
||||
}
|
||||
|
||||
if args.infinit {
|
||||
config.playlist.infinit = args.infinit;
|
||||
}
|
||||
|
||||
if let Some(output) = args.output {
|
||||
config.out.mode = output;
|
||||
}
|
||||
|
||||
if let Some(volume) = args.volume {
|
||||
config.processing.volume = volume;
|
||||
}
|
||||
|
||||
config
|
||||
}
|
||||
// Read command line arguments, and override the config with them.
|
34
lib/Cargo.toml
Normal file
34
lib/Cargo.toml
Normal file
@ -0,0 +1,34 @@
|
||||
[package]
|
||||
name = "ffplayout-lib"
|
||||
description = "Library for ffplayout"
|
||||
license = "GPL-3.0"
|
||||
authors = ["Jonathan Baecker jonbae77@gmail.com"]
|
||||
readme = "README.md"
|
||||
version = "0.9.9"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
chrono = { git = "https://github.com/sbrocket/chrono", branch = "parse-error-kind-public" }
|
||||
crossbeam-channel = "0.5"
|
||||
faccess = "0.2"
|
||||
ffprobe = "0.3"
|
||||
file-rotate = { git = "https://github.com/Ploppz/file-rotate.git", branch = "timestamp-parse-fix" }
|
||||
futures = "0.3"
|
||||
jsonrpc-http-server = "18.0"
|
||||
lettre = "0.10.0-rc.7"
|
||||
log = "0.4"
|
||||
notify = "4.0"
|
||||
once_cell = "1.10"
|
||||
rand = "0.8"
|
||||
regex = "1"
|
||||
reqwest = { version = "0.11", features = ["blocking", "json"] }
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_json = "1.0"
|
||||
serde_yaml = "0.8"
|
||||
shlex = "1.1"
|
||||
simplelog = { version = "^0.12", features = ["paris"] }
|
||||
time = { version = "0.3", features = ["formatting", "macros"] }
|
||||
walkdir = "2"
|
||||
|
||||
[target.x86_64-unknown-linux-musl.dependencies]
|
||||
openssl = { version = "0.10", features = ["vendored"] }
|
@ -1,12 +1,9 @@
|
||||
extern crate log;
|
||||
extern crate simplelog;
|
||||
|
||||
pub mod api;
|
||||
pub mod filter;
|
||||
pub mod input;
|
||||
pub mod macros;
|
||||
pub mod output;
|
||||
pub mod rpc;
|
||||
pub mod utils;
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
pub mod utils;
|
@ -8,7 +8,7 @@ use std::{
|
||||
use serde::{Deserialize, Serialize};
|
||||
use shlex::split;
|
||||
|
||||
use crate::utils::{free_tcp_socket, time_to_sec, Args};
|
||||
use crate::utils::{free_tcp_socket, time_to_sec};
|
||||
use crate::vec_strings;
|
||||
|
||||
/// Global Config
|
||||
@ -168,10 +168,10 @@ pub struct Out {
|
||||
|
||||
impl PlayoutConfig {
|
||||
/// Read config from YAML file, and set some extra config values.
|
||||
pub fn new(args: Option<Args>) -> Self {
|
||||
pub fn new(cfg_path: Option<String>) -> Self {
|
||||
let mut config_path = PathBuf::from("/etc/ffplayout/ffplayout.yml");
|
||||
|
||||
if let Some(cfg) = args.clone().and_then(|a| a.config) {
|
||||
if let Some(cfg) = cfg_path {
|
||||
config_path = PathBuf::from(cfg);
|
||||
}
|
||||
|
||||
@ -259,61 +259,6 @@ impl PlayoutConfig {
|
||||
config.text.node_pos = None;
|
||||
}
|
||||
|
||||
// Read command line arguments, and override the config with them.
|
||||
|
||||
if let Some(arg) = args {
|
||||
if let Some(gen) = arg.generate {
|
||||
config.general.generate = Some(gen);
|
||||
}
|
||||
|
||||
if let Some(log_path) = arg.log {
|
||||
if Path::new(&log_path).is_dir() {
|
||||
config.logging.log_to_file = true;
|
||||
}
|
||||
config.logging.log_path = log_path;
|
||||
}
|
||||
|
||||
if let Some(playlist) = arg.playlist {
|
||||
config.playlist.path = playlist;
|
||||
}
|
||||
|
||||
if let Some(mode) = arg.play_mode {
|
||||
config.processing.mode = mode;
|
||||
}
|
||||
|
||||
if let Some(folder) = arg.folder {
|
||||
config.storage.path = folder;
|
||||
config.processing.mode = "folder".into();
|
||||
}
|
||||
|
||||
if let Some(start) = arg.start {
|
||||
config.playlist.day_start = start.clone();
|
||||
config.playlist.start_sec = Some(time_to_sec(&start));
|
||||
}
|
||||
|
||||
if let Some(length) = arg.length {
|
||||
config.playlist.length = length.clone();
|
||||
|
||||
if length.contains(':') {
|
||||
config.playlist.length_sec = Some(time_to_sec(&length));
|
||||
} else {
|
||||
config.playlist.length_sec = Some(86400.0);
|
||||
}
|
||||
}
|
||||
|
||||
if arg.infinit {
|
||||
config.playlist.infinit = arg.infinit;
|
||||
}
|
||||
|
||||
if let Some(output) = arg.output {
|
||||
config.out.mode = output;
|
||||
}
|
||||
|
||||
if let Some(volume) = arg.volume {
|
||||
config.processing.volume = volume;
|
||||
}
|
||||
}
|
||||
|
||||
config
|
||||
}
|
||||
}
|
@ -2,18 +2,11 @@ use std::{
|
||||
path::Path,
|
||||
process::exit,
|
||||
sync::{
|
||||
atomic::{AtomicBool, AtomicUsize, Ordering},
|
||||
mpsc::channel,
|
||||
atomic::{AtomicUsize, Ordering},
|
||||
{Arc, Mutex},
|
||||
},
|
||||
thread::sleep,
|
||||
time::Duration,
|
||||
};
|
||||
|
||||
use notify::{
|
||||
DebouncedEvent::{Create, Remove, Rename},
|
||||
{watcher, RecursiveMode, Watcher},
|
||||
};
|
||||
use rand::{seq::SliceRandom, thread_rng};
|
||||
use simplelog::*;
|
||||
use walkdir::WalkDir;
|
||||
@ -153,61 +146,3 @@ impl Iterator for FolderSource {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a watcher, which monitor file changes.
|
||||
/// When a change is register, update the current file list.
|
||||
/// This makes it possible, to play infinitely and and always new files to it.
|
||||
pub fn watchman(
|
||||
config: PlayoutConfig,
|
||||
is_terminated: Arc<AtomicBool>,
|
||||
sources: Arc<Mutex<Vec<Media>>>,
|
||||
) {
|
||||
let (tx, rx) = channel();
|
||||
|
||||
let path = config.storage.path;
|
||||
|
||||
if !Path::new(&path).exists() {
|
||||
error!("Folder path not exists: '{path}'");
|
||||
panic!("Folder path not exists: '{path}'");
|
||||
}
|
||||
|
||||
let mut watcher = watcher(tx, Duration::from_secs(1)).unwrap();
|
||||
watcher.watch(path, RecursiveMode::Recursive).unwrap();
|
||||
|
||||
while !is_terminated.load(Ordering::SeqCst) {
|
||||
if let Ok(res) = rx.try_recv() {
|
||||
match res {
|
||||
Create(new_path) => {
|
||||
let index = sources.lock().unwrap().len();
|
||||
let media = Media::new(index, new_path.display().to_string(), false);
|
||||
|
||||
sources.lock().unwrap().push(media);
|
||||
info!("Create new file: <b><magenta>{new_path:?}</></b>");
|
||||
}
|
||||
Remove(old_path) => {
|
||||
sources
|
||||
.lock()
|
||||
.unwrap()
|
||||
.retain(|x| x.source != old_path.display().to_string());
|
||||
info!("Remove file: <b><magenta>{old_path:?}</></b>");
|
||||
}
|
||||
Rename(old_path, new_path) => {
|
||||
let index = sources
|
||||
.lock()
|
||||
.unwrap()
|
||||
.iter()
|
||||
.position(|x| *x.source == old_path.display().to_string())
|
||||
.unwrap();
|
||||
|
||||
let media = Media::new(index, new_path.display().to_string(), false);
|
||||
sources.lock().unwrap()[index] = media;
|
||||
|
||||
info!("Rename file: <b><magenta>{old_path:?}</></b> to <b><magenta>{new_path:?}</></b>");
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
||||
sleep(Duration::from_secs(5));
|
||||
}
|
||||
}
|
@ -17,7 +17,7 @@ use std::{
|
||||
use chrono::{Duration, NaiveDate};
|
||||
use simplelog::*;
|
||||
|
||||
use crate::input::FolderSource;
|
||||
use super::folder::FolderSource;
|
||||
use crate::utils::{json_serializer::JsonPlaylist, time_to_sec, Media, PlayoutConfig};
|
||||
|
||||
/// Generate a vector with dates, from given range.
|
@ -18,15 +18,14 @@ use serde::{Deserialize, Serialize};
|
||||
use serde_json::json;
|
||||
use simplelog::*;
|
||||
|
||||
mod arg_parse;
|
||||
pub mod config;
|
||||
pub mod controller;
|
||||
pub mod folder;
|
||||
mod generator;
|
||||
pub mod json_serializer;
|
||||
mod json_validate;
|
||||
mod logging;
|
||||
|
||||
pub use arg_parse::{get_args, Args};
|
||||
pub use config::{self as playout_config, PlayoutConfig};
|
||||
pub use controller::{PlayerControl, PlayoutStatus, ProcessControl, ProcessUnit::*};
|
||||
pub use generator::generate_playlist;
|
@ -1,10 +0,0 @@
|
||||
pub mod args_parse;
|
||||
pub mod auth;
|
||||
pub mod control;
|
||||
pub mod errors;
|
||||
pub mod files;
|
||||
pub mod handles;
|
||||
pub mod models;
|
||||
pub mod playlist;
|
||||
pub mod routes;
|
||||
pub mod utils;
|
Loading…
Reference in New Issue
Block a user