diff --git a/Halovision/Dependencies/lucidcode.LucidScribe.Interface.Illuminated.dll b/Halovision/Dependencies/lucidcode.LucidScribe.Interface.Illuminated.dll new file mode 100644 index 0000000..a813739 Binary files /dev/null and b/Halovision/Dependencies/lucidcode.LucidScribe.Interface.Illuminated.dll differ diff --git a/Halovision/FifoStream.cs b/Halovision/FifoStream.cs new file mode 100644 index 0000000..7a32595 --- /dev/null +++ b/Halovision/FifoStream.cs @@ -0,0 +1,168 @@ +using System; +using System.IO; +using System.Linq; +using System.Collections; + +namespace lucidcode.LucidScribe.Plugin.Halovision +{ + public class FifoStream : Stream + { + private const int BlockSize = 65536; + private const int MaxBlocksInCache = (3 * 1024 * 1024) / BlockSize; + + private int m_Size; + private int m_RPos; + private int m_WPos; + private Stack m_UsedBlocks = new Stack(); + private ArrayList m_Blocks = new ArrayList(); + + private byte[] AllocBlock() + { + byte[] Result = null; + Result = m_UsedBlocks.Count > 0 ? (byte[])m_UsedBlocks.Pop() : new byte[BlockSize]; + return Result; + } + private void FreeBlock(byte[] block) + { + if (m_UsedBlocks.Count < MaxBlocksInCache) + m_UsedBlocks.Push(block); + } + private byte[] GetWBlock() + { + byte[] Result = null; + if (m_WPos < BlockSize && m_Blocks.Count > 0) + Result = (byte[])m_Blocks[m_Blocks.Count - 1]; + else + { + Result = AllocBlock(); + m_Blocks.Add(Result); + m_WPos = 0; + } + return Result; + } + + // Stream members + public override bool CanRead + { + get { return true; } + } + public override bool CanSeek + { + get { return false; } + } + public override bool CanWrite + { + get { return true; } + } + public override long Length + { + get + { + lock (this) + return m_Size; + } + } + public override long Position + { + get { throw new InvalidOperationException(); } + set { throw new InvalidOperationException(); } + } + public override void Close() + { + Flush(); + } + public override void Flush() + { + lock (this) + { + foreach (byte[] block in m_Blocks) + FreeBlock(block); + m_Blocks.Clear(); + m_RPos = 0; + m_WPos = 0; + m_Size = 0; + } + } + public override void SetLength(long len) + { + throw new InvalidOperationException(); + } + public override long Seek(long pos, SeekOrigin o) + { + throw new InvalidOperationException(); + } + public override int Read(byte[] buf, int ofs, int count) + { + lock (this) + { + int Result = Peek(buf, ofs, count); + Advance(Result); + return Result; + } + } + public override void Write(byte[] buf, int ofs, int count) + { + lock (this) + { + int Left = count; + while (Left > 0) + { + int ToWrite = Math.Min(BlockSize - m_WPos, Left); + Array.Copy(buf, ofs + count - Left, GetWBlock(), m_WPos, ToWrite); + m_WPos += ToWrite; + Left -= ToWrite; + } + m_Size += count; + } + } + + // extra stuff + public int Advance(int count) + { + lock (this) + { + int SizeLeft = count; + while (SizeLeft > 0 && m_Size > 0) + { + if (m_RPos == BlockSize) + { + m_RPos = 0; + FreeBlock((byte[])m_Blocks[0]); + m_Blocks.RemoveAt(0); + } + int ToFeed = m_Blocks.Count == 1 ? Math.Min(m_WPos - m_RPos, SizeLeft) : Math.Min(BlockSize - m_RPos, SizeLeft); + m_RPos += ToFeed; + SizeLeft -= ToFeed; + m_Size -= ToFeed; + } + return count - SizeLeft; + } + } + public int Peek(byte[] buf, int ofs, int count) + { + lock (this) + { + int SizeLeft = count; + int TempBlockPos = m_RPos; + int TempSize = m_Size; + + int CurrentBlock = 0; + while (SizeLeft > 0 && TempSize > 0) + { + if (TempBlockPos == BlockSize) + { + TempBlockPos = 0; + CurrentBlock++; + } + int Upper = CurrentBlock < m_Blocks.Count - 1 ? BlockSize : m_WPos; + int ToFeed = Math.Min(Upper - TempBlockPos, SizeLeft); + Array.Copy((byte[])m_Blocks[CurrentBlock], TempBlockPos, buf, ofs + count - SizeLeft, ToFeed); + SizeLeft -= ToFeed; + TempBlockPos += ToFeed; + TempSize -= ToFeed; + } + return count - SizeLeft; + } + } + } +} diff --git a/Halovision/FormatChunk.cs b/Halovision/FormatChunk.cs index 020e166..f83eef4 100644 --- a/Halovision/FormatChunk.cs +++ b/Halovision/FormatChunk.cs @@ -1,8 +1,6 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Text; -using System.Threading.Tasks; namespace lucidcode.LucidScribe.Plugin.Halovision { diff --git a/Halovision/Halovision.csproj b/Halovision/Halovision.csproj index a173c57..689a7ba 100644 --- a/Halovision/Halovision.csproj +++ b/Halovision/Halovision.csproj @@ -121,6 +121,9 @@ Dependencies\lucidcode.LucidScribe.Interface.dll False + + Dependencies\lucidcode.LucidScribe.Interface.Illuminated.dll + Dependencies\lucidcode.LucidScribe.TCMP.dll @@ -134,6 +137,30 @@ ..\packages\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.Extensions.Desktop.dll + + ..\packages\Microsoft.Win32.Registry.4.7.0\lib\net461\Microsoft.Win32.Registry.dll + + + ..\packages\NAudio.2.1.0\lib\net472\NAudio.dll + + + ..\packages\NAudio.Asio.2.1.0\lib\netstandard2.0\NAudio.Asio.dll + + + ..\packages\NAudio.Core.2.1.0\lib\netstandard2.0\NAudio.Core.dll + + + ..\packages\NAudio.Midi.2.1.0\lib\netstandard2.0\NAudio.Midi.dll + + + ..\packages\NAudio.Wasapi.2.1.0\lib\netstandard2.0\NAudio.Wasapi.dll + + + ..\packages\NAudio.WinForms.2.1.0\lib\net472\NAudio.WinForms.dll + + + ..\packages\NAudio.WinMM.2.1.0\lib\netstandard2.0\NAudio.WinMM.dll + ..\packages\System.Buffers.4.5.1\lib\net461\System.Buffers.dll @@ -166,6 +193,12 @@ True + + ..\packages\System.Security.AccessControl.4.7.0\lib\net461\System.Security.AccessControl.dll + + + ..\packages\System.Security.Principal.Windows.4.7.0\lib\net461\System.Security.Principal.Windows.dll + ..\packages\System.ValueTuple.4.5.0\lib\net47\System.ValueTuple.dll @@ -178,6 +211,7 @@ + @@ -185,6 +219,7 @@ True Resources.resx + @@ -196,6 +231,8 @@ + + diff --git a/Halovision/PluginHandler.cs b/Halovision/PluginHandler.cs index 7027572..1a9b8ef 100644 --- a/Halovision/PluginHandler.cs +++ b/Halovision/PluginHandler.cs @@ -1,7 +1,9 @@ -using System; +using NAudio.Wave; +using NAudio.Wave.SampleProviders; +using System; using System.Collections.Generic; -using System.IO; -using System.Media; +using System.Drawing; +using System.Linq; using System.Threading; using System.Windows.Forms; @@ -11,7 +13,9 @@ public static class Device { static bool Initialized; static bool InitError; - static int Value = 0; + static List Readings = new List() { 0 }; + + public static EventHandler VisionChanged; static VisionForm visionForm; public static bool Initialize() @@ -38,7 +42,14 @@ public static bool Initialize() private static void VisionForm_ValueChanged(int value) { - Value = value; + Readings.Add(value); + + if (Readings.Count > 8) Readings.RemoveAt(0); + + if (VisionChanged != null) + { + VisionChanged((object)value, null); + } } static void loadVisionForm() @@ -72,8 +83,10 @@ public static void Dispose() } public static int GetVision() - { - return Value; + { + int value = Readings.Sum() / Readings.Count; + if (value > 999) return 999; + return value; } public static int GetTossThreshold() @@ -261,8 +274,6 @@ namespace Vision { public class PluginHandler : lucidcode.LucidScribe.Interface.LucidPluginBase { - SoundPlayer sound = new SoundPlayer(); - public override string Name { get @@ -287,34 +298,154 @@ public override double Value if (Device.Auralize && vision > 0) { Auralize(vision); } - + return vision; } } private void Auralize(double frequency) { - var header = new WaveHeader(); - var format = new FormatChunk(); - var austioChunk = new DataChunk(); - var sineData = new SineGenerator(frequency); + var sineWave = new NAudio.Wave.SampleProviders.SignalGenerator() + { + Gain = 0.1, + Frequency = 256 + frequency, + Type = SignalGeneratorType.Sin + }.Take(TimeSpan.FromMilliseconds(256)); - austioChunk.AddSampleData(sineData.Data, sineData.Data); - header.FileLength += format.Length() + austioChunk.Length(); + var waveOutEvent = new WaveOutEvent(); + waveOutEvent.Pause(); + waveOutEvent.Init(sineWave); + waveOutEvent.Play(); + } - var soundBytes = new List(); - soundBytes.AddRange(header.GetBytes()); - soundBytes.AddRange(format.GetBytes()); - soundBytes.AddRange(austioChunk.GetBytes()); + public override void Dispose() + { + Device.Dispose(); + } + } + } - sound.Stream = new MemoryStream(soundBytes.ToArray()); - sound.Play(); + namespace RAW + { + public class PluginHandler : lucidcode.LucidScribe.Interface.ILluminatedPlugin + { + + public string Name + { + get + { + return "Halovision RAW"; + } } - public override void Dispose() + public bool Initialize() + { + try + { + bool initialized = Device.Initialize(); + Device.VisionChanged += VisionChanged; + return initialized; + } + catch (Exception ex) + { + throw (new Exception("The '" + Name + "' plugin failed to initialize: " + ex.Message)); + } + } + + public event Interface.SenseHandler Sensed; + public void VisionChanged(object sender, EventArgs e) + { + if (ClearTicks) + { + ClearTicks = false; + TickCount = ""; + } + int value = (int)sender; + if (value > 999) value = 999; + TickCount += value + ","; + + if (ClearBuffer) + { + ClearBuffer = false; + BufferData = ""; + } + BufferData += value + ","; + } + + public void Dispose() { + Device.VisionChanged -= VisionChanged; Device.Dispose(); } + + public Boolean isEnabled = false; + public Boolean Enabled + { + get + { + return isEnabled; + } + set + { + isEnabled = value; + } + } + + public Color PluginColor = Color.White; + public Color Color + { + get + { + return Color; + } + set + { + Color = value; + } + } + + private Boolean ClearTicks = false; + public String TickCount = ""; + public String Ticks + { + get + { + ClearTicks = true; + return TickCount; + } + set + { + TickCount = value; + } + } + + private Boolean ClearBuffer = false; + public String BufferData = ""; + public String Buffer + { + get + { + ClearBuffer = true; + return BufferData; + } + set + { + BufferData = value; + } + } + + int lastHour; + public int LastHour + { + get + { + return lastHour; + } + set + { + lastHour = value; + } + } } } diff --git a/Halovision/Properties/AssemblyInfo.cs b/Halovision/Properties/AssemblyInfo.cs index edeb5ec..4952a19 100644 --- a/Halovision/Properties/AssemblyInfo.cs +++ b/Halovision/Properties/AssemblyInfo.cs @@ -32,5 +32,5 @@ // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.1.6.0")] -[assembly: AssemblyFileVersion("1.1.6.0")] +[assembly: AssemblyVersion("1.1.7.0")] +[assembly: AssemblyFileVersion("1.1.7.0")] diff --git a/Halovision/SignalGenerator.cs b/Halovision/SignalGenerator.cs new file mode 100644 index 0000000..16cefe2 --- /dev/null +++ b/Halovision/SignalGenerator.cs @@ -0,0 +1,138 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace lucidcode.LucidScribe.Plugin.Halovision +{ + public class SignalGenerator + { + + private SignalType signalType = SignalType.Sine; + /// + /// Signal Type. + /// + public SignalType SignalType + { + get { return signalType; } + set { signalType = value; } + } + + private float frequency = 1f; + /// + /// Signal Frequency. + /// + public float Frequency + { + get { return frequency; } + set { frequency = value; } + } + + private float phase = 0f; + /// + /// Signal Phase. + /// + public float Phase + { + get { return phase; } + set { phase = value; } + } + + private float amplitude = 1f; + /// + /// Signal Amplitude. + /// + public float Amplitude + { + get { return amplitude; } + set { amplitude = value; } + + } + + private float offset = 0f; + /// + /// Signal Offset. + /// + public float Offset + { + get { return offset; } + set { offset = value; } + } + + private float invert = 1; // Yes=-1, No=1 + /// + /// Signal Inverted? + /// + public bool Invert + { + get { return invert == -1; } + set { invert = value ? -1 : 1; } + } + + /// + /// Time the signal generator was started + /// + private long startTime = Stopwatch.GetTimestamp(); + + /// + /// Ticks per second on this CPU + /// + private long ticksPerSecond = Stopwatch.Frequency; + + public SignalGenerator(SignalType initialSignalType) + { + signalType = initialSignalType; + } + + public SignalGenerator() { } + + public float GetValue(float time) + { + float value = 0f; + float t = frequency * time + phase; + switch (signalType) + { + case SignalType.Sine: // sin( 2 * pi * t ) + value = (float)Math.Sin(2f * Math.PI * t); + break; + case SignalType.Square: // sign( sin( 2 * pi * t ) ) + value = Math.Sign(Math.Sin(2f * Math.PI * t)); + break; + case SignalType.Triangle: + // 2 * abs( t - 2 * floor( t / 2 ) - 1 ) - 1 + value = 1f - 4f * (float)Math.Abs + (Math.Round(t - 0.25f) - (t - 0.25f)); + break; + case SignalType.Sawtooth: + // 2 * ( t/a - floor( t/a + 1/2 ) ) + value = 2f * (t - (float)Math.Floor(t + 0.5f)); + break; + } + + return (invert * amplitude * value + offset); + } + + public float GetValue() + { + float time = (float)(Stopwatch.GetTimestamp() - startTime) + / ticksPerSecond; + return GetValue(time); + } + + public void Reset() + { + startTime = Stopwatch.GetTimestamp(); + } + + } + + public enum SignalType + { + Sine, + Square, + Triangle, + Sawtooth + } +} diff --git a/Halovision/VisionForm.designer.cs b/Halovision/VisionForm.designer.cs index c6585db..982e1dc 100644 --- a/Halovision/VisionForm.designer.cs +++ b/Halovision/VisionForm.designer.cs @@ -190,6 +190,7 @@ private void InitializeComponent() // tmrDiff // this.tmrDiff.Enabled = true; + this.tmrDiff.Interval = 20; this.tmrDiff.Tick += new System.EventHandler(this.tmrDiff_Tick); // // pbDifference diff --git a/Halovision/WaveNative.cs b/Halovision/WaveNative.cs new file mode 100644 index 0000000..c8a282b --- /dev/null +++ b/Halovision/WaveNative.cs @@ -0,0 +1,122 @@ +using System; +using System.Threading; +using System.Runtime.InteropServices; + +namespace lucidcode.LucidScribe.Plugin.Halovision.SoundViewer +{ + public enum WaveFormats + { + Pcm = 1, + Float = 3 + } + + [StructLayout(LayoutKind.Sequential)] + public class WaveFormat + { + public short wFormatTag; + public short nChannels; + public int nSamplesPerSec; + public int nAvgBytesPerSec; + public short nBlockAlign; + public short wBitsPerSample; + public short cbSize; + + public WaveFormat(int rate, int bits, int channels) + { + wFormatTag = (short)WaveFormats.Pcm; + nChannels = (short)channels; + nSamplesPerSec = rate; + wBitsPerSample = (short)bits; + cbSize = 0; + + nBlockAlign = (short)(channels * (bits / 8)); + nAvgBytesPerSec = nSamplesPerSec * nBlockAlign; + } + } + + internal class WaveNative + { + // consts + public const int MMSYSERR_NOERROR = 0; // no error + + public const int MM_WOM_OPEN = 0x3BB; + public const int MM_WOM_CLOSE = 0x3BC; + public const int MM_WOM_DONE = 0x3BD; + + public const int MM_WIM_OPEN = 0x3BE; + public const int MM_WIM_CLOSE = 0x3BF; + public const int MM_WIM_DATA = 0x3C0; + + public const int CALLBACK_FUNCTION = 0x00030000; // dwCallback is a FARPROC + + public const int TIME_MS = 0x0001; // time in milliseconds + public const int TIME_SAMPLES = 0x0002; // number of wave samples + public const int TIME_BYTES = 0x0004; // current byte offset + + // callbacks + public delegate void WaveDelegate(IntPtr hdrvr, int uMsg, int dwUser, ref WaveHdr wavhdr, int dwParam2); + + // structs + + [StructLayout(LayoutKind.Sequential)] + public struct WaveHdr + { + public IntPtr lpData; // pointer to locked data buffer + public int dwBufferLength; // length of data buffer + public int dwBytesRecorded; // used for input only + public IntPtr dwUser; // for client's use + public int dwFlags; // assorted flags (see defines) + public int dwLoops; // loop control counter + public IntPtr lpNext; // PWaveHdr, reserved for driver + public int reserved; // reserved for driver + } + + private const string mmdll = "winmm.dll"; + + // WaveOut calls + [DllImport(mmdll)] + public static extern int waveOutGetNumDevs(); + [DllImport(mmdll)] + public static extern int waveOutPrepareHeader(IntPtr hWaveOut, ref WaveHdr lpWaveOutHdr, int uSize); + [DllImport(mmdll)] + public static extern int waveOutUnprepareHeader(IntPtr hWaveOut, ref WaveHdr lpWaveOutHdr, int uSize); + [DllImport(mmdll)] + public static extern int waveOutWrite(IntPtr hWaveOut, ref WaveHdr lpWaveOutHdr, int uSize); + [DllImport(mmdll)] + public static extern int waveOutOpen(out IntPtr hWaveOut, int uDeviceID, WaveFormat lpFormat, WaveDelegate dwCallback, int dwInstance, int dwFlags); + [DllImport(mmdll)] + public static extern int waveOutReset(IntPtr hWaveOut); + [DllImport(mmdll)] + public static extern int waveOutClose(IntPtr hWaveOut); + [DllImport(mmdll)] + public static extern int waveOutPause(IntPtr hWaveOut); + [DllImport(mmdll)] + public static extern int waveOutRestart(IntPtr hWaveOut); + [DllImport(mmdll)] + public static extern int waveOutGetPosition(IntPtr hWaveOut, out int lpInfo, int uSize); + [DllImport(mmdll)] + public static extern int waveOutSetVolume(IntPtr hWaveOut, int dwVolume); + [DllImport(mmdll)] + public static extern int waveOutGetVolume(IntPtr hWaveOut, out int dwVolume); + + // WaveIn calls + [DllImport(mmdll)] + public static extern int waveInGetNumDevs(); + [DllImport(mmdll)] + public static extern int waveInAddBuffer(IntPtr hwi, ref WaveHdr pwh, int cbwh); + [DllImport(mmdll)] + public static extern int waveInClose(IntPtr hwi); + [DllImport(mmdll)] + public static extern int waveInOpen(out IntPtr phwi, int uDeviceID, WaveFormat lpFormat, WaveDelegate dwCallback, int dwInstance, int dwFlags); + [DllImport(mmdll)] + public static extern int waveInPrepareHeader(IntPtr hWaveIn, ref WaveHdr lpWaveInHdr, int uSize); + [DllImport(mmdll)] + public static extern int waveInUnprepareHeader(IntPtr hWaveIn, ref WaveHdr lpWaveInHdr, int uSize); + [DllImport(mmdll)] + public static extern int waveInReset(IntPtr hwi); + [DllImport(mmdll)] + public static extern int waveInStart(IntPtr hwi); + [DllImport(mmdll)] + public static extern int waveInStop(IntPtr hwi); + } +} diff --git a/Halovision/WaveOut.cs b/Halovision/WaveOut.cs new file mode 100644 index 0000000..a0fd524 --- /dev/null +++ b/Halovision/WaveOut.cs @@ -0,0 +1,241 @@ +using System; +using System.Threading; +using System.Runtime.InteropServices; + +namespace lucidcode.LucidScribe.Plugin.Halovision.SoundViewer +{ + internal class WaveOutHelper + { + public static void Try(int err) + { + if (err != WaveNative.MMSYSERR_NOERROR) + throw new Exception(err.ToString()); + } + } + + public delegate void BufferFillEventHandler(IntPtr data, int size); + + internal class WaveOutBuffer : IDisposable + { + public WaveOutBuffer NextBuffer; + + private AutoResetEvent m_PlayEvent = new AutoResetEvent(false); + private IntPtr m_WaveOut; + + private WaveNative.WaveHdr m_Header; + private byte[] m_HeaderData; + private GCHandle m_HeaderHandle; + private GCHandle m_HeaderDataHandle; + + private bool m_Playing; + + internal static void WaveOutProc(IntPtr hdrvr, int uMsg, int dwUser, ref WaveNative.WaveHdr wavhdr, int dwParam2) + { + if (uMsg == WaveNative.MM_WOM_DONE) + { + try + { + GCHandle h = (GCHandle)wavhdr.dwUser; + WaveOutBuffer buf = (WaveOutBuffer)h.Target; + buf.OnCompleted(); + } + catch + { + } + } + } + + public WaveOutBuffer(IntPtr waveOutHandle, int size) + { + m_WaveOut = waveOutHandle; + + m_HeaderHandle = GCHandle.Alloc(m_Header, GCHandleType.Pinned); + m_Header.dwUser = (IntPtr)GCHandle.Alloc(this); + m_HeaderData = new byte[size]; + m_HeaderDataHandle = GCHandle.Alloc(m_HeaderData, GCHandleType.Pinned); + m_Header.lpData = m_HeaderDataHandle.AddrOfPinnedObject(); + m_Header.dwBufferLength = size; + WaveOutHelper.Try(WaveNative.waveOutPrepareHeader(m_WaveOut, ref m_Header, Marshal.SizeOf(m_Header))); + } + ~WaveOutBuffer() + { + Dispose(); + } + public void Dispose() + { + if (m_Header.lpData != IntPtr.Zero) + { + WaveNative.waveOutUnprepareHeader(m_WaveOut, ref m_Header, Marshal.SizeOf(m_Header)); + m_HeaderHandle.Free(); + m_Header.lpData = IntPtr.Zero; + } + m_PlayEvent.Close(); + if (m_HeaderDataHandle.IsAllocated) + m_HeaderDataHandle.Free(); + GC.SuppressFinalize(this); + } + + public int Size + { + get { return m_Header.dwBufferLength; } + } + + public IntPtr Data + { + get { return m_Header.lpData; } + } + + public bool Play() + { + lock (this) + { + m_PlayEvent.Reset(); + m_Playing = WaveNative.waveOutWrite(m_WaveOut, ref m_Header, Marshal.SizeOf(m_Header)) == WaveNative.MMSYSERR_NOERROR; + return m_Playing; + } + } + public void WaitFor() + { + if (m_Playing) + { + m_Playing = m_PlayEvent.WaitOne(); + } + else + { + Thread.Sleep(0); + } + } + public void OnCompleted() + { + m_PlayEvent.Set(); + m_Playing = false; + } + } + + public class WaveOutPlayer : IDisposable + { + private IntPtr m_WaveOut; + private WaveOutBuffer m_Buffers; // linked list + private WaveOutBuffer m_CurrentBuffer; + private Thread m_Thread; + private BufferFillEventHandler m_FillProc; + private bool m_Finished; + private byte m_zero; + + private WaveNative.WaveDelegate m_BufferProc = new WaveNative.WaveDelegate(WaveOutBuffer.WaveOutProc); + + public static int DeviceCount + { + get { return WaveNative.waveOutGetNumDevs(); } + } + + public WaveOutPlayer(int device, WaveFormat format, int bufferSize, int bufferCount, BufferFillEventHandler fillProc) + { + m_zero = format.wBitsPerSample == 8 ? (byte)128 : (byte)0; + m_FillProc = fillProc; + WaveOutHelper.Try(WaveNative.waveOutOpen(out m_WaveOut, device, format, m_BufferProc, 0, WaveNative.CALLBACK_FUNCTION)); + AllocateBuffers(bufferSize, bufferCount); + m_Thread = new Thread(new ThreadStart(ThreadProc)); + m_Thread.Start(); + } + ~WaveOutPlayer() + { + Dispose(); + } + public void Dispose() + { + if (m_Thread != null) + try + { + m_Finished = true; + if (m_WaveOut != IntPtr.Zero) + WaveNative.waveOutReset(m_WaveOut); + m_Thread.Join(); + m_FillProc = null; + FreeBuffers(); + if (m_WaveOut != IntPtr.Zero) + WaveNative.waveOutClose(m_WaveOut); + } + finally + { + m_Thread = null; + m_WaveOut = IntPtr.Zero; + } + GC.SuppressFinalize(this); + } + private void ThreadProc() + { + while (!m_Finished) + { + Advance(); + if (m_FillProc != null && !m_Finished) + m_FillProc(m_CurrentBuffer.Data, m_CurrentBuffer.Size); + else + { + // zero out buffer + byte v = m_zero; + byte[] b = new byte[m_CurrentBuffer.Size]; + for (int i = 0; i < b.Length; i++) + b[i] = v; + Marshal.Copy(b, 0, m_CurrentBuffer.Data, b.Length); + + } + m_CurrentBuffer.Play(); + } + WaitForAllBuffers(); + } + private void AllocateBuffers(int bufferSize, int bufferCount) + { + FreeBuffers(); + if (bufferCount > 0) + { + m_Buffers = new WaveOutBuffer(m_WaveOut, bufferSize); + WaveOutBuffer Prev = m_Buffers; + try + { + for (int i = 1; i < bufferCount; i++) + { + WaveOutBuffer Buf = new WaveOutBuffer(m_WaveOut, bufferSize); + Prev.NextBuffer = Buf; + Prev = Buf; + } + } + finally + { + Prev.NextBuffer = m_Buffers; + } + } + } + private void FreeBuffers() + { + m_CurrentBuffer = null; + if (m_Buffers != null) + { + WaveOutBuffer First = m_Buffers; + m_Buffers = null; + + WaveOutBuffer Current = First; + do + { + WaveOutBuffer Next = Current.NextBuffer; + Current.Dispose(); + Current = Next; + } while (Current != First); + } + } + private void Advance() + { + m_CurrentBuffer = m_CurrentBuffer == null ? m_Buffers : m_CurrentBuffer.NextBuffer; + m_CurrentBuffer.WaitFor(); + } + private void WaitForAllBuffers() + { + WaveOutBuffer Buf = m_Buffers; + while (Buf.NextBuffer != m_Buffers) + { + Buf.WaitFor(); + Buf = Buf.NextBuffer; + } + } + } +} diff --git a/Halovision/packages.config b/Halovision/packages.config index b3de832..5d2f66e 100644 --- a/Halovision/packages.config +++ b/Halovision/packages.config @@ -9,12 +9,22 @@ + + + + + + + + + + diff --git a/Installer/Lucid Scribe Halovision.vdproj b/Installer/Lucid Scribe Halovision.vdproj index 0b47e19..a6f45a2 100644 --- a/Installer/Lucid Scribe Halovision.vdproj +++ b/Installer/Lucid Scribe Halovision.vdproj @@ -633,6 +633,12 @@ } "Entry" { + "MsmKey" = "8:_5294BB40EE33B2C3602EF328FF25AADE" + "OwnerKey" = "8:_395AC690E5F04358B866710FD743FFE4" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { "MsmKey" = "8:_53FD229DEDBBC6B6C38C5D53D2512E09" "OwnerKey" = "8:_395AC690E5F04358B866710FD743FFE4" "MsmSig" = "8:_UNDEFINED" @@ -2002,6 +2008,12 @@ "Entry" { "MsmKey" = "8:_UNDEFINED" + "OwnerKey" = "8:_5294BB40EE33B2C3602EF328FF25AADE" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_UNDEFINED" "OwnerKey" = "8:_9768C46742605F22AB604239F03E17DD" "MsmSig" = "8:_UNDEFINED" } @@ -5273,6 +5285,37 @@ "IsDependency" = "11:FALSE" "IsolateTo" = "8:" } + "{9F6F8455-1EF1-4B85-886A-4223BCC8E7F7}:_5294BB40EE33B2C3602EF328FF25AADE" + { + "AssemblyRegister" = "3:1" + "AssemblyIsInGAC" = "11:FALSE" + "AssemblyAsmDisplayName" = "8:lucidcode.LucidScribe.Interface.Illuminated, Version=1.0.4.0, Culture=neutral, processorArchitecture=MSIL" + "ScatterAssemblies" + { + "_5294BB40EE33B2C3602EF328FF25AADE" + { + "Name" = "8:lucidcode.LucidScribe.Interface.Illuminated.dll" + "Attributes" = "3:512" + } + } + "SourcePath" = "8:lucidcode.LucidScribe.Interface.Illuminated.dll" + "TargetName" = "8:" + "Tag" = "8:" + "Folder" = "8:_491A001224CF4D699EA475B2FB5F2890" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:TRUE" + "IsDependency" = "11:TRUE" + "IsolateTo" = "8:" + } "{9F6F8455-1EF1-4B85-886A-4223BCC8E7F7}:_53FD229DEDBBC6B6C38C5D53D2512E09" { "AssemblyRegister" = "3:1" @@ -10813,15 +10856,15 @@ { "Name" = "8:Microsoft Visual Studio" "ProductName" = "8:Lucid Scribe Halovision" - "ProductCode" = "8:{411774F8-3E0E-4CF2-9192-C614B596B336}" - "PackageCode" = "8:{29D970C5-AC16-4945-8EE1-803FDC2C989D}" + "ProductCode" = "8:{FCF5ED54-C369-448F-A2D6-782AF1035F52}" + "PackageCode" = "8:{07E5B406-9260-4E65-A99C-60379EA87339}" "UpgradeCode" = "8:{CAAB2187-AD23-435C-A3DB-568744247625}" "AspNetVersion" = "8:4.0.30319.0" "RestartWWWService" = "11:FALSE" "RemovePreviousVersions" = "11:TRUE" "DetectNewerInstalledVersion" = "11:TRUE" "InstallAllUsers" = "11:TRUE" - "ProductVersion" = "8:1.1.6" + "ProductVersion" = "8:1.1.7" "Manufacturer" = "8:lucidcode" "ARPHELPTELEPHONE" = "8:" "ARPHELPLINK" = "8:http://www.lucidcode.com/Contact"