Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 38 additions & 17 deletions blueman/gui/manager/ManagerDeviceMenu.py
Original file line number Diff line number Diff line change
Expand Up @@ -195,32 +195,48 @@ def on_device_property_changed(self, lst: "ManagerDeviceList", _device: Device,

def _handle_error_message(self, error: GLib.Error) -> None:
err = self._BLUEZ_ERROR_MAP.get(error.message.split(":", 3)[-1].strip())

if err == self._BluezError.PROFILE_UNAVAILABLE:
logging.warning("No audio endpoints registered to bluetoothd. "
"Pulseaudio Bluetooth module, bluez-alsa, PipeWire or other audio support missing.")
msg = _("No audio endpoints registered")
elif err == self._BluezError.CREATE_SOCKET:
logging.warning("bluetoothd reported input/output error. Check its logs for context.")
msg = _("Input/output error")
elif err == self._BluezError.PAGE_TIMEOUT:
msg = _("Device did not respond")
elif err == self._BluezError.UNKNOWN:
logging.warning("bluetoothd reported an unknown error. "
"Retry or check its logs for context.")
msg = _("Unknown error")
else:
msg = error.message.split(":", 3)[-1].strip()
info: str | None = None
match err:
case self._BluezError.PROFILE_UNAVAILABLE:
info = \
"No audio endpoints registered to bluetoothd. "
"Pulseaudio Bluetooth module, bluez-alsa, PipeWire or other audio support missing."
msg = _("No audio endpoints registered")
case self._BluezError.CREATE_SOCKET:
info = "bluetoothd reported input/output error. Check its logs for context."
msg = _("Input/output error")
case self._BluezError.PAGE_TIMEOUT:
msg = _("Device did not respond")
info = "Is the device turned on?"
case self._BluezError.ABORTED:
msg = _("Aborted")
info = "Is the device turned on?"
case self._BluezError.RESET:
msg = _("Reset")
info = "Check the device for more info."
case self._BluezError.UNKNOWN:
info = "bluetoothd reported an unknown error. \nRetry or check its logs for context."
msg = _("Unknown error")
case self._BluezError.NMBTFAILED:
msg = _("could not create bluetooth connection for NetworkManager")
case _:
msg = error.message.split(":", 3)[-1].strip()

if info is not None:
logging.warning(info)

if err != self._BluezError.CANCELED:
self.Blueman.infobar_update(_("Connection Failed: ") + msg)
self.Blueman.infobar_update(_("Connection Failed: ") + msg, info=info)

class _BluezError(Enum):
PAGE_TIMEOUT = auto()
PROFILE_UNAVAILABLE = auto()
CREATE_SOCKET = auto()
CANCELED = auto()
ABORTED = auto()
RESET = auto()
UNKNOWN = auto()
NMBTFAILED = auto()

# BlueZ 5.62 introduced machine-readable error strings while earlier versions
# used strerror() so that the messages depend on the libc implementation:
Expand All @@ -239,6 +255,11 @@ class _BluezError(Enum):
"br-connection-unknown": _BluezError.UNKNOWN,
"Cancelled": _BluezError.CANCELED,
"br-connection-canceled": _BluezError.CANCELED,
"br-connection-abort-by-local": _BluezError.ABORTED,
"le-connection-abort-by-local": _BluezError.ABORTED,
"br-connection-abort-by-remote": _BluezError.RESET,
"le-connection-abort-by-remote": _BluezError.RESET,
"Connection failed with reason: bt-failed": _BluezError.NMBTFAILED,
}

def show_generic_connect_calc(self, device_uuids: Iterable[str]) -> bool:
Expand Down
21 changes: 10 additions & 11 deletions blueman/main/Manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -289,24 +289,23 @@ def on_error(e: Exception) -> None:
s1 = self.List.connect("discovery-progress", on_progress)
s2 = self.List.connect("adapter-property-changed", prop_changed)

