diff options
author | Simon Garrelou <simon.garrelou@gmail.com> | 2022-12-09 15:21:04 +0100 |
---|---|---|
committer | Simon Garrelou <simon.garrelou@gmail.com> | 2022-12-09 15:21:04 +0100 |
commit | 9d1d1a02fde0a1561ad6a61e551a144bbeadc45b (patch) | |
tree | 7add9eb152c207e0e5cd3aaa6a3cd0b763f3ce4f | |
parent | 84665faeac2e721698dcfdb40d13a3db65e76f80 (diff) | |
download | termsonic-9d1d1a02fde0a1561ad6a61e551a144bbeadc45b.tar.gz termsonic-9d1d1a02fde0a1561ad6a61e551a144bbeadc45b.zip |
Add play queue page
-rw-r--r-- | music/playqueue.go | 17 | ||||
-rw-r--r-- | src/app.go | 16 | ||||
-rw-r--r-- | src/footer.go | 2 | ||||
-rw-r--r-- | src/header.go | 4 | ||||
-rw-r--r-- | src/keybinds.go | 22 | ||||
-rw-r--r-- | src/page_artists.go | 13 | ||||
-rw-r--r-- | src/page_queue.go | 38 |
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 | ||
145 | func (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 | |||
145 | func (p *Queue) setupSpeaker(s beep.Streamer, format beep.Format) (beep.Streamer, error) { | 162 | func (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)) |
@@ -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 @@ | |||
1 | package src | ||
2 | |||
3 | import ( | ||
4 | "github.com/gdamore/tcell/v2" | ||
5 | "github.com/rivo/tview" | ||
6 | ) | ||
7 | |||
8 | func (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 @@ | |||
1 | package src | ||
2 | |||
3 | import ( | ||
4 | "fmt" | ||
5 | |||
6 | "github.com/rivo/tview" | ||
7 | ) | ||
8 | |||
9 | func (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 | |||
21 | func (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 | } | ||