context menus

This commit is contained in:
AnActualEmerald 2022-09-06 00:57:23 -04:00
parent 5e06a3c08e
commit 833f5b96c9
Signed by: emerald
GPG Key ID: CC76D6B296CAC8B0
6 changed files with 82 additions and 27 deletions

View File

@ -1,5 +1,6 @@
use std::sync::Arc;
use std::sync::Mutex;
use std::time::Duration;
use anyhow::anyhow;
use anyhow::Result;
@ -10,7 +11,7 @@ use cpal::InputCallbackInfo;
// use cpal::OutputCallbackInfo;
use tauri::Window;
pub async fn monitor(window: Window, threshold: Arc<Mutex<f32>>) {
pub async fn monitor(window: Window, threshold: Arc<Mutex<f32>>, level: Arc<Mutex<f32>>) {
let device = initialize().expect("Unable to init audio");
println!("Using device {}", device.name().unwrap());
let config = device.default_input_config().unwrap();
@ -23,6 +24,13 @@ pub async fn monitor(window: Window, threshold: Arc<Mutex<f32>>) {
} else {
window.emit("mouth-close", "").unwrap();
}
*level.lock().unwrap() = data
.iter()
.map(|e| e.abs())
.max_by(|a, b| a.total_cmp(&b))
.unwrap()
.clone();
},
move |err| {
println!("Audio error: {:?}", err);
@ -31,8 +39,10 @@ pub async fn monitor(window: Window, threshold: Arc<Mutex<f32>>) {
.unwrap();
println!("Start stream");
stream.play().expect("Error creating output stream");
loop {} // the stream will close if it goes out of scope, so just dwell here
stream.play().expect("Error creating input stream");
// The stream will end if it goes out of scope, so just dwell here
loop {}
}
fn initialize() -> Result<Device> {

View File

@ -18,17 +18,20 @@ mod fs;
const MIC_THRESHOLD: f32 = 0.5f32;
struct MicThreshold(Arc<Mutex<f32>>);
struct AudioLevel(Arc<Mutex<f32>>);
fn main() {
env_logger::init();
let threshold = Arc::new(Mutex::new(MIC_THRESHOLD));
let level = Arc::new(Mutex::new(0.));
tauri::Builder::default()
.manage(MicThreshold(threshold.clone()))
.manage(AudioLevel(level.clone()))
.setup(|app| {
let window = app.get_window("main").unwrap();
tauri::async_runtime::spawn(async move {
monitor(window, threshold).await;
monitor(window, threshold, level).await;
});
let window = app.get_window("main").unwrap();
@ -49,6 +52,7 @@ fn main() {
.invoke_handler(tauri::generate_handler![
set_mic_threshold,
get_mic_threshold,
get_audio_level,
fs::open_image,
])
.run(tauri::generate_context!())
@ -64,3 +68,8 @@ fn set_mic_threshold(threshold: f32, current: State<'_, MicThreshold>) {
fn get_mic_threshold(current: State<'_, MicThreshold>) -> f32 {
*current.0.lock().unwrap()
}
#[tauri::command]
fn get_audio_level(level: State<'_, AudioLevel>) -> f32 {
*level.0.lock().unwrap()
}

View File

@ -1,6 +1,8 @@
<script lang="ts">
import { frames } from "../store";
import { invoke } from "@tauri-apps/api";
import { fade } from "svelte/transition";
import Context from "../components/context.svelte";
export let index: number;
let menuTimeout: NodeJS.Timeout | null = null;
@ -21,22 +23,30 @@
//TODO: load frame from ray
</script>
<div
class="preview"
on:click={openImage}
on:contextmenu={openImage}
on:mouseenter={() =>
(menuTimeout = setTimeout(() => (showMenu = true), 1000))}
on:mouseleave={() => {
if (menuTimeout) {
clearTimeout(menuTimeout);
}
showMenu = false;
}}
>
<p>{showMenu}</p>
{#if src}
<img {src} alt="Frame {{ index }}" />
<div class="box">
<div
class="preview"
on:click={openImage}
on:contextmenu={openImage}
on:mouseenter={() =>
(menuTimeout = setTimeout(() => (showMenu = true), 200))}
on:mouseleave={() => {
if (menuTimeout) {
clearTimeout(menuTimeout);
}
showMenu = false;
}}
>
{#if src}
<img {src} alt="Frame {{ index }}" />
{/if}
</div>
{#if showMenu}
<div transition:fade={{ duration: 50 }} class="context">
<Context>
<p>Context Menu</p>
</Context>
</div>
{/if}
</div>
@ -55,6 +65,14 @@
height: 20vh;
}
.box {
gap: 10px;
display: flex;
.context {
align-self: center;
}
}
img {
width: 75%;
}

View File

@ -0,0 +1,16 @@
<script lang="ts">
</script>
<div class="context">
<slot />
</div>
<style>
.context {
color: white;
background-color: rgba(75, 75, 75, 10);
padding: 1vh;
border-radius: 10px;
align-self: center;
}
</style>

View File

@ -0,0 +1 @@

View File

@ -8,6 +8,7 @@
let transparent = false;
let threshold = 0.0;
let level = 0.0;
onMount(async () => {
await appWindow.setMinSize(new PhysicalSize(720, 600));
@ -18,15 +19,15 @@
setInterval(async () => {
threshold = await invoke("get_mic_threshold");
}, 500);
// setInterval(async () => {
// await invoke("set_mic_threshold", {
// threshold: (threshold + 0.2) % 1.0,
// });
// }, 1000);
setInterval(async () => {
level = await invoke("get_audio_level");
}, 50);
});
</script>
<div class="container" class:transparent>
<Tuber />
{#if !transparent}
<div
transition:fly={{ duration: 200, x: -200, opacity: 100 }}
@ -39,10 +40,9 @@
<div transition:fly={{ duration: 200, x: 200, opacity: 100 }} class="audio">
<p>{threshold.toPrecision(2).toString()}</p>
<p>{(level * 100).toPrecision(3).toString()}</p>
</div>
{/if}
<Tuber />
</div>
<svelte:body on:contextmenu|preventDefault />
@ -62,6 +62,7 @@
.audio {
position: absolute;
display: flex;
gap: 10px;
bottom: 5vh;
top: 5vh;
right: 30px;