Use enum for Role everywhere, fix time shift, fix #433, get config also as normal user
This commit is contained in:
parent
809b649226
commit
7d3173533f
17
Cargo.lock
generated
17
Cargo.lock
generated
@ -565,9 +565,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "asynchronous-codec"
|
name = "asynchronous-codec"
|
||||||
version = "0.6.2"
|
version = "0.7.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4057f2c32adbb2fc158e22fb38433c8e9bbf76b75a4732c7c0cbaf695fb65568"
|
checksum = "a860072022177f903e59730004fb5dc13db9275b79bb2aef7ba8ce831956c233"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bytes",
|
"bytes",
|
||||||
"futures-sink",
|
"futures-sink",
|
||||||
@ -1134,7 +1134,7 @@ checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ffplayout"
|
name = "ffplayout"
|
||||||
version = "0.20.0-beta4"
|
version = "0.20.0-beta5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"chrono",
|
"chrono",
|
||||||
"clap",
|
"clap",
|
||||||
@ -1156,7 +1156,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ffplayout-api"
|
name = "ffplayout-api"
|
||||||
version = "0.20.0-beta4"
|
version = "0.20.0-beta5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"actix-files",
|
"actix-files",
|
||||||
"actix-multipart",
|
"actix-multipart",
|
||||||
@ -1192,7 +1192,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ffplayout-lib"
|
name = "ffplayout-lib"
|
||||||
version = "0.20.0-beta4"
|
version = "0.20.0-beta5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"chrono",
|
"chrono",
|
||||||
"crossbeam-channel",
|
"crossbeam-channel",
|
||||||
@ -3189,7 +3189,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tests"
|
name = "tests"
|
||||||
version = "0.20.0-beta4"
|
version = "0.20.0-beta5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"chrono",
|
"chrono",
|
||||||
"crossbeam-channel",
|
"crossbeam-channel",
|
||||||
@ -3755,8 +3755,9 @@ checksum = "2a0956f1ba7c7909bfb66c2e9e4124ab6f6482560f6628b5aaeba39207c9aad9"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zeromq"
|
name = "zeromq"
|
||||||
version = "0.3.3"
|
version = "0.3.4"
|
||||||
source = "git+https://github.com/zeromq/zmq.rs.git#7baeeffde9e4cb9741d1841cfdee5f00f354b578"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2db35fbc7d9082d39a85c9831ec5dc7b7b135038d2f00bb5ff2a4c0275893da1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"async-std",
|
"async-std",
|
||||||
"async-trait",
|
"async-trait",
|
||||||
|
@ -4,7 +4,7 @@ default-members = ["ffplayout-api", "ffplayout-engine", "tests"]
|
|||||||
resolver = "2"
|
resolver = "2"
|
||||||
|
|
||||||
[workspace.package]
|
[workspace.package]
|
||||||
version = "0.20.0-beta4"
|
version = "0.20.0-beta5"
|
||||||
license = "GPL-3.0"
|
license = "GPL-3.0"
|
||||||
repository = "https://github.com/ffplayout/ffplayout"
|
repository = "https://github.com/ffplayout/ffplayout"
|
||||||
authors = ["Jonathan Baecker <jonbae77@gmail.com>"]
|
authors = ["Jonathan Baecker <jonbae77@gmail.com>"]
|
||||||
|
@ -1,6 +1,11 @@
|
|||||||
|
use std::{env, path::Path};
|
||||||
|
|
||||||
use static_files::NpmBuild;
|
use static_files::NpmBuild;
|
||||||
|
|
||||||
fn main() -> std::io::Result<()> {
|
fn main() -> std::io::Result<()> {
|
||||||
|
let gen_path = Path::new(&env::var("OUT_DIR").unwrap()).join("generated.rs");
|
||||||
|
|
||||||
|
if Ok("release".to_owned()) == env::var("PROFILE") || !gen_path.is_file() {
|
||||||
NpmBuild::new("../ffplayout-frontend")
|
NpmBuild::new("../ffplayout-frontend")
|
||||||
.install()?
|
.install()?
|
||||||
.run("generate")?
|
.run("generate")?
|
||||||
@ -8,4 +13,7 @@ fn main() -> std::io::Result<()> {
|
|||||||
.change_detection()
|
.change_detection()
|
||||||
.to_resource_dir()
|
.to_resource_dir()
|
||||||
.build()
|
.build()
|
||||||
|
} else {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@ use chrono::{Duration, Utc};
|
|||||||
use jsonwebtoken::{self, DecodingKey, EncodingKey, Header, Validation};
|
use jsonwebtoken::{self, DecodingKey, EncodingKey, Header, Validation};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::utils::GlobalSettings;
|
use crate::utils::{GlobalSettings, Role};
|
||||||
|
|
||||||
// Token lifetime
|
// Token lifetime
|
||||||
const JWT_EXPIRATION_DAYS: i64 = 7;
|
const JWT_EXPIRATION_DAYS: i64 = 7;
|
||||||
@ -13,12 +13,12 @@ const JWT_EXPIRATION_DAYS: i64 = 7;
|
|||||||
pub struct Claims {
|
pub struct Claims {
|
||||||
pub id: i32,
|
pub id: i32,
|
||||||
pub username: String,
|
pub username: String,
|
||||||
pub role: String,
|
pub role: Role,
|
||||||
exp: i64,
|
exp: i64,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Claims {
|
impl Claims {
|
||||||
pub fn new(id: i32, username: String, role: String) -> Self {
|
pub fn new(id: i32, username: String, role: Role) -> Self {
|
||||||
Self {
|
Self {
|
||||||
id,
|
id,
|
||||||
username,
|
username,
|
||||||
|
@ -170,7 +170,7 @@ pub async fn login(pool: web::Data<Pool<Sqlite>>, credentials: web::Json<User>)
|
|||||||
{
|
{
|
||||||
let role = handles::select_role(&conn, &user.role_id.unwrap_or_default())
|
let role = handles::select_role(&conn, &user.role_id.unwrap_or_default())
|
||||||
.await
|
.await
|
||||||
.unwrap_or_else(|_| "guest".to_string());
|
.unwrap_or(Role::Guest);
|
||||||
let claims = Claims::new(user.id, user.username.clone(), role.clone());
|
let claims = Claims::new(user.id, user.username.clone(), role.clone());
|
||||||
|
|
||||||
if let Ok(token) = create_jwt(claims) {
|
if let Ok(token) = create_jwt(claims) {
|
||||||
@ -340,7 +340,7 @@ async fn get_channel(
|
|||||||
/// curl -X GET http://127.0.0.1:8787/api/channels -H "Authorization: Bearer <TOKEN>"
|
/// curl -X GET http://127.0.0.1:8787/api/channels -H "Authorization: Bearer <TOKEN>"
|
||||||
/// ```
|
/// ```
|
||||||
#[get("/channels")]
|
#[get("/channels")]
|
||||||
#[has_any_role("Role::Admin", type = "Role")]
|
#[has_any_role("Role::Admin", "Role::User", type = "Role")]
|
||||||
async fn get_all_channels(pool: web::Data<Pool<Sqlite>>) -> Result<impl Responder, ServiceError> {
|
async fn get_all_channels(pool: web::Data<Pool<Sqlite>>) -> Result<impl Responder, ServiceError> {
|
||||||
if let Ok(channel) = handles::select_all_channels(&pool.into_inner()).await {
|
if let Ok(channel) = handles::select_all_channels(&pool.into_inner()).await {
|
||||||
return Ok(web::Json(channel));
|
return Ok(web::Json(channel));
|
||||||
|
@ -13,12 +13,7 @@ use crate::db::{
|
|||||||
db_pool,
|
db_pool,
|
||||||
models::{Channel, TextPreset, User},
|
models::{Channel, TextPreset, User},
|
||||||
};
|
};
|
||||||
use crate::utils::{db_path, local_utc_offset, GlobalSettings};
|
use crate::utils::{db_path, local_utc_offset, GlobalSettings, Role};
|
||||||
|
|
||||||
#[derive(Debug, sqlx::FromRow)]
|
|
||||||
struct Role {
|
|
||||||
name: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn create_schema(conn: &Pool<Sqlite>) -> Result<SqliteQueryResult, sqlx::Error> {
|
async fn create_schema(conn: &Pool<Sqlite>) -> Result<SqliteQueryResult, sqlx::Error> {
|
||||||
let query = "PRAGMA foreign_keys = ON;
|
let query = "PRAGMA foreign_keys = ON;
|
||||||
@ -217,11 +212,11 @@ pub async fn select_last_channel(conn: &Pool<Sqlite>) -> Result<i32, sqlx::Error
|
|||||||
sqlx::query_scalar(query).fetch_one(conn).await
|
sqlx::query_scalar(query).fetch_one(conn).await
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn select_role(conn: &Pool<Sqlite>, id: &i32) -> Result<String, sqlx::Error> {
|
pub async fn select_role(conn: &Pool<Sqlite>, id: &i32) -> Result<Role, sqlx::Error> {
|
||||||
let query = "SELECT name FROM roles WHERE id = $1";
|
let query = "SELECT name FROM roles WHERE id = $1";
|
||||||
let result: Role = sqlx::query_as(query).bind(id).fetch_one(conn).await?;
|
let result: Role = sqlx::query_as(query).bind(id).fetch_one(conn).await?;
|
||||||
|
|
||||||
Ok(result.name)
|
Ok(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn select_login(conn: &Pool<Sqlite>, user: &str) -> Result<User, sqlx::Error> {
|
pub async fn select_login(conn: &Pool<Sqlite>, user: &str) -> Result<User, sqlx::Error> {
|
||||||
|
@ -25,6 +25,7 @@ pub struct User {
|
|||||||
#[serde(skip_serializing)]
|
#[serde(skip_serializing)]
|
||||||
pub channel_id: Option<i32>,
|
pub channel_id: Option<i32>,
|
||||||
#[sqlx(default)]
|
#[sqlx(default)]
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
pub token: Option<String>,
|
pub token: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@ pub mod utils;
|
|||||||
|
|
||||||
use api::{auth, routes::*};
|
use api::{auth, routes::*};
|
||||||
use db::{db_pool, models::LoginUser};
|
use db::{db_pool, models::LoginUser};
|
||||||
use utils::{args_parse::Args, control::ProcessControl, db_path, init_config, run_args, Role};
|
use utils::{args_parse::Args, control::ProcessControl, db_path, init_config, run_args};
|
||||||
|
|
||||||
use ffplayout_lib::utils::{init_logging, PlayoutConfig};
|
use ffplayout_lib::utils::{init_logging, PlayoutConfig};
|
||||||
|
|
||||||
@ -29,7 +29,7 @@ async fn validator(
|
|||||||
// We just get permissions from JWT
|
// We just get permissions from JWT
|
||||||
match auth::decode_jwt(credentials.token()).await {
|
match auth::decode_jwt(credentials.token()).await {
|
||||||
Ok(claims) => {
|
Ok(claims) => {
|
||||||
req.attach(vec![Role::set_role(&claims.role)]);
|
req.attach(vec![claims.role]);
|
||||||
|
|
||||||
req.extensions_mut()
|
req.extensions_mut()
|
||||||
.insert(LoginUser::new(claims.id, claims.username));
|
.insert(LoginUser::new(claims.id, claims.username));
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
use std::{
|
use std::{
|
||||||
env,
|
env,
|
||||||
error::Error,
|
error::Error,
|
||||||
|
fmt,
|
||||||
fs::{self, File},
|
fs::{self, File},
|
||||||
io::{stdin, stdout, Write},
|
io::{stdin, stdout, Write},
|
||||||
path::Path,
|
path::Path,
|
||||||
|
str::FromStr,
|
||||||
};
|
};
|
||||||
|
|
||||||
use chrono::{format::ParseErrorKind, prelude::*};
|
use chrono::{format::ParseErrorKind, prelude::*};
|
||||||
@ -11,9 +13,9 @@ use faccess::PathExt;
|
|||||||
use once_cell::sync::OnceCell;
|
use once_cell::sync::OnceCell;
|
||||||
use path_clean::PathClean;
|
use path_clean::PathClean;
|
||||||
use rpassword::read_password;
|
use rpassword::read_password;
|
||||||
use serde::{de, Deserialize, Deserializer};
|
use serde::{de, Deserialize, Deserializer, Serialize};
|
||||||
use simplelog::*;
|
use simplelog::*;
|
||||||
use sqlx::{Pool, Sqlite};
|
use sqlx::{sqlite::SqliteRow, FromRow, Pool, Row, Sqlite};
|
||||||
|
|
||||||
pub mod args_parse;
|
pub mod args_parse;
|
||||||
pub mod channels;
|
pub mod channels;
|
||||||
@ -30,7 +32,7 @@ use crate::db::{
|
|||||||
use crate::utils::{args_parse::Args, errors::ServiceError};
|
use crate::utils::{args_parse::Args, errors::ServiceError};
|
||||||
use ffplayout_lib::utils::{time_to_sec, PlayoutConfig};
|
use ffplayout_lib::utils::{time_to_sec, PlayoutConfig};
|
||||||
|
|
||||||
#[derive(Clone, Eq, PartialEq)]
|
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
|
||||||
pub enum Role {
|
pub enum Role {
|
||||||
Admin,
|
Admin,
|
||||||
User,
|
User,
|
||||||
@ -47,6 +49,51 @@ impl Role {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl FromStr for Role {
|
||||||
|
type Err = String;
|
||||||
|
|
||||||
|
fn from_str(input: &str) -> Result<Self, Self::Err> {
|
||||||
|
match input {
|
||||||
|
"admin" => Ok(Self::Admin),
|
||||||
|
"user" => Ok(Self::User),
|
||||||
|
_ => Ok(Self::Guest),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for Role {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
match *self {
|
||||||
|
Self::Admin => write!(f, "admin"),
|
||||||
|
Self::User => write!(f, "user"),
|
||||||
|
Self::Guest => write!(f, "guest"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'r> sqlx::decode::Decode<'r, ::sqlx::Sqlite> for Role
|
||||||
|
where
|
||||||
|
&'r str: sqlx::decode::Decode<'r, sqlx::Sqlite>,
|
||||||
|
{
|
||||||
|
fn decode(
|
||||||
|
value: <sqlx::Sqlite as sqlx::database::HasValueRef<'r>>::ValueRef,
|
||||||
|
) -> Result<Role, Box<dyn Error + 'static + Send + Sync>> {
|
||||||
|
let value = <&str as sqlx::decode::Decode<sqlx::Sqlite>>::decode(value)?;
|
||||||
|
|
||||||
|
Ok(value.parse()?)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromRow<'_, SqliteRow> for Role {
|
||||||
|
fn from_row(row: &SqliteRow) -> sqlx::Result<Self> {
|
||||||
|
match row.get("name") {
|
||||||
|
"admin" => Ok(Self::Admin),
|
||||||
|
"user" => Ok(Self::User),
|
||||||
|
_ => Ok(Self::Guest),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, sqlx::FromRow)]
|
#[derive(Debug, sqlx::FromRow)]
|
||||||
pub struct GlobalSettings {
|
pub struct GlobalSettings {
|
||||||
pub secret: String,
|
pub secret: String,
|
||||||
|
@ -26,7 +26,7 @@ serde = { version = "1.0", features = ["derive"] }
|
|||||||
serde_json = "1.0"
|
serde_json = "1.0"
|
||||||
simplelog = { version = "0.12", features = ["paris"] }
|
simplelog = { version = "0.12", features = ["paris"] }
|
||||||
tiny_http = { version = "0.12", default-features = false }
|
tiny_http = { version = "0.12", default-features = false }
|
||||||
zeromq = { git = "https://github.com/zeromq/zmq.rs.git", default-features = false, features = [
|
zeromq = { version = "0.3", default-features = false, features = [
|
||||||
"async-std-runtime",
|
"async-std-runtime",
|
||||||
"tcp-transport",
|
"tcp-transport",
|
||||||
] }
|
] }
|
||||||
|
@ -277,8 +277,9 @@ impl CurrentProgram {
|
|||||||
|
|
||||||
// de-instance node to preserve original values in list
|
// de-instance node to preserve original values in list
|
||||||
let mut node_clone = nodes[index].clone();
|
let mut node_clone = nodes[index].clone();
|
||||||
|
node_clone.seek = time_sec
|
||||||
|
- (node_clone.begin.unwrap() - *self.playout_stat.time_shift.lock().unwrap());
|
||||||
|
|
||||||
node_clone.seek = time_sec - node_clone.begin.unwrap();
|
|
||||||
self.current_node = handle_list_init(
|
self.current_node = handle_list_init(
|
||||||
&self.config,
|
&self.config,
|
||||||
node_clone,
|
node_clone,
|
||||||
|
@ -144,6 +144,7 @@ pub fn write_hls(
|
|||||||
let config_clone = config.clone();
|
let config_clone = config.clone();
|
||||||
let ff_log_format = format!("level+{}", config.logging.ffmpeg_level.to_lowercase());
|
let ff_log_format = format!("level+{}", config.logging.ffmpeg_level.to_lowercase());
|
||||||
let play_stat = playout_stat.clone();
|
let play_stat = playout_stat.clone();
|
||||||
|
let play_stat2 = playout_stat.clone();
|
||||||
let proc_control_c = proc_control.clone();
|
let proc_control_c = proc_control.clone();
|
||||||
|
|
||||||
let get_source = source_generator(
|
let get_source = source_generator(
|
||||||
@ -177,12 +178,15 @@ pub fn write_hls(
|
|||||||
);
|
);
|
||||||
|
|
||||||
if config.task.enable {
|
if config.task.enable {
|
||||||
|
if config.task.path.is_file() {
|
||||||
let task_config = config.clone();
|
let task_config = config.clone();
|
||||||
let task_node = node.clone();
|
let task_node = node.clone();
|
||||||
let server_running = proc_control.server_is_running.load(Ordering::SeqCst);
|
let server_running = proc_control.server_is_running.load(Ordering::SeqCst);
|
||||||
|
let stat = play_stat2.clone();
|
||||||
|
|
||||||
if config.task.path.is_file() {
|
thread::spawn(move || {
|
||||||
thread::spawn(move || task_runner::run(task_config, task_node, server_running));
|
task_runner::run(task_config, task_node, stat, server_running)
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
error!(
|
error!(
|
||||||
"<bright-blue>{:?}</> executable not exists!",
|
"<bright-blue>{:?}</> executable not exists!",
|
||||||
|
@ -45,6 +45,7 @@ pub fn player(
|
|||||||
let mut buffer = [0; 65088];
|
let mut buffer = [0; 65088];
|
||||||
let mut live_on = false;
|
let mut live_on = false;
|
||||||
let playlist_init = playout_stat.list_init.clone();
|
let playlist_init = playout_stat.list_init.clone();
|
||||||
|
let play_stat = playout_stat.clone();
|
||||||
|
|
||||||
// get source iterator
|
// get source iterator
|
||||||
let get_source = source_generator(
|
let get_source = source_generator(
|
||||||
@ -111,12 +112,15 @@ pub fn player(
|
|||||||
);
|
);
|
||||||
|
|
||||||
if config.task.enable {
|
if config.task.enable {
|
||||||
|
if config.task.path.is_file() {
|
||||||
let task_config = config.clone();
|
let task_config = config.clone();
|
||||||
let task_node = node.clone();
|
let task_node = node.clone();
|
||||||
let server_running = proc_control.server_is_running.load(Ordering::SeqCst);
|
let server_running = proc_control.server_is_running.load(Ordering::SeqCst);
|
||||||
|
let stat = play_stat.clone();
|
||||||
|
|
||||||
if config.task.path.is_file() {
|
thread::spawn(move || {
|
||||||
thread::spawn(move || task_runner::run(task_config, task_node, server_running));
|
task_runner::run(task_config, task_node, stat, server_running)
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
error!(
|
error!(
|
||||||
"<bright-blue>{:?}</> executable not exists!",
|
"<bright-blue>{:?}</> executable not exists!",
|
||||||
|
@ -376,11 +376,17 @@ fn control_text(
|
|||||||
/// media info: get infos about current clip
|
/// media info: get infos about current clip
|
||||||
fn media_current(
|
fn media_current(
|
||||||
config: &PlayoutConfig,
|
config: &PlayoutConfig,
|
||||||
|
playout_stat: &PlayoutStatus,
|
||||||
play_control: &PlayerControl,
|
play_control: &PlayerControl,
|
||||||
proc: &ProcessControl,
|
proc: &ProcessControl,
|
||||||
) -> Response<Cursor<Vec<u8>>> {
|
) -> Response<Cursor<Vec<u8>>> {
|
||||||
if let Some(media) = play_control.current_media.lock().unwrap().clone() {
|
if let Some(media) = play_control.current_media.lock().unwrap().clone() {
|
||||||
let data_map = get_data_map(config, media, proc.server_is_running.load(Ordering::SeqCst));
|
let data_map = get_data_map(
|
||||||
|
config,
|
||||||
|
media,
|
||||||
|
playout_stat,
|
||||||
|
proc.server_is_running.load(Ordering::SeqCst),
|
||||||
|
);
|
||||||
|
|
||||||
return json_response(data_map);
|
return json_response(data_map);
|
||||||
};
|
};
|
||||||
@ -389,14 +395,18 @@ fn media_current(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// media info: get infos about next clip
|
/// media info: get infos about next clip
|
||||||
fn media_next(config: &PlayoutConfig, play_control: &PlayerControl) -> Response<Cursor<Vec<u8>>> {
|
fn media_next(
|
||||||
|
config: &PlayoutConfig,
|
||||||
|
playout_stat: &PlayoutStatus,
|
||||||
|
play_control: &PlayerControl,
|
||||||
|
) -> Response<Cursor<Vec<u8>>> {
|
||||||
let index = play_control.current_index.load(Ordering::SeqCst);
|
let index = play_control.current_index.load(Ordering::SeqCst);
|
||||||
let current_list = play_control.current_list.lock().unwrap();
|
let current_list = play_control.current_list.lock().unwrap();
|
||||||
|
|
||||||
if index < current_list.len() {
|
if index < current_list.len() {
|
||||||
let media = current_list[index].clone();
|
let media = current_list[index].clone();
|
||||||
|
|
||||||
let data_map = get_data_map(config, media, false);
|
let data_map = get_data_map(config, media, playout_stat, false);
|
||||||
|
|
||||||
return json_response(data_map);
|
return json_response(data_map);
|
||||||
}
|
}
|
||||||
@ -405,14 +415,18 @@ fn media_next(config: &PlayoutConfig, play_control: &PlayerControl) -> Response<
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// media info: get infos about last clip
|
/// media info: get infos about last clip
|
||||||
fn media_last(config: &PlayoutConfig, play_control: &PlayerControl) -> Response<Cursor<Vec<u8>>> {
|
fn media_last(
|
||||||
|
config: &PlayoutConfig,
|
||||||
|
playout_stat: &PlayoutStatus,
|
||||||
|
play_control: &PlayerControl,
|
||||||
|
) -> Response<Cursor<Vec<u8>>> {
|
||||||
let index = play_control.current_index.load(Ordering::SeqCst);
|
let index = play_control.current_index.load(Ordering::SeqCst);
|
||||||
let current_list = play_control.current_list.lock().unwrap();
|
let current_list = play_control.current_list.lock().unwrap();
|
||||||
|
|
||||||
if index > 1 && index - 2 < current_list.len() {
|
if index > 1 && index - 2 < current_list.len() {
|
||||||
let media = current_list[index - 2].clone();
|
let media = current_list[index - 2].clone();
|
||||||
|
|
||||||
let data_map = get_data_map(config, media, false);
|
let data_map = get_data_map(config, media, playout_stat, false);
|
||||||
|
|
||||||
return json_response(data_map);
|
return json_response(data_map);
|
||||||
}
|
}
|
||||||
@ -464,13 +478,18 @@ fn build_response(
|
|||||||
} else if let Some(media_value) = data.get("media").and_then(|m| m.as_str()) {
|
} else if let Some(media_value) = data.get("media").and_then(|m| m.as_str()) {
|
||||||
match media_value {
|
match media_value {
|
||||||
"current" => {
|
"current" => {
|
||||||
let _ = request.respond(media_current(config, play_control, proc_control));
|
let _ = request.respond(media_current(
|
||||||
|
config,
|
||||||
|
playout_stat,
|
||||||
|
play_control,
|
||||||
|
proc_control,
|
||||||
|
));
|
||||||
}
|
}
|
||||||
"next" => {
|
"next" => {
|
||||||
let _ = request.respond(media_next(config, play_control));
|
let _ = request.respond(media_next(config, playout_stat, play_control));
|
||||||
}
|
}
|
||||||
"last" => {
|
"last" => {
|
||||||
let _ = request.respond(media_last(config, play_control));
|
let _ = request.respond(media_last(config, playout_stat, play_control));
|
||||||
}
|
}
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,7 @@ use ffplayout_lib::{
|
|||||||
filter::Filters,
|
filter::Filters,
|
||||||
utils::{
|
utils::{
|
||||||
config::Template, get_sec, parse_log_level_filter, sec_to_time, time_to_sec, Media,
|
config::Template, get_sec, parse_log_level_filter, sec_to_time, time_to_sec, Media,
|
||||||
OutputMode::*, PlayoutConfig, ProcessMode::*,
|
OutputMode::*, PlayoutConfig, PlayoutStatus, ProcessMode::*,
|
||||||
},
|
},
|
||||||
vec_strings,
|
vec_strings,
|
||||||
};
|
};
|
||||||
@ -258,10 +258,13 @@ pub fn get_media_map(media: Media) -> Value {
|
|||||||
pub fn get_data_map(
|
pub fn get_data_map(
|
||||||
config: &PlayoutConfig,
|
config: &PlayoutConfig,
|
||||||
media: Media,
|
media: Media,
|
||||||
|
playout_stat: &PlayoutStatus,
|
||||||
server_is_running: bool,
|
server_is_running: bool,
|
||||||
) -> Map<String, Value> {
|
) -> Map<String, Value> {
|
||||||
let mut data_map = Map::new();
|
let mut data_map = Map::new();
|
||||||
let begin = media.begin.unwrap_or(0.0);
|
let current_time = get_sec();
|
||||||
|
let shift = *playout_stat.time_shift.lock().unwrap();
|
||||||
|
let begin = media.begin.unwrap_or(0.0) - shift;
|
||||||
|
|
||||||
data_map.insert("play_mode".to_string(), json!(config.processing.mode));
|
data_map.insert("play_mode".to_string(), json!(config.processing.mode));
|
||||||
data_map.insert("ingest_runs".to_string(), json!(server_is_running));
|
data_map.insert("ingest_runs".to_string(), json!(server_is_running));
|
||||||
@ -269,7 +272,7 @@ pub fn get_data_map(
|
|||||||
data_map.insert("start_sec".to_string(), json!(begin));
|
data_map.insert("start_sec".to_string(), json!(begin));
|
||||||
|
|
||||||
if begin > 0.0 {
|
if begin > 0.0 {
|
||||||
let played_time = get_sec() - begin;
|
let played_time = current_time - begin;
|
||||||
let remaining_time = media.out - played_time;
|
let remaining_time = media.out - played_time;
|
||||||
|
|
||||||
data_map.insert("start_time".to_string(), json!(sec_to_time(begin)));
|
data_map.insert("start_time".to_string(), json!(sec_to_time(begin)));
|
||||||
|
@ -3,10 +3,11 @@ use std::process::Command;
|
|||||||
use simplelog::*;
|
use simplelog::*;
|
||||||
|
|
||||||
use crate::utils::get_data_map;
|
use crate::utils::get_data_map;
|
||||||
use ffplayout_lib::utils::{config::PlayoutConfig, Media};
|
use ffplayout_lib::utils::{config::PlayoutConfig, Media, PlayoutStatus};
|
||||||
|
|
||||||
pub fn run(config: PlayoutConfig, node: Media, server_running: bool) {
|
pub fn run(config: PlayoutConfig, node: Media, playout_stat: PlayoutStatus, server_running: bool) {
|
||||||
let obj = serde_json::to_string(&get_data_map(&config, node, server_running)).unwrap();
|
let obj =
|
||||||
|
serde_json::to_string(&get_data_map(&config, node, &playout_stat, server_running)).unwrap();
|
||||||
trace!("Run task: {obj}");
|
trace!("Run task: {obj}");
|
||||||
|
|
||||||
match Command::new(config.task.path).arg(obj).spawn() {
|
match Command::new(config.task.path).arg(obj).spawn() {
|
||||||
|
@ -1 +1 @@
|
|||||||
Subproject commit 0898bcb2413408cca47707db36f00c74ce55c456
|
Subproject commit 8f615c358290b263244f52d10f6783ac39c6948c
|
Loading…
Reference in New Issue
Block a user