diff --git a/CSCore.OSX.Test/CSCore.OSX.Test.csproj b/CSCore.OSX.Test/CSCore.OSX.Test.csproj new file mode 100644 index 00000000..4c5dd072 --- /dev/null +++ b/CSCore.OSX.Test/CSCore.OSX.Test.csproj @@ -0,0 +1,72 @@ + + + + Debug + AnyCPU + {F58C2874-D663-42BD-B406-3526F57868E7} + Library + CSCore.OSX.Test + CSCore.OSX.Test + v4.5 + + + true + full + false + bin\Debug + DEBUG; + prompt + 4 + false + + + full + true + bin\Release + prompt + 4 + false + + + + + ..\packages\NUnit.3.2.1\lib\net45\nunit.framework.dll + nunit + + + ..\CSCore.OSX\lib\MonoMac.dll + + + + + + + + Resources.resx + + + + + + + + + + {C3DCCFE3-DD3F-4EEE-849B-33E355B1E064} + CSCore + + + {BC09FBD9-AAEB-4A4F-965E-1EBE3E880141} + CSCore.OSX + + + + + test_120s_stereo.mp3 + + + ResXFileCodeGenerator + Resources.Designer.cs + + + \ No newline at end of file diff --git a/CSCore.OSX.Test/GlobalTestConfig.cs b/CSCore.OSX.Test/GlobalTestConfig.cs new file mode 100644 index 00000000..065af945 --- /dev/null +++ b/CSCore.OSX.Test/GlobalTestConfig.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using CSCore.Codecs; + +namespace CSCore.OSX.Test +{ + public static class GlobalTestConfig + { + //public const string TestMp3 = @"D:\Temp\test_120s_stereo.mp3"; + public const string _TestMp3 = @"D:\Temp\test_120s.mp3"; + public const string _TestWav2S = @"D:\Temp\test_2s.wav"; + + public static MemoryStream TestMp3AsStream() + { + return new MemoryStream(Properties.Resources.test_120s_stereo); + } + } +} diff --git a/CSCore.OSX.Test/OSXCoreAudio/OSXCoreAudioTests.cs b/CSCore.OSX.Test/OSXCoreAudio/OSXCoreAudioTests.cs new file mode 100644 index 00000000..64d25658 --- /dev/null +++ b/CSCore.OSX.Test/OSXCoreAudio/OSXCoreAudioTests.cs @@ -0,0 +1,34 @@ +using System; +using NUnit.Framework; +using System.IO; + +namespace CSCore.OSX.Test.OSXCoreAudio +{ + [TestFixture] + public class OSXCoreAudioTests + { + [Test] + public void CanCreateWavSourceFromURL() + { + + var filename = Path.ChangeExtension(Path.GetTempFileName(), "mp3"); + try + { + using (var stream = GlobalTestConfig.TestMp3AsStream()) + { + File.WriteAllBytes(filename, stream.ToArray()); + using (var waveSource = new CSCore.OSXCoreAudio.OSXAudioDecoder(filename)) + { + Assert.IsNotNull(waveSource); + Assert.IsTrue(waveSource.Length > 0); + } + } + } + finally + { + File.Delete(filename); + } + } + } +} + diff --git a/CSCore.OSX.Test/Properties/AssemblyInfo.cs b/CSCore.OSX.Test/Properties/AssemblyInfo.cs new file mode 100644 index 00000000..35e32396 --- /dev/null +++ b/CSCore.OSX.Test/Properties/AssemblyInfo.cs @@ -0,0 +1,27 @@ +using System.Reflection; +using System.Runtime.CompilerServices; + +// Information about this assembly is defined by the following attributes. +// Change them to the values specific to your project. + +[assembly: AssemblyTitle("CSCore.OSX.Test")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("")] +[assembly: AssemblyCopyright("patrickyates")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}". +// The form "{Major}.{Minor}.*" will automatically update the build and revision, +// and "{Major}.{Minor}.{Build}.*" will update just the revision. + +[assembly: AssemblyVersion("1.0.*")] + +// The following attributes are used to specify the signing key for the assembly, +// if desired. See the Mono documentation for more information about signing. + +//[assembly: AssemblyDelaySign(false)] +//[assembly: AssemblyKeyFile("")] + diff --git a/CSCore.OSX.Test/Properties/Resources.Designer.cs b/CSCore.OSX.Test/Properties/Resources.Designer.cs new file mode 100644 index 00000000..a0d75c5d --- /dev/null +++ b/CSCore.OSX.Test/Properties/Resources.Designer.cs @@ -0,0 +1,69 @@ +// ------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Mono Runtime Version: 4.0.30319.17020 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// ------------------------------------------------------------------------------ + +namespace CSCore.OSX.Test.Properties { + using System; + + + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + [System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static System.Resources.ResourceManager resourceMan; + + private static System.Globalization.CultureInfo resourceCulture; + + [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)] + internal static System.Resources.ResourceManager ResourceManager { + get { + if (object.Equals(null, resourceMan)) { + System.Resources.ResourceManager temp = new System.Resources.ResourceManager("CSCore.OSX.Test.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)] + internal static System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + internal static byte[] aiff_50s_sine { + get { + object obj = ResourceManager.GetObject("aiff_50s_sine", resourceCulture); + return ((byte[])(obj)); + } + } + + internal static byte[] test_120s_stereo { + get { + object obj = ResourceManager.GetObject("test_120s_stereo", resourceCulture); + return ((byte[])(obj)); + } + } + + internal static System.IO.UnmanagedMemoryStream test_2s { + get { + return ResourceManager.GetStream("test_2s", resourceCulture); + } + } + } +} diff --git a/CSCore.OSX.Test/Properties/Resources.resources b/CSCore.OSX.Test/Properties/Resources.resources new file mode 100644 index 00000000..289662fc Binary files /dev/null and b/CSCore.OSX.Test/Properties/Resources.resources differ diff --git a/CSCore.OSX.Test/Properties/Resources.resx b/CSCore.OSX.Test/Properties/Resources.resx new file mode 100644 index 00000000..06f100ad --- /dev/null +++ b/CSCore.OSX.Test/Properties/Resources.resx @@ -0,0 +1,130 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + ../../CSCore.Test/Resources/50s_sine.aiff;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + ../../CSCore.Test/Resources/test_120s_stereo.mp3;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + ../../CSCore.Test/Resources/test_2s.wav;System.IO.MemoryStream, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/CSCore.OSX.Test/packages.config b/CSCore.OSX.Test/packages.config new file mode 100644 index 00000000..1ff5a2d2 --- /dev/null +++ b/CSCore.OSX.Test/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/CSCore.OSX/CSCore.OSX.csproj b/CSCore.OSX/CSCore.OSX.csproj new file mode 100644 index 00000000..4bce999c --- /dev/null +++ b/CSCore.OSX/CSCore.OSX.csproj @@ -0,0 +1,88 @@ + + + + Debug + AnyCPU + {BC09FBD9-AAEB-4A4F-965E-1EBE3E880141} + Library + CSCore + CSCore.OSX + v4.5 + + + true + full + false + bin\Debug + DEBUG; + prompt + 4 + false + bin\Debug\CSCore.OSX.xml + true + + + true + bin\Release + prompt + 4 + false + bin\Release\CSCore.OSX.xml + true + + + OnOutputUpdated + + + + lib\MonoMac.dll + + + + + + + + + + + + + + + {C3DCCFE3-DD3F-4EEE-849B-33E355B1E064} + CSCore + + + + + + + + + + + + + + + + + $(SolutionDir)/packages/ILRepack.2.0.10/tools/ILRepack.exe /out:../merged-output/$(ConfigurationName)/$(TargetFileName) $(TargetPath) MonoMac.dll + copy "$(TargetDir)/CSCore.OSX.xml" "$(TargetDir)/../merged-output/$(ConfigurationName)/" + del /S /Q "$(TargetDir)/" + copy "$(TargetDir)..\merged-output\$(ConfigurationName)\*.*" "$(TargetDir)" + + + cd $(TargetDir) + monolinker -c skip -b true -l none -p link MonoMac -p skip CSCore -o ../linked-output/$(ConfigurationName) -a CSCore.OSX.dll + cd ../linked-output/$(ConfigurationName) + mono $(SolutionDir)/packages/ILRepack.2.0.10/tools/ILRepack.exe /out:../../merged-output/$(ConfigurationName)/$(TargetFileName) $(TargetFile) MonoMac.dll + cp $(TargetDir)/CSCore.OSX.xml $(TargetDir)/../merged-output/$(ConfigurationName)/ + rm -r $(TargetDir) + mkdir $(TargetDir) + cp $(TargetDir)/../merged-output/$(ConfigurationName)/$(TargetFileName) $(TargetDir) + cp $(TargetDir)/../merged-output/$(ConfigurationName)/CSCore.OSX.xml $(TargetDir) + + + diff --git a/CSCore.OSX/CSCore.OSX.nuspec b/CSCore.OSX/CSCore.OSX.nuspec new file mode 100644 index 00000000..ab3d5a16 --- /dev/null +++ b/CSCore.OSX/CSCore.OSX.nuspec @@ -0,0 +1,14 @@ + + + + $id$ + $version$ + $title$ + $author$ + $author$ + https://github.com/opcon/cscore + false + $description$ + Copyright 2016 + + \ No newline at end of file diff --git a/CSCore.OSX/Codecs/AAC/AACDecoderOSX.cs b/CSCore.OSX/Codecs/AAC/AACDecoderOSX.cs new file mode 100644 index 00000000..fe7012f0 --- /dev/null +++ b/CSCore.OSX/Codecs/AAC/AACDecoderOSX.cs @@ -0,0 +1,48 @@ +using System; +using System.IO; +using CSCore.OSXCoreAudio; +using MonoMac.AudioToolbox; +namespace CSCore.Codecs.AAC +{ + /// + /// Core Audio AAC decoder + /// + public class AACDecoderOSX : OSXAudioDecoder + { + private static bool? _issupported; + + /// + /// Gets a value which indicates whether the CoreAudio AAC decoder is supported on the current platform. + /// + public static bool IsSupported + { + get + { + if (_issupported == null) + { + _issupported = OSXAudio.IsSupported; + } + return _issupported.Value; + } + } + + /// + /// Initializes a new instance of the class. + /// + /// Url which points to a data source which provides AAC data. This is typically a filename. + public AACDecoderOSX(string url) + : base(url) + { + } + + /// + /// Initializes a new instance of the class. + /// + /// Stream which contains AAC data. + public AACDecoderOSX(Stream stream) + : base(stream, AudioFileType.AAC_ADTS) + { + } + } +} + diff --git a/CSCore.OSX/Codecs/MP3/MP3DecoderOSX.cs b/CSCore.OSX/Codecs/MP3/MP3DecoderOSX.cs new file mode 100644 index 00000000..759290c3 --- /dev/null +++ b/CSCore.OSX/Codecs/MP3/MP3DecoderOSX.cs @@ -0,0 +1,48 @@ +using System; +using System.IO; +using CSCore.OSXCoreAudio; +using MonoMac.AudioToolbox; +namespace CSCore.Codecs.MP3 +{ + /// + /// Core Audio MP3 Decoder + /// + public class MP3DecoderOSX : OSXAudioDecoder + { + private static bool? _issupported; + + /// + /// Gets a value which indicates whether the CoreAudio MP3 decoder is supported on the current platform. + /// + public static bool IsSupported + { + get + { + if (_issupported == null) + { + _issupported = OSXAudio.IsSupported; + } + return _issupported.Value; + } + } + + /// + /// Initializes a new instance of the class. + /// + /// Url which points to a data source which provides MP3 data. This is typically a filename. + public MP3DecoderOSX(string url) + : base(url) + { + } + + /// + /// Initializes a new instance of the class. + /// + /// Stream which contains MP3 data. + public MP3DecoderOSX(Stream stream) + : base(stream, AudioFileType.MP3) + { + } + } +} + diff --git a/CSCore.OSX/OSXCoreAudio/AudioStreamSource.cs b/CSCore.OSX/OSXCoreAudio/AudioStreamSource.cs new file mode 100644 index 00000000..7aadc802 --- /dev/null +++ b/CSCore.OSX/OSXCoreAudio/AudioStreamSource.cs @@ -0,0 +1,130 @@ +using System; +using System.IO; +using System.Runtime.InteropServices; +using MonoMac.AudioToolbox; + +namespace CSCore.OSXCoreAudio +{ + /// + /// An class derived from that supports reading from streams. + /// Can be wrapped by an ExtFileAudio object + /// + public class AudioStreamSource : AudioSource + { + private Stream _audioStream; + private bool _disposed = false; + + /// + /// The underlying audio stream + /// + /// The audio stream. + public Stream AudioStream {get {return _audioStream;}} + + //begin with 8kb buffer + private byte[] _byteBuffer = new byte[8 * 1024]; + + /// + /// Initializes a new instance of the class. + /// + /// The underlying stream. Note this cannot be a network stream - must be either Memory or File + /// The codec of the audio stream. + public AudioStreamSource(Stream stream, AudioFileType fileType) : base() + { + if (stream == null) + throw new ArgumentNullException(nameof(stream)); + if (!stream.CanRead) + throw new ArgumentException("Stream is not readable.", nameof(stream)); + if (!(stream is FileStream) && !(stream is MemoryStream)) + throw new ArgumentException("Stream must be either filestream or memorystream", nameof(stream)); + + _audioStream = stream; + + Open(fileType); + } + + /// + /// Gets or sets the size (length) of the stream in bytes + /// + /// The size (length) of the stream in bytes + public override long Size + { + get + { + return _disposed ? 0 : _audioStream.Length; + } + + set + { + if (!_disposed) + _audioStream.SetLength(value); + } + } + + /// + /// Callback used by to read data from the stream + /// + /// The position to read from in the stream + /// The requested number of bytes to read from the stream + /// The buffer to read the data into + /// The actual number of bytes read into the buffer + public override bool Read(long position, int requestCount, IntPtr buffer, out int actualCount) + { + try + { + //casting is okay here since value is always ≤ requestCount (an int) + actualCount = (int)Math.Min(_audioStream.Length - position, requestCount); + + //seek to the correct position in the stream + _audioStream.Position = position; + + if (_audioStream.Position != position) + throw new Exception("Seeking to new position in AudioStreamSource failed!"); + + //automatically grow byte buffer if it's not large enough + //hopefully don't have to worry about it getting too large + if (_byteBuffer.Length < actualCount) _byteBuffer = new byte[actualCount]; + + //read data from the stream into the temporary byte array + actualCount = _audioStream.Read(_byteBuffer, 0, actualCount); + + //copy data from the temporary byte array into the native buffer + Marshal.Copy(_byteBuffer, 0, buffer, actualCount); + + return true; + } + catch + { + actualCount = 0; + return false; + } + } + + /// + /// NOT SUPPORTED + /// + public override bool Write(long position, int requestCount, IntPtr buffer, out int actualCount) + { + throw new NotSupportedException(); + } + + /// + /// Disposes the audio stream and parent AudioSource + /// + /// Indicates that we are manually diposing underlying AudioSource + protected override void Dispose(bool disposing) + { + if (_audioStream != null) + { + _audioStream.Dispose(); + _audioStream = null; + } + _disposed = true; + try + { + base.Dispose(disposing); + } + catch {} + } + } +} + diff --git a/CSCore.OSX/OSXCoreAudio/OSXAudio.cs b/CSCore.OSX/OSXCoreAudio/OSXAudio.cs new file mode 100644 index 00000000..9995ec4c --- /dev/null +++ b/CSCore.OSX/OSXCoreAudio/OSXAudio.cs @@ -0,0 +1,53 @@ +using System; +using CSCore.Codecs; +using CSCore.Codecs.AAC; +using CSCore.Codecs.MP3; + +namespace CSCore.OSXCoreAudio +{ + /// + /// Utility class for the Core Audio APIs on OSX + /// + public static class OSXAudio + { + /// + /// Gets whether the Core Audio APIs are supported - currently just checks we are running on MacOSX + /// + /// Whether Core Audio is supported + public static bool IsSupported { get { return Utils.PlatformDetection.RunningPlatform() == Utils.Platform.MacOSX;}} + + /// + /// Register the OSX Core Audio codecs to the default factory + /// Note that the default action for urls will require downloading the entire stream into a memory stream first + /// + /// The codecs. + public static void RegisterCodecs() + { + RegisterCodecs(CodecFactory.Instance); + } + + /// + /// Register the OSX Core Audio codecs + /// Note that the default action for urls will require downloading the entire stream into a memory stream first + /// + /// The factory to register codecs to + public static void RegisterCodecs(CodecFactory factory) + { + if (!IsSupported) return; + + // Register MP3 + factory.Register("mp3", new CodecFactoryEntry(s => new MP3DecoderOSX(s),"mp3", "mpeg3")); + + // Register AAC + factory.Register("aac", new CodecFactoryEntry(s => new AACDecoderOSX(s), "aac", "mp4", "m4a")); + + // Register default codec + factory.RegisterDefaultCodec((url, isWebURL) => + { + if (isWebURL) return new OSXAudioDecoder(new Uri(url)); + return new OSXAudioDecoder(url); + }); + } + } +} + diff --git a/CSCore.OSX/OSXCoreAudio/OSXAudioDecoder.cs b/CSCore.OSX/OSXCoreAudio/OSXAudioDecoder.cs new file mode 100644 index 00000000..c7e4a1f4 --- /dev/null +++ b/CSCore.OSX/OSXCoreAudio/OSXAudioDecoder.cs @@ -0,0 +1,417 @@ +using System; +using System.Runtime.InteropServices; +using MonoMac.AudioToolbox; +using MonoMac.AudioUnit; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Net; + + +namespace CSCore.OSXCoreAudio +{ + /// + /// The is a generic decoder for all formats + /// supported by the CoreAudio API on OSX + /// + public class OSXAudioDecoder : IWaveSource + { + private WaveFormat _waveFormat; + + private ExtAudioFile _audioFileReader; + private AudioStreamSource _audioStreamSource; + private AudioBuffers _fillBuffers; + private IntPtr _audioBufferMemory; + private AudioStreamBasicDescription _destinationFormat; + private AudioStreamBasicDescription _clientFormat; + private AudioStreamBasicDescription _inputFormat; + + private int _headerFrames = 0; + private int _bufferSize; + private long _position; + private long _totalFrameCount; + + private bool _disposed = false; + private object _lockObj = new object(); + + /// + /// Initializes a new instance of the class. + /// + /// url which points to an audio source which can be decoded. + public OSXAudioDecoder(string url) + { + if (String.IsNullOrEmpty(url)) + throw new ArgumentNullException(nameof(url)); + + _audioFileReader = Initialize(url); + + //Seek to position 0, which will skip over all header frames if they exist, + //to the first sample of audio + SetPosition(0); + } + + /// + /// Initializes a new instance of the class. + /// Note that this constructor downloads the entire stream from the URI into a memory stream + /// This is needed for the Core Audio decoder + /// + /// URI which points to an audio source which can be decoded. + /// The filetype of the audio source + public OSXAudioDecoder(Uri uri, AudioFileType fileType = AudioFileType.MP3) + { + if (String.IsNullOrEmpty(uri.AbsolutePath)) + throw new ArgumentNullException(nameof(uri)); + + //get the stream + + MemoryStream memoryStream = new MemoryStream(); + WebRequest req = WebRequest.Create(uri); + + using (Stream rStream = req.GetResponse().GetResponseStream()) + { + rStream.CopyTo(memoryStream); + } + + _audioFileReader = Initialize(memoryStream, fileType); + + //Seek to position 0, which will skip over all header frames if they exist, + //to the first sample of audio + SetPosition(0); + } + + /// + /// Initializes a new instance of the class. + /// + /// Stream which provides the audio data to decode. + /// The filetype of the stream. Defaults to MP3 + public OSXAudioDecoder(Stream stream, AudioFileType fileType = AudioFileType.MP3) + { + if (stream == null) + throw new ArgumentNullException(nameof(stream)); + if (!stream.CanRead) + throw new ArgumentException("Stream is not readable.", nameof(stream)); + + _audioFileReader = Initialize(stream, fileType); + + //Seek to position 0, which will skip over all header frames if they exist, + //to the first sample of audio + SetPosition(0); + } + + /// + /// Reads a sequence of bytes from the and advances the position + /// within the stream by the number of bytes read + /// + /// + /// An array of bytes. When this method resturns, the contains the specified + /// byte array with the values between and ( + - 1) + /// replaced by the bytes read from the current source. + /// + /// + /// The zero-based byte offset in the at which to begin storing + /// the data read from the current stream. + /// + /// The maximum number of bytes to read from the current source. + /// The total number of bytes read into the buffer. + public int Read(byte[] buffer, int offset, int count) + { + CheckForDisposed(); + + if (buffer == null) + throw new ArgumentNullException("buffer"); + if (buffer.Length < count) + throw new ArgumentException("Length is too small.", "buffer"); + + lock (_lockObj) + { + int read = 0; + if (_audioFileReader == null || _disposed) + return read; + + //align count to block boundary + count -= count % _waveFormat.BlockAlign; + + while (read < count) + { + //get how much we are reading - clamp to maximum buffer size - possibly not needed? + int bytesToRead = Math.Min(count - read, _bufferSize); + int framesToRead = bytesToRead / _clientFormat.BytesPerFrame; // we shouldn't have to do any error checking on this division + + ExtAudioFileError status; + + // we cast to/from uint here because the coreaudio api requires it + // this shouldn't be an issue, because framesToRead is an int, so + // actualFramesRead should be less than max(int) + int actualFramesRead = (int)_audioFileReader.Read((uint)framesToRead, _fillBuffers, out status); + + //Write method status to debug + Debug.WriteLine(status.ToString()); + + //break if we read no frames (reached end of file or something) + if (actualFramesRead == 0) + break; + + //Convert frames read to bytes read + int actualBytesRead = actualFramesRead * _clientFormat.BytesPerFrame; + + //copy the bytes read from audiobuffer to destination buffer + Marshal.Copy(_audioBufferMemory, buffer, offset + read, actualBytesRead); + + //update read count + read += actualBytesRead; + } + + //don't forget to update position + //position is in frames(!!), not bytes + _position += read / _clientFormat.BytesPerFrame; + + return read; + } + } + + private ExtAudioFile Initialize(Stream stream, AudioFileType fileType) + { + //Load audio stream source (child of AudioFile) + _audioStreamSource = new AudioStreamSource(stream, fileType); + + //Wrap AudioStreamSource in extAudioFile object + ExtAudioFile extAudioFile; + ExtAudioFile.WrapAudioFileID(_audioStreamSource.Handle, false, out extAudioFile); + + //Initialize + return Initialize(extAudioFile); + } + + private ExtAudioFile Initialize(string url) + { + //Load the audio file + ExtAudioFile extAudioFile = ExtAudioFile.OpenUrl(MonoMac.CoreFoundation.CFUrl.FromFile(url)); + + //Initialize + return Initialize(extAudioFile); + + } + + ExtAudioFile Initialize(ExtAudioFile extAudioFile) + { + try + { + //This is the file input format + _inputFormat = extAudioFile.FileDataFormat; + + //Create the destination format - use WAV LPCM, 2 channels, input sample rate + _destinationFormat = AudioStreamBasicDescription.CreateLinearPCM(sampleRate: _inputFormat.SampleRate); + + //Unset the integer flag and set the float flag + //Integer flag is set from the constructor above + _destinationFormat.FormatFlags |= AudioFormatFlags.IsFloat; + if (_destinationFormat.FormatFlags.HasFlag(AudioFormatFlags.IsSignedInteger)) + _destinationFormat.FormatFlags |= AudioFormatFlags.IsSignedInteger; + + //Create the client format (what audio is converted too) + //Want 32bit float + _clientFormat = _destinationFormat; + _clientFormat.ChannelsPerFrame = 2; + _clientFormat.BytesPerFrame = sizeof(float) * _clientFormat.ChannelsPerFrame; + _clientFormat.BitsPerChannel = sizeof(float) * 8; + _clientFormat.FramesPerPacket = 1; + _clientFormat.BytesPerPacket = _clientFormat.BytesPerFrame * _clientFormat.FramesPerPacket; + _clientFormat.Reserved = 0; + + //Set the client data format + extAudioFile.ClientDataFormat = _clientFormat; + + //Set the wave format + _waveFormat = new WaveFormat((int)_clientFormat.SampleRate, _clientFormat.BitsPerChannel, _clientFormat.ChannelsPerFrame, AudioEncoding.IeeeFloat); + + //Get the total length in frames of the audio file + _totalFrameCount = extAudioFile.FileLengthFrames; + + // + // WORKAROUND for a bug in ExtFileAudio + // Taken from https://github.com/asantoni/libaudiodecoder/blob/master/src/audiodecodercoreaudio.cpp + // + // Not sure if this is still needed? + // + + AudioConverter ac = extAudioFile.AudioConverter; + + //throws an argument exception if this does not exist + //will only exist if we are decompressing + try + { + AudioConverterPrimeInfo primeInfo = ac.PrimeInfo; + _headerFrames = ac.PrimeInfo.LeadingFrames; + } + catch (ArgumentException) + { + } + + Debug.WriteLine("Initial audio file position is: " + extAudioFile.FileTell()); + Debug.WriteLine("Header frames are: " + _headerFrames); + + + //create audio buffers + _fillBuffers = new AudioBuffers(1); + + const int averageFramesRead = 2048; + _bufferSize = averageFramesRead * _clientFormat.BytesPerFrame; + _audioBufferMemory = Marshal.AllocHGlobal(_bufferSize); + + _fillBuffers.SetData(0, _audioBufferMemory, _bufferSize); + + //We can't just set this directly, because of .net property quirks + AudioBuffer buf = _fillBuffers[0]; + buf.NumberChannels = _clientFormat.ChannelsPerFrame; + _fillBuffers[0] = buf; + + return extAudioFile; + } + catch (Exception) + { + DisposeInternal(); + + throw; + } + } + + /// + /// Gets a value which indicates whether the seeking is supported. True means that seeking is supported. + /// False means that seeking is not supported. + /// Currently always returns true, because CoreAudio can always seek (?). Need to double check this is correct. + /// + public bool CanSeek + { + get + { + //CoreAudio can always seek? + return true; + } + } + + /// + /// Gets the format of the decoded audio data provided by the method. + /// + public WaveFormat WaveFormat + { + get { return _waveFormat; } + } + + /// + /// Gets or sets the position of the output stream, in bytes. + /// + public long Position + { + get { return !_disposed ? _position*_clientFormat.BytesPerFrame : 0; } + set + { + CheckForDisposed(); + SetPosition(value); + } + } + + /// + /// Disposes the . + /// + public void Dispose() + { + if (!_disposed) + { + _disposed = true; + + Dispose(true); + GC.SuppressFinalize(this); + } + } + + private void SetPosition(long position) + { + if (CanSeek) + { + lock (_lockObj) + { + position -= position % _waveFormat.BlockAlign; + + //need seek position in frames + long seek = position / _clientFormat.BytesPerFrame; // shouldn't need to do any error checking on this division + + _audioFileReader.Seek(seek+_headerFrames); + var new_pos = _audioFileReader.FileTell(); + if (new_pos + _headerFrames != seek) + throw new Exception("Setting OSXAudioDecoder position failed!"); + + _position = seek; + } + } + } + + /// + /// Gets the total length of the decoded audio, in bytes. + /// + public long Length + { + get + { + if (_disposed) + return 0; + return _totalFrameCount * _clientFormat.BytesPerFrame; + } + } + + private void CheckForDisposed() + { + if (_disposed) + throw new ObjectDisposedException(GetType().Name); + } + + + /// + /// Disposes the and its internal resources. + /// + /// + /// True to release both managed and unmanaged resources; + /// false to release only managed resources. + /// + protected virtual void Dispose(bool disposing) + { + lock (_lockObj) + { + DisposeInternal(); + } + } + + private void DisposeInternal() + { + if (_audioFileReader != null) + { + _audioFileReader.Dispose(); + _audioFileReader = null; + } + if (_audioStreamSource != null) + { + if (_audioStreamSource.AudioStream != null) + _audioStreamSource.AudioStream.Dispose(); + _audioStreamSource = null; + } + if (_fillBuffers != null) + { + for (int i = 0; i < _fillBuffers.Count; i++) + { + AudioBuffer buf = _fillBuffers[i]; + Marshal.FreeHGlobal(buf.Data); + } + _fillBuffers.Dispose(); + _fillBuffers = null; + } + } + + /// + /// Finalizes an instance of the class. + /// + ~OSXAudioDecoder() + { + Dispose(false); + } + } +} + diff --git a/CSCore.OSX/Properties/AssemblyInfo.cs b/CSCore.OSX/Properties/AssemblyInfo.cs new file mode 100644 index 00000000..43fce7b8 --- /dev/null +++ b/CSCore.OSX/Properties/AssemblyInfo.cs @@ -0,0 +1,27 @@ +using System.Reflection; +using System.Runtime.CompilerServices; + +// Information about this assembly is defined by the following attributes. +// Change them to the values specific to your project. + +[assembly: AssemblyTitle("CSCore.OSX")] +[assembly: AssemblyDescription(".NET Sound Library")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("CSCore")] +[assembly: AssemblyProduct("CSCore")] +[assembly: AssemblyCopyright("Patrick Y. and Florian R.")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}". +// The form "{Major}.{Minor}.*" will automatically update the build and revision, +// and "{Major}.{Minor}.{Build}.*" will update just the revision. + +[assembly: AssemblyVersion("1.1.*")] + +// The following attributes are used to specify the signing key for the assembly, +// if desired. See the Mono documentation for more information about signing. + +//[assembly: AssemblyDelaySign(false)] +//[assembly: AssemblyKeyFile("")] + diff --git a/CSCore.OSX/lib/MonoMac.dll b/CSCore.OSX/lib/MonoMac.dll new file mode 100644 index 00000000..a34555d7 Binary files /dev/null and b/CSCore.OSX/lib/MonoMac.dll differ diff --git a/CSCore.OSX/packages.config b/CSCore.OSX/packages.config new file mode 100644 index 00000000..1644f20c --- /dev/null +++ b/CSCore.OSX/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/CSCore.sln b/CSCore.sln index 3b9a7cd9..bdda2a59 100644 --- a/CSCore.sln +++ b/CSCore.sln @@ -15,14 +15,14 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tools", "Tools", "{1F24CB15 EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CSCli", "Tools\CSCli\CSCli.csproj", "{9C5B4994-70C3-489D-933C-E2049C0505DB}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "InlineILCompiler", "Tools\InlineILCompiler\InlineILCompiler\InlineILCompiler.csproj", "{9522588A-5311-41F1-814C-4FB626FC0B47}" +EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Samples", "Samples", "{41D1D336-13B2-488B-8A85-C0F744035F8B}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Recorder", "Samples\Recorder\Recorder.csproj", "{637070BF-4FD2-4DF9-838F-1C42E7BDAE74}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EqualizerTest", "Samples\Equalizer\EqualizerTest.csproj", "{84AA94EB-9DAB-4255-A16E-8A8BA7DFB913}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "InlineILCompiler", "Tools\InlineILCompiler\InlineILCompiler\InlineILCompiler.csproj", "{9522588A-5311-41F1-814C-4FB626FC0B47}" -EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "X3DAudioSample", "Samples\X3DAudioSample\X3DAudioSample.csproj", "{2CE65814-8EF5-4133-822B-3B7177A4E292}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "XAudio2Playback", "Samples\XAudio2Playback\XAudio2Playback.csproj", "{C6F0D42E-A5D4-4A7B-AD77-91A84449DE04}" @@ -45,10 +45,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CSCoreWaveform", "Samples\C EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BiQuadFilterSample", "Samples\BiQuadFilterSample\BiQuadFilterSample.csproj", "{F8733117-DA1D-40DC-AEF8-98051B86E219}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CSCore.Ffmpeg", "CSCore.Ffmpeg\CSCore.Ffmpeg.csproj", "{F4E6168A-B2CB-413C-AE0E-0D8B856B425E}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FfmpegSample", "Samples\FfmpegSample\FfmpegSample.csproj", "{3CC0E6B1-1E96-4A07-8AE7-A7C7F47911B1}" -EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RecordWithSpecificFormat", "Samples\RecordWithSpecificFormat\RecordWithSpecificFormat.csproj", "{E0198A08-AAA8-4A76-B096-BBE72DA4F93B}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ConvertWavToMp3", "Samples\ConvertWavToMp3\ConvertWavToMp3.csproj", "{9CF28420-D689-46E6-B659-72520A515372}" @@ -57,6 +53,14 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PlayInputDeviceSample", "Sa EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EndpointAudioMeterSample", "Samples\EndpointAudioMeterSample\EndpointAudioMeterSample.csproj", "{2EDF3192-9107-4B7A-914A-EA25AFEB9F85}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FfmpegSample", "Samples\FfmpegSample\FfmpegSample.csproj", "{3CC0E6B1-1E96-4A07-8AE7-A7C7F47911B1}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CSCore.Ffmpeg", "CSCore.Ffmpeg\CSCore.Ffmpeg.csproj", "{F4E6168A-B2CB-413C-AE0E-0D8B856B425E}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CSCore.OSX", "CSCore.OSX\CSCore.OSX.csproj", "{BC09FBD9-AAEB-4A4F-965E-1EBE3E880141}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CSCore.OSX.Test", "CSCore.OSX.Test\CSCore.OSX.Test.csproj", "{F58C2874-D663-42BD-B406-3526F57868E7}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -67,36 +71,86 @@ Global Release|Win32 = Release|Win32 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {C3DCCFE3-DD3F-4EEE-849B-33E355B1E064}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {C3DCCFE3-DD3F-4EEE-849B-33E355B1E064}.Debug|Any CPU.Build.0 = Debug|Any CPU - {C3DCCFE3-DD3F-4EEE-849B-33E355B1E064}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {C3DCCFE3-DD3F-4EEE-849B-33E355B1E064}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {C3DCCFE3-DD3F-4EEE-849B-33E355B1E064}.Debug|Win32.ActiveCfg = Debug|Any CPU - {C3DCCFE3-DD3F-4EEE-849B-33E355B1E064}.Release|Any CPU.ActiveCfg = Release|Any CPU - {C3DCCFE3-DD3F-4EEE-849B-33E355B1E064}.Release|Any CPU.Build.0 = Release|Any CPU - {C3DCCFE3-DD3F-4EEE-849B-33E355B1E064}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {C3DCCFE3-DD3F-4EEE-849B-33E355B1E064}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {C3DCCFE3-DD3F-4EEE-849B-33E355B1E064}.Release|Win32.ActiveCfg = Release|Any CPU - {A4816166-67F7-42FF-B199-2758574312B2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {A4816166-67F7-42FF-B199-2758574312B2}.Debug|Any CPU.Build.0 = Debug|Any CPU - {A4816166-67F7-42FF-B199-2758574312B2}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {A4816166-67F7-42FF-B199-2758574312B2}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {A4816166-67F7-42FF-B199-2758574312B2}.Debug|Win32.ActiveCfg = Debug|Any CPU - {A4816166-67F7-42FF-B199-2758574312B2}.Release|Any CPU.ActiveCfg = Release|Any CPU - {A4816166-67F7-42FF-B199-2758574312B2}.Release|Any CPU.Build.0 = Release|Any CPU - {A4816166-67F7-42FF-B199-2758574312B2}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {A4816166-67F7-42FF-B199-2758574312B2}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {A4816166-67F7-42FF-B199-2758574312B2}.Release|Win32.ActiveCfg = Release|Any CPU - {9C5B4994-70C3-489D-933C-E2049C0505DB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {9C5B4994-70C3-489D-933C-E2049C0505DB}.Debug|Any CPU.Build.0 = Debug|Any CPU - {9C5B4994-70C3-489D-933C-E2049C0505DB}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {9C5B4994-70C3-489D-933C-E2049C0505DB}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {9C5B4994-70C3-489D-933C-E2049C0505DB}.Debug|Win32.ActiveCfg = Debug|Any CPU - {9C5B4994-70C3-489D-933C-E2049C0505DB}.Release|Any CPU.ActiveCfg = Release|Any CPU - {9C5B4994-70C3-489D-933C-E2049C0505DB}.Release|Any CPU.Build.0 = Release|Any CPU - {9C5B4994-70C3-489D-933C-E2049C0505DB}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {9C5B4994-70C3-489D-933C-E2049C0505DB}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {9C5B4994-70C3-489D-933C-E2049C0505DB}.Release|Win32.ActiveCfg = Release|Any CPU + {000B0B0B-A12D-4EED-A261-7F95422E386A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {000B0B0B-A12D-4EED-A261-7F95422E386A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {000B0B0B-A12D-4EED-A261-7F95422E386A}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {000B0B0B-A12D-4EED-A261-7F95422E386A}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {000B0B0B-A12D-4EED-A261-7F95422E386A}.Debug|Win32.ActiveCfg = Debug|Any CPU + {000B0B0B-A12D-4EED-A261-7F95422E386A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {000B0B0B-A12D-4EED-A261-7F95422E386A}.Release|Any CPU.Build.0 = Release|Any CPU + {000B0B0B-A12D-4EED-A261-7F95422E386A}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {000B0B0B-A12D-4EED-A261-7F95422E386A}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {000B0B0B-A12D-4EED-A261-7F95422E386A}.Release|Win32.ActiveCfg = Release|Any CPU + {0027D5BC-DF90-4EE4-B07E-4192A183AC38}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0027D5BC-DF90-4EE4-B07E-4192A183AC38}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0027D5BC-DF90-4EE4-B07E-4192A183AC38}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {0027D5BC-DF90-4EE4-B07E-4192A183AC38}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {0027D5BC-DF90-4EE4-B07E-4192A183AC38}.Debug|Win32.ActiveCfg = Debug|Any CPU + {0027D5BC-DF90-4EE4-B07E-4192A183AC38}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0027D5BC-DF90-4EE4-B07E-4192A183AC38}.Release|Any CPU.Build.0 = Release|Any CPU + {0027D5BC-DF90-4EE4-B07E-4192A183AC38}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {0027D5BC-DF90-4EE4-B07E-4192A183AC38}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {0027D5BC-DF90-4EE4-B07E-4192A183AC38}.Release|Win32.ActiveCfg = Release|Any CPU + {237BD115-097E-4EB9-B447-8299F2EA5C7D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {237BD115-097E-4EB9-B447-8299F2EA5C7D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {237BD115-097E-4EB9-B447-8299F2EA5C7D}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {237BD115-097E-4EB9-B447-8299F2EA5C7D}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {237BD115-097E-4EB9-B447-8299F2EA5C7D}.Debug|Win32.ActiveCfg = Debug|Any CPU + {237BD115-097E-4EB9-B447-8299F2EA5C7D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {237BD115-097E-4EB9-B447-8299F2EA5C7D}.Release|Any CPU.Build.0 = Release|Any CPU + {237BD115-097E-4EB9-B447-8299F2EA5C7D}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {237BD115-097E-4EB9-B447-8299F2EA5C7D}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {237BD115-097E-4EB9-B447-8299F2EA5C7D}.Release|Win32.ActiveCfg = Release|Any CPU + {2CE65814-8EF5-4133-822B-3B7177A4E292}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2CE65814-8EF5-4133-822B-3B7177A4E292}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2CE65814-8EF5-4133-822B-3B7177A4E292}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {2CE65814-8EF5-4133-822B-3B7177A4E292}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {2CE65814-8EF5-4133-822B-3B7177A4E292}.Debug|Win32.ActiveCfg = Debug|Any CPU + {2CE65814-8EF5-4133-822B-3B7177A4E292}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2CE65814-8EF5-4133-822B-3B7177A4E292}.Release|Any CPU.Build.0 = Release|Any CPU + {2CE65814-8EF5-4133-822B-3B7177A4E292}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {2CE65814-8EF5-4133-822B-3B7177A4E292}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {2CE65814-8EF5-4133-822B-3B7177A4E292}.Release|Win32.ActiveCfg = Release|Any CPU + {2EDF3192-9107-4B7A-914A-EA25AFEB9F85}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2EDF3192-9107-4B7A-914A-EA25AFEB9F85}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2EDF3192-9107-4B7A-914A-EA25AFEB9F85}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {2EDF3192-9107-4B7A-914A-EA25AFEB9F85}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {2EDF3192-9107-4B7A-914A-EA25AFEB9F85}.Debug|Win32.ActiveCfg = Debug|Any CPU + {2EDF3192-9107-4B7A-914A-EA25AFEB9F85}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2EDF3192-9107-4B7A-914A-EA25AFEB9F85}.Release|Any CPU.Build.0 = Release|Any CPU + {2EDF3192-9107-4B7A-914A-EA25AFEB9F85}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {2EDF3192-9107-4B7A-914A-EA25AFEB9F85}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {2EDF3192-9107-4B7A-914A-EA25AFEB9F85}.Release|Win32.ActiveCfg = Release|Any CPU + {3CC0E6B1-1E96-4A07-8AE7-A7C7F47911B1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3CC0E6B1-1E96-4A07-8AE7-A7C7F47911B1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3CC0E6B1-1E96-4A07-8AE7-A7C7F47911B1}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {3CC0E6B1-1E96-4A07-8AE7-A7C7F47911B1}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {3CC0E6B1-1E96-4A07-8AE7-A7C7F47911B1}.Debug|Win32.ActiveCfg = Debug|Any CPU + {3CC0E6B1-1E96-4A07-8AE7-A7C7F47911B1}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3CC0E6B1-1E96-4A07-8AE7-A7C7F47911B1}.Release|Any CPU.Build.0 = Release|Any CPU + {3CC0E6B1-1E96-4A07-8AE7-A7C7F47911B1}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {3CC0E6B1-1E96-4A07-8AE7-A7C7F47911B1}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {3CC0E6B1-1E96-4A07-8AE7-A7C7F47911B1}.Release|Win32.ActiveCfg = Release|Any CPU + {529DEB01-14A3-4FEC-AD89-6D4D0DC433C3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {529DEB01-14A3-4FEC-AD89-6D4D0DC433C3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {529DEB01-14A3-4FEC-AD89-6D4D0DC433C3}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {529DEB01-14A3-4FEC-AD89-6D4D0DC433C3}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {529DEB01-14A3-4FEC-AD89-6D4D0DC433C3}.Debug|Win32.ActiveCfg = Debug|Any CPU + {529DEB01-14A3-4FEC-AD89-6D4D0DC433C3}.Release|Any CPU.ActiveCfg = Release|Any CPU + {529DEB01-14A3-4FEC-AD89-6D4D0DC433C3}.Release|Any CPU.Build.0 = Release|Any CPU + {529DEB01-14A3-4FEC-AD89-6D4D0DC433C3}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {529DEB01-14A3-4FEC-AD89-6D4D0DC433C3}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {529DEB01-14A3-4FEC-AD89-6D4D0DC433C3}.Release|Win32.ActiveCfg = Release|Any CPU + {571AC77A-7D3D-44CF-B0E7-08DF03D7B638}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {571AC77A-7D3D-44CF-B0E7-08DF03D7B638}.Debug|Any CPU.Build.0 = Debug|Any CPU + {571AC77A-7D3D-44CF-B0E7-08DF03D7B638}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {571AC77A-7D3D-44CF-B0E7-08DF03D7B638}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {571AC77A-7D3D-44CF-B0E7-08DF03D7B638}.Debug|Win32.ActiveCfg = Debug|Any CPU + {571AC77A-7D3D-44CF-B0E7-08DF03D7B638}.Release|Any CPU.ActiveCfg = Release|Any CPU + {571AC77A-7D3D-44CF-B0E7-08DF03D7B638}.Release|Any CPU.Build.0 = Release|Any CPU + {571AC77A-7D3D-44CF-B0E7-08DF03D7B638}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {571AC77A-7D3D-44CF-B0E7-08DF03D7B638}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {571AC77A-7D3D-44CF-B0E7-08DF03D7B638}.Release|Win32.ActiveCfg = Release|Any CPU {637070BF-4FD2-4DF9-838F-1C42E7BDAE74}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {637070BF-4FD2-4DF9-838F-1C42E7BDAE74}.Debug|Any CPU.Build.0 = Debug|Any CPU {637070BF-4FD2-4DF9-838F-1C42E7BDAE74}.Debug|Mixed Platforms.ActiveCfg = Debug|x86 @@ -109,6 +163,26 @@ Global {637070BF-4FD2-4DF9-838F-1C42E7BDAE74}.Release|Mixed Platforms.Build.0 = Release|x86 {637070BF-4FD2-4DF9-838F-1C42E7BDAE74}.Release|Win32.ActiveCfg = Release|x86 {637070BF-4FD2-4DF9-838F-1C42E7BDAE74}.Release|Win32.Build.0 = Release|x86 + {6C38E542-EFCE-4CAB-9B11-2C3D4D85F5F4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6C38E542-EFCE-4CAB-9B11-2C3D4D85F5F4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6C38E542-EFCE-4CAB-9B11-2C3D4D85F5F4}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {6C38E542-EFCE-4CAB-9B11-2C3D4D85F5F4}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {6C38E542-EFCE-4CAB-9B11-2C3D4D85F5F4}.Debug|Win32.ActiveCfg = Debug|Any CPU + {6C38E542-EFCE-4CAB-9B11-2C3D4D85F5F4}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6C38E542-EFCE-4CAB-9B11-2C3D4D85F5F4}.Release|Any CPU.Build.0 = Release|Any CPU + {6C38E542-EFCE-4CAB-9B11-2C3D4D85F5F4}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {6C38E542-EFCE-4CAB-9B11-2C3D4D85F5F4}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {6C38E542-EFCE-4CAB-9B11-2C3D4D85F5F4}.Release|Win32.ActiveCfg = Release|Any CPU + {6D37DDE4-2418-4EFB-A6E3-DC6A94D9369D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6D37DDE4-2418-4EFB-A6E3-DC6A94D9369D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6D37DDE4-2418-4EFB-A6E3-DC6A94D9369D}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {6D37DDE4-2418-4EFB-A6E3-DC6A94D9369D}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {6D37DDE4-2418-4EFB-A6E3-DC6A94D9369D}.Debug|Win32.ActiveCfg = Debug|Any CPU + {6D37DDE4-2418-4EFB-A6E3-DC6A94D9369D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6D37DDE4-2418-4EFB-A6E3-DC6A94D9369D}.Release|Any CPU.Build.0 = Release|Any CPU + {6D37DDE4-2418-4EFB-A6E3-DC6A94D9369D}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {6D37DDE4-2418-4EFB-A6E3-DC6A94D9369D}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {6D37DDE4-2418-4EFB-A6E3-DC6A94D9369D}.Release|Win32.ActiveCfg = Release|Any CPU {84AA94EB-9DAB-4255-A16E-8A8BA7DFB913}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {84AA94EB-9DAB-4255-A16E-8A8BA7DFB913}.Debug|Any CPU.Build.0 = Debug|Any CPU {84AA94EB-9DAB-4255-A16E-8A8BA7DFB913}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU @@ -128,56 +202,58 @@ Global {9522588A-5311-41F1-814C-4FB626FC0B47}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU {9522588A-5311-41F1-814C-4FB626FC0B47}.Release|Mixed Platforms.Build.0 = Release|Any CPU {9522588A-5311-41F1-814C-4FB626FC0B47}.Release|Win32.ActiveCfg = Release|Any CPU - {2CE65814-8EF5-4133-822B-3B7177A4E292}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {2CE65814-8EF5-4133-822B-3B7177A4E292}.Debug|Any CPU.Build.0 = Debug|Any CPU - {2CE65814-8EF5-4133-822B-3B7177A4E292}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {2CE65814-8EF5-4133-822B-3B7177A4E292}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {2CE65814-8EF5-4133-822B-3B7177A4E292}.Debug|Win32.ActiveCfg = Debug|Any CPU - {2CE65814-8EF5-4133-822B-3B7177A4E292}.Release|Any CPU.ActiveCfg = Release|Any CPU - {2CE65814-8EF5-4133-822B-3B7177A4E292}.Release|Any CPU.Build.0 = Release|Any CPU - {2CE65814-8EF5-4133-822B-3B7177A4E292}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {2CE65814-8EF5-4133-822B-3B7177A4E292}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {2CE65814-8EF5-4133-822B-3B7177A4E292}.Release|Win32.ActiveCfg = Release|Any CPU - {C6F0D42E-A5D4-4A7B-AD77-91A84449DE04}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {C6F0D42E-A5D4-4A7B-AD77-91A84449DE04}.Debug|Any CPU.Build.0 = Debug|Any CPU - {C6F0D42E-A5D4-4A7B-AD77-91A84449DE04}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {C6F0D42E-A5D4-4A7B-AD77-91A84449DE04}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {C6F0D42E-A5D4-4A7B-AD77-91A84449DE04}.Debug|Win32.ActiveCfg = Debug|Any CPU - {C6F0D42E-A5D4-4A7B-AD77-91A84449DE04}.Release|Any CPU.ActiveCfg = Release|Any CPU - {C6F0D42E-A5D4-4A7B-AD77-91A84449DE04}.Release|Any CPU.Build.0 = Release|Any CPU - {C6F0D42E-A5D4-4A7B-AD77-91A84449DE04}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {C6F0D42E-A5D4-4A7B-AD77-91A84449DE04}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {C6F0D42E-A5D4-4A7B-AD77-91A84449DE04}.Release|Win32.ActiveCfg = Release|Any CPU - {237BD115-097E-4EB9-B447-8299F2EA5C7D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {237BD115-097E-4EB9-B447-8299F2EA5C7D}.Debug|Any CPU.Build.0 = Debug|Any CPU - {237BD115-097E-4EB9-B447-8299F2EA5C7D}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {237BD115-097E-4EB9-B447-8299F2EA5C7D}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {237BD115-097E-4EB9-B447-8299F2EA5C7D}.Debug|Win32.ActiveCfg = Debug|Any CPU - {237BD115-097E-4EB9-B447-8299F2EA5C7D}.Release|Any CPU.ActiveCfg = Release|Any CPU - {237BD115-097E-4EB9-B447-8299F2EA5C7D}.Release|Any CPU.Build.0 = Release|Any CPU - {237BD115-097E-4EB9-B447-8299F2EA5C7D}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {237BD115-097E-4EB9-B447-8299F2EA5C7D}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {237BD115-097E-4EB9-B447-8299F2EA5C7D}.Release|Win32.ActiveCfg = Release|Any CPU - {0027D5BC-DF90-4EE4-B07E-4192A183AC38}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {0027D5BC-DF90-4EE4-B07E-4192A183AC38}.Debug|Any CPU.Build.0 = Debug|Any CPU - {0027D5BC-DF90-4EE4-B07E-4192A183AC38}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {0027D5BC-DF90-4EE4-B07E-4192A183AC38}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {0027D5BC-DF90-4EE4-B07E-4192A183AC38}.Debug|Win32.ActiveCfg = Debug|Any CPU - {0027D5BC-DF90-4EE4-B07E-4192A183AC38}.Release|Any CPU.ActiveCfg = Release|Any CPU - {0027D5BC-DF90-4EE4-B07E-4192A183AC38}.Release|Any CPU.Build.0 = Release|Any CPU - {0027D5BC-DF90-4EE4-B07E-4192A183AC38}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {0027D5BC-DF90-4EE4-B07E-4192A183AC38}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {0027D5BC-DF90-4EE4-B07E-4192A183AC38}.Release|Win32.ActiveCfg = Release|Any CPU - {EE2BF129-3451-4ADA-8698-42EE2A293688}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {EE2BF129-3451-4ADA-8698-42EE2A293688}.Debug|Any CPU.Build.0 = Debug|Any CPU - {EE2BF129-3451-4ADA-8698-42EE2A293688}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {EE2BF129-3451-4ADA-8698-42EE2A293688}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {EE2BF129-3451-4ADA-8698-42EE2A293688}.Debug|Win32.ActiveCfg = Debug|Any CPU - {EE2BF129-3451-4ADA-8698-42EE2A293688}.Release|Any CPU.ActiveCfg = Release|Any CPU - {EE2BF129-3451-4ADA-8698-42EE2A293688}.Release|Any CPU.Build.0 = Release|Any CPU - {EE2BF129-3451-4ADA-8698-42EE2A293688}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {EE2BF129-3451-4ADA-8698-42EE2A293688}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {EE2BF129-3451-4ADA-8698-42EE2A293688}.Release|Win32.ActiveCfg = Release|Any CPU + {9C5B4994-70C3-489D-933C-E2049C0505DB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9C5B4994-70C3-489D-933C-E2049C0505DB}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9C5B4994-70C3-489D-933C-E2049C0505DB}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {9C5B4994-70C3-489D-933C-E2049C0505DB}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {9C5B4994-70C3-489D-933C-E2049C0505DB}.Debug|Win32.ActiveCfg = Debug|Any CPU + {9C5B4994-70C3-489D-933C-E2049C0505DB}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9C5B4994-70C3-489D-933C-E2049C0505DB}.Release|Any CPU.Build.0 = Release|Any CPU + {9C5B4994-70C3-489D-933C-E2049C0505DB}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {9C5B4994-70C3-489D-933C-E2049C0505DB}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {9C5B4994-70C3-489D-933C-E2049C0505DB}.Release|Win32.ActiveCfg = Release|Any CPU + {9CF28420-D689-46E6-B659-72520A515372}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9CF28420-D689-46E6-B659-72520A515372}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9CF28420-D689-46E6-B659-72520A515372}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {9CF28420-D689-46E6-B659-72520A515372}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {9CF28420-D689-46E6-B659-72520A515372}.Debug|Win32.ActiveCfg = Debug|Any CPU + {9CF28420-D689-46E6-B659-72520A515372}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9CF28420-D689-46E6-B659-72520A515372}.Release|Any CPU.Build.0 = Release|Any CPU + {9CF28420-D689-46E6-B659-72520A515372}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {9CF28420-D689-46E6-B659-72520A515372}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {9CF28420-D689-46E6-B659-72520A515372}.Release|Win32.ActiveCfg = Release|Any CPU + {A4816166-67F7-42FF-B199-2758574312B2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A4816166-67F7-42FF-B199-2758574312B2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A4816166-67F7-42FF-B199-2758574312B2}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {A4816166-67F7-42FF-B199-2758574312B2}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {A4816166-67F7-42FF-B199-2758574312B2}.Debug|Win32.ActiveCfg = Debug|Any CPU + {A4816166-67F7-42FF-B199-2758574312B2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A4816166-67F7-42FF-B199-2758574312B2}.Release|Any CPU.Build.0 = Release|Any CPU + {A4816166-67F7-42FF-B199-2758574312B2}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {A4816166-67F7-42FF-B199-2758574312B2}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {A4816166-67F7-42FF-B199-2758574312B2}.Release|Win32.ActiveCfg = Release|Any CPU + {BC09FBD9-AAEB-4A4F-965E-1EBE3E880141}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BC09FBD9-AAEB-4A4F-965E-1EBE3E880141}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BC09FBD9-AAEB-4A4F-965E-1EBE3E880141}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {BC09FBD9-AAEB-4A4F-965E-1EBE3E880141}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {BC09FBD9-AAEB-4A4F-965E-1EBE3E880141}.Debug|Win32.ActiveCfg = Debug|Any CPU + {BC09FBD9-AAEB-4A4F-965E-1EBE3E880141}.Debug|Win32.Build.0 = Debug|Any CPU + {BC09FBD9-AAEB-4A4F-965E-1EBE3E880141}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BC09FBD9-AAEB-4A4F-965E-1EBE3E880141}.Release|Any CPU.Build.0 = Release|Any CPU + {BC09FBD9-AAEB-4A4F-965E-1EBE3E880141}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {BC09FBD9-AAEB-4A4F-965E-1EBE3E880141}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {BC09FBD9-AAEB-4A4F-965E-1EBE3E880141}.Release|Win32.ActiveCfg = Release|Any CPU + {BC09FBD9-AAEB-4A4F-965E-1EBE3E880141}.Release|Win32.Build.0 = Release|Any CPU + {C3DCCFE3-DD3F-4EEE-849B-33E355B1E064}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C3DCCFE3-DD3F-4EEE-849B-33E355B1E064}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C3DCCFE3-DD3F-4EEE-849B-33E355B1E064}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {C3DCCFE3-DD3F-4EEE-849B-33E355B1E064}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {C3DCCFE3-DD3F-4EEE-849B-33E355B1E064}.Debug|Win32.ActiveCfg = Debug|Any CPU + {C3DCCFE3-DD3F-4EEE-849B-33E355B1E064}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C3DCCFE3-DD3F-4EEE-849B-33E355B1E064}.Release|Any CPU.Build.0 = Release|Any CPU + {C3DCCFE3-DD3F-4EEE-849B-33E355B1E064}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {C3DCCFE3-DD3F-4EEE-849B-33E355B1E064}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {C3DCCFE3-DD3F-4EEE-849B-33E355B1E064}.Release|Win32.ActiveCfg = Release|Any CPU {C4C6E0DA-3C5A-4D43-B1BA-0289A813AEF4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {C4C6E0DA-3C5A-4D43-B1BA-0289A813AEF4}.Debug|Any CPU.Build.0 = Debug|Any CPU {C4C6E0DA-3C5A-4D43-B1BA-0289A813AEF4}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU @@ -188,56 +264,16 @@ Global {C4C6E0DA-3C5A-4D43-B1BA-0289A813AEF4}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU {C4C6E0DA-3C5A-4D43-B1BA-0289A813AEF4}.Release|Mixed Platforms.Build.0 = Release|Any CPU {C4C6E0DA-3C5A-4D43-B1BA-0289A813AEF4}.Release|Win32.ActiveCfg = Release|Any CPU - {6D37DDE4-2418-4EFB-A6E3-DC6A94D9369D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {6D37DDE4-2418-4EFB-A6E3-DC6A94D9369D}.Debug|Any CPU.Build.0 = Debug|Any CPU - {6D37DDE4-2418-4EFB-A6E3-DC6A94D9369D}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {6D37DDE4-2418-4EFB-A6E3-DC6A94D9369D}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {6D37DDE4-2418-4EFB-A6E3-DC6A94D9369D}.Debug|Win32.ActiveCfg = Debug|Any CPU - {6D37DDE4-2418-4EFB-A6E3-DC6A94D9369D}.Release|Any CPU.ActiveCfg = Release|Any CPU - {6D37DDE4-2418-4EFB-A6E3-DC6A94D9369D}.Release|Any CPU.Build.0 = Release|Any CPU - {6D37DDE4-2418-4EFB-A6E3-DC6A94D9369D}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {6D37DDE4-2418-4EFB-A6E3-DC6A94D9369D}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {6D37DDE4-2418-4EFB-A6E3-DC6A94D9369D}.Release|Win32.ActiveCfg = Release|Any CPU - {6C38E542-EFCE-4CAB-9B11-2C3D4D85F5F4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {6C38E542-EFCE-4CAB-9B11-2C3D4D85F5F4}.Debug|Any CPU.Build.0 = Debug|Any CPU - {6C38E542-EFCE-4CAB-9B11-2C3D4D85F5F4}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {6C38E542-EFCE-4CAB-9B11-2C3D4D85F5F4}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {6C38E542-EFCE-4CAB-9B11-2C3D4D85F5F4}.Debug|Win32.ActiveCfg = Debug|Any CPU - {6C38E542-EFCE-4CAB-9B11-2C3D4D85F5F4}.Release|Any CPU.ActiveCfg = Release|Any CPU - {6C38E542-EFCE-4CAB-9B11-2C3D4D85F5F4}.Release|Any CPU.Build.0 = Release|Any CPU - {6C38E542-EFCE-4CAB-9B11-2C3D4D85F5F4}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {6C38E542-EFCE-4CAB-9B11-2C3D4D85F5F4}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {6C38E542-EFCE-4CAB-9B11-2C3D4D85F5F4}.Release|Win32.ActiveCfg = Release|Any CPU - {000B0B0B-A12D-4EED-A261-7F95422E386A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {000B0B0B-A12D-4EED-A261-7F95422E386A}.Debug|Any CPU.Build.0 = Debug|Any CPU - {000B0B0B-A12D-4EED-A261-7F95422E386A}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {000B0B0B-A12D-4EED-A261-7F95422E386A}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {000B0B0B-A12D-4EED-A261-7F95422E386A}.Debug|Win32.ActiveCfg = Debug|Any CPU - {000B0B0B-A12D-4EED-A261-7F95422E386A}.Release|Any CPU.ActiveCfg = Release|Any CPU - {000B0B0B-A12D-4EED-A261-7F95422E386A}.Release|Any CPU.Build.0 = Release|Any CPU - {000B0B0B-A12D-4EED-A261-7F95422E386A}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {000B0B0B-A12D-4EED-A261-7F95422E386A}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {000B0B0B-A12D-4EED-A261-7F95422E386A}.Release|Win32.ActiveCfg = Release|Any CPU - {529DEB01-14A3-4FEC-AD89-6D4D0DC433C3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {529DEB01-14A3-4FEC-AD89-6D4D0DC433C3}.Debug|Any CPU.Build.0 = Debug|Any CPU - {529DEB01-14A3-4FEC-AD89-6D4D0DC433C3}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {529DEB01-14A3-4FEC-AD89-6D4D0DC433C3}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {529DEB01-14A3-4FEC-AD89-6D4D0DC433C3}.Debug|Win32.ActiveCfg = Debug|Any CPU - {529DEB01-14A3-4FEC-AD89-6D4D0DC433C3}.Release|Any CPU.ActiveCfg = Release|Any CPU - {529DEB01-14A3-4FEC-AD89-6D4D0DC433C3}.Release|Any CPU.Build.0 = Release|Any CPU - {529DEB01-14A3-4FEC-AD89-6D4D0DC433C3}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {529DEB01-14A3-4FEC-AD89-6D4D0DC433C3}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {529DEB01-14A3-4FEC-AD89-6D4D0DC433C3}.Release|Win32.ActiveCfg = Release|Any CPU - {F8733117-DA1D-40DC-AEF8-98051B86E219}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {F8733117-DA1D-40DC-AEF8-98051B86E219}.Debug|Any CPU.Build.0 = Debug|Any CPU - {F8733117-DA1D-40DC-AEF8-98051B86E219}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {F8733117-DA1D-40DC-AEF8-98051B86E219}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {F8733117-DA1D-40DC-AEF8-98051B86E219}.Debug|Win32.ActiveCfg = Debug|Any CPU - {F8733117-DA1D-40DC-AEF8-98051B86E219}.Release|Any CPU.ActiveCfg = Release|Any CPU - {F8733117-DA1D-40DC-AEF8-98051B86E219}.Release|Any CPU.Build.0 = Release|Any CPU - {F8733117-DA1D-40DC-AEF8-98051B86E219}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {F8733117-DA1D-40DC-AEF8-98051B86E219}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {F8733117-DA1D-40DC-AEF8-98051B86E219}.Release|Win32.ActiveCfg = Release|Any CPU + {C6F0D42E-A5D4-4A7B-AD77-91A84449DE04}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C6F0D42E-A5D4-4A7B-AD77-91A84449DE04}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C6F0D42E-A5D4-4A7B-AD77-91A84449DE04}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {C6F0D42E-A5D4-4A7B-AD77-91A84449DE04}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {C6F0D42E-A5D4-4A7B-AD77-91A84449DE04}.Debug|Win32.ActiveCfg = Debug|Any CPU + {C6F0D42E-A5D4-4A7B-AD77-91A84449DE04}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C6F0D42E-A5D4-4A7B-AD77-91A84449DE04}.Release|Any CPU.Build.0 = Release|Any CPU + {C6F0D42E-A5D4-4A7B-AD77-91A84449DE04}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {C6F0D42E-A5D4-4A7B-AD77-91A84449DE04}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {C6F0D42E-A5D4-4A7B-AD77-91A84449DE04}.Release|Win32.ActiveCfg = Release|Any CPU {E0198A08-AAA8-4A76-B096-BBE72DA4F93B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {E0198A08-AAA8-4A76-B096-BBE72DA4F93B}.Debug|Any CPU.Build.0 = Debug|Any CPU {E0198A08-AAA8-4A76-B096-BBE72DA4F93B}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU @@ -248,36 +284,16 @@ Global {E0198A08-AAA8-4A76-B096-BBE72DA4F93B}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU {E0198A08-AAA8-4A76-B096-BBE72DA4F93B}.Release|Mixed Platforms.Build.0 = Release|Any CPU {E0198A08-AAA8-4A76-B096-BBE72DA4F93B}.Release|Win32.ActiveCfg = Release|Any CPU - {9CF28420-D689-46E6-B659-72520A515372}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {9CF28420-D689-46E6-B659-72520A515372}.Debug|Any CPU.Build.0 = Debug|Any CPU - {9CF28420-D689-46E6-B659-72520A515372}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {9CF28420-D689-46E6-B659-72520A515372}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {9CF28420-D689-46E6-B659-72520A515372}.Debug|Win32.ActiveCfg = Debug|Any CPU - {9CF28420-D689-46E6-B659-72520A515372}.Release|Any CPU.ActiveCfg = Release|Any CPU - {9CF28420-D689-46E6-B659-72520A515372}.Release|Any CPU.Build.0 = Release|Any CPU - {9CF28420-D689-46E6-B659-72520A515372}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {9CF28420-D689-46E6-B659-72520A515372}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {9CF28420-D689-46E6-B659-72520A515372}.Release|Win32.ActiveCfg = Release|Any CPU - {571AC77A-7D3D-44CF-B0E7-08DF03D7B638}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {571AC77A-7D3D-44CF-B0E7-08DF03D7B638}.Debug|Any CPU.Build.0 = Debug|Any CPU - {571AC77A-7D3D-44CF-B0E7-08DF03D7B638}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {571AC77A-7D3D-44CF-B0E7-08DF03D7B638}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {571AC77A-7D3D-44CF-B0E7-08DF03D7B638}.Debug|Win32.ActiveCfg = Debug|Any CPU - {571AC77A-7D3D-44CF-B0E7-08DF03D7B638}.Release|Any CPU.ActiveCfg = Release|Any CPU - {571AC77A-7D3D-44CF-B0E7-08DF03D7B638}.Release|Any CPU.Build.0 = Release|Any CPU - {571AC77A-7D3D-44CF-B0E7-08DF03D7B638}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {571AC77A-7D3D-44CF-B0E7-08DF03D7B638}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {571AC77A-7D3D-44CF-B0E7-08DF03D7B638}.Release|Win32.ActiveCfg = Release|Any CPU - {2EDF3192-9107-4B7A-914A-EA25AFEB9F85}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {2EDF3192-9107-4B7A-914A-EA25AFEB9F85}.Debug|Any CPU.Build.0 = Debug|Any CPU - {2EDF3192-9107-4B7A-914A-EA25AFEB9F85}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {2EDF3192-9107-4B7A-914A-EA25AFEB9F85}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {2EDF3192-9107-4B7A-914A-EA25AFEB9F85}.Debug|Win32.ActiveCfg = Debug|Any CPU - {2EDF3192-9107-4B7A-914A-EA25AFEB9F85}.Release|Any CPU.ActiveCfg = Release|Any CPU - {2EDF3192-9107-4B7A-914A-EA25AFEB9F85}.Release|Any CPU.Build.0 = Release|Any CPU - {2EDF3192-9107-4B7A-914A-EA25AFEB9F85}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {2EDF3192-9107-4B7A-914A-EA25AFEB9F85}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {2EDF3192-9107-4B7A-914A-EA25AFEB9F85}.Release|Win32.ActiveCfg = Release|Any CPU + {EE2BF129-3451-4ADA-8698-42EE2A293688}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {EE2BF129-3451-4ADA-8698-42EE2A293688}.Debug|Any CPU.Build.0 = Debug|Any CPU + {EE2BF129-3451-4ADA-8698-42EE2A293688}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {EE2BF129-3451-4ADA-8698-42EE2A293688}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {EE2BF129-3451-4ADA-8698-42EE2A293688}.Debug|Win32.ActiveCfg = Debug|Any CPU + {EE2BF129-3451-4ADA-8698-42EE2A293688}.Release|Any CPU.ActiveCfg = Release|Any CPU + {EE2BF129-3451-4ADA-8698-42EE2A293688}.Release|Any CPU.Build.0 = Release|Any CPU + {EE2BF129-3451-4ADA-8698-42EE2A293688}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {EE2BF129-3451-4ADA-8698-42EE2A293688}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {EE2BF129-3451-4ADA-8698-42EE2A293688}.Release|Win32.ActiveCfg = Release|Any CPU {F4E6168A-B2CB-413C-AE0E-0D8B856B425E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {F4E6168A-B2CB-413C-AE0E-0D8B856B425E}.Debug|Any CPU.Build.0 = Debug|Any CPU {F4E6168A-B2CB-413C-AE0E-0D8B856B425E}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU @@ -288,25 +304,34 @@ Global {F4E6168A-B2CB-413C-AE0E-0D8B856B425E}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU {F4E6168A-B2CB-413C-AE0E-0D8B856B425E}.Release|Mixed Platforms.Build.0 = Release|Any CPU {F4E6168A-B2CB-413C-AE0E-0D8B856B425E}.Release|Win32.ActiveCfg = Release|Any CPU - {3CC0E6B1-1E96-4A07-8AE7-A7C7F47911B1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {3CC0E6B1-1E96-4A07-8AE7-A7C7F47911B1}.Debug|Any CPU.Build.0 = Debug|Any CPU - {3CC0E6B1-1E96-4A07-8AE7-A7C7F47911B1}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {3CC0E6B1-1E96-4A07-8AE7-A7C7F47911B1}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {3CC0E6B1-1E96-4A07-8AE7-A7C7F47911B1}.Debug|Win32.ActiveCfg = Debug|Any CPU - {3CC0E6B1-1E96-4A07-8AE7-A7C7F47911B1}.Release|Any CPU.ActiveCfg = Release|Any CPU - {3CC0E6B1-1E96-4A07-8AE7-A7C7F47911B1}.Release|Any CPU.Build.0 = Release|Any CPU - {3CC0E6B1-1E96-4A07-8AE7-A7C7F47911B1}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {3CC0E6B1-1E96-4A07-8AE7-A7C7F47911B1}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {3CC0E6B1-1E96-4A07-8AE7-A7C7F47911B1}.Release|Win32.ActiveCfg = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE + {F58C2874-D663-42BD-B406-3526F57868E7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F58C2874-D663-42BD-B406-3526F57868E7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F58C2874-D663-42BD-B406-3526F57868E7}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {F58C2874-D663-42BD-B406-3526F57868E7}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {F58C2874-D663-42BD-B406-3526F57868E7}.Debug|Win32.ActiveCfg = Debug|Any CPU + {F58C2874-D663-42BD-B406-3526F57868E7}.Debug|Win32.Build.0 = Debug|Any CPU + {F58C2874-D663-42BD-B406-3526F57868E7}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F58C2874-D663-42BD-B406-3526F57868E7}.Release|Any CPU.Build.0 = Release|Any CPU + {F58C2874-D663-42BD-B406-3526F57868E7}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {F58C2874-D663-42BD-B406-3526F57868E7}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {F58C2874-D663-42BD-B406-3526F57868E7}.Release|Win32.ActiveCfg = Release|Any CPU + {F58C2874-D663-42BD-B406-3526F57868E7}.Release|Win32.Build.0 = Release|Any CPU + {F8733117-DA1D-40DC-AEF8-98051B86E219}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F8733117-DA1D-40DC-AEF8-98051B86E219}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F8733117-DA1D-40DC-AEF8-98051B86E219}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {F8733117-DA1D-40DC-AEF8-98051B86E219}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {F8733117-DA1D-40DC-AEF8-98051B86E219}.Debug|Win32.ActiveCfg = Debug|Any CPU + {F8733117-DA1D-40DC-AEF8-98051B86E219}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F8733117-DA1D-40DC-AEF8-98051B86E219}.Release|Any CPU.Build.0 = Release|Any CPU + {F8733117-DA1D-40DC-AEF8-98051B86E219}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {F8733117-DA1D-40DC-AEF8-98051B86E219}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {F8733117-DA1D-40DC-AEF8-98051B86E219}.Release|Win32.ActiveCfg = Release|Any CPU EndGlobalSection GlobalSection(NestedProjects) = preSolution {9C5B4994-70C3-489D-933C-E2049C0505DB} = {1F24CB15-2CD3-432A-BE46-65CCE8A9DCF3} + {9522588A-5311-41F1-814C-4FB626FC0B47} = {1F24CB15-2CD3-432A-BE46-65CCE8A9DCF3} {637070BF-4FD2-4DF9-838F-1C42E7BDAE74} = {41D1D336-13B2-488B-8A85-C0F744035F8B} {84AA94EB-9DAB-4255-A16E-8A8BA7DFB913} = {41D1D336-13B2-488B-8A85-C0F744035F8B} - {9522588A-5311-41F1-814C-4FB626FC0B47} = {1F24CB15-2CD3-432A-BE46-65CCE8A9DCF3} {2CE65814-8EF5-4133-822B-3B7177A4E292} = {41D1D336-13B2-488B-8A85-C0F744035F8B} {C6F0D42E-A5D4-4A7B-AD77-91A84449DE04} = {41D1D336-13B2-488B-8A85-C0F744035F8B} {237BD115-097E-4EB9-B447-8299F2EA5C7D} = {41D1D336-13B2-488B-8A85-C0F744035F8B} diff --git a/CSCore/CSCore.csproj b/CSCore/CSCore.csproj index b023d171..5c8bd532 100644 --- a/CSCore/CSCore.csproj +++ b/CSCore/CSCore.csproj @@ -601,13 +601,15 @@ PreserveNewest + + - + @echo off & setLocal EnableDELAYedeXpansion chcp 65001 diff --git a/CSCore/Codecs/CodecFactory.cs b/CSCore/Codecs/CodecFactory.cs index 08ec7dca..3c1967f4 100644 --- a/CSCore/Codecs/CodecFactory.cs +++ b/CSCore/Codecs/CodecFactory.cs @@ -14,6 +14,7 @@ using CSCore.Codecs.WAV; using CSCore.Codecs.WMA; using CSCore.MediaFoundation; +using CSCore.Utils; namespace CSCore.Codecs { @@ -27,23 +28,44 @@ public class CodecFactory private readonly Dictionary _codecs; + protected DefaultCodecAction DefaultCodec { get; set; } + + /// + /// Add initial codec entrys to the registry + /// Only adds windows specific codecs if we are running on windows + /// Linux/OSX need to manually register their codecs + /// private CodecFactory() { _codecs = new Dictionary(); - Register("mp3", new CodecFactoryEntry(s => + + Platform plat = PlatformDetection.RunningPlatform(); + + // Add MediaFoundation as default on Windows + if (plat == Platform.Windows) RegisterDefaultCodec((url, isWebURL) => { return new MediaFoundationDecoder(url); }); + + // only register DMO/Mediafoundation if we are on Windows + // require other platforms (Linux/OSX) to register themselves + if (plat == Platform.Windows) { - try + Register("mp3", new CodecFactoryEntry(s => { - return new DmoMp3Decoder(s); - } - catch (Exception) - { - if (Mp3MediafoundationDecoder.IsSupported) - return new Mp3MediafoundationDecoder(s); - throw; - } - }, - "mp3", "mpeg3")); + try + { + return new DmoMp3Decoder(s); + } + catch (Exception) + { + if (Mp3MediafoundationDecoder.IsSupported) + return new Mp3MediafoundationDecoder(s); + throw; + } + }, + "mp3", "mpeg3")); + } + + // These codecs are platform independent + Register("wave", new CodecFactoryEntry(s => { IWaveSource res = new WaveFileReader(s); @@ -62,32 +84,34 @@ private CodecFactory() Register("aiff", new CodecFactoryEntry(s => new AiffReader(s), "aiff", "aif", "aifc")); - if (AacDecoder.IsSupported) + // !! Only attempt to register the following codecs if we are running on windows !! + + if (plat == Platform.Windows && AacDecoder.IsSupported) { Register("aac", new CodecFactoryEntry(s => new AacDecoder(s), "aac", "adt", "adts", "m2ts", "mp2", "3g2", "3gp2", "3gp", "3gpp", "m4a", "m4v", "mp4v", "mp4", "mov")); } - if (WmaDecoder.IsSupported) + if (plat == Platform.Windows && WmaDecoder.IsSupported) { Register("wma", new CodecFactoryEntry(s => new WmaDecoder(s), "asf", "wm", "wmv", "wma")); } - if (Mp1Decoder.IsSupported) + if (plat == Platform.Windows && Mp1Decoder.IsSupported) { Register("mp1", new CodecFactoryEntry(s => new Mp1Decoder(s), "mp1", "m2ts")); } - if (Mp2Decoder.IsSupported) + if (plat == Platform.Windows && Mp2Decoder.IsSupported) { - Register("mp2", new CodecFactoryEntry(s => new Mp2Decoder(s), + Register("mp2", new CodecFactoryEntry(s => new Mp1Decoder(s), "mp2", "m2ts")); } - if (DDPDecoder.IsSupported) + if (plat == Platform.Windows && DDPDecoder.IsSupported) { Register("ddp", new CodecFactoryEntry(s => new DDPDecoder(s), "mp2", "m2ts", "m4a", "m4v", "mp4v", "mp4", "mov", "asf", "wm", "wmv", "wma", "avi", "ac3", "ec3")); @@ -102,6 +126,7 @@ public static CodecFactory Instance get { return _instance; } } + /// /// Gets the file filter in English. This filter can be used e.g. in combination with an OpenFileDialog. /// @@ -129,6 +154,15 @@ public void Register(object key, CodecFactoryEntry codec) _codecs.Add(key, codec); } + /// + /// Registers a default codec action + /// + /// The default codec action to register + public void RegisterDefaultCodec(DefaultCodecAction action) + { + DefaultCodec = action; + } + /// /// Returns a fully initialized instance which is able to decode the specified file. If the /// specified file can not be decoded, this method throws an . @@ -202,7 +236,7 @@ private IWaveSource OpenWebStream(string url) { try { - return Default(url); + return Default(url, true); } catch (Exception) { @@ -220,9 +254,9 @@ private IWaveSource OpenWebStream(string url) } } - private static IWaveSource Default(string url) + private static IWaveSource Default(string url, bool isWebURL = false) { - return new MediaFoundationDecoder(url); + return Instance.DefaultCodec(url, isWebURL); } /// diff --git a/CSCore/Codecs/DefaultCodecAction.cs b/CSCore/Codecs/DefaultCodecAction.cs new file mode 100644 index 00000000..f40c71db --- /dev/null +++ b/CSCore/Codecs/DefaultCodecAction.cs @@ -0,0 +1,12 @@ +using System; +namespace CSCore.Codecs +{ + /// + /// Delegate which initializes the default decoder + /// + /// of the audio file to be opened by the decoder + /// Whether the url is a web url or not + /// Decoder for a specific coded based on a . + public delegate IWaveSource DefaultCodecAction(string url, bool isWebURL = false); +} + diff --git a/CSCore/Utils/PlatformDetection.cs b/CSCore/Utils/PlatformDetection.cs new file mode 100644 index 00000000..62a5f090 --- /dev/null +++ b/CSCore/Utils/PlatformDetection.cs @@ -0,0 +1,61 @@ +using System; +using System.IO; + +namespace CSCore.Utils +{ + /// + /// Operating system platform + /// + public enum Platform + { + /// + /// Windows + /// + Windows, + + /// + /// Linux + /// + Linux, + + /// + /// MacOSX + /// + MacOSX + } + + /// + /// Platform detection code + /// + public static class PlatformDetection + { + /// + /// Checks which platform we are running on + /// Code adapted from here: https://stackoverflow.com/questions/10138040/how-to-detect-properly-windows-linux-mac-operating-systems + /// + /// The platform we are running on + public static Platform RunningPlatform() + { + switch (Environment.OSVersion.Platform) + { + case PlatformID.Unix: + // Well, there are chances MacOSX is reported as Unix instead of MacOSX. + // Instead of platform check, we'll do a feature checks (Mac specific root folders) + if (Directory.Exists("/Applications") + & Directory.Exists("/System") + & Directory.Exists("/Users") + & Directory.Exists("/Volumes")) + return Platform.MacOSX; + else + return Platform.Linux; + + case PlatformID.MacOSX: + return Platform.MacOSX; + + default: + return Platform.Windows; + } + } + } +} +