Allow config to be updated with CLI args
This commit is contained in:
parent
99595eeeed
commit
028fd83296
3 changed files with 120 additions and 15 deletions
|
|
@ -4,7 +4,9 @@ use cosmic::{
|
|||
cosmic_config::{self, cosmic_config_derive::CosmicConfigEntry, CosmicConfigEntry},
|
||||
theme,
|
||||
};
|
||||
use lexopt::prelude::*;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::{path::PathBuf, process};
|
||||
|
||||
use crate::wrappers::HWDeviceType;
|
||||
|
||||
|
|
@ -41,3 +43,52 @@ impl Default for Config {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Config {
|
||||
pub fn with_args(&mut self, args: &mut Args) {
|
||||
if let Some(decoder) = args.decoder {
|
||||
self.hw_decoder = decoder;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Args {
|
||||
pub paths: Vec<PathBuf>,
|
||||
pub decoder: Option<HWDeviceType>,
|
||||
}
|
||||
|
||||
impl Args {
|
||||
pub fn parse_args() -> Result<Self, lexopt::Error> {
|
||||
let mut paths = Vec::new();
|
||||
let mut decoder = None;
|
||||
|
||||
let mut parser = lexopt::Parser::from_env();
|
||||
while let Some(arg) = parser.next()? {
|
||||
match arg {
|
||||
Long("list-hwdec") => {
|
||||
println!("Supported hardware decoders:");
|
||||
for hwdec in HWDeviceType::supported_devices() {
|
||||
println!("\t* [{}] {hwdec}", hwdec.short_name());
|
||||
}
|
||||
process::exit(0);
|
||||
}
|
||||
Long("hwdec") => {
|
||||
decoder = Some(parser.value()?.parse()?);
|
||||
}
|
||||
Value(path) => {
|
||||
let path = path.parse()?;
|
||||
paths.push(path);
|
||||
}
|
||||
_ => return Err(arg.unexpected()),
|
||||
}
|
||||
}
|
||||
|
||||
if paths.is_empty() {
|
||||
return Err(lexopt::Error::MissingValue {
|
||||
option: Some("missing video path".into()),
|
||||
});
|
||||
}
|
||||
|
||||
Ok(Self { paths, decoder })
|
||||
}
|
||||
}
|
||||
|
|
|
|||
29
src/main.rs
29
src/main.rs
|
|
@ -16,14 +16,12 @@ use cosmic::{
|
|||
use std::{
|
||||
any::TypeId,
|
||||
collections::HashMap,
|
||||
env,
|
||||
path::PathBuf,
|
||||
process,
|
||||
env, process,
|
||||
sync::{mpsc, Arc, Mutex},
|
||||
time::{Duration, Instant},
|
||||
};
|
||||
|
||||
use config::{AppTheme, Config, CONFIG_VERSION};
|
||||
use config::{AppTheme, Args, Config, CONFIG_VERSION};
|
||||
mod config;
|
||||
|
||||
use key_bind::{key_binds, KeyBind};
|
||||
|
|
@ -42,16 +40,26 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||
env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("warn")).init();
|
||||
|
||||
localize::localize();
|
||||
|
||||
let mut args = match Args::parse_args() {
|
||||
Ok(args) => args,
|
||||
Err(e) => {
|
||||
log::error!("{e}");
|
||||
process::exit(1);
|
||||
}
|
||||
};
|
||||
|
||||
let (config_handler, config) = match cosmic_config::Config::new(App::APP_ID, CONFIG_VERSION) {
|
||||
Ok(config_handler) => {
|
||||
let config = match Config::get_entry(&config_handler) {
|
||||
let mut config = match Config::get_entry(&config_handler) {
|
||||
Ok(ok) => ok,
|
||||
Err((errs, config)) => {
|
||||
log::info!("errors loading config: {:?}", errs);
|
||||
config
|
||||
}
|
||||
};
|
||||
// Update config with command line args
|
||||
config.with_args(&mut args);
|
||||
(Some(config_handler), config)
|
||||
}
|
||||
Err(err) => {
|
||||
|
|
@ -60,14 +68,9 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||
}
|
||||
};
|
||||
|
||||
//TODO: support multiple paths
|
||||
let path = match env::args().skip(1).next() {
|
||||
Some(arg) => PathBuf::from(arg),
|
||||
None => {
|
||||
log::error!("no argument provided");
|
||||
process::exit(1);
|
||||
}
|
||||
};
|
||||
//TODO: support using multiple paths
|
||||
let Args { mut paths, .. } = args;
|
||||
let path = paths.pop().unwrap();
|
||||
|
||||
let (player_tx, video_queue_lock) = player::run(path);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
use std::str::FromStr;
|
||||
use std::{fmt, iter::FusedIterator, str::FromStr};
|
||||
|
||||
use ffmpeg_next::ffi::{av_hwdevice_iterate_types, AVHWDeviceType};
|
||||
use serde::{
|
||||
|
|
@ -25,6 +25,8 @@ pub enum HWDeviceType {
|
|||
/// DirectX Video Acceleration 2.0
|
||||
/// https://learn.microsoft.com/en-us/windows/win32/medfound/about-dxva-2-0
|
||||
Dxva2,
|
||||
/// Direct Rendering Manager
|
||||
/// https://dri.freedesktop.org/wiki/DRM/
|
||||
Drm,
|
||||
/// MediaCodec
|
||||
/// Android only
|
||||
|
|
@ -70,7 +72,26 @@ impl HWDeviceType {
|
|||
}
|
||||
}
|
||||
|
||||
/// Supported hardware decoders
|
||||
/// Short name for CLI arguments
|
||||
pub const fn short_name(self) -> &'static str {
|
||||
match self {
|
||||
Self::None => "none",
|
||||
Self::Cuda => "cuda",
|
||||
Self::Dxva2 => "dxva2",
|
||||
Self::D3d11va => "d3d11va",
|
||||
Self::D3d12va => "d3d12va",
|
||||
Self::Drm => "drm",
|
||||
Self::MediaCodec => "mediacodec",
|
||||
Self::OpenCl => "opencl",
|
||||
Self::Qsv => "qsv",
|
||||
Self::Vaapi => "vaapi",
|
||||
Self::Vdpau => "vdpau",
|
||||
Self::VideoToolbox => "videotoolbox",
|
||||
Self::Vulkan => "vulkan",
|
||||
}
|
||||
}
|
||||
|
||||
/// System's supported hardware decoders
|
||||
pub fn supported_devices() -> SupportedDeviceIter {
|
||||
SupportedDeviceIter::default()
|
||||
}
|
||||
|
|
@ -104,6 +125,12 @@ impl FromStr for HWDeviceType {
|
|||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for HWDeviceType {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{}", self.name())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<AVHWDeviceType> for HWDeviceType {
|
||||
fn from(value: AVHWDeviceType) -> Self {
|
||||
match value {
|
||||
|
|
@ -131,6 +158,7 @@ impl Default for HWDeviceType {
|
|||
}
|
||||
}
|
||||
|
||||
/// Iterator over system's supported hardware decoders.
|
||||
pub struct SupportedDeviceIter {
|
||||
current: AVHWDeviceType,
|
||||
}
|
||||
|
|
@ -147,13 +175,36 @@ impl Iterator for SupportedDeviceIter {
|
|||
type Item = HWDeviceType;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
// None is a sentinel value that indicates the iterator is exhausted
|
||||
if self.current == AVHWDeviceType::AV_HWDEVICE_TYPE_NONE {
|
||||
None
|
||||
} else {
|
||||
let prev = self.current;
|
||||
// SAFETY: The docs and examples state that the iterator yields the next value
|
||||
// when the previous is passed in.
|
||||
self.current = unsafe { av_hwdevice_iterate_types(prev) };
|
||||
|
||||
Some(prev.into())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl FusedIterator for SupportedDeviceIter {}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::hint::black_box;
|
||||
|
||||
use super::*;
|
||||
|
||||
// The iterator's yielded values aren't important since hardware decoders vary by system
|
||||
// This is just a sanity check to ensure the iterator works
|
||||
#[test]
|
||||
fn supported_device_iter_doesnt_seg_fault() {
|
||||
for decoder in HWDeviceType::supported_devices() {
|
||||
black_box(decoder);
|
||||
}
|
||||
|
||||
let _decoders: Vec<_> = black_box(HWDeviceType::supported_devices().collect());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue