aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon Garrelou <simon.garrelou@gmail.com>2022-12-09 15:21:04 +0100
committerSimon Garrelou <simon.garrelou@gmail.com>2022-12-09 15:21:04 +0100
commit9d1d1a02fde0a1561ad6a61e551a144bbeadc45b (patch)
tree7add9eb152c207e0e5cd3aaa6a3cd0b763f3ce4f
parent84665faeac2e721698dcfdb40d13a3db65e76f80 (diff)
downloadtermsonic-9d1d1a02fde0a1561ad6a61e551a144bbeadc45b.tar.gz
termsonic-9d1d1a02fde0a1561ad6a61e551a144bbeadc45b.zip
Add play queue page
-rw-r--r--music/playqueue.go17
-rw-r--r--src/app.go16
-rw-r--r--src/footer.go2
-rw-r--r--src/header.go4
-rw-r--r--src/keybinds.go22
-rw-r--r--src/page_artists.go13
-rw-r--r--src/page_queue.go38
7 files changed, 97 insertions, 15 deletions
diff --git a/music/playqueue.go b/music/playqueue.go
index 76d14df..fe82c4e 100644
--- a/music/playqueue.go
+++ b/music/playqueue.go
@@ -142,6 +142,23 @@ func (q *Queue) TogglePause() {
142 } 142 }
143} 143}
144 144
145func (q *Queue) SkipTo(s *subsonic.Child) {
146 i := -1
147 for n, s2 := range q.GetSongs() {
148 if s.ID == s2.ID {
149 i = n
150 break
151 }
152 }
153
154 if i == -1 {
155 return
156 }
157
158 q.songs = q.songs[i:]
159 q.Play()
160}
161
145func (p *Queue) setupSpeaker(s beep.Streamer, format beep.Format) (beep.Streamer, error) { 162func (p *Queue) setupSpeaker(s beep.Streamer, format beep.Format) (beep.Streamer, error) {
146 if !p.speakerInitialized { 163 if !p.speakerInitialized {
147 err := speaker.Init(format.SampleRate, format.SampleRate.N(time.Second/10)) 164 err := speaker.Init(format.SampleRate, format.SampleRate.N(time.Second/10))
diff --git a/src/app.go b/src/app.go
index 029644c..3a02dbe 100644
--- a/src/app.go
+++ b/src/app.go
@@ -19,10 +19,13 @@ type app struct {
19 footer *tview.TextView 19 footer *tview.TextView
20 cfg *Config 20 cfg *Config
21 21
22 // Artists panel 22 // Artists page
23 artistsTree *tview.TreeView 23 artistsTree *tview.TreeView
24 songsList *tview.List 24 songsList *tview.List
25 25
26 // Play queue page
27 playQueueList *tview.List
28
26 // Subsonic variables 29 // Subsonic variables
27 sub *subsonic.Client 30 sub *subsonic.Client
28 playQueue *music.Queue 31 playQueue *music.Queue
@@ -42,6 +45,7 @@ func Run(cfg *Config) {
42 a.pages.SetBorder(true) 45 a.pages.SetBorder(true)
43 a.pages.AddPage("config", a.configPage(), true, false) 46 a.pages.AddPage("config", a.configPage(), true, false)
44 a.pages.AddPage("artists", a.artistsPage(), true, false) 47 a.pages.AddPage("artists", a.artistsPage(), true, false)
48 a.pages.AddPage("playqueue", a.queuePage(), true, false)
45 49
46 mainLayout := tview.NewFlex(). 50 mainLayout := tview.NewFlex().
47 SetDirection(tview.FlexRow). 51 SetDirection(tview.FlexRow).
@@ -69,9 +73,12 @@ func Run(cfg *Config) {
69 a.switchToPage("artists") 73 a.switchToPage("artists")
70 return nil 74 return nil
71 case tcell.KeyF2: 75 case tcell.KeyF2:
72 a.switchToPage("playlists") 76 a.switchToPage("playqueue")
73 return nil 77 return nil
74 case tcell.KeyF3: 78 case tcell.KeyF3:
79 a.switchToPage("playlists")
80 return nil
81 case tcell.KeyF4:
75 a.switchToPage("config") 82 a.switchToPage("config")
76 return nil 83 return nil
77 } 84 }
@@ -97,6 +104,11 @@ func (a *app) switchToPage(name string) {
97 a.headerSections.Highlight("artists") 104 a.headerSections.Highlight("artists")
98 a.tv.SetFocus(a.artistsTree) 105 a.tv.SetFocus(a.artistsTree)
99 a.pages.SetBorder(false) 106 a.pages.SetBorder(false)
107 case "playqueue":
108 a.pages.SwitchToPage("playqueue")
109 a.headerSections.Highlight("playqueue")
110 a.tv.SetFocus(a.playQueueList)
111 a.pages.SetBorder(true)
100 case "playlists": 112 case "playlists":
101 a.pages.SwitchToPage("playlists") 113 a.pages.SwitchToPage("playlists")
102 a.headerSections.Highlight("playlists") 114 a.headerSections.Highlight("playlists")
diff --git a/src/footer.go b/src/footer.go
index 2695a61..7240b0f 100644
--- a/src/footer.go
+++ b/src/footer.go
@@ -4,6 +4,8 @@ func (a *app) updateFooter() {
4 switch a.headerSections.GetHighlights()[0] { 4 switch a.headerSections.GetHighlights()[0] {
5 case "artists": 5 case "artists":
6 a.footer.SetText("[blue]l:[yellow] Next song [blue]k:[yellow] Toggle pause") 6 a.footer.SetText("[blue]l:[yellow] Next song [blue]k:[yellow] Toggle pause")
7 case "playqueue":
8 a.footer.SetText("[blue]l:[yellow] Next song [blue]k:[yellow] Toggle pause")
7 case "playlists": 9 case "playlists":
8 a.footer.SetText("Come back later!") 10 a.footer.SetText("Come back later!")
9 case "config": 11 case "config":
diff --git a/src/header.go b/src/header.go
index e7b7eea..961e5b0 100644
--- a/src/header.go
+++ b/src/header.go
@@ -24,7 +24,7 @@ func (a *app) buildHeader() tview.Primitive {
24 a.switchToPage(hl) 24 a.switchToPage(hl)
25 } 25 }
26 }) 26 })
27 fmt.Fprintf(a.headerSections, `["artists"]F1: Artists[""] | ["playlists"]F2: Playlists[""] | ["config"]F3: Configuration[""]`) 27 fmt.Fprintf(a.headerSections, `["artists"]F1: Artists[""] | ["playqueue"]F2: Queue[""] | ["playlists"]F3: Playlists[""] | ["config"]F4: Configuration[""]`)
28 28
29 a.headerNowPlaying = tview.NewTextView().SetTextAlign(tview.AlignRight) 29 a.headerNowPlaying = tview.NewTextView().SetTextAlign(tview.AlignRight)
30 30
@@ -42,6 +42,8 @@ func (a *app) buildHeader() tview.Primitive {
42 a.headerNowPlaying.SetText("Not playing") 42 a.headerNowPlaying.SetText("Not playing")
43 } 43 }
44 44
45 a.updatePageQueue()
46
45 // Fix "Now Playing" not always updating 47 // Fix "Now Playing" not always updating
46 go a.tv.Draw() 48 go a.tv.Draw()
47 }) 49 })
diff --git a/src/keybinds.go b/src/keybinds.go
new file mode 100644
index 0000000..d69be0b
--- /dev/null
+++ b/src/keybinds.go
@@ -0,0 +1,22 @@
1package src
2
3import (
4 "github.com/gdamore/tcell/v2"
5 "github.com/rivo/tview"
6)
7
8func (a *app) setupMusicControlKeys(p *tview.Box) {
9 // Add 'k' and 'l' key bindings
10 p.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey {
11 if event.Rune() == 'l' {
12 a.playQueue.Next()
13 return nil
14 }
15
16 if event.Rune() == 'k' {
17 a.playQueue.TogglePause()
18 return nil
19 }
20 return event
21 })
22}
diff --git a/src/page_artists.go b/src/page_artists.go
index 4361767..104fdc7 100644
--- a/src/page_artists.go
+++ b/src/page_artists.go
@@ -61,18 +61,7 @@ func (a *app) artistsPage() tview.Primitive {
61 return event 61 return event
62 }) 62 })
63 63
64 grid.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey { 64 a.setupMusicControlKeys(grid.Box)
65 if event.Rune() == 'l' {
66 a.playQueue.Next()
67 return nil
68 }
69
70 if event.Rune() == 'k' {
71 a.playQueue.TogglePause()
72 return nil
73 }
74 return event
75 })
76 65
77 grid.AddItem(a.artistsTree, 0, 1, true) 66 grid.AddItem(a.artistsTree, 0, 1, true)
78 grid.AddItem(a.songsList, 0, 1, false) 67 grid.AddItem(a.songsList, 0, 1, false)
diff --git a/src/page_queue.go b/src/page_queue.go
new file mode 100644
index 0000000..fe8910f
--- /dev/null
+++ b/src/page_queue.go
@@ -0,0 +1,38 @@
1package src
2
3import (
4 "fmt"
5
6 "github.com/rivo/tview"
7)
8
9func (a *app) queuePage() tview.Primitive {
10 a.playQueueList = tview.NewList().
11 ShowSecondaryText(false).
12 SetHighlightFullLine(true)
13
14 a.setupMusicControlKeys(a.playQueueList.Box)
15
16 a.updatePageQueue()
17
18 return a.playQueueList
19}
20
21func (a *app) updatePageQueue() {
22 sel := a.playQueueList.GetCurrentItem()
23 a.playQueueList.Clear()
24
25 for _, song := range a.playQueue.GetSongs() {
26 ownSong := *song
27 a.playQueueList.AddItem(fmt.Sprintf("* %s - %s", song.Title, song.Artist), "", 0, func() {
28 a.playQueue.SkipTo(&ownSong)
29 a.playQueueList.SetCurrentItem(0)
30 })
31 }
32
33 if sel < a.playQueueList.GetItemCount() {
34 a.playQueueList.SetCurrentItem(sel)
35 } else {
36 a.playQueueList.SetCurrentItem(a.playQueueList.GetItemCount() - 1)
37 }
38}