public void PlayFile(IAudioClient ac, string path)
        {
            var process = Process.Start(new ProcessStartInfo
            { // FFmpeg requires us to spawn a process and hook into its stdout, so we will create a Process
                FileName  = "ffmpeg",
                Arguments = $"-i {path} " +
                            "-f s16le -ar 48000 -ac 2 pipe:1",
                UseShellExecute        = false,
                RedirectStandardOutput = true
            });

            Thread.Sleep(200); // Sleep for a few seconds to FFmpeg can start processing data.

            int blockSize = 3840;

            byte[] buffer = new byte[blockSize];
            int    byteCount;

            while (true)
            {
                byteCount = process.StandardOutput.BaseStream
                            .Read(buffer, 0, blockSize);

                if (byteCount == 0) // FFmpeg did not output anything
                {
                    break;          // Break out of the while(true) loop, since there was nothing to read.
                }
                ac.Send(buffer, 0, byteCount);
            }
            ac.Wait(); // Wait for the Voice Client to finish sending data
        }
Beispiel #2
0
        /// <summary>
        /// Send audio to the current _vClient channel
        /// </summary>
        /// <param name="path">Path of the .wav file to send</param>
        private void send(string path, Command current, IAudioClient _vClient)
        {
            int blockSize = 3840; // The size of bytes to read per frame; 1920 for mono

            try
            {
                using (FileStream f = File.Open(path, FileMode.Open))
                {
                    byte[] buffer = new byte[blockSize];
                    while (f.Read(buffer, 0, buffer.Length) > 0)
                    {
                        try { _vClient.Send(buffer, 0, buffer.Length); }
                        catch (Discord.Net.TimeoutException e)
                        {
                            log.Error("Error sending audio data: " + e.Message);
                        }
                    }

                    _vClient.Wait();
                    log.Info("Sent audio: " + path);
                }
            }
            catch (FileNotFoundException e) { log.Error(string.Format("Could not find file; ensure {0} is correct path", path)); }
            catch (Exception e) { log.Error(e); }
        }
Beispiel #3
0
        public static async Task PlayMusic(IAudioClient voiceClient, string file)
        {
            var ffmpegProcess = new ProcessStartInfo();

            ffmpegProcess.FileName = @"C:\FFMPEG\bin\ffmpeg.exe";
            ffmpegProcess.Arguments = $"-i {file} -f s16le -ar 48000 -ac 2 pipe:1 -loglevel quiet";
            ffmpegProcess.UseShellExecute = false;
            ffmpegProcess.RedirectStandardOutput = true;

            var p = Process.Start(ffmpegProcess);

            await Task.Delay(1000); //give it 2 seconds to get some dataz
            int blockSize = 3840; // 1920 for mono
            byte[] buffer = new byte[blockSize];
            int read;
            while (!MilliaBot.IsSkipSong)
            {
                read = p.StandardOutput.BaseStream.Read(buffer, 0, blockSize);
                if (read == 0 || MilliaBot.IsSkipSong)
                {
                    MilliaBot.IsSkipSong = false;
                    await Task.Delay(1000);
                    break; //nothing to read
                }
                voiceClient.Send(buffer, 0, read);
            }
            voiceClient.Wait();
        }
        /// <summary>
        /// Plays an mp3 file in the current voiceChannel
        /// </summary>
        /// <param name="filePath">Path for mp3 file</param>
        private void SendAudio(string filePath)
        {
            voiceClient.Wait();
            var channelCount = client.GetService <AudioService>().Config.Channels;         // Get the number of AudioChannels our AudioService has been configured to use.
            var OutFormat    = new WaveFormat(48000, 16, channelCount);                    // Create a new Output Format, using the spec that Discord will accept, and with the number of channels that our client supports.

            using (var MP3Reader = new Mp3FileReader(filePath))                            // Create a new Disposable MP3FileReader, to read audio from the filePath parameter
                using (var resampler = new MediaFoundationResampler(MP3Reader, OutFormat)) // Create a Disposable Resampler, which will convert the read MP3 data to PCM, using our Output Format
                {
                    resampler.ResamplerQuality = 60;                                       // Set the quality of the resampler to 60, the highest quality
                    int    blockSize = OutFormat.AverageBytesPerSecond / 50;               // Establish the size of our AudioBuffer
                    byte[] buffer    = new byte[blockSize];
                    int    byteCount;

                    while ((byteCount = resampler.Read(buffer, 0, blockSize)) > 0) // Read audio into our buffer, and keep a loop open while data is present
                    {
                        if (byteCount < blockSize)
                        {
                            // Incomplete Frame
                            for (int i = byteCount; i < blockSize; i++)
                            {
                                buffer[i] = 0;
                            }
                        }
                        voiceClient.Send(buffer, 0, blockSize); // Send the buffer to Discord
                    }
                }
        }
Beispiel #5
0
        private void SendAudioData(IAudioClient audioClient, PlayRequest request)
        {
            try
            {
                var file = request.File;
                var cancellationToken = request.TokenSource.Token;

                using (var reader = File.OpenRead(file))
                {
                    byte[] buffer = new byte[BLOCK_SIZE];
                    int    byteCount;

                    while ((byteCount = reader.Read(buffer, 0, BLOCK_SIZE)) > 0)
                    {
                        if (cancellationToken.IsCancellationRequested)
                        {
                            audioClient.Clear();
                            return;
                        }

                        audioClient.Send(buffer, 0, byteCount);
                    }
                }

                audioClient.Wait();
            }
            catch (Exception ex)
            {
                Logger.Error(ex.Message, ex);
            }
        }
