]> code.delx.au - pulseaudio/blob - shell-completion/pulseaudio-zsh-completion.zsh
c3baf9d9772951794a49b22dd9f1e72c52f84a5c
[pulseaudio] / shell-completion / pulseaudio-zsh-completion.zsh
1 #compdef pulseaudio pactl pacmd pacat paplay parecord padsp pasuspender
2
3 _devices() {
4 local -a _device_list
5 local cmd _device _device_description
6
7 if [[ $service == pactl || $service == pacmd ]]; then
8 case $words[$((CURRENT - 1))] in
9 set-sink-input-*) cmd=('sink-inputs');;
10 set-sink-*) cmd=('sinks');;
11 set-source-output-*) cmd=('source-outputs');;
12 set-source-*) cmd=('sources');;
13 suspend-sink) cmd=('sinks');;
14 suspend-source) cmd=('sources');;
15 move-sink-input) cmd=('sink-inputs');;
16 move-source-output) cmd=('source-outputs');;
17 kill-sink-input) cmd=('sink-inputs');;
18 kill-source-output) cmd=('source-outputs');;
19 esac
20
21 case $words[$((CURRENT - 2))] in
22 move-sink-input) cmd=('sinks');;
23 move-source-output) cmd=('sources');;
24 esac
25
26 elif [[ $service == (pacat|paplay|parecord) ]]; then
27 if [[ $words == *-r[[:space:]]* ]]; then
28 cmd=('sources')
29 elif [[ $words == *-p[[:space:]]* ]]; then
30 cmd=('sinks')
31 else
32 cmd=('sinks' 'sources')
33 fi
34
35 elif [[ $service == paplay ]]; then
36 cmd=('sinks')
37 elif [[ $service == parecord ]]; then
38 cmd=('sources')
39 fi
40
41 for target in $cmd; do
42 for device_info in ${(ps:\n\n:)"$(_call_program card_tag "pactl list $target")"}; do
43 for line in ${(f)device_info}; do
44 if [[ $target == (sink-inputs|source-outputs) ]]; then
45 if [[ $line == (Sink*Input|Source*Output)* ]]; then
46 _device=${line#*\#}
47 elif [[ $line == *application.name* ]]; then
48 _device_description=${line#*= }
49 fi
50
51 else
52 if [[ $words[$((CURRENT - 1))] == *set-sink-formats* ]]; then
53 if [[ $line == Sink* ]]; then
54 _device=${line#*\#}
55 elif [[ $line == *Description:* ]]; then
56 _device_description=${line#*: }
57 fi
58
59 else
60 if [[ $line == *Name:* ]]; then
61 _device=${line#*: }
62 elif [[ $line == *Description:* ]]; then
63 _device_description=${line#*: }
64 fi
65 fi
66 fi
67 done
68 _device_list+=($_device:$_device_description)
69 done
70 done
71
72 _describe 'device list' _device_list
73 }
74
75 _profiles() {
76 local -a _profile_list
77 local _current_card _raw_profiles _profile_name _profile_description
78
79 _current_card=$words[$((CURRENT - 1))]
80
81 for card in ${(ps:\n\n:)"$(_call_program card_tag "pactl list cards")"}; do
82 if [[ $card == *$_current_card* ]]; then
83 _raw_profiles=${card##*Profiles:}
84 _raw_profiles=${_raw_profiles%%Active Profile:*}
85 for profile in ${(f)_raw_profiles}; do
86 if [[ $profile != [[:blank:]] ]]; then
87 _profile_name=${profile%%: *}
88 _profile_name=${_profile_name//[[:blank:]]/}
89 _profile_name=${_profile_name//:/\\:}
90 _profile_description=${profile#*: }
91 _profile_list+=($_profile_name:$_profile_description)
92 fi
93 done
94 fi
95 done
96
97 _describe 'profile list' _profile_list
98 }
99
100 _ports() {
101 local -a _port_list
102 local _raw_ports _port_name _port_description _current_device
103
104 case $words[$((CURRENT - 2))] in
105 set-sink-port) cmd="sinks";;
106 set-source-port) cmd="sources";;
107 set-port-latency-offset) cmd="cards";;
108 esac
109
110 _current_device=$words[$((CURRENT - 1))]
111
112 for device in ${(ps:\n\n:)"$(_call_program card_tag "pactl list $cmd")"}; do
113 if [[ $device == *Ports:* && $device == *$_current_device* ]]; then
114 _raw_ports=${device##*Ports:}
115 _raw_ports=${_raw_ports%%Active Port:*}
116 for line in ${(f)_raw_ports}; do
117 if [[ $line != [[:blank:]] &&
118 $line != (*Part?of*|*Properties:*|*device.icon_name*) ]]; then
119 _port_name=${line%%: *}
120 _port_name=${_port_name//[[:blank:]]/}
121 _port_description=${line#*: }
122 _port_list+=($_port_name:$_port_description)
123 fi
124 done
125 fi
126 done
127
128 _describe 'port list' _port_list
129 }
130
131 _cards(){
132 local -a _card_list
133 local _card _cad_name
134 for card_info in ${(ps:\n\n:)"$(_call_program card_tag "pactl list cards")"}; do
135 for line in ${(f)card_info}; do
136 if [[ $line == *Name:* ]]; then
137 _card=${line#*: }
138 elif [[ $line == *alsa.long_card_name* ]]; then
139 _card_name=${line#*= \"}
140 _card_name=${_card_name%at*}
141 fi
142 done
143 _card_list+=($_card:$_card_name)
144 done
145
146 _describe 'card list' _card_list
147 }
148
149 _all_modules(){
150 local -a _all_modules_list
151 for module in ${(f)"$(_call_program modules_tag "pulseaudio --dump-modules")"}; do
152 _all_modules_list+=${module%% *}
153 done
154 _describe 'module list' _all_modules_list
155 }
156
157 _loaded_modules(){
158 local -a _loaded_modules_list
159 for module in ${(f)"$(_call_program modules_tag "pactl list modules short")"}; do
160 _loaded_modules_list+=(${${(ps:\t:)module}[1]}:${${(ps:\t:)module}[2]})
161 done
162 _describe 'module list' _loaded_modules_list
163 }
164
165 _resample_methods() {
166 local -a _resample_method_list
167 for method in ${(f)"$(_call_program modules_tag "pulseaudio --dump-resample-methods")"}; do
168 _resample_method_list+=$method
169 done
170 _describe 'resample method list' _resample_method_list
171 }
172
173 _clients() {
174 local -a _client_list
175 local _client _client_description
176 for client_info in ${(ps:\n\n:)"$(_call_program card_tag "pactl list clients")"}; do
177 for line in ${(f)client_info}; do
178 if [[ $line == Client[[:space:]]#* ]]; then
179 _client=${line#*\#}
180 elif [[ $line == *application.name* ]]; then
181 _client_description=${line#*=}
182 fi
183 done
184 _client_list+=($_client:$_client_description)
185 done
186 _describe 'client list' _client_list
187 }
188
189 _pacat_file_formats() {
190 local -a _file_format_list
191 for format in ${(f)"$(_call_program modules_tag "pacat --list-file-formats")"}; do
192 _file_format_list+=(${${(ps:\t:)format}[1]}:${${(ps:\t:)format}[2]})
193 done
194 _describe 'file format list' _file_format_list
195 }
196
197 _pactl_completion() {
198 _pactl_command(){
199 _pactl_commands=(
200 'help: show help and exit'
201 'stat: dump statistics about the PulseAudio daemon'
202 'info: dump info about the PulseAudio daemon'
203 'list: list modules/sources/streams/cards etc...'
204 'exit: ask the PulseAudio daemon to exit'
205 'upload-sample: upload a sound from a file into the sample cache'
206 'play-sample: play the specified sample from the sample cache'
207 'remove-sample: remove the specified sample from the sample cache'
208 'load-module: load a module'
209 'unload-module: unload a module'
210 'move-sink-input: move a stream to a sink'
211 'move-source-output: move a recording stream to a source'
212 'suspend-sink: suspend or resume a sink'
213 'suspend-source: suspend or resume a source'
214 'set-card-profile: set a card profile:cards:_cards'
215 'set-sink-port: set the sink port of a sink'
216 'set-source-port: set the source port of a source'
217 'set-port-latency-offset: set a latency offset on a port'
218 'set-sink-volume: set the volume of a sink'
219 'set-source-volume: set the volume of a source'
220 'set-sink-input-volume: set the volume of a stream'
221 'set-source-output-volume: set the volume of a recording stream'
222 'set-sink-mute: mute a sink'
223 'set-source-mute: mute a source'
224 'set-sink-input-mute: mute a stream'
225 'set-source-output-mute: mute a recording stream'
226 'set-sink-formats: set supported formats of a sink'
227 'subscribe: subscribe to events'
228 )
229 _describe 'pactl commands' _pactl_commands
230 }
231
232 _pactl_list_commands=(
233 'modules: list loaded modules'
234 'sinks: list available sinks'
235 'sources: list available sources'
236 'sink-inputs: list connected sink inputs'
237 'source-outputs: list connected source outputs'
238 'clients: list connected clients'
239 'samples: list samples'
240 'cards: list available cards'
241 )
242
243 _arguments -C \
244 - '(help)' \
245 {-h,--help}'[display this help and exit]' \
246 '--version[show version and exit]' \
247 - '(server)' \
248 {-s,--server}'[name of server to connect to]:host:_hosts' \
249 - '(name)' \
250 {-n,--client-name}'[client name to use]:name' \
251 '::pactl commands:_pactl_command' \
252
253 case $words[$((CURRENT - 1))] in
254 list) _describe 'pactl list commands' _pactl_list_commands;;
255 stat) compadd short;;
256 set-card-profile) _cards;;
257 set-sink-*) _devices;;
258 set-source-*) _devices;;
259 upload-sample) _files;;
260 load-module) _all_modules;;
261 unload-module) _loaded_modules;;
262 suspend-*) _devices;;
263 move-*) _devices;;
264 set-port-latency-offset) _cards;;
265 esac
266
267 case $words[$((CURRENT - 2))] in
268 set-card-profile) _profiles;;
269 set-(sink|source)-port) _ports;;
270 set-port-latency-offset) _ports;;
271 set-*-mute) compadd true false;;
272 suspend-*) compadd true false;;
273 list) compadd short;;
274 move-*) _devices;;
275 '-s' | '-n') _pactl_command;;
276 --server | --client-*) _pactl_command;;
277 esac
278 }
279
280 _pacmd_completion() {
281 _pacmd_command(){
282 _pacmd_commands=(
283 'help: show help and exit'
284 'list-modules: list modules'
285 'list-sinks: list sinks'
286 'list-sources: list sources'
287 'list-clients: list clients'
288 'list-sink-inputs: list sink-inputs'
289 'list-source-outputs: list source-outputs'
290 'stat: dump statistics about the PulseAudio daemon'
291 'info: dump info about the PulseAudio daemon'
292 'load-module: load a module'
293 'unload-module: unload a module'
294 'describe-module: print info for a module'
295 'set-sink-volume: set the volume of a sink'
296 'set-source-volume: set the volume of a source'
297 'set-sink-mute: mute a sink'
298 'set-source-mute: mute a source'
299 'set-sink-input-volume: set the volume of a stream'
300 'set-source-output-volume: set the volume of a recording stream'
301 'set-sink-input-mute: mute a stream'
302 'set-source-output-mute: mute a recording stream'
303 'set-default-sink: set the default sink'
304 'set-default-source: set the default source'
305 'set-card-profile: set a card profile'
306 'set-sink-port: set the sink port of a sink'
307 'set-source-port: set the source port of a source'
308 'set-port-latency-offset: set a latency offset on a port'
309 'suspend-sink: suspend or resume a sink'
310 'suspend-source: suspend or resume a source'
311 'suspend: suspend all sinks and sources'
312 'move-sink-input: move a stream to a sink'
313 'move-source-output: move a recording stream to a source'
314 'update-sink-proplist: update the properties of a sink'
315 'update-source-proplist: update the properties of a source'
316 'update-sink-input-proplist: update the properties of a sink-input'
317 'update-source-output-proplist: update the properties of a source-output'
318 'list-samples: list samples'
319 'play-sample: play the specified sample from the sample cache' # TODO
320 'remove-sample: remove the specified sample from the sample cache' # TODO
321 'load-sample: upload a sound from a file into the sample cache'
322 'load-sample-lazy: lazily upload a sound file into the sample cache'
323 'load-sample-dir-lazy: lazily upload all sound files in a directory into the sample cache'
324 'kill-client: kill a client'
325 'kill-sink-input: kill a sink input'
326 'kill-source-output: kill a source output'
327 'set-log-target: change the log target'
328 'set-log-level: change the log level'
329 'set-log-meta: show source code location in log messages'
330 'set-log-time: show timestamps in log messages'
331 'set-log-backtrace: show backtrace in log messages'
332 'play-file: play a sound file'
333 'dump: show daemon configuration'
334 'dump-volumes: show the state of all volumes'
335 'shared: show shared properties'
336 'exit: ask the PulseAudio daemon to exit'
337 )
338 _describe 'pacmd commands' _pacmd_commands
339 }
340
341 _arguments -C \
342 - '(help)' \
343 {-h,--help}'[display this help and exit]' \
344 '--version[show version and exit]' \
345 '::pacmd commands:_pacmd_command' \
346
347 case $words[$((CURRENT - 1))] in
348 set-card-profile) _cards;;
349 set-sink-*) _devices;;
350 set-source-*) _devices;;
351 load-module) _all_modules;;
352 describe-module) _all_modules;;
353 unload-module) _loaded_modules;;
354 suspend-*) _devices;;
355 move-*) _devices;;
356 set-port-latency-offset) _cards;;
357 load-sample*) _files;;
358 kill-client) _clients;;
359 kill-(sink|source)-*) _devices;;
360 set-log-target) compadd null auto syslog stderr file:;;
361 set-log-*) compadd true false;;
362 play-file) _files;;
363 esac
364
365 case $words[$((CURRENT - 2))] in
366 set-card-profile) _profiles;;
367 set-(sink|source)-port) _ports;;
368 set-port-latency-offset) _ports;;
369 set-*-mute) compadd true false;;
370 suspend-*) compadd true false;;
371 move-*) _devices;;
372 esac
373 }
374
375 _pasuspender_completion() {
376 _arguments -C \
377 {-h,--help}'[display this help and exit]' \
378 '--version[show version and exit]' \
379 {-s,--server}'[name of server to connect to]:host:_hosts' \
380 }
381
382 _padsp_completion() {
383 _arguments -C \
384 '-h[display this help and exit]' \
385 '-s[name of server to connect to]:host:_hosts' \
386 '-n[client name to use]:name:' \
387 '-m[stream name to use]:name:' \
388 '-M[disable /dev/mixer emulation]' \
389 '-S[disable /dev/sndstat emulation]' \
390 '-D[disable /dev/dsp emulation]' \
391 '-d[enable debug output]' \
392 '--[disable further command line parsing]' \
393 }
394
395 # TODO channel map completion
396 _pacat_completion() {
397 _pacat_sample_formats=('s16le' 's16be' 'u8' 'float32le' 'float32be'
398 'ulaw' 'alaw' 's32le' 's32be' 's24le' 's24-32le' 's24-32be')
399
400 _arguments -C \
401 {-h,--help}'[display this help and exit]' \
402 '--version[show version and exit]' \
403 {-r,--record}'[create a connection for recording]' \
404 {-p,--playback}'[create a connection for playback]' \
405 {-s,--server=}'[name of server to connect to]:host:_hosts' \
406 {-d,--device=}'[name of sink/source to connect to]:device:_devices' \
407 {-n,--client-name=}'[client name to use]:name' \
408 '--stream-name=[how to call this stream]:name' \
409 '--volume=[initial volume to use]:volume' \
410 '--rate=[sample rate to use]:rate:(44100 48000 96000)' \
411 '--format=[sample type to use]:format:((${(q)_pacat_sample_formats}))' \
412 '--channels=[number of channels to use]:number:(1 2)' \
413 '--channel-map=[channel map to use]:map' \
414 '--fix-format[use the sample format of the sink]' \
415 '--fix-rate[use the rate of the sink]' \
416 '--fix-channels[channel map of the sink]' \
417 '--no-remix[do not upmix or downmix channels]' \
418 '--no-remap[map channels by index instead of name]' \
419 '--latency=[request the specified latency]:bytes' \
420 '--process-time=[request the specified process time]:bytes' \
421 '--latency-msec=[request the specified latency in msec]:msec' \
422 '--process-time-msec=[request the specified process time in msec]:msec' \
423 '--property=[set the specified property]:property' \
424 '--raw[record/play raw PCM data]' \
425 '--passthrough[passtrough data]' \
426 '--file-format[record/play formatted PCM data]:format:_pacat_file_formats' \
427 '--list-file-formats[list available formats]' \
428 }
429
430 # TODO log-target file completion
431 _pulseaudio_completion() {
432 _arguments -C \
433 {-h,--help}'[display this help and exit]' \
434 '--version[show version and exit]' \
435 '--dump-conf[show default configuration]' \
436 '--dump-modules[show available modules]' \
437 '--dump-resample-methods[show available resample methods]' \
438 '--cleanup-shm[cleanup shared memory]' \
439 '--start[start the daemon]' \
440 {-k,--kill}'[kill a running daemon]' \
441 '--check[check for a running daemon]' \
442 '--system=[run as systemd-wide daemon]:bool:(true false)' \
443 {-D,--daemonize=}'[daemonize after startup]:bool:(true false)' \
444 '--fail=[quit when startup fails]:bool:(true false)' \
445 '--high-priority=[try to set high nice level]:bool:(true false)' \
446 '--realtime=[try to enable rt scheduling]:bool:(true false)' \
447 '--disallow-module-loading=[disallow module loading]:bool:(true false)' \
448 '--disallow-exit=[disallow user requested exit]' \
449 '--exit-idle-time=[terminate the daemon on passed idle time]:time' \
450 '--scache-idle-time=[unload autoloaded samples on passed idle time]:time' \
451 '--log-level=[set the verbosity level]:level' \
452 '-v[increase the verbosity level]' \
453 '--log-target=[set the log target]:target:(auto syslog stderr file\: new_file\:):file' \
454 '--log-meta=[include code location in log messages]:bool:(true false)' \
455 '--log-time=[include timestamps in log messages]:bool:(true false)' \
456 '--log-backtrace=[include backtrace in log messages]:frames' \
457 {-p,--dl-search-path=}'[set the search path for plugins]:dir:_files' \
458 '--resample-method=[set the resample method]:method:_resample_methods' \
459 '--use-pid-file=[create a PID file]:bool:(true false)' \
460 '--no-cpu-limit=[do not install CPU load limiter]:bool:(true false)' \
461 '--disable-shm=[disable shared memory support]:bool:(true false)' \
462 {-L,--load=}'[load the specified module]:modules:_all_modules' \
463 {-F,--file=}'[run the specified script]:file:_files' \
464 '-C[open a command line on the running tty]' \
465 '-n[do not load the default script file]' \
466 }
467
468 _pulseaudio() {
469 local state line curcontext="$curcontext"
470
471 case $service in
472 pulseaudio) _pulseaudio_completion;;
473 pactl) _pactl_completion;;
474 pacmd) _pacmd_completion;;
475 pacat) _pacat_completion;;
476 paplay)_pacat_completion;;
477 parecord)_pacat_completion;;
478 padsp) _padsp_completion;;
479 pasuspender) _pasuspender_completion;;
480 *) _message "Err";;
481 esac
482 }
483
484 _pulseaudio "$@"
485
486 #vim: set ft=zsh sw=4 ts=4 noet