remove demo - we will use. Also add --exec handling

This commit is contained in:
Emil Lerch 2025-09-10 18:40:36 -07:00
parent 6fe5bba155
commit 3a8138c901
Signed by: lobo
GPG key ID: A7B62D657EF764F8
2 changed files with 42 additions and 34 deletions

View file

@ -46,9 +46,9 @@ pub fn build(b: *std.Build) void {
b.installArtifact(stt_lib);
// Create the demo executable
// Create the executable
const exe = b.addExecutable(.{
.name = "stt-demo",
.name = "stt",
.root_module = b.createModule(.{
.root_source_file = b.path("src/main.zig"),
.target = target,
@ -114,7 +114,7 @@ pub fn build(b: *std.Build) void {
const run_dedicated_unit_tests = b.addRunArtifact(dedicated_unit_tests);
// Creates a step for unit testing the demo application
// Creates a step for unit testing the application
const exe_unit_tests = b.addTest(.{
.root_module = b.createModule(.{
.root_source_file = b.path("src/main.zig"),

View file

@ -1,7 +1,4 @@
//! STT Library Demo Application
//!
//! This demonstrates how to use the STT library for speech recognition
//! with callback-based event handling and proper resource management.
//! STT with callback-based event handling
const std = @import("std");
const builtin = @import("builtin");
@ -11,29 +8,38 @@ const stt = @import("stt.zig");
var should_exit = std.atomic.Value(bool).init(false);
/// Demo implementation of speech event handler with comprehensive error handling
const DemoHandler = struct {
const SpeechHandler = struct {
speech_count: u32 = 0,
error_count: u32 = 0,
warning_count: u32 = 0,
recoverable_error_count: u32 = 0,
exec_program: ?[]const u8 = null,
/// Handle detected speech
fn onSpeech(ctx: *anyopaque, text: []const u8) void {
if (builtin.is_test) return; // Suppress output during tests
const self: *DemoHandler = @ptrCast(@alignCast(ctx));
const self: *SpeechHandler = @ptrCast(@alignCast(ctx));
self.speech_count += 1;
// Print with timestamp for better demo experience
// Print with timestamp for better experience
const timestamp = std.time.timestamp();
std.debug.print("[{}] Speech #{}: {s}\n", .{ timestamp, self.speech_count, text });
// Execute program if specified
if (self.exec_program) |program| {
var child = std.process.Child.init(&[_][]const u8{ program, text }, std.heap.page_allocator);
_ = child.spawn() catch |err| {
std.log.err("Failed to execute program '{s}': {}", .{ program, err });
};
}
}
/// Handle basic errors (fallback for compatibility)
fn onError(ctx: *anyopaque, error_code: stt.SttError, message: []const u8) void {
if (builtin.is_test) return; // Suppress output during tests
const self: *DemoHandler = @ptrCast(@alignCast(ctx));
const self: *SpeechHandler = @ptrCast(@alignCast(ctx));
self.error_count += 1;
// Print error with timestamp
@ -43,13 +49,13 @@ const DemoHandler = struct {
/// Handle detailed errors with comprehensive information
fn onDetailedError(ctx: *anyopaque, error_info: stt.SttErrorInfo) void {
const self: *DemoHandler = @ptrCast(@alignCast(ctx));
const self: *SpeechHandler = @ptrCast(@alignCast(ctx));
logDetail(self, error_info) catch |e|
std.log.err("Error writing error {}. Original message: {s}", .{ e, error_info.message });
}
fn logDetail(self: *DemoHandler, error_info: stt.SttErrorInfo) !void {
fn logDetail(self: *SpeechHandler, error_info: stt.SttErrorInfo) !void {
const log = std.log.scoped(.stt);
// Categorize the error for statistics
if (error_info.recoverable)
@ -106,7 +112,7 @@ const DemoHandler = struct {
}
/// Get comprehensive statistics for summary
fn getStats(self: *const DemoHandler) struct {
fn getStats(self: *const SpeechHandler) struct {
speech_count: u32,
error_count: u32,
warning_count: u32,
@ -156,29 +162,31 @@ pub fn main() !void {
});
_ = c.signal(c.SIGINT, signalHandler);
// Create demo handler with statistics tracking
var demo_handler = DemoHandler{};
const speech_handler = stt.SpeechEventHandler{
.onSpeechFn = DemoHandler.onSpeech,
.onErrorFn = DemoHandler.onError,
.onDetailedErrorFn = DemoHandler.onDetailedError,
.ctx = &demo_handler,
};
// Parse command line arguments
const args = try std.process.argsAlloc(allocator);
defer std.process.argsFree(allocator, args);
var model_path: ?[]const u8 = null;
var exec_program: ?[]const u8 = null;
// Parse --model argument
// Parse --model and --exec arguments
for (args[1..]) |arg| {
if (std.mem.startsWith(u8, arg, "--model=")) {
model_path = arg[8..]; // Skip "--model="
break;
} else if (std.mem.startsWith(u8, arg, "--exec=")) {
exec_program = arg[7..]; // Skip "--exec="
}
}
// Create handler with statistics tracking
var handler = SpeechHandler{ .exec_program = exec_program };
const speech_handler = stt.SpeechEventHandler{
.onSpeechFn = SpeechHandler.onSpeech,
.onErrorFn = SpeechHandler.onError,
.onDetailedErrorFn = SpeechHandler.onDetailedError,
.ctx = &handler,
};
// If no model specified, try default locations
const default_paths = [_][]const u8{
"vosk-model-small-en-us-0.15",
@ -197,7 +205,7 @@ pub fn main() !void {
// Check if model path exists
if (model_path == null) {
_ = try stderr.writeAll("Error: Vosk model not found.\n\n");
_ = try stderr.writeAll("Usage: stt-demo [--model=<path>]\n\n");
_ = try stderr.writeAll("Usage: stt [--model=<path>] [--exec=<program>]\n\n");
_ = try stderr.writeAll("Locations searched:\n");
inline for (default_paths) |path|
_ = try stderr.writeAll("\t" ++ path ++ "\n");
@ -289,8 +297,8 @@ pub fn main() !void {
_ = stdout.writeAll("\n----------------------------------------\n") catch {};
_ = stdout.writeAll("Shutdown signal received, stopping...\n") catch {};
// Get final statistics from demo handler
const stats = demo_handler.getStats();
// Get final statistics from handler
const stats = handler.getStats();
std.log.info("Demo Session Summary:", .{});
std.log.info(" Speech detections: {}", .{stats.speech_count});
std.log.info(" Fatal errors: {}", .{stats.error_count});
@ -304,15 +312,15 @@ pub fn main() !void {
_ = stdout.writeAll("Session completed successfully.\n") catch {};
}
// Test the demo functionality
test "demo handler functionality" {
// Test the functionality
test "handler functionality" {
const testing = std.testing;
var demo_handler = DemoHandler{};
var handler = SpeechHandler{};
const speech_handler = stt.SpeechEventHandler{
.onSpeechFn = DemoHandler.onSpeech,
.onErrorFn = DemoHandler.onError,
.ctx = &demo_handler,
.onSpeechFn = SpeechHandler.onSpeech,
.onErrorFn = SpeechHandler.onError,
.ctx = &handler,
};
// Test that callbacks can be invoked without crashing