Beispiel #6
0
        private async Task SendSound(string song)
        {
            if (!_playing)
            {
                _vclient = await _client.GetService <AudioService>().Join(channel);

                _playing = true;
            }
            _skipThis = false;
            await Task.Run(() =>
            {
                int channelCount     = _client.GetService <AudioService>().Config.Channels;
                WaveFormat outFormat = new WaveFormat(48000, 16, channelCount);
                AudioFileReader r    = new AudioFileReader(song);
                using (MediaFoundationResampler resampler = new MediaFoundationResampler(r, outFormat))
                {
                    resampler.ResamplerQuality = 60;
                    int blockSize = outFormat.AverageBytesPerSecond / 50;
                    byte[] buffer = new byte[blockSize];
                    int byteCount;

                    while ((byteCount = resampler.Read(buffer, 0, blockSize)) > 0 && _playing == true)
                    {
                        r.Volume = volume;
                        if (byteCount < blockSize)
                        {
                            // Incomplete Frame
                            for (int i = byteCount; i < blockSize; i++)
                            {
                                buffer[i] = 0;
                                if (_skipThis)
                                {
                                    _vclient.Clear();
                                    break;
                                }
                            }
                        }
                        _vclient.Send(buffer, 0, blockSize);
                        _vclient.Wait();
                    }

                    GetNextSong();
                }
            });
        }
Beispiel #7
0
        internal async Task Play(IAudioClient voiceClient, CancellationToken cancelToken)
        {
            var       bufferTask     = BufferSong(cancelToken).ConfigureAwait(false);
            var       bufferAttempts = 0;
            const int waitPerAttempt = 500;
            var       toAttemptTimes = SongInfo.ProviderType != MusicType.Normal ? 5 : 9;

            while (!prebufferingComplete && bufferAttempts++ < toAttemptTimes)
            {
                await Task.Delay(waitPerAttempt, cancelToken).ConfigureAwait(false);
            }
            cancelToken.ThrowIfCancellationRequested();
            Console.WriteLine($"Prebuffering done? in {waitPerAttempt * bufferAttempts}");
            const int blockSize = 3840;
            var       attempt   = 0;

            while (!cancelToken.IsCancellationRequested)
            {
                //Console.WriteLine($"Read: {songBuffer.ReadPosition}\nWrite: {songBuffer.WritePosition}\nContentLength:{songBuffer.ContentLength}\n---------");
                byte[] buffer = new byte[blockSize];
                var    read   = songBuffer.Read(buffer, blockSize);
                unchecked
                {
                    bytesSent += (ulong)read;
                }
                if (read == 0)
                {
                    if (attempt++ == 20)
                    {
                        voiceClient.Wait();
                        Console.WriteLine($"Song finished. [{songBuffer.ContentLength}]");
                        break;
                    }
                    else
                    {
                        await Task.Delay(100, cancelToken).ConfigureAwait(false);
                    }
                }
                else
                {
                    attempt = 0;
                }

                while (this.MusicPlayer.Paused)
                {
                    await Task.Delay(200, cancelToken).ConfigureAwait(false);
                }
                buffer = AdjustVolume(buffer, MusicPlayer.Volume);
                voiceClient.Send(buffer, 0, read);
            }
            Console.WriteLine("Awiting buffer task");
            await bufferTask;

            Console.WriteLine("Buffer task done.");
            voiceClient.Clear();
            cancelToken.ThrowIfCancellationRequested();
        }
Beispiel #8
0
            public async Task StartPlaylist()
            {
                if (IsPlaying)
                {
                    return;
                }

                if (await IsPlaylistEmpty())
                {
                    return;
                }

                if (PlaybackChannel == null)
                {
                    await ChatChannel.SafeSendMessage("Audio playback channel has not been set.");

                    return;
                }

                if (!await DiscordUtils.CanJoinAndTalkInVoiceChannel(PlaybackChannel, ChatChannel))
                {
                    return;
                }

                _voiceClient = await _client.Audio().Join(PlaybackChannel);

                while (true)
                {
                    if (_stopPlaylistFlag)
                    {
                        _stopPlaylistFlag = false;
                        break;
                    }

                    if (await IsPlaylistEmpty())
                    {
                        return;
                    }

                    await StartCurrentTrackPlayback();

                    if (_prevFlag)
                    {
                        _prevFlag = false;
                        TrackIndex--;
                    }
                    else if (!_skipToFlag)
                    {
                        TrackIndex++;
                    }
                }

                _voiceClient.Wait();
                await _voiceClient.Disconnect();
            }
Beispiel #9
0
        internal async Task Play(IAudioClient voiceClient, CancellationToken cancelToken)
        {
            var t = BufferSong(cancelToken).ConfigureAwait(false);
            int bufferAttempts = 0;
            int waitPerAttempt = 500;
            int toAttemptTimes = SongInfo.ProviderType != MusicType.Normal ? 5 : 9;

            while (!prebufferingComplete && bufferAttempts++ < toAttemptTimes)
            {
                await Task.Delay(waitPerAttempt);
            }
            Console.WriteLine($"Prebuffering done? in {waitPerAttempt * bufferAttempts}");
            int blockSize = 3840;

            byte[] buffer  = new byte[blockSize];
            int    attempt = 0;

            while (!cancelToken.IsCancellationRequested)
            {
                //Console.WriteLine($"Read: {songBuffer.ReadPosition}\nWrite: {songBuffer.WritePosition}\nContentLength:{songBuffer.ContentLength}\n---------");
                int read = songBuffer.Read(buffer, blockSize);
                if (read == 0)
                {
                    if (attempt++ == 10)
                    {
                        voiceClient.Wait();
                        Console.WriteLine("Playing done.");
                        return;
                    }
                    else
                    {
                        await Task.Delay(50);
                    }
                }
                else
                {
                    attempt = 0;
                }

                while (this.MusicPlayer.Paused)
                {
                    await Task.Delay(200);
                }
                buffer = adjustVolume(buffer, MusicPlayer.Volume);
                voiceClient.Send(buffer, 0, read);
            }
            //try {
            //    voiceClient.Clear();
            //    Console.WriteLine("CLEARED");
            //}
            //catch {
            //    Console.WriteLine("CLEAR FAILED!!!");
            //}
        }
