Include notionflux in the main repo instead of its own submodule
[notion/jeffpc.git] / contrib / statusd / statusd_mpd.lua
blobed40b0ad1a7d55141b95cd704b379715123b6bbf
1 -- Authors: <delirium@hackish.org>
2 -- License: Unknown
3 -- Last Changed: Unknown
4 --
5 -- statusd for MPD (Music Player Daemon)
6 -- bugs/requests/comments: delirium@hackish.org
8 -- requires that netcat is available in the path
10 local defaults={
11 -- 500 or less makes seconds increment relatively smoothly while playing
12 update_interval=500,
14 -- mpd server info (localhost:6600 are mpd defaults)
15 address="localhost",
16 port=6600,
18 -- mpd password (if any)
19 password=nil,
21 -- display template
22 -- ---
23 -- can use the following:
24 -- track metadata: %artist, %title, %num, %album, %year, %len
25 -- current track position: %pos
26 -- escape for the percent character: %%
28 -- a default template
29 template = "%artist - %num - %title (%pos / %len)"
32 local settings=table.join(statusd.get_config("mpd"), defaults)
34 local success
35 local last_success
37 local function saferead(file)
38 local data, err, errno
39 repeat
40 data, err, errno = file:read()
41 until errno ~= 4 -- EINTR
42 return data, err, errno
43 end
45 local function get_mpd_status()
46 local cmd_string = "status\ncurrentsong\nclose\n"
47 if settings.password ~= nil then
48 cmd_string = "password " .. settings.password .. "\n" .. cmd_string
49 end
50 cmd_string = string.format('echo -n "%s" | netcat %s %d',
51 cmd_string, settings.address, settings.port)
53 last_success = success
54 success = false
56 local mpd = io.popen(cmd_string, "r")
58 -- welcome msg
59 local data = saferead(mpd)
60 if data == nil or string.sub(data,1,6) ~= "OK MPD" then
61 mpd:close()
62 return "mpd not running"
63 end
65 -- 'password' response (if necessary)
66 if settings.password ~= nil then
67 repeat
68 data = saferead(mpd)
69 until data == nil or string.sub(data,1,2) == "OK" or string.sub(data,1,3) == "ACK"
70 if data == nil or string.sub(data,1,2) ~= "OK" then
71 mpd:close()
72 return "bad mpd password"
73 end
74 end
76 local info = {}
78 -- 'status' response
79 repeat
80 data = saferead(mpd)
81 if data == nil then break end
83 local _,_,attrib,val = string.find(data, "(.-): (.*)")
84 if attrib == "time" then
85 _,_,info.pos,info.len = string.find(val, "(%d+):(%d+)")
86 info.pos = string.format("%d:%02d", math.floor(info.pos / 60), math.mod(info.pos, 60))
87 info.len = string.format("%d:%02d", math.floor(info.len / 60), math.mod(info.len, 60))
88 elseif attrib == "state" then
89 info.state = val
90 end
91 until string.sub(data,1,2) == "OK" or string.sub(data,1,3) == "ACK"
92 if data == nil or string.sub(data,1,2) ~= "OK" then
93 mpd:close()
94 return "error querying mpd status"
95 end
97 -- 'currentsong' response
98 repeat
99 data = saferead(mpd)
100 if data == nil then break end
102 local _,_,attrib,val = string.find(data, "(.-): (.*)")
103 if attrib == "Artist" then info.artist = val
104 elseif attrib == "Title" then info.title = val
105 elseif attrib == "Album" then info.album = val
106 elseif attrib == "Track" then info.num = val
107 elseif attrib == "Date" then info.year = val
109 until string.sub(data,1,2) == "OK" or string.sub(data,1,3) == "ACK"
110 if data == nil or string.sub(data,1,2) ~= "OK" then
111 mpd:close()
112 return "error querying current song"
115 mpd:close()
117 success = true
119 -- done querying; now build the string
120 if info.state == "play" then
121 local mpd_st = settings.template
122 -- fill in %values
123 mpd_st = string.gsub(mpd_st, "%%([%w%_]+)", function (x) return(info[x] or "") end)
124 mpd_st = string.gsub(mpd_st, "%%%%", "%%")
125 return mpd_st
126 elseif info.state == "pause" then
127 return "Paused"
128 else
129 return "No song playing"
134 local mpd_timer
136 local function update_mpd()
137 -- update unless there's an error that's not yet twice in a row, to allow
138 -- for transient errors due to load spikes
139 local mpd_st = get_mpd_status()
140 if success or not last_success then
141 statusd.inform("mpd", mpd_st)
143 mpd_timer:set(settings.update_interval, update_mpd)
146 -- Init
147 mpd_timer=statusd.create_timer()
148 update_mpd()