From 67d60877df816196e51b868e76f091261a2d08da Mon Sep 17 00:00:00 2001 From: Simon Garrelou Date: Fri, 9 Dec 2022 15:39:14 +0100 Subject: Move songs in queue --- music/playqueue.go | 59 ++++++++++++++++++++++++++++++++++++++++++++++-------- src/footer.go | 4 ++-- src/keybinds.go | 39 +++++++++++++++++++++++++++++++++++- 3 files changed, 91 insertions(+), 11 deletions(-) diff --git a/music/playqueue.go b/music/playqueue.go index fe82c4e..7c21b9b 100644 --- a/music/playqueue.go +++ b/music/playqueue.go @@ -81,9 +81,7 @@ func (q *Queue) PlaySong(s *subsonic.Child) error { speaker.Clear() speaker.Play(beep.Seq(streamer, beep.Callback(func() { go q.Next() }))) - if q.onChange != nil { - q.onChange(s, false) - } + q.triggerChange() return nil } @@ -135,11 +133,7 @@ func (q *Queue) TogglePause() { q.isPaused = !q.isPaused - if q.onChange != nil { - if len(q.songs) > 0 { - q.onChange(q.songs[0], q.isPaused) - } - } + q.triggerChange() } func (q *Queue) SkipTo(s *subsonic.Child) { @@ -159,6 +153,55 @@ func (q *Queue) SkipTo(s *subsonic.Child) { q.Play() } +func (q *Queue) RemoveSong(i int) error { + if i >= len(q.songs) { + return fmt.Errorf("index out of bounds") + } + + q.songs = append(q.songs[:i], q.songs[i+1:]...) + if i == 0 { + // We removed the first song: this stops it and prepares for the next + q.Stop() + if !q.isPaused { + q.Play() + } + } + q.triggerChange() + + return nil +} + +func (q *Queue) Switch(a, b int) error { + if a >= len(q.songs) { + return fmt.Errorf("%d is out of bounds", a) + } + + if b >= len(q.songs) { + return fmt.Errorf("%d is out of bounds", b) + } + + tmp := q.songs[a] + q.songs[a] = q.songs[b] + q.songs[b] = tmp + + if (a == 0 || b == 0) && !q.isPaused { + // If we're switching the first song, and it's currently playing, start Play() again + q.Play() + } + + q.triggerChange() + + return nil +} + +func (q *Queue) triggerChange() { + if q.onChange != nil { + if len(q.songs) > 0 { + q.onChange(q.songs[0], q.isPaused) + } + } +} + func (p *Queue) setupSpeaker(s beep.Streamer, format beep.Format) (beep.Streamer, error) { if !p.speakerInitialized { err := speaker.Init(format.SampleRate, format.SampleRate.N(time.Second/10)) diff --git a/src/footer.go b/src/footer.go index 7240b0f..1db1843 100644 --- a/src/footer.go +++ b/src/footer.go @@ -3,9 +3,9 @@ package src func (a *app) updateFooter() { switch a.headerSections.GetHighlights()[0] { case "artists": - a.footer.SetText("[blue]l:[yellow] Next song [blue]k:[yellow] Toggle pause") + a.footer.SetText("[blue]l:[yellow] Next song [blue]p:[yellow] Toggle pause") case "playqueue": - a.footer.SetText("[blue]l:[yellow] Next song [blue]k:[yellow] Toggle pause") + a.footer.SetText("[blue]l:[yellow] Next song [blue]p:[yellow] Toggle pause [blue]d:[yellow] Remove [blue]j:[yellow] Move up [blue]k:[yellow] Move down") case "playlists": a.footer.SetText("Come back later!") case "config": diff --git a/src/keybinds.go b/src/keybinds.go index d69be0b..2a9c16b 100644 --- a/src/keybinds.go +++ b/src/keybinds.go @@ -13,10 +13,47 @@ func (a *app) setupMusicControlKeys(p *tview.Box) { return nil } - if event.Rune() == 'k' { + if event.Rune() == 'p' { a.playQueue.TogglePause() return nil } + + if a.tv.GetFocus() == a.playQueueList { + if event.Rune() == 'd' { + sel := a.playQueueList.GetCurrentItem() + err := a.playQueue.RemoveSong(sel) + if err != nil { + a.alert("Error: %v", err) + } + } else if event.Rune() == 'k' { + sel := a.playQueueList.GetCurrentItem() + if sel == a.playQueueList.GetItemCount()-1 { + return nil + } + err := a.playQueue.Switch(sel, sel+1) + if err != nil { + a.alert("Error: %v", err) + } + + a.playQueueList.SetCurrentItem(sel + 1) + + return nil + } else if event.Rune() == 'j' { + sel := a.playQueueList.GetCurrentItem() + if sel == 0 { + return nil + } + err := a.playQueue.Switch(sel, sel-1) + if err != nil { + a.alert("Error: %v", err) + } + + a.playQueueList.SetCurrentItem(sel - 1) + + return nil + } + } + return event }) } -- cgit v1.2.3