Beispiel #10
0
        private void PlayYouTube(IAudioClient audioClient, string youtubeURL)
        {
            IEnumerable <VideoInfo> downloadUrls = DownloadUrlResolver.GetDownloadUrls(youtubeURL);
            VideoInfo targetVideoInfo            = downloadUrls.First(info => info.VideoType == VideoType.Mp4 && info.Resolution == 720);

            if (targetVideoInfo.RequiresDecryption)
            {
                DownloadUrlResolver.DecryptDownloadUrl(targetVideoInfo);
            }
            Console.WriteLine("Found download url {0}", targetVideoInfo.DownloadUrl);

            Process process = Process.Start(new ProcessStartInfo
            {
                FileName               = "ffmpeg",
                Arguments              = $"-i {targetVideoInfo.DownloadUrl} -f s16le -ar 48000 -ac 2 pipe:1",
                UseShellExecute        = false,
                RedirectStandardOutput = true
            });

            Console.WriteLine("Started ffmpeg");
            Thread.Sleep(5000);

            int blockSize = 3840;

            byte[] buffer = new byte[blockSize];
            int    byteCount;


            while (!shouldStop)
            {
                byteCount = process.StandardOutput.BaseStream.Read(buffer, 0, blockSize);

                if (byteCount == 0)
                {
                    break;
                }

                audioClient.Send(buffer, 0, byteCount);
            }
            audioClient.Wait();

            if (shouldStop)
            {
                process.Kill();
                shouldStop = false;
                audioClient.Disconnect();
            }
        }
Beispiel #11
0
        // Streaming service for youtube audio stream
        public async Task YoutubeStream(string pathOrUrl, CommandEventArgs e)
        {
            Process process = Process.Start(new ProcessStartInfo
            {                                                  // FFmpeg requires us to spawn a process and hook into its stdout, so we will create a Process
                FileName  = "ffmpeg",
                Arguments = $"-i {pathOrUrl} " +               // Here we provide a list of arguments to feed into FFmpeg. -i means the location of the file/URL it will read from
                            "-f s16le -ar 48000 -ac 2 pipe:1", // Next, we tell it to output 16-bit 48000Hz PCM, over 2 channels, to stdout.
                UseShellExecute        = false,
                RedirectStandardOutput = true                  // Capture the stdout of the process
            });

            Thread.Sleep(2000);     // Sleep for a few seconds to FFmpeg can start processing data.

            int blockSize = 3840;   // The size of bytes to read per frame; 1920 for mono

            byte[] buffer = new byte[blockSize];
            int    byteCount;

            while (true)                                      // Loop forever, so data will always be read
            {
                byteCount = process.StandardOutput.BaseStream // Access the underlying MemoryStream from the stdout of FFmpeg
                            .Read(buffer, 0, blockSize);      // Read stdout into the buffer

                int breaklimit = 0;
                while (byteCount == 0 /*&& breaklimit != 5*/)     // counter for failed attempts and sleeps so ffmpeg can read more audio
                {
                    Thread.Sleep(2500);
                    breaklimit++;
                }


                _audio.Send(buffer, 0, byteCount); // Send our data to Discord
                if (breaklimit == 6)               // when the breaklimit reaches 6 failed attempts its fair to say that ffmpeg has either crashed or is finished with the song
                {
                    break;                         // breaks the audio stream
                }
            }
            _audio.Wait();     // Wait for the Voice Client to finish sending data, as ffMPEG may have already finished buffering out a song, and it is unsafe to return now.

            await NextSong(e); // starts the stream for the next song
        }
Beispiel #12
0
        public static void Play(Music MusicToPlay)
        {
            int        channelCount = Program._client.GetService <AudioService>().Config.Channels; // Get the number of AudioChannels our AudioService has been configured to use.
            WaveFormat OutFormat    = new WaveFormat(SampleRate, 16, channelCount);                // Create a new Output Format, using the spec that Discord will accept, and with the number of channels that our client supports.

            try
            {
                mediaStream = new WaveChannel32(new MediaFoundationReader(MusicToPlay.FilePath), Volume, 0F);
                using (mediaStream)
                    using (resampler = new MediaFoundationResampler(mediaStream, OutFormat)) // Create a Disposable Resampler, which will convert the read MP3 data to PCM, using our Output Format
                    {
                        resampler.ResamplerQuality = 60;                                     // Set the quality of the resampler to 60, the highest quality
                        int    blockSize = OutFormat.AverageBytesPerSecond / 50;             // Establish the size of our AudioBuffer
                        byte[] buffer    = new byte[blockSize];
                        int    byteCount;

                        while ((byteCount = resampler.Read(buffer, 0, blockSize)) > 0) // Read audio into our buffer, and keep a loop open while data is present
                        {
                            if (byteCount < blockSize)
                            {
                                // Incomplete Frame
                                for (int i = byteCount; i < blockSize; i++)
                                {
                                    buffer[i] = 0;
                                }
                            }
                            _vClient.Send(buffer, 0, blockSize); // Send the buffer to Discord
                        }
                    }
            }
            catch (Exception ReaderException)
            {
                Console.WriteLine(ReaderException.Message); // Prints any errors to console
            }

            _vClient.Wait(); // Waits for the currently playing sound file to end.
        }
