mpd-status.go (3209B)
1 /*mpd-status - Print the artist, song title, status, elapsed time 2 3 Copyright (C) 2019 Brian C. Lane <bcl@brianlane.com> 4 5 This program is free software; you can redistribute it and/or modify 6 it under the terms of the GNU General Public License as published by 7 the Free Software Foundation; either version 2 of the License, or 8 (at your option) any later version. 9 10 This program is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 GNU General Public License for more details. 14 15 You should have received a copy of the GNU General Public License along 16 with this program; if not, write to the Free Software Foundation, Inc., 17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 18 */ 19 package main 20 21 import ( 22 "flag" 23 "fmt" 24 "github.com/fhs/gompd/mpd" 25 "log" 26 "strings" 27 "time" 28 "unicode/utf8" 29 ) 30 31 /* commandline flags */ 32 type cmdlineArgs struct { 33 Volume bool // Show volume percentage 0-100 34 Elapsed bool // Show the duration:elapsed time 35 Width int // Maximum width 36 } 37 38 /* commandline defaults */ 39 var cfg = cmdlineArgs{ 40 Volume: false, 41 Elapsed: false, 42 Width: 60, 43 } 44 45 /* parseArgs handles parsing the cmdline args and setting values in the global cfg struct */ 46 func parseArgs() { 47 flag.BoolVar(&cfg.Volume, "volume", cfg.Volume, "Include the volume percentage 0-100") 48 flag.BoolVar(&cfg.Elapsed, "elapsed", cfg.Elapsed, "Include the duration:elapsed time") 49 flag.IntVar(&cfg.Width, "width", cfg.Width, "Maximum width of output") 50 51 flag.Parse() 52 } 53 54 func main() { 55 parseArgs() 56 57 // Connect to MPD server 58 conn, err := mpd.Dial("tcp", "localhost:6600") 59 if err != nil { 60 log.Fatalln(err) 61 } 62 defer conn.Close() 63 64 // Get the status and current song 65 status, err := conn.Status() 66 if err != nil { 67 log.Fatalln(err) 68 } 69 song, err := conn.CurrentSong() 70 if err != nil { 71 log.Fatalln(err) 72 } 73 // fmt.Printf("STATUS- %s\n", status) 74 // fmt.Printf("SONG- %s\n", song) 75 76 // Build the optional parts of the output 77 var optional strings.Builder 78 if cfg.Volume { 79 fmt.Fprintf(&optional, " %s%%", status["volume"]) 80 } 81 if cfg.Elapsed { 82 duration, _ := time.ParseDuration(status["duration"] + "s") 83 elapsed, _ := time.ParseDuration(status["elapsed"] + "s") 84 fmt.Fprintf(&optional, " %s/%s", elapsed.Truncate(time.Second), duration.Truncate(time.Second)) 85 } 86 87 // Build the final output string 88 var s strings.Builder 89 switch status["state"] { 90 case "play": 91 s.WriteString("▶ ") 92 case "stop": 93 s.WriteString("◼ ") 94 case "pause": 95 s.WriteString("‖ ") 96 default: 97 s.WriteString(" ") 98 } 99 100 // Build the Artist + title part (do I want to make artist optional? album?) 101 songStr := fmt.Sprintf("%s - %s", song["Artist"], song["Title"]) 102 103 // Calculate how much title to trim 104 trim := cfg.Width - utf8.RuneCountInString(optional.String()) - utf8.RuneCountInString(s.String()) 105 trim = utf8.RuneCountInString(songStr) - trim 106 if trim < 0 { 107 trim = 0 108 } else if trim > utf8.RuneCountInString(songStr) { 109 trim = utf8.RuneCountInString(songStr) 110 } 111 112 // Trim the title so that it will fit into the width 113 fmt.Printf("%s%s%s", s.String(), songStr[trim:], optional.String()) 114 }