/// <summary>Checks whether the two models equal each other.</summary> /// <param name="x">The first model.</param> /// <param name="y">The second model.</param> /// <returns>Whether the two models equal each other.</returns> public bool Equals(CurrentlyPlayingContext x, CurrentlyPlayingContext y) { if (object.ReferenceEquals(x, y)) { return(true); } if (object.ReferenceEquals(x, null)) { return(false); } if (object.ReferenceEquals(y, null)) { return(false); } if (x.GetType() != y.GetType()) { return(false); } return(object.Equals(x.Device?.Id, y.Device?.Id) && string.Equals(x.RepeatState, y.RepeatState) && x.ShuffleState == y.ShuffleState && object.Equals(x.Context?.Uri, y.Context?.Uri) && x.TimestampMs == y.TimestampMs && x.ProgressMs == y.ProgressMs && x.IsPlaying == y.IsPlaying && object.Equals(x.Item?.Id, y.Item?.Id)); }
private void OnPlayerStateUpdate(CurrentlyPlayingContext currentlyPlaying, FullTrack playbackItem) { if (playbackItem.Id != _lastId) { _plugin.DisplayMessage($"Playing '{playbackItem.Name}'..."); } _lastId = playbackItem.Id; var playerStateStruct = PlayerState; playerStateStruct.ProgressMs = currentlyPlaying.ProgressMs; playerStateStruct.IsPlaying = currentlyPlaying.IsPlaying; playerStateStruct.RepeatState = currentlyPlaying.RepeatState; playerStateStruct.ShuffleState = currentlyPlaying.ShuffleState; playerStateStruct.CurrentlyPlaying = new TrackStruct { Id = playbackItem.Id, Name = playbackItem.Name, Artists = playbackItem.Artists.Select(artist => artist.Name).ToArray(), DurationMs = playbackItem.DurationMs, Album = new AlbumStruct { Name = playbackItem.Album.Name } }; PlayerState = playerStateStruct; }
/// <summary>Updates continuously.</summary> private async void UpdateContinuously() { while (this.running) { var newDevicesContainer = await this.api.Player.GetAvailableDevices(); if (!this.devicesEqualityComparer.Equals(this.devicesContainer, newDevicesContainer)) { this.eventAggregator.GetEvent <DevicesChangedEvent>().Publish(newDevicesContainer); this.devicesContainer = newDevicesContainer; } var newCurrentlyPlayingContext = await this.api.Player.GetCurrentlyPlayingContext(); if (!this.playingEqualityComparer.Equals(this.currentlyPlayingContext, newCurrentlyPlayingContext)) { this.eventAggregator.GetEvent <CurrentlyPlayingContextChangedEvent>().Publish(newCurrentlyPlayingContext); this.currentlyPlayingContext = newCurrentlyPlayingContext; await this.UpdateCurrentlyPlayingImage(); } await Task.Delay(TimeSpan.FromSeconds(1)); } }
public async void ShouldToggleUsersPlayback() { await SetupCredentials(); //First get current playback devices IReadOnlyList <Device> devices = await Endpoints.GetUsersAvailableDevices(Creds.Access_token); Assert.True(devices.Any(), "Expected at least 1 playback device. Got none"); //Get currently playing song so we can restore it later. CurrentlyPlayingContext current = await Endpoints.GetUsersCurrentlyPlayingInformation(Creds.Access_token); //Stop playback RegularError reg = await Endpoints.StartOrResumePlayback(Creds.Access_token, devices[0].Id); Assert.False(reg.WasError, "Expected no error, got an error"); //Wait 4 seconds await Task.Delay(4000); //Restart playback reg = await Endpoints.StartOrResumePlayback(Creds.Access_token, devices[0].Id, uris : new List <string>() { current.Item.Uri }); Assert.False(reg.WasError, "Expected no error, got an error"); }
private async Task UpdatePlayerInfo(CurrentlyPlayingContext playing) { DataModel.Player.Shuffle = playing.ShuffleState; DataModel.Player.RepeatState = Enum.Parse <RepeatState>(playing.RepeatState, true); DataModel.Player.Volume = playing.Device.VolumePercent ?? -1; DataModel.Player.IsPlaying = playing.IsPlaying; DataModel.Track.Progress = TimeSpan.FromMilliseconds(playing.ProgressMs); if (playing.Context != null && Enum.TryParse(playing.Context.Type, true, out ContextType contextType)) { DataModel.Player.ContextType = contextType; string contextId = playing.Context.Uri.Split(':').Last(); if (contextId != _contextId) { DataModel.Player.ContextName = contextType switch { ContextType.Artist => (await _spotify.Artists.Get(contextId)).Name, ContextType.Album => (await _spotify.Albums.Get(contextId)).Name, ContextType.Playlist => (await _spotify.Playlists.Get(contextId)).Name, _ => "" }; _contextId = contextId; } } else { DataModel.Player.ContextType = ContextType.None; DataModel.Player.ContextName = ""; _contextId = ""; } }
private async Task UpdateData(double deltaTime) { //this will be null before authentication if (_spotify is null) { return; } try { CurrentlyPlayingContext playing = await _spotify.Player.GetCurrentPlayback(); if (playing is null || DataModel is null) { return; } await UpdatePlayerInfo(playing); //in theory this can also be FullEpisode for podcasts //but it does not seem to work correctly. if (playing.Item is FullTrack track) { await UpdateTrackInfo(track); } } catch (APIException e) { _logger.Error(e.ToString()); } }
/// <summary>Handles the currently playing context changed event.</summary> /// <param name="data">The data.</param> private void HandleCurrentlyPlayingContextChanged(CurrentlyPlayingContext data) { this.isReadingEvents = true; this.TrackName = data.Item?.Name; this.ArtistsNames = data.Item == null ? null : string.Join(", ", data.Item.Artists.Select(o => o.Name)); if (!this.ProgressHasFocus) { if (data.Item != null) { this.Progress = data.ProgressMs ?? 0; this.Duration = data.Item.DurationMs; } else { this.Progress = 0; this.Duration = 1; } } this.isPlaying = data.IsPlaying; this.PlayPauseGlyph = this.isPlaying ? PlayerPageViewModel.PauseGlyph : PlayerPageViewModel.PlayGlyph; this.isShuffleActive = data.ShuffleState; this.ShuffleOpacity = this.isShuffleActive ? 1.0 : 0.3; this.repeatState = string.IsNullOrEmpty(data.RepeatState) ? RepeatState.Off : Enum.Parse <RepeatState>(data.RepeatState, true); this.RepeatGlyph = this.repeatState == RepeatState.Track ? PlayerPageViewModel.RepeatOneGlyph : PlayerPageViewModel.RepeatAllGlyph; this.RepeatOpacity = this.repeatState == RepeatState.Off ? 0.3 : 1.0; this.isReadingEvents = false; }
public async void ShouldGetCurrentlyPlayingSong() { await SetupCredentials(); CurrentlyPlayingContext current = await Endpoints.GetUsersCurrentlyPlayingInformation(Creds.Access_token); Assert.False(current.WasError, "Object Error"); }
private async void OnToggleAddToLibrary() { SpotifyClient client = SpotifyService.Instance.GetSpotifyClient(); // Get current context and check any are null CurrentlyPlayingContext context = this.GetCurrentContext(); if (client != null && context != null) { List <string> ids = new List <string>(); // Cast Item to correct type, add it's URI add make request if (context.Item.Type == ItemType.Track) { FullTrack track = context.Item as FullTrack; ids.Add(track.Id); if (_currentItemIsInLibrary) { // Is in library, remove LibraryRemoveTracksRequest removeRequest = new LibraryRemoveTracksRequest(ids); await client.Library.RemoveTracks(removeRequest); SetLibraryBtnIsLiked(false); } else { // Not in library, add to user's library LibrarySaveTracksRequest removeRequest = new LibrarySaveTracksRequest(ids); await client.Library.SaveTracks(removeRequest); SetLibraryBtnIsLiked(true); } } else if (context.Item.Type == ItemType.Episode) { FullEpisode episode = context.Item as FullEpisode; ids.Add(episode.Id); if (_currentItemIsInLibrary) { LibraryRemoveShowsRequest request = new LibraryRemoveShowsRequest(ids); await client.Library.RemoveShows(request); SetLibraryBtnIsLiked(false); } else { LibrarySaveShowsRequest request = new LibrarySaveShowsRequest(ids); await client.Library.SaveShows(request); SetLibraryBtnIsLiked(true); } } } }
private void Update() { CurrentlyPlayingContext context = GetCurrentContext(); if (context != null) { // Update current position to context position when user is not dragging if (_currentProgressText != null && !_progressStartDrag) { _currentProgressText.text = S4UUtility.MsToTimeString(context.ProgressMs); } // Update Volume slider if (_volumeSlider != null) { _volumeSlider.minValue = 0; _volumeSlider.maxValue = 100; _volumeSlider.value = context.Device.VolumePercent.Value; } // Update play/pause btn sprite with correct play/pause sprite if (_playPauseButton != null) { Image playPauseImg = _playPauseButton.transform.GetChild(0).GetComponent <Image>(); if (context.IsPlaying) { playPauseImg.sprite = _pauseSprite; } else { playPauseImg.sprite = _playSprite; } } FullTrack track = context.Item as FullTrack; if (track != null) { if (_totalProgressText != null) { _totalProgressText.text = S4UUtility.MsToTimeString(track.DurationMs); } if (_currentProgressSlider != null) { _currentProgressSlider.minValue = 0; _currentProgressSlider.maxValue = track.DurationMs; // Update position when user is not dragging slider if (!_progressStartDrag) { _currentProgressSlider.value = context.ProgressMs; } } } } }
public void PlayableItemConverter_CanSerialize() { var context = new CurrentlyPlayingContext { Item = new FullTrack() }; Assert.DoesNotThrow(() => { var serialized = JsonConvert.SerializeObject(context); }); }
public async Task SetMetadata(CurrentlyPlayingContext playbackContext) { if (playbackContext.ValidTrackItemOrNull() is FullTrack track) { await jsRuntime.InvokeVoidAsync($"{JsWrapper}.SetMetadata", playbackContext.IsPlaying, track.Name, string.Join(", ", track.Artists.Select(a => a.Name)), track.Album.Name, track.Album.Images); } }
private void UpdatePlayerState(CurrentlyPlayingContext playback, FullTrack playbackItem) { var lastId = ""; if (_lastFullTrack != null) { lastId = _lastFullTrack.Id; } _deviceId = playback.Device.Id; CurrentlyPlaying = playback; _lastFullTrack = playbackItem; OnPlayerStateUpdate?.Invoke(playback, playbackItem); }
/// <summary>Gets the hash code for the model.</summary> /// <param name="obj">The model.</param> /// <returns>The hash code.</returns> public int GetHashCode(CurrentlyPlayingContext obj) { unchecked { var hashCode = obj.Device != null?obj.Device.Id.GetHashCode() : 0; hashCode = (hashCode * 397) ^ (obj.RepeatState != null ? obj.RepeatState.GetHashCode() : 0); hashCode = (hashCode * 397) ^ obj.ShuffleState.GetHashCode(); hashCode = (hashCode * 397) ^ (obj.Context != null ? obj.Context.Uri.GetHashCode() : 0); hashCode = (hashCode * 397) ^ obj.TimestampMs.GetHashCode(); hashCode = (hashCode * 397) ^ obj.ProgressMs.GetHashCode(); hashCode = (hashCode * 397) ^ obj.IsPlaying.GetHashCode(); hashCode = (hashCode * 397) ^ (obj.Item != null ? obj.Item.GetHashCode() : 0); return(hashCode); } }
public async void ShouldStartPlaybackAtSecondOffset() { await SetupCredentials(); //First get current playback devices IReadOnlyList <Device> devices = await Endpoints.GetUsersAvailableDevices(Creds.Access_token); Assert.True(devices.Any(), "Expected at least 1 playback device. Got none"); //Get currently playing song so we can restore it later. CurrentlyPlayingContext current = await Endpoints.GetUsersCurrentlyPlayingInformation(Creds.Access_token); //Start playback RegularError reg = await Endpoints.StartOrResumePlayback(Creds.Access_token, devices[0].Id, uris : TrackUris, offset : 1); Assert.False(reg.WasError, "Expected no error, got an error"); }
public static TrackEntity Map(CurrentlyPlayingContext currentlyPlayingContext) { return(new TrackEntity() { RowKey = currentlyPlayingContext.Item.Id, PartitionKey = currentlyPlayingContext.Item.Artists.Select(x => x.Name).FirstOrDefault(), Name = currentlyPlayingContext.Item.Name, Artist = currentlyPlayingContext.Item.Artists.FirstOrDefault().Name, Popularity = currentlyPlayingContext.Item.Popularity, TrackLength = currentlyPlayingContext.Item.DurationMs, Album = currentlyPlayingContext.Item.Album.Name, // ReleaseDate = currentlyPlayingContext.Item.Album, RetrievedTimestamp = currentlyPlayingContext.Timestamp, AlbumArtHeight = currentlyPlayingContext.Item.Album.Images.FirstOrDefault().Height, AlbumArtWidth = currentlyPlayingContext.Item.Album.Images.FirstOrDefault().Width, AlbumArtUrl = currentlyPlayingContext.Item.Album.Images.FirstOrDefault().Url }); }
public static async void OnNextSong(Spotify user, CurrentlyPlayingContext playing) { if (!user.Setting.ShuffleOn.Value) { return; } if (playing.Context == null) { Paging <SavedTrack> tracks = await user.spotify.Library.GetTracks(); int i = rnd.Next(0, tracks.Total.Value); LibraryTracksRequest trackReq = new LibraryTracksRequest(); trackReq.Offset = i; Paging <SavedTrack> targetTrack = await user.spotify.Library.GetTracks(trackReq); SavedTrack t = targetTrack.Items[0]; await user.spotify.Player.AddToQueue(new PlayerAddToQueueRequest(t.Track.Uri)); } else if (playing.Context.Type == "playlist" && user.Setting.ShufflePlaylists.Value) { string id = playing.Context.Href.Split('/').Last(); FullPlaylist playlist = await user.spotify.Playlists.Get(id); int i = rnd.Next(0, playlist.Tracks.Total.Value); PlaylistGetItemsRequest playlistGet = new PlaylistGetItemsRequest(); playlistGet.Offset = i; Paging <PlaylistTrack <IPlayableItem> > targetTrack = await user.spotify.Playlists.GetItems(id, playlistGet); PlaylistTrack <IPlayableItem> t = targetTrack.Items[0]; await user.spotify.Player.AddToQueue(new PlayerAddToQueueRequest(((FullTrack)t.Track).Uri)); } else if (playing.Context.Type == "album" && user.Setting.ShuffleAlbums.Value) { #warning Not Implemented } }
private static async void CheckUserEvent(User user) { CurrentlyPlayingContext playing = await user.spotify.Player.GetCurrentPlayback(); if (playing != null) { if (user.lastTrack == null) { user.last = playing; user.lastTrack = (FullTrack)playing.Item; } else if (playing.Item != null) { FullTrack track = (FullTrack)playing.Item; //Check if skipped if (track.Id != user.lastTrack.Id && user.last.ProgressMs < user.lastTrack.DurationMs * IsntSkip) { OnSkip(user, user.lastTrack); } user.lastTrack = track; } //Check if play state changed if (playing.IsPlaying != user.last.IsPlaying) { if (playing.IsPlaying) { OnResume(user, playing); } else { OnPause(user, playing); } } user.last = playing; } }
private void OnPlayPauseClicked() { // Get current context & client, check if null CurrentlyPlayingContext context = GetCurrentContext(); SpotifyClient client = SpotifyService.Instance.GetSpotifyClient(); if (context != null && client != null) { // Get child image, update UI and set Spotify client to do action Image playPauseImg = _playPauseButton.transform.GetChild(0).GetComponent <Image>(); if (context.IsPlaying) { client.Player.PausePlayback(); playPauseImg.sprite = _playSprite; } else { client.Player.ResumePlayback(); playPauseImg.sprite = _pauseSprite; } } }
private void OnToggleRepeat() { SpotifyClient client = SpotifyService.Instance.GetSpotifyClient(); CurrentlyPlayingContext context = this.GetCurrentContext(); if (client != null && context != null) { // Get current shuffle state string currentShuffleState = context.RepeatState; // Determine next shuffle state PlayerSetRepeatRequest.State newState = PlayerSetRepeatRequest.State.Off; switch (currentShuffleState) { case "off": newState = PlayerSetRepeatRequest.State.Track; break; case "track": newState = PlayerSetRepeatRequest.State.Context; break; case "context": newState = PlayerSetRepeatRequest.State.Off; break; default: Debug.LogError($"Unknown Shuffle State '{currentShuffleState}'"); break; } // Build request and send PlayerSetRepeatRequest request = new PlayerSetRepeatRequest(newState); client.Player.SetRepeat(request); } }
/// <summary>Handles the currently playing context changed event.</summary> /// <param name="data">The object.</param> private void HandleCurrentlyPlayingContextChanged(CurrentlyPlayingContext data) { this.IsSelected = data.Context?.Uri == this.PlaylistUri && data.Item?.Uri == this.Uri; }
public static async Task <Skip> Skipped(Spotify user, FullTrack track, CurrentlyPlayingContext playing, SpotterAzure_dbContext dbContext) { if (user.Setting.SkipOn.Value && !(user.Setting.SkipIgnorePlaylist.Value && (playing.Context != null && playing.Context.Type == "playlist"))) { if (playing.Context == null || playing.Context.Type != "playlist" || !(await user.spotify.Playlists.Get(playing.Context.Href.Split('/').Last())).Name.EndsWith(user.Setting.SkipIgnorePostfix)) { List <bool> Exists = await user.spotify.Library.CheckTracks(new LibraryCheckTracksRequest(new List <string>() { track.Id })); if (Exists[0] || !user.Setting.SkipMustBeLiked.Value) { int recent = user.RecentSkips(track.Id, user.Setting.SkipExpiryHours.Value, dbContext); if (recent >= user.Setting.SkipTrigger - 1) { if (user.KickedTracks.Count(x => ((FullTrack)x.Track).Id == track.Id) == 0) { await user.spotify.Playlists.AddItems(user.KickedPlaylist.Id, new PlaylistAddItemsRequest(new List <string>() { track.Uri })); Track t = new Track(track, user); user.KickedTracks.Add(new PlaylistTrack <IPlayableItem>()); user.KickedTracks.Last().Track = track; } if (Exists[0]) { await user.spotify.Library.RemoveTracks(new LibraryRemoveTracksRequest(new List <string>() { track.Id })); } if (playing.Context.Type == "playlist" && user.Setting.SkipRemoveFromPlaylist.Value) { PlaylistRemoveItemsRequest removeReq = new PlaylistRemoveItemsRequest(); PlaylistRemoveItemsRequest.Item removeSongReq = new PlaylistRemoveItemsRequest.Item(); removeSongReq.Uri = track.Uri; removeReq.Tracks = new List <PlaylistRemoveItemsRequest.Item>() { removeSongReq }; await user.spotify.Playlists.RemoveItems(playing.Context.Href.Split('/').Last(), removeReq); } } else { } return(new Skip(track.Id, user)); } } } return(null); }
private static async void CheckUserEvent(Spotify user, SpotterAzure_dbContext dbContext) { CurrentlyPlayingContext playing = await user.spotify.Player.GetCurrentPlayback(); if (playing != null) { if (!lastTracks.ContainsKey(user.SpotId)) { lastTracks.Add(user.SpotId, playing); user.last = playing; user.lastTrack = (FullTrack)user.last.Item; } else if (playing.Item != null) { FullTrack track = (FullTrack)playing.Item; user.last = lastTracks[user.SpotId]; user.lastTrack = (FullTrack)user.last.Item; lastTracks[user.SpotId] = playing; //Check if skipped if (track.Id != user.lastTrack.Id) { Track t = new Track(track, user); Artist a = await t.GetArtist(user, dbContext); t.ArtistId = a.ArtistId; t.Artist = a; await t.GetFeatures(user, dbContext); if (!dbContext.Artists.Any(x => x.ArtistId == t.ArtistId)) { (await dbContext.Artists.AddAsync(a)).State = Microsoft.EntityFrameworkCore.EntityState.Added; } else if (!dbContext.Tracks.Any(x => x.TrackId == t.TrackId)) { (await dbContext.Tracks.AddAsync(t)).State = Microsoft.EntityFrameworkCore.EntityState.Added; } if (dbContext.Tracks.Any(x => x.TrackId == track.Id)) { t = dbContext.Tracks.Where(x => x.TrackId == track.Id).First(); if (t.Features == null) { await t.GetFeatures(user, dbContext); } if (t.Artist == null) { t.ArtistId = a.ArtistId; await t.GetArtist(user, dbContext); } dbContext.Tracks.Update(t); } if (user.last.ProgressMs < user.lastTrack.DurationMs * IsntSkip) { if (OnSkip != null) { Skip s = await OnSkip(user, user.lastTrack, playing, dbContext); if (s != null) { s.Track = t; await dbContext.Skips.AddAsync(s); } } } dbContext.Listens.Add(new Listen(track, user)); if (OnNextSong != null) { OnNextSong(user, playing); } } //Check if play state changed if (playing.IsPlaying != user.last.IsPlaying) { if (playing.IsPlaying) { if (OnResume != null) { OnResume(user, playing); } else if (OnPause != null) { OnPause(user, playing); } } } } } await dbContext.SaveChangesAsync(); }
/// <summary>Handles the currently playing context changed event.</summary> /// <param name="data">The data.</param> private void HandleCurrentlyPlayingContextChanged(CurrentlyPlayingContext data) { this.HasPlaybackState = true; }
private static void Play(object sender, CurrentlyPlayingContext track) { Console.WriteLine($"Playing"); }
private async Task GetCurrentlyPlaying() { _currentlyPlaying = await _spotifyClient.Player.GetCurrentPlayback(); }
private async void FetchLatestPlayer() { if (_client != null) { // get the current context on this run CurrentlyPlayingContext newContext = await _client.Player.GetCurrentPlayback(); // Check if not null if (newContext != null && newContext.Item != null) { // Check and cast the item to the correct type if (newContext.Item.Type == ItemType.Track) { FullTrack currentTrack = newContext.Item as FullTrack; // No previous track or previous item was different type if (_currentItem == null || (_currentItem != null && _currentItem is FullEpisode episode)) { Debug.Log($"No prev track or new type | -> '{S4UUtility.GetTrackString(currentTrack)}'"); _currentItem = currentTrack; OnPlayingItemChanged?.Invoke(_currentItem); } else if (_currentItem != null && _currentItem is FullTrack lastTrack) { // Check if track name & artists aren't the same if (lastTrack.Name != currentTrack.Name || S4UUtility.HasArtistsChanged(lastTrack.Artists, currentTrack.Artists)) { Debug.Log($"Track to new Track | '{S4UUtility.GetTrackString(lastTrack)}' -> '{S4UUtility.GetTrackString(currentTrack)}'"); _currentItem = currentTrack; OnPlayingItemChanged?.Invoke(_currentItem); } } } else if (newContext.Item.Type == ItemType.Episode) { FullEpisode currentEpisode = newContext.Item as FullEpisode; // If no previous item or current item is different type if (_currentItem == null || (_currentItem != null && _currentItem is FullTrack track)) { Debug.Log($"No prev episode or new type | -> '{currentEpisode.Show.Publisher} {currentEpisode.Name}'"); _currentItem = currentEpisode; OnPlayingItemChanged?.Invoke(_currentItem); } else if (_currentItem != null && _currentItem is FullEpisode lastEpisode) { if (lastEpisode.Name != currentEpisode.Name || lastEpisode.Show?.Publisher != currentEpisode.Show?.Publisher) { Debug.Log($"Episode to new Episode | '{lastEpisode.Show.Publisher} {lastEpisode.Name}' -> '{currentEpisode.Show.Publisher} {currentEpisode.Name}'"); _currentItem = currentEpisode; OnPlayingItemChanged?.Invoke(_currentItem); } } } } else { // No context or null current playing item // If previous item has been set if (_currentItem != null) { Debug.Log($"Context null | '{(_currentItem.Type == ItemType.Track ? (_currentItem as FullTrack).Name : (_currentItem as FullEpisode).Name)}' -> ?"); _currentItem = null; OnPlayingItemChanged?.Invoke(null); } } _currentContext = newContext; } else { // If no client but has a previous item, invoke event if (_currentItem != null) { _currentItem = null; OnPlayingItemChanged?.Invoke(null); } } }