Beispiel #13
0
        internal async Task Play(IAudioClient voiceClient, CancellationToken cancelToken)
        {
            var filename = Path.Combine(MusicModule.MusicDataPath, DateTime.Now.UnixTimestamp().ToString());

            SongBuffer sb         = new SongBuffer(filename, SongInfo, skipTo);
            var        bufferTask = sb.BufferSong(cancelToken).ConfigureAwait(false);

            var inStream = new FileStream(sb.GetNextFile(), FileMode.OpenOrCreate, FileAccess.Read, FileShare.Write);;

            bytesSent = 0;

            try
            {
                var attempt = 0;

                var prebufferingTask = CheckPrebufferingAsync(inStream, sb, cancelToken);
                var sw = new Stopwatch();
                sw.Start();
                var t = await Task.WhenAny(prebufferingTask, Task.Delay(5000, cancelToken));

                if (t != prebufferingTask)
                {
                    Console.WriteLine("Prebuffering timed out or canceled. Cannot get any data from the stream.");
                    return;
                }
                else if (prebufferingTask.IsCanceled)
                {
                    Console.WriteLine("Prebuffering timed out. Cannot get any data from the stream.");
                    return;
                }
                sw.Stop();
                Console.WriteLine("Prebuffering successfully completed in " + sw.Elapsed);

                const int blockSize = 3840;
                byte[]    buffer    = new byte[blockSize];
                while (!cancelToken.IsCancellationRequested)
                {
                    //Console.WriteLine($"Read: {songBuffer.ReadPosition}\nWrite: {songBuffer.WritePosition}\nContentLength:{songBuffer.ContentLength}\n---------");
                    var read = inStream.Read(buffer, 0, buffer.Length);
                    //await inStream.CopyToAsync(voiceClient.OutputStream);
                    unchecked
                    {
                        bytesSent += (ulong)read;
                    }
                    if (read < blockSize)
                    {
                        if (sb.IsNextFileReady())
                        {
                            inStream.Dispose();
                            inStream = new FileStream(sb.GetNextFile(), FileMode.Open, FileAccess.Read, FileShare.Write);
                            read    += inStream.Read(buffer, read, buffer.Length - read);
                            attempt  = 0;
                        }
                        if (read == 0)
                        {
                            if (sb.BufferingCompleted)
                            {
                                break;
                            }
                            if (attempt++ == 20)
                            {
                                voiceClient.Wait();
                                MusicPlayer.SongCancelSource.Cancel();
                                break;
                            }
                            else
                            {
                                await Task.Delay(100, cancelToken).ConfigureAwait(false);
                            }
                        }
                        else
                        {
                            attempt = 0;
                        }
                    }
                    else
                    {
                        attempt = 0;
                    }

                    while (this.MusicPlayer.Paused)
                    {
                        await Task.Delay(200, cancelToken).ConfigureAwait(false);
                    }

                    buffer = AdjustVolume(buffer, MusicPlayer.Volume);
                    voiceClient.Send(buffer, 0, read);
                }
            }
            finally
            {
                await bufferTask;
                await Task.Run(() => voiceClient.Clear());

                if (inStream != null)
                {
                    inStream.Dispose();
                }
                Console.WriteLine("l");
                sb.CleanFiles();
            }
        }
Beispiel #14
0
        internal async Task Play(IAudioClient voiceClient, CancellationToken cancelToken)
        {
            var bufferTask = BufferSong(cancelToken).ConfigureAwait(false);
            var bufferAttempts = 0;
            const int waitPerAttempt = 500;
            var toAttemptTimes = SongInfo.ProviderType != MusicType.Normal ? 5 : 9;
            while (!prebufferingComplete && bufferAttempts++ < toAttemptTimes)
            {
                await Task.Delay(waitPerAttempt, cancelToken);
            }
            cancelToken.ThrowIfCancellationRequested();
            Console.WriteLine($"Prebuffering done? in {waitPerAttempt * bufferAttempts}");
            const int blockSize = 3840;
            var attempt = 0;
            while (!cancelToken.IsCancellationRequested)
            {
                //Console.WriteLine($"Read: {songBuffer.ReadPosition}\nWrite: {songBuffer.WritePosition}\nContentLength:{songBuffer.ContentLength}\n---------");
                byte[] buffer = new byte[blockSize];
                var read = songBuffer.Read(buffer, blockSize);
                unchecked
                {
                    bytesSent += (ulong)read;
                }
                if (read == 0)
                    if (attempt++ == 20)
                    {
                        voiceClient.Wait();
                        Console.WriteLine($"Song finished. [{songBuffer.ContentLength}]");
                        break;
                    }
                    else
                        await Task.Delay(100, cancelToken);
                else
                    attempt = 0;

                while (this.MusicPlayer.Paused)
                    await Task.Delay(200, cancelToken);
                buffer = AdjustVolume(buffer, MusicPlayer.Volume);
                voiceClient.Send(buffer, 0, read);
            }
            Console.WriteLine("Awiting buffer task");
            await bufferTask;
            Console.WriteLine("Buffer task done.");
            voiceClient.Clear();
            cancelToken.ThrowIfCancellationRequested();
        }
