// SPDX-FileCopyrightText: © 2026 Jeffrey C. Ollie // SPDX-License-Identifier: MIT //! Plays audio files through the system's sound output, one after another: //! the library end to end, and a way to hear what a file sounds like. //! //! zig build play -- [--volume 0.5] [--times N] bell.flac ... const std = @import("std"); const chime = @import("chime"); pub fn main(init: std.process.Init) !void { const gpa = init.gpa; const io = init.io; var stderr_buffer: [1024]u8 = undefined; var stderr_writer = std.Io.File.stderr().writer(io, &stderr_buffer); const stderr = &stderr_writer.interface; defer stderr.flush() catch {}; var args = try init.minimal.args.iterateAllocator(gpa); defer args.deinit(); _ = args.skip(); var volume: f32 = 1; var times: u32 = 1; var player = try chime.Player.init(gpa, io, .{ .name = "zig-chime", .environ = init.minimal.environ }); defer player.deinit(); var played: usize = 0; while (args.next()) |arg| { if (std.mem.eql(u8, arg, "--volume")) { volume = try std.fmt.parseFloat(f32, args.next() orelse return error.MissingVolume); continue; } if (std.mem.eql(u8, arg, "--times")) { times = try std.fmt.parseInt(u32, args.next() orelse return error.MissingTimes, 10); continue; } var sound = chime.Sound.load(gpa, io, std.Io.Dir.cwd(), arg, .{}) catch |err| { try stderr.print("{s}: {t}\n", .{ arg, err }); continue; }; defer sound.deinit(gpa); defer player.release(&sound); try stderr.print("{s}: {d} Hz, {d} channels, {d} ms\n", .{ arg, sound.rate, sound.channels, sound.durationMs() }); try stderr.flush(); for (0..times) |_| { _ = try player.play(&sound, volume); // Until the Play has finished, with a second to spare in case the // sound server never starts it. var waited: u64 = 0; while (player.isPlaying(&sound) and waited < sound.durationMs() + 1000) : (waited += 10) { try std.Io.Clock.Duration.sleep(.{ .raw = .fromMilliseconds(10), .clock = .awake }, io); } if (player.isPlaying(&sound)) { try stderr.print("{s}: still playing after {d} ms\n", .{ arg, waited }); return error.PlaybackStalled; } } played += 1; } if (played == 0) { try stderr.writeAll("usage: play [--volume V] [--times N] FILE...\n"); return error.NothingPlayed; } }