/// <summary> /// Decodes a Lavalink track string. /// </summary> /// <param name="track">Track string to decode.</param> /// <returns>Decoded Lavalink track.</returns> public static LavalinkTrack DecodeTrack(string track) { var raw = Convert.FromBase64String(track); var msgval = BitConverter.ToInt32(raw, 0); msgval = (int)SwapEndianness((uint)msgval); var msgFlags = (int)((msgval & 0xC0000000L) >> 30); var msgSize = msgval & 0x3FFFFFFF; var decoded = new LavalinkTrack { TrackString = track }; using (var ms = new MemoryStream(msgSize)) { ms.Write(raw, 4, msgSize); ms.Position = 0; using (var br = new BinaryReader(ms)) { var version = (msgFlags & 1) == 1 ? br.ReadByte() & 0xFF : 1; var len = br.ReadInt16(); len = SwapEndianness(len); raw = br.ReadBytes(len); decoded.Title = UTF8.GetString(raw, 0, len); len = br.ReadInt16(); len = SwapEndianness(len); raw = br.ReadBytes(len); decoded.Author = UTF8.GetString(raw, 0, len); decoded._length = (long)SwapEndianness((ulong)br.ReadInt64()); len = br.ReadInt16(); len = SwapEndianness(len); raw = br.ReadBytes(len); decoded.Identifier = UTF8.GetString(raw, 0, len); decoded.IsStream = br.ReadBoolean(); var isthere = br.ReadBoolean(); if (isthere) { len = br.ReadInt16(); len = SwapEndianness(len); raw = br.ReadBytes(len); decoded.Uri = version >= 2 ? new Uri(UTF8.GetString(raw, 0, len)) : null; } } } return(decoded); }
/// <summary> /// Queues the specified track for playback. /// </summary> /// <param name="track">Track to play.</param> /// <returns></returns> public void Play(LavalinkTrack track) { if (!this.IsConnected) { throw new InvalidOperationException("This connection is not valid."); } this.CurrentState.CurrentTrack = track; this.Node.SendPayload(new LavalinkPlay(this, track)); }
/// <summary> /// Queues the specified track for playback. /// </summary> /// <param name="track">Track to play.</param> public async Task PlayAsync(LavalinkTrack track) { if (!this.IsConnected) { throw new InvalidOperationException("This connection is not valid."); } this.CurrentState.CurrentTrack = track; await this.Node.SendPayloadAsync(new LavalinkPlay(this, track)).ConfigureAwait(false); }
/// <summary> /// Decodes a Lavalink track string. /// </summary> /// <param name="track">Track string to decode.</param> /// <returns>Decoded Lavalink track.</returns> public static LavalinkTrack DecodeTrack(string track) { // https://github.com/sedmelluq/lavaplayer/blob/804cd1038229230052d9b1dee5e6d1741e30e284/main/src/main/java/com/sedmelluq/discord/lavaplayer/player/DefaultAudioPlayerManager.java#L63-L64 const int TRACK_INFO_VERSIONED = 1; //const int TRACK_INFO_VERSION = 2; var raw = Convert.FromBase64String(track); var decoded = new LavalinkTrack { TrackString = track }; using (var ms = new MemoryStream(raw)) using (var br = new JavaBinaryReader(ms)) { // https://github.com/sedmelluq/lavaplayer/blob/b0c536098c4f92e6d03b00f19221021f8f50b19b/main/src/main/java/com/sedmelluq/discord/lavaplayer/tools/io/MessageInput.java#L37-L39 var messageHeader = br.ReadInt32(); var messageFlags = (int)((messageHeader & 0xC0000000L) >> 30); var messageSize = messageHeader & 0x3FFFFFFF; //if (messageSize != raw.Length) // Warn($"Size conflict: {messageSize} but was {raw.Length}"); // https://github.com/sedmelluq/lavaplayer/blob/804cd1038229230052d9b1dee5e6d1741e30e284/main/src/main/java/com/sedmelluq/discord/lavaplayer/player/DefaultAudioPlayerManager.java#L268 // java bytes are signed // https://docs.oracle.com/javase/7/docs/api/java/io/DataInput.html#readByte() var version = (messageFlags & TRACK_INFO_VERSIONED) != 0 ? (br.ReadSByte() & 0xFF) : 1; //if (version != TRACK_INFO_VERSION) // Warn($"Version conflict: Expected {TRACK_INFO_VERSION} but got {version}"); decoded.Title = br.ReadJavaUtf8(); decoded.Author = br.ReadJavaUtf8(); decoded._length = br.ReadInt64(); decoded.Identifier = br.ReadJavaUtf8(); decoded.IsStream = br.ReadBoolean(); var uri = br.ReadNullableString(); if (uri != null && version >= 2) { decoded.Uri = new Uri(uri); } else { decoded.Uri = null; } } return(decoded); }
/// <summary> /// Queues the specified track for playback. The track will be played from specified start timestamp to specified end timestamp. /// </summary> /// <param name="track">Track to play.</param> /// <param name="start">Timestamp to start playback at.</param> /// <param name="end">Timestamp to stop playback at.</param> /// <returns></returns> public void PlayPartial(LavalinkTrack track, TimeSpan start, TimeSpan end) { if (!this.IsConnected) { throw new InvalidOperationException("This connection is not valid."); } if (start.TotalMilliseconds < 0 || end <= start) { throw new ArgumentException("Both start and end timestamps need to be greater or equal to zero, and the end timestamp needs to be greater than start timestamp."); } this.CurrentState.CurrentTrack = track; this.Node.SendPayload(new LavalinkPlayPartial(this, track, start, end)); }