Beispiel #15
0
        //m r,radio - init
        //m n,next - next in que
        //m p,pause - pauses, call again to unpause
        //m yq [key_words] - queue from yt by keywords
        //m s,stop - stop
        //m sh - shuffle songs
        //m pl - current playlist

        public override void Install(ModuleManager manager)
        {
            var client = NadekoBot.client;

            manager.CreateCommands("!m", cgb => {
                //queue all more complex commands
                commands.ForEach(cmd => cmd.Init(cgb));

                cgb.CreateCommand("n")
                .Alias("next")
                .Description("Goes to the next song in the queue.")
                .Do(e => {
                    if (Voice != null && Exit == false)
                    {
                        NextSong = true;
                    }
                });

                cgb.CreateCommand("s")
                .Alias("stop")
                .Description("Completely stops the music and unbinds the bot from the channel.")
                .Do(e => {
                    if (Voice != null && Exit == false)
                    {
                        Exit      = true;
                        SongQueue = new List <YouTubeVideo>();
                    }
                });

                cgb.CreateCommand("p")
                .Alias("pause")
                .Description("Pauses the song")
                .Do(async e => {
                    if (Voice != null && Exit == false && CurrentSong != null)
                    {
                        Pause = !Pause;
                        if (Pause)
                        {
                            await e.Send("Pausing. Run the command again to resume.");
                        }
                        else
                        {
                            await e.Send("Resuming...");
                        }
                    }
                });

                cgb.CreateCommand("q")
                .Alias("yq")
                .Description("Queue a song using a multi/single word name.\n**Usage**: `!m q Dream Of Venice`")
                .Parameter("Query", ParameterType.Unparsed)
                .Do(async e => {
                    var youtube = YouTube.Default;
                    var video   = youtube.GetAllVideos(Searches.FindYoutubeUrlByKeywords(e.Args[0]))
                                  .Where(v => v.AdaptiveKind == AdaptiveKind.Audio)
                                  .OrderByDescending(v => v.AudioBitrate).FirstOrDefault();

                    if (video?.Uri != "" && video.Uri != null)
                    {
                        SongQueue.Add(video);
                        if (SongQueue.Count > 1)
                        {
                            await e.Send("**Queued** " + video.FullName);
                        }
                    }
                });

                cgb.CreateCommand("lq")
                .Alias("ls").Alias("lp")
                .Description("Lists up to 10 currently queued songs.")
                .Do(async e => {
                    await e.Send(SongQueue.Count + " videos currently queued.");
                    await e.Send(string.Join("\n", SongQueue.Select(v => v.FullName).Take(10)));
                });

                cgb.CreateCommand("sh")
                .Description("Shuffles the current playlist.")
                .Do(async e => {
                    if (SongQueue.Count < 2)
                    {
                        await e.Send("Not enough songs in order to perform the shuffle.");
                        return;
                    }

                    SongQueue.Shuffle();
                    await e.Send("Songs shuffled!");
                });

                cgb.CreateCommand("radio")
                .Alias("music")
                .Description("Binds to a voice and text channel in order to play music.")
                .Parameter("ChannelName", ParameterType.Unparsed)
                .Do(async e => {
                    if (Voice != null)
                    {
                        return;
                    }
                    VoiceChannel = e.Server.FindChannels(e.GetArg("ChannelName").Trim(), ChannelType.Voice).FirstOrDefault();
                    Voice        = await client.Audio().Join(VoiceChannel);
                    Exit         = false;
                    NextSong     = false;
                    Pause        = false;
                    try {
                        while (true)
                        {
                            if (Exit)
                            {
                                break;
                            }
                            if (SongQueue.Count == 0 || Pause)
                            {
                                Thread.Sleep(100); continue;
                            }
                            if (!LoadNextSong())
                            {
                                break;
                            }

                            await Task.Run(async() => {
                                if (Exit)
                                {
                                    Voice = null;
                                    Exit  = false;
                                    await e.Send("Exiting...");
                                    return;
                                }

                                var streamer = new AudioStreamer(Music.CurrentSong.Uri);
                                streamer.Start();
                                while (streamer.BytesSentToTranscoder < 100 * 0x1000 || streamer.NetworkDone)
                                {
                                    await Task.Delay(500);
                                }

                                int blockSize = 1920 * client.Audio().Config.Channels;
                                byte[] buffer = new byte[blockSize];

                                var msg     = await e.Send("Playing " + Music.CurrentSong.FullName + " [00:00]");
                                int counter = 0;
                                int byteCount;

                                while ((byteCount = streamer.PCMOutput.Read(buffer, 0, blockSize)) > 0)
                                {
                                    Voice.Send(buffer, byteCount);
                                    counter += blockSize;
                                    if (NextSong)
                                    {
                                        NextSong = false;
                                        break;
                                    }
                                    if (Exit)
                                    {
                                        Exit = false;
                                        return;
                                    }
                                    while (Pause)
                                    {
                                        Thread.Sleep(100);
                                    }
                                }
                            });
                        }
                        Voice.Wait();
                    } catch (Exception ex) { Console.WriteLine(ex.ToString()); }
                    await Voice.Disconnect();
                    Voice        = null;
                    VoiceChannel = null;
                });
            });
        }
