fix: improve Bluetooth reliability

This commit is contained in:
2026-07-31 18:42:48 +02:00
parent 4627ac92fd
commit 18122136dd
20 changed files with 1870 additions and 587 deletions
+37 -6
View File
@@ -325,6 +325,7 @@ static void finish_scan() {
static void do_connect(const uint8_t* addr) {
int r = montauk::bt_connect(addr);
if (r >= 0) set_status("Connected");
else if (r == -2) set_status("Connected; audio setup failed - use Retry");
else set_status("Connection failed");
refresh_devices();
clamp_scroll();
@@ -354,6 +355,10 @@ static bool is_connected(const uint8_t* addr) {
return false;
}
static bool is_audio_ready() {
return montauk::audio_bt_status(-1) >= 2;
}
// ============================================================================
// Format helpers
// ============================================================================
@@ -565,8 +570,14 @@ static bool handle_click(int mx, int my) {
if (!row.contains(mx, my)) continue;
Rect action = row_action_button_rect(row);
Rect retry = row_forget_button_rect(row);
bool connected = is_connected(g_scan[i].bdAddr);
if (connected && !is_audio_ready() && retry.contains(mx, my)) {
do_connect(g_scan[i].bdAddr);
return true;
}
if (action.contains(mx, my)) {
if (is_connected(g_scan[i].bdAddr))
if (connected)
do_disconnect(g_scan[i].bdAddr);
else
do_connect(g_scan[i].bdAddr);
@@ -580,6 +591,11 @@ static bool handle_click(int mx, int my) {
Rect action = row_action_button_rect(row);
if (g_devices[i].connected) {
Rect retry = row_forget_button_rect(row);
if (!is_audio_ready() && retry.contains(mx, my)) {
do_connect(g_devices[i].bdAddr);
return true;
}
if (action.contains(mx, my)) {
do_disconnect(g_devices[i].bdAddr);
return true;
@@ -672,6 +688,7 @@ static bool handle_adapter_key(const montauk::abi::KeyEvent& key) {
static void render_devices_tab(Canvas& canvas, const mtk::Theme& theme) {
Rect list = {0, devices_list_top(), g_win_w, gui_max(devices_list_bottom() - devices_list_top(), 0)};
int fh = system_font_height();
bool bt_audio_ready = is_audio_ready();
if (g_device_count == 0) {
draw_centered_text(canvas, list.y, list.h, "No paired devices", theme.text_subtle);
@@ -688,15 +705,17 @@ static void render_devices_tab(Canvas& canvas, const mtk::Theme& theme) {
mtk::draw_list_row(canvas, row, false, (i & 1) != 0, theme);
bool connected = g_devices[i].connected;
bool audio_ready = !connected || bt_audio_ready;
Color dot_color = connected ? GREEN : theme.text_subtle;
fill_circle(canvas, PAD + 6, row.y + ROW_H / 2, 5, dot_color);
Rect action = row_action_button_rect(row);
Rect forget = row_forget_button_rect(row);
int text_x = PAD + 20;
// Connected rows have one button (Disconnect); paired rows have two
// (Connect + Forget), so the text must stop before the leftmost button.
int text_w_max = (connected ? action.x : forget.x) - text_x - 10;
// A connected row whose media path failed exposes Retry + Disconnect;
// otherwise connected rows need only Disconnect.
int text_w_max = (connected && audio_ready ? action.x : forget.x)
- text_x - 10;
draw_text_fit(canvas, text_x, row.y + 8, g_device_names[i], text_w_max, theme.text);
char addr_str[24];
@@ -704,6 +723,10 @@ static void render_devices_tab(Canvas& canvas, const mtk::Theme& theme) {
draw_text_fit(canvas, text_x, row.y + 8 + fh + 2, addr_str, text_w_max, theme.text_subtle);
if (connected) {
if (!audio_ready) {
mtk::draw_button(canvas, forget, "Retry", mtk::BUTTON_PRIMARY,
button_state(forget, true), theme);
}
mtk::draw_button(canvas, action, "Disconnect", mtk::BUTTON_DANGER,
button_state(action, true), theme);
} else {
@@ -721,6 +744,7 @@ static void render_scan_tab(Canvas& canvas, const mtk::Theme& theme) {
Rect scan_btn = scan_button_rect();
Rect list = {0, scan_list_top(), g_win_w, gui_max(scan_list_bottom() - scan_list_top(), 0)};
int fh = system_font_height();
bool bt_audio_ready = is_audio_ready();
if (g_scanning) {
mtk::draw_button(canvas, scan_btn, "Scanning...", mtk::BUTTON_SECONDARY,
@@ -747,8 +771,12 @@ static void render_scan_tab(Canvas& canvas, const mtk::Theme& theme) {
fill_circle(canvas, PAD + 6, row.y + ROW_H / 2, 5, theme.accent);
Rect action = row_action_button_rect(row);
Rect retry = row_forget_button_rect(row);
int text_x = PAD + 20;
int text_w_max = action.x - text_x - 10;
bool conn = is_connected(g_scan[i].bdAddr);
bool audio_ready = !conn || bt_audio_ready;
int text_w_max = (conn && !audio_ready ? retry.x : action.x)
- text_x - 10;
const char* display_name = g_scan[i].name[0] ? g_scan[i].name : "Unknown Device";
draw_text_fit(canvas, text_x, row.y + 4, display_name, text_w_max, theme.text);
@@ -760,7 +788,10 @@ static void render_scan_tab(Canvas& canvas, const mtk::Theme& theme) {
device_class_str(g_scan[i].classOfDevice), addr_str, rssi_bar(g_scan[i].rssi));
draw_text_fit(canvas, text_x, row.y + 4 + fh + 2, detail, text_w_max, theme.text_subtle);
bool conn = is_connected(g_scan[i].bdAddr);
if (conn && !audio_ready) {
mtk::draw_button(canvas, retry, "Retry", mtk::BUTTON_PRIMARY,
button_state(retry, true), theme);
}
mtk::draw_button(canvas, action, conn ? "Disconnect" : "Connect",
conn ? mtk::BUTTON_DANGER : mtk::BUTTON_PRIMARY,
button_state(action, true), theme);