def infobar_update(self, message: str, bt: str | None = None, icon_name: str = "dialog-warning") -> None:
if icon_name == "dialog-warning":
self._infobar.set_message_type(Gtk.MessageType.WARNING)
else:
self._infobar.set_message_type(Gtk.MessageType.INFO)

more_button = self.builder.get_widget("ib_more_button", Gtk.Button)
image = self.builder.get_widget("ib_icon", Gtk.Image)
def infobar_update(self, message: str, bt: str | None = None, info: str | None = None) -> None:
backtace_button = self.builder.get_widget("ib_backtrace_button", Gtk.Button)
msg_lbl = self.builder.get_widget("ib_message", Gtk.Label)
image.set_from_icon_name(icon_name, 16)
info_image = self.builder.get_widget("ib_info_image", Gtk.Image)

info_image.set_visible(False if info is None else True)
info_image.set_tooltip_text("" if info is None else info)

if bt is not None:
msg_lbl.set_text(f"{message}…")
self._infobar_bt = f"{message}\n{bt}"
more_button.show()
backtace_button.show()
self._infobar.set_message_type(Gtk.MessageType.ERROR)
else:
more_button.hide()
backtace_button.hide()
msg_lbl.set_text(f"{message}")
self._infobar.set_message_type(Gtk.MessageType.INFO)

self._infobar.set_visible(True)
self._infobar.set_revealed(True)
Expand Down
6 changes: 5 additions & 1 deletion blueman/main/NetworkManager.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,18 @@ class NMConnectionError(Exception):
pass


class NMConnectionNotSupported(Exception):
pass


class NMConnectionBase:
conntype: str

def __init__(self, service: Service, reply_handler: Callable[[], None],
error_handler: Callable[[NMConnectionError | GLib.Error], None]):
if self.conntype not in ('dun', 'panu'):
error_handler(
NMConnectionError(f"Invalid connection type {self.conntype}, should be panu or dun")
NMConnectionNotSupported(f"Invalid connection type {self.conntype}, should be panu or dun")
)
self.device = service.device
self.bdaddr: BtAddress = self.device['Address']
Expand Down
30 changes: 11 additions & 19 deletions data/ui/manager-main.ui
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
<?xml version='1.0' encoding='UTF-8'?>
<!-- Created with Cambalache 0.96.1 -->
<!-- Created with Cambalache 0.96.3 -->
<interface>
<!-- interface-name manager-main.ui -->
<requires lib="gtk+" version="3.24"/>
<object class="GtkImage" id="ib_more_icon">
<object class="GtkImage" id="ib_backtrace_icon">
<property name="can-focus">False</property>
<property name="icon-name">dialog-information</property>
<property name="visible">True</property>
Expand Down Expand Up @@ -644,10 +644,10 @@
<property name="can-focus">False</property>
<property name="spacing">8</property>
<child>
<object class="GtkButton" id="ib_more_button">
<object class="GtkButton" id="ib_backtrace_button">
<property name="can-focus">True</property>
<property name="image">ib_more_icon</property>
<property name="label" translatable="yes">More</property>
<property name="image">ib_backtrace_icon</property>
<property name="label" translatable="yes">Backtrace</property>
<property name="receives-default">True</property>
<property name="relief">none</property>
</object>
Expand All @@ -668,19 +668,6 @@
<object class="GtkBox">
<property name="can-focus">False</property>
<property name="spacing">16</property>
<child>
<object class="GtkImage" id="ib_icon">
<property name="can-focus">False</property>
<property name="icon-name">dialog-warning</property>
<property name="pixel-size">16</property>
<property name="visible">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="ib_message">
<property name="can-focus">False</property>
Expand All @@ -694,6 +681,11 @@
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkImage" id="ib_info_image">
<property name="icon-name">dialog-question</property>
</object>
</child>
</object>
<packing>
<property name="expand">False</property>
Expand All @@ -703,7 +695,7 @@
</child>
<!-- Custom object fragments -->
<action-widgets>
<action-widget response="0">ib_more_button</action-widget>
<action-widget response="0">ib_backtrace_button</action-widget>
</action-widgets>
</object>
<packing>
Expand Down
Loading