diff --git a/Startup/shell.qml b/Startup/shell.qml index 7c42564..0319ce6 100644 --- a/Startup/shell.qml +++ b/Startup/shell.qml @@ -29,27 +29,19 @@ PanelWindow { property bool waitingForBluetooth: true property bool animationLaunchScheduled: false property bool animationStarted: false + property bool bluetoothConnectRequested: false function bluetoothModelCount() { - if (!Bluetooth.devices) - return 0; - if (typeof Bluetooth.devices.count === "function") - return Bluetooth.devices.count(); - if (Bluetooth.devices.count !== undefined) - return Bluetooth.devices.count; - if (Bluetooth.devices.length !== undefined) - return Bluetooth.devices.length; + if (bluetoothDeviceRepeater) + return bluetoothDeviceRepeater.count; return 0; } - function bluetoothModelGet(index) { - if (!Bluetooth.devices || index < 0 || index >= bluetoothModelCount()) + function bluetoothDeviceAt(index) { + const item = bluetoothDeviceRepeater.itemAt(index); + if (!item) return null; - if (Bluetooth.devices.get) - return Bluetooth.devices.get(index); - if (Bluetooth.devices.length !== undefined) - return Bluetooth.devices[index]; - return null; + return item.device || null; } function bluetoothDeviceName(device) { @@ -64,14 +56,46 @@ PanelWindow { function findTargetBluetoothDevice() { for (var i = 0; i < bluetoothModelCount(); i++) { - var device = bluetoothModelGet(i); - if (bluetoothDeviceName(device) === bluetoothTargetName) + var device = bluetoothDeviceAt(i); + var deviceName = bluetoothDeviceName(device); + console.log("Startup BT: candidate", i, deviceName, device ? Boolean(device.connected) : false); + if (deviceName === bluetoothTargetName) return device; } + console.log("Startup BT: target not found", bluetoothTargetName, "count", bluetoothModelCount()); return null; } + function maybeStartBluetoothOrSkip() { + console.log("Startup BT: maybeStartBluetoothOrSkip", "waiting", waitingForBluetooth, "requested", bluetoothConnectRequested); + if (!waitingForBluetooth) + return; + + const device = findTargetBluetoothDevice(); + if (!device) { + console.log("Startup BT: no matching device yet"); + return; + } + + console.log("Startup BT: matched device", bluetoothDeviceName(device), "connected", Boolean(device.connected)); + + if (device.connected) { + console.log("Startup BT: already connected, starting animation"); + beginAnimation(); + return; + } + + if (!bluetoothConnectRequested) { + bluetoothConnectRequested = true; + console.log("Startup BT: requesting connect", bluetoothDeviceName(device)); + device.connect(); + } else { + console.log("Startup BT: connect already requested, waiting"); + } + } + function beginAnimation() { + console.log("Startup: beginAnimation", "started", animationStarted, "scheduled", animationLaunchScheduled); if (animationStarted || animationLaunchScheduled) return; waitingForBluetooth = false; @@ -82,6 +106,7 @@ PanelWindow { } function handlePrimaryAction() { + console.log("Startup: handlePrimaryAction", "animationStarted", animationStarted, "waitingForBluetooth", waitingForBluetooth); if (!animationStarted) beginAnimation(); else @@ -89,6 +114,7 @@ PanelWindow { } function finishStartup() { + console.log("Startup: finishStartup", "playbackState", player.playbackState); if (player.playbackState !== MediaPlayer.StoppedState) player.stop(); else @@ -100,6 +126,11 @@ PanelWindow { windows: [overlay] } + Component.onCompleted: { + console.log("Startup: overlay completed", "btCount", bluetoothModelCount(), "target", bluetoothTargetName); + maybeStartBluetoothOrSkip(); + } + FocusScope { id: overlayFocus anchors.fill: parent @@ -128,18 +159,76 @@ PanelWindow { ignoreUnknownSignals: true function onCountChanged() { - if (overlay.waitingForBluetooth) - bluetoothRetryTimer.restart(); + if (overlay.waitingForBluetooth) { + console.log("Startup BT: devices count changed", overlay.bluetoothModelCount(), "repeater", bluetoothDeviceRepeater.count); + overlay.bluetoothConnectRequested = false; + overlay.maybeStartBluetoothOrSkip(); + } } function onModelReset() { - if (overlay.waitingForBluetooth) - bluetoothRetryTimer.restart(); + if (overlay.waitingForBluetooth) { + console.log("Startup BT: devices model reset"); + overlay.bluetoothConnectRequested = false; + overlay.maybeStartBluetoothOrSkip(); + } } function onRowsInserted() { - if (overlay.waitingForBluetooth) - bluetoothRetryTimer.restart(); + if (overlay.waitingForBluetooth) { + console.log("Startup BT: device rows inserted"); + overlay.bluetoothConnectRequested = false; + overlay.maybeStartBluetoothOrSkip(); + } + } + + function onRowsRemoved() { + if (overlay.waitingForBluetooth) { + console.log("Startup BT: device rows removed"); + overlay.bluetoothConnectRequested = false; + overlay.maybeStartBluetoothOrSkip(); + } + } + } + + Repeater { + id: bluetoothDeviceRepeater + model: Bluetooth.devices + + delegate: Item { + property var device: modelData + + Component.onCompleted: { + console.log("Startup BT: delegate ready", index, overlay.bluetoothDeviceName(device), Boolean(device ? device.connected : false), "repeaterCount", bluetoothDeviceRepeater.count); + overlay.maybeStartBluetoothOrSkip(); + } + + Connections { + target: device + ignoreUnknownSignals: true + + function onConnectedChanged() { + console.log("Startup BT: connected changed", overlay.bluetoothDeviceName(device), Boolean(device ? device.connected : false)); + if (overlay.waitingForBluetooth) + overlay.maybeStartBluetoothOrSkip(); + } + + function onNameChanged() { + if (overlay.waitingForBluetooth) { + console.log("Startup BT: name changed", overlay.bluetoothDeviceName(device)); + overlay.bluetoothConnectRequested = false; + overlay.maybeStartBluetoothOrSkip(); + } + } + + function onDeviceNameChanged() { + if (overlay.waitingForBluetooth) { + console.log("Startup BT: deviceName changed", overlay.bluetoothDeviceName(device)); + overlay.bluetoothConnectRequested = false; + overlay.maybeStartBluetoothOrSkip(); + } + } + } } } @@ -151,6 +240,7 @@ PanelWindow { playbackRate: 1 audioOutput: AudioOutput {} onPlaybackStateChanged: a => { + console.log("Startup: playback state changed", player.playbackState); if (player.playbackState === MediaPlayer.StoppedState) overlay.finishStartup(); } @@ -161,6 +251,7 @@ PanelWindow { interval: 1000 repeat: false onTriggered: { + console.log("Startup: startup delay elapsed, playing video"); overlay.animationLaunchScheduled = false; overlay.animationStarted = true; player.play(); @@ -174,20 +265,13 @@ PanelWindow { repeat: true onTriggered: { if (!overlay.waitingForBluetooth) { + console.log("Startup BT: retry timer stopping"); stop(); return; } - - const device = overlay.findTargetBluetoothDevice(); - if (!device) - return; - - if (device.connected) { - overlay.beginAnimation(); - return; - } - - device.connect(); + console.log("Startup BT: retry timer fired"); + overlay.bluetoothConnectRequested = false; + overlay.maybeStartBluetoothOrSkip(); } } @@ -196,7 +280,10 @@ PanelWindow { interval: overlay.bluetoothTimeoutMs running: true repeat: false - onTriggered: overlay.beginAnimation() + onTriggered: { + console.log("Startup BT: timeout reached", overlay.bluetoothTimeoutMs); + overlay.beginAnimation(); + } } VideoOutput { @@ -204,28 +291,16 @@ PanelWindow { anchors.fill: parent } - Text { - visible: overlay.waitingForBluetooth - anchors.horizontalCenter: parent.horizontalCenter - anchors.verticalCenter: parent.verticalCenter - color: "#ffffff" - font.family: "Determination Mono" - font.pixelSize: 28 - text: "CONNECTING TO " + overlay.bluetoothTargetName.toUpperCase() - z: 1 - } - - Text { - visible: !overlay.animationStarted - anchors.horizontalCenter: parent.horizontalCenter - anchors.bottom: parent.bottom - anchors.bottomMargin: 56 - color: "#ffffff" - font.family: "Determination Mono" - font.pixelSize: 28 - text: overlay.waitingForBluetooth ? "PRESS Z OR ENTER TO SKIP WAIT" : "STARTING..." - z: 1 - } + // Text { + // visible: overlay.waitingForBluetooth + // anchors.horizontalCenter: parent.horizontalCenter + // anchors.verticalCenter: parent.verticalCenter + // color: "#ffffff" + // font.family: "Determination Mono" + // font.pixelSize: 28 + // text: "CONNECTING TO " + overlay.bluetoothTargetName.toUpperCase() + // z: 1 + // } MouseArea { anchors.fill: parent