mirror of
https://github.com/zoriya/astal.git
synced 2026-05-27 08:02:20 +00:00
monorepo structuring
This commit is contained in:
@@ -0,0 +1,89 @@
|
||||
namespace AstalBluetooth {
|
||||
[DBus (name = "org.bluez.Adapter1")]
|
||||
internal interface IAdapter : DBusProxy {
|
||||
public abstract void remove_device(ObjectPath device) throws Error;
|
||||
public abstract void start_discovery() throws Error;
|
||||
public abstract void stop_discovery() throws Error;
|
||||
|
||||
public abstract string[] uuids { owned get; }
|
||||
public abstract bool discoverable { get; set; }
|
||||
public abstract bool discovering { get; }
|
||||
public abstract bool pairable { get; set; }
|
||||
public abstract bool powered { get; set; }
|
||||
public abstract string address { owned get; }
|
||||
public abstract string alias { owned get; set; }
|
||||
public abstract string modalias { owned get; }
|
||||
public abstract string name { owned get; }
|
||||
public abstract uint class { get; }
|
||||
public abstract uint discoverable_timeout { get; set; }
|
||||
public abstract uint pairable_timeout { get; set; }
|
||||
}
|
||||
|
||||
public class Adapter : Object {
|
||||
private IAdapter proxy;
|
||||
public string object_path { owned get; construct set; }
|
||||
|
||||
internal Adapter(IAdapter proxy) {
|
||||
this.proxy = proxy;
|
||||
this.object_path = proxy.g_object_path;
|
||||
proxy.g_properties_changed.connect((props) => {
|
||||
var map = (HashTable<string, Variant>)props;
|
||||
foreach (var key in map.get_keys()) {
|
||||
var prop = kebab_case(key);
|
||||
if (get_class().find_property(prop) != null) {
|
||||
notify_property(prop);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public string[] uuids { owned get { return proxy.uuids; } }
|
||||
public bool discovering { get { return proxy.discovering; } }
|
||||
public string modalias { owned get { return proxy.modalias; } }
|
||||
public string name { owned get { return proxy.name; } }
|
||||
public uint class { get { return proxy.class; } }
|
||||
public string address { owned get { return proxy.address; } }
|
||||
|
||||
public bool discoverable {
|
||||
get { return proxy.discoverable; }
|
||||
set { proxy.discoverable = value; }
|
||||
}
|
||||
|
||||
public bool pairable {
|
||||
get { return proxy.pairable; }
|
||||
set { proxy.pairable = value; }
|
||||
}
|
||||
|
||||
public bool powered {
|
||||
get { return proxy.powered; }
|
||||
set { proxy.powered = value; }
|
||||
}
|
||||
|
||||
public string alias {
|
||||
owned get { return proxy.alias; }
|
||||
set { proxy.alias = value; }
|
||||
}
|
||||
|
||||
public uint discoverable_timeout {
|
||||
get { return proxy.discoverable_timeout; }
|
||||
set { proxy.discoverable_timeout = value; }
|
||||
}
|
||||
|
||||
public uint pairable_timeout {
|
||||
get { return proxy.pairable_timeout; }
|
||||
set { proxy.pairable_timeout = value; }
|
||||
}
|
||||
|
||||
public void remove_device(Device device) {
|
||||
try { proxy.remove_device((ObjectPath)device.object_path); } catch (Error err) { critical(err.message); }
|
||||
}
|
||||
|
||||
public void start_discovery() {
|
||||
try { proxy.start_discovery(); } catch (Error err) { critical(err.message); }
|
||||
}
|
||||
|
||||
public void stop_discovery() {
|
||||
try { proxy.stop_discovery(); } catch (Error err) { critical(err.message); }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,181 @@
|
||||
namespace AstalBluetooth {
|
||||
public Bluetooth get_default() {
|
||||
return Bluetooth.get_default();
|
||||
}
|
||||
|
||||
public class Bluetooth : Object {
|
||||
private static Bluetooth _instance;
|
||||
|
||||
public static Bluetooth get_default() {
|
||||
if (_instance == null)
|
||||
_instance = new Bluetooth();
|
||||
|
||||
return _instance;
|
||||
}
|
||||
|
||||
private DBusObjectManagerClient manager;
|
||||
|
||||
private HashTable<string, Adapter> _adapters =
|
||||
new HashTable<string, Adapter>(str_hash, str_equal);
|
||||
|
||||
private HashTable<string, Device> _devices =
|
||||
new HashTable<string, Device>(str_hash, str_equal);
|
||||
|
||||
public signal void device_added (Device device) {
|
||||
notify_property("devices");
|
||||
}
|
||||
|
||||
public signal void device_removed (Device device) {
|
||||
notify_property("devices");
|
||||
}
|
||||
|
||||
public signal void adapter_added (Adapter adapter) {
|
||||
notify_property("adapters");
|
||||
}
|
||||
|
||||
public signal void adapter_removed (Adapter adapter) {
|
||||
notify_property("adapters");
|
||||
}
|
||||
|
||||
public bool is_powered { get; private set; default = false; }
|
||||
public bool is_connected { get; private set; default = false; }
|
||||
public Adapter? adapter { get { return adapters.nth_data(0); } }
|
||||
|
||||
public List<weak Adapter> adapters {
|
||||
owned get { return _adapters.get_values(); }
|
||||
}
|
||||
|
||||
public List<weak Device> devices {
|
||||
owned get { return _devices.get_values(); }
|
||||
}
|
||||
|
||||
construct {
|
||||
try {
|
||||
manager = new DBusObjectManagerClient.for_bus_sync(
|
||||
BusType.SYSTEM,
|
||||
DBusObjectManagerClientFlags.NONE,
|
||||
"org.bluez",
|
||||
"/",
|
||||
manager_proxy_get_type,
|
||||
null
|
||||
);
|
||||
|
||||
foreach (var object in manager.get_objects()) {
|
||||
foreach (var iface in object.get_interfaces()) {
|
||||
on_interface_added(object, iface);
|
||||
}
|
||||
}
|
||||
|
||||
manager.interface_added.connect(on_interface_added);
|
||||
manager.interface_removed.connect(on_interface_removed);
|
||||
|
||||
manager.object_added.connect((object) => {
|
||||
foreach (var iface in object.get_interfaces()) {
|
||||
on_interface_added(object, iface);
|
||||
}
|
||||
});
|
||||
|
||||
manager.object_removed.connect((object) => {
|
||||
foreach (var iface in object.get_interfaces()) {
|
||||
on_interface_removed(object, iface);
|
||||
}
|
||||
});
|
||||
} catch (Error err) {
|
||||
critical(err.message);
|
||||
}
|
||||
}
|
||||
|
||||
public void toggle() {
|
||||
adapter.powered = !adapter.powered;
|
||||
}
|
||||
|
||||
[CCode (cname="astal_bluetooth_idevice_proxy_get_type")]
|
||||
extern static GLib.Type get_idevice_proxy_type();
|
||||
|
||||
[CCode (cname="astal_bluetooth_iadapter_proxy_get_type")]
|
||||
extern static GLib.Type get_iadapter_proxy_type();
|
||||
|
||||
private Type manager_proxy_get_type(DBusObjectManagerClient _, string object_path, string? interface_name) {
|
||||
if (interface_name == null)
|
||||
return typeof(DBusObjectProxy);
|
||||
|
||||
switch (interface_name) {
|
||||
case "org.bluez.Device1":
|
||||
return get_idevice_proxy_type();
|
||||
case "org.bluez.Adapter1":
|
||||
return get_iadapter_proxy_type();
|
||||
default:
|
||||
return typeof(DBusProxy);
|
||||
}
|
||||
}
|
||||
|
||||
private void on_interface_added(DBusObject object, DBusInterface iface) {
|
||||
if (iface is IDevice) {
|
||||
var device = new Device((IDevice)iface);
|
||||
_devices.set(device.object_path, device);
|
||||
device_added(device);
|
||||
device.notify.connect(sync);
|
||||
sync();
|
||||
}
|
||||
|
||||
if (iface is IAdapter) {
|
||||
var adapter = new Adapter((IAdapter)iface);
|
||||
_adapters.set(adapter.object_path, adapter);
|
||||
adapter_added(adapter);
|
||||
adapter.notify.connect(sync);
|
||||
sync();
|
||||
}
|
||||
}
|
||||
|
||||
private void on_interface_removed (DBusObject object, DBusInterface iface) {
|
||||
if (iface is IDevice) {
|
||||
unowned var device = (IDevice)iface;
|
||||
device_removed(_devices.get(device.g_object_path));
|
||||
_devices.remove(device.g_object_path);
|
||||
}
|
||||
|
||||
if (iface is IAdapter) {
|
||||
unowned var adapter = (IAdapter)iface;
|
||||
adapter_removed(_adapters.get(adapter.g_object_path));
|
||||
_adapters.remove(adapter.g_object_path);
|
||||
}
|
||||
|
||||
sync();
|
||||
}
|
||||
|
||||
private void sync() {
|
||||
var powered = get_powered();
|
||||
var connected = get_connected();
|
||||
|
||||
if (powered != is_powered || connected != is_connected) {
|
||||
if (powered != is_powered) {
|
||||
is_powered = powered;
|
||||
}
|
||||
|
||||
if (connected != is_connected) {
|
||||
is_connected = connected;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private bool get_powered() {
|
||||
foreach (var adapter in adapters) {
|
||||
if (adapter.powered) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private bool get_connected() {
|
||||
foreach (var device in devices) {
|
||||
if (device.connected) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace AstalBluetooth {
|
||||
public const int MAJOR_VERSION = @MAJOR_VERSION@;
|
||||
public const int MINOR_VERSION = @MINOR_VERSION@;
|
||||
public const int MICRO_VERSION = @MICRO_VERSION@;
|
||||
public const string VERSION = "@VERSION@";
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
namespace AstalBluetooth {
|
||||
[DBus (name = "org.bluez.Device1")]
|
||||
internal interface IDevice : DBusProxy {
|
||||
public abstract void cancel_pairing() throws Error;
|
||||
public abstract async void connect() throws Error;
|
||||
public abstract void connect_profile(string uuid) throws Error;
|
||||
public abstract async void disconnect() throws Error;
|
||||
public abstract void disconnect_profile(string uuid) throws Error;
|
||||
public abstract void pair() throws Error;
|
||||
|
||||
public abstract string[] uuids { owned get; }
|
||||
public abstract bool blocked { get; set; }
|
||||
public abstract bool connected { get; }
|
||||
public abstract bool legacy_pairing { get; }
|
||||
public abstract bool paired { get; }
|
||||
public abstract bool trusted { get; set; }
|
||||
public abstract int16 rssi { get; }
|
||||
public abstract ObjectPath adapter { owned get; }
|
||||
public abstract string address { owned get; }
|
||||
public abstract string alias { owned get; set; }
|
||||
public abstract string icon { owned get; }
|
||||
public abstract string modalias { owned get; }
|
||||
public abstract string name { owned get; }
|
||||
public abstract uint16 appearance { get; }
|
||||
public abstract uint32 class { get; }
|
||||
}
|
||||
|
||||
public class Device : Object {
|
||||
private IDevice proxy;
|
||||
public string object_path { owned get; construct set; }
|
||||
|
||||
internal Device(IDevice proxy) {
|
||||
this.proxy = proxy;
|
||||
this.object_path = proxy.g_object_path;
|
||||
proxy.g_properties_changed.connect((props) => {
|
||||
var map = (HashTable<string, Variant>)props;
|
||||
foreach (var key in map.get_keys()) {
|
||||
var prop = kebab_case(key);
|
||||
if (get_class().find_property(prop) != null) {
|
||||
notify_property(prop);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public string[] uuids { owned get { return proxy.uuids; } }
|
||||
public bool connected { get { return proxy.connected; } }
|
||||
public bool legacy_pairing { get { return proxy.legacy_pairing; } }
|
||||
public bool paired { get { return proxy.paired; } }
|
||||
public int16 rssi { get { return proxy.rssi; } }
|
||||
public ObjectPath adapter { owned get { return proxy.adapter; } }
|
||||
public string address { owned get { return proxy.address; } }
|
||||
public string icon { owned get { return proxy.icon; } }
|
||||
public string modalias { owned get { return proxy.modalias; } }
|
||||
public string name { owned get { return proxy.name; } }
|
||||
public uint16 appearance { get { return proxy.appearance; } }
|
||||
public uint32 class { get { return proxy.class; } }
|
||||
public bool connecting { get; private set; }
|
||||
|
||||
public bool blocked {
|
||||
get { return proxy.blocked; }
|
||||
set { proxy.blocked = value; }
|
||||
}
|
||||
|
||||
public bool trusted {
|
||||
get { return proxy.trusted; }
|
||||
set { proxy.trusted = value; }
|
||||
}
|
||||
|
||||
public string alias {
|
||||
owned get { return proxy.alias; }
|
||||
set { proxy.alias = value; }
|
||||
}
|
||||
|
||||
public void cancel_pairing() {
|
||||
try { proxy.cancel_pairing(); } catch (Error err) { critical(err.message); }
|
||||
}
|
||||
|
||||
public async void connect_device() {
|
||||
try {
|
||||
connecting = true;
|
||||
yield proxy.connect();
|
||||
} catch (Error err) {
|
||||
critical(err.message);
|
||||
} finally {
|
||||
connecting = false;
|
||||
}
|
||||
}
|
||||
|
||||
public async void disconnect_device() {
|
||||
try { yield proxy.disconnect(); } catch (Error err) { critical(err.message); }
|
||||
}
|
||||
|
||||
public void connect_profile(string uuid) {
|
||||
try { proxy.connect_profile(uuid); } catch (Error err) { critical(err.message); }
|
||||
}
|
||||
|
||||
public void disconnect_profile(string uuid) {
|
||||
try { proxy.disconnect_profile(uuid); } catch (Error err) { critical(err.message); }
|
||||
}
|
||||
|
||||
public void pair() {
|
||||
try { proxy.pair(); } catch (Error err) { critical(err.message); }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
project(
|
||||
'astal-bluetooth',
|
||||
'vala',
|
||||
'c',
|
||||
version: run_command('cat', join_paths(meson.project_source_root(), 'version')).stdout().strip(),
|
||||
meson_version: '>= 0.62.0',
|
||||
default_options: [
|
||||
'warning_level=2',
|
||||
'werror=false',
|
||||
'c_std=gnu11',
|
||||
],
|
||||
)
|
||||
|
||||
version_split = meson.project_version().split('.')
|
||||
api_version = version_split[0] + '.' + version_split[1]
|
||||
gir = 'AstalBluetooth-' + api_version + '.gir'
|
||||
typelib = 'AstalBluetooth-' + api_version + '.typelib'
|
||||
|
||||
config = configure_file(
|
||||
input: 'config.vala.in',
|
||||
output: 'config.vala',
|
||||
configuration: {
|
||||
'VERSION': meson.project_version(),
|
||||
'MAJOR_VERSION': version_split[0],
|
||||
'MINOR_VERSION': version_split[1],
|
||||
'MICRO_VERSION': version_split[2],
|
||||
},
|
||||
)
|
||||
|
||||
deps = [
|
||||
dependency('glib-2.0'),
|
||||
dependency('gobject-2.0'),
|
||||
dependency('gio-2.0'),
|
||||
]
|
||||
|
||||
sources = [
|
||||
config,
|
||||
'utils.vala',
|
||||
'device.vala',
|
||||
'adapter.vala',
|
||||
'bluetooth.vala',
|
||||
]
|
||||
|
||||
lib = library(
|
||||
meson.project_name(),
|
||||
sources,
|
||||
dependencies: deps,
|
||||
vala_header: meson.project_name() + '.h',
|
||||
vala_vapi: meson.project_name() + '-' + api_version + '.vapi',
|
||||
vala_gir: gir,
|
||||
version: meson.project_version(),
|
||||
install: true,
|
||||
install_dir: [true, true, true, true],
|
||||
)
|
||||
|
||||
import('pkgconfig').generate(
|
||||
lib,
|
||||
name: meson.project_name(),
|
||||
filebase: meson.project_name() + '-' + api_version,
|
||||
version: meson.project_version(),
|
||||
subdirs: meson.project_name(),
|
||||
requires: deps,
|
||||
install_dir: get_option('libdir') / 'pkgconfig',
|
||||
)
|
||||
|
||||
custom_target(
|
||||
typelib,
|
||||
command: [
|
||||
find_program('g-ir-compiler'),
|
||||
'--output', '@OUTPUT@',
|
||||
'--shared-library', get_option('prefix') / get_option('libdir') / '@PLAINNAME@',
|
||||
meson.current_build_dir() / gir,
|
||||
],
|
||||
input: lib,
|
||||
output: typelib,
|
||||
depends: lib,
|
||||
install: true,
|
||||
install_dir: get_option('libdir') / 'girepository-1.0',
|
||||
)
|
||||
@@ -0,0 +1,21 @@
|
||||
namespace AstalBluetooth {
|
||||
internal string kebab_case(string pascal_case) {
|
||||
StringBuilder kebab_case = new StringBuilder();
|
||||
|
||||
for (int i = 0; i < pascal_case.length; i++) {
|
||||
char c = pascal_case[i];
|
||||
|
||||
if (c >= 'A' && c <= 'Z') {
|
||||
if (i != 0) {
|
||||
kebab_case.append_c('-');
|
||||
}
|
||||
|
||||
kebab_case.append_c((char)(c + 32));
|
||||
} else {
|
||||
kebab_case.append_c(c);
|
||||
}
|
||||
}
|
||||
|
||||
return kebab_case.str;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
0.1.0
|
||||
Reference in New Issue
Block a user