adding a basic obs implementation

This commit is contained in:
Chris Cochrun 2023-11-02 06:30:16 -05:00
parent 499567a4ed
commit de0c26271f
3 changed files with 79 additions and 25 deletions

View file

@ -2,6 +2,7 @@ pub mod ffmpeg;
mod file_helper; mod file_helper;
pub mod image_model; pub mod image_model;
pub mod models; pub mod models;
pub mod obs;
pub mod presentation_model; pub mod presentation_model;
pub mod reveal_js; pub mod reveal_js;
pub mod schema; pub mod schema;
@ -11,8 +12,7 @@ pub mod settings;
pub mod slide_model; pub mod slide_model;
mod slide_obj; mod slide_obj;
pub mod songs; pub mod songs;
pub mod utils;
pub mod video_model; pub mod video_model;
pub mod ytdl; pub mod ytdl;
pub mod utils;
pub mod obs;
// mod video_thumbnail; // mod video_thumbnail;

View file

@ -1,7 +1,8 @@
use core::fmt;
use std::error::Error; use std::error::Error;
use obws::Client;
use obws::responses::scenes::Scenes; use obws::responses::scenes::Scenes;
use obws::Client;
use tracing::debug; use tracing::debug;
pub struct Obs { pub struct Obs {
@ -9,16 +10,43 @@ pub struct Obs {
client: Client, client: Client,
} }
impl fmt::Debug for Obs {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Client")
.field("host", &"localhost")
.field("port", &4455)
.finish()
}
}
impl Clone for Obs {
fn clone(&self) -> Self {
Self {
scenes: self.scenes.clone(),
client: make_client(),
}
}
}
impl Obs { impl Obs {
pub async fn new() -> Result<Self, Box<dyn Error>> { pub async fn new() -> Result<Self, Box<dyn Error>> {
let client = Client::connect("localhost", 4455, Some("")).await?; let client =
Client::connect("localhost", 4455, Some("")).await?;
let scene_list = client.scenes().list().await?; let scene_list = client.scenes().list().await?;
debug!(?scene_list); debug!(?scene_list);
Ok(Self{scenes: scene_list, client}) Ok(Self {
scenes: scene_list,
client,
})
} }
pub fn get_list(self) -> Result<Vec<String>, Box<dyn Error>> { pub fn get_list(self) -> Result<Vec<String>, Box<dyn Error>> {
let scenes = self.scenes.scenes.iter().map(|x| x.name).collect::<Vec<String>>(); let scenes = self
.scenes
.scenes
.iter()
.map(|x| x.name.clone())
.collect::<Vec<String>>();
if scenes.len() > 0 { if scenes.len() > 0 {
Ok(scenes) Ok(scenes)
} else { } else {
@ -26,12 +54,30 @@ impl Obs {
} }
} }
pub fn set_scene(self, scene: String) -> Result<(), Box<dyn Error>> { pub fn set_scene(
if let Some(scene) = self.scenes.scenes.iter().filter(|x| x.name == scene).next() { self,
self.client.scenes().set_current_program_scene(scene.name.as_str()); scene: String,
) -> Result<(), Box<dyn Error>> {
if let Some(scene) = self
.scenes
.scenes
.iter()
.filter(|x| x.name == scene)
.next()
{
self.client
.scenes()
.set_current_program_scene(scene.name.as_str());
Ok(()) Ok(())
} else { } else {
Err("Couldn't set the scene".to_owned())? Err("Couldn't set the scene".to_owned())?
} }
} }
} }
fn make_client() -> Client {
let runtime = tokio::runtime::Runtime::new().unwrap();
let future = Client::connect("localhost", 4455, Some(""));
let client = runtime.block_on(future).unwrap();
client
}

View file

@ -24,6 +24,7 @@ mod service_item_model {
type QUrl = cxx_qt_lib::QUrl; type QUrl = cxx_qt_lib::QUrl;
} }
use crate::obs::Obs;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
#[cxx_qt::qobject] #[cxx_qt::qobject]
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
@ -83,13 +84,26 @@ mod service_item_model {
} }
#[cxx_qt::qobject(base = "QAbstractListModel")] #[cxx_qt::qobject(base = "QAbstractListModel")]
#[derive(Default, Debug)] #[derive(Debug)]
pub struct ServiceItemMod { pub struct ServiceItemMod {
id: i32, id: i32,
service_items: Vec<ServiceItm>, service_items: Vec<ServiceItm>,
obs: Obs, obs: Obs,
} }
impl Default for ServiceItemMod {
fn default() -> Self {
let obs = tokio::runtime::Runtime::new()
.unwrap()
.block_on(async { Obs::new().await.ok().unwrap() });
Self {
id: 0,
service_items: Vec::new(),
obs,
}
}
}
#[cxx_qt::qsignals(ServiceItemMod)] #[cxx_qt::qsignals(ServiceItemMod)]
pub enum Signals<'a> { pub enum Signals<'a> {
#[inherit] #[inherit]
@ -152,7 +166,6 @@ mod service_item_model {
use tracing::{debug, debug_span, error, info, instrument}; use tracing::{debug, debug_span, error, info, instrument};
use zstd::{Decoder, Encoder}; use zstd::{Decoder, Encoder};
use crate::obs::Obs;
impl qobject::ServiceItemMod { impl qobject::ServiceItemMod {
pub fn setup(mut self: Pin<&mut Self>) { pub fn setup(mut self: Pin<&mut Self>) {
todo!() todo!()
@ -349,6 +362,8 @@ mod service_item_model {
let dest_id = dest_index as usize; let dest_id = dest_index as usize;
let cnt = count as usize; let cnt = count as usize;
let end_service_item = source_id + cnt - 1; let end_service_item = source_id + cnt - 1;
// This needs to point to the index above the intended position if moving
// up. Qt's begin_move_rows requires that knowledge for some reason.
let qt_dest_index = if source_index < dest_index { let qt_dest_index = if source_index < dest_index {
dest_index + 1 dest_index + 1
} else { } else {
@ -585,25 +600,19 @@ mod service_item_model {
// println!("service_item is deactivating {:?}", i); // println!("service_item is deactivating {:?}", i);
service_item.active = false; service_item.active = false;
} }
let obs = self.as_mut().obs_mut().clone();
if let Some(service_item) = self if let Some(service_item) = self
.as_mut() .as_mut()
.service_items_mut() .service_items_mut()
.get_mut(index as usize) .get_mut(index as usize)
{ {
println!("service_item is activating {:?}", index); debug!(activating_item = index,
println!( title = ?service_item.name,
"service_item_title: {:?}", background = ?service_item.background,
service_item.name background_type = ?service_item.background_type);
);
println!(
"service_item_background: {:?}",
service_item.background
);
println!(
"service_item_background_type: {:?}",
service_item.background_type
);
service_item.active = true; service_item.active = true;
obs.set_scene(service_item.obs_scene.to_string());
self.as_mut().emit_data_changed( self.as_mut().emit_data_changed(
tl, tl,
br, br,
@ -612,7 +621,6 @@ mod service_item_model {
// We use this signal generated by our signals enum to tell QML that // We use this signal generated by our signals enum to tell QML that
// the active service_item has changed which is used to reposition views. // the active service_item has changed which is used to reposition views.
self.as_mut().emit_active_changed(); self.as_mut().emit_active_changed();
Obs::set_scene(service_item.obs_scene.to_string());
true true
} else { } else {
false false