From 8b0ec61c6f8b8b3815481757752f868323495619 Mon Sep 17 00:00:00 2001 From: Ronald van Engelen Date: Sun, 14 May 2017 12:40:27 +0200 Subject: [PATCH 1/8] basically working --- lcd | 561 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 561 insertions(+) create mode 100644 lcd diff --git a/lcd b/lcd new file mode 100644 index 0000000..e8cd3a6 --- /dev/null +++ b/lcd @@ -0,0 +1,561 @@ +#!/usr/bin/env bash + +LANG=C +mpd_host=sonida +mpd_host=${mpd_host:-localhost} +mpd_port=${mpd_port:-6600} +ssh_host=sonida +ssh_user=root +ssh_userhost="${ssh_user}@${ssh_host}" +media_base_path="/srv/media/music" + +unset mpc_vals +unset mpd_vals +unset alsa_vals +unset exif_vals +unset soxi_vals + +declare -A alsa_vals +declare -A mpc_vals +declare -A mpd_vals +declare -A exif_vals +declare -A soxi_vals + +## output formatting +bold="$(tput bold)" +dim="$(tput dim)" +std="$(tput sgr0)" +red=$(tput setaf 1) # color 1 +blue=$(tput setaf 33) # color 2 +white=$(tput setaf 7) # color 3 + +## input | nfs://srv/media/music/.../track11.aiff +## | AIFF (Little Endian) PCM in 24bit/192kHz @ 4.503bit/s +main_file_bitdepth= +main_file_bitrate= +main_file_bitrate_kvalue= +main_file_bitrate_raw= +main_file_bitrate_unit= +main_file_bitrate_value= +main_file_samplerate= +main_file_sizebytes= +main_mpd_bitdepth= +main_mpd_bitrate= +main_mpd_samplerate= +main_output_bitdepth= +main_output_samplechannelcount= +main_output_sampleencoding= +main_output_samplerate= +main_output_samplerate_raw= +main_playing_trackalbumartist= +main_playing_trackalbumname= +main_playing_trackalbumnumber= +main_playing_trackartist= +main_playing_trackduration= +main_playing_trackperformers= +main_playing_trackplayingpercentage= +main_playing_trackplayingtime= +main_playing_tracktitle= +main_rt_tracknumber_album= +main_rt_tracknumber_playlist= +main_rt_tracknumbers_playlist= + +declare -A alsa_encoding +declare -a mpc_fields=( + artist + track + album + name + file + artist + album + albumartist + comment + composer + date + disc + genre + performer + title + track + time + file + position + mtime + mdate +) + +mpc_format_string= +for mpc_field in ${mpc_fields[@]}; do + mpc_format_string+="${mpc_field}:[%${mpc_field}%]\n" +done + +function check_commands() { + err=() + cmd_mpc="$(type -p mpc || err+=("mpc not found") )" + cmd_soxi="$(type -p soxi || err+=("soxi not found"))" + cmd_exiftool="$(type -p exiftool || err+=("exiftool not found"))" + cmd_netcat="$(type -p nc || err+=("netcat (nc) not found"))" + if [[ ${#err} -gt 0 ]]; then + printf 1>&2 "error: %s\n" "${err[@]}" + fi +} + +function get_csv_value() { + data="$1" + IFS=\; read type field value <<<"${data}" + printf "%s" "${value//\"}" +} + +function get_soxi_value() { + fieldname="$1" + printf 1>&2 "%s: fieldname='%s', value='%s'\n" \ + "${FUNCNAME[0]}" "${fieldname}" "${soxi_info["${fieldname}"]}" + declare vals="${soxi_info["${fieldname}"]}" + #declare -p vals 1>&2 + value="$(get_csv_value "${vals[0]}")" + printf "%s" "${value}" +} + +function filter_soxi_duration() { + ## expects: hh:mm:ss.xxx where xxx are the subseconds (milliseconds?) + duration_fields=($1) + IFS=":" read hours minutes seconds subseconds <<<"${duration_fields[0]//./:}" + minutes=$(echo "${minutes} + ( ${hours} * 60 )" | bc) + printf "%s:%s" "${minutes}" "${seconds}" +} + +function fill_arrays() { + ret_mpc_info + #ret_mpc_now + ret_mpd_now + ret_exif_info "${mpc_vals[file]}" + ret_soxi_info "${mpc_vals[file]}" + ret_alsa_info "1" "0" "root@sonida" + #[[ "${exif_vals[*]}x" == "x" ]] || ret_exif_info "${mpc_vals[file]}" + #[[ "${soxi_vals[*]}x" == "x" ]] || ret_soxi_info "${mpc_vals[file]}" + #[[ "${alsa_vals[*]}x" == "x" ]] || ret_alsa_info "1" "0" "root@sonida" +} + +function info_to_csv() { + fill_arrays + + for f in "${!mpc_vals[@]}"; do + printf '"%s";"%s";"%s";\n' "mpc" "${f}" "${mpc_vals[${f}]}" + done + for f in "${!soxi_vals[@]}"; do + printf '"%s";"%s";"%s";\n' "soxi" "${f}" "${soxi_vals[${f}]}" + done + for f in "${!exif_vals[@]}"; do + printf '"%s";"%s";"%s";\n' "exif" "${f}" "${exif_vals[${f}]}" + done + for f in "${!alsa_vals[@]}"; do + printf '"%s";"%s";"%s";\n' "alsa" "${f}" "${alsa_vals[${f}]}" + done + +} +function soxi_filesize_to_bytes() { + soxi_filesize="$1" # ${soxi_vals[FileSize]} + unit="${soxi_filesize:$(( ${#soxi_filesize} -1 )):1}" + size="${soxi_filesize:0:-1}" + case "${unit}" in + G) value="$(echo "scale=0; ${size} * 1000000" | bc)" ;; + M) value="$(echo "scale=0; ${size} * 1000" | bc)" ;; + K) value="${size}" ;; + *) printf 1>&2 \ + "ANOMALITY: unknown unit '%s' in soxi reported file size ('%s')" \ + "${unit}" "${soxi_filesize}" + return 1 + esac + printf "%s" "${value}" +} + +function alsa_format_outputencoding() { + + alsa_encoding="$1" # ${alsa_vals[format]} + encoding_re="([SU])([0-9]+)_([LB]E)" + if [[ "${alsa_encoding}" =~ ${encoding_re} ]]; then + signedness="${BASH_REMATCH[1]}" + bitdepth="${BASH_REMATCH[2]}" + alsa_encoding[bitdepth]="${bitdepth}" + endianness="${BASH_REMATCH[3]}" + case "${signedness}" in + U) alsa_encoding[signedness]="unsigned" ;; + S) alsa_encoding[signedness]="signed" ;; + esac + case "${endianness}" in + LE) alsa_encoding[endianness]="little endian" ;; + BE) alsa_encoding[endianness]="big endian" ;; + esac + else + printf "ANOMALITY in %s: alsa_encoding '%s' does not match regex.\n" \ + "${FUNCNAME[0]}" "${alsa_encoding}" + return 1 + fi +} + + +function get_info() { + + fill_arrays + + main_playing_tracktitle="${mpc_vals[title]}" + main_playing_trackartist="${mpc_vals[artist]}" + main_playing_trackperformers="${exif_vals[Performer]}" + main_rt_tracknumber_album="${mpc_vals[track]}" + main_rt_tracknumber_playlist="${mpc_vals[rt_playlist_tracknumber]}" + main_rt_tracknumbers_playlist="${mpc_vals[rt_playlist_tracknumbers]}" + main_playing_trackalbumname="${mpc_vals[album]}" + main_playing_trackalbumnumber="${mpc_vals[position]}" + main_playing_trackalbumartist="${mpc_vals[albumartist]}" + main_playing_trackduration="$(filter_soxi_duration "${soxi_vals[Duration]}")" + main_file_sizebytes="$(soxi_filesize_to_bytes ${soxi_vals[FileSize]})" + main_file_bitrate_raw="${soxi_vals[BitRate]}" + main_file_bitrate_value="${main_file_bitrate_raw:0:-1}" + main_file_bitrate_unit="${main_file_bitrate_raw:$(( ${#main_file_bitrate_raw} - 1 )):1}" + main_file_bitrate_kvalue= + if [[ "${main_file_bitrate_unit}x" == "Mx" ]]; then + main_file_bitrate_kvalue="$(echo "${main_file_bitrate_value} * 1000" | bc)" + else + main_file_bitrate_kvalue="${main_file_bitrate_value}" + fi + main_file_bitrate_kvalue="${main_file_bitrate_kvalue%%.00}" + main_file_bitrate="${main_file_bitrate_kvalue}" + main_file_bitdepth="${soxi_vals[Precision]//-bit}" + main_file_samplerate="${soxi_vals[SampleRate]}" + #declare -p alsa_vals 1>&2 + main_output_samplerate_raw=(${alsa_vals[rate]}) + main_output_samplerate="${main_output_samplerate_raw[0]}" + alsa_format_outputencoding "${alsa_vals[format]}" + main_output_bitdepth="${alsa_encoding[bitdepth]}" + main_output_sampleencoding="${alsa_encoding[bitdepth]} bit (${alsa_encoding[signedness]} ${alsa_encoding[endianness]})" + main_output_samplechannelcount="${alsa_vals[channels]}" + + main_playing_trackplayingtime="${mpc_vals[rt_time_elapsed_minutes]}:${mpc_vals[rt_time_elapsed_seconds]}" + main_playing_trackplayingpercentage="${mpc_vals[rt_percentage_played]}%" + + # declare -p main_playing_tracktitle 1>&2 + # declare -p main_playing_trackartist 1>&2 + # declare -p main_rt_tracknumber_album 1>&2 + # declare -p main_rt_tracknumber_playlist 1>&2 + # declare -p main_rt_tracknumbers_playlist 1>&2 + # #declare -p main_playing_trackperformer 1>&2 + # declare -p main_playing_trackalbumname 1>&2 + # declare -p main_playing_trackduration 1>&2 + # declare -p main_playing_trackplayingtime 1>&2 + # declare -p main_playing_trackplayingpercentage 1>&2 + # declare -p main_file_sizebytes 1>&2 + # declare -p main_file_bitrate 1>&2 + # declare -p main_file_bitdepth 1>&2 + # declare -p main_file_samplerate 1>&2 + # declare -p main_output_samplerate 1>&2 + # declare -p main_output_sampleencoding 1>&2 + # declare -p main_output_samplechannelcount 1>&2 + + main_mpd_bitdepth="${mpd_vals[rt_audio_bitdepth]}" + main_mpd_samplerate="${mpd_vals[rt_audio_samplerate]}" + main_mpd_bitrate="${mpd_vals[rt_audio_bitrate]}" + + msg_filesize="$(printf "%-13s: %-13s" \ +"File size" "${main_file_sizebytes} bytes")" + + msg_header="$(printf "%-11s %-18s %8s > %8s > %8s" " " " " "File" "MPD" "DAC")" + msg_bitrate="$(printf "%-11s %-18s: %8s > %8s > %8s" \ +" " "Bit rate (kbit/s)" "${main_file_bitrate}" "${main_mpd_bitrate}" "(n/a)")" + msg_bitdepth="$(printf "%-11s %-18s: %8s > %8s > %8s" \ +" " "Bit depth (bit)" "${main_file_bitdepth}" "${main_mpd_bitdepth}" "${main_output_bitdepth}")" + msg_samplerate="$(printf "%-11s %-18s: %8s > %8s > %8s" \ +" " "Sample rate (Hz)" "${main_file_samplerate}" "${main_mpd_samplerate}" "${main_output_samplerate}")" + + msg_tracktitle="${bold}${main_playing_tracktitle}${std}" + msg_trackartist="${bold}${red}${main_playing_trackartist}${std}" + msg_tracknumber="$(printf "%-4s (of %-3s)" "#${bold}${blue}${main_rt_tracknumber_playlist}${std}" "${main_rt_tracknumbers_playlist}")" + msg_nowplaying="${msg_tracknumber}: ${msg_tracktitle}" + msg_byline="$(printf "%-13s-- by %s" " " "${msg_trackartist}")" + msg_albumline="$(printf "%-13s track %s from %s" \ +" " "${bold}${main_rt_tracknumber_album}${std}" "${bold}${blue}${main_playing_trackalbumname}${std}")" + msg_playingtime="$(printf "%-13s playing %s from %s (%s)" \ +" " "${bold}${std}${main_playing_trackplayingtime}${std}" "${main_playing_trackduration}" "${main_playing_trackplayingpercentage}")" + + echo -en "\ +${msg_nowplaying} +${msg_byline} +${msg_albumline} +${msg_playingtime} +${msg_header} +${msg_bitrate} +${msg_bitdepth} +${msg_samplerate} + +${msg_filesize} +\r" + + +} + +function ret_mpd_now() { + ## fills mpc_vals array with rt_ fields from mpc status + + #res="$(${cmd_mpc} "${mpc_args[@]}" &)" + [[ "${DEBUG}" ]] && declare -p cmd_netcat mpd_host mpd_port 1>&2 + res="$(echo "status" | ${cmd_netcat} -N ${mpd_host} ${mpd_port})" + [[ "${DEBUG}" ]] && declare -p res 1>&2 + linecounter=1 + #playing_re="[(playing|paused)][[:space:]]+#([0-9]+)/([0-9]+)[[:space:]]+([0-9]+):([0-9]+)/([0-9]+):([0-9]+)[[:space:]]+\(([0-9]+%\)" + +# OK MPD 0.19.0 +# volume: -1 +# repeat: 0 +# random: 1 +# single: 0 +# consume: 0 +# playlist: 555 +# playlistlength: 19 +# mixrampdb: 0.000000 +# state: play +# song: 10 +# songid: 681 +# time: 156:163 +# elapsed: 155.829 +# bitrate: 1084 +# audio: 48000:24:2 +# nextsong: 18 +# nextsongid: 689 + # OK + prefix="rt_raw" + key_val_re="^([^\:]+):[[:space:]]+(.*)" + while read -r line; do + if [[ "${line}" =~ ${key_val_re} ]]; then + field="${BASH_REMATCH[1]}" + value="${BASH_REMATCH[2]}" + mpd_vals["${prefix}_${field}"]="${value}" + fi + done<<<"${res}" + IFS=: read audio_samplerate audio_bitdepth audio_channelcount <<< "${mpd_vals[${prefix}_audio]}" + mpd_vals["rt_audio_samplerate"]="${audio_samplerate}" + mpd_vals["rt_audio_bitdepth"]="${audio_bitdepth}" + mpd_vals["rt_audio_channelcount"]="${audio_channelcount}" + mpd_vals["rt_audio_bitrate"]="${mpd_vals[${prefix}_bitrate]}" + + IFS=: read time_elapsed_rounded time_tracktotal <<< "${mpd_vals[${prefix}_time]}" + mpd_vals["rt_time_tracktotal"]="${time_tracktotal}" + + # for k in "${!mpd_vals[@]}"; do + # if [[ "${k}" =~ ^rt ]]; then + # printf 1>&2 "mpd_val %s: '%s'\n" "${k}" "${mpd_vals[${k}]}" + # fi + # done +} + +function ret_mpc_info() { + mpc_args=(-h "${mpd_host}") + mpc_args+=(current) + mpc_args+=(-f "${mpc_format_string}") + res="$(${cmd_mpc} "${mpc_args[@]}" &)" + field_val_re="^([^\:]+):(.*)" + while read -r line; do + if [[ "${line}" =~ ${field_val_re} ]]; then + field="${BASH_REMATCH[1]}" + val="${BASH_REMATCH[2]}" + mpc_vals["${field}"]="${val}" + #else + # printf 1>&2 "%s error: no match with line: '%s'\n" \ + # "${FUNC_NAME[0]}" "${line}" + fi + done<<<"${res}" + #for k in ${!mpc_vals[@]}; do + # printf '"mpcfield";"%s";"%s";\n' "${k}" "${mpc_vals[${k}]}" + # done +} + +function ret_soxi_info() { + rel_file_path="${1}" + file_path="${media_base_path}/${rel_file_path}" + if [[ -f "${file_path}" ]]; then + res="$(${cmd_soxi} "${file_path}")" + field_val_re='([^\:]+):[[:space:]]*(.*)' + while read -r line; do + if [[ "${line}" =~ ${field_val_re} ]]; then + field="${BASH_REMATCH[1]}" + field="${field// /}" + val="${BASH_REMATCH[2]}" + soxi_vals["${field}"]="${val}" + if [[ "${field}x" == "Sample Encodingx" ]]; then + break + fi + fi + done<<<"${res}" + fi +} + +function ret_exif_info() { + rel_file_path="${1}" + file_path="${media_base_path}/${rel_file_path}" + if [[ -f "${file_path}" ]]; then + res="$(${cmd_exiftool} -j "${file_path}")" + #declare -p res 1>&2 + field_val_re='"([^\:]+)":(.*)' + while read -r line; do + if [[ "${line}" =~ ${field_val_re} ]]; then + #declare -p line 1>&2 + field="${BASH_REMATCH[1]}" + val="${BASH_REMATCH[2]}" + exif_vals["${field}"]="${val}" + #else + # printf 1>&2 "error: no match with line: '%s'\n" "${line}" + fi + done<<<"${res}" + #for k in ${!exif_vals[@]}; do + # printf '"exiffield";"%s";"%s";\n' "${k}" "${exif_vals[${k}]}" + #done + fi +} + +function ret_alsa_info() { + alsa_card_no="$1" + alsa_dev_no="$2" + alsa_ssh_userhost="${3:-${ssh_userhost}}" + hw_params_file="/proc/asound/card${alsa_card_no}/pcm${alsa_dev_no}p/sub0/hw_params" + cmd="cat ${hw_params_file}" + if [[ "${alsa_ssh_userhost}x" == "x" ]]; then + res="$(${cmd})" + else + res="$(ssh ${alsa_ssh_userhost} -- "${cmd}")" + fi + if [[ $? -ne 0 ]]; then + printf 1>&2 "error accessing file: '%s' on host '%s'\n" \ + "${hw_params_file}" "${alsa_ssh_userhost}" + return 1 + else + key_val_re="^([^\:]+):[[:space:]]+(.*)" + while read -r line; do + if [[ "${line}" =~ ${key_val_re} ]]; then + field="${BASH_REMATCH[1]}" + val="${BASH_REMATCH[2]}" + alsa_vals["${field}"]="${val}" + else + declare -p line 1>&2 + return 1 + fi + done<<<"${res}" + fi +} + +function terminal_size() { # Calculate the size of the terminal + terminal_cols="$(tput cols)" + terminal_rows="$(tput lines)" +} + + +function main_loop() { + mpc_args=(-h "${mpd_host}") + counter=0 + while : ; do + #"${cmd_mpc}" "${mpc_args[@]}" idle + sleep 0.5 + get_info + fill_arrays + + main_playing_tracktitle="${mpc_vals[title]}" + main_playing_trackartist="${mpc_vals[artist]}" + main_playing_trackperformers="${exif_vals[Performer]}" + main_rt_tracknumber_album="${mpc_vals[track]}" + main_rt_tracknumber_playlist="${mpc_vals[rt_playlist_tracknumber]}" + main_rt_tracknumbers_playlist="${mpc_vals[rt_playlist_tracknumbers]}" + main_playing_trackalbumname="${mpc_vals[album]}" + main_playing_trackalbumnumber="${mpc_vals[position]}" + main_playing_trackalbumartist="${mpc_vals[albumartist]}" + main_playing_trackduration="$(filter_soxi_duration "${soxi_vals[Duration]}")" + main_file_sizebytes="$(soxi_filesize_to_bytes ${soxi_vals[FileSize]})" + main_file_bitrate_raw="${soxi_vals[BitRate]}" + main_file_bitrate_value="${main_file_bitrate_raw:0:-1}" + main_file_bitrate_unit="${main_file_bitrate_raw:$(( ${#main_file_bitrate_raw} - 1 )):1}" + main_file_bitrate_kvalue= + if [[ "${main_file_bitrate_unit}x" == "Mx" ]]; then + main_file_bitrate_kvalue="$(echo "${main_file_bitrate_value} * 1000" | bc)" + else + main_file_bitrate_kvalue="${main_file_bitrate_value}" + fi + main_file_bitrate_kvalue="${main_file_bitrate_kvalue%%.00}" + main_file_bitrate="${main_file_bitrate_kvalue}" + main_file_bitdepth="${soxi_vals[Precision]//-bit}" + main_file_samplerate="${soxi_vals[SampleRate]}" + #declare -p alsa_vals 1>&2 + main_output_samplerate_raw=(${alsa_vals[rate]}) + main_output_samplerate="${main_output_samplerate_raw[0]}" + alsa_format_outputencoding "${alsa_vals[format]}" + main_output_bitdepth="${alsa_encoding[bitdepth]}" + main_output_sampleencoding="${alsa_encoding[bitdepth]} bit (${alsa_encoding[signedness]} ${alsa_encoding[endianness]})" + main_output_samplechannelcount="${alsa_vals[channels]}" + + main_playing_trackplayingtime="${mpc_vals[rt_time_elapsed_minutes]}:${mpc_vals[rt_time_elapsed_seconds]}" + main_playing_trackplayingpercentage="${mpc_vals[rt_percentage_played]}%" + + # declare -p main_playing_tracktitle 1>&2 + # declare -p main_playing_trackartist 1>&2 + # declare -p main_rt_tracknumber_album 1>&2 + # declare -p main_rt_tracknumber_playlist 1>&2 + # declare -p main_rt_tracknumbers_playlist 1>&2 + # #declare -p main_playing_trackperformer 1>&2 + # declare -p main_playing_trackalbumname 1>&2 + # declare -p main_playing_trackduration 1>&2 + # declare -p main_playing_trackplayingtime 1>&2 + # declare -p main_playing_trackplayingpercentage 1>&2 + # declare -p main_file_sizebytes 1>&2 + # declare -p main_file_bitrate 1>&2 + # declare -p main_file_bitdepth 1>&2 + # declare -p main_file_samplerate 1>&2 + # declare -p main_output_samplerate 1>&2 + # declare -p main_output_sampleencoding 1>&2 + # declare -p main_output_samplechannelcount 1>&2 + + main_mpd_bitdepth="${mpd_vals[rt_audio_bitdepth]}" + main_mpd_samplerate="${mpd_vals[rt_audio_samplerate]}" + main_mpd_bitrate="${mpd_vals[rt_audio_bitrate]}" + + msg_filesize="$(printf "%-13s: %-13s" \ +"File size" "${main_file_sizebytes} bytes")" + + msg_header="$(printf "%-11s %-18s %8s > %8s > %8s" " " " " "File" "MPD" "DAC")" + msg_bitrate="$(printf "%-11s %-18s: %8s > %8s > %8s" \ +" " "Bit rate (kbit/s)" "${main_file_bitrate}" "${main_mpd_bitrate}" "(n/a)")" + msg_bitdepth="$(printf "%-11s %-18s: %8s > %8s > %8s" \ +" " "Bit depth (bit)" "${main_file_bitdepth}" "${main_mpd_bitdepth}" "${main_output_bitdepth}")" + msg_samplerate="$(printf "%-11s %-18s: %8s > %8s > %8s" \ +" " "Sample rate (Hz)" "${main_file_samplerate}" "${main_mpd_samplerate}" "${main_output_samplerate}")" + + msg_tracktitle="${bold}${main_playing_tracktitle}${std}" + msg_trackartist="${bold}${red}${main_playing_trackartist}${std}" + msg_tracknumber="$(printf "%-4s (of %-3s)" "#${bold}${blue}${main_rt_tracknumber_playlist}${std}" "${main_rt_tracknumbers_playlist}")" + msg_nowplaying="${msg_tracknumber}: ${msg_tracktitle}" + msg_byline="$(printf "%-13s-- by %s" " " "${msg_trackartist}")" + msg_albumline="$(printf "%-13s track %s from %s" \ +" " "${bold}${main_rt_tracknumber_album}${std}" "${bold}${blue}${main_playing_trackalbumname}${std}")" + msg_playingtime="$(printf "%-13s playing %s from %s (%s)" \ +" " "${bold}${std}${main_playing_trackplayingtime}${std}" "${main_playing_trackduration}" "${main_playing_trackplayingpercentage}")" + + # echo -en "\ + # ${msg_nowplaying} + # ${msg_byline} + # ${msg_albumline} + # ${msg_playingtime} + # ${msg_header} + # ${msg_bitrate} + # ${msg_bitdepth} + # ${msg_samplerate} + + # ${msg_filesize} + # \r" + ((counter++)) + echo -en "bla die bla $counter\ntwee bla die bla $counter\r" + + #tclsh /etc/shairport/smartie/smartie-cat.tcl -tty /dev/ttyUSB0 + done + printf 1>&2 "main_loop done.\n" +} + +check_commands +## if the script is not sourced by another script but run within its +## own shell call function `analyze_commandline_args' +[[ "${BASH_SOURCE[0]:-}" != "${0}" ]] || \ + get_info "$@" -- GitLab From 0cdd8513215d0ab45f49b421bd18381635e95cc5 Mon Sep 17 00:00:00 2001 From: Ronald van Engelen Date: Sun, 14 May 2017 12:41:06 +0200 Subject: [PATCH 2/8] made executable --- lcd | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 lcd diff --git a/lcd b/lcd old mode 100644 new mode 100755 -- GitLab From bbb91c18cfb4b405b5afea43cf0fa5f548362620 Mon Sep 17 00:00:00 2001 From: Ronald van Engelen Date: Sun, 14 May 2017 15:20:37 +0200 Subject: [PATCH 3/8] playlistlength fixed (and cleaned up some stale code) --- lcd | 184 +++++++++++++----------------------------------------------- 1 file changed, 40 insertions(+), 144 deletions(-) diff --git a/lcd b/lcd index e8cd3a6..22a2cd1 100755 --- a/lcd +++ b/lcd @@ -26,7 +26,7 @@ bold="$(tput bold)" dim="$(tput dim)" std="$(tput sgr0)" red=$(tput setaf 1) # color 1 -blue=$(tput setaf 33) # color 2 +blue=$(tput setaf 4) # color 2 white=$(tput setaf 7) # color 3 ## input | nfs://srv/media/music/.../track11.aiff @@ -58,31 +58,28 @@ main_playing_trackplayingtime= main_playing_tracktitle= main_rt_tracknumber_album= main_rt_tracknumber_playlist= -main_rt_tracknumbers_playlist= +main_rt_playlistlength= declare -A alsa_encoding declare -a mpc_fields=( - artist - track - album - name - file - artist album albumartist + artist comment composer date disc + file genre + mdate + mtime + name performer + position + time title + length track - time - file - position - mtime - mdate ) mpc_format_string= @@ -90,6 +87,11 @@ for mpc_field in ${mpc_fields[@]}; do mpc_format_string+="${mpc_field}:[%${mpc_field}%]\n" done +function die() { + printf "%s\n" "$@" 1>&2 + exit 1 +} + function check_commands() { err=() cmd_mpc="$(type -p mpc || err+=("mpc not found") )" @@ -126,7 +128,7 @@ function filter_soxi_duration() { } function fill_arrays() { - ret_mpc_info + ret_mpc_info || return 1 #ret_mpc_now ret_mpd_now ret_exif_info "${mpc_vals[file]}" @@ -197,14 +199,15 @@ function alsa_format_outputencoding() { function get_info() { - fill_arrays - + fill_arrays || return 1 + [[ ${DEBUG} ]] && declare -p mpc_vals 1>&2 + [[ ${DEBUG} ]] && declare -p mpd_vals 1>&2 main_playing_tracktitle="${mpc_vals[title]}" main_playing_trackartist="${mpc_vals[artist]}" main_playing_trackperformers="${exif_vals[Performer]}" main_rt_tracknumber_album="${mpc_vals[track]}" - main_rt_tracknumber_playlist="${mpc_vals[rt_playlist_tracknumber]}" - main_rt_tracknumbers_playlist="${mpc_vals[rt_playlist_tracknumbers]}" + main_rt_tracknumber_playlist="${mpc_vals[position]}" + main_rt_playlistlength="${mpd_vals[rt_raw_playlistlength]}" main_playing_trackalbumname="${mpc_vals[album]}" main_playing_trackalbumnumber="${mpc_vals[position]}" main_playing_trackalbumartist="${mpc_vals[albumartist]}" @@ -267,9 +270,9 @@ function get_info() { msg_samplerate="$(printf "%-11s %-18s: %8s > %8s > %8s" \ " " "Sample rate (Hz)" "${main_file_samplerate}" "${main_mpd_samplerate}" "${main_output_samplerate}")" - msg_tracktitle="${bold}${main_playing_tracktitle}${std}" + msg_tracktitle="${bold}${blue}${main_playing_tracktitle}${std}" msg_trackartist="${bold}${red}${main_playing_trackartist}${std}" - msg_tracknumber="$(printf "%-4s (of %-3s)" "#${bold}${blue}${main_rt_tracknumber_playlist}${std}" "${main_rt_tracknumbers_playlist}")" + msg_tracknumber="$(printf "%-4s (of %3s)" "#${bold}${blue}${main_rt_tracknumber_playlist}${std}" "${main_rt_playlistlength}")" msg_nowplaying="${msg_tracknumber}: ${msg_tracktitle}" msg_byline="$(printf "%-13s-- by %s" " " "${msg_trackartist}")" msg_albumline="$(printf "%-13s track %s from %s" \ @@ -294,34 +297,13 @@ ${msg_filesize} } function ret_mpd_now() { - ## fills mpc_vals array with rt_ fields from mpc status - - #res="$(${cmd_mpc} "${mpc_args[@]}" &)" + ## echo status command to mpd host on mpd port using netcat, to + ## fill mpc_vals array with rt_ fields + [[ "${DEBUG}" ]] && declare -p cmd_netcat mpd_host mpd_port 1>&2 - res="$(echo "status" | ${cmd_netcat} -N ${mpd_host} ${mpd_port})" - [[ "${DEBUG}" ]] && declare -p res 1>&2 + mpd_status="$(echo "status" | ${cmd_netcat} -N ${mpd_host} ${mpd_port})" + [[ "${DEBUG}" ]] && declare -p mpd_status 1>&2 linecounter=1 - #playing_re="[(playing|paused)][[:space:]]+#([0-9]+)/([0-9]+)[[:space:]]+([0-9]+):([0-9]+)/([0-9]+):([0-9]+)[[:space:]]+\(([0-9]+%\)" - -# OK MPD 0.19.0 -# volume: -1 -# repeat: 0 -# random: 1 -# single: 0 -# consume: 0 -# playlist: 555 -# playlistlength: 19 -# mixrampdb: 0.000000 -# state: play -# song: 10 -# songid: 681 -# time: 156:163 -# elapsed: 155.829 -# bitrate: 1084 -# audio: 48000:24:2 -# nextsong: 18 -# nextsongid: 689 - # OK prefix="rt_raw" key_val_re="^([^\:]+):[[:space:]]+(.*)" while read -r line; do @@ -330,7 +312,7 @@ function ret_mpd_now() { value="${BASH_REMATCH[2]}" mpd_vals["${prefix}_${field}"]="${value}" fi - done<<<"${res}" + done<<<"${mpd_status}" IFS=: read audio_samplerate audio_bitdepth audio_channelcount <<< "${mpd_vals[${prefix}_audio]}" mpd_vals["rt_audio_samplerate"]="${audio_samplerate}" mpd_vals["rt_audio_bitdepth"]="${audio_bitdepth}" @@ -351,21 +333,25 @@ function ret_mpc_info() { mpc_args=(-h "${mpd_host}") mpc_args+=(current) mpc_args+=(-f "${mpc_format_string}") + [[ ${DEBUG} ]] && declare -p mpc_format_string 1>&2 res="$(${cmd_mpc} "${mpc_args[@]}" &)" + if [[ $? -ne 0 ]]; then + die "${FUNCNAME[0]}: mpd on %s is not running." + else + if [[ "${res}x" == "x" ]]; then + printf 1>&2 "mpd on %s is not currently playing anything.\n" \ + "${mpd_host}" + return 1 + fi + fi field_val_re="^([^\:]+):(.*)" while read -r line; do if [[ "${line}" =~ ${field_val_re} ]]; then field="${BASH_REMATCH[1]}" val="${BASH_REMATCH[2]}" mpc_vals["${field}"]="${val}" - #else - # printf 1>&2 "%s error: no match with line: '%s'\n" \ - # "${FUNC_NAME[0]}" "${line}" fi done<<<"${res}" - #for k in ${!mpc_vals[@]}; do - # printf '"mpcfield";"%s";"%s";\n' "${k}" "${mpc_vals[${k}]}" - # done } function ret_soxi_info() { @@ -434,7 +420,7 @@ function ret_alsa_info() { val="${BASH_REMATCH[2]}" alsa_vals["${field}"]="${val}" else - declare -p line 1>&2 + [[ ${DEBUG} ]] && declare -p line 1>&2 return 1 fi done<<<"${res}" @@ -455,96 +441,6 @@ function main_loop() { sleep 0.5 get_info fill_arrays - - main_playing_tracktitle="${mpc_vals[title]}" - main_playing_trackartist="${mpc_vals[artist]}" - main_playing_trackperformers="${exif_vals[Performer]}" - main_rt_tracknumber_album="${mpc_vals[track]}" - main_rt_tracknumber_playlist="${mpc_vals[rt_playlist_tracknumber]}" - main_rt_tracknumbers_playlist="${mpc_vals[rt_playlist_tracknumbers]}" - main_playing_trackalbumname="${mpc_vals[album]}" - main_playing_trackalbumnumber="${mpc_vals[position]}" - main_playing_trackalbumartist="${mpc_vals[albumartist]}" - main_playing_trackduration="$(filter_soxi_duration "${soxi_vals[Duration]}")" - main_file_sizebytes="$(soxi_filesize_to_bytes ${soxi_vals[FileSize]})" - main_file_bitrate_raw="${soxi_vals[BitRate]}" - main_file_bitrate_value="${main_file_bitrate_raw:0:-1}" - main_file_bitrate_unit="${main_file_bitrate_raw:$(( ${#main_file_bitrate_raw} - 1 )):1}" - main_file_bitrate_kvalue= - if [[ "${main_file_bitrate_unit}x" == "Mx" ]]; then - main_file_bitrate_kvalue="$(echo "${main_file_bitrate_value} * 1000" | bc)" - else - main_file_bitrate_kvalue="${main_file_bitrate_value}" - fi - main_file_bitrate_kvalue="${main_file_bitrate_kvalue%%.00}" - main_file_bitrate="${main_file_bitrate_kvalue}" - main_file_bitdepth="${soxi_vals[Precision]//-bit}" - main_file_samplerate="${soxi_vals[SampleRate]}" - #declare -p alsa_vals 1>&2 - main_output_samplerate_raw=(${alsa_vals[rate]}) - main_output_samplerate="${main_output_samplerate_raw[0]}" - alsa_format_outputencoding "${alsa_vals[format]}" - main_output_bitdepth="${alsa_encoding[bitdepth]}" - main_output_sampleencoding="${alsa_encoding[bitdepth]} bit (${alsa_encoding[signedness]} ${alsa_encoding[endianness]})" - main_output_samplechannelcount="${alsa_vals[channels]}" - - main_playing_trackplayingtime="${mpc_vals[rt_time_elapsed_minutes]}:${mpc_vals[rt_time_elapsed_seconds]}" - main_playing_trackplayingpercentage="${mpc_vals[rt_percentage_played]}%" - - # declare -p main_playing_tracktitle 1>&2 - # declare -p main_playing_trackartist 1>&2 - # declare -p main_rt_tracknumber_album 1>&2 - # declare -p main_rt_tracknumber_playlist 1>&2 - # declare -p main_rt_tracknumbers_playlist 1>&2 - # #declare -p main_playing_trackperformer 1>&2 - # declare -p main_playing_trackalbumname 1>&2 - # declare -p main_playing_trackduration 1>&2 - # declare -p main_playing_trackplayingtime 1>&2 - # declare -p main_playing_trackplayingpercentage 1>&2 - # declare -p main_file_sizebytes 1>&2 - # declare -p main_file_bitrate 1>&2 - # declare -p main_file_bitdepth 1>&2 - # declare -p main_file_samplerate 1>&2 - # declare -p main_output_samplerate 1>&2 - # declare -p main_output_sampleencoding 1>&2 - # declare -p main_output_samplechannelcount 1>&2 - - main_mpd_bitdepth="${mpd_vals[rt_audio_bitdepth]}" - main_mpd_samplerate="${mpd_vals[rt_audio_samplerate]}" - main_mpd_bitrate="${mpd_vals[rt_audio_bitrate]}" - - msg_filesize="$(printf "%-13s: %-13s" \ -"File size" "${main_file_sizebytes} bytes")" - - msg_header="$(printf "%-11s %-18s %8s > %8s > %8s" " " " " "File" "MPD" "DAC")" - msg_bitrate="$(printf "%-11s %-18s: %8s > %8s > %8s" \ -" " "Bit rate (kbit/s)" "${main_file_bitrate}" "${main_mpd_bitrate}" "(n/a)")" - msg_bitdepth="$(printf "%-11s %-18s: %8s > %8s > %8s" \ -" " "Bit depth (bit)" "${main_file_bitdepth}" "${main_mpd_bitdepth}" "${main_output_bitdepth}")" - msg_samplerate="$(printf "%-11s %-18s: %8s > %8s > %8s" \ -" " "Sample rate (Hz)" "${main_file_samplerate}" "${main_mpd_samplerate}" "${main_output_samplerate}")" - - msg_tracktitle="${bold}${main_playing_tracktitle}${std}" - msg_trackartist="${bold}${red}${main_playing_trackartist}${std}" - msg_tracknumber="$(printf "%-4s (of %-3s)" "#${bold}${blue}${main_rt_tracknumber_playlist}${std}" "${main_rt_tracknumbers_playlist}")" - msg_nowplaying="${msg_tracknumber}: ${msg_tracktitle}" - msg_byline="$(printf "%-13s-- by %s" " " "${msg_trackartist}")" - msg_albumline="$(printf "%-13s track %s from %s" \ -" " "${bold}${main_rt_tracknumber_album}${std}" "${bold}${blue}${main_playing_trackalbumname}${std}")" - msg_playingtime="$(printf "%-13s playing %s from %s (%s)" \ -" " "${bold}${std}${main_playing_trackplayingtime}${std}" "${main_playing_trackduration}" "${main_playing_trackplayingpercentage}")" - - # echo -en "\ - # ${msg_nowplaying} - # ${msg_byline} - # ${msg_albumline} - # ${msg_playingtime} - # ${msg_header} - # ${msg_bitrate} - # ${msg_bitdepth} - # ${msg_samplerate} - - # ${msg_filesize} # \r" ((counter++)) echo -en "bla die bla $counter\ntwee bla die bla $counter\r" -- GitLab From e46f372ccbd016e09dc2fa428945d43e78bda29a Mon Sep 17 00:00:00 2001 From: Ronald van Engelen Date: Sun, 14 May 2017 15:20:51 +0200 Subject: [PATCH 4/8] no idea --- mpd-monitor | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/mpd-monitor b/mpd-monitor index 543b03a..5d6f43d 100755 --- a/mpd-monitor +++ b/mpd-monitor @@ -191,13 +191,14 @@ function does_mpd_haveoutputs() { if [[ ${#MPD_OUTPUTS[@]} -lt 1 ]]; then ## no outputs found - debug "bla" + debug "no outputs found" + declare -p MPD_OUTPUTS 1>&2 printf "%s" "${MSG_MPDCONF_NO_AUDIOOUTOUTS}" return 1 else msg="$(printf "\`%s' " "${MPD_OUTPUTS[@]}")" [[ ! -z ${DEBUG} ]] && \ - debug "using outputs: ${msg}" + declare -p MPD_OUTPUTS 1>&2 printf "output: %s (total: %s)\n" \ "${MPD_OUTPUTS[@]}" "${#MPD_OUTPUTS[@]}" 1>&2; return 0 @@ -263,7 +264,6 @@ function get_mpd_alsa_audio_outputs() { ## audio_output defined in the mpd configuration. [[ ! -z "${DEBUG}" ]] && \ debug "entering \`${FUNCNAME}' with arguments \`$*'" - ## be sure not to match global parameter `audio_output_format' audio_output_started_regexp="^[[:space:]]*audio_output[[:space:]]" audio_output_ended_regexp="}" @@ -274,7 +274,6 @@ function get_mpd_alsa_audio_outputs() { audio_output_comment_regexp="^[[:space:]]*#" while read -r line; do - if [[ ! -z "${output_started}" ]]; then ## inside output? if [[ "${line}" =~ ${audio_output_ended_regexp} ]]; then @@ -305,8 +304,7 @@ function get_mpd_alsa_audio_outputs() { fi fi - - done < ${MPD_CONFIGURATIONFILE} + done<"${MPD_CONFIGURATIONFILE}" if [[ ${output_counter} -gt 0 ]]; then [[ ! -z "${DEBUG}" ]] && \ @@ -337,13 +335,11 @@ function get_mpd_device() { ## return it. [[ ! -z "${DEBUG}" ]] && \ debug "entering \`${FUNCNAME}' with arguments \`$*'" - mpd_device="" mpd_staticoutput="${mpd_staticoutput}" mpd_fixed_samplerate="" mpd_fixed_channelcount="" mpd_fixed_sampleencoding="" - alsa_outputs="$(get_mpd_alsa_audio_outputs)" if [[ ${alsa_outputs} -lt 1 ]]; then die "no alsa outputs found in the ${MSG_MPDCONF}" @@ -725,15 +721,12 @@ function get_alsa_streamfile() { ## configuration file (needed for `get_alsa_props'). [[ ! -z "${DEBUG}" ]] && \ debug "entering \`${FUNCNAME}' with arguments \`$*'" - - #monitor file = /proc/asound/card1/stream0 alsa_streamfile="" alsa_streamfile_regexp="monitor[[:space:]]file[[:space:]]*=[[:space:]]*(.*)" - alsa_hwaddress_value=$(get_mpd_device) [[ ! -z "${DEBUG}" ]] && \ - debug "got alsa hwaddress: \`${alsa_hwaddress_value}'" + declare -p alsa_hwaddress_value 1>&2 alsa_hwaddress="${alsa_hwaddress_value/hw:/}" alsa_dev_nr="${alsa_hwaddress%%,*}" @@ -974,8 +967,9 @@ function main() { if [[ -z "${MPD_CONFIGURATIONFILE}" ]]; then MPD_CONFIGURATIONFILE="$(get_mpdconf_filepath)" [[ $? -ne 0 ]] && die "${MPD_CONFIGURATIONFILE}" + else + declare -p MPD_CONFIGURATIONFILE 1>&2 fi - ## check if mpd is configured globally for a static audio output MPDCONF_GLOBAL_STATICFORMAT="$(get_mpdconf_parameter "audio_output_format")" @@ -1001,7 +995,9 @@ function main() { ## mpd configuration file alsa_streamfile="$(get_alsa_streamfile)" if [[ $? -ne 0 ]]; then - die "could not get current file from alsa" + die "could not get current file from alsa" + else + declare -p alsa_streamfile 1>&2 fi ## get the path to the (parent) music directory from the mpd -- GitLab From 7546cae06dd9aabb6adeccd281ce61973aed6b19 Mon Sep 17 00:00:00 2001 From: Ronald van Engelen Date: Mon, 15 May 2017 10:50:26 +0200 Subject: [PATCH 5/8] command line arguments added --- lcd | 305 +++++++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 230 insertions(+), 75 deletions(-) diff --git a/lcd b/lcd index 22a2cd1..54b5348 100755 --- a/lcd +++ b/lcd @@ -1,25 +1,33 @@ #!/usr/bin/env bash +## This script for bash 4.x on linux displays the way an audio file is +## streamed from storage, through mpd, to alsa (the DAC). +## +## Copyright (C) 2017 Ronald van Engelen +## This program is free software: you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation, either version 3 of the License, or +## (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program. If not, see . +## +## Source: https://github.com/ronalde/mpd-configure +## See also: https://lacocina.nl/detect-alsa-output-capabilities LANG=C -mpd_host=sonida -mpd_host=${mpd_host:-localhost} -mpd_port=${mpd_port:-6600} -ssh_host=sonida -ssh_user=root -ssh_userhost="${ssh_user}@${ssh_host}" -media_base_path="/srv/media/music" -unset mpc_vals -unset mpd_vals -unset alsa_vals -unset exif_vals -unset soxi_vals +app_name_mm="mpd-monitor" +app_version="0.1.0" +app_info_url="https://lacocina.nl/mpd-display-status" -declare -A alsa_vals -declare -A mpc_vals -declare -A mpd_vals -declare -A exif_vals -declare -A soxi_vals +def_mpd_host="localhost" +def_mpd_port="6600" +def_ssh_user="root" ## output formatting bold="$(tput bold)" @@ -29,63 +37,116 @@ red=$(tput setaf 1) # color 1 blue=$(tput setaf 4) # color 2 white=$(tput setaf 7) # color 3 -## input | nfs://srv/media/music/.../track11.aiff -## | AIFF (Little Endian) PCM in 24bit/192kHz @ 4.503bit/s -main_file_bitdepth= -main_file_bitrate= -main_file_bitrate_kvalue= -main_file_bitrate_raw= -main_file_bitrate_unit= -main_file_bitrate_value= -main_file_samplerate= -main_file_sizebytes= -main_mpd_bitdepth= -main_mpd_bitrate= -main_mpd_samplerate= -main_output_bitdepth= -main_output_samplechannelcount= -main_output_sampleencoding= -main_output_samplerate= -main_output_samplerate_raw= -main_playing_trackalbumartist= -main_playing_trackalbumname= -main_playing_trackalbumnumber= -main_playing_trackartist= -main_playing_trackduration= -main_playing_trackperformers= -main_playing_trackplayingpercentage= -main_playing_trackplayingtime= -main_playing_tracktitle= -main_rt_tracknumber_album= -main_rt_tracknumber_playlist= -main_rt_playlistlength= +arg_mpd_host="" +arg_mpd_port="" +arg_ssh_user="" +arg_mpd_music_dir="" + +function display_usageinfo() { + + msg_usage="\ +Usage: +${app_name_mm} -d|--mpd-music-dir PATH [optional arguments] +-or- +${app_name_mm} PATH + +PATH should be the path to the directory used as 'music_directory' by +mpd running on MPDHOST. + +Optional arguments: + -m|--mpd-host MPDHOST The IP address or hostname on which mpd + runs. + Defaults to 'localhost'. + -p|--mpd-port MPDPORT The port on which mpd on MPDHOST + listens. + Defaults to '6600'. + -u|--ssh-user SSHUSER The username for the ssh connection to + MPDHOST used to get realtime alsa + information on MPDHOST. + (Only used when MPDHOST is remote, ie not + 'localhost' or '127.0.x.y'.) + +Background information: +${app_info_url} +" + printf 1>&2 "%s\n" "${msg_usage}" +} -declare -A alsa_encoding -declare -a mpc_fields=( - album - albumartist - artist - comment - composer - date - disc - file - genre - mdate - mtime - name - performer - position - time - title - length - track -) -mpc_format_string= -for mpc_field in ${mpc_fields[@]}; do - mpc_format_string+="${mpc_field}:[%${mpc_field}%]\n" -done +function analyze_command_line() { + ## parse command line arguments using the `manual loop` method + ## described in http://mywiki.wooledge.org/BashFAQ/035. + while :; do + case "${1:-}" in + -m|--mpd-host) + if [[ "${2}x" == "x" ]]; then + die "argument \`$1' requires the dns host name or ip address for the host running mpd." + else + arg_mpd_host="$2" + shift 2 + continue + fi + ;; + -u|--ssh-user) + if [[ "${2}x" == "x" ]]; then + die "argument \`$1' requires a non-empty value." + else + arg_ssh_user="${2}" + shift 2 + continue + fi + ;; + -d|--mpd-music-dir) + if [[ "${2}x" == "x" ]]; then + die "argument \`$1' requires the path to the directory where the music for mpd is stored." + break + else + arg_mpd_music_dir="$2" + mpd_music_dir="${arg_mpd_music_dir}" + shift 2 + continue + fi + ;; + -h|-\?|--help) + display_usageinfo + exit + ;; + --) + shift + break + ;; + -?*) + printf "Notice: unknown option \`%s' ignored\n\n." "$1" 1>&2 + display_usageinfo + exit + ;; + *) + break + esac + done + + ## shift the options index to get the remainder of the command + ## line arguments containing the font descriptions + ## and return them as 0-separated strings. + #printf 1>&2 "OPTIND: \`%s'\n" "${OPTIND}" + shift $((OPTIND - 1)) + if [[ "${arg_mpd_music_dir}x" == "x" ]]; then + arg_single="$@" + arg_mpd_music_dir="${arg_single}" + if [[ ! -d "${arg_mpd_music_dir}" ]]; then + printf 1>&2 "error: invalid mpd music directory \`%s' specified.\n\n" \ + "${arg_mpd_music_dir}" + display_usageinfo + else + ## single argument, use in defaults + mpd_music_dir="${arg_mpd_music_dir}" + mpd_host="${def_mpd_host}" + mpd_port="${def_mpd_port}" + ssh_host="" + fi + fi + +} function die() { printf "%s\n" "$@" 1>&2 @@ -100,6 +161,7 @@ function check_commands() { cmd_netcat="$(type -p nc || err+=("netcat (nc) not found"))" if [[ ${#err} -gt 0 ]]; then printf 1>&2 "error: %s\n" "${err[@]}" + return 1 fi } @@ -199,6 +261,30 @@ function alsa_format_outputencoding() { function get_info() { + ## parse command line arguments + analyze_command_line "$@" + + ## check presenece of needed commands + check_commands || return 1 + + if [[ ! -d "${mpd_music_dir}" ]]; then + die "error: can't access directory ${mpd_music_dir}." + fi + mpd_host="${arg_mpd_host:-${def_mpd_host}}" + mpd_port="${arg_mpd_port:-${def_mpd_port}}" + ssh_user="${arg_ssh_user:-${def_ssh_user}}" + ssh_host="${arg_ssh_host:-}" + localhost_re="127.0.[0-9]+.[0-9]+|localhost" + if [[ "${mpd_host}" =~ ${localhost_re} ]]; then + ## mpd runs local, no need for ssh to get alsa properties + ssh_userhost="" + else + ssh_host="${mpd_host}" + ## mpd runs remote, use ssh to get alsa properties + ssh_userhost="${ssh_user}@${ssh_host}" + fi + declare -p mpd_host ssh_host ssh_user mpd_music_dir 1>&2 + fill_arrays || return 1 [[ ${DEBUG} ]] && declare -p mpc_vals 1>&2 [[ ${DEBUG} ]] && declare -p mpd_vals 1>&2 @@ -356,7 +442,7 @@ function ret_mpc_info() { function ret_soxi_info() { rel_file_path="${1}" - file_path="${media_base_path}/${rel_file_path}" + file_path="${arg_mpd_music_dir}/${rel_file_path}" if [[ -f "${file_path}" ]]; then res="$(${cmd_soxi} "${file_path}")" field_val_re='([^\:]+):[[:space:]]*(.*)' @@ -376,7 +462,7 @@ function ret_soxi_info() { function ret_exif_info() { rel_file_path="${1}" - file_path="${media_base_path}/${rel_file_path}" + file_path="${arg_mpd_music_dir}/${rel_file_path}" if [[ -f "${file_path}" ]]; then res="$(${cmd_exiftool} -j "${file_path}")" #declare -p res 1>&2 @@ -450,7 +536,76 @@ function main_loop() { printf 1>&2 "main_loop done.\n" } -check_commands +unset mpc_vals +unset mpd_vals +unset alsa_vals +unset exif_vals +unset soxi_vals + +declare -A alsa_vals +declare -A mpc_vals +declare -A mpd_vals +declare -A exif_vals +declare -A soxi_vals + +## input | nfs://srv/media/music/.../track11.aiff +## | AIFF (Little Endian) PCM in 24bit/192kHz @ 4.503bit/s +main_file_bitdepth= +main_file_bitrate= +main_file_bitrate_kvalue= +main_file_bitrate_raw= +main_file_bitrate_unit= +main_file_bitrate_value= +main_file_samplerate= +main_file_sizebytes= +main_mpd_bitdepth= +main_mpd_bitrate= +main_mpd_samplerate= +main_output_bitdepth= +main_output_samplechannelcount= +main_output_sampleencoding= +main_output_samplerate= +main_output_samplerate_raw= +main_playing_trackalbumartist= +main_playing_trackalbumname= +main_playing_trackalbumnumber= +main_playing_trackartist= +main_playing_trackduration= +main_playing_trackperformers= +main_playing_trackplayingpercentage= +main_playing_trackplayingtime= +main_playing_tracktitle= +main_rt_tracknumber_album= +main_rt_tracknumber_playlist= +main_rt_playlistlength= + +declare -A alsa_encoding +declare -a mpc_fields=( + album + albumartist + artist + comment + composer + date + disc + file + genre + mdate + mtime + name + performer + position + time + title + length + track +) + +mpc_format_string= +for mpc_field in ${mpc_fields[@]}; do + mpc_format_string+="${mpc_field}:[%${mpc_field}%]\n" +done + ## if the script is not sourced by another script but run within its ## own shell call function `analyze_commandline_args' [[ "${BASH_SOURCE[0]:-}" != "${0}" ]] || \ -- GitLab From 1780751a07225be188c2cfaf3942acf3d2b6c097 Mon Sep 17 00:00:00 2001 From: Ronald van Engelen Date: Mon, 15 May 2017 11:28:07 +0200 Subject: [PATCH 6/8] some bitperfect cloring in output --- lcd | 81 +++++++++++++++++++++++++++++++++---------------------------- 1 file changed, 44 insertions(+), 37 deletions(-) diff --git a/lcd b/lcd index 54b5348..e422ddf 100755 --- a/lcd +++ b/lcd @@ -33,9 +33,10 @@ def_ssh_user="root" bold="$(tput bold)" dim="$(tput dim)" std="$(tput sgr0)" -red=$(tput setaf 1) # color 1 -blue=$(tput setaf 4) # color 2 -white=$(tput setaf 7) # color 3 +red=$(tput setaf 1) +green=$(tput setaf 2) +blue=$(tput setaf 4) +white=$(tput setaf 7) arg_mpd_host="" arg_mpd_port="" @@ -153,6 +154,11 @@ function die() { exit 1 } +function human_bytes() { + bytes="$1" + numfmt --to=iec-i --suffix=B --format="%.1f" "${bytes}" +} + function check_commands() { err=() cmd_mpc="$(type -p mpc || err+=("mpc not found") )" @@ -322,59 +328,60 @@ function get_info() { main_playing_trackplayingtime="${mpc_vals[rt_time_elapsed_minutes]}:${mpc_vals[rt_time_elapsed_seconds]}" main_playing_trackplayingpercentage="${mpc_vals[rt_percentage_played]}%" - - # declare -p main_playing_tracktitle 1>&2 - # declare -p main_playing_trackartist 1>&2 - # declare -p main_rt_tracknumber_album 1>&2 - # declare -p main_rt_tracknumber_playlist 1>&2 - # declare -p main_rt_tracknumbers_playlist 1>&2 - # #declare -p main_playing_trackperformer 1>&2 - # declare -p main_playing_trackalbumname 1>&2 - # declare -p main_playing_trackduration 1>&2 - # declare -p main_playing_trackplayingtime 1>&2 - # declare -p main_playing_trackplayingpercentage 1>&2 - # declare -p main_file_sizebytes 1>&2 - # declare -p main_file_bitrate 1>&2 - # declare -p main_file_bitdepth 1>&2 - # declare -p main_file_samplerate 1>&2 - # declare -p main_output_samplerate 1>&2 - # declare -p main_output_sampleencoding 1>&2 - # declare -p main_output_samplechannelcount 1>&2 - + declare -p main_playing_trackplayingpercentage 1>&2 main_mpd_bitdepth="${mpd_vals[rt_audio_bitdepth]}" main_mpd_samplerate="${mpd_vals[rt_audio_samplerate]}" main_mpd_bitrate="${mpd_vals[rt_audio_bitrate]}" - msg_filesize="$(printf "%-13s: %-13s" \ -"File size" "${main_file_sizebytes} bytes")" - - msg_header="$(printf "%-11s %-18s %8s > %8s > %8s" " " " " "File" "MPD" "DAC")" - msg_bitrate="$(printf "%-11s %-18s: %8s > %8s > %8s" \ + main_file_sizehbytes="$(human_bytes "${main_file_sizebytes}")" + msg_filesize="$(printf "%-12s: %-13s (%s)" \ +"File size" "${main_file_sizebytes} bytes" "${main_file_sizehbytes}")" + + color_bitdepth_file_mpd="${red}" + color_bitdepth_mpd_output="${red}" + if [[ ${main_mpd_bitdepth} -ge ${main_file_bitdepth} ]]; then + color_bitdepth_file_mpd="${green}" + if [[ ${main_output_bitdepth} -ge ${main_mpd_bitdepth} ]]; then + color_bitdepth_mpd_output="${green}" + fi + fi + color_sample_rate_file_mpd="${red}" + color_sample_rate_mpd_output="${red}" + if [[ ${main_mpd_samplerate} -ge ${main_file_samplerate} ]]; then + color_samplerate_file_mpd="${green}" + if [[ ${main_output_samplerate} -ge ${main_mpd_samplerate} ]]; then + color_samplerate_mpd_output="${green}" + fi + fi + + + msg_header="$(printf "%-11s %-18s ${white}%8s${std} > ${white}%8s${std} > ${white}%8s${std}" " " " " "File" "MPD" "DAC")" + msg_bitrate="$(printf "%-11s %-18s: ${dim}${white}%8s${std} > ${white}%8s${std} > ${dim}${white}%8s${std}" \ " " "Bit rate (kbit/s)" "${main_file_bitrate}" "${main_mpd_bitrate}" "(n/a)")" - msg_bitdepth="$(printf "%-11s %-18s: %8s > %8s > %8s" \ + msg_bitdepth="$(printf "%-11s %-18s: %8s ${color_bitdepth_file_mpd}> %8s ${color_bitdepth_mpd_output}> %8s${std}" \ " " "Bit depth (bit)" "${main_file_bitdepth}" "${main_mpd_bitdepth}" "${main_output_bitdepth}")" - msg_samplerate="$(printf "%-11s %-18s: %8s > %8s > %8s" \ + msg_samplerate="$(printf "%-11s %-18s: %8s ${color_samplerate_file_mpd}> %8s${std} ${color_samplerate_mpd_output}> %8s${std}" \ " " "Sample rate (Hz)" "${main_file_samplerate}" "${main_mpd_samplerate}" "${main_output_samplerate}")" - msg_tracktitle="${bold}${blue}${main_playing_tracktitle}${std}" - msg_trackartist="${bold}${red}${main_playing_trackartist}${std}" - msg_tracknumber="$(printf "%-4s (of %3s)" "#${bold}${blue}${main_rt_tracknumber_playlist}${std}" "${main_rt_playlistlength}")" + msg_tracktitle="${bold}${white}${main_playing_tracktitle}${std}" + msg_trackartist="${blue}${main_playing_trackartist}${std}" + msg_tracknumber="$(printf "%-4s of %-3s" "#${bold}${blue}${main_rt_tracknumber_playlist}${std}" "${main_rt_playlistlength}")" msg_nowplaying="${msg_tracknumber}: ${msg_tracktitle}" - msg_byline="$(printf "%-13s-- by %s" " " "${msg_trackartist}")" - msg_albumline="$(printf "%-13s track %s from %s" \ + msg_byline="$(printf "%-12s-- by %s" " " "${msg_trackartist}")" + msg_albumline="$(printf "%-12strack %s from %s" \ " " "${bold}${main_rt_tracknumber_album}${std}" "${bold}${blue}${main_playing_trackalbumname}${std}")" msg_playingtime="$(printf "%-13s playing %s from %s (%s)" \ " " "${bold}${std}${main_playing_trackplayingtime}${std}" "${main_playing_trackduration}" "${main_playing_trackplayingpercentage}")" echo -en "\ ${msg_nowplaying} -${msg_byline} ${msg_albumline} -${msg_playingtime} +${msg_byline} + ${msg_header} -${msg_bitrate} ${msg_bitdepth} ${msg_samplerate} +${msg_bitrate} ${msg_filesize} \r" -- GitLab From 97fae4cb80bef188a3b522b70c167fde24ceda28 Mon Sep 17 00:00:00 2001 From: Ronald van Engelen Date: Mon, 15 May 2017 12:12:51 +0200 Subject: [PATCH 7/8] started with mpd ouput handling --- lcd | 59 ++++++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 42 insertions(+), 17 deletions(-) diff --git a/lcd b/lcd index e422ddf..b043738 100755 --- a/lcd +++ b/lcd @@ -61,6 +61,7 @@ Optional arguments: -p|--mpd-port MPDPORT The port on which mpd on MPDHOST listens. Defaults to '6600'. + -x|--mpd-password PASSWD The password for mpd. -u|--ssh-user SSHUSER The username for the ssh connection to MPDHOST used to get realtime alsa information on MPDHOST. @@ -88,6 +89,15 @@ function analyze_command_line() { continue fi ;; + -x|--mpd-password) + if [[ "${2}x" == "x" ]]; then + die "argument \`$1' requires a non-empty value." + else + arg_mpd_password="${2}" + shift 2 + continue + fi + ;; -u|--ssh-user) if [[ "${2}x" == "x" ]]; then die "argument \`$1' requires a non-empty value." @@ -143,6 +153,7 @@ function analyze_command_line() { mpd_music_dir="${arg_mpd_music_dir}" mpd_host="${def_mpd_host}" mpd_port="${def_mpd_port}" + mpd_password="" ssh_host="" fi fi @@ -201,7 +212,7 @@ function fill_arrays() { ret_mpd_now ret_exif_info "${mpc_vals[file]}" ret_soxi_info "${mpc_vals[file]}" - ret_alsa_info "1" "0" "root@sonida" + ret_alsa_info "1" "0" #[[ "${exif_vals[*]}x" == "x" ]] || ret_exif_info "${mpc_vals[file]}" #[[ "${soxi_vals[*]}x" == "x" ]] || ret_soxi_info "${mpc_vals[file]}" #[[ "${alsa_vals[*]}x" == "x" ]] || ret_alsa_info "1" "0" "root@sonida" @@ -278,7 +289,8 @@ function get_info() { fi mpd_host="${arg_mpd_host:-${def_mpd_host}}" mpd_port="${arg_mpd_port:-${def_mpd_port}}" - ssh_user="${arg_ssh_user:-${def_ssh_user}}" + ssh_user="${arg_ssh_user:-${def_ssh_user}}" + mpd_password="${arg_mpd_password:-}" ssh_host="${arg_ssh_host:-}" localhost_re="127.0.[0-9]+.[0-9]+|localhost" if [[ "${mpd_host}" =~ ${localhost_re} ]]; then @@ -289,11 +301,11 @@ function get_info() { ## mpd runs remote, use ssh to get alsa properties ssh_userhost="${ssh_user}@${ssh_host}" fi - declare -p mpd_host ssh_host ssh_user mpd_music_dir 1>&2 + [[ ${DEBUG} ]] && declare -p mpd_host ssh_host ssh_user mpd_music_dir 1>&2 fill_arrays || return 1 - [[ ${DEBUG} ]] && declare -p mpc_vals 1>&2 - [[ ${DEBUG} ]] && declare -p mpd_vals 1>&2 + [[ ${DEBUG} ]] && declare -p mpc_vals mpd_vals 1>&2 + main_playing_tracktitle="${mpc_vals[title]}" main_playing_trackartist="${mpc_vals[artist]}" main_playing_trackperformers="${exif_vals[Performer]}" @@ -367,8 +379,8 @@ function get_info() { msg_trackartist="${blue}${main_playing_trackartist}${std}" msg_tracknumber="$(printf "%-4s of %-3s" "#${bold}${blue}${main_rt_tracknumber_playlist}${std}" "${main_rt_playlistlength}")" msg_nowplaying="${msg_tracknumber}: ${msg_tracktitle}" - msg_byline="$(printf "%-12s-- by %s" " " "${msg_trackartist}")" - msg_albumline="$(printf "%-12strack %s from %s" \ + msg_byline="$(printf "%-11s-- by %s" " " "${msg_trackartist}")" + msg_albumline="$(printf "%-11strack %s from album %s" \ " " "${bold}${main_rt_tracknumber_album}${std}" "${bold}${blue}${main_playing_trackalbumname}${std}")" msg_playingtime="$(printf "%-13s playing %s from %s (%s)" \ " " "${bold}${std}${main_playing_trackplayingtime}${std}" "${main_playing_trackduration}" "${main_playing_trackplayingpercentage}")" @@ -385,8 +397,6 @@ ${msg_bitrate} ${msg_filesize} \r" - - } function ret_mpd_now() { @@ -423,7 +433,14 @@ function ret_mpd_now() { } function ret_mpc_info() { - mpc_args=(-h "${mpd_host}") + ## get information from mpd using mpc with the 'current' command + ## and a format string. + if [[ "${mpd_password}x" == "x" ]]; then + mpc_args=(-h "${mpd_host}") + else + mpc_args=(-h "${mpd_password}@${mpd_host}") + fi + mpc_args+=(-p "${mpd_port}") mpc_args+=(current) mpc_args+=(-f "${mpc_format_string}") [[ ${DEBUG} ]] && declare -p mpc_format_string 1>&2 @@ -472,28 +489,36 @@ function ret_exif_info() { file_path="${arg_mpd_music_dir}/${rel_file_path}" if [[ -f "${file_path}" ]]; then res="$(${cmd_exiftool} -j "${file_path}")" - #declare -p res 1>&2 field_val_re='"([^\:]+)":(.*)' while read -r line; do if [[ "${line}" =~ ${field_val_re} ]]; then - #declare -p line 1>&2 field="${BASH_REMATCH[1]}" val="${BASH_REMATCH[2]}" exif_vals["${field}"]="${val}" - #else - # printf 1>&2 "error: no match with line: '%s'\n" "${line}" fi done<<<"${res}" - #for k in ${!exif_vals[@]}; do - # printf '"exiffield";"%s";"%s";\n' "${k}" "${exif_vals[${k}]}" - #done fi } function ret_alsa_info() { + ## TODO: fix handling of mpd output(s) alsa_card_no="$1" alsa_dev_no="$2" alsa_ssh_userhost="${3:-${ssh_userhost}}" + if [[ "${mpd_password}x" == "x" ]]; then + mpc_args=(-h "${mpd_host}") + else + mpc_args=(-h "${mpd_password}@${mpd_host}") + fi + mpc_args+=(-p "${mpd_port}") + mpc_args+=(output) + mpc_output_re="Output[[:space:]]([0-9]+)[[:space:]]\(([^\(]+)\)" + while read -r line; do + if [[ "${line}" =~ ${mpc_output_re} ]]; then + mpd_outputs+=("${BASH_REMATCH[2]}") + fi + done< <(${cmd_mpc} "${mpc_args[@]}") + declare -p mpd_outputs 1>&2 hw_params_file="/proc/asound/card${alsa_card_no}/pcm${alsa_dev_no}p/sub0/hw_params" cmd="cat ${hw_params_file}" if [[ "${alsa_ssh_userhost}x" == "x" ]]; then -- GitLab From 7b2cf4c051208afefca8b20d7e4c67f47665a3b0 Mon Sep 17 00:00:00 2001 From: Ronald van Engelen Date: Mon, 29 May 2017 01:42:09 +0200 Subject: [PATCH 8/8] with flex remote alsa host --- lcd | 265 +++++++++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 234 insertions(+), 31 deletions(-) diff --git a/lcd b/lcd index b043738..ba18c4d 100755 --- a/lcd +++ b/lcd @@ -156,6 +156,11 @@ function analyze_command_line() { mpd_password="" ssh_host="" fi + else + [[ ${DEBUG} ]] && \ + declare -p arg_mpd_music_dir \ + arg_mpd_host arg_mpd_port arg_mpd_password \ + arg_ssh_user 1>&2 fi } @@ -166,8 +171,12 @@ function die() { } function human_bytes() { - bytes="$1" - numfmt --to=iec-i --suffix=B --format="%.1f" "${bytes}" + bytes="${1##*.}" + if [[ "${bytes}x" == "x" ]]; then + printf "%s" "0" + else + numfmt --to=iec-i --suffix=B --format="%.1f" "${bytes}" + fi } function check_commands() { @@ -206,13 +215,175 @@ function filter_soxi_duration() { printf "%s:%s" "${minutes}" "${seconds}" } +function run_func() { + func="$1" + shift + args="$@" + [[ ${DEBUG} ]] && declare -p 1>&2 func args + if [[ "${alsa_ssh_userhost}x" == "x" ]]; then + [[ ${DEBUG} ]] && \ + printf 1>&2 "running on local host.\n" + "${func}" + else + [[ ${DEBUG} ]] && \ + printf 1>&2 "running through ssh://using %s.\n" \ + "${alsa_ssh_userhost}" + ssh ${alsa_ssh_userhost} -- \ + "$(declare -f ${func}); ${func} "${args}"" + fi +} + +function ret_mpdconf_contents() { + ## return the contents of the mpd configuration file + alsa_ssh_userhost="${alsa_ssh_userhost:-}" + mpdconf_path="$1" + #declare -p mpdconf_path 1>&2 + #xargs -0 echo < "${mpd_conf}" + if [[ -f "${mpdconf_path}" ]]; then + cat "${mpdconf_path}" + else + printf 1>&2 "error: mpd configuration file %s does not exist on host %s.\n" \ + "${mpdconf_path}" "$(hostname)" + return 1 + fi +} + + +function ret_mpdconf_commandline() { + ## return the command line arguments for running mpd + alsa_ssh_userhost="${alsa_ssh_userhost:-}" + mpd_pid="$(pidof mpd | awk '{print $1}')" + xargs -0 echo < /proc/${mpd_pid}/cmdline +} + + +function ret_mpdconf_default() { + ## function + for conffile in $XDG_CONFIG_HOME/mpd/mpd.conf \ + ~/.mpdconf \ + ~/.mpd/mpd.conf \ + /etc/mpd.conf; do + if [[ "${conffile}x" != "x" ]]; then + if [[ -f ${conffile} ]]; then + [[ ${DEBUG} ]] && \ + printf 1>&2 "using mpd configuration file %s\n" \ + "${conffile}" + echo ${conffile} + return 0 + fi + fi + done + printf 1>&2 "warning: no mpd configuration found.\n" + return 1 +} + + +function ret_mpdconf_path() { + ## returns the name of the mpd.conf file in use by mpd (either + ## local or remote) + ## all possible mpd command line arguments + ## the command mpd itself (including a possible path) gets + ## stripped before + mpd_args=(--no-config) + mpd_args+=(--no-daemon) + mpd_args+=(-v) + mpd_args+=(--verbose) + mpd_args+=(--stderr) + ## strip each command line argument from all possible arguments + ## the remainder is the mpd conf file + mpd_real_args=($(run_func ret_mpdconf_commandline)) + mpd_rest_args=(${mpd_real_args[@]:1}) + for arg in ${mpd_args[@]}; do + mpd_rest_args=(${mpd_rest_args[@]//${arg}}) + done + mpd_conf_file="${mpd_rest_args[0]}" + if [[ "${mpd_conf_file}x" == "x" ]]; then + [[ ${DEBUG} ]] && \ + printf 1>&2 "no conffile specified on mpd command line, \ +test default locations\n" + run_func ret_mpdconf_default + else + printf "%s" "${mpd_conf_file}" + fi +} + +function get_mpdconf_contents() { + mpdconf_path="$1" + run_func ret_mpdconf_contents "${mpdconf_path}" +} + + +function get_mpd_alsa_outputs() { + ## TODO + # while read -r line; do + # done< <(ssh ${alsa_ssh_userhost} -- "cat /ec/mpd.conf") + mpdconf_path=$(ret_mpdconf_path) + #mpdconf_contents="$(get_mpdconf_contents "${mpdconf_path}")" + #declare -p mpdconf_path mpdconf_contents 1>&2 + start_audio_output_re="^[[:space:]]*audio_output[[:space:]]*\{" + end_audio_output_re="[[:space:]]*\}" + ## only handle alsa audio outputs + type_re="^[[:space:]]*type[[:space:]]*[\"'](.*)[\"']" + device_re="^[[:space:]]*device[[:space:]]*[\"']hw:([0-9]+),([0-9]+)[\"']" + audio_outputs=0 + inside_audio_output= + inside_alsa_output= + declare -a devices + while read -r line; do + # declare -p line inside_audio_output inside_alsa_output 1>&2 + if [[ "${inside_audio_output}x" == "x" ]]; then + if [[ "${line}" =~ ${start_audio_output_re} ]]; then + ## new audio_output started + ((audio_outputs++)) + inside_audio_output=true + [[ ${DEBUG} ]] && \ + printf 1>&2 "\n *** starting audio_output\n" + elif [[ "${line}" =~ ${end_audio_output_re} ]]; then + ## end of audio output + inside_audio_output= + fi + else + if [[ "${line}" =~ ${type_re} ]]; then + type="${BASH_REMATCH[1]}" + [[ ${DEBUG} ]] && \ + printf 1>&2 " ** audio_output type: %s\n" "${type}" + if [[ "${type}x" == "alsax" ]]; then + inside_alsa_output=true + else + inside_alsa_output= + fi + elif [[ "${line}" =~ ${device_re} ]] && \ + [[ "${inside_alsa_output}x" != "x" ]]; then + alsa_dev="${BASH_REMATCH[1]}" + alsa_int="${BASH_REMATCH[2]}" + [[ ${DEBUG} ]] && \ + printf 1>&2 " ** audio_output device: hw:%s,%s\n" \ + "${alsa_dev}" "${alsa_int}" + devices+=("hw:${alsa_dev},${alsa_int}") + inside_audio_output= + inside_alsa_output= + fi + fi + done< <(get_mpdconf_contents "${mpdconf_path}") + # declare -p audio_outputs devices 1>&2 + ## TODO: handle multiple devices + for device in ${devices[0]}; do + #printf 1>&2 "alsa device: " + printf "%s" "${device}" + #printf 1>&2 "\n" + done +} + function fill_arrays() { ret_mpc_info || return 1 #ret_mpc_now ret_mpd_now ret_exif_info "${mpc_vals[file]}" ret_soxi_info "${mpc_vals[file]}" - ret_alsa_info "1" "0" + ## TODO get right card and interface numbers + alsa_hw="$(get_mpd_alsa_outputs)" + [[ ${DEBUG} ]] && declare -p alsa_hw 1>&2 + ret_alsa_info "${alsa_hw}" #[[ "${exif_vals[*]}x" == "x" ]] || ret_exif_info "${mpc_vals[file]}" #[[ "${soxi_vals[*]}x" == "x" ]] || ret_soxi_info "${mpc_vals[file]}" #[[ "${alsa_vals[*]}x" == "x" ]] || ret_alsa_info "1" "0" "root@sonida" @@ -281,7 +452,7 @@ function get_info() { ## parse command line arguments analyze_command_line "$@" - ## check presenece of needed commands + ## check presence of needed commands check_commands || return 1 if [[ ! -d "${mpd_music_dir}" ]]; then @@ -291,19 +462,20 @@ function get_info() { mpd_port="${arg_mpd_port:-${def_mpd_port}}" ssh_user="${arg_ssh_user:-${def_ssh_user}}" mpd_password="${arg_mpd_password:-}" - ssh_host="${arg_ssh_host:-}" + ssh_host="${mpd_host:-}" localhost_re="127.0.[0-9]+.[0-9]+|localhost" if [[ "${mpd_host}" =~ ${localhost_re} ]]; then ## mpd runs local, no need for ssh to get alsa properties - ssh_userhost="" + alsa_ssh_userhost="" else - ssh_host="${mpd_host}" + aalsa_ssh_host="${mpd_host}" ## mpd runs remote, use ssh to get alsa properties - ssh_userhost="${ssh_user}@${ssh_host}" + alsa_ssh_userhost="${ssh_user}@${ssh_host}" fi [[ ${DEBUG} ]] && declare -p mpd_host ssh_host ssh_user mpd_music_dir 1>&2 - fill_arrays || return 1 + fill_arrays + #|| return 1 [[ ${DEBUG} ]] && declare -p mpc_vals mpd_vals 1>&2 main_playing_tracktitle="${mpc_vals[title]}" @@ -340,7 +512,7 @@ function get_info() { main_playing_trackplayingtime="${mpc_vals[rt_time_elapsed_minutes]}:${mpc_vals[rt_time_elapsed_seconds]}" main_playing_trackplayingpercentage="${mpc_vals[rt_percentage_played]}%" - declare -p main_playing_trackplayingpercentage 1>&2 + #declare -p main_playing_trackplayingpercentage 1>&2 main_mpd_bitdepth="${mpd_vals[rt_audio_bitdepth]}" main_mpd_samplerate="${mpd_vals[rt_audio_samplerate]}" main_mpd_bitrate="${mpd_vals[rt_audio_bitrate]}" @@ -403,9 +575,11 @@ function ret_mpd_now() { ## echo status command to mpd host on mpd port using netcat, to ## fill mpc_vals array with rt_ fields - [[ "${DEBUG}" ]] && declare -p cmd_netcat mpd_host mpd_port 1>&2 + [[ ${DEBUG} ]] && \ + declare -p cmd_netcat mpd_host mpd_port 1>&2 mpd_status="$(echo "status" | ${cmd_netcat} -N ${mpd_host} ${mpd_port})" - [[ "${DEBUG}" ]] && declare -p mpd_status 1>&2 + [[ ${DEBUG} ]] && \ + declare -p mpd_status 1>&2 linecounter=1 prefix="rt_raw" key_val_re="^([^\:]+):[[:space:]]+(.*)" @@ -443,7 +617,8 @@ function ret_mpc_info() { mpc_args+=(-p "${mpd_port}") mpc_args+=(current) mpc_args+=(-f "${mpc_format_string}") - [[ ${DEBUG} ]] && declare -p mpc_format_string 1>&2 + [[ ${DEBUG} ]] && \ + declare -p mpc_format_string 1>&2 res="$(${cmd_mpc} "${mpc_args[@]}" &)" if [[ $? -ne 0 ]]; then die "${FUNCNAME[0]}: mpd on %s is not running." @@ -500,11 +675,30 @@ function ret_exif_info() { fi } -function ret_alsa_info() { - ## TODO: fix handling of mpd output(s) +function get_hwparams() { alsa_card_no="$1" alsa_dev_no="$2" - alsa_ssh_userhost="${3:-${ssh_userhost}}" + hwparams_file="/proc/asound/card${alsa_card_no}/pcm${alsa_dev_no}p/sub0/hw_params" + if [[ -f "${hwparams_file}" ]]; then + ## return the contents of the file + xargs -0 echo < "${hwparams_file}" + else + printf 1>&2 "error accessing file: '%s' on host '%s'\n" \ + "${hwparams_file}" "$(hostname)" + return 1 + fi +} + +function ret_alsa_info() { + ## TODO: fix handling of mpd output(s) + ## expects "hw:x,y" + alsa_hw="${1//hw:/}" + alsa_card_no="${alsa_hw##*,}" + alsa_dev_no="${alsa_hw%%,*}" + alsa_ssh_userhost="${alsa_ssh_userhost:-}" + [[ ${DEBUG} ]] && \ + declare -p alsa_hw alsa_card_no alsa_dev_no alsa_ssh_userhost + declare -a mpc_args if [[ "${mpd_password}x" == "x" ]]; then mpc_args=(-h "${mpd_host}") else @@ -512,37 +706,46 @@ function ret_alsa_info() { fi mpc_args+=(-p "${mpd_port}") mpc_args+=(output) + [[ ${DEBUG} ]] && \ + declare -p mpd_host mpd_port mpc_args 1>&2 mpc_output_re="Output[[:space:]]([0-9]+)[[:space:]]\(([^\(]+)\)" while read -r line; do if [[ "${line}" =~ ${mpc_output_re} ]]; then mpd_outputs+=("${BASH_REMATCH[2]}") fi done< <(${cmd_mpc} "${mpc_args[@]}") - declare -p mpd_outputs 1>&2 - hw_params_file="/proc/asound/card${alsa_card_no}/pcm${alsa_dev_no}p/sub0/hw_params" - cmd="cat ${hw_params_file}" - if [[ "${alsa_ssh_userhost}x" == "x" ]]; then - res="$(${cmd})" - else - res="$(ssh ${alsa_ssh_userhost} -- "${cmd}")" - fi - if [[ $? -ne 0 ]]; then - printf 1>&2 "error accessing file: '%s' on host '%s'\n" \ - "${hw_params_file}" "${alsa_ssh_userhost}" - return 1 - else + [[ ${DEBUG} ]] && \ + declare -p mpd_outputs 1>&2 + + #hw_params_file="/proc/asound/card${alsa_card_no}/pcm${alsa_dev_no}p/sub0/hw_params" + #cmd="cat ${hw_params_file}" + #if [[ "${alsa_ssh_userhost}x" == "x" ]]; then + ## use local alsa + # xargs -0 echo < /proc/${mpd_pid}/cmdline + # read res < ${hw_params_file} + #else + ## use alsa on remote host + #res="$(ssh ${alsa_ssh_userhost} -- "${cmd}")" + #fi +# if [[ $? -ne 0 ]]; then +# printf 1>&2 "error accessing file: '%s' on host '%s'\n" \ +# "${hw_params_file}" "${alsa_ssh_userhost}" +# return 1 + # else key_val_re="^([^\:]+):[[:space:]]+(.*)" while read -r line; do if [[ "${line}" =~ ${key_val_re} ]]; then field="${BASH_REMATCH[1]}" val="${BASH_REMATCH[2]}" alsa_vals["${field}"]="${val}" + [[ ${DEBUG} ]] && declare -p line field val 1>&2 else [[ ${DEBUG} ]] && declare -p line 1>&2 return 1 fi - done<<<"${res}" - fi + + done< <(run_func get_hwparams "${alsa_card_no} ${alsa_dev_no}") +# fi } function terminal_size() { # Calculate the size of the terminal -- GitLab