something-x-dev 1.5.0.dev12__tar.gz → 1.6.0.dev13__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.
Files changed (25) hide show
  1. {something_x_dev-1.5.0.dev12/something_x_dev.egg-info → something_x_dev-1.6.0.dev13}/PKG-INFO +1 -1
  2. {something_x_dev-1.5.0.dev12 → something_x_dev-1.6.0.dev13}/nothing_app/pages/device.py +2 -0
  3. {something_x_dev-1.5.0.dev12 → something_x_dev-1.6.0.dev13}/nothing_app/protocol.py +33 -3
  4. {something_x_dev-1.5.0.dev12 → something_x_dev-1.6.0.dev13}/pyproject.toml +1 -1
  5. {something_x_dev-1.5.0.dev12 → something_x_dev-1.6.0.dev13/something_x_dev.egg-info}/PKG-INFO +1 -1
  6. {something_x_dev-1.5.0.dev12 → something_x_dev-1.6.0.dev13}/LICENSE +0 -0
  7. {something_x_dev-1.5.0.dev12 → something_x_dev-1.6.0.dev13}/README.md +0 -0
  8. {something_x_dev-1.5.0.dev12 → something_x_dev-1.6.0.dev13}/nothing_app/__init__.py +0 -0
  9. {something_x_dev-1.5.0.dev12 → something_x_dev-1.6.0.dev13}/nothing_app/application.py +0 -0
  10. {something_x_dev-1.5.0.dev12 → something_x_dev-1.6.0.dev13}/nothing_app/bluetooth.py +0 -0
  11. {something_x_dev-1.5.0.dev12 → something_x_dev-1.6.0.dev13}/nothing_app/data/__init__.py +0 -0
  12. {something_x_dev-1.5.0.dev12 → something_x_dev-1.6.0.dev13}/nothing_app/data/com.something.x.omarchy.desktop +0 -0
  13. {something_x_dev-1.5.0.dev12 → something_x_dev-1.6.0.dev13}/nothing_app/data/style.css +0 -0
  14. {something_x_dev-1.5.0.dev12 → something_x_dev-1.6.0.dev13}/nothing_app/pages/__init__.py +0 -0
  15. {something_x_dev-1.5.0.dev12 → something_x_dev-1.6.0.dev13}/nothing_app/pages/home.py +0 -0
  16. {something_x_dev-1.5.0.dev12 → something_x_dev-1.6.0.dev13}/nothing_app/profiles.py +0 -0
  17. {something_x_dev-1.5.0.dev12 → something_x_dev-1.6.0.dev13}/nothing_app/splash.py +0 -0
  18. {something_x_dev-1.5.0.dev12 → something_x_dev-1.6.0.dev13}/nothing_app/tray.py +0 -0
  19. {something_x_dev-1.5.0.dev12 → something_x_dev-1.6.0.dev13}/nothing_app/window.py +0 -0
  20. {something_x_dev-1.5.0.dev12 → something_x_dev-1.6.0.dev13}/setup.cfg +0 -0
  21. {something_x_dev-1.5.0.dev12 → something_x_dev-1.6.0.dev13}/something_x_dev.egg-info/SOURCES.txt +0 -0
  22. {something_x_dev-1.5.0.dev12 → something_x_dev-1.6.0.dev13}/something_x_dev.egg-info/dependency_links.txt +0 -0
  23. {something_x_dev-1.5.0.dev12 → something_x_dev-1.6.0.dev13}/something_x_dev.egg-info/entry_points.txt +0 -0
  24. {something_x_dev-1.5.0.dev12 → something_x_dev-1.6.0.dev13}/something_x_dev.egg-info/requires.txt +0 -0
  25. {something_x_dev-1.5.0.dev12 → something_x_dev-1.6.0.dev13}/something_x_dev.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: something-x-dev
3
- Version: 1.5.0.dev12
3
+ Version: 1.6.0.dev13
4
4
  Summary: Something X device manager for Omarchy / Linux
5
5
  Author: Raphael
6
6
  License: MIT
@@ -582,7 +582,9 @@ class DevicePage(Gtk.Box):
582
582
  return False
583
583
 
584
584
  def _sync_anc_ui(self, active_mode: int):
585
+ supported = self._nothing_dev.state.supported_anc_modes if self._nothing_dev else None
585
586
  for mode, btn in self._anc_buttons:
