fix: improve Bluetooth reliability
This commit is contained in:
@@ -258,7 +258,7 @@ namespace montauk::abi {
|
||||
static constexpr int AUDIO_CTL_PAUSE = 3;
|
||||
static constexpr int AUDIO_CTL_GET_OUTPUT = 4; // 0=HDA, 1=Bluetooth
|
||||
static constexpr int AUDIO_CTL_SET_OUTPUT = 5; // Switch audio output
|
||||
static constexpr int AUDIO_CTL_BT_STATUS = 6; // Get Bluetooth status
|
||||
static constexpr int AUDIO_CTL_BT_STATUS = 6; // 0=unavailable, 1=setup, 2=ready
|
||||
static constexpr int AUDIO_CTL_SET_MASTER_VOLUME = 7; // 0-100
|
||||
static constexpr int AUDIO_CTL_GET_MASTER_VOLUME = 8;
|
||||
static constexpr int AUDIO_CTL_SET_MUTE = 9; // 0/1, per-stream
|
||||
|
||||
@@ -550,7 +550,7 @@
|
||||
audio_get_output AUDIO_CTL_GET_OUTPUT (4): 0=HDA, 1=Bluetooth
|
||||
audio_set_output AUDIO_CTL_SET_OUTPUT (5): switch all streams
|
||||
(SET_OUTPUT, 5) switch a stream's output route
|
||||
audio_bt_status AUDIO_CTL_BT_STATUS (6)
|
||||
audio_bt_status AUDIO_CTL_BT_STATUS (6): 0=unavailable, 1=setup, 2=ready
|
||||
audio_set_master_volume, _get_ AUDIO_CTL_{SET,GET}_MASTER_VOLUME (7/8), 0-100
|
||||
audio_set_mute, audio_get_mute AUDIO_CTL_{SET,GET}_MUTE (9/10), per-stream
|
||||
audio_set_master_mute, _get_ AUDIO_CTL_{SET,GET}_MASTER_MUTE (11/12)
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user