Пример #1
0
        public async Task PlayAsync(ICommandContext Context, ITextChannel Channel = null, bool KeepCurrent = false, TimeSpan?SeekTo = null, bool AvoidState = false)
        {
            if (Channel == null)
            {
                Channel = Context.Channel as ITextChannel;
            }

            string lId = Channel.GetSettings().Language;

            LanguageEntry Language = Global.Languages.GetLanguage(lId);

            if (!AvoidState)
            {
                if (State == PlayerState.Playing || State == PlayerState.Paused)
                {
                    await Channel.SendMessageAsync(Language.GetEntry("MusicHandler:AlreadyPlaying"));

                    return;
                }
            }
            if (State == PlayerState.Disconnected)
            {
                bool Success = await ConnectAsync(Context);

                if (!Success)
                {
                    return;
                }
            }
            if (!KeepCurrent || Current == null)
            {
                Current = Queue[QueueIndex];
            }

            string Url = Current.UrlOrId;

            WebSocket ws = null;

            if (Current.IsYouTube)
            {
                YoutubeClient  Client = new YoutubeClient();
                StreamManifest sm     = null;
                try
                {
                    sm = await Client.Videos.Streams.GetManifestAsync(VideoId.TryParse(Current.UrlOrId).Value);
                }
                catch (Exception e)
                {
                    File.WriteAllText("tempexceptionfrommusicplayer.json", JsonConvert.SerializeObject(e, Formatting.Indented));

                    await Global.Client.GetGuild(Global.Settings.DevServer.Id)
                    .GetTextChannel(Global.Settings.DevServer.ErrorReportChannelId).SendFileAsync("tempexceptionfrommusicplayer.json", "");

                    File.Delete("tempexceptionfrommusicplayer.json");
                }
                if (sm != null)
                {
                    IEnumerable <IAudioStreamInfo> streamInfos = sm.GetAudioStreams();

                    if (streamInfos.Count() > 0)
                    {
                        IStreamInfo info = streamInfos.GetWithHighestBitrate();
                        Url = info.Url;
                    }
                }

                if (Url == Current.UrlOrId)
                {
                    Url = null;
                }
            }
            else
            {
                if (Current.IsListenMoe)
                {
                    Url = Current.PublicUrl;
                    ws  = new WebSocket(Current.PublicUrl.Contains("kpop") ? "wss://listen.moe/kpop/gateway_v2" : "wss://listen.moe/gateway_v2");

                    Timer t = new Timer((state) =>
                    {
                        try
                        {
                            ws.Send("{ \"op\": 9 }");
                        }
                        catch
                        {
                            Logger.Log(LogType.WebSocket, ConsoleColor.Red, "Error", "Couldn't send heartbeat to LISTEN.moe!");
                        }
                    }, null, -1, -1);

                    ws.OnOpen += (s, e) =>
                    {
                        ws.Send("{ \"op\": 0, \"d\": { \"auth\": \"\" } }"); // { op: 0, d: { auth: "" } }
                    };
                    ws.OnMessage += (s, e) =>
                    {
                        ListenMoe parsed = JsonConvert.DeserializeObject <ListenMoe>(e.Data);
                        if (parsed.OpCode == 0)
                        {
                            t.Change(0, parsed.Data.HeartBeat);
                        }
                        else if (parsed.OpCode == 1 && parsed.Type == "TRACK_UPDATE")
                        {
                            ListenMoeStartTime = parsed.Data.StartTime;
                            Current.Author     = string.Join(" && ", parsed.Data.Song.Artists.Select(i => i.NameRomaji ?? i.Name));
                            Current.Duration   = TimeSpan.FromSeconds(parsed.Data.Song.Duration);
                            Current.Title      = parsed.Data.Song.Title;
                            Current.Thumbnail  = null;
                            foreach (ListenMoeAlbum album in parsed.Data.Song.Albums)
                            {
                                if (album.Image != null)
                                {
                                    Current.Thumbnail = album.Image;
                                    break;
                                }
                            }
                            if (State > PlayerState.Connected && State != PlayerState.Paused)
                            {
                                SendNowPlayingAsync(Context, Channel).GetAwaiter().GetResult();
                            }
                        }
                    };
                    ws.OnClose += (s, e) =>
                    {
                        t.Change(Timeout.Infinite, Timeout.Infinite);
                        t.Dispose();
                    };

                    ws.Connect();
                }
                else if (Global.SoundCloud == null)
                {
                    if (!IterateIndex(true))
                    {
                        Current = null;
                        await Channel.SendMessageAsync(Language.GetEntry("MusicHandler:SoundCloudNotAvailable"));
                    }
                    else
                    {
                        await Channel.SendMessageAsync(Language.GetEntry("MusicHandler:OnlySoundCloudTracks"));

                        new Task(async() => await PlayAsync(Context, Channel, AvoidState: true));
                    }
                    return;
                }
                else
                {
                    Url += "?client_id=" + Global.SoundCloud.ClientId;
                }
            }

            if (Url == null)
            {
                if (!IterateIndex())
                {
                    Current = null;
                    await Channel.SendMessageAsync(Language.GetEntry("MusicHandler:FinishedPlaying"));

                    State = PlayerState.Connected;
                }
                else
                {
                    new Task(async() => await PlayAsync(Context, Channel, AvoidState: true)).Start();
                    return;
                }
            }

            try
            {
                Reader = new FFmpegReader(Url);

                /*
                 * switch (encoding.Name)
                 * {
                 *  case "webm":
                 *  case "3gpp":
                 *      Stream s = await new HttpClient().GetStreamAsync(Url);
                 *      Reader = new NAudio.Vorbis.VorbisWaveReader(s);
                 *      break;
                 *
                 *  default:
                 *      Reader = new MediaFoundationReader(Url);
                 *      break;
                 * }
                 */
            }
            catch (Exception e)
            {
                System.Console.WriteLine(e);
                await Channel.SendMessageAsync(Language.GetEntry("MusicHandler:SongInaccessible", "SONGNAME", Current.Title));

                if (!IterateIndex(Global.SoundCloud == null))
                {
                    Current = null;
                    await Channel.SendMessageAsync(Language.GetEntry("MusicHandler:FinishedPlaying"));

                    State = PlayerState.Connected;
                }
                else
                {
                    new Task(async() => await PlayAsync(Context, Channel, AvoidState: true)).Start();
                }
                return;
            }

            if (PCMStream == null || !PCMStream.CanWrite)
            {
                PCMStream = Client.CreatePCMStream(AudioApplication.Music, 128 * 1024, 200, 0);
            }

            //WaveFormat OutFormat = new WaveFormat(48000, 16, 2);


            /*
             * MediaFoundationResampler Resampler = new MediaFoundationResampler(Reader, OutFormat)
             * {
             *  ResamplerQuality = 60
             * };
             */

            //if (SeekTo.HasValue && !Current.IsListenMoe) Reader.CurrentTime = SeekTo.Value;
            if (SeekTo.HasValue && SeekTo != TimeSpan.Zero && !Current.IsListenMoe)
            {
                Reader.ReadUntil(SeekTo.Value);
            }
            BackupTime = TimeSpan.Zero;

            //int Size = OutFormat.AverageBytesPerSecond / 50;
            int Size = Reader.BufferSize(1);

            byte[] Buffer = new byte[Size];
            int    Count  = 0;

            State         = PlayerState.Playing;
            TextChannelId = Channel.Id;
            if (!Current.IsListenMoe)
            {
                await SendNowPlayingAsync(Context, Channel);
            }

            /*while (Reader.CanRead && (Count = Resampler.Read(Buffer, 0, Size)) > 0
             *  && Request == PlayerRequest.Idle && State > PlayerState.Connected)*/
            while (Reader.CanRead && (Count = Reader.Read(Buffer, 0, Size)) > 0 &&
                   Request == PlayerRequest.Idle && State > PlayerState.Connected)
            {
                if (State == PlayerState.Paused)
                {
                    await Channel.SendMessageAsync("", embed : new EmbedBuilder()
                    {
                        Title = Language.GetEntry("MusicHandler:Paused"),
                        Color = Color
                    }.Build());


                    while (State == PlayerState.Paused && Request == PlayerRequest.Idle)
                    {
                        Thread.Sleep(100);
                    }

                    string cId = Channel.GetSettings().Language;
                    if (cId != lId)
                    {
                        Language = Global.Languages.GetLanguage(cId);
                    }
                    lId = cId;

                    if (State == PlayerState.Playing)
                    {
                        await Channel.SendMessageAsync("", embed : new EmbedBuilder()
                        {
                            Title = Language.GetEntry("MusicHandler:Resumed"),
                            Color = Color
                        }.Build());

                        if (Current.IsListenMoe)
                        {
                            await SendNowPlayingAsync(Context, Channel);
                        }
                    }
                }
                if (Request > 0)
                {
                    break;
                }

                if (CurrentTime.TotalSeconds % 10 == 0 && BackupTime.TotalSeconds != CurrentTime.TotalSeconds)
                {
                    PropertyChanged?.Invoke();
                    BackupTime = CurrentTime;
                }

                try
                {
                    if (State < PlayerState.Playing)
                    {
                        break;
                    }
                    ChangeVolume(Buffer, Volume / 100f);
                    await PCMStream.WriteAsync(Buffer, 0, Count);
                }
                catch (Exception e)
                {
                    if (State == PlayerState.Disconnected || Client.ConnectionState == ConnectionState.Disconnected || Client.ConnectionState == ConnectionState.Disconnecting)
                    {
                        break;
                    }

                    string cId = Channel.GetSettings().Language;
                    if (cId != lId)
                    {
                        Language = Global.Languages.GetLanguage(cId);
                    }
                    lId = cId;

                    await Channel.SendMessageAsync(Language.GetEntry("MusicHandler:PlaybackErrorOccured"));

                    Request = PlayerRequest.Stop;
                    Logger.Log(LogType.Music, ConsoleColor.Red, "Error", e.ToString());
                    if (Global.Settings.DevServer.ErrorReportChannelId != 0)
                    {
                        ITextChannel Report = Global.Client.GetChannel(Global.Settings.DevServer.ErrorReportChannelId) as ITextChannel;
                        await Report.SendMessageAsync($"An error occured while playing on a server!\n```\n{ e }\n```\n" +
                                                      $"Client:\n { JsonConvert.SerializeObject(this) }");
                    }
                    break;
                }
            }
            if (ws != null && ws.IsAlive)
            {
                ws.Close();
            }

            if (Request == PlayerRequest.Idle && State > PlayerState.Connected)
            {
                Request = PlayerRequest.Next;
            }

            //Resampler.Dispose();
            Reader.Dispose();
            Reader = null;
            //Resampler = null;
            try { await PCMStream.FlushAsync(); } catch { } // It may be disposed

            if (Request == PlayerRequest.Next)
            {
                Request = PlayerRequest.Idle;
                if (!IterateIndex(Global.SoundCloud == null))
                {
                    if (State != PlayerState.Connected && State != PlayerState.Disconnected)
                    {
                        State = PlayerState.Connected;
                    }
                    Current = null;

                    string cId = Channel.GetSettings().Language;
                    if (cId != lId)
                    {
                        Language = Global.Languages.GetLanguage(cId);
                    }
                    lId = cId;

                    await Channel.SendMessageAsync(Language.GetEntry("MusicHandler:FinishedPlaying"));
                }
            }
            else if (Request == PlayerRequest.Stop)
            {
                Request = PlayerRequest.Idle;
                State   = PlayerState.Connected;
                Current = null;
            }

            if (State > PlayerState.Connected)
            {
                new Task(async() => await PlayAsync(Context, Channel, AvoidState: true)).Start();
            }
        }