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 From ecfbf082bfab22e34d8036896f51069ce0c18302 Mon Sep 17 00:00:00 2001 From: Aylur Date: Tue, 15 Oct 2024 20:58:49 +0000 Subject: docs: astal-io doc comments --- lib/astal/io/application.vala | 36 +++++++++++++++++++++++++++++++++++- 1 file changed, 35 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 b32de34..60a7d3e 100644 --- a/lib/astal/io/application.vala +++ b/lib/astal/io/application.vala @@ -4,6 +4,10 @@ public errordomain AppError { TAKEOVER_FAILED, } +/** + * This interface is used as a placeholder for the Astal Application class. + * It is not meant to be used by consumers. + */ public interface Application : Object { public abstract void quit() throws Error; public abstract void inspector() throws Error; @@ -16,6 +20,10 @@ public interface Application : Object { } } +/** + * Starts a [class@GLib.SocketService] and binds `XDG_RUNTIME_DIR/astal/.sock`. + * This socket is then used by the astal cli. Not meant for public usage, but for [func@AstalIO.Application.acquire_socket]. + */ public SocketService acquire_socket(Application app, out string sock) throws Error { var name = app.instance_name; foreach (var instance in get_instances()) { @@ -65,6 +73,10 @@ public SocketService acquire_socket(Application app, out string sock) throws Err return service; } +/** + * Get a list of running Astal.Application instances. + * It is the equivalent of `astal --list`. + */ public static List get_instances() { var list = new List(); var prefix = "io.Astal."; @@ -87,6 +99,10 @@ public static List get_instances() { return list; } +/** + * Quit an an Astal instances. + * It is the equivalent of `astal --quit -i instance`. + */ public static void quit_instance(string instance) { try { IApplication proxy = Bus.get_proxy_sync( @@ -101,6 +117,10 @@ public static void quit_instance(string instance) { } } +/** + * Open the Gtk debug tool of an an Astal instances. + * It is the equivalent of `astal --inspector -i instance`. + */ public static void open_inspector(string instance) { try { IApplication proxy = Bus.get_proxy_sync( @@ -115,6 +135,10 @@ public static void open_inspector(string instance) { } } +/** + * Toggle a Window of an Astal instances. + * It is the equivalent of `astal -i instance --toggle window`. + */ public static void toggle_window_by_name(string instance, string window) { try { IApplication proxy = Bus.get_proxy_sync( @@ -129,7 +153,11 @@ public static void toggle_window_by_name(string instance, string window) { } } -public static string send_message(string instance_name, string msg) { +/** + * Send a message to an Astal instances. + * It is the equivalent of `astal -i instance content of the message`. + */ +public static string send_message(string instance, string msg) { var rundir = Environment.get_user_runtime_dir(); var socket_path = @"$rundir/astal/$instance_name.sock"; var client = new SocketClient(); @@ -146,11 +174,17 @@ public static string send_message(string instance_name, string msg) { } } +/** + * Read the socket of an Astal.Application instance. + */ 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); } +/** + * Write the socket of an Astal.Application instance. + */ public async void write_sock(SocketConnection conn, string response) throws IOError { yield conn.output_stream.write_async(response.concat("\x04").data, Priority.DEFAULT); } -- cgit v1.2.3 From 8368b20eda96674e0f5a502b92d3afb936b71b0b Mon Sep 17 00:00:00 2001 From: Aylur Date: Wed, 16 Oct 2024 10:28:24 +0000 Subject: fix io send_message --- lib/astal/io/application.vala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/astal/io/application.vala') diff --git a/lib/astal/io/application.vala b/lib/astal/io/application.vala index 60a7d3e..a420128 100644 --- a/lib/astal/io/application.vala +++ b/lib/astal/io/application.vala @@ -159,7 +159,7 @@ public static void toggle_window_by_name(string instance, string window) { */ public static string send_message(string instance, string msg) { var rundir = Environment.get_user_runtime_dir(); - var socket_path = @"$rundir/astal/$instance_name.sock"; + var socket_path = @"$rundir/astal/$instance.sock"; var client = new SocketClient(); try { -- cgit v1.2.3 From 306e64998c1bf1fb997c1098ae92d6edfef31cd2 Mon Sep 17 00:00:00 2001 From: Aylur Date: Wed, 23 Oct 2024 20:37:32 +0000 Subject: docs: astal3 and io comments --- lib/astal/io/application.vala | 6 +++--- 1 file changed, 3 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 a420128..c7bd311 100644 --- a/lib/astal/io/application.vala +++ b/lib/astal/io/application.vala @@ -21,8 +21,8 @@ public interface Application : Object { } /** - * Starts a [class@GLib.SocketService] and binds `XDG_RUNTIME_DIR/astal/.sock`. - * This socket is then used by the astal cli. Not meant for public usage, but for [func@AstalIO.Application.acquire_socket]. + * Starts a [class@Gio.SocketService] and binds `XDG_RUNTIME_DIR/astal/.sock`. + * This socket is then used by the astal cli. Not meant for public usage, but for [method@AstalIO.Application.acquire_socket]. */ public SocketService acquire_socket(Application app, out string sock) throws Error { var name = app.instance_name; @@ -186,7 +186,7 @@ public async string read_sock(SocketConnection conn) throws IOError { * Write the socket of an Astal.Application instance. */ public async void write_sock(SocketConnection conn, string response) throws IOError { - yield conn.output_stream.write_async(response.concat("\x04").data, Priority.DEFAULT); + yield conn.output_stream.write_async(@"$response\x04".data, Priority.DEFAULT); } [DBus (name="io.Astal.Application")] -- cgit v1.2.3 From 439571abec531d9b50d22f647335112645e43d86 Mon Sep 17 00:00:00 2001 From: Aylur Date: Sun, 27 Oct 2024 22:12:35 +0000 Subject: cli: better err logs --- lib/astal/io/application.vala | 69 ++++++++++++++++--------------------------- 1 file changed, 26 insertions(+), 43 deletions(-) (limited to 'lib/astal/io/application.vala') diff --git a/lib/astal/io/application.vala b/lib/astal/io/application.vala index c7bd311..09b61b5 100644 --- a/lib/astal/io/application.vala +++ b/lib/astal/io/application.vala @@ -103,75 +103,58 @@ public static List get_instances() { * Quit an an Astal instances. * It is the equivalent of `astal --quit -i instance`. */ -public static void quit_instance(string instance) { - try { - IApplication proxy = Bus.get_proxy_sync( - BusType.SESSION, - "io.Astal." + instance, - "/io/Astal/Application" - ); +public static void quit_instance(string instance) throws Error { + IApplication proxy = Bus.get_proxy_sync( + BusType.SESSION, + "io.Astal." + instance, + "/io/Astal/Application" + ); - proxy.quit(); - } catch (Error err) { - critical(err.message); - } + proxy.quit(); } /** * Open the Gtk debug tool of an an Astal instances. * It is the equivalent of `astal --inspector -i instance`. */ -public static void open_inspector(string instance) { - try { - IApplication proxy = Bus.get_proxy_sync( - BusType.SESSION, - "io.Astal." + instance, - "/io/Astal/Application" - ); +public static void open_inspector(string instance) throws Error { + IApplication proxy = Bus.get_proxy_sync( + BusType.SESSION, + "io.Astal." + instance, + "/io/Astal/Application" + ); - proxy.inspector(); - } catch (Error err) { - critical(err.message); - } + proxy.inspector(); } /** * Toggle a Window of an Astal instances. * It is the equivalent of `astal -i instance --toggle window`. */ -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" - ); +public static void toggle_window_by_name(string instance, string window) throws Error { + IApplication proxy = Bus.get_proxy_sync( + BusType.SESSION, + "io.Astal." + instance, + "/io/Astal/Application" + ); - proxy.toggle_window(window); - } catch (Error err) { - critical(err.message); - } + proxy.toggle_window(window); } /** * Send a message to an Astal instances. * It is the equivalent of `astal -i instance content of the message`. */ -public static string send_message(string instance, string msg) { +public static string send_message(string instance, string msg) throws Error { var rundir = Environment.get_user_runtime_dir(); var socket_path = @"$rundir/astal/$instance.sock"; var client = new SocketClient(); - try { - var conn = client.connect(new UnixSocketAddress(socket_path), null); - conn.output_stream.write(msg.concat("\x04").data); + 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 ""; - } + var stream = new DataInputStream(conn.input_stream); + return stream.read_upto("\x04", -1, null, null); } /** -- cgit v1.2.3