summary refs log tree commit diff
path: root/src/main.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/main.zig')
-rw-r--r--src/main.zig76
1 files changed, 58 insertions, 18 deletions
diff --git a/src/main.zig b/src/main.zig
index 21e4f3a..7e8d8c5 100644
--- a/src/main.zig
+++ b/src/main.zig
@@ -16,16 +16,17 @@
 // You should have received a copy of the GNU Lesser General Public License
 // along with zeal.  If not, see <https://www.gnu.org/licenses/>.
 
-const al = @import("al.zig");
-const alc = @import("alc.zig");
-const expectEqual = std.testing.expectEqual;
-const eql = std.meta.eql;
+const Allocator = std.mem.Allocator;
+const SndFile = sf.SndFile;
+pub const al = @import("al.zig");
+pub const alc = @import("alc.zig");
+const sf = @import("sf.zig");
 const std = @import("std");
 
 pub const Device = struct {
     pimpl: *alc.Device,
 
-    pub fn init(name: ?[]const u8) alc.Error!Device {
+    pub fn init(name: ?[:0]const u8) alc.Error!Device {
         return Device{ .pimpl = try alc.openDevice(name) };
     }
 
@@ -87,15 +88,61 @@ pub const Buffer = struct {
     context: Context,
     reference: u32,
 
-    pub fn init(context: Context, name: []const u8) !Buffer {
+    pub fn init(allocator: *Allocator, context: Context,
+                name: [:0]const u8) !Buffer {
         try checkContext(context);
-        const reference = try al.genBuffer();
+        const snd_file = try SndFile.open(name, sf.Mode.read);
+        defer snd_file.close();
+        const data = try snd_file.readAll(allocator);
+        defer allocator.free(data);
+        const al_data = switch (snd_file.channels) {
+            1 => al.Data{ .mono16 = data },
+            2 => al.Data{ .stereo16 = data },
+            else => unreachable,
+        };
+
+        const reference = try al.buffer.create();
+        try al.buffer.fill(reference, al_data, snd_file.sample_rate);
         return Buffer{ .context = context, .reference = reference };
     }
 
     pub fn deinit(self: Buffer) !void {
         try checkContext(self.context);
-        try al.deleteBuffer(&self.reference);
+        try al.buffer.destroy(&self.reference);
+    }
+};
+
+pub const Source = struct {
+    context: Context,
+    reference: u32,
+
+    pub fn init(context: Context) !Source {
+        try checkContext(context);
+        const reference = try al.source.create();
+        return Source{ .context = context, .reference = reference };
+    }
+
+    pub fn deinit(self: Source) !void {
+        try checkContext(self.context);
+        try al.source.destroy(&self.reference);
+    }
+
+    pub fn isPlaying(self: Source) !bool {
+        try checkContext(self.context);
+        const state = try al.source.get(i32, self.reference, al.SOURCE_STATE);
+        return state == al.PLAYING;
+    }
+
+    pub fn getSecOffset(self: Source) !f32 {
+        try checkContext(self.context);
+        return try al.source.get(f32, self.reference, al.SEC_OFFSET);
+    }
+
+    pub fn play(self: Source, buffer: Buffer) !void {
+        try checkContext(self.context);
+        try al.source.set(self.reference, al.BUFFER,
+                          @intCast(i32, buffer.reference));
+        try al.source.play(self.reference);
     }
 };
 
@@ -104,6 +151,9 @@ test "Device" {
     try device.deinit();
 }
 
+const testing = std.testing;
+const expectEqual = testing.expectEqual;
+
 test "Context" {
     const device = try Device.init(null);
     defer device.deinit() catch unreachable;
@@ -132,13 +182,3 @@ test "Listener" {
     try listener.setPosition(.{ 1, 2, 3 });
     try listener.setOrientation(.{ 4, 5, 6 }, .{ 7, 8, 9 });
 }
-
-test "Buffer" {
-    const context = try Context.init(try Device.init(null), &.{});
-    defer context.device.deinit() catch unreachable;
-    defer context.deinit() catch unreachable;
-
-    try useContext(context);
-    const buffer = try Buffer.init(context, "");
-    defer buffer.deinit() catch unreachable;
-}