Files
VRCWT-OSC/internal/app/discord_mute.go
2026-06-25 02:36:55 +09:00

90 lines
1.8 KiB
Go

package app
import (
"fmt"
"log"
"strings"
"time"
"vrc_osc_go/internal/osc"
)
const discordDebounce = 300 * time.Millisecond
func handleDiscordSend(state *discordMuteState, args []osc.Value) error {
state.mu.Lock()
defer state.mu.Unlock()
if len(args) == 0 {
return fmt.Errorf("OSC args is empty")
}
isPressed, err := toBool(args[0])
if err != nil {
return err
}
now := time.Now()
if !state.lastAction.IsZero() && now.Sub(state.lastAction) < discordDebounce {
return nil
}
if isPressed && !state.buttonPressed {
state.buttonPressed = true
if state.muted {
log.Printf("ACTION VRChat button pressed -> Discord unmute hotkey")
if err := pressDiscordMuteHotkey(); err != nil {
return err
}
state.muted = false
SetDiscordMuted(state.muted)
state.lastAction = now
} else {
log.Printf("INFO already unmuted")
}
return nil
}
if !isPressed && state.buttonPressed {
state.buttonPressed = false
if !state.muted {
log.Printf("ACTION VRChat button released -> Discord mute hotkey")
if err := pressDiscordMuteHotkey(); err != nil {
return err
}
state.muted = true
SetDiscordMuted(state.muted)
state.lastAction = now
} else {
log.Printf("INFO already muted")
}
}
return nil
}
func toBool(v osc.Value) (bool, error) {
switch v.Type {
case 'T':
return true, nil
case 'F':
return false, nil
case 'i':
return v.Int != 0, nil
case 'f':
return v.Float != 0, nil
case 's':
switch strings.ToLower(strings.TrimSpace(v.Str)) {
case "true", "1", "on", "yes":
return true, nil
case "false", "0", "off", "no":
return false, nil
default:
return false, fmt.Errorf("unsupported OSC value: %q", v.Str)
}
case 0:
return false, fmt.Errorf("unsupported OSC value")
default:
return false, fmt.Errorf("unsupported OSC type: %q", v.Type)
}
}