modal bindings and extended mpd capabilities

This commit is contained in:
crater2150 2012-03-16 00:52:06 +01:00
parent 3f3552f4e2
commit 23c922db3d
12 changed files with 1064 additions and 216 deletions

View file

@ -1,17 +1,24 @@
-- aweswt.lua
-- Application switcher using dmenu
--
local io = io
local table = table
local pairs = pairs
local awful = awful
local client = client
local string = string
local USE_NAME = true
module("aweswt")
local M = {}
function get_out (a)
local dmenu = "dmenu -nf '#888888' -nb '#222222' -sf '#ffffff' -sb '#285577' -p 'switch to application:' -fn 'Terminus 8' -i"
local get_out, get_input, _switch
-- switch with window titles
M.switch = function()
_switch(true)
end
-- switch with client instance and class
M.switch_class = function()
_switch(false)
end
get_out = function (a)
local f = io.popen(a)
t = {}
for line in f:lines() do
@ -20,13 +27,12 @@ function get_out (a)
return t
end
function get_input (a)
local dmenu = "dmenu -nf '#888888' -nb '#222222' -sf '#ffffff' -sb '#285577' -p 'switch to application:' -fn 'Terminus 8' -i"
get_input = function (a)
s1 = 'echo "' .. a .. '" | ' .. dmenu
return get_out(s1)
end
function switch ()
_switch = function(use_name)
local clients = client.get()
if table.getn(clients) == 0 then
@ -39,8 +45,7 @@ function switch ()
for key, client in pairs(clients) do
local app
if USE_NAME then
--app = key .. ':' .. string.sub(client['name'], 1, 20)
if use_name then
app = client['name']
else
app = key .. ':' .. client['instance'] .. '.' .. client['class']
@ -64,3 +69,4 @@ function switch ()
end
end
return M

View file