Beispiel #16
0
        public async void SendOnlineAudio(CommandEventArgs e, string pathOrUrl)
        {
            try
            {
                await joinVoiceChannel(e);
            }
            catch (Exception ex)
            {
                Console.WriteLine("WARNING: Bot failed!");
                e.Channel.SendMessage("ERROR: Bot failed");
                return;
            }

            if (!isInSameVoice(e))
            {
                e.Channel.SendMessage("You are not in the same voice as me!");
                return;
            }

            YouTubeVideo ytVideo = new YouTubeVideo(pathOrUrl, e.User.Name);

            //Couldn't find a video so do not add
            if (ytVideo.title == "")
            {
                e.Channel.SendMessage("Could not find video!");
                return;
            }

            if (playingSong)
            {
                queue.Enqueue(ytVideo);
                sendMessage(ytVideo.requester + " added `" + ytVideo.title + "` **" + ytVideo.duration + "** to the queue! **[" + queue.Count + "]**");
                return;
            }

            currentSong = ytVideo;

            if (_vClient == null)
            {
                e.Channel.SendMessage("You are not in a voice channel!");
                return;
            }

            playingSong = true;
            sendMessage("Playing `" + currentSong.title + "` **" + currentSong.duration + "**");

            var process = Process.Start(new ProcessStartInfo
            {                                                                                                                                                                                           // FFmpeg requires us to spawn a process and hook into its stdout, so we will create a Process
                FileName               = "cmd.exe",
                Arguments              = "/C youtube-dl.exe -f 140  -o - " + pathOrUrl + " -q -i | ffmpeg.exe -i pipe:0 -f s16le -ar 48000 -ac 2 pipe:1 -af \"volume=" + volume + "\" -loglevel quiet", // Next, we tell it to output 16-bit 48000Hz PCM, over 2 channels, to stdout.
                UseShellExecute        = false,
                RedirectStandardOutput = true,                                                                                                                                                          // Capture the stdout of the process
                RedirectStandardError  = false,
            });

            //Thread.Sleep(1500); // Sleep for a few seconds to FFmpeg can start processing data.

            int blockSize = 3840; // The size of bytes to read per frame; 1920 for mono

            byte[] buffer = new byte[blockSize];
            int    byteCount;

            while (playingSong) // Loop forever, so data will always be read
            {
                if (!playingSong || process.HasExited)
                {
                    Console.WriteLine("task canceled");
                    break;
                }

                byteCount = process.StandardOutput.BaseStream // Access the underlying MemoryStream from the stdout of FFmpeg
                            .Read(buffer, 0, blockSize);      // Read stdout into the buffer


                if (byteCount == 0) // FFmpeg did not output anything
                {
                    break;          // Break out of the while(true) loop, since there was nothing to read.
                }
                try
                {
                    _vClient.Send(buffer, 0, byteCount); // Send our data to Discord
                }
                catch (OperationCanceledException ex)
                {
                    Console.WriteLine("Operation cancelled!");
                    break;
                }
            }

            _vClient.Clear();
            try {
                _vClient.Wait(); // Wait for the Voice Client to finish sending data, as ffMPEG may have already finished buffering out a song, and it is unsafe to return now.
            }catch (OperationCanceledException ex)
            {
                Console.WriteLine("Operation canceled");
            }
            if (!process.HasExited)
            {
                process.Kill();
                process.Dispose();
                Console.WriteLine("Killed process");
            }
            //set current votes to 0, if a vote was underway, but not enough voted to skip
            votes.Clear();

            playingSong = false;

            if (!queue.Any())
            {
                sendMessage("No songs in queue! Disconnecting...");
                leaveVoiceChannel();
                return;
            }

            string video = queue.First().url;

            queue.Dequeue();
            //Thread.Sleep(1000); //Sleep for a sec so it can stop music
            //Play next song
            //await Task.Run(() => SendOnlineAudio(e, video), ct);
            SendOnlineAudio(e, video);
        }
Beispiel #17
0
        public void PlaySound(AudioService audioService, IAudioClient audioClient, TrackRequest trackRequest)
        {
            var channels   = audioService.Config.Channels;
            var timePlayed = 0;
            var outFormat  = new WaveFormat(48000, 16, channels);

            SetVolumeOfCurrentTrack(trackRequest.Volume);

            using (var audioFileStream = new MediaFoundationReader(trackRequest.Track.Path))
                using (var waveChannel32 = new WaveChannel32(audioFileStream, (_volumeOverride > 0 ? _volumeOverride : _volume) * 0.2f, 0f)
                {
                    PadWithZeroes = false
                })
                    using (var effectStream = new EffectStream(waveChannel32))
                        using (var blockAlignmentStream = new BlockAlignReductionStream(effectStream))
                            using (var resampler = new MediaFoundationResampler(blockAlignmentStream, outFormat)) {
                                resampler.ResamplerQuality = 60;
                                ApplyEffects(waveChannel32, effectStream, trackRequest);

                                // Establish the size of our AudioBuffer
                                var blockSize = outFormat.AverageBytesPerSecond / 50;
                                var buffer    = new byte[blockSize];
                                int byteCount;

                                // Read audio into our buffer, and keep a loop open while data is present
                                while ((byteCount = resampler.Read(buffer, 0, blockSize)) > 0)
                                {
                                    waveChannel32.Volume = (_volumeOverride > 0 ? _volumeOverride : _volume) * 0.2f;

                                    // Limit play length (--length)
                                    timePlayed += byteCount * 1000 / outFormat.AverageBytesPerSecond;
                                    if (trackRequest.TimeLimit > 0 && timePlayed > trackRequest.TimeLimit)
                                    {
                                        break;
                                    }

                                    if (byteCount < blockSize)
                                    {
                                        // Incomplete Frame
                                        for (var i = byteCount; i < blockSize; i++)
                                        {
                                            buffer[i] = 0;
                                        }
                                    }

                                    if (audioClient.State == ConnectionState.Disconnected || Stop)
                                    {
                                        break;
                                    }

                                    // Send the buffer to Discord
                                    try {
                                        audioClient.Send(buffer, 0, blockSize);
                                    } catch (Exception) {
                                        break;
                                    }
                                }
                                MyLogger.WriteLine("Voice finished enqueuing", ConsoleColor.Green);
                            }

            if (Stop)
            {
                audioClient.Clear();
                Stop = false;
            }

            audioClient.Wait();
        }
