mirror of
https://github.com/zoriya/astal.git
synced 2026-05-25 23:38:07 +00:00
0738194780
starting point of the monorepo
197 lines
5.1 KiB
Vala
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();
|
|
}
|
|
}
|
|
}
|