diff options
author | TSR Berry <20988865+TSRBerry@users.noreply.github.com> | 2023-04-08 01:22:00 +0200 |
---|---|---|
committer | Mary <thog@protonmail.com> | 2023-04-27 23:51:14 +0200 |
commit | cee712105850ac3385cd0091a923438167433f9f (patch) | |
tree | 4a5274b21d8b7f938c0d0ce18736d3f2993b11b1 /src/Ryujinx.Audio/AudioManager.cs | |
parent | cd124bda587ef09668a971fa1cac1c3f0cfc9f21 (diff) |
Move solution and projects to src
Diffstat (limited to 'src/Ryujinx.Audio/AudioManager.cs')
-rw-r--r-- | src/Ryujinx.Audio/AudioManager.cs | 132 |
1 files changed, 132 insertions, 0 deletions
diff --git a/src/Ryujinx.Audio/AudioManager.cs b/src/Ryujinx.Audio/AudioManager.cs new file mode 100644 index 00000000..c37ca4a3 --- /dev/null +++ b/src/Ryujinx.Audio/AudioManager.cs @@ -0,0 +1,132 @@ +using System; +using System.Threading; + +namespace Ryujinx.Audio +{ + /// <summary> + /// Manage audio input and output system. + /// </summary> + public class AudioManager : IDisposable + { + /// <summary> + /// Lock used to control the waiters registration. + /// </summary> + private object _lock = new object(); + + /// <summary> + /// Events signaled when the driver played audio buffers. + /// </summary> + private ManualResetEvent[] _updateRequiredEvents; + + /// <summary> + /// Action to execute when the driver played audio buffers. + /// </summary> + private Action[] _actions; + + /// <summary> + /// The worker thread in charge of handling sessions update. + /// </summary> + private Thread _workerThread; + + private bool _isRunning; + + /// <summary> + /// Create a new <see cref="AudioManager"/>. + /// </summary> + public AudioManager() + { + _updateRequiredEvents = new ManualResetEvent[2]; + _actions = new Action[2]; + _isRunning = false; + + // Termination event. + _updateRequiredEvents[1] = new ManualResetEvent(false); + + _workerThread = new Thread(Update) + { + Name = "AudioManager.Worker" + }; + } + + /// <summary> + /// Start the <see cref="AudioManager"/>. + /// </summary> + public void Start() + { + if (_workerThread.IsAlive) + { + throw new InvalidOperationException(); + } + + _isRunning = true; + _workerThread.Start(); + } + + /// <summary> + /// Initialize update handlers. + /// </summary> + /// <param name="updatedRequiredEvent ">The driver event that will get signaled by the device driver when an audio buffer finished playing/being captured</param> + /// <param name="outputCallback">The callback to call when an audio buffer finished playing</param> + /// <param name="inputCallback">The callback to call when an audio buffer was captured</param> + public void Initialize(ManualResetEvent updatedRequiredEvent, Action outputCallback, Action inputCallback) + { + lock (_lock) + { + _updateRequiredEvents[0] = updatedRequiredEvent; + _actions[0] = outputCallback; + _actions[1] = inputCallback; + } + } + + /// <summary> + /// Entrypoint of the <see cref="_workerThread"/> in charge of updating the <see cref="AudioManager"/>. + /// </summary> + private void Update() + { + while (_isRunning) + { + int index = WaitHandle.WaitAny(_updateRequiredEvents); + + // Last index is here to indicate thread termination. + if (index + 1 == _updateRequiredEvents.Length) + { + break; + } + + lock (_lock) + { + foreach (Action action in _actions) + { + action?.Invoke(); + } + + _updateRequiredEvents[0].Reset(); + } + } + } + + /// <summary> + /// Stop updating the <see cref="AudioManager"/> without stopping the worker thread. + /// </summary> + public void StopUpdates() + { + _isRunning = false; + } + + public void Dispose() + { + Dispose(true); + } + + protected virtual void Dispose(bool disposing) + { + if (disposing) + { + _updateRequiredEvents[1].Set(); + _workerThread.Join(); + + _updateRequiredEvents[1].Dispose(); + } + } + } +}
\ No newline at end of file |