1#![deny(missing_docs)]
2pub mod util;
6pub mod core;
8pub mod font;
10pub mod modules;
12pub mod images;
14
15pub mod versions;
16pub mod config;
17pub mod socket;
18pub mod thread;
19
20pub use streamdeck;
21pub use hidapi;
22pub use palette;
23pub use image;
24pub use async_trait::async_trait;
25pub use async_recursion::async_recursion;
26
27use std::sync::Arc;
28use hidapi::HidApi;
29use streamdeck::pids;
30use streamdeck::StreamDeck;
31use crate::config::{Config, UniqueDeviceConfig};
32use crate::core::{SDCore};
33use crate::modules::ModuleManager;
34use thread::ImageCollection;
35use crate::socket::SocketManager;
36use crate::thread::rendering::custom::RenderingManager;
37
38#[macro_use] extern crate async_trait;
39
40pub async fn connect_any(module_manager: Arc<ModuleManager>, render_manager: Arc<RenderingManager>, socket_manager: Arc<SocketManager>, config: Arc<Config>, device_config: UniqueDeviceConfig, image_collection: ImageCollection, hid: &HidApi, frame_rate: u32) -> Result<Arc<SDCore>, Error> {
42 Ok(SDCore::new(module_manager, render_manager, socket_manager, config, device_config, image_collection, attempt_connection_to_any(hid)?, frame_rate).await)
43}
44
45fn attempt_connection_to_any(hid: &HidApi) -> Result<StreamDeck, Error> {
46 let mut decks = find_decks(hid);
47
48 if let Some((vid, pid, serial)) = decks.pop() {
49 match StreamDeck::connect_with_hid(&hid, vid, pid, serial) {
50 Ok(streamdeck) => Ok(streamdeck),
51 Err(err) => Err(Error::StreamDeckError(err))
52 }
53 } else {
54 Err(Error::DeviceNotFound)
55 }
56}
57
58pub async fn connect(module_manager: Arc<ModuleManager>, render_manager: Arc<RenderingManager>, socket_manager: Arc<SocketManager>, config: Arc<Config>, device_config: UniqueDeviceConfig, image_collection: ImageCollection, hid: &HidApi, vid: u16, pid: u16, serial: &str, frame_rate: u32) -> Result<Arc<SDCore>, Error> {
60 Ok(SDCore::new(module_manager, render_manager, socket_manager, config, device_config, image_collection, attempt_connection(hid, vid, pid, serial)?, frame_rate).await)
61}
62
63fn attempt_connection(hid: &HidApi, vid: u16, pid: u16, serial: &str) -> Result<StreamDeck, Error> {
64 match StreamDeck::connect_with_hid(&hid, vid, pid, Some(serial.to_string())) {
65 Ok(streamdeck) => Ok(streamdeck),
66 Err(err) => Err(Error::StreamDeckError(err))
67 }
68}
69
70pub fn find_decks(hid: &HidApi) -> Vec<(u16, u16, Option<String>)> {
72 let devices = hid
73 .device_list()
74 .filter(|item| check_if_streamdeck(item.product_id()));
75
76 devices.map(
77 |d| (
78 d.vendor_id(),
79 d.product_id(),
80 d.serial_number().map(|f| f.to_string())
81 ))
82 .filter(|(_, _, s)| {
83 if let Some(s) = s {
84 return s.chars().all(|c| char::is_ascii_alphanumeric(&c));
85 }
86
87 false
88 })
89 .collect()
90}
91
92pub fn check_if_streamdeck(product_id: u16) -> bool {
94 match product_id {
95 pids::MINI | pids::ORIGINAL | pids::ORIGINAL_V2 | pids::XL | pids::MK2 => true,
96 _ => false,
97 }
98}
99
100#[derive(Debug)]
102pub enum Error {
103 DeviceNotFound,
105 StreamDeckError(streamdeck::Error)
107}