Client LuaCsForBarotrauma
Alc.cs
1 /***
2 
3 MIT License
4 
5 Copyright (c) 2018 Nathan Glover
6 
7 Permission is hereby granted, free of charge, to any person obtaining a copy
8 of this software and associated documentation files (the "Software"), to deal
9 in the Software without restriction, including without limitation the rights
10 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 copies of the Software, and to permit persons to whom the Software is
12 furnished to do so, subject to the following conditions:
13 
14 The above copyright notice and this permission notice shall be included in all
15 copies or substantial portions of the Software.
16 
17 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 SOFTWARE.
24 
25 ****************
26 
27 Further modified for use in Barotrauma.
28 Original source code at https://github.com/NathanielGlover/OpenAL.NETCore/
29 
30 ***/
31 
32 using System;
33 using System.Runtime.InteropServices;
34 using System.Collections.Generic;
35 using System.Text;
36 
37 namespace OpenAL
38 {
39  public class Alc
40  {
41 #if OSX
42  public const string OpenAlDll = "/System/Library/Frameworks/OpenAL.framework/OpenAL";
43 #elif LINUX
44  public const string OpenAlDll = "libopenal.so.1";
45 #elif WINDOWS
46  public const string OpenAlDll = "soft_oal_x64.dll";
47 #endif
48 
49  public delegate void ErrorReasonCallback(string str);
50 
51 #if WINDOWS
52  [DllImport(OpenAlDll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "alcSetErrorReasonCallback")]
53  private static extern void SetErrorReasonCallback(IntPtr callback);
54 
55  [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
56  private delegate void ErrorReasonCallbackInternal(IntPtr cstr);
57 
58  private static ErrorReasonCallbackInternal CurrentErrorReasonCallback;
59  private static IntPtr CurrentErrorReasonCallbackPtr;
60 
61  public static void SetErrorReasonCallback(ErrorReasonCallback callback)
62  {
63  CurrentErrorReasonCallback = (IntPtr cstr) =>
64  {
65  int strLen = 0;
66  while (Marshal.ReadByte(cstr, strLen) != '\0') { strLen++; }
67  byte[] bytes = new byte[strLen];
68  Marshal.Copy(cstr, bytes, 0, strLen);
69  string csStr = Encoding.UTF8.GetString(bytes);
70 
71  callback?.Invoke(csStr);
72  };
73 
74  CurrentErrorReasonCallbackPtr = Marshal.GetFunctionPointerForDelegate(CurrentErrorReasonCallback);
75  SetErrorReasonCallback(CurrentErrorReasonCallbackPtr);
76  }
77 #else
78  public static void SetErrorReasonCallback(ErrorReasonCallback callback)
79  {
80  //FIXME: not implemented on macOS and Linux
81  }
82 #endif
83 
84  #region Enum
85 
86  public const int False = 0;
87  public const int True = 1;
88  public const int Frequency = 0x1007;
89  public const int Refresh = 0x1008;
90  public const int Sync = 0x1009;
91  public const int MonoSources = 0x1010;
92  public const int StereoSources = 0x1011;
93  public const int NoError = False;
94  public const int InvalidDevice = 0xA001;
95  public const int InvalidContext = 0xA002;
96  public const int InvalidEnum = 0xA003;
97  public const int InvalidValue = 0xA004;
98  public const int OutOfMemory = 0xA005;
99  public const int DefaultDeviceSpecifier = 0x1004;
100  public const int DeviceSpecifier = 0x1005;
101  public const int Extensions = 0x1006;
102  public const int MajorVersion = 0x1000;
103  public const int MinorVersion = 0x1001;
104  public const int AttributesSize = 0x1002;
105  public const int AllAttributes = 0x1003;
106  public const int DefaultAllDevicesSpecifier = 0x1012;
107  public const int AllDevicesSpecifier = 0x1013;
108  public const int CaptureDeviceSpecifier = 0x310;
109  public const int CaptureDefaultDeviceSpecifier = 0x311;
110  public const int EnumCaptureSamples = 0x312;
111  public const int EnumConnected = 0x313;
112 
113 
114  public const int OutputDevicesSpecifier =
115 #if OSX
117 #else
119 #endif
120 
121 #endregion
122 
123 #region Context Management Functions
124 
125  [DllImport(OpenAlDll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "alcCreateContext")]
126  private static extern IntPtr _CreateContext(IntPtr device, IntPtr attrlist);
127 
128  public static IntPtr CreateContext(IntPtr device, int[] attrList)
129  {
130  GCHandle handle = GCHandle.Alloc(attrList, GCHandleType.Pinned);
131  IntPtr retVal = _CreateContext(device, handle.AddrOfPinnedObject());
132  handle.Free();
133  return retVal;
134  }
135 
136  [DllImport(OpenAlDll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "alcMakeContextCurrent")]
137  public static extern bool MakeContextCurrent(IntPtr context);
138 
139  [DllImport(OpenAlDll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "alcProcessContext")]
140  public static extern void ProcessContext(IntPtr context);
141 
142  [DllImport(OpenAlDll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "alcSuspendContext")]
143  public static extern void SuspendContext(IntPtr context);
144 
145  [DllImport(OpenAlDll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "alcDestroyContext")]
146  public static extern void DestroyContext(IntPtr context);
147 
148  [DllImport(OpenAlDll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "alcGetCurrentContext")]
149  public static extern IntPtr GetCurrentContext();
150 
151  [DllImport(OpenAlDll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "alcGetContextsDevice")]
152  public static extern IntPtr GetContextsDevice(IntPtr context);
153 
154  [DllImport(OpenAlDll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "alcOpenDevice")]
155  private static extern IntPtr OpenDevice(IntPtr deviceName);
156 
157  public static IntPtr OpenDevice(string deviceName)
158  {
159  if (deviceName == null)
160  {
161  return OpenDevice(IntPtr.Zero);
162  }
163 
164  byte[] devicenameBytes = Encoding.UTF8.GetBytes(deviceName + "\0");
165  GCHandle devicenameHandle = GCHandle.Alloc(devicenameBytes, GCHandleType.Pinned);
166  IntPtr retVal = OpenDevice(devicenameHandle.AddrOfPinnedObject());
167  devicenameHandle.Free();
168 
169  return retVal;
170  }
171 
172  [DllImport(OpenAlDll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "alcCloseDevice")]
173  public static extern bool CloseDevice(IntPtr device);
174 
175  [DllImport(OpenAlDll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "alcGetError")]
176  public static extern int GetError(IntPtr device);
177 
178  public static string GetErrorString(int errorCode)
179  {
180  switch (errorCode)
181  {
182  case NoError:
183  return "No error";
184  case InvalidContext:
185  return "Invalid context";
186  case InvalidDevice:
187  return "Invalid device";
188  case InvalidEnum:
189  return "Invalid enum";
190  case InvalidValue:
191  return "Invalid value";
192  case OutOfMemory:
193  return "Out of memory";
194  default:
195  return "Unknown error";
196  }
197  }
198 
199  [DllImport(OpenAlDll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "alcIsExtensionPresent")]
200  public static extern bool IsExtensionPresent(IntPtr device, string extname);
201 
202  [DllImport(OpenAlDll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "alcGetProcAddress")]
203  public static extern IntPtr GetProcAddress(IntPtr device, string funcname);
204 
205  [DllImport(OpenAlDll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "alcGetEnumValue")]
206  public static extern int GetEnumValue(IntPtr device, string enumname);
207 
208 #endregion
209 
210 #region Query Functions
211 
212  [DllImport(OpenAlDll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "alcGetString")]
213  private static extern IntPtr _GetString(IntPtr device, int param);
214 
215  public static string GetString(IntPtr device, int param)
216  {
217  IntPtr strPtr = _GetString(device, param);
218  int strLen = 0;
219  while (Marshal.ReadByte(strPtr,strLen)!='\0') { strLen++; }
220  byte[] bytes = new byte[strLen];
221  Marshal.Copy(strPtr, bytes, 0, strLen);
222  return Encoding.UTF8.GetString(bytes);
223  }
224 
225  public static IReadOnlyList<string> GetStringList(IntPtr device, int param)
226  {
227  List<string> retVal = new List<string>();
228  IntPtr strPtr = _GetString(device, param);
229  if (strPtr == IntPtr.Zero) { return retVal; }
230  int strStart = 0;
231  int strEnd = 0;
232  byte currChar = Marshal.ReadByte(strPtr, strEnd);
233  if (currChar == '\0') { return retVal; }
234  byte prevChar = 255;
235  while (true)
236  {
237  strEnd++;
238  prevChar = currChar;
239  currChar = Marshal.ReadByte(strPtr, strEnd);
240 
241  if (currChar == '\0')
242  {
243  if (prevChar == '\0')
244  {
245  break;
246  }
247  byte[] bytes = new byte[strEnd-strStart];
248  Marshal.Copy(strPtr+strStart, bytes, 0, strEnd - strStart);
249  retVal.Add(Encoding.UTF8.GetString(bytes));
250  strStart = strEnd+1;
251  }
252  }
253  return retVal;
254  }
255 
256  [DllImport(OpenAlDll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "alcGetIntegerv")]
257  public static extern void GetIntegerv(IntPtr device, int param, int size, IntPtr data);
258 
259  public static void GetInteger(IntPtr device, int param, out int data)
260  {
261  int[] dataArr = new int[1];
262  GCHandle handle = GCHandle.Alloc(dataArr,GCHandleType.Pinned);
263  GetIntegerv(device, param, 1, handle.AddrOfPinnedObject());
264  handle.Free();
265  data = dataArr[0];
266  }
267 
268 #endregion
269 
270 #region Capture Functions
271 
272  [DllImport(OpenAlDll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "alcCaptureOpenDevice")]
273  private static extern IntPtr CaptureOpenDevice(IntPtr devicename, uint frequency, int format, int buffersize);
274 
275  public static IntPtr CaptureOpenDevice(string devicename, uint frequency, int format, int buffersize)
276  {
277  byte[] devicenameBytes = Encoding.UTF8.GetBytes(devicename + "\0");
278  GCHandle devicenameHandle = GCHandle.Alloc(devicenameBytes, GCHandleType.Pinned);
279  IntPtr retVal = CaptureOpenDevice(devicenameHandle.AddrOfPinnedObject(), frequency, format, buffersize);
280  devicenameHandle.Free();
281  return retVal;
282  }
283 
284  [DllImport(OpenAlDll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "alcCaptureCloseDevice")]
285  public static extern bool CaptureCloseDevice(IntPtr device);
286 
287  [DllImport(OpenAlDll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "alcCaptureStart")]
288  public static extern void CaptureStart(IntPtr device);
289 
290  [DllImport(OpenAlDll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "alcCaptureStop")]
291  public static extern void CaptureStop(IntPtr device);
292 
293  [DllImport(OpenAlDll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "alcCaptureSamples")]
294  public static extern void CaptureSamples(IntPtr device, IntPtr buffer, int samples);
295 
296 #endregion
297  }
298 }
static bool MakeContextCurrent(IntPtr context)
const int CaptureDeviceSpecifier
Definition: Alc.cs:108
const int AllAttributes
Definition: Alc.cs:105
const int InvalidContext
Definition: Alc.cs:95
const int InvalidValue
Definition: Alc.cs:97
static IntPtr CaptureOpenDevice(string devicename, uint frequency, int format, int buffersize)
Definition: Alc.cs:275
const int OutOfMemory
Definition: Alc.cs:98
const int EnumConnected
Definition: Alc.cs:111
const int InvalidDevice
Definition: Alc.cs:94
static int GetEnumValue(IntPtr device, string enumname)
static void CaptureStop(IntPtr device)
static IntPtr GetCurrentContext()
static IntPtr OpenDevice(string deviceName)
Definition: Alc.cs:157
static IReadOnlyList< string > GetStringList(IntPtr device, int param)
Definition: Alc.cs:225
static void CaptureSamples(IntPtr device, IntPtr buffer, int samples)
static int GetError(IntPtr device)
static void DestroyContext(IntPtr context)
const int MonoSources
Definition: Alc.cs:91
const int DeviceSpecifier
Definition: Alc.cs:100
const int AllDevicesSpecifier
Definition: Alc.cs:107
static bool CloseDevice(IntPtr device)
static void CaptureStart(IntPtr device)
const int InvalidEnum
Definition: Alc.cs:96
const int StereoSources
Definition: Alc.cs:92
const int AttributesSize
Definition: Alc.cs:104
static IntPtr GetContextsDevice(IntPtr context)
static void SetErrorReasonCallback(ErrorReasonCallback callback)
Definition: Alc.cs:78
const int MajorVersion
Definition: Alc.cs:102
const int MinorVersion
Definition: Alc.cs:103
static bool CaptureCloseDevice(IntPtr device)
static string GetErrorString(int errorCode)
Definition: Alc.cs:178
const int Extensions
Definition: Alc.cs:101
const int DefaultAllDevicesSpecifier
Definition: Alc.cs:106
const int Frequency
Definition: Alc.cs:88
delegate void ErrorReasonCallback(string str)
static void GetInteger(IntPtr device, int param, out int data)
Definition: Alc.cs:259
const int True
Definition: Alc.cs:87
const int Refresh
Definition: Alc.cs:89
static IntPtr CreateContext(IntPtr device, int[] attrList)
Definition: Alc.cs:128
const int DefaultDeviceSpecifier
Definition: Alc.cs:99
static void SuspendContext(IntPtr context)
static void GetIntegerv(IntPtr device, int param, int size, IntPtr data)
static IntPtr GetProcAddress(IntPtr device, string funcname)
const int EnumCaptureSamples
Definition: Alc.cs:110
const int Sync
Definition: Alc.cs:90
const int CaptureDefaultDeviceSpecifier
Definition: Alc.cs:109
const int OutputDevicesSpecifier
Definition: Alc.cs:114
const int NoError
Definition: Alc.cs:93
static bool IsExtensionPresent(IntPtr device, string extname)
static void ProcessContext(IntPtr context)
const int False
Definition: Alc.cs:86
static string GetString(IntPtr device, int param)
Definition: Alc.cs:215
Definition: Al.cs:36