Beispiel #18
0
        internal async Task Play(IAudioClient voiceClient, CancellationToken cancelToken)
        {
            var filename = Path.Combine(MusicModule.MusicDataPath, DateTime.Now.UnixTimestamp().ToString());

            SongBuffer sb = new SongBuffer(filename, SongInfo, skipTo);
            var bufferTask = sb.BufferSong(cancelToken).ConfigureAwait(false);

            var inStream = new FileStream(sb.GetNextFile(), FileMode.OpenOrCreate, FileAccess.Read, FileShare.Write); ;

            bytesSent = 0;

            try
            {
                var attempt = 0;             

                var prebufferingTask = CheckPrebufferingAsync(inStream, sb, cancelToken);
                var sw = new Stopwatch();
                sw.Start();
                var t = await Task.WhenAny(prebufferingTask, Task.Delay(5000, cancelToken));
                if (t != prebufferingTask)
                {
                    Console.WriteLine("Prebuffering timed out or canceled. Cannot get any data from the stream.");
                    return;
                }
                else if(prebufferingTask.IsCanceled)
                {
                    Console.WriteLine("Prebuffering timed out. Cannot get any data from the stream.");
                    return;
                }
                sw.Stop();
                Console.WriteLine("Prebuffering successfully completed in "+ sw.Elapsed);

                const int blockSize = 3840;
                byte[] buffer = new byte[blockSize];
                while (!cancelToken.IsCancellationRequested)
                {
                    //Console.WriteLine($"Read: {songBuffer.ReadPosition}\nWrite: {songBuffer.WritePosition}\nContentLength:{songBuffer.ContentLength}\n---------");
                    var read = inStream.Read(buffer, 0, buffer.Length);
                    //await inStream.CopyToAsync(voiceClient.OutputStream);
                    unchecked
                    {
                        bytesSent += (ulong)read;
                    }
                    if (read < blockSize)
                    {
                        if (sb.IsNextFileReady())
                        {
                            inStream.Dispose();
                            inStream = new FileStream(sb.GetNextFile(), FileMode.Open, FileAccess.Read, FileShare.Write);
                            read += inStream.Read(buffer, read, buffer.Length - read);
                            attempt = 0;
                        }
                        if (read == 0)
                        {
                            if (sb.BufferingCompleted)
                                break;
                            if (attempt++ == 20)
                            {
                                voiceClient.Wait();
                                MusicPlayer.SongCancelSource.Cancel();
                                break;
                            }
                            else
                                await Task.Delay(100, cancelToken).ConfigureAwait(false);                         
                        }
                        else
                            attempt = 0;
                    }
                    else
                        attempt = 0;

                    while (this.MusicPlayer.Paused)
                        await Task.Delay(200, cancelToken).ConfigureAwait(false);

                    buffer = AdjustVolume(buffer, MusicPlayer.Volume);
                    voiceClient.Send(buffer, 0, read);
                }
            }
            finally
            {
                await bufferTask;
                await Task.Run(() => voiceClient.Clear());
                if(inStream != null)
                    inStream.Dispose();
                Console.WriteLine("l");
                sb.CleanFiles();
            }
        }
Beispiel #19
0
            public async Task StartPlaylist()
            {
                if (IsPlaying) return;

                if (await IsPlaylistEmpty())
                    return;

                if (PlaybackChannel == null)
                {
                    await ChatChannel.SafeSendMessage("Audio playback channel has not been set.");
                    return;
                }

                if (!await DiscordUtils.CanJoinAndTalkInVoiceChannel(PlaybackChannel, ChatChannel))
                    return;

                _voiceClient = await _client.Audio().Join(PlaybackChannel);

                while (true)
                {
                    if (_stopPlaylistFlag)
                    {
                        _stopPlaylistFlag = false;
                        break;
                    }

                    if (await IsPlaylistEmpty())
                        return;

                    await StartCurrentTrackPlayback();

                    if (_prevFlag)
                    {
                        _prevFlag = false;
                        TrackIndex--;
                    }
                    else if (!_skipToFlag)
                        TrackIndex++;
                }

                _voiceClient.Wait();
                await _voiceClient.Disconnect();
            }
Beispiel #20
0
        async Task StreamFunc()
        {
            CancellationToken cancellationToken = tokenSource.Token;
            IAudioClient      voiceClient       = null;
            TranscodingTask   streamer          = null;

            try {
                uint byteCounter = 0;

                // Download and read audio from the url
                streamer = new TranscodingTask(streamRequest, bufferingStream);
                streamer.Start();

                // Wait until we have at least a few kb transcoded or network stream done
                while (true)
                {
                    if (streamRequest.NetworkDone)
                    {
                        await Task.Delay(600);

                        break;
                    }
                    if (streamer.ReadyBytesLeft > 5 * 1024)
                    {
                        break;
                    }
                    await Task.Delay(200);
                }

                if (cancellationToken.IsCancellationRequested)
                {
                    return;
                }

                // Start streaming to voice
                await streamRequest.Channel.SendMessage($"Playing **{streamRequest.Title}** [{streamRequest.Length}]");

                var audioService = client.Audio();
                voiceClient = await audioService.Join(streamRequest.VoiceChannel);

                int    blockSize   = 1920 * audioService.Config.Channels;
                byte[] voiceBuffer = new byte[blockSize];
                var    ringBuffer  = streamer.PCMOutput;

                Stopwatch timeout = Stopwatch.StartNew();
                while (true)
                {
                    var readCount = ringBuffer.Read(voiceBuffer, 0, voiceBuffer.Length);

                    if (readCount == 0)
                    {
                        if (timeout.ElapsedMilliseconds > 1500)
                        {
                            Console.WriteLine("Audio stream timed out. Disconnecting.");
                            break;
                        }

                        await Task.Delay(200);

                        continue;
                    }

                    if (cancellationToken.IsCancellationRequested)
                    {
                        return;
                    }

                    timeout.Restart();

                    byteCounter += (uint)voiceBuffer.Length;
                    voiceClient.Send(voiceBuffer, 0, voiceBuffer.Length);
                }

                streamer.Cancel();

                voiceClient.Wait();
            } catch (Exception ex) {
                await streamRequest.Channel.SendMessage($":musical_note: {streamRequest.User.Mention} Something went wrong, please report this. :angry: :anger:");

                Console.WriteLine("Exception while playing music: " + ex);
            } finally {
                if (voiceClient != null)
                {
                    await streamRequest.Channel.SendMessage($"Finished playing **{streamRequest.Title}**");

                    State = StreamTaskState.Completed;
                    streamer?.Cancel();
                    await voiceClient.Disconnect();

                    await Task.Delay(500);
                }
            }
        }
