Move solution and projects to src
This commit is contained in:
132
src/Ryujinx.Audio/AudioManager.cs
Normal file
132
src/Ryujinx.Audio/AudioManager.cs
Normal file
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user