From 1bb910d3da78a0c2c59af4b4c3005a6c617f96c7 Mon Sep 17 00:00:00 2001 From: jb-alvarado Date: Thu, 7 Apr 2022 17:44:46 +0200 Subject: [PATCH] add controller functions: next, back, reset --- src/filter/mod.rs | 17 ++++--- src/input/folder.rs | 11 ++--- src/input/playlist.rs | 96 ++++++++++++++++++++++---------------- src/main.rs | 2 +- src/output/desktop.rs | 2 +- src/output/hls.rs | 2 +- src/output/mod.rs | 14 +++--- src/output/stream.rs | 2 +- src/utils/json_reader.rs | 4 +- src/utils/mod.rs | 44 ++++++++++-------- src/utils/rpc_server.rs | 99 ++++++++++++++++++++++------------------ 11 files changed, 161 insertions(+), 132 deletions(-) diff --git a/src/filter/mod.rs b/src/filter/mod.rs index deff3a8e..be7ed418 100644 --- a/src/filter/mod.rs +++ b/src/filter/mod.rs @@ -4,7 +4,7 @@ use simplelog::*; pub mod v_drawtext; -use crate::utils::{get_delta, is_close, GlobalConfig, Media, PlayoutStatus}; +use crate::utils::{get_delta, is_close, GlobalConfig, Media}; #[derive(Debug, Clone)] struct Filters { @@ -122,7 +122,7 @@ fn scale(width: i64, height: i64, aspect: f64, chain: &mut Filters, config: &Glo } fn fade(node: &mut Media, chain: &mut Filters, codec_type: String) { - let mut t = "".to_string(); + let mut t = String::new(); if codec_type == "audio".to_string() { t = "a".to_string() @@ -290,11 +290,10 @@ fn realtime_filter( chain: &mut Filters, config: &GlobalConfig, codec_type: String, - playout_stat: &PlayoutStatus, ) { // this realtime filter is important for HLS output to stay in sync - let mut t = "".to_string(); + let mut t = String::new(); if codec_type == "audio".to_string() { t = "a".to_string() @@ -302,7 +301,7 @@ fn realtime_filter( if config.out.mode.to_lowercase() == "hls".to_string() { let mut speed_filter = format!("{t}realtime=speed=1"); - let (delta, _) = get_delta(&node.begin.unwrap(), &playout_stat, true); + let (delta, _) = get_delta(&node.begin.unwrap()); let duration = node.out - node.seek; if delta < 0.0 { @@ -317,7 +316,7 @@ fn realtime_filter( } } -pub fn filter_chains(node: &mut Media, playout_stat: &PlayoutStatus) -> Vec { +pub fn filter_chains(node: &mut Media) -> Vec { let config = GlobalConfig::global(); let mut filters = Filters::new(); @@ -355,15 +354,15 @@ pub fn filter_chains(node: &mut Media, playout_stat: &PlayoutStatus) -> Vec = vec![]; if filters.video_chain.is_some() { diff --git a/src/input/folder.rs b/src/input/folder.rs index 38cbbaf5..737e9cc3 100644 --- a/src/input/folder.rs +++ b/src/input/folder.rs @@ -12,7 +12,7 @@ use std::{ use walkdir::WalkDir; -use crate::utils::{get_sec, GlobalConfig, Media, PlayoutStatus}; +use crate::utils::{get_sec, GlobalConfig, Media}; #[derive(Debug, Clone)] pub struct Source { @@ -20,14 +20,12 @@ pub struct Source { pub nodes: Arc>>, current_node: Media, index: Arc>, - playout_stat: PlayoutStatus, } impl Source { pub fn new( current_list: Arc>>, global_index: Arc>, - playout_stat: PlayoutStatus, ) -> Self { let config = GlobalConfig::global(); let mut media_list = vec![]; @@ -72,9 +70,8 @@ impl Source { Self { config: config.clone(), nodes: current_list, - current_node: Media::new(0, "".to_string(), false), + current_node: Media::new(0, String::new(), false), index: global_index, - playout_stat, } } @@ -113,7 +110,7 @@ impl Iterator for Source { let i = *self.index.lock().unwrap(); self.current_node = self.nodes.lock().unwrap()[i].clone(); self.current_node.add_probe(); - self.current_node.add_filter(&self.playout_stat); + self.current_node.add_filter(); self.current_node.begin = Some(get_sec()); *self.index.lock().unwrap() += 1; @@ -130,7 +127,7 @@ impl Iterator for Source { self.current_node = self.nodes.lock().unwrap()[0].clone(); self.current_node.add_probe(); - self.current_node.add_filter(&self.playout_stat); + self.current_node.add_filter(); self.current_node.begin = Some(get_sec()); *self.index.lock().unwrap() = 1; diff --git a/src/input/playlist.rs b/src/input/playlist.rs index edf299f4..0736d954 100644 --- a/src/input/playlist.rs +++ b/src/input/playlist.rs @@ -2,6 +2,8 @@ use std::{ fs, path::Path, sync::{Arc, Mutex}, + thread::sleep, + time::Duration, }; use serde_json::json; @@ -22,7 +24,6 @@ pub struct CurrentProgram { json_date: String, pub nodes: Arc>>, current_node: Media, - pub init: Arc>, index: Arc>, rt_handle: Handle, is_terminated: Arc>, @@ -60,8 +61,7 @@ impl CurrentProgram { json_path: json.current_file, json_date: json.date, nodes: current_list, - current_node: Media::new(0, "".to_string(), false), - init: Arc::new(Mutex::new(true)), + current_node: Media::new(0, String::new(), false), index: global_index, rt_handle, is_terminated, @@ -115,7 +115,7 @@ impl CurrentProgram { "Playlist {} not exists!", self.json_path.clone().unwrap() ); - let mut media = Media::new(0, "".to_string(), false); + let mut media = Media::new(0, String::new(), false); media.begin = Some(get_sec()); media.duration = DUMMY_LEN; media.out = DUMMY_LEN; @@ -123,7 +123,7 @@ impl CurrentProgram { self.json_path = None; *self.nodes.lock().unwrap() = vec![media.clone()]; self.current_node = media; - *self.init.lock().unwrap() = true; + *self.playout_stat.list_init.lock().unwrap() = true; *self.index.lock().unwrap() = 0; } } @@ -132,7 +132,7 @@ impl CurrentProgram { let current_time = get_sec(); let start_sec = self.config.playlist.start_sec.unwrap(); let target_length = self.config.playlist.length_sec.unwrap(); - let (delta, total_delta) = get_delta(¤t_time, &self.playout_stat, true); + let (delta, total_delta) = get_delta(¤t_time); let mut duration = self.current_node.out.clone(); if self.current_node.duration > self.current_node.out { @@ -159,8 +159,10 @@ impl CurrentProgram { }); *self.playout_stat.current_date.lock().unwrap() = json.date.clone(); - let status_data: String = serde_json::to_string(&data).expect("Serialize status data failed"); - fs::write(self.config.general.stat_file.clone(), &status_data).expect("Unable to write file"); + let status_data: String = + serde_json::to_string(&data).expect("Serialize status data failed"); + fs::write(self.config.general.stat_file.clone(), &status_data) + .expect("Unable to write file"); self.json_path = json.current_file.clone(); self.json_mod = json.modified; @@ -169,7 +171,7 @@ impl CurrentProgram { *self.index.lock().unwrap() = 0; if json.current_file.is_none() { - *self.init.lock().unwrap() = true; + *self.playout_stat.list_init.lock().unwrap() = true; } } } @@ -203,11 +205,19 @@ impl CurrentProgram { } fn get_current_clip(&mut self) { - let time_sec = self.get_current_time(); + let mut time_sec = self.get_current_time(); + + if *self.playout_stat.current_date.lock().unwrap() == *self.playout_stat.date.lock().unwrap() + && *self.playout_stat.time_shift.lock().unwrap() != 0.0 + { + let shift = *self.playout_stat.time_shift.lock().unwrap(); + info!("Shift playlist start for {shift} seconds"); + time_sec += shift; + } for (i, item) in self.nodes.lock().unwrap().iter_mut().enumerate() { if item.begin.unwrap() + item.out - item.seek > time_sec { - *self.init.lock().unwrap() = false; + *self.playout_stat.list_init.lock().unwrap() = false; *self.index.lock().unwrap() = i; break; @@ -218,7 +228,7 @@ impl CurrentProgram { fn init_clip(&mut self) { self.get_current_clip(); - if !*self.init.lock().unwrap() { + if !*self.playout_stat.list_init.lock().unwrap() { let time_sec = self.get_current_time(); let index = *self.index.lock().unwrap(); @@ -227,7 +237,7 @@ impl CurrentProgram { *self.index.lock().unwrap() += 1; node_clone.seek = time_sec - node_clone.begin.unwrap(); - self.current_node = handle_list_init(node_clone, &self.playout_stat); + self.current_node = handle_list_init(node_clone); } } } @@ -236,7 +246,7 @@ impl Iterator for CurrentProgram { type Item = Media; fn next(&mut self) -> Option { - if *self.init.lock().unwrap() { + if *self.playout_stat.list_init.lock().unwrap() { debug!("Playlist init"); self.check_update(true); @@ -244,7 +254,7 @@ impl Iterator for CurrentProgram { self.init_clip(); } - if *self.init.lock().unwrap() { + if *self.playout_stat.list_init.lock().unwrap() { // on init load playlist, could be not long enough, // so we check if we can take the next playlist already, // or we fill the gap with a dummy. @@ -262,23 +272,23 @@ impl Iterator for CurrentProgram { self.init_clip(); } else { let mut current_time = get_sec(); - let (_, total_delta) = get_delta(¤t_time, &self.playout_stat, true); + let (_, total_delta) = get_delta(¤t_time); let mut duration = DUMMY_LEN; if DUMMY_LEN > total_delta { duration = total_delta; - *self.init.lock().unwrap() = false; + *self.playout_stat.list_init.lock().unwrap() = false; } if self.config.playlist.start_sec.unwrap() > current_time { current_time += self.config.playlist.length_sec.unwrap() + 1.0; } - let mut media = Media::new(0, "".to_string(), false); + let mut media = Media::new(0, String::new(), false); media.begin = Some(current_time); media.duration = duration; media.out = duration; - self.current_node = gen_source(media, &self.playout_stat); + self.current_node = gen_source(media); self.nodes.lock().unwrap().push(self.current_node.clone()); *self.index.lock().unwrap() = self.nodes.lock().unwrap().len(); } @@ -315,11 +325,7 @@ impl Iterator for CurrentProgram { let last_playlist = self.json_path.clone(); let last_ad = self.current_node.last_ad.clone(); self.check_for_next_playlist(); - let (_, total_delta) = get_delta( - &self.config.playlist.start_sec.unwrap(), - &self.playout_stat, - true, - ); + let (_, total_delta) = get_delta(&self.config.playlist.start_sec.unwrap()); if last_playlist == self.json_path && total_delta.abs() > self.config.general.stop_threshold @@ -327,7 +333,7 @@ impl Iterator for CurrentProgram { // Test if playlist is to early finish, // and if we have to fill it with a placeholder. let index = *self.index.lock().unwrap(); - self.current_node = Media::new(index, "".to_string(), false); + self.current_node = Media::new(index, String::new(), false); self.current_node.begin = Some(get_sec()); let mut duration = total_delta.abs(); @@ -336,12 +342,12 @@ impl Iterator for CurrentProgram { } self.current_node.duration = duration; self.current_node.out = duration; - self.current_node = gen_source(self.current_node.clone(), &self.playout_stat); + self.current_node = gen_source(self.current_node.clone()); self.nodes.lock().unwrap().push(self.current_node.clone()); self.last_next_ad(); self.current_node.last_ad = last_ad; - self.current_node.add_filter(&self.playout_stat); + self.current_node.add_filter(); *self.index.lock().unwrap() += 1; @@ -350,7 +356,7 @@ impl Iterator for CurrentProgram { *self.index.lock().unwrap() = 0; self.current_node = - gen_source(self.nodes.lock().unwrap()[0].clone(), &self.playout_stat); + gen_source(self.nodes.lock().unwrap()[0].clone()); self.last_next_ad(); self.current_node.last_ad = last_ad; @@ -371,14 +377,26 @@ fn timed_source( // check begin and length from clip // return clip only if we are in 24 hours time range - let (delta, total_delta) = get_delta(&node.begin.unwrap(), &playout_stat, true); + let (delta, total_delta) = get_delta(&node.begin.unwrap()); + let mut shifted_delta = delta; let mut new_node = node.clone(); new_node.process = Some(false); if config.playlist.length.contains(":") { - debug!("Delta: {delta:.3}"); - debug!("Total delta: {total_delta:.3}"); - let sync = check_sync(delta); + if *playout_stat.current_date.lock().unwrap() == *playout_stat.date.lock().unwrap() + && *playout_stat.time_shift.lock().unwrap() != 0.0 + { + sleep(Duration::from_millis(300)); + shifted_delta = delta - *playout_stat.time_shift.lock().unwrap(); + + debug!("Delta: {shifted_delta:.3}, shifted: {delta:.3}"); + } else { + debug!("Delta: {shifted_delta:.3}"); + } + + debug!("Total time remaining: {total_delta:.3}"); + + let sync = check_sync(shifted_delta); if !sync { new_node.cmd = None; @@ -392,7 +410,7 @@ fn timed_source( || !config.playlist.length.contains(":") { // when we are in the 24 hour range, get the clip - new_node = gen_source(node, &playout_stat); + new_node = gen_source(node); new_node.process = Some(true); } else if total_delta <= 0.0 { info!("Begin is over play time, skip: {}", node.source); @@ -403,7 +421,7 @@ fn timed_source( new_node } -fn gen_source(mut node: Media, playout_stat: &PlayoutStatus) -> Media { +fn gen_source(mut node: Media) -> Media { if Path::new(&node.source).is_file() { node.add_probe(); node.cmd = Some(seek_and_length( @@ -412,7 +430,7 @@ fn gen_source(mut node: Media, playout_stat: &PlayoutStatus) -> Media { node.out, node.duration, )); - node.add_filter(&playout_stat); + node.add_filter(); } else { if node.source.chars().count() == 0 { warn!( @@ -425,17 +443,17 @@ fn gen_source(mut node: Media, playout_stat: &PlayoutStatus) -> Media { let (source, cmd) = gen_dummy(node.out - node.seek); node.source = source; node.cmd = Some(cmd); - node.add_filter(&playout_stat); + node.add_filter(); } node } -fn handle_list_init(mut node: Media, playout_stat: &PlayoutStatus) -> Media { +fn handle_list_init(mut node: Media) -> Media { // handle init clip, but this clip can be the last one in playlist, // this we have to figure out and calculate the right length - let (_, total_delta) = get_delta(&node.begin.unwrap(), &playout_stat, true); + let (_, total_delta) = get_delta(&node.begin.unwrap()); let mut out = node.out; if node.out - node.seek > total_delta { @@ -444,7 +462,7 @@ fn handle_list_init(mut node: Media, playout_stat: &PlayoutStatus) -> Media { node.out = out; - let new_node = gen_source(node, &playout_stat); + let new_node = gen_source(node); new_node } diff --git a/src/main.rs b/src/main.rs index 0676bdc7..cc4dd126 100644 --- a/src/main.rs +++ b/src/main.rs @@ -38,7 +38,7 @@ fn main() { if !PathBuf::from(config.general.stat_file.clone()).exists() { let data = json!({ "time_shift": 0.0, - "date": "".to_string(), + "date": String::new(), }); let json: String = serde_json::to_string(&data).expect("Serialize status data failed"); diff --git a/src/output/desktop.rs b/src/output/desktop.rs index 052b429e..f5523b1f 100644 --- a/src/output/desktop.rs +++ b/src/output/desktop.rs @@ -29,7 +29,7 @@ pub fn output(log_format: String) -> process::Child { ); let mut filter: String = "null,".to_string(); - filter.push_str(v_drawtext::filter_node(&mut Media::new(0, "".to_string(), false)).as_str()); + filter.push_str(v_drawtext::filter_node(&mut Media::new(0, String::new(), false)).as_str()); enc_filter = vec!["-vf".to_string(), filter]; } diff --git a/src/output/hls.rs b/src/output/hls.rs index 6156158e..2d9eeb46 100644 --- a/src/output/hls.rs +++ b/src/output/hls.rs @@ -37,7 +37,7 @@ pub fn write_hls( let dec_settings = config.out.clone().output_cmd.unwrap(); let ff_log_format = format!("level+{}", config.logging.ffmpeg_level.to_lowercase()); - let (get_source, _) = source_generator( + let get_source = source_generator( rt_handle, config.clone(), play_control.current_list.clone(), diff --git a/src/output/mod.rs b/src/output/mod.rs index b98a46cd..4773e0ef 100644 --- a/src/output/mod.rs +++ b/src/output/mod.rs @@ -34,9 +34,7 @@ pub fn source_generator( index: Arc>, playout_stat: PlayoutStatus, is_terminated: Arc>, -) -> (Box>, Arc>) { - let mut init_playlist: Arc> = Arc::new(Mutex::new(false)); - +) -> Box> { let get_source = match config.processing.clone().mode.as_str() { "folder" => { let path = config.storage.path.clone(); @@ -47,7 +45,7 @@ pub fn source_generator( info!("Playout in folder mode."); - let folder_source = Source::new(current_list, index, playout_stat); + let folder_source = Source::new(current_list, index); let (sender, receiver) = channel(); let mut watchman = watcher(sender, Duration::from_secs(2)).unwrap(); @@ -70,7 +68,6 @@ pub fn source_generator( current_list, index, ); - init_playlist = program.init.clone(); Box::new(program) as Box> } @@ -80,7 +77,7 @@ pub fn source_generator( } }; - (get_source, init_playlist) + get_source } pub fn player( @@ -96,8 +93,9 @@ pub fn player( let server_is_running: Arc> = Arc::new(Mutex::new(false)); let mut buffer: [u8; 65088] = [0; 65088]; let mut live_on = false; + let playlist_init = playout_stat.list_init.clone(); - let (get_source, init_playlist) = source_generator( + let get_source = source_generator( rt_handle, config.clone(), play_control.current_list.clone(), @@ -209,7 +207,7 @@ pub fn player( live_on = true; - *init_playlist.lock().unwrap() = true; + *playlist_init.lock().unwrap() = true; } if let Ok(receive) = ingest_receiver.try_recv() { diff --git a/src/output/stream.rs b/src/output/stream.rs index 307678c7..aaee2a89 100644 --- a/src/output/stream.rs +++ b/src/output/stream.rs @@ -32,7 +32,7 @@ pub fn output(log_format: String) -> process::Child { ); let mut filter: String = "[0:v]null,".to_string(); - filter.push_str(v_drawtext::filter_node(&mut Media::new(0, "".to_string(), false)).as_str()); + filter.push_str(v_drawtext::filter_node(&mut Media::new(0, String::new(), false)).as_str()); if config.out.preview { filter.push_str(",split=2[v_out1][v_out2]"); diff --git a/src/utils/json_reader.rs b/src/utils/json_reader.rs index f19c0eb9..6cf66ae4 100644 --- a/src/utils/json_reader.rs +++ b/src/utils/json_reader.rs @@ -23,7 +23,7 @@ pub struct Playlist { impl Playlist { fn new(date: String, start: f64) -> Self { - let mut media = Media::new(0, "".to_string(), false); + let mut media = Media::new(0, String::new(), false); media.begin = Some(start); media.duration = DUMMY_LEN; media.out = DUMMY_LEN; @@ -31,7 +31,7 @@ impl Playlist { date, start_sec: Some(start), current_file: None, - modified: Some("".to_string()), + modified: Some(String::new()), program: vec![media], } } diff --git a/src/utils/mod.rs b/src/utils/mod.rs index d8e6e4f0..c3978a59 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -1,8 +1,8 @@ use chrono::prelude::*; use chrono::Duration; use ffprobe::{ffprobe, Format, Stream}; -use serde::{Deserialize, Serialize}; use std::{ + fs, fs::metadata, io::{BufRead, BufReader, Error}, path::Path, @@ -17,6 +17,8 @@ use jsonrpc_http_server::CloseHandle; use process_control::Terminator; use regex::Regex; use simplelog::*; +use serde::{Deserialize, Serialize}; +use serde_json::json; mod arg_parse; mod config; @@ -108,6 +110,7 @@ pub struct PlayoutStatus { pub time_shift: Arc>, pub date: Arc>, pub current_date: Arc>, + pub list_init: Arc>, } impl PlayoutStatus { @@ -116,6 +119,7 @@ impl PlayoutStatus { time_shift: Arc::new(Mutex::new(0.0)), date: Arc::new(Mutex::new(String::new())), current_date: Arc::new(Mutex::new(String::new())), + list_init: Arc::new(Mutex::new(true)), } } } @@ -131,7 +135,7 @@ impl PlayerControl { pub fn new() -> Self { Self { current_media: Arc::new(Mutex::new(None)), - current_list: Arc::new(Mutex::new(vec![Media::new(0, "".to_string(), false)])), + current_list: Arc::new(Mutex::new(vec![Media::new(0, String::new(), false)])), index: Arc::new(Mutex::new(0)), } } @@ -175,7 +179,7 @@ impl Media { seek: 0.0, out: duration, duration: duration, - category: "".to_string(), + category: String::new(), source: src.clone(), cmd: Some(vec!["-i".to_string(), src]), filter: Some(vec![]), @@ -201,9 +205,9 @@ impl Media { } } - pub fn add_filter(&mut self, playout_stat: &PlayoutStatus) { + pub fn add_filter(&mut self) { let mut node = self.clone(); - self.filter = Some(filter_chains(&mut node, &playout_stat)) + self.filter = Some(filter_chains(&mut node)) } } @@ -270,6 +274,21 @@ impl MediaProbe { } } +pub fn write_status(date: String, shift: f64) { + let config = GlobalConfig::global(); + let stat_file = config.general.stat_file.clone(); + + let data = json!({ + "time_shift": shift, + "date": date, + }); + + let status_data: String = serde_json::to_string(&data) + .expect("Serialize status data failed"); + fs::write(stat_file, &status_data) + .expect("Unable to write file"); +} + // pub fn get_timestamp() -> i64 { // let local: DateTime = Local::now(); @@ -337,13 +356,13 @@ pub fn is_close(a: f64, b: f64, to: f64) -> bool { false } -pub fn get_delta(begin: &f64, playout_stat: &PlayoutStatus, shift: bool) -> (f64, f64) { +pub fn get_delta(begin: &f64) -> (f64, f64) { let config = GlobalConfig::global(); let mut current_time = get_sec(); let start = config.playlist.start_sec.unwrap(); let length = time_to_sec(&config.playlist.length); let mut target_length = 86400.0; - let mut total_delta; + let total_delta; if length > 0.0 && length != target_length { target_length = length @@ -366,17 +385,6 @@ pub fn get_delta(begin: &f64, playout_stat: &PlayoutStatus, shift: bool) -> (f64 total_delta = target_length + start - current_time; } - println!("current_delta: {current_delta}"); - println!("shift: {}", *playout_stat.time_shift.lock().unwrap()); - - if shift - && *playout_stat.current_date.lock().unwrap() == *playout_stat.date.lock().unwrap() - && *playout_stat.time_shift.lock().unwrap() != 0.0 - { - current_delta -= *playout_stat.time_shift.lock().unwrap(); - total_delta -= *playout_stat.time_shift.lock().unwrap(); - } - (current_delta, total_delta) } diff --git a/src/utils/rpc_server.rs b/src/utils/rpc_server.rs index 3af9eef4..d5c4d34c 100644 --- a/src/utils/rpc_server.rs +++ b/src/utils/rpc_server.rs @@ -1,15 +1,16 @@ -use std::fs; -use serde_json::{json, Map}; +use std::sync::{Arc, Mutex}; use jsonrpc_http_server::jsonrpc_core::{IoHandler, Params, Value}; use jsonrpc_http_server::{ hyper, AccessControlAllowOrigin, DomainsValidation, Response, RestApi, ServerBuilder, }; +use process_control::Terminator; +use serde_json::{json, Map}; use simplelog::*; use crate::utils::{ - get_delta, get_sec, sec_to_time, GlobalConfig, Media, PlayerControl, PlayoutStatus, - ProcessControl, + get_delta, get_sec, sec_to_time, write_status, GlobalConfig, Media, PlayerControl, + PlayoutStatus, ProcessControl, }; fn get_media_map(media: Media) -> Value { @@ -44,6 +45,19 @@ fn get_data_map(config: &GlobalConfig, media: Media) -> Map { data_map } +fn kill_decoder(terminator: Arc>>) -> Result<(), String> { + match &*terminator.lock().unwrap() { + Some(decoder) => unsafe { + if let Err(e) = decoder.terminate() { + return Err(format!("Terminate decoder: {e}")); + } + }, + None => return Err("No decoder terminator found".to_string()), + } + + Ok(()) +} + pub async fn run_rpc( play_control: PlayerControl, playout_stat: PlayoutStatus, @@ -52,56 +66,36 @@ pub async fn run_rpc( let config = GlobalConfig::global(); let mut io = IoHandler::default(); let play = play_control.clone(); - let stat = playout_stat.clone(); let proc = proc_control.clone(); io.add_sync_method("player", move |params: Params| { - let stat_file = config.general.stat_file.clone(); - match params { Params::Map(map) => { if map.contains_key("control") && map["control"] == "next".to_string() { - if let Some(decoder) = &*proc.decoder_term.lock().unwrap() { - unsafe { - if let Ok(_) = decoder.terminate() { - info!("Move to next clip"); - let index = *play.index.lock().unwrap(); + if let Ok(_) = kill_decoder(proc.decoder_term.clone()) { + info!("Move to next clip"); + let index = *play.index.lock().unwrap(); - if index < play.current_list.lock().unwrap().len() { - let mut data_map = Map::new(); - let mut media = - play.current_list.lock().unwrap()[index].clone(); - media.add_probe(); + if index < play.current_list.lock().unwrap().len() { + let mut data_map = Map::new(); + let mut media = play.current_list.lock().unwrap()[index].clone(); + media.add_probe(); - let (delta, _) = - get_delta(&media.begin.unwrap_or(0.0), &stat, false); + let (delta, _) = get_delta(&media.begin.unwrap_or(0.0)); + *playout_stat.time_shift.lock().unwrap() = delta; + write_status(playout_stat.current_date.lock().unwrap().clone(), delta); - let data = json!({ - "time_shift": delta, - "date": *stat.current_date.lock().unwrap(), - }); + data_map.insert("operation".to_string(), json!("Move to next clip")); + data_map.insert("media".to_string(), get_media_map(media)); - let status_data: String = serde_json::to_string(&data) - .expect("Serialize status data failed"); - fs::write(stat_file, &status_data) - .expect("Unable to write file"); - - data_map.insert( - "operation".to_string(), - json!("Move to next clip"), - ); - data_map.insert("media".to_string(), get_media_map(media)); - - return Ok(Value::Object(data_map)); - } - } + return Ok(Value::Object(data_map)); } } - return Ok(Value::String(format!("Move failed"))); + return Ok(Value::String("Move failed".to_string())); } if map.contains_key("control") && map["control"] == "back".to_string() { - if let Some(decoder) = &*proc.decoder_term.lock().unwrap() { + if let Ok(_) = kill_decoder(proc.decoder_term.clone()) { let index = *play.index.lock().unwrap(); if index > 1 && play.current_list.lock().unwrap().len() > 1 { @@ -110,17 +104,32 @@ pub async fn run_rpc( let mut media = play.current_list.lock().unwrap()[index - 2].clone(); *play.index.lock().unwrap() = index - 2; media.add_probe(); + + let (delta, _) = get_delta(&media.begin.unwrap_or(0.0)); + *playout_stat.time_shift.lock().unwrap() = delta; + write_status(playout_stat.current_date.lock().unwrap().clone(), delta); + data_map.insert("operation".to_string(), json!("Move to last clip")); data_map.insert("media".to_string(), get_media_map(media)); - unsafe { - if let Ok(_) = decoder.terminate() { - return Ok(Value::Object(data_map)); - } - } + return Ok(Value::Object(data_map)); } } - return Ok(Value::String(format!("Move failed"))); + return Ok(Value::String("Move failed".to_string())); + } + + if map.contains_key("control") && map["control"] == "reset".to_string() { + *playout_stat.date.lock().unwrap() = String::new(); + *playout_stat.time_shift.lock().unwrap() = 0.0; + *playout_stat.list_init.lock().unwrap() = true; + + write_status(String::new().clone(), 0.0); + + if let Err(e) = kill_decoder(proc.decoder_term.clone()) { + error!("{e}"); + } + + return Ok(Value::String("Reset playout to original state".to_string())); } if map.contains_key("media") && map["media"] == "current".to_string() {