From 6a8c41cd1d5e218d0dacffb836fdd7d4ec6333dd Mon Sep 17 00:00:00 2001 From: Aylur Date: Mon, 14 Oct 2024 16:01:36 +0000 Subject: feat: astal-io --- lib/astal/io/application.vala | 161 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 161 insertions(+) create mode 100644 lib/astal/io/application.vala (limited to 'lib/astal/io/application.vala') diff --git a/lib/astal/io/application.vala b/lib/astal/io/application.vala new file mode 100644 index 0000000..00bef57 --- /dev/null +++ b/lib/astal/io/application.vala @@ -0,0 +1,161 @@ +namespace AstalIO { +public errordomain AppError { + NAME_OCCUPIED, + TAKEOVER_FAILED, +} + +public interface Application : Object { + public abstract void quit() throws Error; + public abstract void inspector() throws Error; + public abstract void toggle_window(string window) throws Error; + + public abstract string instance_name { owned get; construct set; } + public abstract void acquire_socket() throws Error; + public abstract void request(string msg, SocketConnection conn) throws Error; +} + +public SocketService acquire_socket(Application app) throws Error { + var name = app.instance_name; + foreach (var instance in get_instances()) { + if (instance == name) { + throw new AppError.NAME_OCCUPIED(@"$name is occupied"); + } + } + + var rundir = Environment.get_user_runtime_dir(); + var path = @"$rundir/$name.sock"; + + if (FileUtils.test(path, FileTest.EXISTS)) { + try { + File.new_for_path(path).delete(null); + } catch (Error err) { + throw new AppError.TAKEOVER_FAILED("could not delete previous socket"); + } + } + + var service = new SocketService(); + service.add_address( + new UnixSocketAddress(path), + SocketType.STREAM, + SocketProtocol.DEFAULT, + null, + null + ); + + service.incoming.connect((conn) => { + read_sock.begin(conn, (_, res) => { + try { + string message = read_sock.end(res); + app.request(message != null ? message.strip() : "", conn); + } catch (Error err) { + critical(err.message); + } + }); + return false; + }); + + return service; +} + +public static List get_instances() { + var list = new List(); + var prefix = "io.Astal."; + + try { + DBusImpl dbus = Bus.get_proxy_sync( + BusType.SESSION, + "org.freedesktop.DBus", + "/org/freedesktop/DBus" + ); + + foreach (var busname in dbus.list_names()) { + if (busname.has_prefix(prefix)) + list.append(busname.replace(prefix, "")); + } + } catch (Error err) { + critical(err.message); + } + + return list; +} + +public static void quit_instance(string instance) { + try { + IApplication proxy = Bus.get_proxy_sync( + BusType.SESSION, + "io.Astal." + instance, + "/io/Astal/Application" + ); + + proxy.quit(); + } catch (Error err) { + critical(err.message); + } +} + +public static void open_inspector(string instance) { + try { + IApplication proxy = Bus.get_proxy_sync( + BusType.SESSION, + "io.Astal." + instance, + "/io/Astal/Application" + ); + + proxy.inspector(); + } catch (Error err) { + critical(err.message); + } +} + +public static void toggle_window_by_name(string instance, string window) { + try { + IApplication proxy = Bus.get_proxy_sync( + BusType.SESSION, + "io.Astal." + instance, + "/io/Astal/Application" + ); + + proxy.toggle_window(window); + } catch (Error err) { + critical(err.message); + } +} + +public static string send_message(string instance_name, string msg) { + var rundir = Environment.get_user_runtime_dir(); + var socket_path = @"$rundir/$instance_name.sock"; + var client = new SocketClient(); + + try { + var conn = client.connect(new UnixSocketAddress(socket_path), null); + conn.output_stream.write(msg.concat("\x04").data); + + var stream = new DataInputStream(conn.input_stream); + return stream.read_upto("\x04", -1, null, null); + } catch (Error err) { + printerr(err.message); + return ""; + } +} + +public async string read_sock(SocketConnection conn) throws IOError { + var stream = new DataInputStream(conn.input_stream); + return yield stream.read_upto_async("\x04", -1, Priority.DEFAULT, null, null); +} + +public async void write_sock(SocketConnection conn, string response) throws IOError { + yield conn.output_stream.write_async(response.concat("\x04").data, Priority.DEFAULT); +} + +[DBus (name="io.Astal.Application")] +private interface IApplication : DBusProxy { + public abstract void quit() throws GLib.Error; + public abstract void inspector() throws GLib.Error; + public abstract void toggle_window(string window) throws GLib.Error; +} + +[DBus (name="org.freedesktop.DBus")] +private interface DBusImpl : DBusProxy { + public abstract string[] list_names() throws Error; +} +} -- cgit v1.2.3 From 2f71cd4c08bb4514efe43533e6a5d03535204c29 Mon Sep 17 00:00:00 2001 From: Aylur Date: Tue, 15 Oct 2024 01:26:32 +0200 Subject: refactor lua and gjs lib --- lib/astal/io/application.vala | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'lib/astal/io/application.vala') diff --git a/lib/astal/io/application.vala b/lib/astal/io/application.vala index 00bef57..60318ed 100644 --- a/lib/astal/io/application.vala +++ b/lib/astal/io/application.vala @@ -14,7 +14,7 @@ public interface Application : Object { public abstract void request(string msg, SocketConnection conn) throws Error; } -public SocketService acquire_socket(Application app) throws Error { +public SocketService acquire_socket(Application app, out string sock) throws Error { var name = app.instance_name; foreach (var instance in get_instances()) { if (instance == name) { @@ -23,7 +23,13 @@ public SocketService acquire_socket(Application app) throws Error { } var rundir = Environment.get_user_runtime_dir(); - var path = @"$rundir/$name.sock"; + var dir = @"$rundir/astal"; + var path = @"$dir/$name.sock"; + sock = path; + + if (!FileUtils.test(dir, FileTest.IS_DIR)) { + File.new_for_path(path).make_directory_with_parents(null); + } if (FileUtils.test(path, FileTest.EXISTS)) { try { @@ -123,7 +129,7 @@ public static void toggle_window_by_name(string instance, string window) { public static string send_message(string instance_name, string msg) { var rundir = Environment.get_user_runtime_dir(); - var socket_path = @"$rundir/$instance_name.sock"; + var socket_path = @"$rundir/astal/$instance_name.sock"; var client = new SocketClient(); try { -- cgit v1.2.3 From dde50e333a237efb4ddaf522398dedf1a69999d1 Mon Sep 17 00:00:00 2001 From: Aylur Date: Tue, 15 Oct 2024 11:47:26 +0000 Subject: docs: update references flake --- lib/astal/io/application.vala | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'lib/astal/io/application.vala') diff --git a/lib/astal/io/application.vala b/lib/astal/io/application.vala index 60318ed..b32de34 100644 --- a/lib/astal/io/application.vala +++ b/lib/astal/io/application.vala @@ -11,7 +11,9 @@ public interface Application : Object { public abstract string instance_name { owned get; construct set; } public abstract void acquire_socket() throws Error; - public abstract void request(string msg, SocketConnection conn) throws Error; + public virtual void request(string msg, SocketConnection conn) throws Error { + write_sock.begin(conn, @"missing response implementation on $instance_name"); + } } public SocketService acquire_socket(Application app, out string sock) throws Error { -- cgit v1.2.3