| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132 |
- 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();
- }
- }
- }
- }
|