private async Task UpdateSends(System.Threading.CancellationToken newListener) { foreach (var kvpSpeaker in ConnectedChannels) { IAudioClient speaker = kvpSpeaker.Value; await speaker.SetSpeakingAsync(true); AudioOutStream speak = speaker.CreateDirectOpusStream(); Console.WriteLine("Speaker"); foreach (var kvpListener in ConnectedChannels.Where(c => !speaker.Equals(c))) { Console.WriteLine("Listener"); IAudioClient listener = kvpListener.Value; await kvpListener.Value.CreateOpusStream().CopyToAsync(speaker.CreateOpusStream()); var users = (await(listener as IVoiceChannel).GetUsersAsync().FlattenAsync()).Where(u => !u.IsBot); foreach (var user in users) { await ListenUserAsync(user).CopyToAsync(speak); } } await speak.WriteAsync(new byte[3840], newListener); await speaker.SetSpeakingAsync(false); } }
public async Task Play(IAudioClient voiceClient, CancellationToken cancelToken) { if (m_outStream == null) { m_outStream = voiceClient.CreateOpusStream(2000); } using (SongStream stream = new SongStream(m_outStream, m_info, cancelToken)) { await stream.StartStream(m_skipTo, 1.0f); await stream.FlushAsync(); } }
private async Task PlayWithConversionAsync(string path) { if (CancellationToken.IsCancellationRequested) { return; } using (var process = InputToOpus(path, application: AudioApplication.Music)) // TODO: Skip conversion if possible using (var source = process.StandardOutput.BaseStream) using (var destination = _audioClient.CreateOpusStream()) { if (process.HasExited || !source.CanRead) { return; } await source.CopyToAsync(destination, 1024, CancellationToken).ConfigureAwait(false); await destination.FlushAsync(CancellationToken).ConfigureAwait(false); } }
private async Task PlayMusic(IVoiceChannel channel, Playlist playlist) { var token = tokenSource.Token; PlayerState = PlayerState.Idle; VoiceChannel = channel; Playlist = playlist; playedSongs.Clear(); var logTag = $"[Music {VoiceChannel.GuildId}] "; logger.LogInformation($"{logTag}Starting music player in guild {Guild.Name}, channel {VoiceChannel.Name}"); ConnectionState = ConnectionState.Connecting; IAudioClient audioClient = null; AudioOutStream discordStream = null; try { audioClient = await VoiceChannel.ConnectAsync(); discordStream = audioClient.CreateOpusStream(); logger.LogDebug($"{logTag}Connected"); ConnectionState = ConnectionState.Connected; while (!token.IsCancellationRequested) { var songId = playlist.GetNextSong(); if (songId == null) { break; } logger.LogDebug($"{logTag}Playing next song (Id: {songId})"); var song = await musicService.GetSong(songId); if (song == null) { logger.LogWarning($"{logTag}Failed to get data for song id {songId}"); continue; } var playHistoryEntry = new PlayHistoryEntry { song = song, state = SongState.Playing }; var oggStream = await song.GetOggStream(); if (oggStream == null) { logger.LogWarning($"{logTag}Failed to get ogg stream for current song (Id: {songId})"); playHistoryEntry.state = SongState.Error; playedSongs.Add(playHistoryEntry); continue; } playedSongs.Add(playHistoryEntry); try { var opusStream = new OpusOggReadStream(null, oggStream); PlayerState = PlayerState.Playing; while (opusStream.HasNextPacket && !token.IsCancellationRequested) { var packet = opusStream.RetrieveNextPacket(); if (packet == null) { break; } await discordStream.WriteAsync(packet, 0, packet.Length); } playHistoryEntry.state = SongState.Finished; playedSongs[playedSongs.Count - 1] = playHistoryEntry; } catch (Exception ex) { logger.LogError(ex, $"{logTag}Exception while playing, skipping to next track"); playHistoryEntry.state = SongState.Error; playedSongs[playedSongs.Count - 1] = playHistoryEntry; } finally { oggStream.Dispose(); await discordStream.FlushAsync(); } PlayerState = PlayerState.Idle; } } catch (Exception ex) { logger.LogError(ex, $"{logTag}Exception in music player"); } finally { logger.LogInformation($"{logTag}Stopping music player"); VoiceChannel = null; Playlist = null; ConnectionState = ConnectionState.Disconnecting; discordStream?.Dispose(); if (audioClient != null) { audioClient.Disconnected -= ClientDisconnected; audioClient.Dispose(); } ConnectionState = ConnectionState.Disconnected; PlayerState = PlayerState.Disconnected; logger.LogDebug($"{logTag}Stopped music player"); } Task ClientDisconnected(Exception ex) { return(Task.Run(() => { if (ex != null) { logger.LogError(ex, "Audio client disconnected with exception"); } tokenSource.Cancel(); })); } }