@ -1,3 +1,6 @@
local aweswt = require("aweswt")
local mb = require("modalbind")
local mpd = require("mpd")
-- {{{ Mouse bindings
root.buttons(awful.util.table.join(
@ -7,6 +10,31 @@ awful.button({ }, 5, awful.tag.viewprev)
-- }}}
mpdmap = {
name = "MPD",
m = mpd.ctrl.toggle,
n = mpd.ctrl.next,
N = mpd.ctrl.prev,
s = function() awful.util.spawn("mpd") end,
g = function () awful.util.spawn(cmd.mpd_client) end,
d = mpd.disconnect,
c = mpd.connect
}
mpdpromts = {
name = "MPD PROMPTS",
a = mpd.prompt.artist,
A = mpd.prompt.album,
t = mpd.prompt.title,
r = mpd.prompt.toggle_replace_on_search,
}
progmap = {
name = "PROGRAMS",
f = function () awful.util.spawn(cmd.browser) end,
i = function () awful.util.spawn(cmd.im_client) end,
m = function () awful.util.spawn(cmd.mail_client) end
}
-- {{{ Key bindings
globalkeys = awful.util.table.join(
--{{{ Focus and Tags
@ -25,81 +53,80 @@ globalkeys = awful.util.table.join(
if client.focus then client.focus:raise() end
end),
awful.key({ modkey, "Control" }, "j", function () awful.screen.focus_relative( 1) end),
awful.key({ modkey, "Control" }, "k", function () awful.screen.focus_relative(-1) end),
awful.key({ modkey, "Control" }, "j", function ()
awful.screen.focus_relative( 1)
end),
awful.key({ modkey, "Control" }, "k", function ()
awful.screen.focus_relative(-1)
end),
awful.key({ }, "Menu", aweswt.switch),
--}}}
--{{{ Layout manipulation
awful.key({ modkey, "Shift" }, "j", function () awful.client.swap.byidx( 1) end),
awful.key({ modkey, "Shift" }, "k", function () awful.client.swap.byidx( -1) end),
awful.key({ modkey, "Shift" }, "j", function ()
awful.client.swap.byidx( 1)
end),
awful.key({ modkey, "Shift" }, "k", function ()
awful.client.swap.byidx( -1)
end),
awful.key({ modkey, }, "u", awful.client.urgent.jumpto),
awful.key({ modkey, }, "Tab",
function ()
awful.key({ modkey, }, "Tab", function ()
awful.client.focus.history.previous()
if client.focus then
client.focus:raise()
end
end),
awful.key({ "Mod1", }, "Tab",
function ()
awful.key({ "Mod1", }, "Tab", function ()
awful.client.focus.history.previous()
if client.focus then
client.focus:raise()
end
end),
awful.key({ modkey, }, "l", function () awful.tag.incmwfact( 0.05) end),
awful.key({ modkey, }, "h", function () awful.tag.incmwfact(-0.05) end),
awful.key({ modkey, "Shift" }, "h", function () awful.tag.incnmaster( 1) end),
awful.key({ modkey, "Shift" }, "l", function () awful.tag.incnmaster(-1) end),
awful.key({ modkey, "Control" }, "h", function () awful.tag.incncol( 1) end),
awful.key({ modkey, "Control" }, "l", function () awful.tag.incncol(-1) end),
awful.key({ modkey, }, "space", function () awful.layout.inc(layouts, 1) end),
awful.key({ modkey, "Shift" }, "space", function () awful.layout.inc(layouts, 0) end),
--}}}
--
--{{{ Spawns
awful.key({ modkey, }, "Return", function () awful.util.spawn(terminal) end),
awful.key({ modkey, }, "f", function () awful.util.spawn("webbrowser") end),
awful.key({ modkey, }, "t", function () awful.util.spawn("mail-client") end),
awful.key({ modkey, }, "p", function () awful.util.spawn("im-client") end),
awful.key({ modkey, }, "g", function () awful.util.spawn("gmpc") end),
awful.key({ modkey, }, "w", function () awful.util.spawn("awsetbg -a -r /home/crater2150/.config/awesome/walls/ &") end),
awful.key({ modkey, "Control" }, "r", awesome.restart),
awful.key({ modkey, "Shift" }, "q", awesome.quit),
awful.key({ }, "Menu", aweswt.switch),
awful.key({ modkey }, "BackSpace", rodentbane.start),
--}}}
awful.key({ modkey, }, "Return", function () awful.util.spawn(cmd.terminal) end),
--{{{ tabletpc keys
--{{{ Modal mappings
awful.key({ hyper }, "6", function () awful.util.spawn("/usr/local/bin/rotate") end),
awful.key({ modkey }, "x", function () teardrop("cellwriter","top","center", 0.99, 0.4)end ),
awful.key({ modkey, "Control" }, "Delete", function () awful.util.spawn("xlock") end),
awful.key({ hyper }, "1", function () awful.util.spawn("/usr/local/bin/tabletstick 1") end),
awful.key({ hyper }, "2", function () awful.util.spawn("/usr/local/bin/tabletstick 2") end),
awful.key({ hyper }, "3", function () awful.util.spawn("/usr/local/bin/tabletstick 3") end),
awful.key({ hyper }, "4", function () awful.util.spawn("/usr/local/bin/tabletstick 4") end),
awful.key({ hyper }, "5", function () awful.util.spawn("/usr/local/bin/tabletstick 4") end),
--}}}
--{{{ thinkpad
awful.key({ }, "XF86Sleep", function () awful.util.spawn("/usr/local/bin/s2ram")end ),
awful.key({ }, "XF86Away", function () awful.util.spawn("xlock")end ),
awful.key({ }, "XF86TouchpadToggle", function () awful.util.spawn("touchpad")end ),
awful.key({ modkey }, "m", function () mb.grab(mpdmap, true) end),
awful.key({ modkey, "Shift" }, "m", function () mb.grab(mpdpromts) end),
awful.key({ modkey }, "c", function () mb.grab(progmap) end),
--}}}
--{{{ Audio control
awful.key({ }, "Print", function () teardrop("urxvtc -e alsamixer","top","center", 0.99, 0.4)end ),
awful.key({ }, "XF86AudioLowerVolume", function () awful.util.spawn("amixer set Master 2%-")end ),
awful.key({ }, "XF86AudioRaiseVolume", function () awful.util.spawn("amixer set Master 2%+")end ),
awful.key({ }, "XF86AudioMute", function () awful.util.spawn("amixer set Master toggle") end),
awful.key({ modkey }, "m", function () awful.util.spawn("mpc toggle") end),
awful.key({ modkey }, ">", function () awful.util.spawn("mpc next") end),
awful.key({ modkey }, "<", function () awful.util.spawn("mpc prev") end),
awful.key({ modkey , "Shift" }, "m", mpd_prompt.grabber),
awful.key({ }, "XF86AudioPlay", function () awful.util.spawn("mpc toggle") end),
awful.key({ }, "XF86AudioNext", function () awful.util.spawn("mpc next") end),
awful.key({ }, "XF86AudioPrev", function () awful.util.spawn("mpc prev") end),
awful.key({ modkey }, "`", function () teardrop("urxvtc -e ncmpcpp","bottom","center", 0.99, 0.4)end ),
awful.key({ }, "XF86AudioPlay", mpd.ctrl.toggle),
awful.key({ }, "XF86AudioNext", mpd.ctrl.next),
awful.key({ }, "XF86AudioPrev", mpd.ctrl.prev),
--}}}
-- {{{ teardrops
awful.key({ }, "F12", function () teardrop(cmd.terminal,"center","center", 0.99, 0.7)end ),
awful.key({ modkey }, "`", function () teardrop("urxvtc -e ncmpcpp","bottom","center", 0.99, 0.4)end ),
awful.key({ }, "Print", function () teardrop("urxvtc -e alsamixer","top","center", 0.99, 0.4)end ),
-- }}}
--{{{ Prompt
awful.key({ modkey }, "r", function ()
@ -114,21 +141,18 @@ globalkeys = awful.util.table.join(
obvious.popup_run_prompt.set_run_function(awful.util.eval)
obvious.popup_run_prompt.run_prompt()
end),
awful.key({ }, "F12", function () teardrop(terminal,"center","center", 0.99, 0.7)end ),
--}}}
--{{{ Default
awful.key({ modkey, }, "l", function () awful.tag.incmwfact( 0.05) end),
awful.key({ modkey, }, "h", function () awful.tag.incmwfact(-0.05) end),
awful.key({ modkey, "Shift" }, "h", function () awful.tag.incnmaster( 1) end),
awful.key({ modkey, "Shift" }, "l", function () awful.tag.incnmaster(-1) end),
awful.key({ modkey, "Control" }, "h", function () awful.tag.incncol( 1) end),
awful.key({ modkey, "Control" }, "l", function () awful.tag.incncol(-1) end),
awful.key({ modkey, }, "space", function () awful.layout.inc(layouts, 1) end),
awful.key({ modkey, "Shift" }, "space", function () awful.layout.inc(layouts, 0) end)
--{{{ misc. XF86 Keys
awful.key({ }, "XF86Sleep", function () awful.util.spawn("/usr/local/bin/s2ram")end ),
awful.key({ }, "XF86Away", function () awful.util.spawn("xlock")end ),
awful.key({ }, "XF86TouchpadToggle", function () awful.util.spawn("touchpad")end ),
--}}}
awful.key({ modkey }, "BackSpace", rodentbane.start)
)
function client_opacity_set(c, default, max, step)
@ -159,7 +183,7 @@ clientkeys = awful.util.table.join(
awful.key({ }, "XF86Calculater", awful.client.movetoscreen )
)
-- Compute the maximum number of digit we need, limited to 9
-- Compute the maximum number of digit we need, limited to 22
keynumber = 0
for s = 1, screen.count() do
keynumber = math.min(22, math.max(#tags[s], keynumber));
@ -214,3 +238,5 @@ clientbuttons = awful.util.table.join(
-- Set keys
root.keys(globalkeys)
-- }}}
-- vim: set fenc=utf-8 tw=80 foldmethod=marker :

View file

@ -1,5 +1,3 @@
terminal = "urxvtc -e tmux"
editor_cmd = "urxvtc -e vim"
modkey = "Mod4"
hyper = "Mod3"
rule_screen=1

601
luampd.lua Normal file
View file

@ -0,0 +1,601 @@
-------------------------------------------------------------------
-- Copyright (c) 2006 Stephen M. Jothen
-- All rights reserved.
--
-- Redistribution and use in source and binary forms, with or without
-- modification, are permitted provided that the following conditions
-- are met:
-- 1. Redistributions of source code must retain the above copyright
-- notice, this list of conditions and the following disclaimer.
-- 2. Redistributions in binary form must reproduce the above copyright
-- notice, this list of conditions and the following disclaimer in the
-- documentation and/or other materials provided with the distribution.
-- 3. The name of the author may not be used to endorse or promote products
-- derived from this software without specific prior written permission.
--
-- THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
-- IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-- OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-- IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
-- INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
-- NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-- DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-- THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-- THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-------------------------------------------------------------------
-- LuaMPD - Lua interface to the MusicPD protocol
--
-- Author: Steve Jothen <sjothen at gmail dot com>
-------------------------------------------------------------------
------------------------------------------------
-- Classes and requires
------------------------------------------------
local socket = require("socket")
local luampd = {}
------------------------------------------------
-- Private functions and tables
------------------------------------------------
-- errors taken from ack.h in the mpd sources
local err_table = {
["1"] = "ACK_ERROR_NOT_LIST",
["2"] = "ACK_ERROR_ARG",
["3"] = "ACK_ERROR_PASSWORD",
["4"] = "ACK_ERROR_PERMISSION",
["5"] = "ACK_ERROR_UNKNOWN",
["50"] = "ACK_ERROR_NO_EXIST",
["51"] = "ACK_ERROR_PLAYLIST_MAX",
["52"] = "ACK_ERROR_SYSTEM",
["53"] = "ACK_ERROR_PLAYLIST_LOAD",
["54"] = "ACK_ERROR_UPDATE_ALREADY",
["55"] = "ACK_ERROR_PLAYER_SYNC",
["56"] = "ACK_ERROR_EXIST",
}
-- turns a table of strings into groups seperated by a
-- delimiting string, and then turns each group of lines
-- into key, value pair tables
local function multi_hash(delimiter, lines)
local size = table.maxn(lines)
local patches = {}
local patch = {}
while size >= 1 do
if string.find(lines[size], delimiter) then
-- add to the patches repository
local k, v = socket.skip(2, string.find(lines[size], "(.+):%s(.+)"))
if k and v then
-- we have our key value pair!
patch[string.lower(k)] = v
-- we want the key to be lowercase
end
table.insert(patches, patch)
patch = {}
else
-- were still modifying the current patch
local k, v = socket.skip(2, string.find(lines[size], "(.+):%s(.+)"))
if k and v then
patch[string.lower(k)] = v
end
end
size = size - 1
end
return patches
end
-- will turn a table of strings that match
-- key: value
-- into a table such as { key = value, key2 = value2 }
local function hash(lines)
local hash = {}
for key, value in pairs(lines) do
local k, v = socket.skip(2, string.find(value, "(.+):%s(.+)"))
if k and v then
-- lowercase the key for easier access (tabl.artist rather than tabl.Artist)
hash[string.lower(k)] = v
end
end
return hash
end
local function handle_error(line)
-- line is the actual error line received from mpd
local err_num, com_num = socket.skip(2, string.find(line, "ACK %[(%d+)@(%d+)%]"))
if err_table[err_num] then
error(err_table[err_num])
else
-- unknown error
error(err_table["5"])
end
end
local function get_response(obj, command)
-- collect the lines into this table
local response_lines = {}
if obj.socket then
obj.socket:send(command .. '\n')
-- send the command with newline and collect response
-- a response is everything up until an ACK or OK
local line = obj.socket:receive("*l")
while (line ~= "OK") do
if line == nil then
-- bug?? on ubuntu mpd will close socket randomly
-- with large playlists while listing them
-- try playlistinfo (with playlist size > 13000)
error("SOCKET_ERROR")
elseif string.sub(line, 1, 3) == "ACK" then
break
-- let us handle this erro
end
table.insert(response_lines, line)
line = obj.socket:receive("*l")
end
-- if we stopped on an ACK then we better return information about it..
-- last line in the table will be the ack message
if string.sub(line, 1, 3) == "ACK" then
handle_error(line)
--elseif line == "OK" then
-- return true
else
return response_lines
end
else
-- not connected??
error("SOCKET_ERROR")
end
end
------------------------------------------------
-- Public instance methods
------------------------------------------------
function luampd:new(info)
-- local instance of object
local instance = {
hostname = info.hostname or "localhost",
password = info.password or nil,
port = info.port or 6600,
debug = info.debug or false,
}
instance.socket = socket.connect(instance.hostname, instance.port)
if instance.socket then
-- try and get ok from the server
local line = instance.socket:receive("*l")
if line:find("OK MPD (.+)") then
-- connected, send password
if instance.password then
instance.socket:send(string.format("password %s\n", self.password))
-- correct password?
local ok_pass = instance.socket:receive("*l")
if ok_pass ~= "OK" then
error(string.format("Wrong password to %s:d", instance.hostname, instance.port))
end
end
else
-- not mpd or wrong hostname
error(string.format("Cant get response from %s:%d", instance.hostname, instance.port))
end
else
-- socket.connect returns nil, somethings wrong
error(string.format("Socket cant connect to %s:%d", instance.hostname, instance.port))
end
return setmetatable(instance, { __index = luampd })
end
------------------------------------------------
-- Admin functions
------------------------------------------------
-- Some of these functions are in the documentation but dont work?
-- disableoutput, enableoutput
function luampd:disableoutput(outputid)
get_response(self, string.format("disableoutput %d", outputid))
end
function luampd:enableoutput(outputid)
get_response(self, string.format("enableoutput %d", outputid))
end
function luampd:kill()
get_response(self, "kill")
self.socket = nil
end
function luampd:outputs()
local response = get_response(self, "outputs")
return hash(response)
end
function luampd:update()
get_response(self, "update")
end
------------------------------------------------
-- Database functions
------------------------------------------------
function luampd:find(stype, swhat)
local send_string = string.format("find %s \"%s\"", stype, swhat)
local data = get_response(self, send_string)
return multi_hash("^file:", data)
end
-- how should we handle these functions?
-- list/listall/lsinfo
function luampd:list(meta, meta2, search)
end
function luampd:listall(path)
end
function luampd:listallinfo(path)
local send_string
if path then
send_string = string.format("listallinfo \"%s\"", path)
else
send_string = "listallinfo"
end
local response = get_response(self, send_string)
local songs = multi_hash("file:(.+)", response)
return songs
end
function luampd:lsinfo(path)
end
function luampd:search(stype, swhat)
local send_string = string.format("search %s \"%s\"", stype, swhat)
local data = get_response(self, send_string)
return multi_hash("^file:", data)
end
------------------------------------------------
-- Playlist functions
------------------------------------------------
function luampd:add(file)
local add = string.format("add \"%s\"", file)
get_response(self, add)
end
function luampd:clear()
get_response(self, "clear")
end
function luampd:currentsong()
local song = get_response(self, "currentsong")
local hash = hash(song)
return hash
end
function luampd:delete(song)
get_response(self, string.format("delete %d", song))
end
function luampd:deleteid(songid)
get_response(self, string.format("deleteid %s", songid))
end
function luampd:load_playlist(path)
get_response(self, string.format("load %s", path))
end
function luampd:move(from, to)
get_response(self, string.format("move %d %d", from, to))
end
function luampd:moveid(fromid, toid)
get_response(self, string.format("moveid %d %d", fromid, toid))
end
function luampd:playlistinfo(song)
local send_string
if song then
send_string = string.format("playlistinfo %d", song)
local response = get_response(self, send_string)
return hash(response)
else
send_string = "playlistinfo"
local response = get_response(self, send_string)
return multi_hash("^file:", response)
end
end
function luampd:playlistid(songid)
local send_string
if songid then
send_string = string.format("playlistid %d", songid)
local response = get_response(self, send_string)
return hash(response)
else
send_string = "playlistid"
local response = get_response(self, send_string)
return multi_hash("^file:", response)
end
end
function luampd:plchanges(version)
local send_string = string.format("plchanges %d", version)
local response = get_response(self, send_string)
return multi_hash(response)
end
function luampd:plchangesposid(version)
end
function luampd:rm(name)
get_response(self,
string.format("rm \"%s\"", name))
end
function luampd:save(name)
get_response(self,
string.format("save \"%s\"", name))
end
function luampd:shuffle()
get_response(self, "shuffle")
end
function luampd:swap(song1, song2)
get_response(self,
string.format("swap %d %d", song1, song2))
end
function luampd:swapid(songid1, songid2)
get_response(self,
string.format("swapid %d %d", songid1, songid2))
end
------------------------------------------------
-- Playback functions
------------------------------------------------
-- Some of the common tables:
--
-- Status:
-- Fields: volume, repeat, random, playlist, playlistlength, xfade,
-- state, song, songid, time, bitrate, audio
--
-- CurrentSong:
-- Fields: file, artist, album, track, title, time, pos, id
-- sets the crossfading to seconds and returns the xfade status
--
function luampd:crossfade(seconds)
get_response(self,
string.format("crossfade %d", seconds))
return self:status()
end
-- go to next song, returns song table
--
function luampd:next_()
get_response(self, "next")
return self:currentsong()
end
-- pause the current song, returns true/false
-- (play, pause, stop, etc)
--
function luampd:pause()
get_response(self, "pause")
if self:status()["state"] == "pause" then
return true
else
return false
end
end
-- starts playing, returns the current song as a table
--
function luampd:play()
get_response(self, "play")
return self:currentsong()
end
-- start playing a song by its song id
--
function luampd:playid(songid)
get_response(self,
string.format("playid %d", songid))
return self:currentsong()
end
-- go to the previous song and return the current song
--
function luampd:previous()
get_response(self, "previous")
return self:currentsong()
end
-- sets random on or off (state should be either
-- 1 (for on) or 0 (for off))
--
function luampd:random(state)
get_response(self,
string.format("random %d", state))
if self:state()["random"] == tostring(state) then
return true
else
return false
end
end
-- sets repeat (see above about state)
--
function luampd:repeat_(state)
get_response(self,
string.format("repeat %d", state))
if self:state()["repeat"] == tostring(state) then
return true
else
return false
end
end
-- seeks to the specified time (in seconds) in the song
-- returns status
function luampd:seek(song, time)
get_response(self,
string.format("seek %d %d", song, time))
return self:status()
end
-- same as above, except uses songid instead of song
-- returns status
function luampd:seekid(songid, time)
get_response(self,
string.format("seekid %d %d", songid, time))
return self:status()
end
-- set the volume (0-100), anything lower or higher should be handled
-- by the server (-10 will become 0, 110 will become 100)
-- returns status object
--
function luampd:setvol(vol)
get_response(self,
string.format("setvol %d", vol))
if self:status()["volume"] == tostring(vol) then
return true
else
return false
end
end
-- stops playing and returns the current status object
function luampd:stop()
get_response(self, "stop")
if self:status()["state"] == "stop" then
return true
else
return false
end
end
------------------------------------------------
-- Miscellaneous functions
------------------------------------------------
function luampd:clearerror()
get_response(self, "clearerror")
end
--
function luampd:close()
get_response(self, "close")
self.socket = nil
end
function luampd:commands()
end
function luampd:notcommands()
end
-- wrong password handled in get_response
function luampd:password(pass)
get_response(self,
string.format("password %s", pass))
end
function luampd:ping()
get_response(self, "ping")
end
function luampd:stats()
local stats = get_response(self, "stats")
return hash(stats)
end
function luampd:status()
local status = get_response(self, "status")
return hash(status)
end
------------------------------------------------
-- More lua-esque functions, iterators
------------------------------------------------
-- 2011-03-15 crater2150: let iterators return size, which is already calculated
-- anyway
function luampd:database()
local dbase = self:listallinfo(nil)
local count = 0
local size = table.maxn(dbase)
return function()
count = count + 1
if count <= size then
return dbase[count]
end
end, size
end
function luampd:playlist()
local plist = self:playlistinfo(nil)
local count = 0
local size = table.maxn(plist)
return function()
count = count + 1
if count <= size then
return plist[count]
end
end, size
end
function luampd:ifind(stype, swhat)
local found = self:find(stype, swhat)
local count = 0
local size = table.maxn(found)
return function()
count = count + 1
if count <= size then
return found[count]
end
end, size
end
function luampd:isearch(stype, swhat)
local found = self:search(stype, swhat)
local count = 0
local size = table.maxn(found)
return function()
count = count + 1
if count <= size then
return found[count]
end
end, size
end
function luampd:iadd(file_iterator)
for song in file_iterator do
self:add(song.file)
end
end
return luampd

148
modalbind.lua Normal file
View file

@ -0,0 +1,148 @@
local M = {}
local inited = false
local modewidget = {}
local modewibox = { screen = -1 }
--local functions
local ensure_init, set_default, update_settings, show_box, hide_box
M.grab = function(keymap, stay_in_mode)
if keymap.name then show_box(mouse.screen, keymap) end
keygrabber.run(function(mod, key, event)
if key == "Escape" then
keygrabber.stop()
hide_box();
return true
end
if event == "release" then return true end
if keymap[key] then
keygrabber.stop()
keymap[key]()
if stay_in_mode then
M.grab(keymap, true)
else
hide_box()
return true
end
end
return true
end)
end
-- Partially adapted from Obvious Widget Library module "popup_run_prompt" --
-- Original Author: Andrei "Garoth" Thorp --
-- Copyright 2009 Andrei "Garoth" Thorp --
local defaults = {}
-- Default is 1 for people without compositing
defaults.opacity = 1.0
defaults.height = 22
defaults.border_width = 1
defaults.x_offset = 18
defaults.show_options = true
-- Clone the defaults for the used settings
local settings = {}
for key, value in pairs(defaults) do
settings[key] = value
end
M.set_opacity = function (amount)
settings.opacity = amount or defaults.opacity
update_settings()
end
M.set_height = function (amount)
settings.height = amount or defaults.height
update_settings()
end
M.set_border_width = function (amount)
settings.border_width = amount or defaults.border_width
update_settings()
end
M.set_x_offset = function (amount)
settings.x_offset = amount or defaults.x_offset
update_settings()
end
M.set_show_options = function (bool)
settings.show_options = bool
end
ensure_init = function ()
if inited then
return
end
inited = true
for s = 1, screen.count() do
modewidget[s] = widget({
type = "textbox",
name = "modewidget" .. s,
align = "center"
})
modewibox[s] = wibox({
fg = beautiful.fg_normal,
bg = beautiful.bg_normal,
border_width = settings.border_width,
border_color = beautiful.bg_focus,
})
set_default(s)
modewibox[s].visible = false
modewibox[s].screen = s
modewibox[s].ontop = true
-- Widgets for prompt wibox
modewibox[s].widgets = {
modewidget[s],
layout = awful.widget.layout.vertical.center
}
end
end
set_default = function (s)
modewibox[s]:geometry({
width = modewidget[s].extents(modewidget[s]).width,
height = settings.height,
x = settings.x_offset < 0 and
screen[s].geometry.x - width + settings.x_offset or
settings.x_offset,
y = screen[s].geometry.y + screen[s].geometry.height - settings.height
})
end
update_settings = function ()
for s, value in ipairs(modewibox) do
value.border_width = settings.border_width
set_default(s)
value.opacity = settings.opacity
end
end
show_box = function (s, map)
ensure_init()
modewibox.screen = s
local label = " -- " .. map.name .. " -- "
if settings.show_options then
for key in pairs(map) do
if key ~= "name" then label = label .. " " .. key end
end
end
modewidget[s].text = label
set_default(s)
modewibox[s].visible = true
end
hide_box = function ()
local s = modewibox.screen
if s ~= -1 then modewibox[s].visible = false end
end
return M

150
mpd.lua Normal file
View file

@ -0,0 +1,150 @@
local luampd = require("luampd")
local M = {}
local type = ""
-- local functions
local show, mpc_play_search, notify
local conn = nil
local defaults = {}
local settings = {}
defaults.host = "127.0.0.1"
defaults.port = 6600
defaults.replace_on_search = true
for key, value in pairs(defaults) do
settings[key] = value
end
-- {{{ basic functions
M.connect = function ()
print("Connecting to mpd")
conn = luampd:new({
hostname = settings.hostname,
port = settings.port,
debug = false
})
end
M.disconnect = function()
if conn ~= nil then conn:close() end
conn = nil
end
M.ensure_connection = function()
if conn == nil then M.connect() end
end
-- }}}
-- {{{ mpd.ctrl submodule
M.ctrl = {}
M.ctrl.toggle = function ()
M.ensure_connection()
local status = conn:status()
if status["state"] == "pause" or status["state"] == "stop" then
conn:play()
else
conn:pause()
end
end
M.ctrl.play = function ()
M.ensure_connection()
conn:play()
-- TODO widget updating
end
M.ctrl.pause = function ()
M.ensure_connection()
conn:pause()
-- TODO widget updating
end
M.ctrl.next = function ()
M.ensure_connection()
conn:next_()
-- TODO widget updating
end
M.ctrl.prev = function ()
M.ensure_connection()
conn:previous()
-- TODO widget updating
end
-- }}}
-- {{{ mpd.prompt submodule
local clear_before = cfg.mpd_prompt_clear_before == nil and
true or
cfg.mpd_prompt_clear_before
M.prompt = {}
M.prompt.artist = function()
type = "artist"
show()
end
M.prompt.album = function()
type = "album"
show()
end
M.prompt.title = function()
type = "title"
show()
end
M.prompt.title = title
M.prompt.replace_on_search = function(bool)
clear_before = bool
end
M.prompt.toggle_replace_on_search = function()
clear_before = not clear_before
notify("MPD prompts now " ..(
clear_before and "replace" or "add to"
).. " the playlist")
end
function show()
obvious.popup_run_prompt.set_prompt_string("Play ".. type .. ":")
obvious.popup_run_prompt.set_cache("/mpd_ ".. type);
obvious.popup_run_prompt.set_run_function(mpc_play_search)
obvious.popup_run_prompt.run_prompt()
end
function mpc_play_search(s)
M.ensure_connection()
if clear_before then conn:clear() end
local result, num = conn:isearch(type, s)
notify("Found " .. (num) .. " matches");
conn:iadd(result)
conn:play()
end
-- }}}
-- {{{ notify wrapper
notify = function(stext)
if not (naughty == nil) then
naughty.notify({
text= stext
})
end
end
--}}}
return M
-- vim: set fenc=utf-8 tw=80 foldmethod=marker :

View file

@ -1,78 +0,0 @@
local awful = awful
local obvious = obvious
local naughty = naughty
local keygrabber = keygrabber
local io = io
local pairs = pairs
local M = {}
local type = ""
local clear_before = true
local keymap = {}
local show,
mpc_play_search
M.grabber = function()
keygrabber.run(function(mod, key, event)
if event == "release" then return true end
keygrabber.stop()
if keymap[key] then keymap[key]() end
return true
end)
end
M.artist = function()
type = "artist"
show()
end
M.album = function()
type = "album"
show()
end
M.title = function()
type = "title"
show()
end
M.title = title
M.replace_on_search = function(bool)
clear_before = bool
end
M.toggle_replace_on_search = function()
clear_before = not clear_before
if not (naughty == nil) then
naughty.notify({
text="MPD prompts now " ..(
clear_before and "replace" or "add to"
).. " the playlist"
})
end
end
function show()
obvious.popup_run_prompt.set_prompt_string("Play ".. type .. ":")
obvious.popup_run_prompt.set_run_function(mpc_play_search)
obvious.popup_run_prompt.run_prompt()
end
function mpc_play_search(s)
if clear_before then awful.util.spawn("mpc clear") end
awful.util.spawn_with_shell("mpc search ".. type .." '" .. s .. "' | mpc add")
awful.util.spawn("mpc play");
end
keymap = {
a = M.artist,
A = M.album,
t = M.title,
r = M.toggle_replace_on_search
}
return M

3
rc.lua
View file

@ -9,11 +9,8 @@ require("teardrop")
require("obvious.popup_run_prompt")
require("vicious")
require("rodentbane.rodentbane")
require("aweswt")
mpd_prompt = require("mpd_prompt")
MY_PATH = os.getenv("HOME") .. "/.config/awesome/"
WALLPATH = MY_PATH .. "walls/"
dofile (MY_PATH .. "localconf.lua")

View file

@ -15,15 +15,15 @@ tags.setup = {
{ name = "F1:☭", layout = layouts[1] },
{ name = "F2:♚", layout = layouts[1] },
{ name = "F3:♛", layout = layouts[1] },
{ name = "F4:♜", layout = layouts[1] },
{ name = "F5:♝", layout = layouts[1] },
{ name = "F6:♞", layout = layouts[1] },
{ name = "F7:♟", layout = layouts[1] },
{ name = "F8:⚖", layout = layouts[1] },
{ name = "F9:⚛", layout = layouts[1] },
{ name = "F10:⚡", layout = layouts[1] },
{ name = "F11:⚰", layout = layouts[1] },
{ name = "F12:⚙", layout = layouts[1] }
{ name = "F4:♜", layout = layouts[1] }--,
-- { name = "F5:♝", layout = layouts[1] },
-- { name = "F6:♞", layout = layouts[1] },
-- { name = "F7:♟", layout = layouts[1] },
-- { name = "F8:⚖", layout = layouts[1] },
-- { name = "F9:⚛", layout = layouts[1] },
-- { name = "F10:⚡", layout = layouts[1] },
-- { name = "F11:⚰", layout = layouts[1] },
-- { name = "F12:⚙", layout = layouts[1] }
}
for s = 1, screen.count() do

View file

@ -170,8 +170,8 @@ for s = 1, screen.count() do
-- Create the wibox
leftwibox[s] = awful.wibox({ position = "left", screen = s })
rightwibox[s] = awful.wibox({ position = "right", screen = s })
leftwibox[s] = awful.wibox({ position = "left", screen = s, width = 18 })
rightwibox[s] = awful.wibox({ position = "right", screen = s , width = 18})
-- Add widgets to the wibox - order matters
leftwibox[s].widgets = {
mytaglist[s],

View file

@ -12,7 +12,7 @@ theme.wallpaper_cmd = { "awsetbg -l" }
-- }}}
-- {{{ Styles
theme.font = "sans 8"
theme.font = "dejavu 7"
-- {{{ Colors
theme.fg_normal = "#DCDCDC"