using axXez.TS3.Audio; using axXez.TS3.Protocol; using System; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; namespace axXez.TS3 { /// /// High-level TeamSpeak voice connection. Extends with audio playback /// via . /// The counterpart to for the UDP voice protocol. /// public class VoiceConnection : VoiceClient, IDisposable { private readonly AudioPlayer _player; /// Handler raised when the current audio track finishes playing. public delegate void VoiceConnectionTrackEndedHandler(VoiceConnection sender); /// Raised when the current audio track finishes playing. public event VoiceConnectionTrackEndedHandler OnTrackEnded; public bool IsPlaying => _player.IsPlaying; public bool IsPaused => _player.IsPaused; public bool IsStreaming => _player.IsStreaming; public TimeSpan Position => _player.Position; public TimeSpan Duration => _player.Duration; public float Volume { get => _player.Volume; set => _player.Volume = value; } /// /// Creates a new . /// Throws if ffmpeg or yt-dlp are not installed. /// public VoiceConnection(string host, int port = 9987, string nickname = "Bot", VoiceIdentity identity = null, VoiceClientOptions options = null) : base(host, port, nickname, identity, options) { _player = new AudioPlayer(this); OnDisconnected += _ => _player.Stop(); _player.TrackEnded += () => OnTrackEnded?.Invoke(this); _player.Error += ex => GlobalLogger.LogError("VoiceConnection", $"Audio error in [{Nickname}]", ex); } /// Sends a graceful disconnect to the server and stops the voice client. public new void Stop() { if (State == VoiceClientState.Connected) Disconnect(); else base.Stop(); } /// Converts via ffmpeg and plays it. public Task PlayFileAsync(string filePath, CancellationToken ct = default) => _player.PlayFileAsync(filePath, ct); /// Resolves a YouTube URL via yt-dlp and streams the audio. public async Task PlayYouTubeAsync(string url, IReadOnlyList extraArgs = null, CancellationToken ct = default) { string direct = await YtDlp.ResolveAsync(url, extraArgs, ct); _player.PlayStream(direct); } /// Streams audio from a direct URL via ffmpeg. public void PlayStream(string url) => _player.PlayStream(url); public void PausePlayback() => _player.Pause(); public void ResumePlayback() => _player.Resume(); public void StopPlayback() => _player.Stop(); public void Seek(TimeSpan position) => _player.Seek(position); public void Dispose() { _player.Stop(); Stop(); } } }