From: <an...@us...> - 2008-01-07 00:49:44
|
Revision: 1217 http://mp-plugins.svn.sourceforge.net/mp-plugins/?rev=1217&view=rev Author: and-81 Date: 2008-01-06 16:49:42 -0800 (Sun, 06 Jan 2008) Log Message: ----------- Modified Paths: -------------- trunk/plugins/MCEReplacement/MCEReplacement.cs trunk/plugins/MCEReplacement/MCEReplacement.csproj Added Paths: ----------- trunk/plugins/MCEReplacement/GenericPCQueue.cs Added: trunk/plugins/MCEReplacement/GenericPCQueue.cs =================================================================== --- trunk/plugins/MCEReplacement/GenericPCQueue.cs (rev 0) +++ trunk/plugins/MCEReplacement/GenericPCQueue.cs 2008-01-07 00:49:42 UTC (rev 1217) @@ -0,0 +1,220 @@ +using System; +using System.Collections.Generic; +#if TRACE +using System.Diagnostics; +#endif +using System.Threading; + +namespace MediaPortal.Plugins +{ + + #region Delegates + + /// <summary> + /// Delegate for GenericPCQueue sink. + /// </summary> + /// <param name="obj">Generic object to process.</param> + public delegate void GenericPCQueueSink<T>(T obj); + + #endregion Delegates + + /// <summary> + /// Implements a thread-safe Producer/Consumer Queue for generics. + /// </summary> + public class GenericPCQueue<T> : IDisposable + { + + #region Variables + + Thread _workerThread; + Queue<T> _queue; + object _queueLock; + EventWaitHandle _queueWaitHandle; + volatile bool _processQueue; + + GenericPCQueueSink<T> _sink; + + #endregion Variables + + #region Constructor + + /// <summary> + /// Create a new MessageQueue. + /// </summary> + /// <param name="sink">Where to send dequeued messages.</param> + public GenericPCQueue(GenericPCQueueSink<T> sink) + { + if (sink == null) + throw new ArgumentNullException("sink"); + + _sink = sink; + + // Create locking and control mechanisms ... + _queueLock = new object(); + _queueWaitHandle = new AutoResetEvent(false); + + // Create FIFO generic queue + _queue = new Queue<T>(); + } + + #endregion Constructor + + #region IDisposable + + /// <summary> + /// Releases unmanaged and - optionally - managed resources + /// </summary> + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + /// <summary> + /// Releases unmanaged and - optionally - managed resources + /// </summary> + /// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param> + protected virtual void Dispose(bool disposing) + { + if (disposing) + { + // Dispose managed resources ... + Stop(); + + _workerThread = null; + + _queue.Clear(); + _queue = null; + + _queueLock = null; + + _queueWaitHandle.Close(); + _queueWaitHandle = null; + } + + // Free native resources ... + + } + + #endregion IDisposable + + #region Implementation + + /// <summary> + /// Start processing the queue. + /// </summary> + public void Start() + { + if (_processQueue) + return; + + _processQueue = true; + + // Create the worker thread ... + _workerThread = new Thread(new ThreadStart(WorkerThread)); + _workerThread.Name = "GenericPCQueue"; + _workerThread.IsBackground = true; + + _workerThread.Start(); + } + + /// <summary> + /// Stop processing the queue. + /// </summary> + public void Stop() + { + if (!_processQueue) + return; + + // Signal the worker thread to stop ... + _processQueue = false; + _queueWaitHandle.Set(); + + // Join the worker thread and wait for it to finish ... + if (_workerThread != null && _workerThread.IsAlive && !_workerThread.Join(1000)) + { + _workerThread.Abort(); + _workerThread.Join(); + } + + _workerThread = null; + } + + /// <summary> + /// Add a generic object to the queue. + /// </summary> + /// <param name="obj">Generic object to place in the queue.</param> + public void Enqueue(T obj) + { + if (obj == null) + throw new ArgumentNullException("obj"); + + lock (_queueLock) + { + _queue.Enqueue(obj); + + _queueWaitHandle.Set(); + } + } + + /// <summary> + /// Clears the queue of any messages. + /// </summary> + public void ClearQueue() + { + lock (_queueLock) + { + _queue.Clear(); + } + } + + /// <summary> + /// Queue processing worker thread. + /// </summary> + void WorkerThread() + { + try + { + T obj = default(T); + bool didDequeue = false; + + while (_processQueue) + { + lock (_queueLock) + { + if (_queue.Count > 0) + { + obj = _queue.Dequeue(); + didDequeue = true; + } + } + + if (didDequeue) + { + _sink(obj); + obj = default(T); + didDequeue = false; + } + else + { + _queueWaitHandle.WaitOne(); + } + } + } +#if TRACE + catch (ThreadAbortException threadAbortException) + { + Trace.WriteLine(threadAbortException.ToString()); + } +#else + catch (ThreadAbortException) + { + } +#endif + } + + #endregion Implementation + + } + +} Modified: trunk/plugins/MCEReplacement/MCEReplacement.cs =================================================================== --- trunk/plugins/MCEReplacement/MCEReplacement.cs 2008-01-07 00:48:54 UTC (rev 1216) +++ trunk/plugins/MCEReplacement/MCEReplacement.cs 2008-01-07 00:49:42 UTC (rev 1217) @@ -114,6 +114,8 @@ static Hashtable _macroStacks; + GenericPCQueue<string> _buttonQueue; + #endregion Variables #region Properties @@ -354,6 +356,9 @@ if (ControlExternalEnabled) LoadExternalConfigs(); + _buttonQueue = new GenericPCQueue<string>(ProcessRemoteButton); + _buttonQueue.Start(); + // Load MicrosoftMceTransceiver if (!MessageModeEnabled && (MCERemoteEnabled || DifferentRemoteEnabled)) { @@ -411,6 +416,9 @@ _mceTransceiver.Stop(); } + _buttonQueue.Stop(); + _buttonQueue.Dispose(); + if (LogVerbose) Log.Info("MCEReplacement: Stopped"); } @@ -796,11 +804,22 @@ } /// <summary> - /// Handles remote buttons received. + /// Queues remote buttons received. /// </summary> /// <param name="remoteButton">The remote button.</param> void RemoteButtonReceived(string remoteButton) { + Log.Debug("MCEReplacement: RemoteButtonReceived({0})", remoteButton); + _buttonQueue.Enqueue(remoteButton); + } + + /// <summary> + /// Handles remote buttons received. + /// </summary> + /// <param name="remoteButton">The remote button.</param> + void ProcessRemoteButton(string remoteButton) + { + Log.Debug("MCEReplacement: ProcessRemoteButton({0})", remoteButton); int keyCode = int.Parse(remoteButton); // Handle MCE Remote button presses ... @@ -1174,7 +1193,7 @@ string setName = MultiMaps[_multiMappingSet]; if (LogVerbose) - Log.Info("MCEReplacement: Multi-Mapping has changed to \"{0}\"", setName); + Log.Info("MCEReplacement: Multi-Mapping has cycled to \"{0}\"", setName); MPCommon.ShowNotifyDialog("Multi-Mapping", setName, 2); } @@ -1194,7 +1213,7 @@ for (int index = 0; index < MultiMaps.Length; index++) { - if (MultiMaps[index].Equals(multiMapping, StringComparison.OrdinalIgnoreCase)) + if (MultiMaps[index].Equals(multiMapping, StringComparison.CurrentCultureIgnoreCase)) { _multiMappingSet = index; @@ -1205,10 +1224,11 @@ Log.Info("MCEReplacement: Multi-Mapping has changed to \"{0}\"", setName); MPCommon.ShowNotifyDialog("Multi-Mapping", setName, 2); - return; } } + + Log.Warn("MCEReplacement: Could not find Multi-Mapping \"{0}\"", multiMapping); } /// <summary> @@ -1379,7 +1399,6 @@ } } - /// <summary> /// Loads the default remote button input handler. /// </summary> @@ -1615,6 +1634,14 @@ string ejectCommand = command.Substring(Common.CmdPrefixEject.Length); Common.ProcessEjectCommand(ejectCommand); } + else if (command.StartsWith(Common.CmdPrefixMultiMap, StringComparison.OrdinalIgnoreCase)) + { + string multiMapping = command.Substring(Common.CmdPrefixMultiMap.Length); + if (_inConfiguration) + MessageBox.Show(multiMapping, "Change multi-mapping", MessageBoxButtons.OK, MessageBoxIcon.Information); + else + ChangeMultiMapping(multiMapping); + } else if (command.StartsWith(Common.CmdPrefixPopup, StringComparison.OrdinalIgnoreCase)) { string[] commands = Common.SplitPopupCommand(command.Substring(Common.CmdPrefixPopup.Length)); Modified: trunk/plugins/MCEReplacement/MCEReplacement.csproj =================================================================== --- trunk/plugins/MCEReplacement/MCEReplacement.csproj 2008-01-07 00:48:54 UTC (rev 1216) +++ trunk/plugins/MCEReplacement/MCEReplacement.csproj 2008-01-07 00:49:42 UTC (rev 1217) @@ -94,6 +94,7 @@ <Compile Include="Forms\StbSetup.Designer.cs"> <DependentUpon>StbSetup.cs</DependentUpon> </Compile> + <Compile Include="GenericPCQueue.cs" /> <Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Forms\MultiMapNameBox.cs"> <SubType>Form</SubType> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |