diff --git a/Spoti15.cs b/Spoti15.cs index 89ecd67..a1871a1 100644 --- a/Spoti15.cs +++ b/Spoti15.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Windows.Forms; using System.Drawing; using System.Threading.Tasks; @@ -8,6 +8,7 @@ using SpotifyAPI.Web.Enums; using SpotifyAPI.Web.Models; using System.Globalization; +using System.IO; namespace Spoti15 { @@ -41,6 +42,7 @@ class Spoti15 private bool cachedLikedTrack = false; private bool likedSongNotification = false; private bool unlikedSongNotification = false; + private bool noSongPlayingNotification = false; private bool showingError = false; private string errorString = ""; private FullTrack likedOrUnlikedSong; @@ -115,25 +117,13 @@ private void CheckInput(object source, EventArgs e) inControlMenu = lcd.IsButtonPressed(LogiLcd.LcdButton.Mono3); if(inControlMenu && !seeking) { - bool btn2InCtlNow = lcd.IsButtonPressed(LogiLcd.LcdButton.Mono2); - if(btn2InCtlNow && !btn2Before) - { - var error = api.PausePlayback(); - if(error.HasError()) - { - showingError = true; - errorString = error.Error.Message; - hideErrorTimer = new Timer(); - hideErrorTimer.Enabled = true; - hideErrorTimer.Interval = 3000; - hideErrorTimer.Tick += OnErrorHidden; - } - } - btn2Before = btn2InCtlNow; - bool btn1InCtlNow = lcd.IsButtonPressed(LogiLcd.LcdButton.Mono1); if(btn1InCtlNow && !btn1Before) { + if (cachedPlayback == null || cachedPlayback.Item == null) + { + return; + } var error = api.SkipPlaybackToNext(); if (error.HasError()) { @@ -150,7 +140,20 @@ private void CheckInput(object source, EventArgs e) bool btn0InCtlNow = lcd.IsButtonPressed(LogiLcd.LcdButton.Mono0); if(btn0InCtlNow && !btn0Before) { - var error = api.SkipPlaybackToPrevious(); + var error = new ErrorResponse(); + if (cachedPlayback == null || cachedPlayback.Item == null) + { + return; + } + if ((double)cachedPlayback.ProgressMs >= 3000) + { + error = api.SeekPlayback(0); + } + else + { + error = api.SkipPlaybackToPrevious(); + } + if (error.HasError()) { showingError = true; @@ -165,10 +168,18 @@ private void CheckInput(object source, EventArgs e) return; } - if (seeking && !btn2Before && cachedPlayback != null && cachedPlayback.CurrentlyPlayingType != TrackType.Ad) + if ((seeking) && (!btn2Before) && (cachedPlayback != null) && (cachedPlayback.CurrentlyPlayingType != TrackType.Ad)) { + //skip seek position if nothing playing to prevent crash + if (cachedPlayback == null || cachedPlayback.Item == null) + { + return; + } // set seek position to current - currentSeekPosition = (double)cachedPlayback.ProgressMs / cachedPlayback.Item.DurationMs; + else + { + currentSeekPosition = (double)cachedPlayback.ProgressMs / cachedPlayback.Item.DurationMs; + } } btn2Before = seeking; @@ -222,12 +233,18 @@ private void CheckInput(object source, EventArgs e) var thisItem = cachedPlayback; if(thisItem == null || thisItem.Item == null) { + noSongPlayingNotification = true; + disableLikedSongNotificationTimer = new Timer(); + disableLikedSongNotificationTimer.Enabled = true; + disableLikedSongNotificationTimer.Interval = 5000; + disableLikedSongNotificationTimer.Tick += OnLikedSongNotificationFinished; + btn0Before = btn0Now; return; } - if(likedSongNotification || unlikedSongNotification) + if(likedSongNotification || unlikedSongNotification || noSongPlayingNotification) { - likedSongNotification = unlikedSongNotification = false; + likedSongNotification = unlikedSongNotification = noSongPlayingNotification = false; btn0Before = btn0Now; disableLikedSongNotificationTimer.Enabled = false; return; @@ -237,7 +254,7 @@ private void CheckInput(object source, EventArgs e) likedOrUnlikedSong = thisItem.Item; ListedItem.Add(likedOrUnlikedSong.Id); - if(cachedLikedTrack) + if (cachedLikedTrack) { api.RemoveSavedTracks(ListedItem); likedSongNotification = false; @@ -345,7 +362,7 @@ private void OnErrorHidden(object source, EventArgs e) private void OnLikedSongNotificationFinished(object source, EventArgs e) { - likedSongNotification = unlikedSongNotification = false; + likedSongNotification = unlikedSongNotification = noSongPlayingNotification = false; disableLikedSongNotificationTimer.Enabled = false; } @@ -812,7 +829,7 @@ private void DrawPlaylistStatus(Graphics g) } else { - DrawText(g, 3, "Unknown"); + DrawText(g, 0, "Liked Songs"); // refer to line 1043 } } @@ -842,9 +859,17 @@ public void UpdateLcd() { if(api == null) { - // TODO: draw spotify logo + // TODO: draw spotify logo (done) + var spotlogo = new byte[] { 66, 77, 150, 1, 0, 0, 0, 0, 0, 0, 62, 0, 0, 0, 40, 0, 0, 0, 43, 0, 0, 0, 43, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 196, 14, 0, 0, 196, 14, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 128, 0, 0, 0, 0, 0, 3, 255, 248, 0, 0, 0, 0, 0, 15, 255, 254, 0, 0, 0, 0, 0, 31, 255, 255, 0, 0, 0, 0, 0, 127, 255, 255, 192, 0, 0, 0, 0, 255, 255, 255, 224, 0, 0, 0, 1, 255, 255, 255, 240, 0, 0, 0, 3, 255, 255, 255, 248, 0, 0, 0, 7, 255, 255, 255, 252, 0, 0, 0, 7, 255, 255, 255, 252, 0, 0, 0, 15, 255, 255, 255, 254, 0, 0, 0, 31, 255, 255, 241, 255, 0, 0, 0, 31, 255, 255, 193, 255, 0, 0, 0, 31, 195, 254, 3, 255, 0, 0, 0, 63, 192, 0, 15, 255, 128, 0, 0, 63, 224, 0, 127, 255, 128, 0, 0, 63, 255, 255, 254, 127, 128, 0, 0, 63, 255, 255, 248, 127, 128, 0, 0, 63, 255, 255, 192, 127, 192, 0, 0, 127, 129, 248, 0, 255, 192, 0, 0, 127, 128, 0, 3, 255, 192, 0, 0, 127, 192, 0, 31, 255, 192, 0, 0, 63, 252, 3, 255, 223, 128, 0, 0, 63, 255, 255, 255, 15, 128, 0, 0, 63, 255, 255, 248, 15, 128, 0, 0, 63, 7, 255, 128, 31, 128, 0, 0, 63, 0, 0, 0, 63, 128, 0, 0, 31, 0, 0, 0, 255, 0, 0, 0, 31, 128, 0, 15, 255, 0, 0, 0, 31, 252, 0, 255, 255, 0, 0, 0, 15, 255, 255, 255, 254, 0, 0, 0, 7, 255, 255, 255, 252, 0, 0, 0, 7, 255, 255, 255, 252, 0, 0, 0, 3, 255, 255, 255, 248, 0, 0, 0, 1, 255, 255, 255, 240, 0, 0, 0, 0, 255, 255, 255, 224, 0, 0, 0, 0, 127, 255, 255, 192, 0, 0, 0, 0, 31, 255, 255, 0, 0, 0, 0, 0, 7, 255, 254, 0, 0, 0, 0, 0, 1, 255, 240, 0, 0, 0, 0, 0, 0, 31, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; + Bitmap bmp; + using (var ms = new MemoryStream(spotlogo)) + { + bmp = new Bitmap(ms); + } + int x = (LogiLcd.MonoWidth / 2) - 43 / 2; g.Clear(bgColor); - DrawTextScroll(g, 2, "SPOTIFY"); + g.DrawImage(bmp, x, 0); + //DrawTextScroll(g, 2, "SPOTI15", bigFont); } else if(showingError) { @@ -875,33 +900,45 @@ public void UpdateLcd() DrawPlaybackStatus(g, false); } - else if(seeking && cachedPlayback != null && cachedPlayback.Item != null) + else if (noSongPlayingNotification) { g.Clear(bgColor); + DrawTextScroll(g, 1, "CANNOT LIKE SONG", bigFont); + DrawTextScroll(g, 3, "Spotify not playing"); + } + else if(seeking && cachedPlayback != null) + { + g.Clear(bgColor); + DrawTextScroll(g, 1, "SEEKING", bigFont); - DrawTextScroll(g, 1, "SEEKING"); - - var posInMs = (int)(cachedPlayback.Item.DurationMs * currentSeekPosition); - DrawTextScroll(g, 3, string.Format("{0:D2}:{1:D2}", posInMs / 60000, (posInMs % 60000) / 1000)); + if (cachedPlayback.Item == null) + { + DrawTextScroll(g, 3, "Spotify not playing"); + } + else + { + var posInMs = (int)(cachedPlayback.Item.DurationMs * currentSeekPosition); + DrawTextScroll(g, 3, string.Format("{0:D2}:{1:D2}", posInMs / 60000, (posInMs % 60000) / 1000)); - // Draw progress bar - g.DrawRectangle(Pens.White, 8, LogiLcd.MonoHeight - 16, (LogiLcd.MonoWidth - 24), 6); - g.FillRectangle(Brushes.White, 8, LogiLcd.MonoHeight - 16, (int)((LogiLcd.MonoWidth - 24) * currentSeekPosition), 6); + // Draw progress bar + g.DrawRectangle(Pens.White, 8, LogiLcd.MonoHeight - 16, (LogiLcd.MonoWidth - 24), 6); + g.FillRectangle(Brushes.White, 8, LogiLcd.MonoHeight - 16, (int)((LogiLcd.MonoWidth - 24) * currentSeekPosition), 6); - g.FillPolygon(Brushes.White, new Point[] { - new Point((LogiLcd.MonoWidth - 19), LogiLcd.MonoHeight - 7), - new Point((LogiLcd.MonoWidth - 19), LogiLcd.MonoHeight - 1), - new Point((LogiLcd.MonoWidth - 14), LogiLcd.MonoHeight - 4) - }); + g.FillPolygon(Brushes.White, new Point[] { + new Point((LogiLcd.MonoWidth - 19), LogiLcd.MonoHeight - 7), + new Point((LogiLcd.MonoWidth - 19), LogiLcd.MonoHeight - 1), + new Point((LogiLcd.MonoWidth - 14), LogiLcd.MonoHeight - 4) + }); - g.FillPolygon(Brushes.White, new Point[] { - new Point(60, LogiLcd.MonoHeight - 7), - new Point(60, LogiLcd.MonoHeight - 1), - new Point(55, LogiLcd.MonoHeight - 4) - }); + g.FillPolygon(Brushes.White, new Point[] { + new Point(60, LogiLcd.MonoHeight - 7), + new Point(60, LogiLcd.MonoHeight - 1), + new Point(55, LogiLcd.MonoHeight - 4) + }); - DrawText(g, 6, "OK", iconFont, 8); - DrawPlaylistStatus(g); + DrawText(g, 6, "OK", iconFont, 8); + DrawPlaylistStatus(g); + } } else if(inControlMenu && cachedPlayback != null) { @@ -931,25 +968,18 @@ public void UpdateLcd() new Point(18, LogiLcd.MonoHeight - 4) }); - if (cachedPlayback.IsPlaying) - { - g.FillRectangle(Brushes.White, new Rectangle((LogiLcd.MonoWidth - 58), LogiLcd.MonoHeight - 6, 2, 5)); - g.FillRectangle(Brushes.White, new Rectangle((LogiLcd.MonoWidth - 61), LogiLcd.MonoHeight - 6, 2, 5)); - } - else - { - g.FillPolygon(Brushes.White, new Point[] { - new Point((LogiLcd.MonoWidth - 64), LogiLcd.MonoHeight - 7), - new Point((LogiLcd.MonoWidth - 64), LogiLcd.MonoHeight - 1), - new Point((LogiLcd.MonoWidth - 59), LogiLcd.MonoHeight - 4) - }); - } - DrawTextScroll(g, 1, "UP NEXT", bigFont); if(cachedPlayback.Context == null) { - + if (cachedPlayback.Item == null) + { + DrawTextScroll(g, 3, "Spotify not playing"); + } + else + { + DrawTextScroll(g, 3, "Unknown"); + } } else if (cachedPlayback.Context.Type == "playlist" && upNextPlaylistTrack != null) { @@ -986,7 +1016,31 @@ public void UpdateLcd() if(cachedPlayback.Context == null) { + if (cachedPlayback.Item == null) + { + DrawTextScroll(g, 1, "STOPPED", bigFont); + DrawTextScroll(g, 3, "Spotify not playing"); + } + else + { + DrawTextScroll(g, 1, "SINGLE", bigFont); + DrawTextScroll(g, 3, cachedPlayback.Item.Album.Name); + DrawTextScroll(g, 4, GetStringFromArtists(cachedPlayback.Item.Artists.ToArray())); + DrawTextScroll(g, 5, string.Format("Released {0}", cachedPlayback.Item.Album.ReleaseDate)); + if (cachedAlbum != null) + { + string genres = GetStringFromGenres(cachedAlbum.Genres.ToArray()); + if (genres == "") + { + DrawText(g, 0, string.Format("e {0}", cachedAlbum.Popularity), iconFont, 5, 5); + } + else + { + DrawTextScroll(g, 6, string.Format("{0} - {1} followers", GetStringFromGenres(cachedAlbum.Genres.ToArray()), cachedAlbum.Popularity)); + } + } + } } else if(cachedPlayback.Context.Type == "playlist") { @@ -1030,9 +1084,15 @@ public void UpdateLcd() DrawPlaybackStatus(g, true); } + else if(cachedPlayback.Context.Type == "collection") + { + DrawTextScroll(g, 1, "LIKED SONGS", bigFont); //tested, can't find anything that shows as a "collection" other than liked songs + + DrawPlaybackStatus(g, true); + } else { - DrawTextScroll(g, 1, cachedPlayback.Context.Type); + DrawTextScroll(g, 1, cachedPlayback.Context.Type, bigFont); } } else @@ -1041,11 +1101,14 @@ public void UpdateLcd() var playback = cachedPlayback; if (playback == null || playback.Item == null) { + string currentTime1 = DateTime.Now.ToString("h:mm:ss tt"); + Size textSize1 = TextRenderer.MeasureText(currentTime1, mainFont); + DrawText(g, 0, currentTime1, LogiLcd.MonoWidth - textSize1.Width); if (playback == null) { g.Clear(bgColor); - DrawTextScroll(g, 1, "ERROR"); - DrawTextScroll(g, 2, "SPOTIFY PLAYBACK NOT DETECTED"); + DrawTextScroll(g, 1, "STARTING", bigFont); + DrawTextScroll(g, 3, "Wait for API to initialize"); DoRender(); return; } @@ -1059,11 +1122,16 @@ public void UpdateLcd() else if (playback.HasError()) { g.Clear(bgColor); - DrawTextScroll(g, 1, "ERROR"); + DrawTextScroll(g, 1, "API ERROR"); DrawTextScroll(g, 2, playback.Error.Message); + DoRender(); + return; } else { + DrawTextScroll(g, 1, "NO TRACK INFORMATION", bigFont); + DrawTextScroll(g, 3, "Spotify not playing"); + DoRender(); return; } }