[UP] use ion3-plus haha.
[arrow.git] / archlinux_conf / etc / ion3 / old / statusd_mocp.lua
blob3087e4dc0dcd8c449350b4a92b6f4e92c5951f29
1 -- statusd_mocp.lua
2 --[[
3 statusd for moc (Music On Console). This is called mocp for two reasons.
4 First, there is already a statusd_moc.lua. Secondly, the actual executable
5 is called mocp on Debian because moc is taken by Qt.
7 Moc is a great replacement for xmms. It's even better in an ion3 environment
8 because it's all console based.
10 Keys are now dynamically generated by the output from "mocp -i". If mocp adds a
11 new field, it will be statusd.inform()ed. No more messy tables or redundant
12 variables. The keys follow the ion convention and are lowercased.
14 You can also use the new user_defined_* variables. This lets you
15 have a template for when mocp is playing or paused (with lots of information)
16 and a very simple one for when it is off. If you use the keys directly, then
17 you will get a lot of "?" when mocp is off. You can either edit this file
18 directly or edit your cfg_statusbar.lua (see below). I recommend editing your
19 cfg_statusbar.lua.
21 The format of the user_defined_* is to use the normal keys listed below
22 but without the mocp_ prefix. For instance, in your cfg_statusbar.lua file
23 you could have:
25 if not rotate_statusbar.configurations then
26 rotate_statusbar.configurations = {
27 -- Moc meter
28 mocp = {
29 -- Update the statusbar every 2 seconds.
30 update_interval = 2 * 1000,
32 -- Template when moc is playing music
33 user_defined_play = 'moc: %state "%title" '
34 .. "(%currenttime / %totaltime)",
36 -- Template when moc is paused
37 user_defined_pause = 'moc: %state "%songtitle" %bitrate '
38 .. "[%currenttime | %totaltime]",
40 -- State is the only value reported when mocp is stopped.
41 user_defined_stop = "moc: %state",
43 -- State is the only value reported when mocp is off.
44 user_defined_off = "",
47 end
49 And then in your statusbar template, use %mocp_user_defined. It will use
50 one of the user_defined_* templates depending on mocp's state.
52 Keys currently reported by "mocp -i":
53 %mocp_state (can be "PLAY", "PAUSE", "STOP", or "OFF")
54 %mocp_file (e.g. "/music/cdbaby/Celldweller_-_Switchback_-_2001.ogg")
55 %mocp_title (e.g. "Celldweller - Switchback - 2001 (The Beta Cessions)")
56 %mocp_artist (e.g. "Celldweller")
57 %mocp_songtitle (e.g. "Switchback - 2001")
58 %mocp_album (e.g. "The Beta Cessions")
59 %mocp_totaltime (e.g. "04:35")
60 %mocp_timeleft (e.g. "04:22")
61 %mocp_totalsec (e.g. "275")
62 %mocp_currenttime (e.g. "00:13")
63 %mocp_currentsec (e.g. "13")
64 %mocp_bitrate (e.g. "87Kbps")
65 %mocp_rate (e.g. "44KHz")
67 This is not generated by mocp's output. The format is determined by the
68 template in cfg_statusbar.lua.
69 %mocp_user_defined (String based on user_defined_* and moc's state)
71 Default settings you can change from your statusbar configuration:
72 update_interval How frequently to change the status
73 socket_dir Where mocp's socket is relative to ion's working directory
74 command Command to execute to get information from mocp
75 user_defined_play Statusbar template when mocp is playing
76 user_defined_pause Statusbar template when mocp is paused
77 user_defined_stop Statusbar template when mocp is stopped
78 user_defined_off Statusbar template when mocp is not running
81 Usage:
83 1) If you do not have ~/.ion3/cfg_statusbar.lua, copy that file from Ion3 to
84 your ~/.ion3 directory. On Debian, it is in /etc/X11/ion3/cfg_statusbar.lua.
86 2) Ion3 will load the appropriate modules if they are in the template at
87 startup.
89 So place one or more of the above %mocp_* fields into the template in
90 ~/.ion3/cfg_statusbar.lua.
92 3) You can use the user_defined_* keys instead of using the keys
93 in step #2. To do this, open up ~/.ion3/cfg_statusbar.lua and go to
94 the section with the defaults. Add on_template and off_template in the
95 table for mocp (you may have to add one similar to the load or mail).
97 Then in your ~/.ion3/cfg_statusbar.lua, simply add %mocp_user_defined
98 and it will expand either user_defined_* at runtime.
100 4) Restart ion3 (Hit F12 and type 'session/restart')
102 Alternative Usage: you could use rotate_statusbar.lua so you can rotate
103 between templates. This is useful when you have too much information for
104 one statusbar template or you only care to know the info periodically.
106 To do this, copy rotate_statusbar.lua to ~/.ion3/cfg_statusbar.lua and
107 do steps 2-4 above.
110 You can test this out independent of ion. This will print all of
111 the key=value pairs statusd.inform() was sent.
113 1) Copy statusd_mocp.lua to ~/.ion3/
115 2) Run '/usr/lib/ion3/ion-statusd -m mocp'
116 This will dump out all of the updates to the terminal as they happen
118 3) Hit control+c when you are done testing.
121 All public domain based on statusd_moc.lua. It also borrows some
122 ideas from rss_feed.lua which is public domain too. I used the idea of
123 an on/off template from statusd_mocmon.lua.
126 tyranix [tyranix at gmail]
128 --]]
130 local defaults={
131 -- Update every 2 seconds
132 update_interval=9*1000,
134 -- ~/.moc is where moc stores preferences and the socket
135 socket_dir=os.getenv("HOME").."/.moc",
137 -- Command to get information from mocp.
138 command="mocp -i 2>/dev/null",
140 -- User defined template. If mocp is off, we replace it with the other
141 -- template. This template format is similar to the statusbar template
142 -- except that I only replace %mocp_* keys. Leave off the mocp_ part
143 -- because we don't need that here.
144 user_defined_play = 'moc: %state "%title" (%currenttime / %totaltime)',
146 -- User defined template when moc is paused.
147 user_defined_pause = 'moc: %state "%songtitle" %bitrate '
148 .. "[%currenttime | %totaltime]",
150 -- User defined template when moc is stopped. Only the state key can be
151 -- replaced in this string.
152 user_defined_stop = "moc: %state",
154 -- User defined template. This is what is displayed if moc is turned off.
155 -- Only the state key can be replaced.
156 -- When moc isn't running, I prefer to not display anything.
157 user_defined_off = "",
160 local mocp_timer = nil
161 local mocp_values = {}
163 -- Overwrite our defaults with the user's settings
164 local settings = table.join(statusd.get_config("mocp"), defaults)
166 -- This must come after the above settings definition.
167 local mocp_templates = {
168 PLAY = settings.user_defined_play,
169 PAUSE = settings.user_defined_pause,
170 STOP = settings.user_defined_stop,
171 OFF = settings.user_defined_off,
174 -- Used by gsub on each pattern matched. This sets the values.
175 -- 'name' and 'setting' are the two referenced patterns (in parentheses).
176 local function set_mocp_values(name, value)
177 mocp_values[string.lower(name)] = value
180 -- Used by gsub on each pattern matched. This returns the value for a template.
181 local function get_mocp_values(name)
182 if not mocp_values[name] then
183 return "?"
184 else
185 return mocp_values[name]
189 -- Tell statusd to update its keys with our new values.
190 local function inform_statusd(mocp_status)
191 local name, value
192 mocp_values = {}
194 -- If we didn't get any output from mocp, then it is turned off.
195 if not mocp_status or mocp_status == "" then
196 mocp_values["state"] = "OFF"
197 else
198 -- Go through the output from 'mocp -i' and find the values.
199 -- All of mocp's output has this format: Name: setting\n
200 -- Even when there is no setting, there's always a space.
201 -- The 20 at the end prevents it from going into an infinite loop if
202 -- the user specified some strange option. It makes at most 20
203 -- substitutions.
204 string.gsub(mocp_status, "(%w+): ([^\n]*)", set_mocp_values, 20)
207 -- Report all of the known values from mocp -i (not user defined).
208 -- For off/stopped, it is only the state.
209 for name, value in pairs(mocp_values) do
210 statusd.inform("mocp_" .. name, value)
213 -- Point to the right user defined template depending on moc's state
214 local template = mocp_templates[mocp_values["state"]];
215 if not template then
216 template = "statusd_mocp: Error! Invalid state '"
217 .. mocp_values["state"] .. "' found"
220 -- Report the user's template
221 local result = string.gsub(template, "%%([a-z0-9_]+)", get_mocp_values)
222 statusd.inform("mocp_user_defined", result)
225 -- Continually read input until partial_data is nil then parse it.
226 local function read_from_mocp(partial_data)
227 -- statusd.popen_bgread() will return data as it becomes available.
228 -- The easiest way to handle this is to keep concatenating the data
229 -- until it runs out. There's no guarantee that popen_bgread() will
230 -- return full lines (up to a newline).
231 local mocp_status = ""
232 while partial_data do
233 mocp_status = mocp_status .. partial_data
234 -- Yield until we get more input. popen_bgread will call resume on us.
235 partial_data = coroutine.yield()
238 -- After we have read all the data, then inform statusd.
239 inform_statusd(mocp_status)
241 -- Continually call the update function.
242 mocp_timer:set(settings.update_interval, update_mocp)
245 -- Continually read from stderr. It just prints it out to stdout now.
246 -- This should never be called because we're dumping it to /dev/null.
247 local function print_stderr(partial_data)
248 local mocp_error = ""
249 while partial_data do
250 mocp_error = mocp_error .. partial_data
251 -- Yield until we get more input. popen_bgread will call resume on us.
252 partial_data = coroutine.yield()
254 print(mocp_error, "\n")
257 -- Main loop for mocp.
258 function update_mocp()
259 -- If there is no PID file, then moc is turned off.
260 local f=io.open(settings.socket_dir.."/pid")
261 if not f then
262 -- mocp is turned off
263 read_from_mocp()
264 else
265 f:close()
267 -- Tell ion to start up mocp and keep reading partial
268 -- chunks until it is complete. This is better for
269 -- performance because ion doesn't have to block here.
270 statusd.popen_bgread(settings.command,
271 coroutine.wrap(read_from_mocp),
272 coroutine.wrap(print_stderr))
276 -- Timer so we can keep telling statusd what the current value is.
277 mocp_timer = statusd.create_timer()
278 update_mocp()