Files
astal/core/src/variable.vala
Aylur 0738194780 move libastal to /core
starting point of the monorepo
2024-09-01 02:06:50 +02:00

197 lines
5.1 KiB
Vala

namespace Astal {
public class VariableBase : Object {
public signal void changed ();
public signal void dropped ();
public signal void error (string err);
// lua-lgi crashes when using its emitting mechanism
public void emit_changed() { changed(); }
public void emit_dropped() { dropped(); }
public void emit_error(string err) { this.error(err); }
~VariableBase() {
dropped();
}
}
public class Variable : VariableBase {
public Value value { owned get; set; }
private uint poll_id = 0;
private Process? watch_proc;
private uint poll_interval { get; set; default = 1000; }
private string[] poll_exec { get; set; }
private Closure? poll_transform { get; set; }
private Closure? poll_fn { get; set; }
private Closure? watch_transform { get; set; }
private string[] watch_exec { get; set; }
public Variable(Value init) {
Object(value: init);
}
public Variable poll(
uint interval,
string exec,
Closure? transform
) throws Error {
string[] argv;
Shell.parse_argv(exec, out argv);
return pollv(interval, argv, transform);
}
public Variable pollv(
uint interval,
string[] execv,
Closure? transform
) throws Error {
if (is_polling())
stop_poll();
poll_interval = interval;
poll_exec = execv;
poll_transform = transform;
poll_fn = null;
start_poll();
return this;
}
public Variable pollfn(
uint interval,
Closure fn
) throws Error {
if (is_polling())
stop_poll();
poll_interval = interval;
poll_fn = fn;
poll_exec = null;
start_poll();
return this;
}
public Variable watch(
string exec,
Closure? transform
) throws Error {
string[] argv;
Shell.parse_argv(exec, out argv);
return watchv(argv, transform);
}
public Variable watchv(
string[] execv,
Closure? transform
) throws Error {
if (is_watching())
stop_watch();
watch_exec = execv;
watch_transform = transform;
start_watch();
return this;
}
construct {
notify["value"].connect(() => changed());
dropped.connect(() => {
if (is_polling())
stop_poll();
if (is_watching())
stop_watch();
});
}
private void set_closure(string val, Closure? transform) {
if (transform != null) {
var str = Value(typeof(string));
str.set_string(val);
var ret_val = Value(this.value.type());
transform.invoke(ref ret_val, { str, this.value });
this.value = ret_val;
}
else {
if (this.value.type() == Type.STRING && this.value.get_string() == val)
return;
var str = Value(typeof(string));
str.set_string(val);
this.value = str;
}
}
private void set_fn() {
var ret_val = Value(this.value.type());
poll_fn.invoke(ref ret_val, { this.value });
this.value = ret_val;
}
public void start_poll() throws Error {
return_if_fail(poll_id == 0);
if (poll_fn != null) {
set_fn();
poll_id = Timeout.add(poll_interval, () => {
set_fn();
return Source.CONTINUE;
}, Priority.DEFAULT);
}
if (poll_exec != null) {
Process.exec_asyncv.begin(poll_exec, (_, res) => {
try {
var str = Process.exec_asyncv.end(res);
set_closure(str, poll_transform);
} catch (Error err) {
this.error(err.message);
}
});
poll_id = Timeout.add(poll_interval, () => {
Process.exec_asyncv.begin(poll_exec, (_, res) => {
try {
var str = Process.exec_asyncv.end(res);
set_closure(str, poll_transform);
} catch (Error err) {
this.error(err.message);
Source.remove(poll_id);
poll_id = 0;
}
});
return Source.CONTINUE;
}, Priority.DEFAULT);
}
}
public void start_watch() throws Error {
return_if_fail(watch_proc == null);
return_if_fail(watch_exec != null);
watch_proc = new Process.subprocessv(watch_exec);
watch_proc.stdout.connect((str) => set_closure(str, watch_transform));
watch_proc.stderr.connect((str) => this.error(str));
}
public void stop_poll() {
return_if_fail(poll_id != 0);
Source.remove(poll_id);
poll_id = 0;
}
public void stop_watch() {
return_if_fail(watch_proc != null);
watch_proc.kill();
watch_proc = null;
}
public bool is_polling() { return poll_id > 0; }
public bool is_watching() { return watch_proc != null; }
~Variable() {
dropped();
}
}
}