unify init process, simplify argument names and model values
This commit is contained in:
parent
7463512fa6
commit
2f5911fd35
1
.vscode/settings.json
vendored
1
.vscode/settings.json
vendored
@ -61,6 +61,7 @@
|
|||||||
"reqwest",
|
"reqwest",
|
||||||
"rsplit",
|
"rsplit",
|
||||||
"rustls",
|
"rustls",
|
||||||
|
"sqlite",
|
||||||
"sqlx",
|
"sqlx",
|
||||||
"starttls",
|
"starttls",
|
||||||
"tokio",
|
"tokio",
|
||||||
|
@ -12,7 +12,7 @@ COPY <<-EOT /run.sh
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
if [ ! -f /db/ffplayout.db ]; then
|
if [ ! -f /db/ffplayout.db ]; then
|
||||||
ffplayout -u admin -p admin -m contact@example.com --storage "/tv-media" --playlist "/playlists" --public "/public" --log-path "/logging" --shared-storage
|
ffplayout -i -u admin -p admin -m contact@example.com --storage "/tv-media" --playlist "/playlists" --public "/public" --log-path "/logging" --shared
|
||||||
fi
|
fi
|
||||||
|
|
||||||
/usr/bin/ffplayout -l "0.0.0.0:8787"
|
/usr/bin/ffplayout -l "0.0.0.0:8787"
|
||||||
|
@ -14,7 +14,7 @@ COPY <<-EOT /run.sh
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
if [ ! -f /db/ffplayout.db ]; then
|
if [ ! -f /db/ffplayout.db ]; then
|
||||||
ffplayout -u admin -p admin -m contact@example.com --storage "/tv-media" --playlist "/playlists" --public "/public" --log-path "/logging" --shared-storage
|
ffplayout -i -u admin -p admin -m contact@example.com --storage "/tv-media" --playlist "/playlists" --public "/public" --log-path "/logging" --shared
|
||||||
fi
|
fi
|
||||||
|
|
||||||
/usr/bin/ffplayout -l "0.0.0.0:8787"
|
/usr/bin/ffplayout -l "0.0.0.0:8787"
|
||||||
|
@ -204,7 +204,7 @@ COPY <<-EOT /run.sh
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
if [ ! -f /db/ffplayout.db ]; then
|
if [ ! -f /db/ffplayout.db ]; then
|
||||||
ffplayout -u admin -p admin -m contact@example.com --storage "/tv-media" --playlist "/playlists" --public "/public" --log-path "/logging" --shared-storage
|
ffplayout -i -u admin -p admin -m contact@example.com --storage "/tv-media" --playlist "/playlists" --public "/public" --log-path "/logging" --shared
|
||||||
fi
|
fi
|
||||||
|
|
||||||
/usr/bin/ffplayout -l "0.0.0.0:8787"
|
/usr/bin/ffplayout -l "0.0.0.0:8787"
|
||||||
|
@ -1,23 +1,19 @@
|
|||||||
### Install ffplayout
|
### Install ffplayout
|
||||||
|
|
||||||
|
**Note:** This is the official and supported way.
|
||||||
|
|
||||||
ffplayout provides ***.deb** and ***.rpm** packages, which makes it more easy to install and use, but there is still some steps to do.
|
ffplayout provides ***.deb** and ***.rpm** packages, which makes it more easy to install and use, but there is still some steps to do.
|
||||||
|
|
||||||
1. download the latest ffplayout from [release](https://github.com/ffplayout/ffplayout/releases/latest) page and place the package in the **/tmp** folder.
|
1. download the latest ffplayout from [release](https://github.com/ffplayout/ffplayout/releases/latest) page and place the package in the **/tmp** folder.
|
||||||
2. install it with `apt install /tmp/ffplayout_<VERSION>_amd64.deb`
|
2. install it with `apt install /tmp/ffplayout_<VERSION>_amd64.deb`
|
||||||
3. install ffmpeg/ffprobe, or compile and copy it to **/usr/local/bin/**
|
3. install ffmpeg/ffprobe, or compile and copy it to **/usr/local/bin/**
|
||||||
4. activate systemd services:
|
4. initial defaults and add global admin user: `sudo -u ffpu ffplayout -i`
|
||||||
- `systemctl enable ffplayout`
|
5. use a revers proxy for SSL, Port is **8787**.
|
||||||
5. initial defaults and add global admin user:
|
6. login with your browser, address without proxy would be: **http://[IP ADDRESS]:8787**
|
||||||
- `sudo -u ffpu ffplayout -i`
|
|
||||||
6. start ffplayout:
|
|
||||||
- `systemctl start ffplayout`
|
|
||||||
7. use a revers proxy for SSL, Port is **8787**.
|
|
||||||
8. login with your browser, address without proxy would be: **http://[IP ADDRESS]:8787**
|
|
||||||
|
|
||||||
Default location for playlists and media files are: **/var/lib/ffplayout/**.
|
|
||||||
|
|
||||||
### Manual Install
|
### Manual Install
|
||||||
-----
|
|
||||||
|
**Note:** This is for advanced user only.
|
||||||
|
|
||||||
- install ffmpeg/ffprobe, or compile and copy it to **/usr/local/bin/**
|
- install ffmpeg/ffprobe, or compile and copy it to **/usr/local/bin/**
|
||||||
- download the latest archive from [release](https://github.com/ffplayout/ffplayout/releases/latest) page
|
- download the latest archive from [release](https://github.com/ffplayout/ffplayout/releases/latest) page
|
||||||
|
@ -135,7 +135,7 @@ assets = [
|
|||||||
],
|
],
|
||||||
]
|
]
|
||||||
maintainer-scripts = "../debian/"
|
maintainer-scripts = "../debian/"
|
||||||
systemd-units = { enable = false, unit-scripts = "../assets" }
|
systemd-units = { enable = true, unit-scripts = "../assets" }
|
||||||
|
|
||||||
[package.metadata.deb.variants.arm64]
|
[package.metadata.deb.variants.arm64]
|
||||||
assets = [
|
assets = [
|
||||||
|
@ -490,9 +490,9 @@ async fn patch_channel(
|
|||||||
if !role.has_authority(&Role::GlobalAdmin) {
|
if !role.has_authority(&Role::GlobalAdmin) {
|
||||||
let channel = handles::select_channel(&pool, &id).await?;
|
let channel = handles::select_channel(&pool, &id).await?;
|
||||||
|
|
||||||
data.hls_path = channel.hls_path;
|
data.public = channel.public;
|
||||||
data.playlist_path = channel.playlist_path;
|
data.playlists = channel.playlists;
|
||||||
data.storage_path = channel.storage_path;
|
data.storage = channel.storage;
|
||||||
}
|
}
|
||||||
|
|
||||||
handles::update_channel(&pool, *id, data).await?;
|
handles::update_channel(&pool, *id, data).await?;
|
||||||
@ -669,13 +669,13 @@ async fn update_playout_config(
|
|||||||
user: web::ReqData<UserMeta>,
|
user: web::ReqData<UserMeta>,
|
||||||
) -> Result<impl Responder, ServiceError> {
|
) -> Result<impl Responder, ServiceError> {
|
||||||
let manager = controllers.lock().unwrap().get(*id).unwrap();
|
let manager = controllers.lock().unwrap().get(*id).unwrap();
|
||||||
let p = manager.channel.lock().unwrap().storage_path.clone();
|
let p = manager.channel.lock().unwrap().storage.clone();
|
||||||
let storage_path = Path::new(&p);
|
let storage = Path::new(&p);
|
||||||
let config_id = manager.config.lock().unwrap().general.id;
|
let config_id = manager.config.lock().unwrap().general.id;
|
||||||
|
|
||||||
let (_, _, logo) = norm_abs_path(storage_path, &data.processing.logo)?;
|
let (_, _, logo) = norm_abs_path(storage, &data.processing.logo)?;
|
||||||
let (_, _, filler) = norm_abs_path(storage_path, &data.storage.filler)?;
|
let (_, _, filler) = norm_abs_path(storage, &data.storage.filler)?;
|
||||||
let (_, _, font) = norm_abs_path(storage_path, &data.text.font)?;
|
let (_, _, font) = norm_abs_path(storage, &data.text.font)?;
|
||||||
|
|
||||||
data.processing.logo = logo;
|
data.processing.logo = logo;
|
||||||
data.storage.filler = filler;
|
data.storage.filler = filler;
|
||||||
@ -1064,14 +1064,14 @@ pub async fn gen_playlist(
|
|||||||
) -> Result<impl Responder, ServiceError> {
|
) -> Result<impl Responder, ServiceError> {
|
||||||
let manager = controllers.lock().unwrap().get(params.0).unwrap();
|
let manager = controllers.lock().unwrap().get(params.0).unwrap();
|
||||||
manager.config.lock().unwrap().general.generate = Some(vec![params.1.clone()]);
|
manager.config.lock().unwrap().general.generate = Some(vec![params.1.clone()]);
|
||||||
let storage_path = manager.config.lock().unwrap().channel.storage_path.clone();
|
let storage = manager.config.lock().unwrap().channel.storage.clone();
|
||||||
|
|
||||||
if let Some(obj) = data {
|
if let Some(obj) = data {
|
||||||
if let Some(paths) = &obj.paths {
|
if let Some(paths) = &obj.paths {
|
||||||
let mut path_list = vec![];
|
let mut path_list = vec![];
|
||||||
|
|
||||||
for path in paths {
|
for path in paths {
|
||||||
let (p, _, _) = norm_abs_path(&storage_path, path)?;
|
let (p, _, _) = norm_abs_path(&storage, path)?;
|
||||||
|
|
||||||
path_list.push(p);
|
path_list.push(p);
|
||||||
}
|
}
|
||||||
@ -1306,9 +1306,9 @@ async fn get_file(
|
|||||||
let id: i32 = req.match_info().query("id").parse()?;
|
let id: i32 = req.match_info().query("id").parse()?;
|
||||||
let manager = controllers.lock().unwrap().get(id).unwrap();
|
let manager = controllers.lock().unwrap().get(id).unwrap();
|
||||||
let config = manager.config.lock().unwrap();
|
let config = manager.config.lock().unwrap();
|
||||||
let storage_path = config.channel.storage_path.clone();
|
let storage = config.channel.storage.clone();
|
||||||
let file_path = req.match_info().query("filename");
|
let file_path = req.match_info().query("filename");
|
||||||
let (path, _, _) = norm_abs_path(&storage_path, file_path)?;
|
let (path, _, _) = norm_abs_path(&storage, file_path)?;
|
||||||
let file = actix_files::NamedFile::open(path)?;
|
let file = actix_files::NamedFile::open(path)?;
|
||||||
|
|
||||||
Ok(file
|
Ok(file
|
||||||
@ -1339,7 +1339,7 @@ async fn get_public(
|
|||||||
{
|
{
|
||||||
let manager = controllers.lock().unwrap().get(id).unwrap();
|
let manager = controllers.lock().unwrap().get(id).unwrap();
|
||||||
let config = manager.config.lock().unwrap();
|
let config = manager.config.lock().unwrap();
|
||||||
config.channel.hls_path.join(public)
|
config.channel.public.join(public)
|
||||||
} else {
|
} else {
|
||||||
public_path()
|
public_path()
|
||||||
}
|
}
|
||||||
|
@ -36,7 +36,8 @@ pub async fn db_migrate(conn: &Pool<Sqlite>) -> Result<(), Box<dyn std::error::E
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub async fn select_global(conn: &Pool<Sqlite>) -> Result<GlobalSettings, sqlx::Error> {
|
pub async fn select_global(conn: &Pool<Sqlite>) -> Result<GlobalSettings, sqlx::Error> {
|
||||||
let query = "SELECT id, secret, logging_path, playlist_root, public_root, storage_root, shared_storage FROM global WHERE id = 1";
|
let query =
|
||||||
|
"SELECT id, secret, logs, playlists, public, storage, shared FROM global WHERE id = 1";
|
||||||
|
|
||||||
sqlx::query_as(query).fetch_one(conn).await
|
sqlx::query_as(query).fetch_one(conn).await
|
||||||
}
|
}
|
||||||
@ -45,15 +46,15 @@ pub async fn update_global(
|
|||||||
conn: &Pool<Sqlite>,
|
conn: &Pool<Sqlite>,
|
||||||
global: GlobalSettings,
|
global: GlobalSettings,
|
||||||
) -> Result<SqliteQueryResult, sqlx::Error> {
|
) -> Result<SqliteQueryResult, sqlx::Error> {
|
||||||
let query = "UPDATE global SET logging_path = $2, playlist_root = $3, public_root = $4, storage_root = $5, shared_storage = $6 WHERE id = 1";
|
let query = "UPDATE global SET logs = $2, playlists = $3, public = $4, storage = $5, shared = $6 WHERE id = 1";
|
||||||
|
|
||||||
sqlx::query(query)
|
sqlx::query(query)
|
||||||
.bind(global.id)
|
.bind(global.id)
|
||||||
.bind(global.logging_path)
|
.bind(global.logs)
|
||||||
.bind(global.playlist_root)
|
.bind(global.playlists)
|
||||||
.bind(global.public_root)
|
.bind(global.public)
|
||||||
.bind(global.storage_root)
|
.bind(global.storage)
|
||||||
.bind(global.shared_storage)
|
.bind(global.shared)
|
||||||
.execute(conn)
|
.execute(conn)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
@ -73,7 +74,7 @@ pub async fn select_related_channels(
|
|||||||
) -> Result<Vec<Channel>, sqlx::Error> {
|
) -> Result<Vec<Channel>, sqlx::Error> {
|
||||||
let query = match user_id {
|
let query = match user_id {
|
||||||
Some(id) => format!(
|
Some(id) => format!(
|
||||||
"SELECT c.id, c.name, c.preview_url, c.extra_extensions, c.active, c.hls_path, c.playlist_path, c.storage_path, c.last_date, c.time_shift FROM channels c
|
"SELECT c.id, c.name, c.preview_url, c.extra_extensions, c.active, c.public, c.playlists, c.storage, c.last_date, c.time_shift FROM channels c
|
||||||
left join user_channels uc on uc.channel_id = c.id
|
left join user_channels uc on uc.channel_id = c.id
|
||||||
left join user u on u.id = uc.user_id
|
left join user u on u.id = uc.user_id
|
||||||
WHERE u.id = {id} ORDER BY c.id ASC;"
|
WHERE u.id = {id} ORDER BY c.id ASC;"
|
||||||
@ -110,16 +111,16 @@ pub async fn update_channel(
|
|||||||
channel: Channel,
|
channel: Channel,
|
||||||
) -> Result<SqliteQueryResult, sqlx::Error> {
|
) -> Result<SqliteQueryResult, sqlx::Error> {
|
||||||
let query =
|
let query =
|
||||||
"UPDATE channels SET name = $2, preview_url = $3, extra_extensions = $4, hls_path = $5, playlist_path = $6, storage_path = $7 WHERE id = $1";
|
"UPDATE channels SET name = $2, preview_url = $3, extra_extensions = $4, public = $5, playlists = $6, storage = $7 WHERE id = $1";
|
||||||
|
|
||||||
sqlx::query(query)
|
sqlx::query(query)
|
||||||
.bind(id)
|
.bind(id)
|
||||||
.bind(channel.name)
|
.bind(channel.name)
|
||||||
.bind(channel.preview_url)
|
.bind(channel.preview_url)
|
||||||
.bind(channel.extra_extensions)
|
.bind(channel.extra_extensions)
|
||||||
.bind(channel.hls_path)
|
.bind(channel.public)
|
||||||
.bind(channel.playlist_path)
|
.bind(channel.playlists)
|
||||||
.bind(channel.storage_path)
|
.bind(channel.storage)
|
||||||
.execute(conn)
|
.execute(conn)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
@ -151,14 +152,14 @@ pub async fn update_player(
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub async fn insert_channel(conn: &Pool<Sqlite>, channel: Channel) -> Result<Channel, sqlx::Error> {
|
pub async fn insert_channel(conn: &Pool<Sqlite>, channel: Channel) -> Result<Channel, sqlx::Error> {
|
||||||
let query = "INSERT INTO channels (name, preview_url, extra_extensions, hls_path, playlist_path, storage_path) VALUES($1, $2, $3, $4, $5, $6)";
|
let query = "INSERT INTO channels (name, preview_url, extra_extensions, public, playlists, storage) VALUES($1, $2, $3, $4, $5, $6)";
|
||||||
let result = sqlx::query(query)
|
let result = sqlx::query(query)
|
||||||
.bind(channel.name)
|
.bind(channel.name)
|
||||||
.bind(channel.preview_url)
|
.bind(channel.preview_url)
|
||||||
.bind(channel.extra_extensions)
|
.bind(channel.extra_extensions)
|
||||||
.bind(channel.hls_path)
|
.bind(channel.public)
|
||||||
.bind(channel.playlist_path)
|
.bind(channel.playlists)
|
||||||
.bind(channel.storage_path)
|
.bind(channel.storage)
|
||||||
.execute(conn)
|
.execute(conn)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
|
@ -16,11 +16,11 @@ use crate::utils::config::PlayoutConfig;
|
|||||||
pub struct GlobalSettings {
|
pub struct GlobalSettings {
|
||||||
pub id: i32,
|
pub id: i32,
|
||||||
pub secret: Option<String>,
|
pub secret: Option<String>,
|
||||||
pub logging_path: String,
|
pub logs: String,
|
||||||
pub playlist_root: String,
|
pub playlists: String,
|
||||||
pub public_root: String,
|
pub public: String,
|
||||||
pub storage_root: String,
|
pub storage: String,
|
||||||
pub shared_storage: bool,
|
pub shared: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GlobalSettings {
|
impl GlobalSettings {
|
||||||
@ -32,11 +32,11 @@ impl GlobalSettings {
|
|||||||
Err(_) => GlobalSettings {
|
Err(_) => GlobalSettings {
|
||||||
id: 0,
|
id: 0,
|
||||||
secret: None,
|
secret: None,
|
||||||
logging_path: String::new(),
|
logs: String::new(),
|
||||||
playlist_root: String::new(),
|
playlists: String::new(),
|
||||||
public_root: String::new(),
|
public: String::new(),
|
||||||
storage_root: String::new(),
|
storage: String::new(),
|
||||||
shared_storage: false,
|
shared: false,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -61,9 +61,9 @@ pub struct Channel {
|
|||||||
pub preview_url: String,
|
pub preview_url: String,
|
||||||
pub extra_extensions: String,
|
pub extra_extensions: String,
|
||||||
pub active: bool,
|
pub active: bool,
|
||||||
pub hls_path: String,
|
pub public: String,
|
||||||
pub playlist_path: String,
|
pub playlists: String,
|
||||||
pub storage_path: String,
|
pub storage: String,
|
||||||
pub last_date: Option<String>,
|
pub last_date: Option<String>,
|
||||||
pub time_shift: f64,
|
pub time_shift: f64,
|
||||||
|
|
||||||
|
@ -243,7 +243,7 @@ async fn main() -> std::io::Result<()> {
|
|||||||
exit(1);
|
exit(1);
|
||||||
};
|
};
|
||||||
} else if ARGS.validate {
|
} else if ARGS.validate {
|
||||||
let mut playlist_path = config.channel.playlist_path.clone();
|
let mut playlist_path = config.channel.playlists.clone();
|
||||||
let start_sec = config.playlist.start_sec.unwrap();
|
let start_sec = config.playlist.start_sec.unwrap();
|
||||||
let date = get_date(false, start_sec, false);
|
let date = get_date(false, start_sec, false);
|
||||||
|
|
||||||
|
@ -349,7 +349,7 @@ pub fn start_channel(manager: ChannelManager) -> Result<(), ProcessError> {
|
|||||||
let channel_id = config.general.channel_id;
|
let channel_id = config.general.channel_id;
|
||||||
|
|
||||||
drain_hls_path(
|
drain_hls_path(
|
||||||
&config.channel.hls_path,
|
&config.channel.public,
|
||||||
&config.output.output_cmd.clone().unwrap_or_default(),
|
&config.output.output_cmd.clone().unwrap_or_default(),
|
||||||
channel_id,
|
channel_id,
|
||||||
)?;
|
)?;
|
||||||
|
@ -29,7 +29,7 @@ pub fn watchman(
|
|||||||
sources: Arc<Mutex<Vec<Media>>>,
|
sources: Arc<Mutex<Vec<Media>>>,
|
||||||
) {
|
) {
|
||||||
let id = config.general.channel_id;
|
let id = config.general.channel_id;
|
||||||
let path = Path::new(&config.channel.storage_path);
|
let path = Path::new(&config.channel.storage);
|
||||||
|
|
||||||
if !path.exists() {
|
if !path.exists() {
|
||||||
error!(target: Target::file_mail(), channel = id; "Folder path not exists: '{path:?}'");
|
error!(target: Target::file_mail(), channel = id; "Folder path not exists: '{path:?}'");
|
||||||
|
@ -75,7 +75,7 @@ pub fn ingest_server(
|
|||||||
let ingest_is_running = channel_mgr.ingest_is_running.clone();
|
let ingest_is_running = channel_mgr.ingest_is_running.clone();
|
||||||
let vtt_dummy = config
|
let vtt_dummy = config
|
||||||
.channel
|
.channel
|
||||||
.storage_path
|
.storage
|
||||||
.join(config.processing.vtt_dummy.clone().unwrap_or_default());
|
.join(config.processing.vtt_dummy.clone().unwrap_or_default());
|
||||||
|
|
||||||
if let Some(ingest_input_cmd) = config.advanced.ingest.input_cmd {
|
if let Some(ingest_input_cmd) = config.advanced.ingest.input_cmd {
|
||||||
|
@ -28,7 +28,7 @@ pub fn source_generator(manager: ChannelManager) -> Box<dyn Iterator<Item = Medi
|
|||||||
info!(target: Target::file_mail(), channel = id; "Playout in folder mode");
|
info!(target: Target::file_mail(), channel = id; "Playout in folder mode");
|
||||||
debug!(target: Target::file_mail(), channel = id;
|
debug!(target: Target::file_mail(), channel = id;
|
||||||
"Monitor folder: <b><magenta>{:?}</></b>",
|
"Monitor folder: <b><magenta>{:?}</></b>",
|
||||||
config.channel.storage_path
|
config.channel.storage
|
||||||
);
|
);
|
||||||
|
|
||||||
let config_clone = config.clone();
|
let config_clone = config.clone();
|
||||||
|
@ -314,14 +314,11 @@ impl CurrentProgram {
|
|||||||
self.current_node =
|
self.current_node =
|
||||||
handle_list_init(&self.config, node_clone, &self.manager, last_index);
|
handle_list_init(&self.config, node_clone, &self.manager, last_index);
|
||||||
|
|
||||||
if self.current_node.source.contains(
|
if self
|
||||||
&self
|
.current_node
|
||||||
.config
|
.source
|
||||||
.channel
|
.contains(&self.config.channel.storage.to_string_lossy().to_string())
|
||||||
.storage_path
|
|| self.current_node.source.contains("color=c=#121212")
|
||||||
.to_string_lossy()
|
|
||||||
.to_string(),
|
|
||||||
) || self.current_node.source.contains("color=c=#121212")
|
|
||||||
{
|
{
|
||||||
is_filler = true;
|
is_filler = true;
|
||||||
}
|
}
|
||||||
|
@ -65,7 +65,7 @@ fn ingest_to_hls_server(manager: ChannelManager) -> Result<(), ProcessError> {
|
|||||||
if config.processing.vtt_enable {
|
if config.processing.vtt_enable {
|
||||||
let vtt_dummy = config
|
let vtt_dummy = config
|
||||||
.channel
|
.channel
|
||||||
.storage_path
|
.storage
|
||||||
.join(config.processing.vtt_dummy.clone().unwrap_or_default());
|
.join(config.processing.vtt_dummy.clone().unwrap_or_default());
|
||||||
|
|
||||||
if vtt_dummy.is_file() {
|
if vtt_dummy.is_file() {
|
||||||
|
@ -40,7 +40,7 @@ impl FolderSource {
|
|||||||
path_list.push(path)
|
path_list.push(path)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
path_list.push(&config.channel.storage_path)
|
path_list.push(&config.channel.storage)
|
||||||
}
|
}
|
||||||
|
|
||||||
for path in &path_list {
|
for path in &path_list {
|
||||||
|
@ -28,13 +28,13 @@ pub fn import_file(
|
|||||||
program: vec![],
|
program: vec![],
|
||||||
};
|
};
|
||||||
|
|
||||||
let playlist_root = &config.channel.playlist_path;
|
let playlist_root = &config.channel.playlists;
|
||||||
if !playlist_root.is_dir() {
|
if !playlist_root.is_dir() {
|
||||||
return Err(Error::new(
|
return Err(Error::new(
|
||||||
ErrorKind::Other,
|
ErrorKind::Other,
|
||||||
format!(
|
format!(
|
||||||
"Playlist folder <b><magenta>{:?}</></b> not exists!",
|
"Playlist folder <b><magenta>{:?}</></b> not exists!",
|
||||||
config.channel.playlist_path,
|
config.channel.playlists,
|
||||||
),
|
),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
@ -100,11 +100,11 @@ pub fn read_json(
|
|||||||
) -> JsonPlaylist {
|
) -> JsonPlaylist {
|
||||||
let id = config.general.channel_id;
|
let id = config.general.channel_id;
|
||||||
let config_clone = config.clone();
|
let config_clone = config.clone();
|
||||||
let mut playlist_path = config.channel.playlist_path.clone();
|
let mut playlist_path = config.channel.playlists.clone();
|
||||||
let start_sec = config.playlist.start_sec.unwrap();
|
let start_sec = config.playlist.start_sec.unwrap();
|
||||||
let date = get_date(seek, start_sec, get_next);
|
let date = get_date(seek, start_sec, get_next);
|
||||||
|
|
||||||
if playlist_path.is_dir() || is_remote(&config.channel.playlist_path.to_string_lossy()) {
|
if playlist_path.is_dir() || is_remote(&config.channel.playlists.to_string_lossy()) {
|
||||||
let d: Vec<&str> = date.split('-').collect();
|
let d: Vec<&str> = date.split('-').collect();
|
||||||
playlist_path = playlist_path
|
playlist_path = playlist_path
|
||||||
.join(d[0])
|
.join(d[0])
|
||||||
|
@ -69,7 +69,7 @@ pub fn prepare_output_cmd(
|
|||||||
let re_v = Regex::new(r"\[?0:v(:0)?\]?").unwrap();
|
let re_v = Regex::new(r"\[?0:v(:0)?\]?").unwrap();
|
||||||
let vtt_dummy = config
|
let vtt_dummy = config
|
||||||
.channel
|
.channel
|
||||||
.storage_path
|
.storage
|
||||||
.join(config.processing.vtt_dummy.clone().unwrap_or_default());
|
.join(config.processing.vtt_dummy.clone().unwrap_or_default());
|
||||||
|
|
||||||
if let Some(mut filter) = filters.clone() {
|
if let Some(mut filter) = filters.clone() {
|
||||||
@ -622,7 +622,7 @@ pub fn loop_image(config: &PlayoutConfig, node: &Media) -> Vec<String> {
|
|||||||
let vtt_file = Path::new(&node.source).with_extension("vtt");
|
let vtt_file = Path::new(&node.source).with_extension("vtt");
|
||||||
let vtt_dummy = config
|
let vtt_dummy = config
|
||||||
.channel
|
.channel
|
||||||
.storage_path
|
.storage
|
||||||
.join(config.processing.vtt_dummy.clone().unwrap_or_default());
|
.join(config.processing.vtt_dummy.clone().unwrap_or_default());
|
||||||
|
|
||||||
if node.seek > 0.5 {
|
if node.seek > 0.5 {
|
||||||
@ -663,7 +663,7 @@ pub fn loop_filler(config: &PlayoutConfig, node: &Media) -> Vec<String> {
|
|||||||
let vtt_file = Path::new(&node.source).with_extension("vtt");
|
let vtt_file = Path::new(&node.source).with_extension("vtt");
|
||||||
let vtt_dummy = config
|
let vtt_dummy = config
|
||||||
.channel
|
.channel
|
||||||
.storage_path
|
.storage
|
||||||
.join(config.processing.vtt_dummy.clone().unwrap_or_default());
|
.join(config.processing.vtt_dummy.clone().unwrap_or_default());
|
||||||
|
|
||||||
if vtt_file.is_file() {
|
if vtt_file.is_file() {
|
||||||
@ -737,7 +737,7 @@ pub fn seek_and_length(config: &PlayoutConfig, node: &mut Media) -> Vec<String>
|
|||||||
let vtt_file = Path::new(&node.source).with_extension("vtt");
|
let vtt_file = Path::new(&node.source).with_extension("vtt");
|
||||||
let vtt_dummy = config
|
let vtt_dummy = config
|
||||||
.channel
|
.channel
|
||||||
.storage_path
|
.storage
|
||||||
.join(config.processing.vtt_dummy.clone().unwrap_or_default());
|
.join(config.processing.vtt_dummy.clone().unwrap_or_default());
|
||||||
|
|
||||||
if node.seek > 0.5 {
|
if node.seek > 0.5 {
|
||||||
@ -788,7 +788,7 @@ pub fn gen_dummy(config: &PlayoutConfig, duration: f64) -> (String, Vec<String>)
|
|||||||
if config.processing.vtt_enable {
|
if config.processing.vtt_enable {
|
||||||
let vtt_dummy = config
|
let vtt_dummy = config
|
||||||
.channel
|
.channel
|
||||||
.storage_path
|
.storage
|
||||||
.join(config.processing.vtt_dummy.clone().unwrap_or_default());
|
.join(config.processing.vtt_dummy.clone().unwrap_or_default());
|
||||||
|
|
||||||
if vtt_dummy.is_file() {
|
if vtt_dummy.is_file() {
|
||||||
|
@ -45,7 +45,7 @@ pub struct Args {
|
|||||||
)]
|
)]
|
||||||
pub init: bool,
|
pub init: bool,
|
||||||
|
|
||||||
#[clap(short, long, help_heading = Some("Initial Setup"), help = "Add a global admin user")]
|
#[clap(short, long, help_heading = Some("Initial Setup"), help = "Add a global admin")]
|
||||||
pub add: bool,
|
pub add: bool,
|
||||||
|
|
||||||
#[clap(short, long, help_heading = Some("Initial Setup"), help = "Create admin user")]
|
#[clap(short, long, help_heading = Some("Initial Setup"), help = "Create admin user")]
|
||||||
@ -66,16 +66,16 @@ pub struct Args {
|
|||||||
help_heading = Some("Initial Setup"),
|
help_heading = Some("Initial Setup"),
|
||||||
help = "Share storage across channels, important for running in Containers"
|
help = "Share storage across channels, important for running in Containers"
|
||||||
)]
|
)]
|
||||||
pub shared_storage: bool,
|
pub shared: bool,
|
||||||
|
|
||||||
#[clap(long, env, help_heading = Some("Initial Setup / General"), help = "Logging path")]
|
#[clap(long, env, help_heading = Some("Initial Setup / General"), help = "Logging path")]
|
||||||
pub log_path: Option<PathBuf>,
|
pub logs: Option<String>,
|
||||||
|
|
||||||
#[clap(long, env, help_heading = Some("Initial Setup / General"), help = "Path to public files, also HLS playlists")]
|
#[clap(long, env, help_heading = Some("Initial Setup / General"), help = "Path to public files, also HLS playlists")]
|
||||||
pub public: Option<String>,
|
pub public: Option<String>,
|
||||||
|
|
||||||
#[clap(long, help_heading = Some("Initial Setup / Playlist"), help = "Path to playlist, or playlist root folder.")]
|
#[clap(long, help_heading = Some("Initial Setup / Playlist"), help = "Path to playlist, or playlist root folder.")]
|
||||||
pub playlist: Option<String>,
|
pub playlists: Option<String>,
|
||||||
|
|
||||||
#[clap(long, env, help_heading = Some("General"), help = "Path to database file")]
|
#[clap(long, env, help_heading = Some("General"), help = "Path to database file")]
|
||||||
pub db: Option<PathBuf>,
|
pub db: Option<PathBuf>,
|
||||||
@ -129,7 +129,7 @@ pub struct Args {
|
|||||||
long,
|
long,
|
||||||
env,
|
env,
|
||||||
help_heading = Some("General / Playout"),
|
help_heading = Some("General / Playout"),
|
||||||
help = "Channels by ids to process (for export config, foreground running, etc.)",
|
help = "Channels by ids to process (for export config, generate playlist, foreground running, etc.)",
|
||||||
num_args = 1..,
|
num_args = 1..,
|
||||||
)]
|
)]
|
||||||
pub channels: Option<Vec<i32>>,
|
pub channels: Option<Vec<i32>>,
|
||||||
@ -184,6 +184,7 @@ fn global_user(args: &mut Args) {
|
|||||||
let mut user = String::new();
|
let mut user = String::new();
|
||||||
let mut mail = String::new();
|
let mut mail = String::new();
|
||||||
|
|
||||||
|
if args.username.is_none() {
|
||||||
print!("Global admin: ");
|
print!("Global admin: ");
|
||||||
stdout().flush().unwrap();
|
stdout().flush().unwrap();
|
||||||
|
|
||||||
@ -192,13 +193,17 @@ fn global_user(args: &mut Args) {
|
|||||||
.expect("Did not enter a correct name?");
|
.expect("Did not enter a correct name?");
|
||||||
|
|
||||||
args.username = Some(user.trim().to_string());
|
args.username = Some(user.trim().to_string());
|
||||||
|
}
|
||||||
|
|
||||||
|
if args.password.is_none() {
|
||||||
print!("Password: ");
|
print!("Password: ");
|
||||||
stdout().flush().unwrap();
|
stdout().flush().unwrap();
|
||||||
let password = read_password();
|
let password = read_password();
|
||||||
|
|
||||||
args.password = password.ok();
|
args.password = password.ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
if args.mail.is_none() {
|
||||||
print!("Mail: ");
|
print!("Mail: ");
|
||||||
stdout().flush().unwrap();
|
stdout().flush().unwrap();
|
||||||
|
|
||||||
@ -207,6 +212,7 @@ fn global_user(args: &mut Args) {
|
|||||||
.expect("Did not enter a correct name?");
|
.expect("Did not enter a correct name?");
|
||||||
|
|
||||||
args.mail = Some(mail.trim().to_string());
|
args.mail = Some(mail.trim().to_string());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn run_args(pool: &Pool<Sqlite>) -> Result<(), i32> {
|
pub async fn run_args(pool: &Pool<Sqlite>) -> Result<(), i32> {
|
||||||
@ -230,22 +236,25 @@ pub async fn run_args(pool: &Pool<Sqlite>) -> Result<(), i32> {
|
|||||||
let mut storage = String::new();
|
let mut storage = String::new();
|
||||||
let mut playlist = String::new();
|
let mut playlist = String::new();
|
||||||
let mut logging = String::new();
|
let mut logging = String::new();
|
||||||
let mut hls = String::new();
|
let mut public = String::new();
|
||||||
let mut shared_store = String::new();
|
let mut shared_store = String::new();
|
||||||
let mut global = GlobalSettings {
|
let mut global = GlobalSettings {
|
||||||
id: 0,
|
id: 0,
|
||||||
secret: None,
|
secret: None,
|
||||||
logging_path: String::new(),
|
logs: String::new(),
|
||||||
playlist_root: String::new(),
|
playlists: String::new(),
|
||||||
public_root: String::new(),
|
public: String::new(),
|
||||||
storage_root: String::new(),
|
storage: String::new(),
|
||||||
shared_storage: false,
|
shared: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
if check_user.unwrap_or_default().is_empty() {
|
if check_user.unwrap_or_default().is_empty() {
|
||||||
global_user(&mut args);
|
global_user(&mut args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(st) = args.storage {
|
||||||
|
global.storage = st;
|
||||||
|
} else {
|
||||||
print!("Storage path [/var/lib/ffplayout/tv-media]: ");
|
print!("Storage path [/var/lib/ffplayout/tv-media]: ");
|
||||||
stdout().flush().unwrap();
|
stdout().flush().unwrap();
|
||||||
|
|
||||||
@ -253,15 +262,19 @@ pub async fn run_args(pool: &Pool<Sqlite>) -> Result<(), i32> {
|
|||||||
.read_line(&mut storage)
|
.read_line(&mut storage)
|
||||||
.expect("Did not enter a correct path?");
|
.expect("Did not enter a correct path?");
|
||||||
|
|
||||||
if storage.trim().is_empty() {
|
global.storage = if storage.trim().is_empty() {
|
||||||
global.storage_root = "/var/lib/ffplayout/tv-media".to_string();
|
"/var/lib/ffplayout/tv-media".to_string()
|
||||||
} else {
|
} else {
|
||||||
global.storage_root = storage
|
storage
|
||||||
.trim()
|
.trim()
|
||||||
.trim_matches(|c| c == '"' || c == '\'')
|
.trim_matches(|c| c == '"' || c == '\'')
|
||||||
.to_string();
|
.to_string()
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(pl) = args.playlists {
|
||||||
|
global.playlists = pl
|
||||||
|
} else {
|
||||||
print!("Playlist path [/var/lib/ffplayout/playlists]: ");
|
print!("Playlist path [/var/lib/ffplayout/playlists]: ");
|
||||||
stdout().flush().unwrap();
|
stdout().flush().unwrap();
|
||||||
|
|
||||||
@ -269,15 +282,19 @@ pub async fn run_args(pool: &Pool<Sqlite>) -> Result<(), i32> {
|
|||||||
.read_line(&mut playlist)
|
.read_line(&mut playlist)
|
||||||
.expect("Did not enter a correct path?");
|
.expect("Did not enter a correct path?");
|
||||||
|
|
||||||
if playlist.trim().is_empty() {
|
global.playlists = if playlist.trim().is_empty() {
|
||||||
global.playlist_root = "/var/lib/ffplayout/playlists".to_string();
|
"/var/lib/ffplayout/playlists".to_string()
|
||||||
} else {
|
} else {
|
||||||
global.playlist_root = playlist
|
playlist
|
||||||
.trim()
|
.trim()
|
||||||
.trim_matches(|c| c == '"' || c == '\'')
|
.trim_matches(|c| c == '"' || c == '\'')
|
||||||
.to_string();
|
.to_string()
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(lp) = args.logs {
|
||||||
|
global.logs = lp;
|
||||||
|
} else {
|
||||||
print!("Logging path [/var/log/ffplayout]: ");
|
print!("Logging path [/var/log/ffplayout]: ");
|
||||||
stdout().flush().unwrap();
|
stdout().flush().unwrap();
|
||||||
|
|
||||||
@ -285,31 +302,39 @@ pub async fn run_args(pool: &Pool<Sqlite>) -> Result<(), i32> {
|
|||||||
.read_line(&mut logging)
|
.read_line(&mut logging)
|
||||||
.expect("Did not enter a correct path?");
|
.expect("Did not enter a correct path?");
|
||||||
|
|
||||||
if logging.trim().is_empty() {
|
global.logs = if logging.trim().is_empty() {
|
||||||
global.logging_path = "/var/log/ffplayout".to_string();
|
"/var/log/ffplayout".to_string()
|
||||||
} else {
|
} else {
|
||||||
global.logging_path = logging
|
logging
|
||||||
.trim()
|
.trim()
|
||||||
.trim_matches(|c| c == '"' || c == '\'')
|
.trim_matches(|c| c == '"' || c == '\'')
|
||||||
.to_string();
|
.to_string()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(p) = args.public {
|
||||||
|
global.public = p;
|
||||||
|
} else {
|
||||||
print!("Public (HLS) path [/usr/share/ffplayout/public]: ");
|
print!("Public (HLS) path [/usr/share/ffplayout/public]: ");
|
||||||
stdout().flush().unwrap();
|
stdout().flush().unwrap();
|
||||||
|
|
||||||
stdin()
|
stdin()
|
||||||
.read_line(&mut hls)
|
.read_line(&mut public)
|
||||||
.expect("Did not enter a correct path?");
|
.expect("Did not enter a correct path?");
|
||||||
|
|
||||||
if hls.trim().is_empty() {
|
global.public = if public.trim().is_empty() {
|
||||||
global.public_root = "/usr/share/ffplayout/public".to_string();
|
"/usr/share/ffplayout/public".to_string()
|
||||||
} else {
|
} else {
|
||||||
global.public_root = hls
|
public
|
||||||
.trim()
|
.trim()
|
||||||
.trim_matches(|c| c == '"' || c == '\'')
|
.trim_matches(|c| c == '"' || c == '\'')
|
||||||
.to_string();
|
.to_string()
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if args.shared {
|
||||||
|
global.shared = true;
|
||||||
|
} else {
|
||||||
print!("Shared storage [Y/n]: ");
|
print!("Shared storage [Y/n]: ");
|
||||||
stdout().flush().unwrap();
|
stdout().flush().unwrap();
|
||||||
|
|
||||||
@ -317,7 +342,8 @@ pub async fn run_args(pool: &Pool<Sqlite>) -> Result<(), i32> {
|
|||||||
.read_line(&mut shared_store)
|
.read_line(&mut shared_store)
|
||||||
.expect("Did not enter a yes or no?");
|
.expect("Did not enter a yes or no?");
|
||||||
|
|
||||||
global.shared_storage = shared_store.trim().to_lowercase().starts_with('y');
|
global.shared = shared_store.trim().to_lowercase().starts_with('y');
|
||||||
|
}
|
||||||
|
|
||||||
if let Err(e) = handles::update_global(pool, global.clone()).await {
|
if let Err(e) = handles::update_global(pool, global.clone()).await {
|
||||||
eprintln!("{e}");
|
eprintln!("{e}");
|
||||||
@ -325,25 +351,25 @@ pub async fn run_args(pool: &Pool<Sqlite>) -> Result<(), i32> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let mut channel = handles::select_channel(pool, &1).await.unwrap();
|
let mut channel = handles::select_channel(pool, &1).await.unwrap();
|
||||||
channel.hls_path = global.public_root;
|
channel.public = global.public;
|
||||||
channel.playlist_path = global.playlist_root;
|
channel.playlists = global.playlists;
|
||||||
channel.storage_path = global.storage_root;
|
channel.storage = global.storage;
|
||||||
|
|
||||||
let mut storage_path = PathBuf::from(channel.storage_path.clone());
|
let mut storage_path = PathBuf::from(channel.storage.clone());
|
||||||
|
|
||||||
if global.shared_storage {
|
if global.shared {
|
||||||
storage_path = storage_path.join("1");
|
storage_path = storage_path.join("1");
|
||||||
|
|
||||||
channel.preview_url = "http://127.0.0.1:8787/1/stream.m3u8".to_string();
|
channel.preview_url = "http://127.0.0.1:8787/1/stream.m3u8".to_string();
|
||||||
channel.hls_path = Path::new(&channel.hls_path)
|
channel.public = Path::new(&channel.public)
|
||||||
.join("1")
|
.join("1")
|
||||||
.to_string_lossy()
|
.to_string_lossy()
|
||||||
.to_string();
|
.to_string();
|
||||||
channel.playlist_path = Path::new(&channel.playlist_path)
|
channel.playlists = Path::new(&channel.playlists)
|
||||||
.join("1")
|
.join("1")
|
||||||
.to_string_lossy()
|
.to_string_lossy()
|
||||||
.to_string();
|
.to_string();
|
||||||
channel.storage_path = storage_path.to_string_lossy().to_string();
|
channel.storage = storage_path.to_string_lossy().to_string();
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Err(e) = copy_assets(&storage_path).await {
|
if let Err(e) = copy_assets(&storage_path).await {
|
||||||
@ -358,20 +384,13 @@ pub async fn run_args(pool: &Pool<Sqlite>) -> Result<(), i32> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
println!("\nSet global settings done...");
|
println!("\nSet global settings done...");
|
||||||
}
|
} else if args.add {
|
||||||
|
|
||||||
if args.add {
|
|
||||||
global_user(&mut args);
|
global_user(&mut args);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(username) = args.username {
|
if let Some(username) = args.username {
|
||||||
error_code = 0;
|
error_code = 0;
|
||||||
|
|
||||||
if args.mail.is_none() || args.password.is_none() {
|
|
||||||
eprintln!("Mail/password missing!");
|
|
||||||
error_code = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
let chl: Vec<i32> = channels.clone().iter().map(|c| c.id).collect();
|
let chl: Vec<i32> = channels.clone().iter().map(|c| c.id).collect();
|
||||||
|
|
||||||
let ff_user = User {
|
let ff_user = User {
|
||||||
@ -392,73 +411,6 @@ pub async fn run_args(pool: &Pool<Sqlite>) -> Result<(), i32> {
|
|||||||
println!("Create global admin user \"{username}\" done...");
|
println!("Create global admin user \"{username}\" done...");
|
||||||
}
|
}
|
||||||
|
|
||||||
if !args.init
|
|
||||||
&& args.storage.is_some()
|
|
||||||
&& args.playlist.is_some()
|
|
||||||
&& args.public.is_some()
|
|
||||||
&& args.log_path.is_some()
|
|
||||||
{
|
|
||||||
error_code = 0;
|
|
||||||
|
|
||||||
let global = GlobalSettings {
|
|
||||||
id: 0,
|
|
||||||
secret: None,
|
|
||||||
logging_path: args.log_path.unwrap().to_string_lossy().to_string(),
|
|
||||||
playlist_root: args.playlist.unwrap(),
|
|
||||||
public_root: args.public.unwrap(),
|
|
||||||
storage_root: args.storage.unwrap(),
|
|
||||||
shared_storage: args.shared_storage,
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut channel = handles::select_channel(pool, &1)
|
|
||||||
.await
|
|
||||||
.expect("Select Channel 1");
|
|
||||||
let mut storage_path = PathBuf::from(global.storage_root.clone());
|
|
||||||
|
|
||||||
if args.shared_storage {
|
|
||||||
storage_path = storage_path.join("1");
|
|
||||||
|
|
||||||
channel.hls_path = Path::new(&global.public_root)
|
|
||||||
.join("1")
|
|
||||||
.to_string_lossy()
|
|
||||||
.to_string();
|
|
||||||
channel.playlist_path = Path::new(&global.playlist_root)
|
|
||||||
.join("1")
|
|
||||||
.to_string_lossy()
|
|
||||||
.to_string();
|
|
||||||
channel.storage_path = storage_path.to_string_lossy().to_string();
|
|
||||||
} else {
|
|
||||||
channel.hls_path = global.public_root.clone();
|
|
||||||
channel.playlist_path = global.playlist_root.clone();
|
|
||||||
channel.storage_path = global.storage_root.clone();
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Err(e) = copy_assets(&storage_path).await {
|
|
||||||
eprintln!("{e}");
|
|
||||||
};
|
|
||||||
|
|
||||||
match handles::update_global(pool, global.clone()).await {
|
|
||||||
Ok(_) => println!("Update globals done..."),
|
|
||||||
Err(e) => {
|
|
||||||
eprintln!("{e}");
|
|
||||||
error_code = 1;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
match handles::update_channel(pool, 1, channel).await {
|
|
||||||
Ok(_) => println!("Update channel done..."),
|
|
||||||
Err(e) => {
|
|
||||||
eprintln!("{e}");
|
|
||||||
error_code = 1;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
#[cfg(target_family = "unix")]
|
|
||||||
{
|
|
||||||
update_permissions().await;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ARGS.list_channels {
|
if ARGS.list_channels {
|
||||||
let chl = channels
|
let chl = channels
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -35,7 +35,7 @@ pub async fn create_channel(
|
|||||||
target_channel: Channel,
|
target_channel: Channel,
|
||||||
) -> Result<Channel, ServiceError> {
|
) -> Result<Channel, ServiceError> {
|
||||||
let channel = handles::insert_channel(conn, target_channel).await?;
|
let channel = handles::insert_channel(conn, target_channel).await?;
|
||||||
let storage_path = PathBuf::from(channel.storage_path.clone());
|
let storage_path = PathBuf::from(channel.storage.clone());
|
||||||
|
|
||||||
handles::new_channel_presets(conn, channel.id).await?;
|
handles::new_channel_presets(conn, channel.id).await?;
|
||||||
|
|
||||||
|
@ -176,21 +176,21 @@ pub struct PlayoutConfig {
|
|||||||
|
|
||||||
#[derive(Debug, Default, Clone, Deserialize, Serialize)]
|
#[derive(Debug, Default, Clone, Deserialize, Serialize)]
|
||||||
pub struct Channel {
|
pub struct Channel {
|
||||||
pub logging_path: PathBuf,
|
pub logs: PathBuf,
|
||||||
pub hls_path: PathBuf,
|
pub public: PathBuf,
|
||||||
pub playlist_path: PathBuf,
|
pub playlists: PathBuf,
|
||||||
pub storage_path: PathBuf,
|
pub storage: PathBuf,
|
||||||
pub shared_storage: bool,
|
pub shared: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Channel {
|
impl Channel {
|
||||||
pub fn new(config: &models::GlobalSettings, channel: models::Channel) -> Self {
|
pub fn new(config: &models::GlobalSettings, channel: models::Channel) -> Self {
|
||||||
Self {
|
Self {
|
||||||
logging_path: PathBuf::from(config.logging_path.clone()),
|
logs: PathBuf::from(config.logs.clone()),
|
||||||
hls_path: PathBuf::from(channel.hls_path.clone()),
|
public: PathBuf::from(channel.public.clone()),
|
||||||
playlist_path: PathBuf::from(channel.playlist_path.clone()),
|
playlists: PathBuf::from(channel.playlists.clone()),
|
||||||
storage_path: PathBuf::from(channel.storage_path.clone()),
|
storage: PathBuf::from(channel.storage.clone()),
|
||||||
shared_storage: config.shared_storage,
|
shared: config.shared,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -588,27 +588,23 @@ impl PlayoutConfig {
|
|||||||
let task = Task::new(&config);
|
let task = Task::new(&config);
|
||||||
let mut output = Output::new(&config);
|
let mut output = Output::new(&config);
|
||||||
|
|
||||||
if !channel.storage_path.is_dir() {
|
if !channel.storage.is_dir() {
|
||||||
tokio::fs::create_dir_all(&channel.storage_path)
|
tokio::fs::create_dir_all(&channel.storage)
|
||||||
.await
|
.await
|
||||||
.unwrap_or_else(|_| {
|
.unwrap_or_else(|_| panic!("Can't create storage folder: {:#?}", channel.storage));
|
||||||
panic!("Can't create storage folder: {:#?}", channel.storage_path)
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut storage =
|
let mut storage = Storage::new(&config, channel.storage.clone(), global.shared);
|
||||||
Storage::new(&config, channel.storage_path.clone(), global.shared_storage);
|
|
||||||
|
|
||||||
if !channel.playlist_path.is_dir() {
|
if !channel.playlists.is_dir() {
|
||||||
tokio::fs::create_dir_all(&channel.playlist_path).await?;
|
tokio::fs::create_dir_all(&channel.playlists).await?;
|
||||||
}
|
}
|
||||||
|
|
||||||
if !channel.logging_path.is_dir() {
|
if !channel.logs.is_dir() {
|
||||||
tokio::fs::create_dir_all(&channel.logging_path).await?;
|
tokio::fs::create_dir_all(&channel.logs).await?;
|
||||||
}
|
}
|
||||||
|
|
||||||
let (filler_path, _, filler) =
|
let (filler_path, _, filler) = norm_abs_path(&channel.storage, &config.storage_filler)?;
|
||||||
norm_abs_path(&channel.storage_path, &config.storage_filler)?;
|
|
||||||
|
|
||||||
storage.filler = filler;
|
storage.filler = filler;
|
||||||
storage.filler_path = filler_path;
|
storage.filler_path = filler_path;
|
||||||
@ -621,7 +617,7 @@ impl PlayoutConfig {
|
|||||||
playlist.length_sec = Some(86400.0);
|
playlist.length_sec = Some(86400.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
let (logo_path, _, logo) = norm_abs_path(&channel.storage_path, &processing.logo)?;
|
let (logo_path, _, logo) = norm_abs_path(&channel.storage, &processing.logo)?;
|
||||||
|
|
||||||
if processing.add_logo && !logo_path.is_file() {
|
if processing.add_logo && !logo_path.is_file() {
|
||||||
processing.add_logo = false;
|
processing.add_logo = false;
|
||||||
@ -709,13 +705,13 @@ impl PlayoutConfig {
|
|||||||
|
|
||||||
for item in cmd.iter_mut() {
|
for item in cmd.iter_mut() {
|
||||||
if item.ends_with(".ts") || (item.ends_with(".m3u8") && item != "master.m3u8") {
|
if item.ends_with(".ts") || (item.ends_with(".m3u8") && item != "master.m3u8") {
|
||||||
if let Ok((hls_path, _, _)) = norm_abs_path(&channel.hls_path, item) {
|
if let Ok((public, _, _)) = norm_abs_path(&channel.public, item) {
|
||||||
let parent = hls_path.parent().ok_or("HLS parent path")?;
|
let parent = public.parent().ok_or("HLS parent path")?;
|
||||||
|
|
||||||
if !parent.is_dir() {
|
if !parent.is_dir() {
|
||||||
fs::create_dir_all(parent).await?;
|
fs::create_dir_all(parent).await?;
|
||||||
}
|
}
|
||||||
item.clone_from(&hls_path.to_string_lossy().to_string());
|
item.clone_from(&public.to_string_lossy().to_string());
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -736,7 +732,7 @@ impl PlayoutConfig {
|
|||||||
text.node_pos = None;
|
text.node_pos = None;
|
||||||
}
|
}
|
||||||
|
|
||||||
let (font_path, _, font) = norm_abs_path(&channel.storage_path, &text.font)?;
|
let (font_path, _, font) = norm_abs_path(&channel.storage, &text.font)?;
|
||||||
text.font = font;
|
text.font = font;
|
||||||
text.font_path = font_path.to_string_lossy().to_string();
|
text.font_path = font_path.to_string_lossy().to_string();
|
||||||
|
|
||||||
@ -853,12 +849,12 @@ pub async fn get_config(
|
|||||||
config.storage.paths = paths;
|
config.storage.paths = paths;
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(playlist) = args.playlist {
|
if let Some(playlist) = args.playlists {
|
||||||
config.channel.playlist_path = PathBuf::from(&playlist);
|
config.channel.playlists = PathBuf::from(&playlist);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(folder) = args.folder {
|
if let Some(folder) = args.folder {
|
||||||
config.channel.storage_path = folder;
|
config.channel.storage = folder;
|
||||||
config.processing.mode = ProcessMode::Folder;
|
config.processing.mode = ProcessMode::Folder;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -877,10 +873,10 @@ pub async fn get_config(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if args.shared_storage {
|
if args.shared {
|
||||||
// config.channel.shared_storage could be true already,
|
// config.channel.shared could be true already,
|
||||||
// so should not be overridden with false when args.shared_storage is not set
|
// so should not be overridden with false when args.shared is not set
|
||||||
config.channel.shared_storage = args.shared_storage
|
config.channel.shared = args.shared
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(volume) = args.volume {
|
if let Some(volume) = args.volume {
|
||||||
|
@ -115,13 +115,12 @@ pub async fn browser(
|
|||||||
let mut extensions = config.storage.extensions.clone();
|
let mut extensions = config.storage.extensions.clone();
|
||||||
extensions.append(&mut channel_extensions);
|
extensions.append(&mut channel_extensions);
|
||||||
|
|
||||||
let (path, parent, path_component) =
|
let (path, parent, path_component) = norm_abs_path(&config.channel.storage, &path_obj.source)?;
|
||||||
norm_abs_path(&config.channel.storage_path, &path_obj.source)?;
|
|
||||||
|
|
||||||
let parent_path = if !path_component.is_empty() {
|
let parent_path = if !path_component.is_empty() {
|
||||||
path.parent().unwrap()
|
path.parent().unwrap()
|
||||||
} else {
|
} else {
|
||||||
&config.channel.storage_path
|
&config.channel.storage
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut obj = PathObject::new(path_component, Some(parent));
|
let mut obj = PathObject::new(path_component, Some(parent));
|
||||||
@ -212,7 +211,7 @@ pub async fn create_directory(
|
|||||||
config: &PlayoutConfig,
|
config: &PlayoutConfig,
|
||||||
path_obj: &PathObject,
|
path_obj: &PathObject,
|
||||||
) -> Result<HttpResponse, ServiceError> {
|
) -> Result<HttpResponse, ServiceError> {
|
||||||
let (path, _, _) = norm_abs_path(&config.channel.storage_path, &path_obj.source)?;
|
let (path, _, _) = norm_abs_path(&config.channel.storage, &path_obj.source)?;
|
||||||
|
|
||||||
if let Err(e) = fs::create_dir_all(&path).await {
|
if let Err(e) = fs::create_dir_all(&path).await {
|
||||||
return Err(ServiceError::BadRequest(e.to_string()));
|
return Err(ServiceError::BadRequest(e.to_string()));
|
||||||
@ -281,8 +280,8 @@ pub async fn rename_file(
|
|||||||
config: &PlayoutConfig,
|
config: &PlayoutConfig,
|
||||||
move_object: &MoveObject,
|
move_object: &MoveObject,
|
||||||
) -> Result<MoveObject, ServiceError> {
|
) -> Result<MoveObject, ServiceError> {
|
||||||
let (source_path, _, _) = norm_abs_path(&config.channel.storage_path, &move_object.source)?;
|
let (source_path, _, _) = norm_abs_path(&config.channel.storage, &move_object.source)?;
|
||||||
let (mut target_path, _, _) = norm_abs_path(&config.channel.storage_path, &move_object.target)?;
|
let (mut target_path, _, _) = norm_abs_path(&config.channel.storage, &move_object.target)?;
|
||||||
|
|
||||||
if !source_path.exists() {
|
if !source_path.exists() {
|
||||||
return Err(ServiceError::BadRequest("Source file not exist!".into()));
|
return Err(ServiceError::BadRequest("Source file not exist!".into()));
|
||||||
@ -314,7 +313,7 @@ pub async fn remove_file_or_folder(
|
|||||||
config: &PlayoutConfig,
|
config: &PlayoutConfig,
|
||||||
source_path: &str,
|
source_path: &str,
|
||||||
) -> Result<(), ServiceError> {
|
) -> Result<(), ServiceError> {
|
||||||
let (source, _, _) = norm_abs_path(&config.channel.storage_path, source_path)?;
|
let (source, _, _) = norm_abs_path(&config.channel.storage, source_path)?;
|
||||||
|
|
||||||
if !source.exists() {
|
if !source.exists() {
|
||||||
return Err(ServiceError::BadRequest("Source does not exists!".into()));
|
return Err(ServiceError::BadRequest("Source does not exists!".into()));
|
||||||
@ -346,7 +345,7 @@ pub async fn remove_file_or_folder(
|
|||||||
}
|
}
|
||||||
|
|
||||||
async fn valid_path(config: &PlayoutConfig, path: &str) -> Result<PathBuf, ServiceError> {
|
async fn valid_path(config: &PlayoutConfig, path: &str) -> Result<PathBuf, ServiceError> {
|
||||||
let (test_path, _, _) = norm_abs_path(&config.channel.storage_path, path)?;
|
let (test_path, _, _) = norm_abs_path(&config.channel.storage, path)?;
|
||||||
|
|
||||||
if !test_path.is_dir() {
|
if !test_path.is_dir() {
|
||||||
return Err(ServiceError::BadRequest("Target folder not exists!".into()));
|
return Err(ServiceError::BadRequest("Target folder not exists!".into()));
|
||||||
|
@ -206,7 +206,7 @@ pub fn playlist_generator(manager: &ChannelManager) -> Result<Vec<JsonPlaylist>,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let playlist_root = &config.channel.playlist_path;
|
let playlist_root = &config.channel.playlists;
|
||||||
let mut playlists = vec![];
|
let mut playlists = vec![];
|
||||||
let mut date_range = vec![];
|
let mut date_range = vec![];
|
||||||
let mut from_template = false;
|
let mut from_template = false;
|
||||||
@ -215,7 +215,7 @@ pub fn playlist_generator(manager: &ChannelManager) -> Result<Vec<JsonPlaylist>,
|
|||||||
error!(
|
error!(
|
||||||
target: Target::all(), channel = id;
|
target: Target::all(), channel = id;
|
||||||
"Playlist folder <b><magenta>{:?}</></b> not exists!",
|
"Playlist folder <b><magenta>{:?}</></b> not exists!",
|
||||||
config.channel.playlist_path
|
config.channel.playlists
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -299,11 +299,7 @@ fn file_formatter(
|
|||||||
|
|
||||||
pub fn log_file_path() -> PathBuf {
|
pub fn log_file_path() -> PathBuf {
|
||||||
let config = GlobalSettings::global();
|
let config = GlobalSettings::global();
|
||||||
|
let mut log_path = PathBuf::from(&ARGS.logs.as_ref().unwrap_or(&config.logs));
|
||||||
let mut log_path = ARGS
|
|
||||||
.log_path
|
|
||||||
.clone()
|
|
||||||
.unwrap_or(PathBuf::from(&config.logging_path));
|
|
||||||
|
|
||||||
if !log_path.is_absolute() {
|
if !log_path.is_absolute() {
|
||||||
log_path = env::current_dir().unwrap().join(log_path);
|
log_path = env::current_dir().unwrap().join(log_path);
|
||||||
|
@ -203,7 +203,7 @@ pub fn public_path() -> PathBuf {
|
|||||||
let dev_path = env::current_dir()
|
let dev_path = env::current_dir()
|
||||||
.unwrap_or_default()
|
.unwrap_or_default()
|
||||||
.join("frontend/.output/public/");
|
.join("frontend/.output/public/");
|
||||||
let mut public_path = PathBuf::from(&config.public_root);
|
let mut public_path = PathBuf::from(&config.public);
|
||||||
|
|
||||||
if let Some(p) = &ARGS.public {
|
if let Some(p) = &ARGS.public {
|
||||||
// When public path is set as argument use this path for serving static files.
|
// When public path is set as argument use this path for serving static files.
|
||||||
|
@ -14,7 +14,7 @@ pub async fn read_playlist(
|
|||||||
date: String,
|
date: String,
|
||||||
) -> Result<JsonPlaylist, ServiceError> {
|
) -> Result<JsonPlaylist, ServiceError> {
|
||||||
let d: Vec<&str> = date.split('-').collect();
|
let d: Vec<&str> = date.split('-').collect();
|
||||||
let mut playlist_path = config.channel.playlist_path.clone();
|
let mut playlist_path = config.channel.playlists.clone();
|
||||||
|
|
||||||
playlist_path = playlist_path
|
playlist_path = playlist_path
|
||||||
.join(d[0])
|
.join(d[0])
|
||||||
@ -34,7 +34,7 @@ pub async fn write_playlist(
|
|||||||
) -> Result<String, ServiceError> {
|
) -> Result<String, ServiceError> {
|
||||||
let date = json_data.date.clone();
|
let date = json_data.date.clone();
|
||||||
let d: Vec<&str> = date.split('-').collect();
|
let d: Vec<&str> = date.split('-').collect();
|
||||||
let mut playlist_path = config.channel.playlist_path.clone();
|
let mut playlist_path = config.channel.playlists.clone();
|
||||||
|
|
||||||
if !playlist_path
|
if !playlist_path
|
||||||
.extension()
|
.extension()
|
||||||
@ -93,7 +93,7 @@ pub fn generate_playlist(manager: ChannelManager) -> Result<JsonPlaylist, Servic
|
|||||||
|
|
||||||
for path in &source.paths {
|
for path in &source.paths {
|
||||||
let (safe_path, _, _) =
|
let (safe_path, _, _) =
|
||||||
norm_abs_path(&config.channel.storage_path, &path.to_string_lossy())?;
|
norm_abs_path(&config.channel.storage, &path.to_string_lossy())?;
|
||||||
paths.push(safe_path);
|
paths.push(safe_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -124,7 +124,7 @@ pub fn generate_playlist(manager: ChannelManager) -> Result<JsonPlaylist, Servic
|
|||||||
|
|
||||||
pub async fn delete_playlist(config: &PlayoutConfig, date: &str) -> Result<String, ServiceError> {
|
pub async fn delete_playlist(config: &PlayoutConfig, date: &str) -> Result<String, ServiceError> {
|
||||||
let d: Vec<&str> = date.split('-').collect();
|
let d: Vec<&str> = date.split('-').collect();
|
||||||
let mut playlist_path = PathBuf::from(&config.channel.playlist_path);
|
let mut playlist_path = PathBuf::from(&config.channel.playlists);
|
||||||
|
|
||||||
playlist_path = playlist_path
|
playlist_path = playlist_path
|
||||||
.join(d[0])
|
.join(d[0])
|
||||||
|
@ -118,7 +118,7 @@ pub fn stat(config: PlayoutConfig) -> SystemStat {
|
|||||||
|
|
||||||
for disk in &*disks {
|
for disk in &*disks {
|
||||||
if disk.mount_point().to_string_lossy().len() > 1
|
if disk.mount_point().to_string_lossy().len() > 1
|
||||||
&& config.channel.storage_path.starts_with(disk.mount_point())
|
&& config.channel.storage.starts_with(disk.mount_point())
|
||||||
{
|
{
|
||||||
storage.path = disk.name().to_string_lossy().to_string();
|
storage.path = disk.name().to_string_lossy().to_string();
|
||||||
storage.total = disk.total_space();
|
storage.total = disk.total_space();
|
||||||
|
@ -5,11 +5,11 @@ CREATE TABLE
|
|||||||
global (
|
global (
|
||||||
id INTEGER PRIMARY KEY,
|
id INTEGER PRIMARY KEY,
|
||||||
secret TEXT NOT NULL,
|
secret TEXT NOT NULL,
|
||||||
logging_path TEXT NOT NULL DEFAULT "/var/log/ffplayout",
|
logs TEXT NOT NULL DEFAULT "/var/log/ffplayout",
|
||||||
playlist_root TEXT NOT NULL DEFAULT "/var/lib/ffplayout/playlists",
|
playlists TEXT NOT NULL DEFAULT "/var/lib/ffplayout/playlists",
|
||||||
public_root TEXT NOT NULL DEFAULT "/usr/share/ffplayout/public",
|
public TEXT NOT NULL DEFAULT "/usr/share/ffplayout/public",
|
||||||
storage_root TEXT NOT NULL DEFAULT "/var/lib/ffplayout/tv-media",
|
storage TEXT NOT NULL DEFAULT "/var/lib/ffplayout/tv-media",
|
||||||
shared_storage INTEGER NOT NULL DEFAULT 0,
|
shared INTEGER NOT NULL DEFAULT 0,
|
||||||
UNIQUE (secret)
|
UNIQUE (secret)
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -27,9 +27,9 @@ CREATE TABLE
|
|||||||
preview_url TEXT NOT NULL,
|
preview_url TEXT NOT NULL,
|
||||||
extra_extensions TEXT NOT NULL DEFAULT 'jpg,jpeg,png',
|
extra_extensions TEXT NOT NULL DEFAULT 'jpg,jpeg,png',
|
||||||
active INTEGER NOT NULL DEFAULT 0,
|
active INTEGER NOT NULL DEFAULT 0,
|
||||||
hls_path TEXT NOT NULL DEFAULT "/usr/share/ffplayout/public",
|
public TEXT NOT NULL DEFAULT "/usr/share/ffplayout/public",
|
||||||
playlist_path TEXT NOT NULL DEFAULT "/var/lib/ffplayout/playlists",
|
playlists TEXT NOT NULL DEFAULT "/var/lib/ffplayout/playlists",
|
||||||
storage_path TEXT NOT NULL DEFAULT "/var/lib/ffplayout/tv-media",
|
storage TEXT NOT NULL DEFAULT "/var/lib/ffplayout/tv-media",
|
||||||
last_date TEXT,
|
last_date TEXT,
|
||||||
time_shift REAL NOT NULL DEFAULT 0
|
time_shift REAL NOT NULL DEFAULT 0
|
||||||
);
|
);
|
||||||
|
@ -39,8 +39,8 @@ name = "api_routes"
|
|||||||
path = "src/api_routes.rs"
|
path = "src/api_routes.rs"
|
||||||
|
|
||||||
[[test]]
|
[[test]]
|
||||||
name = "lib_utils"
|
name = "utils"
|
||||||
path = "src/lib_utils.rs"
|
path = "src/utils.rs"
|
||||||
|
|
||||||
[[test]]
|
[[test]]
|
||||||
name = "engine_playlist"
|
name = "engine_playlist"
|
||||||
|
@ -22,8 +22,8 @@ async fn prepare_config() -> (PlayoutConfig, ChannelManager, Pool<Sqlite>) {
|
|||||||
|
|
||||||
sqlx::query(
|
sqlx::query(
|
||||||
r#"
|
r#"
|
||||||
UPDATE global SET public_root = "assets/hls", logging_path = "assets/log", playlist_root = "assets/playlists", storage_root = "assets/storage";
|
UPDATE global SET public = "assets/hls", logs = "assets/log", playlists = "assets/playlists", storage = "assets/storage";
|
||||||
UPDATE channels SET hls_path = "assets/hls", playlist_path = "assets/playlists", storage_path = "assets/storage";
|
UPDATE channels SET public = "assets/hls", playlists = "assets/playlists", storage = "assets/storage";
|
||||||
"#,
|
"#,
|
||||||
)
|
)
|
||||||
.execute(&pool)
|
.execute(&pool)
|
||||||
|
@ -22,8 +22,8 @@ async fn prepare_config() -> (PlayoutConfig, ChannelManager) {
|
|||||||
|
|
||||||
sqlx::query(
|
sqlx::query(
|
||||||
r#"
|
r#"
|
||||||
UPDATE global SET public_root = "assets/hls", logging_path = "assets/log", playlist_root = "assets/playlists", storage_root = "assets/storage";
|
UPDATE global SET public = "assets/hls", logs = "assets/log", playlists = "assets/playlists", storage = "assets/storage";
|
||||||
UPDATE channels SET hls_path = "assets/hls", playlist_path = "assets/playlists", storage_path = "assets/storage";
|
UPDATE channels SET public = "assets/hls", playlists = "assets/playlists", storage = "assets/storage";
|
||||||
UPDATE configurations SET processing_width = 1024, processing_height = 576;
|
UPDATE configurations SET processing_width = 1024, processing_height = 576;
|
||||||
"#,
|
"#,
|
||||||
)
|
)
|
||||||
|
@ -25,8 +25,8 @@ async fn prepare_config() -> (PlayoutConfig, ChannelManager) {
|
|||||||
|
|
||||||
sqlx::query(
|
sqlx::query(
|
||||||
r#"
|
r#"
|
||||||
UPDATE global SET public_root = "assets/hls", logging_path = "assets/log", playlist_root = "assets/playlists", storage_root = "assets/storage";
|
UPDATE global SET public = "assets/hls", logs = "assets/log", playlists = "assets/playlists", storages = "assets/storage";
|
||||||
UPDATE channels SET hls_path = "assets/hls", playlist_path = "assets/playlists", storage_path = "assets/storage";
|
UPDATE channels SET public = "assets/hls", playlists = "assets/playlists", storage = "assets/storage";
|
||||||
UPDATE configurations SET processing_width = 1024, processing_height = 576;
|
UPDATE configurations SET processing_width = 1024, processing_height = 576;
|
||||||
"#,
|
"#,
|
||||||
)
|
)
|
||||||
@ -104,7 +104,7 @@ fn test_generate_playlist_from_folder() {
|
|||||||
config.processing.mode = Playlist;
|
config.processing.mode = Playlist;
|
||||||
config.storage.filler = "assets/".into();
|
config.storage.filler = "assets/".into();
|
||||||
config.playlist.length_sec = Some(86400.0);
|
config.playlist.length_sec = Some(86400.0);
|
||||||
config.channel.playlist_path = "assets/playlists".into();
|
config.channel.playlists = "assets/playlists".into();
|
||||||
|
|
||||||
let playlist = generate_playlist(manager);
|
let playlist = generate_playlist(manager);
|
||||||
|
|
||||||
@ -149,7 +149,7 @@ fn test_generate_playlist_from_template() {
|
|||||||
config.processing.mode = Playlist;
|
config.processing.mode = Playlist;
|
||||||
config.storage.filler = "assets/".into();
|
config.storage.filler = "assets/".into();
|
||||||
config.playlist.length_sec = Some(86400.0);
|
config.playlist.length_sec = Some(86400.0);
|
||||||
config.channel.playlist_path = "assets/playlists".into();
|
config.channel.playlists = "assets/playlists".into();
|
||||||
|
|
||||||
let playlist = generate_playlist(manager);
|
let playlist = generate_playlist(manager);
|
||||||
|
|
||||||
|
@ -24,8 +24,8 @@ async fn prepare_config() -> (PlayoutConfig, ChannelManager) {
|
|||||||
|
|
||||||
sqlx::query(
|
sqlx::query(
|
||||||
r#"
|
r#"
|
||||||
UPDATE global SET public_root = "assets/hls", logging_path = "assets/log", playlist_root = "assets/playlists", storage_root = "assets/storage";
|
UPDATE global SET public = "assets/hls", logs = "assets/log", playlists = "assets/playlists", storage = "assets/storage";
|
||||||
UPDATE channels SET hls_path = "assets/hls", playlist_path = "assets/playlists", storage_path = "assets/storage";
|
UPDATE channels SET public = "assets/hls", playlists = "assets/playlists", storage = "assets/storage";
|
||||||
UPDATE configurations SET processing_width = 1024, processing_height = 576;
|
UPDATE configurations SET processing_width = 1024, processing_height = 576;
|
||||||
"#,
|
"#,
|
||||||
)
|
)
|
||||||
@ -67,7 +67,7 @@ fn test_gen_source() {
|
|||||||
config.playlist.start_sec = Some(0.0);
|
config.playlist.start_sec = Some(0.0);
|
||||||
config.playlist.length = "24:00:00".into();
|
config.playlist.length = "24:00:00".into();
|
||||||
config.playlist.length_sec = Some(86400.0);
|
config.playlist.length_sec = Some(86400.0);
|
||||||
config.channel.playlist_path = "assets/playlists".into();
|
config.channel.playlists = "assets/playlists".into();
|
||||||
config.storage.filler = "assets/media_filler/filler_0.mp4".into();
|
config.storage.filler = "assets/media_filler/filler_0.mp4".into();
|
||||||
|
|
||||||
let mut valid_source_with_probe = Media::new(0, "assets/media_mix/av_sync.mp4", true);
|
let mut valid_source_with_probe = Media::new(0, "assets/media_mix/av_sync.mp4", true);
|
||||||
@ -114,7 +114,7 @@ fn playlist_missing() {
|
|||||||
config.playlist.start_sec = Some(0.0);
|
config.playlist.start_sec = Some(0.0);
|
||||||
config.playlist.length = "24:00:00".into();
|
config.playlist.length = "24:00:00".into();
|
||||||
config.playlist.length_sec = Some(86400.0);
|
config.playlist.length_sec = Some(86400.0);
|
||||||
config.channel.playlist_path = "assets/playlists".into();
|
config.channel.playlists = "assets/playlists".into();
|
||||||
config.storage.filler = "assets/media_filler/filler_0.mp4".into();
|
config.storage.filler = "assets/media_filler/filler_0.mp4".into();
|
||||||
config.output.mode = Null;
|
config.output.mode = Null;
|
||||||
config.output.output_count = 1;
|
config.output.output_count = 1;
|
||||||
@ -148,7 +148,7 @@ fn playlist_next_missing() {
|
|||||||
config.playlist.start_sec = Some(0.0);
|
config.playlist.start_sec = Some(0.0);
|
||||||
config.playlist.length = "24:00:00".into();
|
config.playlist.length = "24:00:00".into();
|
||||||
config.playlist.length_sec = Some(86400.0);
|
config.playlist.length_sec = Some(86400.0);
|
||||||
config.channel.playlist_path = "assets/playlists".into();
|
config.channel.playlists = "assets/playlists".into();
|
||||||
config.storage.filler = "assets/media_filler/filler_0.mp4".into();
|
config.storage.filler = "assets/media_filler/filler_0.mp4".into();
|
||||||
config.output.mode = Null;
|
config.output.mode = Null;
|
||||||
config.output.output_count = 1;
|
config.output.output_count = 1;
|
||||||
@ -182,7 +182,7 @@ fn playlist_to_short() {
|
|||||||
config.playlist.start_sec = Some(21600.0);
|
config.playlist.start_sec = Some(21600.0);
|
||||||
config.playlist.length = "24:00:00".into();
|
config.playlist.length = "24:00:00".into();
|
||||||
config.playlist.length_sec = Some(86400.0);
|
config.playlist.length_sec = Some(86400.0);
|
||||||
config.channel.playlist_path = "assets/playlists".into();
|
config.channel.playlists = "assets/playlists".into();
|
||||||
config.storage.filler = "assets/media_filler/filler_0.mp4".into();
|
config.storage.filler = "assets/media_filler/filler_0.mp4".into();
|
||||||
config.output.mode = Null;
|
config.output.mode = Null;
|
||||||
config.output.output_count = 1;
|
config.output.output_count = 1;
|
||||||
@ -216,7 +216,7 @@ fn playlist_init_after_list_end() {
|
|||||||
config.playlist.start_sec = Some(21600.0);
|
config.playlist.start_sec = Some(21600.0);
|
||||||
config.playlist.length = "24:00:00".into();
|
config.playlist.length = "24:00:00".into();
|
||||||
config.playlist.length_sec = Some(86400.0);
|
config.playlist.length_sec = Some(86400.0);
|
||||||
config.channel.playlist_path = "assets/playlists".into();
|
config.channel.playlists = "assets/playlists".into();
|
||||||
config.storage.filler = "assets/media_filler/filler_0.mp4".into();
|
config.storage.filler = "assets/media_filler/filler_0.mp4".into();
|
||||||
config.output.mode = Null;
|
config.output.mode = Null;
|
||||||
config.output.output_count = 1;
|
config.output.output_count = 1;
|
||||||
@ -250,7 +250,7 @@ fn playlist_change_at_midnight() {
|
|||||||
config.playlist.start_sec = Some(0.0);
|
config.playlist.start_sec = Some(0.0);
|
||||||
config.playlist.length = "24:00:00".into();
|
config.playlist.length = "24:00:00".into();
|
||||||
config.playlist.length_sec = Some(86400.0);
|
config.playlist.length_sec = Some(86400.0);
|
||||||
config.channel.playlist_path = "assets/playlists".into();
|
config.channel.playlists = "assets/playlists".into();
|
||||||
config.storage.filler = "assets/media_filler/filler_0.mp4".into();
|
config.storage.filler = "assets/media_filler/filler_0.mp4".into();
|
||||||
config.output.mode = Null;
|
config.output.mode = Null;
|
||||||
config.output.output_count = 1;
|
config.output.output_count = 1;
|
||||||
@ -284,7 +284,7 @@ fn playlist_change_before_midnight() {
|
|||||||
config.playlist.start_sec = Some(0.0);
|
config.playlist.start_sec = Some(0.0);
|
||||||
config.playlist.length = "24:00:00".into();
|
config.playlist.length = "24:00:00".into();
|
||||||
config.playlist.length_sec = Some(86400.0);
|
config.playlist.length_sec = Some(86400.0);
|
||||||
config.channel.playlist_path = "assets/playlists".into();
|
config.channel.playlists = "assets/playlists".into();
|
||||||
config.storage.filler = "assets/media_filler/filler_0.mp4".into();
|
config.storage.filler = "assets/media_filler/filler_0.mp4".into();
|
||||||
config.output.mode = Null;
|
config.output.mode = Null;
|
||||||
config.output.output_count = 1;
|
config.output.output_count = 1;
|
||||||
@ -318,7 +318,7 @@ fn playlist_change_at_six() {
|
|||||||
config.playlist.start_sec = Some(21600.0);
|
config.playlist.start_sec = Some(21600.0);
|
||||||
config.playlist.length = "24:00:00".into();
|
config.playlist.length = "24:00:00".into();
|
||||||
config.playlist.length_sec = Some(86400.0);
|
config.playlist.length_sec = Some(86400.0);
|
||||||
config.channel.playlist_path = "assets/playlists".into();
|
config.channel.playlists = "assets/playlists".into();
|
||||||
config.storage.filler = "assets/media_filler/filler_0.mp4".into();
|
config.storage.filler = "assets/media_filler/filler_0.mp4".into();
|
||||||
config.output.mode = Null;
|
config.output.mode = Null;
|
||||||
config.output.output_count = 1;
|
config.output.output_count = 1;
|
||||||
|
@ -18,8 +18,8 @@ async fn prepare_config() -> (PlayoutConfig, ChannelManager) {
|
|||||||
|
|
||||||
sqlx::query(
|
sqlx::query(
|
||||||
r#"
|
r#"
|
||||||
UPDATE global SET public_root = "assets/hls", logging_path = "assets/log", playlist_root = "assets/playlists", storage_root = "assets/storage";
|
UPDATE global SET public = "assets/hls", logs = "assets/log", playlists = "assets/playlists", storage = "assets/storage";
|
||||||
UPDATE channels SET hls_path = "assets/hls", playlist_path = "assets/playlists", storage_path = "assets/storage";
|
UPDATE channels SET public = "assets/hls", playlists = "assets/playlists", storage = "assets/storage";
|
||||||
UPDATE configurations SET processing_width = 1024, processing_height = 576;
|
UPDATE configurations SET processing_width = 1024, processing_height = 576;
|
||||||
"#,
|
"#,
|
||||||
)
|
)
|
Loading…
Reference in New Issue
Block a user