private void UpdatePlaylistDetailsUI() { if (_playlist != null) { if (_headerParent) { _headerParent.gameObject.SetActive(true); } if (_headerImg != null) { SpotifyAPI.Web.Image image = S4UUtility.GetLowestResolutionImage(_playlist.Images, 300, 300); StartCoroutine(S4UUtility.LoadImageFromUrl(image?.Url, (loadedSprite) => { _headerImg.sprite = loadedSprite; })); } if (_headerTitle != null) { _headerTitle.text = _playlist.Name; } if (_headerDescription != null) { _headerDescription.text = _playlist.Description; } if (_headerDetails != null) { _headerDetails.text = $"{ _playlist.Owner.DisplayName} • {_playlist.Tracks.Total.Value} songs"; } if (_headerType != null) { _headerType.text = _playlist.Type.ToUpper(); } } }
private void UpdateUI() { if (_artist != null) { SetUIActive(true); if (_artistName != null) { _artistName.text = _artist.Name; } if (_icon != null) { // Update to target image size RectTransform rect = _icon.GetComponent <RectTransform>(); rect.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, ImageSize.x); rect.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, ImageSize.y); SpotifyAPI.Web.Image lowestResImg = S4UUtility.GetLowestResolutionImage(_artist.Images); StartCoroutine(S4UUtility.LoadImageFromUrl(lowestResImg?.Url, (sprite) => { _icon.sprite = sprite; })); } } else { SetUIActive(false); } }
public override void OnInspectorGUI() { GUIContent content; // Title EditorGUILayout.LabelField("General Config", EditorStyles.boldLabel); // Client ID content = new GUIContent("Spotify Client ID", "Your client id, found in your Spotify Dashboard. Don't have an id? Go here: https://developer.spotify.com/dashboard/"); _config.ClientID = EditorGUILayout.TextField(content, _config.ClientID); content = new GUIContent("Redirect URI", "The redirect uri used to pass Spotify authentification onto your app. This exact URI needs to be in your Spotify Dashboard. Dont change this if you don't know what you are doing."); _config.RedirectUri = EditorGUILayout.TextField(content, _config.RedirectUri); // API scopes content = new GUIContent("API Scopes", "All API scopes that will the user will be asked to authorize."); List <string> allScopes = S4UUtility.GetAllScopes(); _selectedScopesFlag = EditorGUILayout.MaskField(content, _selectedScopesFlag, allScopes.ToArray()); _config.APIScopes = FlagToAPIScopes(_selectedScopesFlag); EditorGUILayout.Space(); EditorGUILayout.HelpBox("The 'API Scopes' allow you to pick and choose which elements of the API you wish to use. It is recommended to select only the required scopes you need. \n\nFor more information, view the Spotify API guide on authorization scopes (Click the button below)", MessageType.Info); if (GUILayout.Button("Scopes Documentation")) { Application.OpenURL("https://developer.spotify.com/documentation/general/guides/scopes/"); } EditorGUILayout.Space(); }
public async void Start() { _loadParent.gameObject.SetActive(true); _headerParent.gameObject.SetActive(false); _songsParent.gameObject.SetActive(false); SpotifyClient client = SpotifyService.Instance.GetSpotifyClient(); if (client != null) { Paging <SavedTrack> paging = await client.Library.GetTracks(); // Load all saved tracks _allSavedTracks = await S4UUtility.GetAllOfPagingAsync(client, paging, MaximumLength) as List <SavedTrack>; // Only show cwer if (_allSavedTracks.Count > MaximumLength) { _allSavedTracks.RemoveRange(MaximumLength, (_allSavedTracks.Count - 1) - MaximumLength); } // Load current user to display creator PrivateUser profile = await SpotifyService.Instance.GetSpotifyClient().UserProfile.Current(); _creator = profile.DisplayName; _dispatcher.Add(() => { UpdateUI(); }); } }
// Updates the left hand side of the player (Artwork, track name, artists) private void UpdatePlayerInfo(string trackName, string artistNames, string artUrl) { if (_trackName != null) { _trackName.text = trackName; } if (_artistsNames != null) { _artistsNames.text = artistNames; } if (_trackIcon != null) { // Load sprite from url if (string.IsNullOrEmpty(artUrl)) { _trackIcon.sprite = null; } else { StartCoroutine(S4UUtility.LoadImageFromUrl(artUrl, (loadedSprite) => { _trackIcon.sprite = loadedSprite; })); } } }
public void StartAuthentification() { // Check if previous auth if (HasPreviousAuthentification()) { // Load local pkce saved token _pkceToken = LoadPKCEToken(); if (_pkceToken != null) { // Set API authenticator SetAuthenticator(_pkceToken); // if not expired, output expire time if (!_pkceToken.IsExpired) { DateTime expireDT = S4UUtility.GetTokenExpiry(_pkceToken.CreatedAt, _pkceToken.ExpiresIn); Debug.Log($"PKCE token loaded | Expires at '{expireDT.ToLocalTime()}'"); } } } else { // No previous auth, first time, get new GetFreshAuth(); } }
public DateTime GetExpiryDateTime() { if (_pkceToken != null) { return(S4UUtility.GetTokenExpiry(_pkceToken.CreatedAt, _pkceToken.ExpiresIn)); } return(DateTime.MinValue); }
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; } } } } }
private void DownloadUpdateSprite(Image img, List <SpotifyAPI.Web.Image> images) { if (img != null && img.sprite == null) { SpotifyAPI.Web.Image icon = S4UUtility.GetLowestResolutionImage(images); if (icon != null) { StartCoroutine(S4UUtility.LoadImageFromUrl(icon.Url, (loadedSprite) => { _icon.sprite = loadedSprite; })); } } }
protected override async void OnSpotifyConnectionChanged(SpotifyClient client) { base.OnSpotifyConnectionChanged(client); if (client != null) { bool isPremium = await S4UUtility.IsUserPremium(client); _dispatcher.Add(() => { _freeUserWarningParent.SetActive(!isPremium); }); } }
private async void PlayingItemChanged(IPlayableItem newPlayingItem) { if (newPlayingItem == null) { // No new item playing, reset UI UpdatePlayerInfo("No track playing", "No track playing", ""); SetLibraryBtnIsLiked(false); _currentProgressSlider.value = 0; _totalProgressText.text = _currentProgressText.text = "00:00"; } else { if (newPlayingItem.Type == ItemType.Track) { if (newPlayingItem is FullTrack track) { // Update player information with track info string allArtists = S4UUtility.ArtistsToSeparatedString(", ", track.Artists); SpotifyAPI.Web.Image image = S4UUtility.GetLowestResolutionImage(track.Album.Images); UpdatePlayerInfo(track.Name, allArtists, image?.Url); // Make request to see if track is part of user's library var client = SpotifyService.Instance.GetSpotifyClient(); LibraryCheckTracksRequest request = new LibraryCheckTracksRequest(new List <string>() { track.Id }); var result = await client.Library.CheckTracks(request); if (result.Count > 0) { SetLibraryBtnIsLiked(result[0]); } } } else if (newPlayingItem.Type == ItemType.Episode) { if (newPlayingItem is FullEpisode episode) { string creators = episode.Show.Publisher; SpotifyAPI.Web.Image image = S4UUtility.GetLowestResolutionImage(episode.Images); UpdatePlayerInfo(episode.Name, creators, image?.Url); } } } }
protected override async void OnSpotifyConnectionChanged(SpotifyClient client) { base.OnSpotifyConnectionChanged(client); // Check if we have permission to access logged in user's playlists if (SpotifyService.Instance.AreScopesAuthorized(Scopes.PlaylistReadPrivate)) { // Get first page from client Paging <SimplePlaylist> page = await client.Playlists.CurrentUsers(); // Get rest of pages from utility function and set variable to run on main thread _allPlaylists = await S4UUtility.GetAllOfPagingAsync(client, page); _isPopulated = false; } else { Debug.LogError($"Not authorized to access '{Scopes.PlaylistReadPrivate}'"); } }
private void UpdateUI() { if (_playlist != null) { if (_nameText != null) { _nameText.text = _playlist.Name; } if (_creatorText != null) { _creatorText.text = "By " + _playlist.Owner.DisplayName; } if (_icon != null) { SpotifyAPI.Web.Image image = S4UUtility.GetLowestResolutionImage(_playlist.Images); if (image != null) { StartCoroutine(S4UUtility.LoadImageFromUrl(image.Url, (loadedSprite) => { _icon.sprite = loadedSprite; })); } } if (_playPlaylistBtn != null) { _playPlaylistBtn.onClick.AddListener(() => { SpotifyClient client = SpotifyService.Instance.GetSpotifyClient(); PlayerResumePlaybackRequest request = new PlayerResumePlaybackRequest { ContextUri = _playlist.Uri }; client.Player.ResumePlayback(request); }); } } }
private void OnTokenRefreshed(object sender, PKCETokenResponse token) { DateTime expireDT = S4UUtility.GetTokenExpiry(token.CreatedAt, token.ExpiresIn); Debug.Log($"PKCE token refreshed | Expires at '{expireDT.ToLocalTime()}'"); bool triggerEvent = _pkceToken.IsExpired && !token.IsExpired; _pkceToken = token; if (PKCEConfig != null) { SavePKCEToken(_pkceToken); } if (triggerEvent) { Debug.Log("PKCE: Success in refreshing expired token into new token"); OnAuthenticatorComplete?.Invoke(_pkceAuthenticator); } }
private void UpdateUI() { if (_track != null) { if (_trackNameText != null) { _trackNameText.text = _track.Name; } if (_trackArtistsText != null) { _trackArtistsText.text = S4UUtility.ArtistsToSeparatedString(", ", _track.Artists); } if (_albumText != null) { _albumText.text = _track.Album.Name; } if (_durationText != null) { _durationText.text = S4UUtility.MsToTimeString(_track.DurationMs); } } }
/// <summary> /// Converts a flag number into the enabled API scopes /// </summary> /// <param name="flag"></param> /// <returns></returns> private List <string> FlagToAPIScopes(int flag) { List <string> allScopes = S4UUtility.GetAllScopes(); List <string> selectedScopes = new List <string>(); // Convert integer into binary string "10010101" string binaryString = Convert.ToString(flag, 2); // Reverse string so order matches list order var array = binaryString.ToCharArray(); Array.Reverse(array); binaryString = new string(array); // If binary longer than list, all selected if (binaryString.Length > allScopes.Count) { return(allScopes); // All selected } else if (binaryString.Length <= 0) { return(new List <string>()); // Empty, none selected } else { // Iterate through binary string, add scope if it is enabled in bianry string for (int i = 0; i < binaryString.Length; i++) { char currentBinaryValue = binaryString[i]; if (currentBinaryValue == '1') { selectedScopes.Add(allScopes[i]); } } return(selectedScopes); } }
private void UpdateUI() { if (_name != null) { _name.text = _track.Name; } if (_artist != null) { _artist.text = S4UUtility.ArtistsToSeparatedString(", ", _track.Artists); } if (_duration != null) { _duration.text = S4UUtility.MsToTimeString(_track.DurationMs); } if (_playBtn != null) { _playBtn.onClick.AddListener(() => { var client = SpotifyService.Instance.GetSpotifyClient(); if (client != null) { PlayerResumePlaybackRequest request = new PlayerResumePlaybackRequest() { //ContextUri = , // Play within context of just the individual track Uris = new List <string>() { _track.Uri }, }; client.Player.ResumePlayback(request); Debug.Log($"Spotify App | Playing searched song '{S4UUtility.ArtistsToSeparatedString(", ", _track.Artists)} - {_track.Name}'"); } }); } }
/// <summary> /// Gets a string to display a song and it's properties, separated with a dash. For example, "BLACKPINK - Don't Know What To Do" /// </summary> /// <param name="currentTrack"></param> /// <returns></returns> public static string GetTrackString(FullTrack track) { string artists = S4UUtility.ArtistsToSeparatedString(",", track.Artists); return(artists + " - " + track.Name); }
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); } } }
private void OnProgressSliderValueChanged(float newValueMs) { _progressDragNewValue = newValueMs; _currentProgressText.text = S4UUtility.MsToTimeString((int)_progressDragNewValue); }
private void LogTrackChange(string source) { Debug.Log($"Spotify App | {source} '{S4UUtility.ArtistsToSeparatedString(", ", _track.Artists)} - {_track.Name}'"); }