Added AudioCapture.IsRunning property.
Fixed formatting.
This commit is contained in:
parent
f1976edb8b
commit
b19d7bf4c5
2 changed files with 278 additions and 247 deletions
|
@ -1,188 +1,174 @@
|
|||
#region License
|
||||
//
|
||||
// The Open Toolkit Library License
|
||||
//
|
||||
// Copyright (c) 2006 - 2009 the Open Toolkit library.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights to
|
||||
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
// the Software, and to permit persons to whom the Software is furnished to do
|
||||
// so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
// OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
#region License
|
||||
//
|
||||
// The Open Toolkit Library License
|
||||
//
|
||||
// Copyright (c) 2006 - 2009 the Open Toolkit library.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights to
|
||||
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
// the Software, and to permit persons to whom the Software is furnished to do
|
||||
// so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
// OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace OpenTK.Audio
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Provides methods to instantiate, use and destroy an audio device for recording.
|
||||
/// Static methods are provided to list available devices known by the driver.
|
||||
/// </summary>
|
||||
public sealed class AudioCapture : IDisposable
|
||||
{
|
||||
#region Fields
|
||||
|
||||
// This must stay private info so the end-user cannot call any Alc commands for the recording device.
|
||||
IntPtr Handle;
|
||||
|
||||
// Alc.CaptureStop should be called prior to device shutdown, this keeps track of Alc.CaptureStart/Stop calls.
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace OpenTK.Audio
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Provides methods to instantiate, use and destroy an audio device for recording.
|
||||
/// Static methods are provided to list available devices known by the driver.
|
||||
/// </summary>
|
||||
public sealed class AudioCapture : IDisposable
|
||||
{
|
||||
#region Fields
|
||||
|
||||
// This must stay private info so the end-user cannot call any Alc commands for the recording device.
|
||||
IntPtr Handle;
|
||||
|
||||
// Alc.CaptureStop should be called prior to device shutdown, this keeps track of Alc.CaptureStart/Stop calls.
|
||||
bool _isrecording = false;
|
||||
|
||||
ALFormat sample_format;
|
||||
int sample_frequency;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Device Name
|
||||
private string device_name;
|
||||
/// <summary>The name of the device associated with this instance.</summary>
|
||||
public string CurrentDeviceName
|
||||
{
|
||||
get
|
||||
{
|
||||
return device_name;
|
||||
}
|
||||
}
|
||||
#endregion Device Name
|
||||
|
||||
#region public static properties
|
||||
/// <summary>Returns a list of strings containing all known recording devices.</summary>
|
||||
public static IList<string> AvailableDevices
|
||||
{
|
||||
get
|
||||
{
|
||||
return AudioDeviceEnumerator.AvailableRecordingDevices;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Returns the name of the device that will be used as recording default.</summary>
|
||||
public static string DefaultDevice
|
||||
{
|
||||
get
|
||||
{
|
||||
return AudioDeviceEnumerator.DefaultRecordingDevice;
|
||||
}
|
||||
}
|
||||
#endregion public static properties
|
||||
|
||||
#region Constructor
|
||||
|
||||
static AudioCapture()
|
||||
{
|
||||
if (AudioDeviceEnumerator.IsOpenALSupported) // forces enumeration
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Opens the default device for audio recording.
|
||||
/// Implicitly set parameters are: 22050Hz, 16Bit Mono, 4096 samples ringbuffer.
|
||||
/// </summary>
|
||||
int sample_frequency;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
static AudioCapture()
|
||||
{
|
||||
if (AudioDeviceEnumerator.IsOpenALSupported) // forces enumeration
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Opens the default device for audio recording.
|
||||
/// Implicitly set parameters are: 22050Hz, 16Bit Mono, 4096 samples ringbuffer.
|
||||
/// </summary>
|
||||
public AudioCapture()
|
||||
: this(AudioCapture.DefaultDevice, 22050, ALFormat.Mono16, 4096)
|
||||
{
|
||||
}
|
||||
|
||||
: this(AudioCapture.DefaultDevice, 22050, ALFormat.Mono16, 4096)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>Opens a device for audio recording.</summary>
|
||||
/// <param name="deviceName">The device name.</param>
|
||||
/// <param name="deviceName">The device name.</param>
|
||||
/// <param name="frequency">The frequency that the data should be captured at.</param>
|
||||
/// <param name="sampleFormat">The requested capture buffer format.</param>
|
||||
/// <param name="bufferSize">The size of OpenAL's capture internal ring-buffer. This value expects number of samples, not bytes.</param>
|
||||
public AudioCapture(string deviceName, int frequency, ALFormat sampleFormat, int bufferSize)
|
||||
{
|
||||
if (!AudioDeviceEnumerator.IsOpenALSupported)
|
||||
throw new DllNotFoundException("openal32.dll");
|
||||
|
||||
// Try to open specified device. If it fails, try to open default device.
|
||||
device_name = deviceName;
|
||||
Handle = Alc.CaptureOpenDevice(deviceName, frequency, sampleFormat, bufferSize);
|
||||
|
||||
if (Handle == IntPtr.Zero)
|
||||
{
|
||||
Debug.WriteLine(ErrorMessage(deviceName, frequency, sampleFormat, bufferSize));
|
||||
device_name = "IntPtr.Zero";
|
||||
Handle = Alc.CaptureOpenDevice(null, frequency, sampleFormat, bufferSize);
|
||||
}
|
||||
|
||||
if (Handle == IntPtr.Zero)
|
||||
/// <param name="bufferSize">The size of OpenAL's capture internal ring-buffer. This value expects number of samples, not bytes.</param>
|
||||
public AudioCapture(string deviceName, int frequency, ALFormat sampleFormat, int bufferSize)
|
||||
{
|
||||
if (!AudioDeviceEnumerator.IsOpenALSupported)
|
||||
throw new DllNotFoundException("openal32.dll");
|
||||
if (frequency <= 0)
|
||||
throw new ArgumentOutOfRangeException("frequency");
|
||||
if (bufferSize <= 0)
|
||||
throw new ArgumentOutOfRangeException("bufferSize");
|
||||
|
||||
// Try to open specified device. If it fails, try to open default device.
|
||||
device_name = deviceName;
|
||||
Handle = Alc.CaptureOpenDevice(deviceName, frequency, sampleFormat, bufferSize);
|
||||
|
||||
if (Handle == IntPtr.Zero)
|
||||
{
|
||||
Debug.WriteLine(ErrorMessage("IntPtr.Zero", frequency, sampleFormat, bufferSize));
|
||||
device_name = AudioDeviceEnumerator.DefaultRecordingDevice;
|
||||
Handle = Alc.CaptureOpenDevice(AudioDeviceEnumerator.DefaultRecordingDevice, frequency, sampleFormat, bufferSize);
|
||||
}
|
||||
|
||||
if (Handle == IntPtr.Zero)
|
||||
Debug.WriteLine(ErrorMessage(deviceName, frequency, sampleFormat, bufferSize));
|
||||
device_name = "IntPtr.Zero";
|
||||
Handle = Alc.CaptureOpenDevice(null, frequency, sampleFormat, bufferSize);
|
||||
}
|
||||
|
||||
if (Handle == IntPtr.Zero)
|
||||
{
|
||||
// Everything we tried failed. Capture may not be supported, bail out.
|
||||
Debug.WriteLine(ErrorMessage(AudioDeviceEnumerator.DefaultRecordingDevice, frequency, sampleFormat, bufferSize));
|
||||
device_name = "None";
|
||||
|
||||
throw new AudioDeviceException("All attempts to open capture devices returned IntPtr.Zero. See debug log for verbose list.");
|
||||
}
|
||||
|
||||
Debug.WriteLine(ErrorMessage("IntPtr.Zero", frequency, sampleFormat, bufferSize));
|
||||
device_name = AudioDeviceEnumerator.DefaultRecordingDevice;
|
||||
Handle = Alc.CaptureOpenDevice(AudioDeviceEnumerator.DefaultRecordingDevice, frequency, sampleFormat, bufferSize);
|
||||
}
|
||||
|
||||
if (Handle == IntPtr.Zero)
|
||||
{
|
||||
// Everything we tried failed. Capture may not be supported, bail out.
|
||||
Debug.WriteLine(ErrorMessage(AudioDeviceEnumerator.DefaultRecordingDevice, frequency, sampleFormat, bufferSize));
|
||||
device_name = "None";
|
||||
|
||||
throw new AudioDeviceException("All attempts to open capture devices returned IntPtr.Zero. See debug log for verbose list.");
|
||||
}
|
||||
|
||||
// handle is not null, check for some Alc Error
|
||||
CheckErrors();
|
||||
|
||||
SampleFormat = sampleFormat;
|
||||
SampleFrequency = frequency;
|
||||
}
|
||||
|
||||
#endregion Constructor
|
||||
|
||||
#region IDisposable Members
|
||||
|
||||
~AudioCapture()
|
||||
{
|
||||
Dispose();
|
||||
}
|
||||
|
||||
private bool IsDisposed;
|
||||
|
||||
/// <summary>Closes the device and disposes the instance.</summary>
|
||||
public void Dispose()
|
||||
{
|
||||
this.Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
private void Dispose(bool manual)
|
||||
{
|
||||
if (!this.IsDisposed)
|
||||
{
|
||||
if (this.Handle != IntPtr.Zero)
|
||||
{
|
||||
if (this._isrecording)
|
||||
this.Stop();
|
||||
|
||||
Alc.CaptureCloseDevice(this.Handle);
|
||||
}
|
||||
this.IsDisposed = true;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion Destructor
|
||||
SampleFrequency = frequency;
|
||||
}
|
||||
|
||||
#endregion Constructor
|
||||
|
||||
#region Public Members
|
||||
|
||||
#region CurrentDevice
|
||||
|
||||
private string device_name;
|
||||
|
||||
/// <summary>
|
||||
/// The name of the device associated with this instance.
|
||||
/// </summary>
|
||||
public string CurrentDevice
|
||||
{
|
||||
get
|
||||
{
|
||||
return device_name;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region AvailableDevices
|
||||
|
||||
/// <summary>
|
||||
/// Returns a list of strings containing all known recording devices.
|
||||
/// </summary>
|
||||
public static IList<string> AvailableDevices
|
||||
{
|
||||
get
|
||||
{
|
||||
return AudioDeviceEnumerator.AvailableRecordingDevices;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region DefaultDevice
|
||||
|
||||
/// <summary>
|
||||
/// Returns the name of the device that will be used as recording default.
|
||||
/// </summary>
|
||||
public static string DefaultDevice
|
||||
{
|
||||
get
|
||||
{
|
||||
return AudioDeviceEnumerator.DefaultRecordingDevice;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region CheckErrors
|
||||
|
||||
/// <summary>
|
||||
|
@ -195,70 +181,70 @@ namespace OpenTK.Audio
|
|||
public void CheckErrors()
|
||||
{
|
||||
new AudioDeviceErrorChecker(Handle).Dispose();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region CurrentError
|
||||
|
||||
/// <summary>Returns the ALC error code for this device.</summary>
|
||||
public AlcError CurrentError
|
||||
{
|
||||
get
|
||||
{
|
||||
return Alc.GetError(Handle);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Start & Stop
|
||||
|
||||
/// <summary>
|
||||
/// Start recording samples.
|
||||
/// The number of available samples can be obtained through the <see cref="AvailableSamples"/> property.
|
||||
/// The data can be queried with any <see cref="ReadSamples"/> method.
|
||||
/// </summary>
|
||||
public void Start()
|
||||
{
|
||||
Alc.CaptureStart(Handle);
|
||||
_isrecording = true;
|
||||
}
|
||||
|
||||
/// <summary>Stop recording samples. This will not clear previously recorded samples.</summary>
|
||||
public void Stop()
|
||||
{
|
||||
Alc.CaptureStop(Handle);
|
||||
_isrecording = false;
|
||||
}
|
||||
|
||||
/// <summary>Returns the ALC error code for this device.</summary>
|
||||
public AlcError CurrentError
|
||||
{
|
||||
get
|
||||
{
|
||||
return Alc.GetError(Handle);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Start & Stop
|
||||
|
||||
/// <summary>
|
||||
/// Start recording samples.
|
||||
/// The number of available samples can be obtained through the <see cref="AvailableSamples"/> property.
|
||||
/// The data can be queried with any <see cref="ReadSamples"/> method.
|
||||
/// </summary>
|
||||
public void Start()
|
||||
{
|
||||
Alc.CaptureStart(Handle);
|
||||
_isrecording = true;
|
||||
}
|
||||
|
||||
/// <summary>Stop recording samples. This will not clear previously recorded samples.</summary>
|
||||
public void Stop()
|
||||
{
|
||||
Alc.CaptureStop(Handle);
|
||||
_isrecording = false;
|
||||
}
|
||||
|
||||
#endregion Start & Stop Capture
|
||||
|
||||
#region AvailableSamples
|
||||
|
||||
/// <summary>Returns the number of available samples for capture.</summary>
|
||||
public int AvailableSamples
|
||||
{
|
||||
get
|
||||
{
|
||||
// TODO: Investigate inconsistency between documentation and actual usage.
|
||||
// Doc claims the 3rd param is Number-of-Bytes, but it appears to be Number-of-Int32s
|
||||
int result;
|
||||
Alc.GetInteger(Handle, AlcGetInteger.CaptureSamples, 1, out result);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Returns the number of available samples for capture.</summary>
|
||||
public int AvailableSamples
|
||||
{
|
||||
get
|
||||
{
|
||||
// TODO: Investigate inconsistency between documentation and actual usage.
|
||||
// Doc claims the 3rd param is Number-of-Bytes, but it appears to be Number-of-Int32s
|
||||
int result;
|
||||
Alc.GetInteger(Handle, AlcGetInteger.CaptureSamples, 1, out result);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion Available samples property
|
||||
|
||||
#region ReadSamples
|
||||
|
||||
/// <summary>Fills the specified buffer with samples from the internal capture ring-buffer. This method does not block: it is an error to specify a sampleCount larger than AvailableSamples.</summary>
|
||||
/// <summary>Fills the specified buffer with samples from the internal capture ring-buffer. This method does not block: it is an error to specify a sampleCount larger than AvailableSamples.</summary>
|
||||
/// <param name="buffer">A pointer to a previously initialized and pinned array.</param>
|
||||
/// <param name="sampleCount">The number of samples to be written to the buffer.</param>
|
||||
public void ReadSamples(IntPtr buffer, int sampleCount)
|
||||
public void ReadSamples(IntPtr buffer, int sampleCount)
|
||||
{
|
||||
Alc.CaptureSamples(Handle, buffer, sampleCount);
|
||||
Alc.CaptureSamples(Handle, buffer, sampleCount);
|
||||
}
|
||||
|
||||
/// <summary>Fills the specified buffer with samples from the internal capture ring-buffer. This method does not block: it is an error to specify a sampleCount larger than AvailableSamples.</summary>
|
||||
|
@ -284,8 +270,8 @@ namespace OpenTK.Audio
|
|||
GCHandle buffer_ptr = GCHandle.Alloc(buffer, GCHandleType.Pinned);
|
||||
try { ReadSamples(buffer_ptr.AddrOfPinnedObject(), sampleCount); }
|
||||
finally { buffer_ptr.Free(); }
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region SampleFormat & SampleFrequency
|
||||
|
@ -310,6 +296,18 @@ namespace OpenTK.Audio
|
|||
|
||||
#endregion
|
||||
|
||||
#region IsRunning
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether this instance is currently capturing samples.
|
||||
/// </summary>
|
||||
public bool IsRunning
|
||||
{
|
||||
get { return _isrecording; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private Members
|
||||
|
@ -332,7 +330,7 @@ namespace OpenTK.Audio
|
|||
case ALFormat.MultiQuad8Ext: return 4;
|
||||
case ALFormat.MultiQuad16Ext: return 8;
|
||||
case ALFormat.MultiQuad32Ext: return 16;
|
||||
|
||||
|
||||
case ALFormat.Multi51Chn8Ext: return 6;
|
||||
case ALFormat.Multi51Chn16Ext: return 12;
|
||||
case ALFormat.Multi51Chn32Ext: return 24;
|
||||
|
@ -375,5 +373,38 @@ namespace OpenTK.Audio
|
|||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
#region IDisposable Members
|
||||
|
||||
~AudioCapture()
|
||||
{
|
||||
Dispose();
|
||||
}
|
||||
|
||||
private bool IsDisposed;
|
||||
|
||||
/// <summary>Closes the device and disposes the instance.</summary>
|
||||
public void Dispose()
|
||||
{
|
||||
this.Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
private void Dispose(bool manual)
|
||||
{
|
||||
if (!this.IsDisposed)
|
||||
{
|
||||
if (this.Handle != IntPtr.Zero)
|
||||
{
|
||||
if (this._isrecording)
|
||||
this.Stop();
|
||||
|
||||
Alc.CaptureCloseDevice(this.Handle);
|
||||
}
|
||||
this.IsDisposed = true;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion Destructor
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,28 +1,28 @@
|
|||
#region License
|
||||
//
|
||||
// The Open Toolkit Library License
|
||||
//
|
||||
// Copyright (c) 2006 - 2009 the Open Toolkit library.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights to
|
||||
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
// the Software, and to permit persons to whom the Software is furnished to do
|
||||
// so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
// OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
#region License
|
||||
//
|
||||
// The Open Toolkit Library License
|
||||
//
|
||||
// Copyright (c) 2006 - 2009 the Open Toolkit library.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights to
|
||||
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
// the Software, and to permit persons to whom the Software is furnished to do
|
||||
// so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
// OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
|
|
Loading…
Reference in a new issue