something-x-dev 1.2.3.dev3__tar.gz → 1.3.0.dev5__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {something_x_dev-1.2.3.dev3/something_x_dev.egg-info → something_x_dev-1.3.0.dev5}/PKG-INFO +1 -1
- {something_x_dev-1.2.3.dev3 → something_x_dev-1.3.0.dev5}/nothing_app/pages/device.py +30 -12
- {something_x_dev-1.2.3.dev3 → something_x_dev-1.3.0.dev5}/nothing_app/protocol.py +27 -21
- {something_x_dev-1.2.3.dev3 → something_x_dev-1.3.0.dev5}/nothing_app/window.py +30 -1
- {something_x_dev-1.2.3.dev3 → something_x_dev-1.3.0.dev5}/pyproject.toml +1 -1
- {something_x_dev-1.2.3.dev3 → something_x_dev-1.3.0.dev5/something_x_dev.egg-info}/PKG-INFO +1 -1
- {something_x_dev-1.2.3.dev3 → something_x_dev-1.3.0.dev5}/LICENSE +0 -0
- {something_x_dev-1.2.3.dev3 → something_x_dev-1.3.0.dev5}/README.md +0 -0
- {something_x_dev-1.2.3.dev3 → something_x_dev-1.3.0.dev5}/nothing_app/__init__.py +0 -0
- {something_x_dev-1.2.3.dev3 → something_x_dev-1.3.0.dev5}/nothing_app/application.py +0 -0
- {something_x_dev-1.2.3.dev3 → something_x_dev-1.3.0.dev5}/nothing_app/bluetooth.py +0 -0
- {something_x_dev-1.2.3.dev3 → something_x_dev-1.3.0.dev5}/nothing_app/data/__init__.py +0 -0
- {something_x_dev-1.2.3.dev3 → something_x_dev-1.3.0.dev5}/nothing_app/data/com.something.x.omarchy.desktop +0 -0
- {something_x_dev-1.2.3.dev3 → something_x_dev-1.3.0.dev5}/nothing_app/data/style.css +0 -0
- {something_x_dev-1.2.3.dev3 → something_x_dev-1.3.0.dev5}/nothing_app/pages/__init__.py +0 -0
- {something_x_dev-1.2.3.dev3 → something_x_dev-1.3.0.dev5}/nothing_app/pages/home.py +0 -0
- {something_x_dev-1.2.3.dev3 → something_x_dev-1.3.0.dev5}/nothing_app/profiles.py +0 -0
- {something_x_dev-1.2.3.dev3 → something_x_dev-1.3.0.dev5}/nothing_app/splash.py +0 -0
- {something_x_dev-1.2.3.dev3 → something_x_dev-1.3.0.dev5}/setup.cfg +0 -0
- {something_x_dev-1.2.3.dev3 → something_x_dev-1.3.0.dev5}/something_x_dev.egg-info/SOURCES.txt +0 -0
- {something_x_dev-1.2.3.dev3 → something_x_dev-1.3.0.dev5}/something_x_dev.egg-info/dependency_links.txt +0 -0
- {something_x_dev-1.2.3.dev3 → something_x_dev-1.3.0.dev5}/something_x_dev.egg-info/entry_points.txt +0 -0
- {something_x_dev-1.2.3.dev3 → something_x_dev-1.3.0.dev5}/something_x_dev.egg-info/requires.txt +0 -0
- {something_x_dev-1.2.3.dev3 → something_x_dev-1.3.0.dev5}/something_x_dev.egg-info/top_level.txt +0 -0
|
@@ -265,11 +265,17 @@ def _settings_row(title: str, subtitle: str = "", right_widget: Gtk.Widget | Non
|
|
|
265
265
|
|
|
266
266
|
|
|
267
267
|
class DevicePage(Gtk.Box):
|
|
268
|
-
def __init__(
|
|
268
|
+
def __init__(
|
|
269
|
+
self,
|
|
270
|
+
bt_device: BluetoothDevice,
|
|
271
|
+
bt_manager: BluetoothManager,
|
|
272
|
+
nothing_dev: NothingDevice | None = None,
|
|
273
|
+
):
|
|
269
274
|
super().__init__(orientation=Gtk.Orientation.VERTICAL)
|
|
270
275
|
self._bt_device = bt_device
|
|
271
276
|
self._bt = bt_manager
|
|
272
277
|
self._nothing_dev: NothingDevice | None = None
|
|
278
|
+
self._nd_handlers: list[int] = []
|
|
273
279
|
self._anc_buttons: list[tuple[int, Gtk.Button]] = []
|
|
274
280
|
self._eq_buttons: list[tuple[str, Gtk.Button]] = []
|
|
275
281
|
self._updating_ui = False
|
|
@@ -281,7 +287,7 @@ class DevicePage(Gtk.Box):
|
|
|
281
287
|
self._connect_retry_id: int | None = None
|
|
282
288
|
self._build()
|
|
283
289
|
if bt_device.is_nothing:
|
|
284
|
-
self._connect_nothing()
|
|
290
|
+
self._connect_nothing(nothing_dev)
|
|
285
291
|
if bt_device.connected:
|
|
286
292
|
GLib.timeout_add(800, self._query_volume)
|
|
287
293
|
|
|
@@ -474,17 +480,31 @@ class DevicePage(Gtk.Box):
|
|
|
474
480
|
|
|
475
481
|
def cleanup(self):
|
|
476
482
|
if self._nothing_dev:
|
|
477
|
-
self.
|
|
483
|
+
for h in self._nd_handlers:
|
|
484
|
+
try:
|
|
485
|
+
self._nothing_dev.disconnect(h)
|
|
486
|
+
except Exception:
|
|
487
|
+
pass
|
|
488
|
+
self._nd_handlers = []
|
|
478
489
|
self._bt.disconnect(self._bt_conn_handler)
|
|
479
490
|
self._bt.disconnect(self._bt_disc_handler)
|
|
480
491
|
|
|
481
|
-
def _connect_nothing(self):
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
492
|
+
def _connect_nothing(self, existing: NothingDevice | None):
|
|
493
|
+
if existing is not None:
|
|
494
|
+
self._nothing_dev = existing
|
|
495
|
+
else:
|
|
496
|
+
self._nothing_dev = NothingDevice(self._bt_device.address)
|
|
497
|
+
if self._bt_device.connected:
|
|
498
|
+
self._nothing_dev.connect_rfcomm()
|
|
499
|
+
|
|
500
|
+
self._nd_handlers = [
|
|
501
|
+
self._nothing_dev.connect("state-changed", self._on_state_changed),
|
|
502
|
+
self._nothing_dev.connect("connected", self._on_rfcomm_connected),
|
|
503
|
+
self._nothing_dev.connect("disconnected", self._on_rfcomm_disconnected),
|
|
504
|
+
]
|
|
505
|
+
if self._nothing_dev.rfcomm_connected:
|
|
506
|
+
self._on_state_changed(self._nothing_dev)
|
|
507
|
+
GLib.timeout_add(800, self._query_volume)
|
|
488
508
|
|
|
489
509
|
def _on_state_changed(self, dev: NothingDevice):
|
|
490
510
|
state = dev.state
|
|
@@ -568,8 +588,6 @@ class DevicePage(Gtk.Box):
|
|
|
568
588
|
|
|
569
589
|
def _on_conn_btn_clicked(self, _btn):
|
|
570
590
|
if self._bt_device.connected:
|
|
571
|
-
if self._nothing_dev:
|
|
572
|
-
self._nothing_dev.disconnect_rfcomm()
|
|
573
591
|
self._bt.disconnect_device(self._bt_device.path)
|
|
574
592
|
else:
|
|
575
593
|
self._conn_btn.set_label("CONNECTING…")
|
|
@@ -147,7 +147,7 @@ class NothingDevice(GObject.Object):
|
|
|
147
147
|
self._anc_pending_mode: int = ANCMode.OFF
|
|
148
148
|
self._last_anc_level: int = _ANC_STRONG
|
|
149
149
|
self._thread: threading.Thread | None = None
|
|
150
|
-
self._low_bat_notified: set[
|
|
150
|
+
self._low_bat_notified: dict[str, set[int]] = {}
|
|
151
151
|
|
|
152
152
|
# ── Public API ────────────────────────────────────────────────────────────
|
|
153
153
|
|
|
@@ -602,29 +602,35 @@ class NothingDevice(GObject.Object):
|
|
|
602
602
|
eq_val = EQ_PRESETS.get(p["eq"], 0)
|
|
603
603
|
self._x55_send(_CMD_SET_EQ, bytes([eq_val]), label=f"restore EQ={p['eq']}")
|
|
604
604
|
|
|
605
|
+
_LOW_BAT_THRESHOLDS = (20, 15, 10, 5)
|
|
606
|
+
|
|
605
607
|
def _check_low_battery(self, slot: str, pct: int, label: str):
|
|
606
608
|
if pct < 0:
|
|
607
609
|
return
|
|
608
|
-
if pct
|
|
609
|
-
self._low_bat_notified.
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
610
|
+
if pct > 25:
|
|
611
|
+
self._low_bat_notified.pop(slot, None)
|
|
612
|
+
return
|
|
613
|
+
notified = self._low_bat_notified.setdefault(slot, set())
|
|
614
|
+
for threshold in self._LOW_BAT_THRESHOLDS:
|
|
615
|
+
if pct <= threshold and threshold not in notified:
|
|
616
|
+
notified.add(threshold)
|
|
617
|
+
threading.Thread(
|
|
618
|
+
target=subprocess.run,
|
|
619
|
+
args=(
|
|
620
|
+
[
|
|
621
|
+
"notify-send",
|
|
622
|
+
"-u",
|
|
623
|
+
"critical",
|
|
624
|
+
"-i",
|
|
625
|
+
"battery-caution",
|
|
626
|
+
"Something X",
|
|
627
|
+
f"{label}: {pct}% battery remaining",
|
|
628
|
+
],
|
|
629
|
+
),
|
|
630
|
+
kwargs={"capture_output": True},
|
|
631
|
+
daemon=True,
|
|
632
|
+
).start()
|
|
633
|
+
break
|
|
628
634
|
|
|
629
635
|
def _activation_fallback(self):
|
|
630
636
|
if not self._activated and self._rfcomm_connected:
|
|
@@ -5,6 +5,7 @@ gi.require_version("Adw", "1")
|
|
|
5
5
|
from gi.repository import Gtk, Adw
|
|
6
6
|
|
|
7
7
|
from .bluetooth import BluetoothDevice, BluetoothManager
|
|
8
|
+
from .protocol import NothingDevice
|
|
8
9
|
from .pages.home import HomePage
|
|
9
10
|
from .pages.device import DevicePage
|
|
10
11
|
|
|
@@ -15,7 +16,34 @@ class SomethingXWindow(Adw.ApplicationWindow):
|
|
|
15
16
|
self.set_default_size(420, 780)
|
|
16
17
|
self.set_resizable(True)
|
|
17
18
|
self._bt = bt_manager
|
|
19
|
+
self._nothing_devices: dict[str, NothingDevice] = {}
|
|
20
|
+
self._bt_conn_handler = bt_manager.connect("device-connected", self._on_bt_connected)
|
|
21
|
+
self._bt_disc_handler = bt_manager.connect("device-disconnected", self._on_bt_disconnected)
|
|
18
22
|
self._build()
|
|
23
|
+
self._autoconnect_existing()
|
|
24
|
+
|
|
25
|
+
def _autoconnect_existing(self):
|
|
26
|
+
for dev in self._bt.get_nothing_devices():
|
|
27
|
+
if dev.connected:
|
|
28
|
+
self._start_nothing_device(dev.path, dev.address)
|
|
29
|
+
|
|
30
|
+
def _start_nothing_device(self, path: str, address: str):
|
|
31
|
+
if path in self._nothing_devices:
|
|
32
|
+
return
|
|
33
|
+
nd = NothingDevice(address)
|
|
34
|
+
self._nothing_devices[path] = nd
|
|
35
|
+
nd.connect_rfcomm()
|
|
36
|
+
print(f"[window] autoconnect RFCOMM → {address}")
|
|
37
|
+
|
|
38
|
+
def _on_bt_connected(self, _mgr, path: str):
|
|
39
|
+
dev = self._bt.devices.get(path)
|
|
40
|
+
if dev and dev.is_nothing:
|
|
41
|
+
self._start_nothing_device(path, dev.address)
|
|
42
|
+
|
|
43
|
+
def _on_bt_disconnected(self, _mgr, path: str):
|
|
44
|
+
nd = self._nothing_devices.pop(path, None)
|
|
45
|
+
if nd:
|
|
46
|
+
nd.disconnect_rfcomm()
|
|
19
47
|
|
|
20
48
|
def _build(self):
|
|
21
49
|
nav = Adw.NavigationView()
|
|
@@ -64,7 +92,8 @@ class SomethingXWindow(Adw.ApplicationWindow):
|
|
|
64
92
|
header.add_css_class("nothing-header")
|
|
65
93
|
toolbar_view.add_top_bar(header)
|
|
66
94
|
|
|
67
|
-
|
|
95
|
+
nothing_dev = self._nothing_devices.get(bt_device.path)
|
|
96
|
+
device_page = DevicePage(bt_device=bt_device, bt_manager=self._bt, nothing_dev=nothing_dev)
|
|
68
97
|
toolbar_view.set_content(device_page)
|
|
69
98
|
|
|
70
99
|
nav_page.set_child(toolbar_view)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{something_x_dev-1.2.3.dev3 → something_x_dev-1.3.0.dev5}/something_x_dev.egg-info/SOURCES.txt
RENAMED
|
File without changes
|
|
File without changes
|
{something_x_dev-1.2.3.dev3 → something_x_dev-1.3.0.dev5}/something_x_dev.egg-info/entry_points.txt
RENAMED
|
File without changes
|
{something_x_dev-1.2.3.dev3 → something_x_dev-1.3.0.dev5}/something_x_dev.egg-info/requires.txt
RENAMED
|
File without changes
|
{something_x_dev-1.2.3.dev3 → something_x_dev-1.3.0.dev5}/something_x_dev.egg-info/top_level.txt
RENAMED
|
File without changes
|