1 -- Authors: Hendrik Iben <hiben@tzi.de>
2 -- License: GPL, version 2
3 -- Last Changed: 2006-03-23
5 -- statusd_xmmsip.lua v20060323
7 -- Interface to the XMMS InfoPipe-Plugin
8 -- Inspired by the high cpu attention statusd_xmms.lua + python demand...
9 -- ( no offense, just observation... :-)
10 -- (using statusd_xmms while writing this... ;-) )
12 -- Written by Hendrik Iben < hiben at tzi dot de >
15 -- xmmsip provides a lot of statusd-monitors
16 -- You can compose the text displayed in your statusbar using these individual
17 -- monitors or/and you may specify a string with a setup of the values you
21 -- xmmsip_pllen : Length of the playlist (number of entries)
22 -- xmmsip_plcur : Current song in playlist (number of entry)
23 -- xmmsip_file : Current file played
24 -- xmmsip_title : Current file's title
25 -- xmmsip_usectime : Length of file in milliseconds (-1 for streams)
26 -- xmmsip_time : Length of file in minutes:seconds or '>>>' for streams
27 -- xmmsip_usecpos : Position in file in milliseconds
28 -- xmmsip_pos : Position in file in minutes:seconds
29 -- xmmsip_usecleft : Time left in milliseconds (0 for streams)
30 -- xmmsip_left : Time left in minutes:seconds or "<<<" for streams
31 -- xmmsip_status : XMMS's status : (Playing, Paused, Stopped, Not running)
32 -- xmmsip_sstatus : same as above but all lowercase
33 -- xmmsip_bitrate : Current bitrate (not average bitrate)
34 -- xmmsip_kbitrate : Current bitrate in kilobit per seconds (using 1000 for k)
35 -- xmmsip_freq : Sampling frequency in Hz
36 -- xmmsip_kfreq : Sampling frequency in kHz
37 -- xmmsip_channels : Current channels (1,2,?)
38 -- xmmsip_xmmsproto : Protocol version of XMMS
39 -- xmmsip_infover : Version of InfoPipe-Plugin
41 -- xmmsip_user : String resulting from 'user_format'-string
42 -- or 'not_running'-string
44 -- While it is perfectly legal to use these directly in your statusbar I
45 -- recommend you to only use xmmsip_user and configure the format string.
46 -- This way you do not get a '?' for every monitor when XMMS is not running...
48 -- Setting up the 'user_format'-string is done by forming a string where each
49 -- xmmsip_x-monitor is referenced to by '%x%'
52 -- "...%xmmsip_status %xmmsip_title ..blub..." in cfg_statusbar template
54 -- -> "%status% %title%" in xmmsip-config 'user_format'
55 -- and "...%xmmsip_user ..blub..." in cfg_statusbar template
57 -- The mentionend 'not_running'-string is specified in xmmsip-config as
58 -- 'not_running' and will replace %xmmsip_user% whenever the XMMS InfoPipe
59 -- is not running (or found...)
61 -- If you are finally convinced that xmmsip_user is the only monitor you need
62 -- you may disable telling statusd about the other monitors. I have no idea, if
63 -- this has much impact on performance but who knows...
65 -- xmmsip-config -> do_monitors = false
67 -- speaking of configuration you might want a description of what the settings
68 -- do and what the defaults are :
70 -- interval : delay between checking the pipe (5 seconds)
71 -- user : user name (for xmms-session) (current user)
72 -- xmms_session : the xmms-session to use (0)
73 -- do_monitors : inform statusd of all monitors or just of xmmsip_user (true)
74 -- user_format : template for xmmsip_user (see in code)
75 -- not_running : replacement for xmmsip_user when no pipe is found
79 -- ion3 (tested with 20060305 gentoo ebuild)
80 -- lua (tested with 5.0.2)
81 -- xmms-infopipe v1.3 or compatible
82 -- I have not tested pipes from/for other players...
84 -- Serving suggestions :
85 -- I use the rotate_statusbar replacement for the standard statusbar as I
86 -- want to display a lot of things but not always...
87 -- XMMS-status information takes quite a bit of space so you might consider
88 -- doing it a bit like me .. but of course in your own special and
91 -- This is my current setup :
93 -- cfg_statusbar (rotate_statusbar)
96 -- rotate_statusbar.configurations = {
100 -- interval = 1 * 1000,
101 -- user_format = "XMMS (%status%) %title% (%left%/%time%)",
102 -- not_running = "Turn on the Radio!",
103 -- do_monitors = false,
108 -- rotate_statusbar.settings = {
111 -- all_statusbars = {
112 -- "[ %date || %xmmsip_user ]%filler%systray",
113 -- "[ %fortune ]%filler%systray",
117 -- This setup updates the information every second showing the status of
118 -- xmms, the current title, the time that is left and the total time
119 -- of the current song.
120 -- Additionally when xmms is not running a get a reminder to turn it on,
121 -- and as I do not need the other monitors they are disabled.
125 -- Feel free to contact me if you discover bugs or want to comment on this.
128 -- You are free to distribute this software under the terms of the GNU
129 -- General Public License Version 2.
131 if not statusd_xmmsip
then
134 user
= os
.getenv("USER"),
137 user_format
= "%status%: %title% (%pos%/%time%, %plcur%/%pllen%, %kfreq%kHz@%kbitrate%kbps)",
138 not_running
= "Not runnning...",
142 -- merge external settings with defaults
143 local settings
= table.join (statusd
.get_config("xmmsip"), statusd_xmmsip
)
145 -- location of the infopipe
146 local xmmsinfopipe
= "/tmp/xmms-info"
148 -- info-pipe is named by user and session
149 if settings
.user
~= nil -- should not happen... but default should be okay anyway...
151 xmmsinfopipe
= xmmsinfopipe
.. "_" .. settings
.user
.. "." .. settings
.xmms_session
154 -- mapping to InfoPipe-keys
156 xmmsip_pllen
= "Tunes in playlist",
157 xmmsip_plcur
= "Currently playing",
158 xmmsip_file
= "File",
159 xmmsip_title
= "Title",
160 xmmsip_usectime
= "uSecTime",
161 xmmsip_time
= "Time",
162 xmmsip_usecpos
= "uSecPosition",
163 xmmsip_pos
= "Position",
164 xmmsip_left
= "left",
165 xmmsip_usecleft
= "usecleft",
166 xmmsip_status
= "Status",
167 xmmsip_sstatus
= "sstatus",
168 xmmsip_bitrate
= "Current bitrate",
169 xmmsip_kbitrate
= "kbitrate",
170 xmmsip_freq
= "Samping Frequency", -- will this ever get fixed ?
171 xmmsip_kfreq
= "kfreq",
172 xmmsip_channels
= "Channels",
173 xmmsip_xmmsproto
= "XMMS protocol version",
174 xmmsip_infover
= "InfoPipe Plugin version",
177 -- changes all 'nil's in the infotable to '?' (for statusbar)
178 -- needed when the infopipe is not running or incompatible...
179 local function fixTable(it
)
180 for _
, v
in pairs(valueassoc
)
190 -- some convenience values
191 local function addSpecialValues(it
)
192 local bitrate
= it
[valueassoc
["xmmsip_bitrate"]]
195 it
[valueassoc
["xmmsip_kbitrate"]]
= math
.floor(bitrate
/ 1000)
197 local status
= it
[valueassoc
["xmmsip_status"]]
200 it
[valueassoc
["xmmsip_sstatus"]]
= string.lower(status
)
202 local freq
= it
[valueassoc
["xmmsip_freq"]]
205 it
[valueassoc
["xmmsip_kfreq"]]
= math
.floor(freq
/ 1000)
207 local usectime
= it
[valueassoc
["xmmsip_usectime"]]
208 local usecpos
= it
[valueassoc
["xmmsip_usecpos"]]
209 -- streaming leaves time at zero
210 if ( ( usectime
~= nil ) and ( usecpos
~= nil ) )
212 -- force lua to coerce this to a number...
213 if ((usectime
+ 0) > 0)
216 local usecleft
= usectime
- usecpos
217 local mins
= math
.floor( usecleft
/ (60 * 1000) )
218 local secs
= math
.floor( math
.mod( usecleft
, 60 * 1000 ) / 1000 )
219 local left
= string.format("%i:%02i", mins
, secs
)
220 it
[valueassoc
["xmmsip_usecleft"]]
= usecleft
221 it
[valueassoc
["xmmsip_left"]]
= left
224 -- I would so like to use unicode for the
225 -- moebius but ion does not like it - yet...
226 it
[valueassoc
["xmmsip_time"]]
=">>>"
227 it
[valueassoc
["xmmsip_left"]]
="<<<"
228 it
[valueassoc
["xmmsip_usecleft"]]
=0
234 -- this formats the user_format-string
235 local function makeUserString(s
, it
)
237 for k
, v
in pairs(valueassoc
)
239 -- it would be annoying to type 'xmmsip_' in front
241 _
, _
, stripped
= string.find(k
, "xmmsip_(.*)")
242 rval
= string.gsub(rval
, "%%"..stripped
.."%%", it
[v
])
250 -- retrive information from the pipe - if it exists,
251 -- calculate some additional values and clean the table
253 -- After that update statusd-monitors if the users wishes
254 -- and create the user-string from the template
255 local function fetch_data(partial_data
)
256 local infotable
= { } -- tabula rasa
260 pipedata
= pipedata
.. partial_data
261 partial_data
= coroutine
.yield()
264 local running
= true -- assume the best
266 if pipedata
and pipedata
~= ""
268 for attribute
, value
in string.gfind(pipedata
, "([^:]*):%s*([^\n]*)\n")
270 infotable
[attribute
] = value
275 infotable
[valueassoc
["xmmsip_status"]]
="Not running"
278 -- compute things like time left or divide things by 1000...
279 infotable
= addSpecialValues(infotable
)
280 -- scan for nil-values and fix them with '?'
281 infotable
= fixTable(infotable
)
283 -- if we are to update the monitors...
284 if settings
.do_monitors
286 for k
, v
in pairs(valueassoc
)
288 -- do so, but coerce to string
289 statusd
.inform(k
, ""..infotable
[v
])
293 -- create appropriate user-string
296 statusd
.inform("xmmsip_user", makeUserString(settings
.user_format
, infotable
))
298 statusd
.inform("xmmsip_user", settings
.not_running
)
301 xmmsip_timer
:set(settings
.interval
, update_xmmsip
)
304 -- fetch error (and discard...)
305 local function flush_stderr(partial_data
)
309 result
= result
.. partial_data
310 partial_data
= coroutine
.yield()
313 -- I don't know what to do with the actual error...
314 -- This would be called a lot when the pipe is not
318 -- update monitor with bgread
319 function update_xmmsip()
320 statusd
.popen_bgread(
321 'cat ' .. xmmsinfopipe
322 , coroutine
.wrap(fetch_data
)
323 , coroutine
.wrap(flush_stderr
)
328 xmmsip_timer
= statusd
.create_timer()