Exemplo n.º 1
0
        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);
            }
        }
Exemplo n.º 2
0
        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();
            }
        }
Exemplo n.º 3
0
        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);
                    }
        }
Exemplo n.º 4
0
        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();
                }));
            }
        }