mirror of
https://github.com/jwinterm/grim.git
synced 2026-10-29 09:48:47 +01:00
camera: desktop support
This commit is contained in:
@@ -12,10 +12,31 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use lazy_static::lazy_static;
|
||||
use std::sync::{Arc, RwLock};
|
||||
use std::sync::atomic::{AtomicBool, AtomicI32, Ordering};
|
||||
use std::thread;
|
||||
use eye::hal::PlatformContext;
|
||||
use eye::hal::traits::{Context, Device, Stream};
|
||||
|
||||
use crate::gui::platform::PlatformCallbacks;
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct Desktop;
|
||||
/// Desktop platform related actions.
|
||||
pub struct Desktop {
|
||||
/// Camera index.
|
||||
camera_index: AtomicI32,
|
||||
/// Flag to check if camera stop is needed.
|
||||
stop_camera: Arc<AtomicBool>
|
||||
}
|
||||
|
||||
impl Default for Desktop {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
camera_index: AtomicI32::new(0),
|
||||
stop_camera: Arc::new(AtomicBool::new(false))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl PlatformCallbacks for Desktop {
|
||||
fn show_keyboard(&self) {}
|
||||
@@ -32,20 +53,113 @@ impl PlatformCallbacks for Desktop {
|
||||
clipboard.get_text().unwrap_or("".to_string())
|
||||
}
|
||||
|
||||
fn camera_image(&self) -> Option<(Vec<u8>, u32)> {
|
||||
Some((vec![].into(), 0))
|
||||
}
|
||||
|
||||
fn cameras_amount(&self) -> u32 {
|
||||
let devices = PlatformContext::default().devices();
|
||||
if devices.is_ok() {
|
||||
return devices.unwrap().len() as u32;
|
||||
}
|
||||
0
|
||||
}
|
||||
|
||||
fn switch_camera(&self) {
|
||||
let amount = self.cameras_amount();
|
||||
if amount < 2 {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
fn start_camera(&self) {
|
||||
// Clear image.
|
||||
{
|
||||
let mut w_image = LAST_CAMERA_IMAGE.write().unwrap();
|
||||
*w_image = None;
|
||||
}
|
||||
|
||||
// Query for available devices.
|
||||
let devices = PlatformContext::default().devices();
|
||||
if devices.is_err() {
|
||||
return;
|
||||
}
|
||||
let devices = devices.unwrap();
|
||||
|
||||
// Setup camera index.
|
||||
let saved_index = self.camera_index.load(Ordering::Relaxed);
|
||||
let camera_index = if devices.len() <= self.camera_index.load(Ordering::Relaxed) as usize {
|
||||
self.camera_index.store(0, Ordering::Relaxed);
|
||||
0
|
||||
} else {
|
||||
saved_index
|
||||
};
|
||||
|
||||
// Setup stop camera flag.
|
||||
let stop_camera = self.stop_camera.clone();
|
||||
stop_camera.store(false, Ordering::Relaxed);
|
||||
|
||||
let devices = devices.clone();
|
||||
|
||||
// Capture images at separate thread.
|
||||
thread::spawn(move || {
|
||||
tokio::runtime::Builder::new_multi_thread()
|
||||
.enable_all()
|
||||
.build()
|
||||
.unwrap()
|
||||
.block_on(async {
|
||||
// Open camera.
|
||||
let context = PlatformContext::default();
|
||||
if let Ok(dev) = context.open_device(&devices[camera_index as usize].uri) {
|
||||
let streams = dev.streams().unwrap();
|
||||
let stream_desc = streams[0].clone();
|
||||
println!("Camera stream: {:?}", stream_desc);
|
||||
let mut stream = dev.start_stream(&stream_desc).unwrap();
|
||||
loop {
|
||||
// Stop if camera was stopped.
|
||||
if stop_camera.load(Ordering::Relaxed) {
|
||||
stop_camera.store(false, Ordering::Relaxed);
|
||||
break;
|
||||
}
|
||||
// Get frame.
|
||||
if let Some(frame) = stream.next() {
|
||||
// Get data from frame.
|
||||
if let Ok(frame_data) = frame {
|
||||
// Save image.
|
||||
let mut w_image = LAST_CAMERA_IMAGE.write().unwrap();
|
||||
*w_image = Some((frame_data.to_vec(), 0));
|
||||
} else {
|
||||
// Clear image.
|
||||
let mut w_image = LAST_CAMERA_IMAGE.write().unwrap();
|
||||
*w_image = None;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
// Clear image.
|
||||
let mut w_image = LAST_CAMERA_IMAGE.write().unwrap();
|
||||
*w_image = None;
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
fn stop_camera(&self) {
|
||||
// Stop camera.
|
||||
self.stop_camera.store(true, Ordering::Relaxed);
|
||||
// Clear image.
|
||||
let mut w_image = LAST_CAMERA_IMAGE.write().unwrap();
|
||||
*w_image = None;
|
||||
}
|
||||
|
||||
fn switch_camera(&self) {
|
||||
fn camera_image(&self) -> Option<(Vec<u8>, u32)> {
|
||||
let r_image = LAST_CAMERA_IMAGE.read().unwrap();
|
||||
if r_image.is_some() {
|
||||
return Some(r_image.clone().unwrap());
|
||||
}
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
/// Last captured image from started camera.
|
||||
lazy_static! {
|
||||
static ref LAST_CAMERA_IMAGE: Arc<RwLock<Option<(Vec<u8>, u32)>>> = Arc::new(RwLock::new(None));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user