Newer
Older
EARS-LINUX / program / SoundLopper.cs
using System;
using System.Diagnostics;
using System.IO;
using System.Threading;

public class SoundLooper : IDisposable
{
    private Process _proc;
    private Thread _thread;
    private volatile bool _running;
    private string _path;

    public event Action<string> Log;

    public bool IsPlaying { get { return _running; } }

    public void Start(string wavPath)
    {
        Stop();

        if (string.IsNullOrEmpty(wavPath) || !File.Exists(wavPath))
        {
            Emit("Sound file not found: " + wavPath);
            return;
        }

        _path = wavPath;
        _running = true;
        _thread = new Thread(LoopWorker);
        _thread.IsBackground = true;
        _thread.Start();
        Emit("Looping started: " + wavPath);
    }

    public void Stop()
    {
        if (!_running) return;
        _running = false;

        try
        {
            var p = _proc;
            if (p != null && !p.HasExited) p.Kill();
        }
        catch { }

        _proc = null;

        if (_thread != null && _thread.IsAlive)
            _thread.Join(500);

        _thread = null;
        Emit("Looping stopped");
    }

    private void LoopWorker()
    {
        while (_running)
        {
            try
            {
                var psi = new ProcessStartInfo
                {
                    FileName = PlayerCommand(),
                    Arguments = "\"" + _path + "\"",
                    UseShellExecute = false,
                    RedirectStandardError = true,
                    RedirectStandardOutput = true,
                    CreateNoWindow = true
                };

                _proc = Process.Start(psi);
                _proc.WaitForExit();
            }
            catch (Exception ex)
            {
                Emit("Playback error: " + ex.Message);
                _running = false;
                return;
            }
        }
    }

    private static string _player;
    private static string PlayerCommand()
    {
        if (_player != null) return _player;
        _player = Exists("paplay") ? "paplay" : "aplay";
        return _player;
    }

    private static bool Exists(string cmd)
    {
        try
        {
            var p = Process.Start(new ProcessStartInfo
            {
                FileName = "which",
                Arguments = cmd,
                UseShellExecute = false,
                RedirectStandardOutput = true
            });
            p.WaitForExit();
            return p.ExitCode == 0;
        }
        catch { return false; }
    }

    private void Emit(string msg)
    {
        var h = Log;
        if (h != null) h(msg);
        else Console.WriteLine("[SoundLooper] " + msg);
    }

    public void Dispose() { Stop(); }
}