2
0
mirror of https://github.com/9ParsonsB/Pulsar.git synced 2025-04-05 17:39:39 -04:00
2022-12-04 15:01:56 -03:30

142 lines
4.2 KiB
C#

using NetCoreAudio.Interfaces;
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Timers;
namespace NetCoreAudio.Players
{
internal class WindowsPlayer : IPlayer
{
[DllImport("winmm.dll")]
private static extern int mciSendString(string command, StringBuilder stringReturn, int returnLength, IntPtr hwndCallback);
[DllImport("winmm.dll")]
private static extern int mciGetErrorString(int errorCode, StringBuilder errorText, int errorTextSize);
[DllImport("winmm.dll")]
public static extern int waveOutSetVolume(IntPtr hwo, uint dwVolume);
private System.Timers.Timer _playbackTimer;
private Stopwatch _playStopwatch;
private string _fileName;
public event EventHandler PlaybackFinished;
public bool Playing { get; private set; }
public bool Paused { get; private set; }
public Task Play(string fileName)
{
_fileName = $"\"{fileName}\"";
_playbackTimer = new System.Timers.Timer
{
AutoReset = false
};
_playStopwatch = new Stopwatch();
ExecuteMciCommand($"Status {_fileName} Length");
ExecuteMciCommand($"Play {_fileName}");
Paused = false;
Playing = true;
_playbackTimer.Elapsed += HandlePlaybackFinished;
_playbackTimer.Start();
_playStopwatch.Start();
return Task.CompletedTask;
}
public Task Pause()
{
if (Playing && !Paused)
{
ExecuteMciCommand($"Pause {_fileName}");
Paused = true;
_playbackTimer.Stop();
_playStopwatch.Stop();
_playbackTimer.Interval -= _playStopwatch.ElapsedMilliseconds;
}
return Task.CompletedTask;
}
public Task Resume()
{
if (Playing && Paused)
{
ExecuteMciCommand($"Resume {_fileName}");
Paused = false;
_playbackTimer.Start();
_playStopwatch.Reset();
_playStopwatch.Start();
}
return Task.CompletedTask;
}
public Task Stop(bool force = false)
{
if (Playing || force)
{
ExecuteMciCommand($"Stop {_fileName}");
Playing = false;
Paused = false;
_playbackTimer?.Stop();
_playStopwatch?.Stop();
}
return Task.CompletedTask;
}
private void HandlePlaybackFinished(object sender, ElapsedEventArgs e)
{
Playing = false;
PlaybackFinished?.Invoke(this, e);
_playbackTimer?.Dispose();
_playbackTimer = null;
}
private Task ExecuteMciCommand(string commandString)
{
var sb = new StringBuilder();
var result = mciSendString(commandString, sb, 1024 * 1024, IntPtr.Zero);
if (result != 0)
{
var errorSb = new StringBuilder($"Error executing MCI command '{commandString}'. Error code: {result}.");
var sb2 = new StringBuilder(128);
mciGetErrorString(result, sb2, 128);
errorSb.Append($" Message: {sb2}");
throw new Exception(errorSb.ToString());
}
if (commandString.ToLower().StartsWith("status") && int.TryParse(sb.ToString(), out var length))
_playbackTimer.Interval = length + 75;
return Task.CompletedTask;
}
public Task SetVolume(byte percent)
{
// Calculate the volume that's being set
int NewVolume = ushort.MaxValue / 100 * percent;
// Set the same volume for both the left and the right channels
uint NewVolumeAllChannels = ((uint)NewVolume & 0x0000ffff) | ((uint)NewVolume << 16);
// Set the volume
waveOutSetVolume(IntPtr.Zero, NewVolumeAllChannels);
return Task.CompletedTask;
}
public void Dispose()
{
Stop().Wait();
ExecuteMciCommand("Close All");
}
}
}