1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
|
// Audio Library Context wrapper
// Copyright (C) 2021-2022 Nguyễn Gia Phong
//
// This file is part of zeal.
//
// Zeal is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Zeal is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// 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 c = @import("cimport.zig");
/// Opaque device handle.
pub const Device = c.ALCdevice;
/// Opaque context handle.
pub const Context = c.ALCcontext;
pub const Error = error {
/// Invalid device handle.
InvalidDevice,
/// Invalid context handle.
InvalidContext,
/// Invalid enum parameter passed to an ALC call.
InvalidEnum,
/// Invalid value parameter passed to an ALC call.
InvalidValue,
/// Out of memory.
OutOfMemory,
};
pub const FALSE = c.ALC_FALSE;
pub const TRUE = c.ALC_TRUE;
pub const DONT_CARE = c.ALC_DONT_CATE_SOFT;
/// Context creation key to specify whether to enable HRTF
/// (either `FALSE`, `TRUE` or `DONT_CARE`).
pub const HRTF = c.ALC_HRTF_SOFT;
/// Create and attach a context to the given device.
pub fn createContext(device: *Device, attrlist: [:0]const i32) Error!*Context {
if (c.alcCreateContext(device, attrlist.ptr)) |context|
return context;
return switch (c.alcGetError(device)) {
c.ALC_INVALID_DEVICE => Error.InvalidDevice,
c.ALC_INVALID_VALUE => Error.InvalidValue,
else => unreachable,
};
}
/// Make the given context the active process-wide context.
/// Passing NULL clears the active context.
pub fn makeContextCurrent(context: ?*Context) Error!void {
if (c.alcMakeContextCurrent(context) == TRUE)
return;
if (c.alcGetError(null) == c.ALC_INVALID_CONTEXT)
return Error.InvalidContext;
unreachable;
}
/// Remove a context from its device and destroys it.
pub fn destroyContext(context: *Context) Error!void {
c.alcDestroyContext(context);
if (c.alcGetError(null) == c.ALC_INVALID_CONTEXT)
return Error.InvalidContext;
}
/// Return the currently active context.
pub fn getCurrentContext() ?*Context {
return c.alcGetCurrentContext();
}
/// Return the device that a particular context is attached to.
pub fn getContextsDevice(context: *Context) Error!*Device {
if (c.alcGetContextsDevice(context)) |device|
return device;
if (c.alcGetError(null) == c.ALC_INVALID_CONTEXT)
return Error.InvalidContext;
unreachable;
}
/// Open the named playback device.
pub fn openDevice(name: ?[:0]const u8) Error!*Device {
const name_ptr = if (name == null) null else name.?.ptr;
if (c.alcOpenDevice(name_ptr)) |device|
return device;
return switch (c.alcGetError(null)) {
c.ALC_INVALID_VALUE => Error.InvalidValue,
c.ALC_OUT_OF_MEMORY => Error.OutOfMemory,
else => unreachable,
};
}
/// Close the given playback device.
pub fn closeDevice(device: *Device) Error!void {
if (c.alcCloseDevice(device) == TRUE)
return;
if (c.alcGetError(device) == c.ALC_INVALID_DEVICE)
return Error.InvalidDevice;
unreachable;
}
pub fn getInt(device: *Device, param: c.ALCenum) Error!i32 {
var data: i32 = undefined;
c.alcGetIntegerv(device, param, 1, &data);
return switch (c.alcGetError(device)) {
c.ALC_NO_ERROR => data,
c.ALC_INVALID_VALUE => Error.InvalidValue,
c.ALC_INVALID_ENUM => Error.InvalidEnum,
c.ALC_INVALID_DEVICE => Error.InvalidDevice,
c.ALC_INVALID_CONTEXT => Error.InvalidContext,
else => unreachable,
};
}
|