-#
+# Bash tab-completion for GStreamer. -*- shell-script -*-
# Put this in /etc/bash_completion.d/
-#
-_gst_launch()
-{
- local cur
+_gst_inspect() {
+ local _gst_version=1.0
+ local cur cword prev words
+ _gst_init_completion
+ [[ "$cur" == "=" ]] && cur=
+ [[ "$cur" =~ -.*=*$ ]] && prev="${cur%%=*}" cur="${cur#*=}"
+
+ _gst_common_options || return
+
+ COMPREPLY=( $(compgen \
+ -W "$(_gst_parse_help gst-inspect-$_gst_version) \
+ $(_gst_plugins) $(_gst_elements)" \
+ -- "$cur") )
+ [[ $COMPREPLY == *= ]] && compopt -o nospace 2>/dev/null
+} &&
+complete -F _gst_inspect gst-inspect-1.0
- : ${GST_REGISTRY:=~/.gstreamer-0.11/registry.xml}
- : ${GST_COMPLETE:=~/.gstreamer-0.11/complete}
+_gst_launch() {
+ local _gst_version=1.0
+ local cur cword prev words
+ _gst_init_completion
+ local curtype option element property
+ _gst_launch_parse
+ _gst_common_options || return
- if [ ! -f "${GST_REGISTRY}" ] ; then
- return 0
- fi
+ COMPREPLY=( $(_gst_launch_compgen) )
+ [[ $COMPREPLY == *= ]] && compopt -o nospace 2>/dev/null
+} &&
+complete -o default -F _gst_launch gst-launch-1.0
- if [ ! -f "${GST_COMPLETE}" \
- -o "${GST_REGISTRY}" -nt "${GST_COMPLETE}" ] ; then
- sed -n 's/^..<name>\(.*\)<\/name>/\1/ p' ${GST_REGISTRY} >${GST_COMPLETE}
- fi
+_gst_common_options() {
+ if [[ -n "$curtype" ]]; then # Called from _gst_launch
+ [[ $curtype == optionval ]] || return 0
+ else # Called from _gst_inspect
+ local option="$prev"
+ fi
- cur=${COMP_WORDS[COMP_CWORD]}
- COMPREPLY=( $(grep ^$cur $GST_COMPLETE) )
+ case "$option" in
+ --gst-debug-level)
+ COMPREPLY=( $(compgen -W "0 1 2 3 4 5" -- "$cur") );;
+ --gst-debug) # TODO: comma-separated list of category_name:level pairs.
+ ;;
+ --gst-plugin-path) # TODO: support multiple (colon-separated) paths.
+ COMPREPLY=( $(compgen -d -- "$cur") );;
+ --gst-plugin-load) # TODO: comma-separated list of plugins (files?).
+ ;;
+ *) return 0;;
+ esac
+ return 1 # No need to attempt further completions.
+}
+
+_gst_launch_compgen() {
+ case $curtype in
+ option)
+ compgen \
+ -W "$(_gst_parse_help gst-launch-$_gst_version)" \
+ -- "$cur" ;;
+ element)
+ compgen -W "$(_gst_elements)" -- "$cur" ;;
+ option-or-element)
+ compgen \
+ -W "$(_gst_parse_help gst-launch-$_gst_version) \
+ $(_gst_elements)" \
+ -- "$cur" ;;
+ optionval)
+ case "$option" in
+ -o|--output) compgen -f -- "$cur" ;;
+ --exclude) ;; # TODO: comma-separated list of status information types.
+ esac ;;
+ \!)
+ compgen -W '!' -- "$cur" ;;
+ property)
+ compgen -W "$(_gst_properties $element) ! " -- "$cur" ;;
+ propertyval)
+ compgen -W "$(_gst_property_values $element $property)" -- "$cur" ;;
+ esac
+}
+
+_gst_plugins() {
+ gst-inspect-$_gst_version 2>/dev/null |
+ grep -v 'Total count' |
+ awk -F': +' '{print $1}' |
+ uniq
+}
+
+_gst_elements() {
+ gst-inspect-$_gst_version 2>/dev/null |
+ grep -v 'Total count' |
+ awk -F': +' '{print $2}'
+}
+
+_gst_properties() {
+ local element="$1"
+ gst-inspect-$_gst_version "$element" 2>/dev/null |
+ sed -n '/^Element Properties:$/,$ p' |
+ awk '/^ [a-z]/ { print $1 "=" }'
+}
- return 0
+_gst_property_values() {
+ local element=$1 property=$2
+ gst-inspect-$_gst_version $element 2>/dev/null |
+ awk "
+ /^Element Properties:\$/ { inproperties = 1; next; }
+ inproperties && /^ $property / { inproperty = 1; next; }
+ inproperty && /^ *Boolean/ { printf \"true\nfalse\n\"; exit; }
+ inproperty && /^ *Enum/ { inenum = 1; next; }
+ inenum && /^ *\([0-9]+\): / { print \$2; next; }
+ inproperty && /^ [a-z]/ { exit; }"
}
-complete -F _gst_launch -o default gst-launch
+# Walks over $words, sets $curtype to the string:
+#
+# 'option' if $cur is an option or flag like "-a" or "--abc".
+# 'optionval' if $cur is the value of an option
+# (which will be set in $option).
+# 'element' if $cur is a GStreamer element name.
+# '!' if $cur is '!'.
+# 'property' if $cur is the name of a property of a GStreamer element
+# (which will be set in $element).
+# 'propertyval' if $cur is the value of an element's property
+# (which will be set in $element and $property, respectively).
+#
+# ($cur is the word currently being completed.)
+#
+# Before calling this function make sure that $curtype, $option, $element and
+# $property are local, and that $cur, $cword and $words have been initialised.
+#
+# See test cases in tests/misc/test-gstreamer-completion.sh in the
+# gstreamer source repository.
+#
+_gst_launch_parse() {
+ local i next state
+ curtype= i=1 state=start
+ while [[ $i -le $cword ]]; do
+ next="${words[i]}"
+ # Note that COMP_WORDBREAKS by default includes "=" and ":".
+ case "$state,$next" in
+ start,-*=*) curtype=optionval option="${next%%=*}" state=start;;
+ start,-*) curtype=option option="$next" state=option;;
+ start,) curtype=option-or-element;;
+ start,*) curtype=element element="$next" state=element;;
+ option,=) curtype=optionval state=option=;;
+ option,*) _gst_takes_arg "$option" &&
+ curtype=optionval state=start ||
+ # re-evaluate without incrementing i:
+ { curtype= state=start; continue; }
+ ;;
+ option=,*) curtype=optionval state=start;;
+ element,\!) curtype='!' state='!';;
+ \!,*) curtype=element element="$next" state=element;;
+ element,*=)
+ curtype=propertyval property="${next%=}" state=property=;;
+ element,*=*)
+ curtype=propertyval property="${next%%=*}" state=element;;
+ element,*) curtype=property property="$next" state=property;;
+ property,=) curtype=propertyval state=property=;;
+ property=,*) curtype=propertyval state=element;;
+ esac
+ i=$((i + 1))
+ done
+ cur="${cur#*=}"
+}
+
+_gst_takes_arg() {
+ case "$1" in
+ -o|--output|--gst-debug-level|--gst-debug) true;;
+ --gst-plugin-path|--gst-plugin-load|--exclude) true;;
+ *) false;;
+ esac
+}
+
+_gst_parse_help() {
+ $1 --help-all 2>&1 | grep -Eo -e '--[a-z-]+'
+}
+
+_gst_init_completion() {
+ if type _get_comp_words_by_ref &>/dev/null; then
+ # Available since bash-completion 1.2
+ _get_comp_words_by_ref cur cword prev words
+ else
+ # bash-completion not installed or too old. Use bash's raw facilities.
+ # This won't complete properly if the cursor is in the middle of a
+ # word.
+ cur="${COMP_WORDS[COMP_CWORD]}"
+ prev="${COMP_WORDS[COMP_CWORD-1]}"
+ cword=$COMP_CWORD
+ words=("${COMP_WORDS[@]}")
+ fi
+}