// Copyright 2023 System76 // SPDX-License-Identifier: GPL-3.0-only use cosmic::{ app::{message, Command, Core, Settings}, cosmic_config::{self, CosmicConfigEntry}, cosmic_theme, executor, font, iced::{ event::{self, Event}, keyboard::{Event as KeyEvent, Key, Modifiers}, mouse::Event as MouseEvent, subscription::Subscription, window, Alignment, Color, Length, Limits, }, theme, widget::{self, Slider}, Application, ApplicationExt, Element, }; use iced_video_player::{ gst::{self, prelude::*}, gst_pbutils, Video, VideoPlayer, }; use std::{ any::TypeId, collections::HashMap, time::{Duration, Instant}, }; use crate::{ config::{Config, CONFIG_VERSION}, key_bind::{key_binds, KeyBind}, }; mod config; mod key_bind; mod localize; static CONTROLS_TIMEOUT: Duration = Duration::new(2, 0); const GST_PLAY_FLAG_VIDEO: i32 = 1 << 0; const GST_PLAY_FLAG_AUDIO: i32 = 1 << 1; const GST_PLAY_FLAG_TEXT: i32 = 1 << 2; /// Runs application with these settings #[rustfmt::skip] pub fn main() -> Result<(), Box> { env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("warn")).init(); localize::localize(); 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) { Ok(ok) => ok, Err((errs, config)) => { log::info!("errors loading config: {:?}", errs); config } }; (Some(config_handler), config) } Err(err) => { log::error!("failed to create config handler: {}", err); (None, Config::default()) } }; let mut settings = Settings::default(); settings = settings.theme(config.app_theme.theme()); settings = settings.size_limits(Limits::NONE.min_width(360.0).min_height(180.0)); let url = url::Url::from_file_path( std::env::args().nth(1).unwrap() ) .unwrap(); let flags = Flags { config_handler, config, url, }; cosmic::app::run::(settings, flags)?; Ok(()) } #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub enum Action { Fullscreen, PlayPause, SeekBackward, SeekForward, } impl Action { pub fn message(&self) -> Message { match self { Self::Fullscreen => Message::Fullscreen, Self::PlayPause => Message::PlayPause, Self::SeekBackward => Message::SeekRelative(-10.0), Self::SeekForward => Message::SeekRelative(10.0), } } } #[derive(Clone)] pub struct Flags { config_handler: Option, config: Config, url: url::Url, } /// Messages that are used specifically by our [`App`]. #[derive(Clone, Debug)] pub enum Message { Config(Config), Fullscreen, Key(Modifiers, Key), AudioCode(usize), TextCode(usize), PlayPause, Seek(f64), SeekRelative(f64), SeekRelease, EndOfStream, MissingPlugin(gst::Message), NewFrame, Reload, ShowControls, SystemThemeModeChange(cosmic_theme::ThemeMode), } /// The [`App`] stores application-specific state. pub struct App { core: Core, flags: Flags, controls: bool, controls_time: Instant, fullscreen: bool, key_binds: HashMap, video_opt: Option