add cancel action to pipeline to stop without transcribing

This commit is contained in:
LeonardoTrapani
2025-10-10 20:08:41 +02:00
parent b437f575e6
commit e8b9c1eff0
5 changed files with 46 additions and 6 deletions
+10
View File
@@ -129,6 +129,9 @@ hyprvoice serve
# Toggle recording on/off # Toggle recording on/off
hyprvoice toggle hyprvoice toggle
# Cancel current operation
hyprvoice cancel
# Check current status # Check current status
hyprvoice status hyprvoice status
@@ -145,6 +148,7 @@ Most setups use this toggle pattern in window manager config:
```bash ```bash
bind = SUPER, R, exec, hyprvoice toggle bind = SUPER, R, exec, hyprvoice toggle
bind = SUPER SHIFT, R, exec, hyprvoice cancel # Optional: cancel current operation
``` ```
## Keyboard Shortcuts Setup ## Keyboard Shortcuts Setup
@@ -157,6 +161,9 @@ Add to your `~/.config/hypr/hyprland.conf`:
# Hyprvoice - Voice to Text (toggle recording) # Hyprvoice - Voice to Text (toggle recording)
bind = SUPER, R, exec, hyprvoice toggle bind = SUPER, R, exec, hyprvoice toggle
# Optional: Cancel current operation
bind = SUPER SHIFT, C, exec, hyprvoice cancel
# Optional: Status check # Optional: Status check
bind = SUPER SHIFT, R, exec, hyprvoice status && notify-send "Hyprvoice" "$(hyprvoice status)" bind = SUPER SHIFT, R, exec, hyprvoice status && notify-send "Hyprvoice" "$(hyprvoice status)"
``` ```
@@ -170,6 +177,8 @@ bind = SUPER SHIFT, R, exec, hyprvoice status && notify-send "Hyprvoice" "$(hypr
3. **Press keybind again** → Recording stops, transcription begins 3. **Press keybind again** → Recording stops, transcription begins
4. **Text appears** → Injected at cursor position or clipboard 4. **Text appears** → Injected at cursor position or clipboard
**Cancel anytime:** Press your cancel keybind (e.g., `SUPER+SHIFT+C`) to abort the current operation and return to idle.
### CLI Usage ### CLI Usage
```bash ```bash
@@ -615,6 +624,7 @@ go run ./cmd/hyprvoice stop
Simple single-character commands over Unix socket: Simple single-character commands over Unix socket:
- `t` - Toggle recording on/off - `t` - Toggle recording on/off
- `c` - Cancel current operation
- `s` - Get current status - `s` - Get current status
- `v` - Get protocol version - `v` - Get protocol version
- `q` - Quit daemon gracefully - `q` - Quit daemon gracefully
+16
View File
@@ -28,6 +28,7 @@ func init() {
rootCmd.AddCommand( rootCmd.AddCommand(
serveCmd(), serveCmd(),
toggleCmd(), toggleCmd(),
cancelCmd(),
statusCmd(), statusCmd(),
versionCmd(), versionCmd(),
stopCmd(), stopCmd(),
@@ -109,6 +110,21 @@ func stopCmd() *cobra.Command {
} }
} }
func cancelCmd() *cobra.Command {
return &cobra.Command{
Use: "cancel",
Short: "Cancel current operation",
RunE: func(cmd *cobra.Command, args []string) error {
resp, err := bus.SendCommand('c')
if err != nil {
return fmt.Errorf("failed to cancel operation: %w", err)
}
fmt.Print(resp)
return nil
},
}
}
func configureCmd() *cobra.Command { func configureCmd() *cobra.Command {
return &cobra.Command{ return &cobra.Command{
Use: "configure", Use: "configure",
+15 -2
View File
@@ -162,6 +162,9 @@ func (d *Daemon) handle(c net.Conn) {
case 't': case 't':
d.toggle() d.toggle()
fmt.Fprint(c, "OK toggled\n") fmt.Fprint(c, "OK toggled\n")
case 'c':
d.cancelPipeline()
fmt.Fprint(c, "OK cancelled\n")
case 's': case 's':
status := d.status() status := d.status()
fmt.Fprintf(c, "STATUS status=%s\n", status) fmt.Fprintf(c, "STATUS status=%s\n", status)
@@ -191,7 +194,7 @@ func (d *Daemon) toggle() {
go d.monitorPipelineErrors(p) go d.monitorPipelineErrors(p)
case pipeline.Recording: case pipeline.Recording:
d.stopPipeline() // aborted during recording (chunks not sent to transcriber yet) d.stopPipeline()
go d.notifier.Error("Recording Aborted") go d.notifier.Error("Recording Aborted")
case pipeline.Transcribing: case pipeline.Transcribing:
@@ -207,11 +210,21 @@ func (d *Daemon) toggle() {
go d.notifier.Notify("Hyprvoice", "Recording Ended... Transcribing") go d.notifier.Notify("Hyprvoice", "Recording Ended... Transcribing")
case pipeline.Injecting: case pipeline.Injecting:
d.stopPipeline() // aborted during injection d.stopPipeline()
go d.notifier.Error("Injection Aborted") go d.notifier.Error("Injection Aborted")
} }
} }
func (d *Daemon) cancelPipeline() {
switch d.status() {
case pipeline.Idle:
log.Printf("Daemon: Cancel requested but pipeline is idle, ignoring")
default:
d.stopPipeline()
go d.notifier.Notify("Hyprvoice", "Operation Cancelled")
}
}
func (d *Daemon) monitorPipelineErrors(p pipeline.Pipeline) { func (d *Daemon) monitorPipelineErrors(p pipeline.Pipeline) {
errorCh := p.GetErrorCh() errorCh := p.GetErrorCh()
for { for {
+3 -2
View File
@@ -30,6 +30,7 @@ const (
const ( const (
Inject Action = "inject" Inject Action = "inject"
Cancel Action = "cancel"
) )
type Pipeline interface { type Pipeline interface {
@@ -115,7 +116,8 @@ func (p *pipeline) run(ctx context.Context) {
defer func() { defer func() {
if stopErr := t.Stop(ctx); stopErr != nil { if stopErr := t.Stop(ctx); stopErr != nil {
log.Printf("Pipeline: Error stopping transcriber: %v", stopErr) log.Printf("Pipeline: Error stopping transcriber: %v", stopErr)
p.sendError("Transcription Error", "Failed to stop transcriber cleanly", stopErr) // Silently call an error now because on simple transcriber we just transcribe all audio when we stop, and might fail when force stop
//p.sendError("Transcription Error", "Failed to stop transcriber cleanly", stopErr)
} }
}() }()
@@ -232,7 +234,6 @@ func (p *pipeline) handleInjectAction(ctx context.Context, recorder *recording.R
log.Printf("Pipeline: Text injection completed successfully") log.Printf("Pipeline: Text injection completed successfully")
} }
// Return to idle state after injection is complete
p.setStatus(Idle) p.setStatus(Idle)
} }
+2 -2
View File
@@ -1,6 +1,6 @@
# Maintainer: Leonardo Trapani <leo@trapani.sh> # Maintainer: Leonardo Trapani <leo@trapani.sh>
pkgname=hyprvoice-bin pkgname=hyprvoice-bin
pkgver=0.1.5 pkgver=0.1.6
pkgrel=1 pkgrel=1
pkgdesc="Voice-powered typing for Wayland/Hyprland" pkgdesc="Voice-powered typing for Wayland/Hyprland"
arch=('x86_64') arch=('x86_64')
@@ -25,7 +25,7 @@ source=(
"hyprvoice-${pkgver}::https://github.com/leonardotrapani/hyprvoice/releases/download/${pkgver}/hyprvoice-linux-x86_64" "hyprvoice-${pkgver}::https://github.com/leonardotrapani/hyprvoice/releases/download/${pkgver}/hyprvoice-linux-x86_64"
"hyprvoice.service" "hyprvoice.service"
) )
sha256sums=('c3b881864b126341f4b456be3422a4a76657019f750676ba4967776adc931fb8' sha256sums=('5dc88ac616659adb2026043c0c9bd046f3dcfdb1fcca8962ef5994d5c245c631'
'bc4d17afa3a56fc50b09faae4cef9faf2a4ec7f08798b4098ba41ad78b02ab20') 'bc4d17afa3a56fc50b09faae4cef9faf2a4ec7f08798b4098ba41ad78b02ab20')
install=hyprvoice.install install=hyprvoice.install