From 69a3eb99637f90f77ed4fd661b0fc07cf4b0e097 Mon Sep 17 00:00:00 2001 From: Hannah Ward Date: Fri, 14 Jul 2017 15:19:43 +0100 Subject: [PATCH 1/8] mpd: Allow mpd connection via UNIX socket --- widget/mpd.lua | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/widget/mpd.lua b/widget/mpd.lua index d0b37d7d..72ed6eab 100644 --- a/widget/mpd.lua +++ b/widget/mpd.lua @@ -36,10 +36,21 @@ local function factory(args) local followtag = args.followtag or false local settings = args.settings or function() end - local mpdh = string.format("telnet://%s:%s", host, port) + local mpdh = "" + local cmd = "" local echo = string.format("printf \"%sstatus\\ncurrentsong\\nclose\\n\"", password) - local cmd = string.format("%s | curl --connect-timeout 1 -fsm 3 %s", echo, mpdh) - + + -- If host begins with "/", we can assume that it is a socket + if host.sub(host, 1, 1) == "/" then + -- It's a socket, use socat to talk directly to it + mpdh = string.format("UNIX-CONNECT:%s", host) + cmd = string.format("%s | socat - %s", echo, mpdh) + else + -- It's not a socket, assume IP or other host + mpdh = string.format("telnet://%s:%s", host, port) + cmd = string.format("%s | curl --connect-timeout 1 -fsm 3 %s", echo, mpdh) + end + mpd_notification_preset = { title = "Now playing", timeout = 6 } helpers.set_map("current mpd track", nil) From 9d6ad745798c240cf123d83f7026f6ac4e427109 Mon Sep 17 00:00:00 2001 From: Hannah Ward Date: Fri, 14 Jul 2017 15:25:51 +0100 Subject: [PATCH 2/8] mpd: Import the string function directly Instead of using a string instance's sub() function we can instead use the global one to clean things up a bit --- widget/mpd.lua | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/widget/mpd.lua b/widget/mpd.lua index 72ed6eab..6a0281a5 100644 --- a/widget/mpd.lua +++ b/widget/mpd.lua @@ -16,7 +16,8 @@ local wibox = require("wibox") local os = { getenv = os.getenv } local string = { format = string.format, gmatch = string.gmatch, - match = string.match } + match = string.match, + sub = string.sub } -- MPD infos -- lain.widget.mpd @@ -41,7 +42,7 @@ local function factory(args) local echo = string.format("printf \"%sstatus\\ncurrentsong\\nclose\\n\"", password) -- If host begins with "/", we can assume that it is a socket - if host.sub(host, 1, 1) == "/" then + if string.sub(host, 1, 1) == "/" then -- It's a socket, use socat to talk directly to it mpdh = string.format("UNIX-CONNECT:%s", host) cmd = string.format("%s | socat - %s", echo, mpdh) From c20eae85658be33c13e799a596afcf69cf81861c Mon Sep 17 00:00:00 2001 From: Hannah Ward Date: Mon, 17 Jul 2017 10:39:17 +0100 Subject: [PATCH 3/8] helpers: Add UNIX socket connection method to helpers --- helpers.lua | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/helpers.lua b/helpers.lua index 4e5ce1fa..127e8b98 100644 --- a/helpers.lua +++ b/helpers.lua @@ -15,6 +15,8 @@ local io = { lines = io.lines, local rawget = rawget local table = { sort = table.sort } +local gio = require("lgi").Gio + -- Lain helper functions for internal use -- lain.helpers local helpers = {} @@ -134,6 +136,42 @@ end -- }}} + +-- {{{ Network functions + +-- Send some data to a UNIX socket +function helpers.send_to_unix_socket(unix_path, data, buffer_length) + + -- First, create an output buffer to recieve from + local recv_buffer = "" + -- We'll need to allocate `buffer_length` bytes to it + for i=1,buffer_length do + recv_buffer = recv_bufer .. " " + end + + -- Create a socket to send some data from + local sock = gio.Socket.new(gio.SocketFamily.UNIX, + gio.SocketType.STREAM, + gio.SocketProtocol.DEFAULT) + + -- Create a socket address to connect to + local addr = gio.UnixSocketAddress.new(path) + + -- Connect across + sock:connect(addr) + + -- Send our message + sock:send(data) + + -- Pull back anything it sends back + sock:receive(recv_buffer) + + return recv_buffer +end + + +-- }}} + -- {{{ Misc -- check if an element exist on a table From d1332d955d6d981e30c53ac9196b5024fe346d5a Mon Sep 17 00:00:00 2001 From: Hannah Ward Date: Mon, 17 Jul 2017 11:16:54 +0100 Subject: [PATCH 4/8] helpers: Add Basic IPv4 socket send Both network methods appear to work in isolation, just gotta see if they work when integrated properly. Saves anyone else diving into LGI I guess --- helpers.lua | 50 ++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 42 insertions(+), 8 deletions(-) diff --git a/helpers.lua b/helpers.lua index 127e8b98..07c1952c 100644 --- a/helpers.lua +++ b/helpers.lua @@ -139,36 +139,70 @@ end -- {{{ Network functions --- Send some data to a UNIX socket -function helpers.send_to_unix_socket(unix_path, data, buffer_length) - +-- Create a recieving buffer +-- NOTE: Not sure whether to export this with helpers or not +-- Probably just gonna leave it local for now +function generate_buffer(buffer_length) -- First, create an output buffer to recieve from local recv_buffer = "" -- We'll need to allocate `buffer_length` bytes to it for i=1,buffer_length do - recv_buffer = recv_bufer .. " " + local recv_buffer = recv_buffer .. " " end + return recv_buffer +end + +-- Send some data to a UNIX socket + +function helpers.send_to_unix_socket(unix_path, data, buffer_length) + -- Create a buffer to recieve into + local recv_buffer = generate_buffer(buffer_length) + -- Create a socket to send some data from local sock = gio.Socket.new(gio.SocketFamily.UNIX, gio.SocketType.STREAM, gio.SocketProtocol.DEFAULT) -- Create a socket address to connect to - local addr = gio.UnixSocketAddress.new(path) - + local addr = gio.UnixSocketAddress.new(unix_path) -- Connect across sock:connect(addr) - -- Send our message sock:send(data) - -- Pull back anything it sends back sock:receive(recv_buffer) + + sock:close() return recv_buffer end +-- Send some data to an IPv4 socket +function helpers.send_to_ip_address(ip_address, port, data, buffer_length) + -- Create a buffer to recieve into + local recv_buffer = generate_buffer(buffer_length) + + -- Create a socket to send some data from + local sock = gio.Socket.new(gio.SocketFamily.IPV4, + gio.SocketType.STREAM, + gio.SocketProtocol.DEFAULT) + + -- Create a socket address to connect to + local inet_addr = Gio.InetAddress.new_from_string(ip_address) + local addr = gio.UnixSocketAddress.new(inet_addr, port) + + -- Connect across + sock:connect(addr) + + -- Send our message + sock:send(data) + + -- Pull back anything it sends back + sock:receive(recv_buffer) + + return recv_buffer +end -- }}} From f416604449ab56b996b0ae3f4ad40c6e02152008 Mon Sep 17 00:00:00 2001 From: Hannah Ward Date: Mon, 17 Jul 2017 11:30:01 +0100 Subject: [PATCH 5/8] helpers: Fix variable names in network methods --- helpers.lua | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/helpers.lua b/helpers.lua index 07c1952c..9a0b3120 100644 --- a/helpers.lua +++ b/helpers.lua @@ -144,10 +144,10 @@ end -- Probably just gonna leave it local for now function generate_buffer(buffer_length) -- First, create an output buffer to recieve from - local recv_buffer = "" + local recv_buffer = " " -- We'll need to allocate `buffer_length` bytes to it for i=1,buffer_length do - local recv_buffer = recv_buffer .. " " + recv_buffer = recv_buffer .. " " end return recv_buffer @@ -189,9 +189,8 @@ function helpers.send_to_ip_address(ip_address, port, data, buffer_length) gio.SocketProtocol.DEFAULT) -- Create a socket address to connect to - local inet_addr = Gio.InetAddress.new_from_string(ip_address) - local addr = gio.UnixSocketAddress.new(inet_addr, port) - + local inet_addr = gio.InetAddress.new_from_string(ip_address) + local addr = gio.InetSocketAddress.new(inet_addr, port) -- Connect across sock:connect(addr) From c4903a96bd28312ae75346eb58cb2c0ad759f2bb Mon Sep 17 00:00:00 2001 From: Hannah Ward Date: Mon, 17 Jul 2017 11:51:15 +0100 Subject: [PATCH 6/8] helpers: Make sure we close the socket when we're done --- helpers.lua | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/helpers.lua b/helpers.lua index 9a0b3120..ec55a1ce 100644 --- a/helpers.lua +++ b/helpers.lua @@ -193,13 +193,11 @@ function helpers.send_to_ip_address(ip_address, port, data, buffer_length) local addr = gio.InetSocketAddress.new(inet_addr, port) -- Connect across sock:connect(addr) - -- Send our message sock:send(data) - -- Pull back anything it sends back sock:receive(recv_buffer) - + sock:close() return recv_buffer end From a697b94772cefa8754de579a37caef5de5ac5ac9 Mon Sep 17 00:00:00 2001 From: Hannah Ward Date: Mon, 17 Jul 2017 15:12:06 +0100 Subject: [PATCH 7/8] mpd: Communication between socket and TCP working --- helpers.lua | 76 +++++++++++++++++++++----------------------------- widget/mpd.lua | 17 ++--------- 2 files changed, 35 insertions(+), 58 deletions(-) diff --git a/helpers.lua b/helpers.lua index ec55a1ce..c8342056 100644 --- a/helpers.lua +++ b/helpers.lua @@ -15,7 +15,7 @@ local io = { lines = io.lines, local rawget = rawget local table = { sort = table.sort } -local gio = require("lgi").Gio +local Gio = require("lgi").Gio -- Lain helper functions for internal use -- lain.helpers @@ -153,54 +153,42 @@ function generate_buffer(buffer_length) return recv_buffer end --- Send some data to a UNIX socket +-- Wrapper function to send to any sort of address +function helpers.send_to_address(host, port, data, buffer_length, callback) + -- Have a default buffer length of 1000 + if not buffer_length then + buffer_length = 1000 + end -function helpers.send_to_unix_socket(unix_path, data, buffer_length) - -- Create a buffer to recieve into + -- Generate a buffer to store our result in local recv_buffer = generate_buffer(buffer_length) - -- Create a socket to send some data from - local sock = gio.Socket.new(gio.SocketFamily.UNIX, - gio.SocketType.STREAM, - gio.SocketProtocol.DEFAULT) - - -- Create a socket address to connect to - local addr = gio.UnixSocketAddress.new(unix_path) - -- Connect across - sock:connect(addr) - -- Send our message - sock:send(data) - -- Pull back anything it sends back - sock:receive(recv_buffer) - - sock:close() - - return recv_buffer -end + -- Check if we should be sending to a socket or an IP + local is_socket = (string.sub(host, 1, 1) == "/") --- Send some data to an IPv4 socket -function helpers.send_to_ip_address(ip_address, port, data, buffer_length) - -- Create a buffer to recieve into - local recv_buffer = generate_buffer(buffer_length) - - -- Create a socket to send some data from - local sock = gio.Socket.new(gio.SocketFamily.IPV4, - gio.SocketType.STREAM, - gio.SocketProtocol.DEFAULT) - - -- Create a socket address to connect to - local inet_addr = gio.InetAddress.new_from_string(ip_address) - local addr = gio.InetSocketAddress.new(inet_addr, port) - -- Connect across - sock:connect(addr) - -- Send our message - sock:send(data) - -- Pull back anything it sends back - sock:receive(recv_buffer) - sock:close() - return recv_buffer -end + -- Create a client to listen and send with + local client = Gio.SocketClient() + + local addr + if is_socket then + addr = Gio.UnixSocketAddress.new(host) + else + local inet_addr = gio.InetAddress.new_from_string(host) + addr = Gio.InetSocketAddress.new(inet_addr, port) + end + + local conn = client:connect(addr) + + local input_stream = conn:get_output_stream() + local output_stream = conn:get_input_stream() + + input_stream:write(data) + output_stream:read(recv_buffer) + output_stream:read(recv_buffer) + + callback(recv_buffer) +end -- }}} -- {{{ Misc diff --git a/widget/mpd.lua b/widget/mpd.lua index 6a0281a5..bb5cb5be 100644 --- a/widget/mpd.lua +++ b/widget/mpd.lua @@ -39,25 +39,14 @@ local function factory(args) local mpdh = "" local cmd = "" - local echo = string.format("printf \"%sstatus\\ncurrentsong\\nclose\\n\"", password) + local echo = string.format("%sstatus\ncurrentsong\nclose\n", password) - -- If host begins with "/", we can assume that it is a socket - if string.sub(host, 1, 1) == "/" then - -- It's a socket, use socat to talk directly to it - mpdh = string.format("UNIX-CONNECT:%s", host) - cmd = string.format("%s | socat - %s", echo, mpdh) - else - -- It's not a socket, assume IP or other host - mpdh = string.format("telnet://%s:%s", host, port) - cmd = string.format("%s | curl --connect-timeout 1 -fsm 3 %s", echo, mpdh) - end - mpd_notification_preset = { title = "Now playing", timeout = 6 } helpers.set_map("current mpd track", nil) - function mpd.update() - helpers.async({ shell, "-c", cmd }, function(f) + helpers.send_to_address(host, port, echo, 10000, function(f) + local res = 0 mpd_now = { random_mode = false, single_mode = false, From 61bdee5586c30a2672f13ce9fe033ec40fc20283 Mon Sep 17 00:00:00 2001 From: Hannah Ward Date: Mon, 17 Jul 2017 15:13:17 +0100 Subject: [PATCH 8/8] mpd: Remove unused result variable --- widget/mpd.lua | 1 - 1 file changed, 1 deletion(-) diff --git a/widget/mpd.lua b/widget/mpd.lua index bb5cb5be..f7d885f7 100644 --- a/widget/mpd.lua +++ b/widget/mpd.lua @@ -46,7 +46,6 @@ local function factory(args) helpers.set_map("current mpd track", nil) function mpd.update() helpers.send_to_address(host, port, echo, 10000, function(f) - local res = 0 mpd_now = { random_mode = false, single_mode = false,