587
+ btn.set_visible(supported is None or mode in supported)
586
588
  if mode == active_mode:
587
589
  btn.add_css_class("active")
588
590
  else:
@@ -123,6 +123,8 @@ class DeviceState:
123
123
  serial_number: str = "—"
124
124
  left_wearing: bool = False
125
125
  right_wearing: bool = False
126
+ # None = not yet determined (show all); frozenset = confirmed supported modes
127
+ supported_anc_modes: frozenset | None = None
126
128
 
127
129
 
128
130
  # ── Device class ─────────────────────────────────────────────────────────────
@@ -451,7 +453,15 @@ class NothingDevice(GObject.Object):
451
453
  _log(f"[protocol] firmware={ver!r}")
452
454
  changed = True
453
455
  elif cmd_id == _CMD_REMOTE_CONF:
454
- sn = payload.decode(errors="replace").strip("\x00").strip()
456
+ # Payload is newline-separated "device_id,field_id,value" entries.
457
+ # field 4 = serial number (e.g. SH10212543006451)
458
+ raw = payload.decode(errors="replace").strip("\x00")
459
+ sn = None
460
+ for line in raw.splitlines():
461
+ parts = line.split(",", 2)
462
+ if len(parts) == 3 and parts[1] == "4" and parts[2].strip():
463
+ sn = parts[2].strip()
464
+ break
455
465
  if sn and sn != self.state.serial_number:
456
466
  self.state.serial_number = sn
457
467
  _log(f"[protocol] serial={sn!r}")
@@ -500,9 +510,12 @@ class NothingDevice(GObject.Object):
500
510
  def _parse_anc(self, payload: bytes) -> bool:
501
511
  # Payload: [type:1][value:1][pad:1] triplets
502
512
  # type=1: NOISE_REDUCTION_MODE type=2: NOISE_REDUCTION_LEVEL (last active level)
513
+ # level val 1–4 = ANC strength → ANC is supported
514
+ # level val 0 or 0xFE = no ANC strength → only Off + Transparency
503
515
  if len(payload) < 3:
504
516
  return False
505
517
  changed = False
518
+ level_val: int | None = None
506
519
  for i in range(0, len(payload) - 2, 3):
507
520
  t, val = payload[i], payload[i + 1]
508
521
  if t == 1: # NOISE_REDUCTION_MODE
@@ -516,8 +529,25 @@ class NothingDevice(GObject.Object):
516
529
  self.state.anc_mode = mode
517
530
  _log(f"[protocol] ANC mode → {ANCMode.LABELS.get(mode, mode)} (wire val {val})")
518
531
  changed = True
519
- elif t == 2 and 1 <= val <= 4: # NOISE_REDUCTION_LEVEL (ANC strength 1–4)
520
- self._last_anc_level = val
532
+ elif t == 2: # NOISE_REDUCTION_LEVEL
533
+ level_val = val
534
+ if 1 <= val <= 4:
535
+ self._last_anc_level = val
536
+
537
+ # First time we see a level entry, lock in supported modes.
538
+ # val 1–4 = ANC strength present → all three modes are available.
539
+ # val 0 or 0xFE = no ANC strength → device only supports Off + Transparency.
540
+ if level_val is not None and self.state.supported_anc_modes is None:
541
+ if 1 <= level_val <= 4:
542
+ modes = frozenset([ANCMode.OFF, ANCMode.NOISE_CANCELLATION, ANCMode.TRANSPARENCY])
543
+ else:
544
+ modes = frozenset([ANCMode.OFF, ANCMode.TRANSPARENCY])
545
+ self.state.supported_anc_modes = modes
546
+ _log(
547
+ f"[protocol] supported ANC modes detected: {[ANCMode.LABELS.get(m, m) for m in sorted(modes)]}"
548
+ )
549
+ changed = True
550
+
521
551
  return changed
522
552
 
523
553
  def _parse_earphone_status(self, payload: bytes) -> bool:
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "something-x-dev"
7
- version = "1.5.0.dev12"
7
+ version = "1.6.0.dev13"
8
8
  description = "Something X device manager for Omarchy / Linux"
9
9
  readme = "README.md"
10
10
  license = { text = "MIT" }
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: something-x-dev
3
- Version: 1.5.0.dev12
3
+ Version: 1.6.0.dev13
4
4
  Summary: Something X device manager for Omarchy / Linux
5
5
  Author: Raphael
6
6
  License: MIT