Beispiel #21
0
        internal async Task Play(IAudioClient voiceClient, CancellationToken cancelToken)
        {
            var bufferTask = new ConfiguredTaskAwaitable();

            try {
                bufferTask = BufferSong(cancelToken).ConfigureAwait(false);
            }
            catch (Exception ex) {
                var clr = Console.ForegroundColor;
                Console.ForegroundColor = ConsoleColor.Red;
                Console.WriteLine($"ERR BUFFER START : {ex.Message}\n{ex}");
                Console.ForegroundColor = clr;
            }
            var       bufferAttempts = 0;
            const int waitPerAttempt = 500;
            var       toAttemptTimes = SongInfo.ProviderType != MusicType.Normal ? 5 : 9;

            while (!prebufferingComplete && bufferAttempts++ < toAttemptTimes)
            {
                await Task.Delay(waitPerAttempt, cancelToken);
            }
            cancelToken.ThrowIfCancellationRequested();
            Console.WriteLine($"Prebuffering done? in {waitPerAttempt * bufferAttempts}");
            const int blockSize = 3840;
            var       attempt   = 0;

            while (!cancelToken.IsCancellationRequested)
            {
                //Console.WriteLine($"Read: {songBuffer.ReadPosition}\nWrite: {songBuffer.WritePosition}\nContentLength:{songBuffer.ContentLength}\n---------");
                byte[] buffer = new byte[blockSize];
                var    read   = songBuffer.Read(buffer, blockSize);
                if (read == 0)
                {
                    if (attempt++ == 20)
                    {
                        Console.WriteLine("Waiting to empty out buffer.");
                        voiceClient.Wait();
                        Console.WriteLine($"Song finished. [{songBuffer.ContentLength}]");
                        break;
                    }
                    else
                    {
                        await Task.Delay(100, cancelToken);
                    }
                }
                else
                {
                    attempt = 0;
                }

                while (this.MusicPlayer.Paused)
                {
                    await Task.Delay(200, cancelToken);
                }
                buffer = AdjustVolume(buffer, MusicPlayer.Volume);
                voiceClient.Send(buffer, 0, read);
            }
            await bufferTask;

            voiceClient.Clear();
            cancelToken.ThrowIfCancellationRequested();
        }
Beispiel #22
0
        public void PlaySoundEffect(User user, Channel ch, string name)
        {
            if (string.IsNullOrWhiteSpace(name))
            {
                return;
            }

            // Ensure voice channel is connected

            ConnectToVoice();

            // Play the sound effect

            Task.Run(() =>
            {
                try
                {
                    sending.WaitOne();

                    var effect = SoundEffectRepository.FindByName(name);

                    if (audio != null && effect != null)
                    {
                        if (effect.Duration.TotalMilliseconds == 0)
                        {
                            return;
                        }

                        SoundboardLoggingService.Instance.Info(
                            string.Format("[{0}] playing <{1}>", user.Name, name));

                        // Change "playing" to the sound effect name

                        SetStatusMessage(name);

                        // Records play statistics

                        Statistics.Play(user, effect);

                        // Notify users soundbot will begin playing

                        SendMessage(ch, string.Format(Properties.Resources.MessagePlayingSound, name));

                        // Resample and stream sound effect over the configured voice channel

                        var format = new WaveFormat(48000, 16, 2);
                        var length = Convert.ToInt32(format.AverageBytesPerSecond / 60.0 * 1000.0);
                        var buffer = new byte[length];

                        using (var reader = new WaveFileReader(effect.Path))
                            using (var resampler = new WaveFormatConversionStream(format, reader))
                            {
                                int count = 0;
                                while ((count = resampler.Read(buffer, 0, length)) > 0)
                                {
                                    audio.Send(buffer, 0, count);
                                }
                            }

                        audio.Wait();

                        SetStatusMessage(Configuration.Status);
                    }
                }
                catch (Exception ex)
                {
                    SoundboardLoggingService.Instance.Error(
                        string.Format(Properties.Resources.MessagePlayingFailed, name), ex);
                }
                finally
                {
                    sending.Set();
                }
            });
        }
Beispiel #23
0
 // Subtask for async operation of above function
 public void SendAudioTask(string filePath)
 {
     // Flag to prevent multiple simultaneous audio
     sendingAudio = true;
     try
     {
         // Get the number of AudioChannels our AudioService has been configured to use.
         var channelCount = client.GetService <AudioService>().Config.Channels;
         // Create a new Output Format, using the spec that Discord will accept, and with the number of channels that our client supports.
         var OutFormat = new WaveFormat(48000, 16, channelCount);
         // Select the right type of reader, based on the file extension.
         MediaFoundationResampler resampler = null;
         if (filePath.ToLower().Contains(".mp3"))
         {
             // MP3 file
             // Create a new Disposable MP3FileReader, to read audio from the filePath parameter
             var Reader = new Mp3FileReader(filePath);
             resampler = new MediaFoundationResampler(Reader, OutFormat);
         }
         if (filePath.ToLower().Contains(".wav"))
         {
             // WAV file
             // Create a new Disposable WaveFileReader, to read audio from the filePath parameter
             var Reader = new WaveFileReader(filePath);
             resampler = new MediaFoundationResampler(Reader, OutFormat);
         }
         // Only attempt output if we have a good file type
         if (resampler != null)
         {
             // Set the quality of the resampler to 60, the highest quality
             resampler.ResamplerQuality = 60;
             // Establish the size of our AudioBuffer
             int    blockSize = OutFormat.AverageBytesPerSecond / 50;
             byte[] buffer    = new byte[blockSize];
             int    byteCount;
             try
             {
                 // Read audio into our buffer, and keep a loop open while data is present
                 while ((byteCount = resampler.Read(buffer, 0, blockSize)) > 0)
                 {
                     if (byteCount < blockSize)
                     {
                         // Incomplete Frame, pad it
                         for (int i = byteCount; i < blockSize; i++)
                         {
                             buffer[i] = 0;
                         }
                     }
                     // Send the buffer to Discord
                     vClient.Send(buffer, 0, blockSize);
                 }
                 vClient.Wait();
             }
             catch (Exception ex)
             {
                 // Do nothing, just absorb the exception- likely as not we were cancelled.
             }
         }
     }
     catch (Exception ex)
     {
         // Set a flag so we can annunciate a bad file
         badfile = true;
     }
     //Set flag to say we're no longer sending audio.
     sendingAudio = false;
 }