fix default video save directory

Signed-off-by: 21pages <pages21@163.com>
This commit is contained in:
21pages 2022-10-12 16:06:15 +08:00
parent e94c3467eb
commit 150057f92d
9 changed files with 87 additions and 32 deletions

View File

@ -338,8 +338,8 @@ class _GeneralState extends State<_General> {
} else { } else {
dir = defaultDirectory; dir = defaultDirectory;
} }
final canlaunch = await canLaunchUrl(Uri.file(dir)); // canLaunchUrl blocked on windows portable, user SYSTEM
return {'dir': dir, 'canlaunch': canlaunch}; return {'dir': dir, 'canlaunch': true};
}(), hasData: (data) { }(), hasData: (data) {
Map<String, dynamic> map = data as Map<String, dynamic>; Map<String, dynamic> map = data as Map<String, dynamic>;
String dir = map['dir']!; String dir = map['dir']!;
@ -703,7 +703,7 @@ class _Network extends StatefulWidget {
class _NetworkState extends State<_Network> with AutomaticKeepAliveClientMixin { class _NetworkState extends State<_Network> with AutomaticKeepAliveClientMixin {
@override @override
bool get wantKeepAlive => true; bool get wantKeepAlive => true;
bool locked = true; bool locked = bind.mainIsInstalled();
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {

View File

@ -3,7 +3,7 @@ use hbb_common::anyhow::anyhow;
use hbb_common::{ use hbb_common::{
bail, chrono, bail, chrono,
config::Config, config::Config,
directories_next, log,
message_proto::{message, video_frame, EncodedVideoFrame, Message}, message_proto::{message, video_frame, EncodedVideoFrame, Message},
ResultType, ResultType,
}; };
@ -23,7 +23,7 @@ use webm::mux::{self, Segment, Track, VideoTrack, Writer};
const MIN_SECS: u64 = 1; const MIN_SECS: u64 = 1;
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
pub enum RecodeCodecID { pub enum RecordCodecID {
VP9, VP9,
H264, H264,
H265, H265,
@ -32,10 +32,11 @@ pub enum RecodeCodecID {
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct RecorderContext { pub struct RecorderContext {
pub id: String, pub id: String,
pub default_dir: String,
pub filename: String, pub filename: String,
pub width: usize, pub width: usize,
pub height: usize, pub height: usize,
pub codec_id: RecodeCodecID, pub codec_id: RecordCodecID,
} }
impl RecorderContext { impl RecorderContext {
@ -46,30 +47,22 @@ impl RecorderContext {
std::fs::create_dir_all(&dir)?; std::fs::create_dir_all(&dir)?;
} }
} else { } else {
dir = Self::default_save_directory(); dir = self.default_dir.clone();
if !dir.is_empty() && !PathBuf::from(&dir).exists() { if !dir.is_empty() && !PathBuf::from(&dir).exists() {
std::fs::create_dir_all(&dir)?; std::fs::create_dir_all(&dir)?;
} }
} }
let file = self.id.clone() let file = self.id.clone()
+ &chrono::Local::now().format("_%Y%m%d%H%M%S").to_string() + &chrono::Local::now().format("_%Y%m%d%H%M%S").to_string()
+ if self.codec_id == RecodeCodecID::VP9 { + if self.codec_id == RecordCodecID::VP9 {
".webm" ".webm"
} else { } else {
".mp4" ".mp4"
}; };
self.filename = PathBuf::from(&dir).join(file).to_string_lossy().to_string(); self.filename = PathBuf::from(&dir).join(file).to_string_lossy().to_string();
log::info!("video save to:{}", self.filename);
Ok(()) Ok(())
} }
pub fn default_save_directory() -> String {
if let Some(user) = directories_next::UserDirs::new() {
if let Some(video_dir) = user.video_dir() {
return video_dir.join("RustDesk").to_string_lossy().to_string();
}
}
"".to_owned()
}
} }
unsafe impl Send for Recorder {} unsafe impl Send for Recorder {}
@ -105,7 +98,7 @@ impl Recorder {
pub fn new(mut ctx: RecorderContext) -> ResultType<Self> { pub fn new(mut ctx: RecorderContext) -> ResultType<Self> {
ctx.set_filename()?; ctx.set_filename()?;
let recorder = match ctx.codec_id { let recorder = match ctx.codec_id {
RecodeCodecID::VP9 => Recorder { RecordCodecID::VP9 => Recorder {
inner: Box::new(WebmRecorder::new(ctx.clone())?), inner: Box::new(WebmRecorder::new(ctx.clone())?),
ctx, ctx,
}, },
@ -123,7 +116,7 @@ impl Recorder {
fn change(&mut self, mut ctx: RecorderContext) -> ResultType<()> { fn change(&mut self, mut ctx: RecorderContext) -> ResultType<()> {
ctx.set_filename()?; ctx.set_filename()?;
self.inner = match ctx.codec_id { self.inner = match ctx.codec_id {
RecodeCodecID::VP9 => Box::new(WebmRecorder::new(ctx.clone())?), RecordCodecID::VP9 => Box::new(WebmRecorder::new(ctx.clone())?),
#[cfg(feature = "hwcodec")] #[cfg(feature = "hwcodec")]
_ => Box::new(HwRecorder::new(ctx.clone())?), _ => Box::new(HwRecorder::new(ctx.clone())?),
#[cfg(not(feature = "hwcodec"))] #[cfg(not(feature = "hwcodec"))]
@ -144,9 +137,9 @@ impl Recorder {
pub fn write_frame(&mut self, frame: &video_frame::Union) -> ResultType<()> { pub fn write_frame(&mut self, frame: &video_frame::Union) -> ResultType<()> {
match frame { match frame {
video_frame::Union::Vp9s(vp9s) => { video_frame::Union::Vp9s(vp9s) => {
if self.ctx.codec_id != RecodeCodecID::VP9 { if self.ctx.codec_id != RecordCodecID::VP9 {
self.change(RecorderContext { self.change(RecorderContext {
codec_id: RecodeCodecID::VP9, codec_id: RecordCodecID::VP9,
..self.ctx.clone() ..self.ctx.clone()
})?; })?;
} }
@ -154,25 +147,25 @@ impl Recorder {
} }
#[cfg(feature = "hwcodec")] #[cfg(feature = "hwcodec")]
video_frame::Union::H264s(h264s) => { video_frame::Union::H264s(h264s) => {
if self.ctx.codec_id != RecodeCodecID::H264 { if self.ctx.codec_id != RecordCodecID::H264 {
self.change(RecorderContext { self.change(RecorderContext {
codec_id: RecodeCodecID::H264, codec_id: RecordCodecID::H264,
..self.ctx.clone() ..self.ctx.clone()
})?; })?;
} }
if self.ctx.codec_id == RecodeCodecID::H264 { if self.ctx.codec_id == RecordCodecID::H264 {
h264s.frames.iter().map(|f| self.write_video(f)).count(); h264s.frames.iter().map(|f| self.write_video(f)).count();
} }
} }
#[cfg(feature = "hwcodec")] #[cfg(feature = "hwcodec")]
video_frame::Union::H265s(h265s) => { video_frame::Union::H265s(h265s) => {
if self.ctx.codec_id != RecodeCodecID::H265 { if self.ctx.codec_id != RecordCodecID::H265 {
self.change(RecorderContext { self.change(RecorderContext {
codec_id: RecodeCodecID::H265, codec_id: RecordCodecID::H265,
..self.ctx.clone() ..self.ctx.clone()
})?; })?;
} }
if self.ctx.codec_id == RecodeCodecID::H265 { if self.ctx.codec_id == RecordCodecID::H265 {
h265s.frames.iter().map(|f| self.write_video(f)).count(); h265s.frames.iter().map(|f| self.write_video(f)).count();
} }
} }
@ -266,7 +259,7 @@ impl RecorderApi for HwRecorder {
filename: ctx.filename.clone(), filename: ctx.filename.clone(),
width: ctx.width, width: ctx.width,
height: ctx.height, height: ctx.height,
is265: ctx.codec_id == RecodeCodecID::H265, is265: ctx.codec_id == RecordCodecID::H265,
framerate: crate::hwcodec::DEFAULT_TIME_BASE[1] as _, framerate: crate::hwcodec::DEFAULT_TIME_BASE[1] as _,
}) })
.map_err(|_| anyhow!("Failed to create hardware muxer"))?; .map_err(|_| anyhow!("Failed to create hardware muxer"))?;

View File

@ -860,10 +860,11 @@ impl VideoHandler {
if start { if start {
self.recorder = Recorder::new(RecorderContext { self.recorder = Recorder::new(RecorderContext {
id, id,
default_dir: crate::ui_interface::default_video_save_directory(),
filename: "".to_owned(), filename: "".to_owned(),
width: w as _, width: w as _,
height: h as _, height: h as _,
codec_id: scrap::record::RecodeCodecID::VP9, codec_id: scrap::record::RecordCodecID::VP9,
}) })
.map_or(Default::default(), |r| Arc::new(Mutex::new(Some(r)))); .map_or(Default::default(), |r| Arc::new(Mutex::new(Some(r))));
} else { } else {

View File

@ -33,6 +33,9 @@ pub fn core_main() -> Option<Vec<String>> {
} }
if _is_connect { if _is_connect {
return core_main_invoke_new_connection(std::env::args()); return core_main_invoke_new_connection(std::env::args());
}
if args.contains(&"--install".to_string()) {
is_setup = true;
} }
if is_setup { if is_setup {
if args.is_empty() { if args.is_empty() {

View File

@ -4,6 +4,7 @@ use hbb_common::{allow_err, bail, log};
use libc::{c_char, c_int, c_void}; use libc::{c_char, c_int, c_void};
use std::{ use std::{
cell::RefCell, cell::RefCell,
path::PathBuf,
sync::{ sync::{
atomic::{AtomicBool, Ordering}, atomic::{AtomicBool, Ordering},
Arc, Arc,
@ -516,6 +517,17 @@ pub fn get_active_username() -> String {
get_value_of_seat0(2) get_value_of_seat0(2)
} }
pub fn get_active_user_home() -> Option<PathBuf> {
let username = get_active_username();
if !username.is_empty() {
let home = PathBuf::from(format!("/home/{}", username));
if home.exists() {
return Some(home);
}
}
None
}
pub fn is_prelogin() -> bool { pub fn is_prelogin() -> bool {
let n = get_active_userid().len(); let n = get_active_userid().len();
n < 4 && n > 1 n < 4 && n > 1

View File

@ -20,6 +20,7 @@ use hbb_common::{bail, log};
use include_dir::{include_dir, Dir}; use include_dir::{include_dir, Dir};
use objc::{class, msg_send, sel, sel_impl}; use objc::{class, msg_send, sel, sel_impl};
use scrap::{libc::c_void, quartz::ffi::*}; use scrap::{libc::c_void, quartz::ffi::*};
use std::path::PathBuf;
static PRIVILEGES_SCRIPTS_DIR: Dir = static PRIVILEGES_SCRIPTS_DIR: Dir =
include_dir!("$CARGO_MANIFEST_DIR/src/platform/privileges_scripts"); include_dir!("$CARGO_MANIFEST_DIR/src/platform/privileges_scripts");
@ -374,6 +375,17 @@ pub fn get_active_userid() -> String {
get_active_user("-n") get_active_user("-n")
} }
pub fn get_active_user_home() -> Option<PathBuf> {
let username = get_active_username();
if !username.is_empty() {
let home = PathBuf::from(format!("/Users/{}", username));
if home.exists() {
return Some(home);
}
}
None
}
pub fn is_prelogin() -> bool { pub fn is_prelogin() -> bool {
get_active_userid() == "0" get_active_userid() == "0"
} }

View File

@ -10,6 +10,7 @@ use std::io::prelude::*;
use std::{ use std::{
ffi::{CString, OsString}, ffi::{CString, OsString},
fs, io, mem, fs, io, mem,
path::PathBuf,
sync::{Arc, Mutex}, sync::{Arc, Mutex},
time::{Duration, Instant}, time::{Duration, Instant},
}; };
@ -734,6 +735,18 @@ pub fn get_active_username() -> String {
.to_owned() .to_owned()
} }
pub fn get_active_user_home() -> Option<PathBuf> {
let username = get_active_username();
if !username.is_empty() {
let drive = std::env::var("SystemDrive").unwrap_or("C:".to_owned());
let home = PathBuf::from(format!("{}\\Users\\{}", drive, username));
if home.exists() {
return Some(home);
}
}
None
}
pub fn is_prelogin() -> bool { pub fn is_prelogin() -> bool {
let username = get_active_username(); let username = get_active_username();
username.is_empty() || username == "SYSTEM" username.is_empty() || username == "SYSTEM"

View File

@ -443,10 +443,11 @@ fn run(sp: GenericService) -> ResultType<()> {
let recorder = if !Config::get_option("allow-auto-record-incoming").is_empty() { let recorder = if !Config::get_option("allow-auto-record-incoming").is_empty() {
Recorder::new(RecorderContext { Recorder::new(RecorderContext {
id: "local".to_owned(), id: "local".to_owned(),
default_dir: crate::ui_interface::default_video_save_directory(),
filename: "".to_owned(), filename: "".to_owned(),
width: c.width, width: c.width,
height: c.height, height: c.height,
codec_id: scrap::record::RecodeCodecID::VP9, codec_id: scrap::record::RecordCodecID::VP9,
}) })
.map_or(Default::default(), |r| Arc::new(Mutex::new(Some(r)))) .map_or(Default::default(), |r| Arc::new(Mutex::new(Some(r))))
} else { } else {

View File

@ -10,6 +10,7 @@ use hbb_common::password_security;
use hbb_common::{ use hbb_common::{
allow_err, allow_err,
config::{self, Config, LocalConfig, PeerConfig, RENDEZVOUS_PORT, RENDEZVOUS_TIMEOUT}, config::{self, Config, LocalConfig, PeerConfig, RENDEZVOUS_PORT, RENDEZVOUS_TIMEOUT},
directories_next,
futures::future::join_all, futures::future::join_all,
log, log,
protobuf::Message as _, protobuf::Message as _,
@ -19,8 +20,8 @@ use hbb_common::{
tokio::{self, sync::mpsc, time}, tokio::{self, sync::mpsc, time},
}; };
use crate::common::SOFTWARE_UPDATE_URL;
use crate::ipc; use crate::ipc;
use crate::{common::SOFTWARE_UPDATE_URL, platform};
type Message = RendezvousMessage; type Message = RendezvousMessage;
@ -731,7 +732,26 @@ pub fn get_langs() -> String {
#[inline] #[inline]
pub fn default_video_save_directory() -> String { pub fn default_video_save_directory() -> String {
scrap::record::RecorderContext::default_save_directory() let appname = crate::get_app_name();
if let Some(user) = directories_next::UserDirs::new() {
if let Some(video_dir) = user.video_dir() {
return video_dir.join(appname).to_string_lossy().to_string();
}
}
if let Some(home) = platform::get_active_user_home() {
let name = if cfg!(target_os = "macos") {
"Movies"
} else {
"Videos"
};
return home.join(name).join(appname).to_string_lossy().to_string();
}
if let Ok(exe) = std::env::current_exe() {
if let Some(dir) = exe.parent() {
return dir.join("videos").to_string_lossy().to_string();
}
}
"".to_owned()
} }
#[inline] #[inline]