Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 4 additions & 4 deletions apps/wisp-desktop/src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
use std::collections::VecDeque;
use std::time::Instant;

use wisp_audiokit::{Event, SessionResult, SourceLabel};
use wisp_audiokit::{Event, SessionError, SessionResult, SourceLabel};

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum SessionState {
Expand Down Expand Up @@ -42,7 +42,7 @@ pub struct AppModel {
pub state: SessionState,
pub segments: Vec<Segment>,
pub recent_log: VecDeque<String>,
pub last_error: Option<String>,
pub last_error: Option<SessionError>,
}

impl AppModel {
Expand All @@ -64,9 +64,9 @@ impl AppModel {

pub fn fail(
&mut self,
message: impl Into<String>,
error: SessionError,
) {
self.last_error = Some(message.into());
self.last_error = Some(error);
self.state = SessionState::Failed;
self.finalize_all_segments();
}
Expand Down
8 changes: 4 additions & 4 deletions apps/wisp-desktop/src/session_runner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use std::sync::mpsc::{Receiver, Sender, TryRecvError, channel};
use std::thread::JoinHandle;
use std::time::Duration;

use wisp_audiokit::{Event, Session};
use wisp_audiokit::{Event, Session, SessionError};

/// Commands the UI sends to the worker.
pub enum Command {
Expand All @@ -28,7 +28,7 @@ pub enum Update {
/// `Session::stop()` returned; the session has been torn down.
Stopped,
/// Lifecycle error (start/construct failed).
Error(String),
Error(SessionError),
}

pub struct SessionRunner {
Expand Down Expand Up @@ -108,12 +108,12 @@ fn run_session(
let session = match Session::new(output_dir, locale) {
Ok(s) => s,
Err(e) => {
let _ = update_tx.send(Update::Error(e.to_string()));
let _ = update_tx.send(Update::Error(e));
return;
},
};
if let Err(e) = session.start() {
let _ = update_tx.send(Update::Error(e.to_string()));
let _ = update_tx.send(Update::Error(e));
return;
}
let _ = update_tx.send(Update::Started);
Expand Down
6 changes: 3 additions & 3 deletions apps/wisp-desktop/src/transcript_view.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use gpui::{
Context, ElementId, FontWeight, InteractiveElement, IntoElement, ParentElement, Render,
ScrollHandle, StatefulInteractiveElement, Styled, Window, div, px, rgb,
};
use wisp_audiokit::SourceLabel;
use wisp_audiokit::{SessionError, SourceLabel};

use crate::app::{AppModel, Segment, SessionState};

Expand Down Expand Up @@ -113,7 +113,7 @@ impl Render for TranscriptView {
state,
segments.len(),
log_count,
last_error.as_deref(),
last_error.as_ref(),
))
}
}
Expand Down Expand Up @@ -320,7 +320,7 @@ fn render_status_bar(
state: SessionState,
segment_count: usize,
log_count: usize,
last_error: Option<&str>,
last_error: Option<&SessionError>,
) -> impl IntoElement {
let (dot, status_text) = match state {
SessionState::Idle => (theme::record_idle(), "Idle".to_string()),
Expand Down
26 changes: 26 additions & 0 deletions crates/wisp-audiokit/src/error.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/// Errors surfaced by [`crate::Session`] operations.
#[derive(Debug, Clone, thiserror::Error)]
pub enum SessionError {
#[cfg(target_os = "macos")]
#[error("path contains a NUL byte or is not representable as a C string: {0:?}")]
InvalidPath(std::path::PathBuf),

#[cfg(target_os = "macos")]
#[error("locale contains a NUL byte: {0}")]
InvalidLocale(String),

#[cfg(target_os = "macos")]
#[error("WispAudioKit session construction failed")]
Construction,

#[cfg(target_os = "macos")]
#[error("WispAudioKit session start failed: {0}")]
Start(String),

#[cfg(not(target_os = "macos"))]
#[error("WispAudioKit is only available on macOS")]
UnsupportedPlatform,
}

/// Result alias for session operations.
pub type Result<T> = std::result::Result<T, SessionError>;
39 changes: 9 additions & 30 deletions crates/wisp-audiokit/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@
//! Wraps the raw FFI from `wisp-audiokit-sys`. macOS-only; on other platforms
//! everything is stubbed out so the workspace stays buildable.

mod error;

pub use error::{Result, SessionError};

#[cfg(target_os = "macos")]
mod imp {
use std::ffi::{CStr, CString};
Expand All @@ -13,6 +17,8 @@ mod imp {
use wisp_audiokit_sys as sys;
use wisp_core::SourceLabel;

use crate::error::{Result, SessionError};

/// `WispAudioKit` library version (e.g. `"0.1.0"`).
///
/// # Panics
Expand Down Expand Up @@ -50,25 +56,6 @@ mod imp {
Log(String),
}

/// Errors surfaced by [`Session`] operations.
#[derive(Debug, thiserror::Error)]
pub enum SessionError {
#[error("path contains a NUL byte or is not representable as a C string: {0:?}")]
InvalidPath(std::path::PathBuf),

#[error("locale contains a NUL byte: {0}")]
InvalidLocale(String),

#[error("WispAudioKit session construction failed")]
Construction,

#[error("WispAudioKit session start failed: {0}")]
Start(String),
}

/// Result alias for session operations.
pub type Result<T> = std::result::Result<T, SessionError>;

// ---- Session -------------------------------------------------------

/// Owns one running (or yet-to-be-started) capture + transcription session.
Expand Down Expand Up @@ -267,6 +254,8 @@ mod imp {

use wisp_core::SourceLabel;

use crate::error::{Result, SessionError};

/// `WispAudioKit` library version. Always empty on non-macOS targets.
#[must_use]
pub fn version() -> &'static str {
Expand All @@ -290,16 +279,6 @@ mod imp {
Log(String),
}

/// Errors surfaced by [`Session`] operations.
#[derive(Debug, thiserror::Error)]
pub enum SessionError {
#[error("WispAudioKit is only available on macOS")]
UnsupportedPlatform,
}

/// Result alias for session operations.
pub type Result<T> = std::result::Result<T, SessionError>;

/// Stub session — always returns [`SessionError::UnsupportedPlatform`].
pub struct Session;

Expand Down Expand Up @@ -337,7 +316,7 @@ mod imp {
}

pub use imp::version;
pub use imp::{Event, Session, SessionError, SessionResult};
pub use imp::{Event, Session, SessionResult};
pub use wisp_core::SourceLabel;

#[cfg(all(test, target_os = "macos"))]
Expand Down
1 change: 1 addition & 0 deletions crates/wisp-core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,4 @@ workspace = true
# so they live here in the shared crate.
chrono = { workspace = true, features = ["serde"] }
serde = { workspace = true }
thiserror = { workspace = true }
4 changes: 4 additions & 0 deletions crates/wisp-core/src/error.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
/// Errors produced when parsing a [`crate::SourceLabel`] from its stable string form.
#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
#[error("unrecognized source label: {0}")]
pub struct SourceLabelError(pub String);
2 changes: 2 additions & 0 deletions crates/wisp-core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@
//! framework wrapper (`wisp-audiokit`) into storage (`wisp-storage`) and
//! the `GPUI` desktop app (`wisp-desktop`).

mod error;
mod ids;
mod source;
mod transcript;

pub use error::SourceLabelError;
pub use ids::{SegmentId, SessionId};
pub use source::SourceLabel;
pub use transcript::{NewSegment, NewSession, Segment, Session};
4 changes: 2 additions & 2 deletions crates/wisp-core/src/source.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,13 @@ impl SourceLabel {
}

impl std::str::FromStr for SourceLabel {
type Err = ();
type Err = crate::SourceLabelError;

fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
match s {
"mic" => Ok(Self::Mic),
"system" => Ok(Self::System),
_ => Err(()),
_ => Err(crate::SourceLabelError(s.to_owned())),
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions crates/wisp-storage/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ pub enum StorageError {
source: rusqlite::Error,
},

#[error("unrecognized source label in database: {0}")]
UnknownSource(String),
#[error(transparent)]
SourceLabel(#[from] wisp_core::SourceLabelError),
}

pub type Result<T> = std::result::Result<T, StorageError>;
10 changes: 4 additions & 6 deletions crates/wisp-storage/src/segments.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use chrono::Utc;
use rusqlite::{Connection, params};
use wisp_core::{NewSegment, Segment, SegmentId, SessionId, SourceLabel};

use crate::error::{Result, StorageError};
use crate::error::Result;

/// Read/write operations for the `segments` table.
pub struct Segments<'a> {
Expand Down Expand Up @@ -55,7 +55,7 @@ impl<'a> Segments<'a> {
///
/// # Errors
/// Returns [`crate::StorageError::Sqlite`] on query failure or
/// [`StorageError::UnknownSource`] if the DB holds a `source` value
/// [`StorageError::SourceLabel`] if the DB holds a `source` value
/// outside `{"mic","system"}` (only possible via direct DB edits).
pub fn list_by_session(
&self,
Expand All @@ -81,7 +81,7 @@ impl<'a> Segments<'a> {
///
/// # Errors
/// Returns [`crate::StorageError::Sqlite`] on query failure or
/// [`StorageError::UnknownSource`] (see [`Self::list_by_session`]).
/// [`StorageError::SourceLabel`] (see [`Self::list_by_session`]).
pub fn search(
&self,
query: &str,
Expand Down Expand Up @@ -109,9 +109,7 @@ impl<'a> Segments<'a> {

fn row_to_segment(row: &rusqlite::Row<'_>) -> Result<Segment> {
let source_str: String = row.get(2)?;
let source = source_str
.parse::<SourceLabel>()
.map_err(|()| StorageError::UnknownSource(source_str))?;
let source = source_str.parse::<SourceLabel>()?;
Ok(Segment {
id: SegmentId::from(row.get::<_, i64>(0)?),
session_id: SessionId::from(row.get::<_, i64>(1)?),
Expand Down