aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsalmonik <raisersoft@proton.me>2026-05-16 12:47:43 +0200
committersalmonik <raisersoft@proton.me>2026-05-16 12:47:43 +0200
commit43562db0804338f2d55dff13439f1165f8dd9d3f (patch)
tree134248a95024815194d152de56f9b3f70d24d096
parentAdd scrobbling support (Last.fm + ListenBrainz) and rsp settings reload (diff)
downloadrsplayer-43562db0804338f2d55dff13439f1165f8dd9d3f.tar.gz
rsplayer-43562db0804338f2d55dff13439f1165f8dd9d3f.zip
first public release.
-rw-r--r--Cargo.lock2
-rw-r--r--Cargo.toml4
-rw-r--r--README.md53
-rw-r--r--completions/rsp.bash38
-rw-r--r--completions/rsp.elvish224
-rw-r--r--completions/rsp.fish37
-rw-r--r--completions/rsp.powershell280
-rw-r--r--completions/rsp.zsh23
-rwxr-xr-xinstall.sh9
-rw-r--r--src/daemon.rs32
-rw-r--r--src/notification.rs8
-rw-r--r--src/queue.rs16
12 files changed, 115 insertions, 611 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 923e985..6d359ef 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -2032,7 +2032,7 @@ dependencies = [
2032 2032
2033[[package]] 2033[[package]]
2034name = "rsp" 2034name = "rsp"
2035version = "0.8.0" 2035version = "0.8.1"
2036dependencies = [ 2036dependencies = [
2037 "chrono", 2037 "chrono",
2038 "clap", 2038 "clap",
diff --git a/Cargo.toml b/Cargo.toml
index 270ea7d..0393d3b 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,10 +1,10 @@
1[package] 1[package]
2name = "rsp" 2name = "rsp"
3version = "0.8.0" 3version = "0.8.1"
4edition = "2024" 4edition = "2024"
5description = "Rust music player daemon with Unix socket IPC" 5description = "Rust music player daemon with Unix socket IPC"
6license = "GPL-3.0 or later" 6license = "GPL-3.0 or later"
7repository = "https://github.com/yourusername/rsplayer" 7repository = "https://codeberg.org/salmonik/RSPlayer"
8keywords = ["music", "player", "daemon", "audio"] 8keywords = ["music", "player", "daemon", "audio"]
9categories = ["multimedia", "command-line-utilities"] 9categories = ["multimedia", "command-line-utilities"]
10 10
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..2092f2a
--- /dev/null
+++ b/README.md
@@ -0,0 +1,53 @@
1# RSPlayer is a daemon driven CLI music player with scrobbling written in rust
2
3## Installation
4```
5git clone https://codeberg.org/salmonik/RSPlayer.git
6cd RSPlayer
7./install.sh
8```
9
10install.sh will:
11compile RSP (make sure you have rust properly installed!)
12install shell autocompletions (zsh, bash and fish supported)
13install user systemd service and activate it
14
15## Usage
16
17configuration is generated at startup in $XDG_CONFIG_HOME/rsplayer/config.toml
18most important values there are:
19listenbrainz_token (last.fm scrobbling not yet tested)
20display_format (supports $ARTIST $ALBUM and $TRACK)
21music_paths (for DB usage, still WIP)
22scan_interval (same as above)
23
24all other values can be changed in runtime using commands
25
26as for commands:
27RSP will be installed as rsp, in this fragment, rsp will be ommited
28
29these commands should only be used in testing or by systemd service:
30`start-daemon` Start the daemon
31`stop-daemon` Stop the daemon
32`restart` Restart the daemon (kill existing and start new)
33
34these are normal commands:
35`play` Play a track, album, or artist
36`pause` Pause playback
37`resume` Resume playback
38`toggle` Toggle play/pause
39`stop` Stop playback
40`next` Skip to next track
41`previous` Skip to previous track
42`volume` Set volume (0-100)
43`shuffle` Shuffle mode
44`queue` Queue management
45`status` Show player status
46`scan` Scan music paths to populate database
47`settings` Settings management
48`help` Print this message or the help of the given subcommand(s)
49
50
51## Technical stuff
52The main culprit of this player is lack of integration with programs such as playerctl
53this is due to the daemon not being asynchronous
diff --git a/completions/rsp.bash b/completions/rsp.bash
index 1812802..c4e295f 100644
--- a/completions/rsp.bash
+++ b/completions/rsp.bash
@@ -16,9 +16,6 @@ _rsp() {
16 ",$1") 16 ",$1")
17 cmd="rsp" 17 cmd="rsp"
18 ;; 18 ;;
19 rsp,completions)
20 cmd="rsp__subcmd__completions"
21 ;;
22 rsp,help) 19 rsp,help)
23 cmd="rsp__subcmd__help" 20 cmd="rsp__subcmd__help"
24 ;; 21 ;;
@@ -70,9 +67,6 @@ _rsp() {
70 rsp,volume) 67 rsp,volume)
71 cmd="rsp__subcmd__volume" 68 cmd="rsp__subcmd__volume"
72 ;; 69 ;;
73 rsp__subcmd__help,completions)
74 cmd="rsp__subcmd__help__subcmd__completions"
75 ;;
76 rsp__subcmd__help,help) 70 rsp__subcmd__help,help)
77 cmd="rsp__subcmd__help__subcmd__help" 71 cmd="rsp__subcmd__help__subcmd__help"
78 ;; 72 ;;
@@ -173,7 +167,7 @@ _rsp() {
173 167
174 case "${cmd}" in 168 case "${cmd}" in
175 rsp) 169 rsp)
176 opts="-h --help start-daemon stop-daemon restart play pause resume toggle stop next previous volume shuffle queue status scan settings completions help" 170 opts="-h --help start-daemon stop-daemon restart play pause resume toggle stop next previous volume shuffle queue status scan settings help"
177 if [[ ${cur} == -* || ${COMP_CWORD} -eq 1 ]] ; then 171 if [[ ${cur} == -* || ${COMP_CWORD} -eq 1 ]] ; then
178 COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) 172 COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
179 return 0 173 return 0
@@ -186,22 +180,8 @@ _rsp() {
186 COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) 180 COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
187 return 0 181 return 0
188 ;; 182 ;;
189 rsp__subcmd__completions)
190 opts="-h --help [SHELL]"
191 if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
192 COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
193 return 0
194 fi
195 case "${prev}" in
196 *)
197 COMPREPLY=()
198 ;;
199 esac
200 COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
201 return 0
202 ;;
203 rsp__subcmd__help) 183 rsp__subcmd__help)
204 opts="start-daemon stop-daemon restart play pause resume toggle stop next previous volume shuffle queue status scan settings completions help" 184 opts="start-daemon stop-daemon restart play pause resume toggle stop next previous volume shuffle queue status scan settings help"
205 if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then 185 if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
206 COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) 186 COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
207 return 0 187 return 0
@@ -214,20 +194,6 @@ _rsp() {
214 COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) 194 COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
215 return 0 195 return 0
216 ;; 196 ;;
217 rsp__subcmd__help__subcmd__completions)
218 opts=""
219 if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then
220 COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
221 return 0
222 fi
223 case "${prev}" in
224 *)
225 COMPREPLY=()
226 ;;
227 esac
228 COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
229 return 0
230 ;;
231 rsp__subcmd__help__subcmd__help) 197 rsp__subcmd__help__subcmd__help)
232 opts="" 198 opts=""
233 if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then 199 if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then
diff --git a/completions/rsp.elvish b/completions/rsp.elvish
deleted file mode 100644
index 54ccdfe..0000000
--- a/completions/rsp.elvish
+++ /dev/null
@@ -1,224 +0,0 @@
1
2use builtin;
3use str;
4
5set edit:completion:arg-completer[rsp] = {|@words|
6 fn spaces {|n|
7 builtin:repeat $n ' ' | str:join ''
8 }
9 fn cand {|text desc|
10 edit:complex-candidate $text &display=$text' '(spaces (- 14 (wcswidth $text)))$desc
11 }
12 var command = 'rsp'
13 for word $words[1..-1] {
14 if (str:has-prefix $word '-') {
15 break
16 }
17 set command = $command';'$word
18 }
19 var completions = [
20 &'rsp'= {
21 cand -h 'Print help'
22 cand --help 'Print help'
23 cand start-daemon 'Start the daemon'
24 cand stop-daemon 'Stop the daemon'
25 cand restart 'Restart the daemon (kill existing and start new)'
26 cand play 'Play a track, album, or artist'
27 cand pause 'Pause playback'
28 cand resume 'Resume playback'
29 cand toggle 'Toggle play/pause'
30 cand stop 'Stop playback'
31 cand next 'Skip to next track'
32 cand previous 'Skip to previous track'
33 cand volume 'Set volume (0-100)'
34 cand shuffle 'Shuffle mode'
35 cand queue 'Queue management'
36 cand status 'Show player status'
37 cand scan 'Scan music paths to populate database'
38 cand settings 'Settings management'
39 cand completions 'Generate shell completions (developer only)'
40 cand help 'Print this message or the help of the given subcommand(s)'
41 }
42 &'rsp;start-daemon'= {
43 cand -h 'Print help'
44 cand --help 'Print help'
45 }
46 &'rsp;stop-daemon'= {
47 cand -h 'Print help'
48 cand --help 'Print help'
49 }
50 &'rsp;restart'= {
51 cand -h 'Print help'
52 cand --help 'Print help'
53 }
54 &'rsp;play'= {
55 cand -i 'Add after current track and skip to it'
56 cand --now 'Add after current track and skip to it'
57 cand -n 'Add to queue after current track (don''t skip)'
58 cand --next 'Add to queue after current track (don''t skip)'
59 cand -h 'Print help'
60 cand --help 'Print help'
61 }
62 &'rsp;pause'= {
63 cand -h 'Print help'
64 cand --help 'Print help'
65 }
66 &'rsp;resume'= {
67 cand -h 'Print help'
68 cand --help 'Print help'
69 }
70 &'rsp;toggle'= {
71 cand -h 'Print help'
72 cand --help 'Print help'
73 }
74 &'rsp;stop'= {
75 cand -h 'Print help'
76 cand --help 'Print help'
77 }
78 &'rsp;next'= {
79 cand -h 'Print help'
80 cand --help 'Print help'
81 }
82 &'rsp;previous'= {
83 cand -h 'Print help'
84 cand --help 'Print help'
85 }
86 &'rsp;volume'= {
87 cand -h 'Print help'
88 cand --help 'Print help'
89 }
90 &'rsp;shuffle'= {
91 cand -h 'Print help'
92 cand --help 'Print help'
93 }
94 &'rsp;queue'= {
95 cand -h 'Print help'
96 cand --help 'Print help'
97 }
98 &'rsp;status'= {
99 cand -h 'Print help'
100 cand --help 'Print help'
101 }
102 &'rsp;scan'= {
103 cand --paths 'paths'
104 cand --force 'force'
105 cand -h 'Print help'
106 cand --help 'Print help'
107 }
108 &'rsp;settings'= {
109 cand -h 'Print help'
110 cand --help 'Print help'
111 cand get 'Get a setting value'
112 cand set 'Set a setting value'
113 cand list 'List all settings'
114 cand unset 'Unset a setting'
115 cand help 'Print this message or the help of the given subcommand(s)'
116 }
117 &'rsp;settings;get'= {
118 cand -h 'Print help'
119 cand --help 'Print help'
120 }
121 &'rsp;settings;set'= {
122 cand -h 'Print help'
123 cand --help 'Print help'
124 }
125 &'rsp;settings;list'= {
126 cand -h 'Print help'
127 cand --help 'Print help'
128 }
129 &'rsp;settings;unset'= {
130 cand -h 'Print help'
131 cand --help 'Print help'
132 }
133 &'rsp;settings;help'= {
134 cand get 'Get a setting value'
135 cand set 'Set a setting value'
136 cand list 'List all settings'
137 cand unset 'Unset a setting'
138 cand help 'Print this message or the help of the given subcommand(s)'
139 }
140 &'rsp;settings;help;get'= {
141 }
142 &'rsp;settings;help;set'= {
143 }
144 &'rsp;settings;help;list'= {
145 }
146 &'rsp;settings;help;unset'= {
147 }
148 &'rsp;settings;help;help'= {
149 }
150 &'rsp;completions'= {
151 cand -h 'Print help'
152 cand --help 'Print help'
153 }
154 &'rsp;help'= {
155 cand start-daemon 'Start the daemon'
156 cand stop-daemon 'Stop the daemon'
157 cand restart 'Restart the daemon (kill existing and start new)'
158 cand play 'Play a track, album, or artist'
159 cand pause 'Pause playback'
160 cand resume 'Resume playback'
161 cand toggle 'Toggle play/pause'
162 cand stop 'Stop playback'
163 cand next 'Skip to next track'
164 cand previous 'Skip to previous track'
165 cand volume 'Set volume (0-100)'
166 cand shuffle 'Shuffle mode'
167 cand queue 'Queue management'
168 cand status 'Show player status'
169 cand scan 'Scan music paths to populate database'
170 cand settings 'Settings management'
171 cand completions 'Generate shell completions (developer only)'
172 cand help 'Print this message or the help of the given subcommand(s)'
173 }
174 &'rsp;help;start-daemon'= {
175 }
176 &'rsp;help;stop-daemon'= {
177 }
178 &'rsp;help;restart'= {
179 }
180 &'rsp;help;play'= {
181 }
182 &'rsp;help;pause'= {
183 }
184 &'rsp;help;resume'= {
185 }
186 &'rsp;help;toggle'= {
187 }
188 &'rsp;help;stop'= {
189 }
190 &'rsp;help;next'= {
191 }
192 &'rsp;help;previous'= {
193 }
194 &'rsp;help;volume'= {
195 }
196 &'rsp;help;shuffle'= {
197 }
198 &'rsp;help;queue'= {
199 }
200 &'rsp;help;status'= {
201 }
202 &'rsp;help;scan'= {
203 }
204 &'rsp;help;settings'= {
205 cand get 'Get a setting value'
206 cand set 'Set a setting value'
207 cand list 'List all settings'
208 cand unset 'Unset a setting'
209 }
210 &'rsp;help;settings;get'= {
211 }
212 &'rsp;help;settings;set'= {
213 }
214 &'rsp;help;settings;list'= {
215 }
216 &'rsp;help;settings;unset'= {
217 }
218 &'rsp;help;completions'= {
219 }
220 &'rsp;help;help'= {
221 }
222 ]
223 $completions[$command]
224}
diff --git a/completions/rsp.fish b/completions/rsp.fish
index 265fe37..8764bb9 100644
--- a/completions/rsp.fish
+++ b/completions/rsp.fish
@@ -41,7 +41,6 @@ complete -c rsp -n "__fish_rsp_needs_command" -f -a "queue" -d 'Queue management
41complete -c rsp -n "__fish_rsp_needs_command" -f -a "status" -d 'Show player status' 41complete -c rsp -n "__fish_rsp_needs_command" -f -a "status" -d 'Show player status'
42complete -c rsp -n "__fish_rsp_needs_command" -f -a "scan" -d 'Scan music paths to populate database' 42complete -c rsp -n "__fish_rsp_needs_command" -f -a "scan" -d 'Scan music paths to populate database'
43complete -c rsp -n "__fish_rsp_needs_command" -f -a "settings" -d 'Settings management' 43complete -c rsp -n "__fish_rsp_needs_command" -f -a "settings" -d 'Settings management'
44complete -c rsp -n "__fish_rsp_needs_command" -f -a "completions" -d 'Generate shell completions (developer only)'
45complete -c rsp -n "__fish_rsp_needs_command" -f -a "help" -d 'Print this message or the help of the given subcommand(s)' 44complete -c rsp -n "__fish_rsp_needs_command" -f -a "help" -d 'Print this message or the help of the given subcommand(s)'
46complete -c rsp -n "__fish_rsp_using_subcommand start-daemon" -s h -l help -d 'Print help' 45complete -c rsp -n "__fish_rsp_using_subcommand start-daemon" -s h -l help -d 'Print help'
47complete -c rsp -n "__fish_rsp_using_subcommand stop-daemon" -s h -l help -d 'Print help' 46complete -c rsp -n "__fish_rsp_using_subcommand stop-daemon" -s h -l help -d 'Print help'
@@ -77,25 +76,23 @@ complete -c rsp -n "__fish_rsp_using_subcommand settings; and __fish_seen_subcom
77complete -c rsp -n "__fish_rsp_using_subcommand settings; and __fish_seen_subcommand_from help" -f -a "list" -d 'List all settings' 76complete -c rsp -n "__fish_rsp_using_subcommand settings; and __fish_seen_subcommand_from help" -f -a "list" -d 'List all settings'
78complete -c rsp -n "__fish_rsp_using_subcommand settings; and __fish_seen_subcommand_from help" -f -a "unset" -d 'Unset a setting' 77complete -c rsp -n "__fish_rsp_using_subcommand settings; and __fish_seen_subcommand_from help" -f -a "unset" -d 'Unset a setting'
79complete -c rsp -n "__fish_rsp_using_subcommand settings; and __fish_seen_subcommand_from help" -f -a "help" -d 'Print this message or the help of the given subcommand(s)' 78complete -c rsp -n "__fish_rsp_using_subcommand settings; and __fish_seen_subcommand_from help" -f -a "help" -d 'Print this message or the help of the given subcommand(s)'
80complete -c rsp -n "__fish_rsp_using_subcommand completions" -s h -l help -d 'Print help' 79complete -c rsp -n "__fish_rsp_using_subcommand help; and not __fish_seen_subcommand_from start-daemon stop-daemon restart play pause resume toggle stop next previous volume shuffle queue status scan settings help" -f -a "start-daemon" -d 'Start the daemon'
81complete -c rsp -n "__fish_rsp_using_subcommand help; and not __fish_seen_subcommand_from start-daemon stop-daemon restart play pause resume toggle stop next previous volume shuffle queue status scan settings completions help" -f -a "start-daemon" -d 'Start the daemon' 80complete -c rsp -n "__fish_rsp_using_subcommand help; and not __fish_seen_subcommand_from start-daemon stop-daemon restart play pause resume toggle stop next previous volume shuffle queue status scan settings help" -f -a "stop-daemon" -d 'Stop the daemon'
82complete -c rsp -n "__fish_rsp_using_subcommand help; and not __fish_seen_subcommand_from start-daemon stop-daemon restart play pause resume toggle stop next previous volume shuffle queue status scan settings completions help" -f -a "stop-daemon" -d 'Stop the daemon' 81complete -c rsp -n "__fish_rsp_using_subcommand help; and not __fish_seen_subcommand_from start-daemon stop-daemon restart play pause resume toggle stop next previous volume shuffle queue status scan settings help" -f -a "restart" -d 'Restart the daemon (kill existing and start new)'
83complete -c rsp -n "__fish_rsp_using_subcommand help; and not __fish_seen_subcommand_from start-daemon stop-daemon restart play pause resume toggle stop next previous volume shuffle queue status scan settings completions help" -f -a "restart" -d 'Restart the daemon (kill existing and start new)' 82complete -c rsp -n "__fish_rsp_using_subcommand help; and not __fish_seen_subcommand_from start-daemon stop-daemon restart play pause resume toggle stop next previous volume shuffle queue status scan settings help" -f -a "play" -d 'Play a track, album, or artist'
84complete -c rsp -n "__fish_rsp_using_subcommand help; and not __fish_seen_subcommand_from start-daemon stop-daemon restart play pause resume toggle stop next previous volume shuffle queue status scan settings completions help" -f -a "play" -d 'Play a track, album, or artist' 83complete -c rsp -n "__fish_rsp_using_subcommand help; and not __fish_seen_subcommand_from start-daemon stop-daemon restart play pause resume toggle stop next previous volume shuffle queue status scan settings help" -f -a "pause" -d 'Pause playback'
85complete -c rsp -n "__fish_rsp_using_subcommand help; and not __fish_seen_subcommand_from start-daemon stop-daemon restart play pause resume toggle stop next previous volume shuffle queue status scan settings completions help" -f -a "pause" -d 'Pause playback' 84complete -c rsp -n "__fish_rsp_using_subcommand help; and not __fish_seen_subcommand_from start-daemon stop-daemon restart play pause resume toggle stop next previous volume shuffle queue status scan settings help" -f -a "resume" -d 'Resume playback'
86complete -c rsp -n "__fish_rsp_using_subcommand help; and not __fish_seen_subcommand_from start-daemon stop-daemon restart play pause resume toggle stop next previous volume shuffle queue status scan settings completions help" -f -a "resume" -d 'Resume playback' 85complete -c rsp -n "__fish_rsp_using_subcommand help; and not __fish_seen_subcommand_from start-daemon stop-daemon restart play pause resume toggle stop next previous volume shuffle queue status scan settings help" -f -a "toggle" -d 'Toggle play/pause'
87complete -c rsp -n "__fish_rsp_using_subcommand help; and not __fish_seen_subcommand_from start-daemon stop-daemon restart play pause resume toggle stop next previous volume shuffle queue status scan settings completions help" -f -a "toggle" -d 'Toggle play/pause' 86complete -c rsp -n "__fish_rsp_using_subcommand help; and not __fish_seen_subcommand_from start-daemon stop-daemon restart play pause resume toggle stop next previous volume shuffle queue status scan settings help" -f -a "stop" -d 'Stop playback'
88complete -c rsp -n "__fish_rsp_using_subcommand help; and not __fish_seen_subcommand_from start-daemon stop-daemon restart play pause resume toggle stop next previous volume shuffle queue status scan settings completions help" -f -a "stop" -d 'Stop playback' 87complete -c rsp -n "__fish_rsp_using_subcommand help; and not __fish_seen_subcommand_from start-daemon stop-daemon restart play pause resume toggle stop next previous volume shuffle queue status scan settings help" -f -a "next" -d 'Skip to next track'
89complete -c rsp -n "__fish_rsp_using_subcommand help; and not __fish_seen_subcommand_from start-daemon stop-daemon restart play pause resume toggle stop next previous volume shuffle queue status scan settings completions help" -f -a "next" -d 'Skip to next track' 88complete -c rsp -n "__fish_rsp_using_subcommand help; and not __fish_seen_subcommand_from start-daemon stop-daemon restart play pause resume toggle stop next previous volume shuffle queue status scan settings help" -f -a "previous" -d 'Skip to previous track'
90complete -c rsp -n "__fish_rsp_using_subcommand help; and not __fish_seen_subcommand_from start-daemon stop-daemon restart play pause resume toggle stop next previous volume shuffle queue status scan settings completions help" -f -a "previous" -d 'Skip to previous track' 89complete -c rsp -n "__fish_rsp_using_subcommand help; and not __fish_seen_subcommand_from start-daemon stop-daemon restart play pause resume toggle stop next previous volume shuffle queue status scan settings help" -f -a "volume" -d 'Set volume (0-100)'
91complete -c rsp -n "__fish_rsp_using_subcommand help; and not __fish_seen_subcommand_from start-daemon stop-daemon restart play pause resume toggle stop next previous volume shuffle queue status scan settings completions help" -f -a "volume" -d 'Set volume (0-100)' 90complete -c rsp -n "__fish_rsp_using_subcommand help; and not __fish_seen_subcommand_from start-daemon stop-daemon restart play pause resume toggle stop next previous volume shuffle queue status scan settings help" -f -a "shuffle" -d 'Shuffle mode'
92complete -c rsp -n "__fish_rsp_using_subcommand help; and not __fish_seen_subcommand_from start-daemon stop-daemon restart play pause resume toggle stop next previous volume shuffle queue status scan settings completions help" -f -a "shuffle" -d 'Shuffle mode' 91complete -c rsp -n "__fish_rsp_using_subcommand help; and not __fish_seen_subcommand_from start-daemon stop-daemon restart play pause resume toggle stop next previous volume shuffle queue status scan settings help" -f -a "queue" -d 'Queue management'
93complete -c rsp -n "__fish_rsp_using_subcommand help; and not __fish_seen_subcommand_from start-daemon stop-daemon restart play pause resume toggle stop next previous volume shuffle queue status scan settings completions help" -f -a "queue" -d 'Queue management' 92complete -c rsp -n "__fish_rsp_using_subcommand help; and not __fish_seen_subcommand_from start-daemon stop-daemon restart play pause resume toggle stop next previous volume shuffle queue status scan settings help" -f -a "status" -d 'Show player status'
94complete -c rsp -n "__fish_rsp_using_subcommand help; and not __fish_seen_subcommand_from start-daemon stop-daemon restart play pause resume toggle stop next previous volume shuffle queue status scan settings completions help" -f -a "status" -d 'Show player status' 93complete -c rsp -n "__fish_rsp_using_subcommand help; and not __fish_seen_subcommand_from start-daemon stop-daemon restart play pause resume toggle stop next previous volume shuffle queue status scan settings help" -f -a "scan" -d 'Scan music paths to populate database'
95complete -c rsp -n "__fish_rsp_using_subcommand help; and not __fish_seen_subcommand_from start-daemon stop-daemon restart play pause resume toggle stop next previous volume shuffle queue status scan settings completions help" -f -a "scan" -d 'Scan music paths to populate database' 94complete -c rsp -n "__fish_rsp_using_subcommand help; and not __fish_seen_subcommand_from start-daemon stop-daemon restart play pause resume toggle stop next previous volume shuffle queue status scan settings help" -f -a "settings" -d 'Settings management'
96complete -c rsp -n "__fish_rsp_using_subcommand help; and not __fish_seen_subcommand_from start-daemon stop-daemon restart play pause resume toggle stop next previous volume shuffle queue status scan settings completions help" -f -a "settings" -d 'Settings management' 95complete -c rsp -n "__fish_rsp_using_subcommand help; and not __fish_seen_subcommand_from start-daemon stop-daemon restart play pause resume toggle stop next previous volume shuffle queue status scan settings help" -f -a "help" -d 'Print this message or the help of the given subcommand(s)'
97complete -c rsp -n "__fish_rsp_using_subcommand help; and not __fish_seen_subcommand_from start-daemon stop-daemon restart play pause resume toggle stop next previous volume shuffle queue status scan settings completions help" -f -a "completions" -d 'Generate shell completions (developer only)'
98complete -c rsp -n "__fish_rsp_using_subcommand help; and not __fish_seen_subcommand_from start-daemon stop-daemon restart play pause resume toggle stop next previous volume shuffle queue status scan settings completions help" -f -a "help" -d 'Print this message or the help of the given subcommand(s)'
99complete -c rsp -n "__fish_rsp_using_subcommand help; and __fish_seen_subcommand_from settings" -f -a "get" -d 'Get a setting value' 96complete -c rsp -n "__fish_rsp_using_subcommand help; and __fish_seen_subcommand_from settings" -f -a "get" -d 'Get a setting value'
100complete -c rsp -n "__fish_rsp_using_subcommand help; and __fish_seen_subcommand_from settings" -f -a "set" -d 'Set a setting value' 97complete -c rsp -n "__fish_rsp_using_subcommand help; and __fish_seen_subcommand_from settings" -f -a "set" -d 'Set a setting value'
101complete -c rsp -n "__fish_rsp_using_subcommand help; and __fish_seen_subcommand_from settings" -f -a "list" -d 'List all settings' 98complete -c rsp -n "__fish_rsp_using_subcommand help; and __fish_seen_subcommand_from settings" -f -a "list" -d 'List all settings'
diff --git a/completions/rsp.powershell b/completions/rsp.powershell
deleted file mode 100644
index 58db681..0000000
--- a/completions/rsp.powershell
+++ /dev/null
@@ -1,280 +0,0 @@
1
2using namespace System.Management.Automation
3using namespace System.Management.Automation.Language
4
5Register-ArgumentCompleter -Native -CommandName 'rsp' -ScriptBlock {
6 param($wordToComplete, $commandAst, $cursorPosition)
7
8 $commandElements = $commandAst.CommandElements
9 $command = @(
10 'rsp'
11 for ($i = 1; $i -lt $commandElements.Count; $i++) {
12 $element = $commandElements[$i]
13 if ($element -isnot [StringConstantExpressionAst] -or
14 $element.StringConstantType -ne [StringConstantType]::BareWord -or
15 $element.Value.StartsWith('-') -or
16 $element.Value -eq $wordToComplete) {
17 break
18 }
19 $element.Value
20 }) -join ';'
21
22 $completions = @(switch ($command) {
23 'rsp' {
24 [CompletionResult]::new('-h', '-h', [CompletionResultType]::ParameterName, 'Print help')
25 [CompletionResult]::new('--help', '--help', [CompletionResultType]::ParameterName, 'Print help')
26 [CompletionResult]::new('start-daemon', 'start-daemon', [CompletionResultType]::ParameterValue, 'Start the daemon')
27 [CompletionResult]::new('stop-daemon', 'stop-daemon', [CompletionResultType]::ParameterValue, 'Stop the daemon')
28 [CompletionResult]::new('restart', 'restart', [CompletionResultType]::ParameterValue, 'Restart the daemon (kill existing and start new)')
29 [CompletionResult]::new('play', 'play', [CompletionResultType]::ParameterValue, 'Play a track, album, or artist')
30 [CompletionResult]::new('pause', 'pause', [CompletionResultType]::ParameterValue, 'Pause playback')
31 [CompletionResult]::new('resume', 'resume', [CompletionResultType]::ParameterValue, 'Resume playback')
32 [CompletionResult]::new('toggle', 'toggle', [CompletionResultType]::ParameterValue, 'Toggle play/pause')
33 [CompletionResult]::new('stop', 'stop', [CompletionResultType]::ParameterValue, 'Stop playback')
34 [CompletionResult]::new('next', 'next', [CompletionResultType]::ParameterValue, 'Skip to next track')
35 [CompletionResult]::new('previous', 'previous', [CompletionResultType]::ParameterValue, 'Skip to previous track')
36 [CompletionResult]::new('volume', 'volume', [CompletionResultType]::ParameterValue, 'Set volume (0-100)')
37 [CompletionResult]::new('shuffle', 'shuffle', [CompletionResultType]::ParameterValue, 'Shuffle mode')
38 [CompletionResult]::new('queue', 'queue', [CompletionResultType]::ParameterValue, 'Queue management')
39 [CompletionResult]::new('status', 'status', [CompletionResultType]::ParameterValue, 'Show player status')
40 [CompletionResult]::new('scan', 'scan', [CompletionResultType]::ParameterValue, 'Scan music paths to populate database')
41 [CompletionResult]::new('settings', 'settings', [CompletionResultType]::ParameterValue, 'Settings management')
42 [CompletionResult]::new('completions', 'completions', [CompletionResultType]::ParameterValue, 'Generate shell completions (developer only)')
43 [CompletionResult]::new('help', 'help', [CompletionResultType]::ParameterValue, 'Print this message or the help of the given subcommand(s)')
44 break
45 }
46 'rsp;start-daemon' {
47 [CompletionResult]::new('-h', '-h', [CompletionResultType]::ParameterName, 'Print help')
48 [CompletionResult]::new('--help', '--help', [CompletionResultType]::ParameterName, 'Print help')
49 break
50 }
51 'rsp;stop-daemon' {
52 [CompletionResult]::new('-h', '-h', [CompletionResultType]::ParameterName, 'Print help')
53 [CompletionResult]::new('--help', '--help', [CompletionResultType]::ParameterName, 'Print help')
54 break
55 }
56 'rsp;restart' {
57 [CompletionResult]::new('-h', '-h', [CompletionResultType]::ParameterName, 'Print help')
58 [CompletionResult]::new('--help', '--help', [CompletionResultType]::ParameterName, 'Print help')
59 break
60 }
61 'rsp;play' {
62 [CompletionResult]::new('-i', '-i', [CompletionResultType]::ParameterName, 'Add after current track and skip to it')
63 [CompletionResult]::new('--now', '--now', [CompletionResultType]::ParameterName, 'Add after current track and skip to it')
64 [CompletionResult]::new('-n', '-n', [CompletionResultType]::ParameterName, 'Add to queue after current track (don''t skip)')
65 [CompletionResult]::new('--next', '--next', [CompletionResultType]::ParameterName, 'Add to queue after current track (don''t skip)')
66 [CompletionResult]::new('-h', '-h', [CompletionResultType]::ParameterName, 'Print help')
67 [CompletionResult]::new('--help', '--help', [CompletionResultType]::ParameterName, 'Print help')
68 break
69 }
70 'rsp;pause' {
71 [CompletionResult]::new('-h', '-h', [CompletionResultType]::ParameterName, 'Print help')
72 [CompletionResult]::new('--help', '--help', [CompletionResultType]::ParameterName, 'Print help')
73 break
74 }
75 'rsp;resume' {
76 [CompletionResult]::new('-h', '-h', [CompletionResultType]::ParameterName, 'Print help')
77 [CompletionResult]::new('--help', '--help', [CompletionResultType]::ParameterName, 'Print help')
78 break
79 }
80 'rsp;toggle' {
81 [CompletionResult]::new('-h', '-h', [CompletionResultType]::ParameterName, 'Print help')
82 [CompletionResult]::new('--help', '--help', [CompletionResultType]::ParameterName, 'Print help')
83 break
84 }
85 'rsp;stop' {
86 [CompletionResult]::new('-h', '-h', [CompletionResultType]::ParameterName, 'Print help')
87 [CompletionResult]::new('--help', '--help', [CompletionResultType]::ParameterName, 'Print help')
88 break
89 }
90 'rsp;next' {
91 [CompletionResult]::new('-h', '-h', [CompletionResultType]::ParameterName, 'Print help')
92 [CompletionResult]::new('--help', '--help', [CompletionResultType]::ParameterName, 'Print help')
93 break
94 }
95 'rsp;previous' {
96 [CompletionResult]::new('-h', '-h', [CompletionResultType]::ParameterName, 'Print help')
97 [CompletionResult]::new('--help', '--help', [CompletionResultType]::ParameterName, 'Print help')
98 break
99 }
100 'rsp;volume' {
101 [CompletionResult]::new('-h', '-h', [CompletionResultType]::ParameterName, 'Print help')
102 [CompletionResult]::new('--help', '--help', [CompletionResultType]::ParameterName, 'Print help')
103 break
104 }
105 'rsp;shuffle' {
106 [CompletionResult]::new('-h', '-h', [CompletionResultType]::ParameterName, 'Print help')
107 [CompletionResult]::new('--help', '--help', [CompletionResultType]::ParameterName, 'Print help')
108 break
109 }
110 'rsp;queue' {
111 [CompletionResult]::new('-h', '-h', [CompletionResultType]::ParameterName, 'Print help')
112 [CompletionResult]::new('--help', '--help', [CompletionResultType]::ParameterName, 'Print help')
113 break
114 }
115 'rsp;status' {
116 [CompletionResult]::new('-h', '-h', [CompletionResultType]::ParameterName, 'Print help')
117 [CompletionResult]::new('--help', '--help', [CompletionResultType]::ParameterName, 'Print help')
118 break
119 }
120 'rsp;scan' {
121 [CompletionResult]::new('--paths', '--paths', [CompletionResultType]::ParameterName, 'paths')
122 [CompletionResult]::new('--force', '--force', [CompletionResultType]::ParameterName, 'force')
123 [CompletionResult]::new('-h', '-h', [CompletionResultType]::ParameterName, 'Print help')
124 [CompletionResult]::new('--help', '--help', [CompletionResultType]::ParameterName, 'Print help')
125 break
126 }
127 'rsp;settings' {
128 [CompletionResult]::new('-h', '-h', [CompletionResultType]::ParameterName, 'Print help')
129 [CompletionResult]::new('--help', '--help', [CompletionResultType]::ParameterName, 'Print help')
130 [CompletionResult]::new('get', 'get', [CompletionResultType]::ParameterValue, 'Get a setting value')
131 [CompletionResult]::new('set', 'set', [CompletionResultType]::ParameterValue, 'Set a setting value')
132 [CompletionResult]::new('list', 'list', [CompletionResultType]::ParameterValue, 'List all settings')
133 [CompletionResult]::new('unset', 'unset', [CompletionResultType]::ParameterValue, 'Unset a setting')
134 [CompletionResult]::new('help', 'help', [CompletionResultType]::ParameterValue, 'Print this message or the help of the given subcommand(s)')
135 break
136 }
137 'rsp;settings;get' {
138 [CompletionResult]::new('-h', '-h', [CompletionResultType]::ParameterName, 'Print help')
139 [CompletionResult]::new('--help', '--help', [CompletionResultType]::ParameterName, 'Print help')
140 break
141 }
142 'rsp;settings;set' {
143 [CompletionResult]::new('-h', '-h', [CompletionResultType]::ParameterName, 'Print help')
144 [CompletionResult]::new('--help', '--help', [CompletionResultType]::ParameterName, 'Print help')
145 break
146 }
147 'rsp;settings;list' {
148 [CompletionResult]::new('-h', '-h', [CompletionResultType]::ParameterName, 'Print help')
149 [CompletionResult]::new('--help', '--help', [CompletionResultType]::ParameterName, 'Print help')
150 break
151 }
152 'rsp;settings;unset' {
153 [CompletionResult]::new('-h', '-h', [CompletionResultType]::ParameterName, 'Print help')
154 [CompletionResult]::new('--help', '--help', [CompletionResultType]::ParameterName, 'Print help')
155 break
156 }
157 'rsp;settings;help' {
158 [CompletionResult]::new('get', 'get', [CompletionResultType]::ParameterValue, 'Get a setting value')
159 [CompletionResult]::new('set', 'set', [CompletionResultType]::ParameterValue, 'Set a setting value')
160 [CompletionResult]::new('list', 'list', [CompletionResultType]::ParameterValue, 'List all settings')
161 [CompletionResult]::new('unset', 'unset', [CompletionResultType]::ParameterValue, 'Unset a setting')
162 [CompletionResult]::new('help', 'help', [CompletionResultType]::ParameterValue, 'Print this message or the help of the given subcommand(s)')
163 break
164 }
165 'rsp;settings;help;get' {
166 break
167 }
168 'rsp;settings;help;set' {
169 break
170 }
171 'rsp;settings;help;list' {
172 break
173 }
174 'rsp;settings;help;unset' {
175 break
176 }
177 'rsp;settings;help;help' {
178 break
179 }
180 'rsp;completions' {
181 [CompletionResult]::new('-h', '-h', [CompletionResultType]::ParameterName, 'Print help')
182 [CompletionResult]::new('--help', '--help', [CompletionResultType]::ParameterName, 'Print help')
183 break
184 }
185 'rsp;help' {
186 [CompletionResult]::new('start-daemon', 'start-daemon', [CompletionResultType]::ParameterValue, 'Start the daemon')
187 [CompletionResult]::new('stop-daemon', 'stop-daemon', [CompletionResultType]::ParameterValue, 'Stop the daemon')
188 [CompletionResult]::new('restart', 'restart', [CompletionResultType]::ParameterValue, 'Restart the daemon (kill existing and start new)')
189 [CompletionResult]::new('play', 'play', [CompletionResultType]::ParameterValue, 'Play a track, album, or artist')
190 [CompletionResult]::new('pause', 'pause', [CompletionResultType]::ParameterValue, 'Pause playback')
191 [CompletionResult]::new('resume', 'resume', [CompletionResultType]::ParameterValue, 'Resume playback')
192 [CompletionResult]::new('toggle', 'toggle', [CompletionResultType]::ParameterValue, 'Toggle play/pause')
193 [CompletionResult]::new('stop', 'stop', [CompletionResultType]::ParameterValue, 'Stop playback')
194 [CompletionResult]::new('next', 'next', [CompletionResultType]::ParameterValue, 'Skip to next track')
195 [CompletionResult]::new('previous', 'previous', [CompletionResultType]::ParameterValue, 'Skip to previous track')
196 [CompletionResult]::new('volume', 'volume', [CompletionResultType]::ParameterValue, 'Set volume (0-100)')
197 [CompletionResult]::new('shuffle', 'shuffle', [CompletionResultType]::ParameterValue, 'Shuffle mode')
198 [CompletionResult]::new('queue', 'queue', [CompletionResultType]::ParameterValue, 'Queue management')
199 [CompletionResult]::new('status', 'status', [CompletionResultType]::ParameterValue, 'Show player status')
200 [CompletionResult]::new('scan', 'scan', [CompletionResultType]::ParameterValue, 'Scan music paths to populate database')
201 [CompletionResult]::new('settings', 'settings', [CompletionResultType]::ParameterValue, 'Settings management')
202 [CompletionResult]::new('completions', 'completions', [CompletionResultType]::ParameterValue, 'Generate shell completions (developer only)')
203 [CompletionResult]::new('help', 'help', [CompletionResultType]::ParameterValue, 'Print this message or the help of the given subcommand(s)')
204 break
205 }
206 'rsp;help;start-daemon' {
207 break
208 }
209 'rsp;help;stop-daemon' {
210 break
211 }
212 'rsp;help;restart' {
213 break
214 }
215 'rsp;help;play' {
216 break
217 }
218 'rsp;help;pause' {
219 break
220 }
221 'rsp;help;resume' {
222 break
223 }
224 'rsp;help;toggle' {
225 break
226 }
227 'rsp;help;stop' {
228 break
229 }
230 'rsp;help;next' {
231 break
232 }
233 'rsp;help;previous' {
234 break
235 }
236 'rsp;help;volume' {
237 break
238 }
239 'rsp;help;shuffle' {
240 break
241 }
242 'rsp;help;queue' {
243 break
244 }
245 'rsp;help;status' {
246 break
247 }
248 'rsp;help;scan' {
249 break
250 }
251 'rsp;help;settings' {
252 [CompletionResult]::new('get', 'get', [CompletionResultType]::ParameterValue, 'Get a setting value')
253 [CompletionResult]::new('set', 'set', [CompletionResultType]::ParameterValue, 'Set a setting value')
254 [CompletionResult]::new('list', 'list', [CompletionResultType]::ParameterValue, 'List all settings')
255 [CompletionResult]::new('unset', 'unset', [CompletionResultType]::ParameterValue, 'Unset a setting')
256 break
257 }
258 'rsp;help;settings;get' {
259 break
260 }
261 'rsp;help;settings;set' {
262 break
263 }
264 'rsp;help;settings;list' {
265 break
266 }
267 'rsp;help;settings;unset' {
268 break
269 }
270 'rsp;help;completions' {
271 break
272 }
273 'rsp;help;help' {
274 break
275 }
276 })
277
278 $completions.Where{ $_.CompletionText -like "$wordToComplete*" } |
279 Sort-Object -Property ListItemText
280}
diff --git a/completions/rsp.zsh b/completions/rsp.zsh
index e8da3d7..dd24572 100644
--- a/completions/rsp.zsh
+++ b/completions/rsp.zsh
@@ -209,13 +209,6 @@ esac
209 ;; 209 ;;
210esac 210esac
211;; 211;;
212(completions)
213_arguments "${_arguments_options[@]}" : \
214'-h[Print help]' \
215'--help[Print help]' \
216'::shell -- Shell to generate (bash, zsh, fish, elvish, powershell) If not specified, generates all completion files:_default' \
217&& ret=0
218;;
219(help) 212(help)
220_arguments "${_arguments_options[@]}" : \ 213_arguments "${_arguments_options[@]}" : \
221":: :_rsp__subcmd__help_commands" \ 214":: :_rsp__subcmd__help_commands" \
@@ -320,10 +313,6 @@ _arguments "${_arguments_options[@]}" : \
320 ;; 313 ;;
321esac 314esac
322;; 315;;
323(completions)
324_arguments "${_arguments_options[@]}" : \
325&& ret=0
326;;
327(help) 316(help)
328_arguments "${_arguments_options[@]}" : \ 317_arguments "${_arguments_options[@]}" : \
329&& ret=0 318&& ret=0
@@ -356,16 +345,10 @@ _rsp_commands() {
356'status:Show player status' \ 345'status:Show player status' \
357'scan:Scan music paths to populate database' \ 346'scan:Scan music paths to populate database' \
358'settings:Settings management' \ 347'settings:Settings management' \
359'completions:Generate shell completions (developer only)' \
360'help:Print this message or the help of the given subcommand(s)' \ 348'help:Print this message or the help of the given subcommand(s)' \
361 ) 349 )
362 _describe -t commands 'rsp commands' commands "$@" 350 _describe -t commands 'rsp commands' commands "$@"
363} 351}
364(( $+functions[_rsp__subcmd__completions_commands] )) ||
365_rsp__subcmd__completions_commands() {
366 local commands; commands=()
367 _describe -t commands 'rsp completions commands' commands "$@"
368}
369(( $+functions[_rsp__subcmd__help_commands] )) || 352(( $+functions[_rsp__subcmd__help_commands] )) ||
370_rsp__subcmd__help_commands() { 353_rsp__subcmd__help_commands() {
371 local commands; commands=( 354 local commands; commands=(
@@ -385,16 +368,10 @@ _rsp__subcmd__help_commands() {
385'status:Show player status' \ 368'status:Show player status' \
386'scan:Scan music paths to populate database' \ 369'scan:Scan music paths to populate database' \
387'settings:Settings management' \ 370'settings:Settings management' \
388'completions:Generate shell completions (developer only)' \
389'help:Print this message or the help of the given subcommand(s)' \ 371'help:Print this message or the help of the given subcommand(s)' \
390 ) 372 )
391 _describe -t commands 'rsp help commands' commands "$@" 373 _describe -t commands 'rsp help commands' commands "$@"
392} 374}
393(( $+functions[_rsp__subcmd__help__subcmd__completions_commands] )) ||
394_rsp__subcmd__help__subcmd__completions_commands() {
395 local commands; commands=()
396 _describe -t commands 'rsp help completions commands' commands "$@"
397}
398(( $+functions[_rsp__subcmd__help__subcmd__help_commands] )) || 375(( $+functions[_rsp__subcmd__help__subcmd__help_commands] )) ||
399_rsp__subcmd__help__subcmd__help_commands() { 376_rsp__subcmd__help__subcmd__help_commands() {
400 local commands; commands=() 377 local commands; commands=()
diff --git a/install.sh b/install.sh
index 3133601..872118c 100755
--- a/install.sh
+++ b/install.sh
@@ -48,15 +48,6 @@ case "$shell_name" in
48 cp "$SCRIPT_DIR/completions/rsp.fish" "$dest" 48 cp "$SCRIPT_DIR/completions/rsp.fish" "$dest"
49 echo " → Fish completions: $dest" 49 echo " → Fish completions: $dest"
50 ;; 50 ;;
51 elvish)
52 dest="$HOME/.config/elvish/rc.d/rsp.elvish"
53 mkdir -p "$(dirname "$dest")"
54 cp "$SCRIPT_DIR/completions/rsp.elvish" "$dest"
55 echo " → Elvish completions: $dest"
56 ;;
57 powershell)
58 echo " → PowerShell: source \"$SCRIPT_DIR/completions/rsp.powershell\" from your profile"
59 ;;
60 *) 51 *)
61 echo " → Unrecognized shell '$shell_name'; completion files are in $SCRIPT_DIR/completions/" 52 echo " → Unrecognized shell '$shell_name'; completion files are in $SCRIPT_DIR/completions/"
62 ;; 53 ;;
diff --git a/src/daemon.rs b/src/daemon.rs
index 06b925e..59fc3d8 100644
--- a/src/daemon.rs
+++ b/src/daemon.rs
@@ -544,10 +544,10 @@ fn process_command(
544 ); 544 );
545 let result = match temp_scrobbler.validate_listenbrainz_token() { 545 let result = match temp_scrobbler.validate_listenbrainz_token() {
546 Ok(Some(user)) => { 546 Ok(Some(user)) => {
547 notification::notify_change(&format!( 547 notification::notify(
548 "Logged in to ListenBrainz as {}", 548 "RSPlayer scrobbler login",
549 user 549 &format!("Logged in to ListenBrainz as {}", user),
550 )); 550 );
551 format!("ListenBrainz token valid (user: {})\n", user) 551 format!("ListenBrainz token valid (user: {})\n", user)
552 } 552 }
553 Ok(None) => { 553 Ok(None) => {
@@ -779,19 +779,19 @@ fn process_command(
779 for file in &files { 779 for file in &files {
780 q.add_track(file.clone()); 780 q.add_track(file.clone());
781 } 781 }
782 if was_empty 782 if was_empty && !was_playing {
783 && !was_playing 783 q.shuffle_initial();
784 && let Some(track) = q.current() 784 if let Some(track) = q.current() {
785 { 785 audio.play(track.path.clone());
786 audio.play(track.path.clone()); 786 send_now_playing(scrobbler, track);
787 send_now_playing(scrobbler, track); 787 if let Ok(mut s) = scrobble_state.lock() {
788 if let Ok(mut s) = scrobble_state.lock() { 788 s.start(track.clone());
789 s.start(track.clone()); 789 }
790 let fmt = Config::load()
791 .ok()
792 .and_then(|c| c.display_format.clone());
793 notification::notify_track(track, fmt.as_deref());
790 } 794 }
791 let fmt = Config::load()
792 .ok()
793 .and_then(|c| c.display_format.clone());
794 notification::notify_track(track, fmt.as_deref());
795 } 795 }
796 format!("Queued {} tracks from: {}\n", files.len(), path_str) 796 format!("Queued {} tracks from: {}\n", files.len(), path_str)
797 } 797 }
diff --git a/src/notification.rs b/src/notification.rs
index df9c622..2c8d80f 100644
--- a/src/notification.rs
+++ b/src/notification.rs
@@ -45,3 +45,11 @@ pub fn notify_error(context: &str) {
45 .appname("RSPlayer") 45 .appname("RSPlayer")
46 .show(); 46 .show();
47} 47}
48
49pub fn notify(summary: &str, body: &str) {
50 let _ = notify_rust::Notification::new()
51 .summary(summary)
52 .body(body)
53 .appname("RSPlayer")
54 .show();
55}
diff --git a/src/queue.rs b/src/queue.rs
index 8f98173..26aeb8b 100644
--- a/src/queue.rs
+++ b/src/queue.rs
@@ -385,6 +385,22 @@ impl Queue {
385 &self.shuffled_indices 385 &self.shuffled_indices
386 } 386 }
387 387
388 pub fn shuffle_initial(&mut self) {
389 if self.position != 0 || self.tracks.len() <= 1 {
390 return;
391 }
392 let mut rng = rand::rng();
393 match self.shuffle {
394 ShuffleMode::All => {
395 self.shuffled_indices.shuffle(&mut rng);
396 }
397 ShuffleMode::Album => {
398 self.shuffle_album_range(0..self.tracks.len(), &mut rng);
399 }
400 ShuffleMode::None => {}
401 }
402 }
403
388 pub fn clear(&mut self) { 404 pub fn clear(&mut self) {
389 self.tracks.clear(); 405 self.tracks.clear();
390 self.position = 0; 406 self.position = 0;