Take parameters from CLI options
[khatus.git] / bin / khatus_loop
index 4952483..af5b6ab 100755 (executable)
@@ -1,9 +1,120 @@
 #! /bin/bash
 
-MSG_TAG_SEP=': '
+set -e
+
+produce_volume() {
+    pactl list sinks \
+    | awk '
+        /^\tMute:/ {
+            printf("%s,", $0);
+        }
+        /^\tVolume:/ {
+            for (i=2; i<=NF; i++) printf(" %s", $i);
+        }' \
+    | awk -v RS=',' '
+        /^[ \t]*Mute:/        {mute  = $2}
+        /^[ \t]*front-left:/  {left  = $4}
+        /^[ \t]*front-right:/ {right = $4}
+        END {
+            if (mute == "yes") {
+                printf("x")
+            } else {
+                printf("%s %s", left, right)
+            }
+        }
+        '
+}
+
+produce_mpd_state() {
+    echo 'status' \
+    | nc 127.0.0.1 6600 \
+    | awk '
+        {
+            status[$1] = $2
+        }
+
+        /^time: +[0-9]+:[0-9]+$/ {
+            split($2, time, ":")
+            seconds_current = time[1]
+            seconds_total   = time[2]
+
+            hours = int(seconds_current / 60 / 60);
+            secs_beyond_hours = seconds_current - (hours * 60 * 60);
+            mins = int(secs_beyond_hours / 60);
+            secs = secs_beyond_hours - (mins * 60);
+            if (hours > 0) {
+                current_time = sprintf("%d:%.2d:%.2d", hours, mins, secs)
+            } else {
+                current_time = sprintf("%.2d:%.2d", mins, secs)
+            }
+
+            if (seconds_total > 0) {
+                time_percentage = (seconds_current / seconds_total) * 100
+                current_percentage = sprintf("%d%%", time_percentage)
+            } else {
+                current_percentage = "~"
+            }
+        }
+
+        END {
+            state = status["state:"]
+
+            if (state == "play") {
+                symbol = "▶"
+            } else if (state == "pause") {
+                symbol = "❚❚"
+            } else if (state == "stop") {
+                symbol = "⬛"
+            } else {
+                symbol = "--"
+            }
+
+            printf(\
+                "%s %s %s",
+                status["state:"], current_time, current_percentage\
+            )
+        }
+        '
+}
+
+produce_mpd_song() {
+    echo 'currentsong' \
+    | nc 127.0.0.1 6600 \
+    | awk '
+        /^OK/ {
+            next
+        }
+
+        {
+            key = $1
+            sub("^" key " +", "")
+            val = $0
+            data[key] = val
+        }
+
+        END {
+            name  = data["Name:"]
+            title = data["Title:"]
+            file  = data["file:"]
+
+            if (name) {
+                out = name
+            } else if (title) {
+                out = title
+            } else if (file) {
+                last = split(file, parts, "/")
+                out = parts[last]
+            } else {
+                out = ""
+            }
+            print out
+        }
+        '
+}
 
 produce_weather() {
-    metar -d "$WEATHER_STATION_ID" 2>&1 \
+    weather_station_id="$1"
+    metar -d "$weather_station_id" 2>&1 \
     | awk '
         /METAR pattern not found in NOAA data/ {
             failures++
@@ -31,28 +142,58 @@ consume() {
     pipe="$1"
     tail -f "$pipe" \
     | stdbuf -o L awk \
+        -v opt_debug=0 \
+        -v opt_mpd_song_max_chars=10 \
         '
-            /^in:WEATHER:/\
+            /^in:VOLUME/\
+            {
+                split_msg_parts()
+                db["volume"] = msg_body
+            }
+
+            /^in:MPD_STATE/\
             {
-                db["weather_temperature"] = read_msg()
+                split_msg_parts()
+                db["mpd_state"]             = $1
+                db["mpd_curr_song_time"]    = $2
+                db["mpd_curr_song_percent"] = $3
             }
 
-            /^in:DATE_TIME:/\
+            /^in:MPD_SONG/\
             {
-                db["datetime"] = read_msg()
+                split_msg_parts()
+                db["mpd_curr_song_name"] = msg_body
             }
 
-            /^out:BAR:/\
+            /^in:WEATHER/\
             {
+                split_msg_parts()
+                db["weather_temperature"] = msg_body
+            }
+
+            /^in:DATE_TIME/\
+            {
+                split_msg_parts()
+                db["datetime"] = msg_body
+            }
+
+            /^out:BAR/\
+            {
+                split_msg_parts()
                 print make_bar()
             }
 
-            function read_msg() {
-                sub("^" $1 " +", "")
-                return $0
+
+            function split_msg_parts() {
+                msg_head = $1
+                sub("^" msg_head " +", "")
+                msg_body = $0
+                debug(msg_head, msg_body)
             }
 
-            function make_bar(    position, bar, i) {
+            function make_bar(    position, bar, sep, i, j) {
+                position[++i] = sprintf("(%s)", db["volume"])
+                position[++i] = make_status_mpd()
                 position[++i] = db["weather_temperature"]
                 position[++i] = db["datetime"]
                 bar = ""
@@ -63,6 +204,46 @@ consume() {
                 }
                 return bar
             }
+
+            function make_status_mpd(    state, status) {
+                state = db["mpd_state"]
+
+                if (state == "play") {
+                    status = make_status_mpd_state_known("▶")
+                } else if (state == "pause") {
+                    status = make_status_mpd_state_known("❚❚")
+                } else if (state == "stop") {
+                    status = make_status_mpd_state_known("⬛")
+                } else {
+                    status = make_status_mpd_state_unknown("--")
+                }
+
+                return sprintf("[%s]", status)
+            }
+
+            function make_status_mpd_state_known(symbol) {
+                return sprintf(\
+                    "%s %s %s %s",
+                    symbol,
+                    db["mpd_curr_song_time"],
+                    db["mpd_curr_song_percent"],
+                    substr(db["mpd_curr_song_name"], 1, opt_mpd_song_max_chars)\
+                )
+            }
+
+            function make_status_mpd_state_unknown(symbol) {
+                return sprintf("%s", symbol)
+            }
+
+            function debug(location, msg) {
+                if (opt_debug) {
+                    print_error(location, msg)
+                }
+            }
+
+            function print_error(location, msg) {
+                print(location " ==> " msg) > "/dev/stderr"
+            }
         '
 }
 
@@ -73,28 +254,66 @@ produce_bar_req() {
 spawn() {
     cmd="$1"
     pipe="$2"
-    tag="$3"
+    msg_head="$3"
     interval="$4"
     while true; do
-        echo "${tag}${MSG_TAG_SEP}$($cmd)" > "$pipe"
+        echo "${msg_head} $($cmd)" > "$pipe"
         sleep  "$interval"
     done &
 }
 
 main() {
-    dir_bin="$1"
-    dir_data="$2"
-    pipe="$dir_data/pipe"
+    # Defaults
+    dir_data="$HOME/.khatus"
+    weather_station_id='KJFK'
+
+    # User-overrides
+    OPTS=$(
+        getopt \
+            -o '' \
+            -l data-dir:,weather-station: \
+            -- "$@"
+    )
+    eval set -- "$OPTS"
+    while true
+    do
+        case "$1" in
+            --data-dir)
+                dir_data="$2"
+                shift 2
+                ;;
+            --weather-station)
+                weather_station_id="$2"
+                shift 2
+                ;;
+            --)
+                shift
+                break
+                ;;
+        esac
+    done
+
+    ( echo "Khatus starting with the following parameters:"
+      ( echo "    dir_data|= $dir_data"
+        echo "    weather_station_id|= $weather_station_id"
+      ) | column -ts\|
+      echo ''
+    ) >&2
 
-    WEATHER_STATION_ID='KJFK'
+    pipe="$dir_data/khatus_data_pipe"
 
+    mkdir -p "$dir_data"
     rm -f "$pipe"
     mkfifo "$pipe"
 
-    spawn produce_datetime  "$pipe" 'in:DATE_TIME' 1
-    spawn produce_weather   "$pipe" 'in:WEATHER'   $(( 30 * 60 ))
-    spawn produce_bar_req   "$pipe" 'out:BAR'      1
-    consume "$pipe"
+    # TODO: Redirect each worker's stderr to a dedicated log file
+    spawn produce_datetime                      "$pipe" 'in:DATE_TIME' 1
+    spawn "produce_weather $weather_station_id" "$pipe" 'in:WEATHER'   $(( 30 * 60 ))
+    spawn produce_mpd_state                     "$pipe" 'in:MPD_STATE' 1
+    spawn produce_mpd_song                      "$pipe" 'in:MPD_SONG'  1
+    spawn produce_volume                        "$pipe" 'in:VOLUME'    1
+    spawn produce_bar_req                       "$pipe" 'out:BAR'      1
+          consume                               "$pipe"
 }
 
 main $@
This page took 0.04223 seconds and 4 git commands to generate.