Commit Graph
25 Commits
Author SHA1 Message Date
vicrodh b4c3bab91b fix(qconnect): WS-authoritative shuffle/repeat gating, button reflection, pause-to-iOS
Shuffle and Repeat now go to the CLOUD whenever connected (renderer OR controller),
gating on transport_connected like Tauri's v2_toggle_shuffle / v2_set_repeat_mode,
instead of the old peer-active gate that fell through to a LOCAL reshuffle when QBZ
was the active renderer — that did nothing visible AND risked a divergent local
order. QBZ sends only the seed + pivot; the cloud owns the order; the toggle reads
the cloud-authoritative queue.shuffle_mode. The local shuffle path is now reachable
only when NOT connected.

- shuffle/repeat button reflects the cloud queue flag (queue.shuffle_mode for the
  controller branch, core queue state via refresh_transport_modes for the renderer
  branch), not the per-renderer field the cloud never populates for a peer — fixes
  the iOS-reflects / WebPlayer-doesn't asymmetry.
- pause/play to a peer renderer: send a BARE SetPlayerState (playing_state only).
  iOS reports current_queue_item_id=null while playing, so resolving the qid landed
  on queue_item_id 0 — the protocol's "unknown" placeholder — and iOS could not
  anchor the pause, auto-resuming. A bare transport toggle is spec-sanctioned: the
  renderer pauses/resumes its own current item in place.
- skip_serializing_if on the SetPlayerState request structs so a None field is
  OMITTED, not serialized as null; and the mapper now treats a null current_queue_item
  as absent. Without this the bare command failed to encode and was never sent.
- log the outbound SetPlayerState payload for controller diagnostics.

cc
2026-06-05 17:44:11 -06:00
vicrodh 03a551e6ff feat(qconnect): real duration/queue_item_ids in join report + DeviceAudioQualityChanged(27)
Add the RndrSrvrDeviceAudioQualityChanged(27) renderer report end to end:
the report-type variant + message string in qconnect-protocol renderer.rs,
the RendererDeviceAudioQualityChangedMessage proto struct plus the genuinely
free tag-27 field on QConnectMessage (26=file AQ, 28=max AQ), and the mapper
arm. Wire the adapter emitter report_device_audio_quality_if_changed (deduped
via a new last_reported_device_audio_quality sync-state field) next to the
file-AQ report, sourcing the real output stream config. Fix the deferred-join
StateUpdated report to resolve the real current track duration (via CoreBridge)
and current/next queue_item_ids instead of hardcoding nulls.

cc
2026-06-01 04:29:18 -06:00
vicrodh fea9dbe1d4 feat(qconnect-app): emit PlaybackError app event from renderer failure
Decodes PlaybackErrorMessage off the InboundPayloadBytes batch and emits a
PlaybackError app event; the Tauri event sink forwards it to qconnect:event
via its existing catch-all emit.

cc
2026-06-01 03:23:03 -06:00
vicrodh d865097a4c feat(qconnect-protocol): decode PlaybackErrorMessage + ErrorType
Models the renderer per-track failure (TRACK_NOT_STREAMABLE/NETWORK_ERROR/...).
Envelope-vs-batch placement verified against transport bytes: the decoder
receives the batch QConnectMessages (CloudPayload.payload tag 7), and the
official Message record carries playback_error at tag 3, so the field is
attached to QConnectMessage inside messages[], NOT to the batch wrapper.

cc
2026-06-01 03:20:09 -06:00
vicrodh 3ac68e788a feat(qconnect): surface server queue_hash onto queue state
Decoder now reads field #100 (previously decoded-then-dropped) on QueueState
and carries it through to QConnectQueueState.last_server_queue_hash via the
QueueStateReplaced reducer path (full-state replace already clones it).

cc
2026-06-01 03:16:16 -06:00
victorrhgap 016b0f6166 chore: remove unused required_i32_to_u64 function
cc
2026-03-31 11:09:32 -06:00
victorrhgap 235bd08e2c fix(qconnect): tolerate missing queue_version major/minor fields
Qobuz changed their protocol to sometimes send QueueVersionRef
without major/minor populated. Our decoder treated these as
required fields, causing all cloud_type=6 messages to fail with
"missing required numeric field 'queue_version.major'".

Default to 0 when absent — matches the dev panel behavior.

cc
2026-03-24 21:14:44 -06:00
vicrodh de29f1e2e0 chore(qconnect): checkpoint current poc state
cx
2026-03-13 17:28:05 -06:00
vicrodh c83aedac75 fix(qconnect): align renderer state with official queue semantics
cx
2026-03-12 23:10:31 -06:00
vicrodh e748ab6616 fix(qconnect): treat omitted cloud queue ids as zero
cx
2026-03-12 20:56:56 -06:00
vicrodh d3c2d4c6ca fix(qconnect): align queue load payload and inbound diagnostics
cx
2026-03-12 19:31:27 -06:00
vicrodh 441b74ac91 test(qconnect): lock seekbar workaround behavior
cx
2026-03-12 15:32:49 -06:00
vicrodh f6506cd4ea fix: break infinite feedback loop in renderer state reports
The server echoes every RNDR_SRVR_STATE_UPDATED as a SET_STATE command
with only next_track updated (playing_state=null, current_track=null).
send_renderer_reports was replying to these echo SET_STATE commands
with another state report, creating an infinite loop that generated
47k log lines (8.2MB) in seconds and completely blocked playback.

Fix: only send state reports for substantive SET_STATE commands that
carry playing_state or current_track changes. Echo commands (next_track
only) are silently consumed.

Also demote diagnostic logging from info to debug to reduce terminal
noise during normal operation.
2026-02-22 15:58:56 -06:00
vicrodh 40a2fa618e fix: omit queue_item_ids from renderer state reports to fix seekbar sync
The server rejects renderer state reports with "Current track not found
in queue nor autoplay" after QBZ-initiated queue loads, because it assigns
non-standard queue_item_ids (first track = track_id, rest = 1..N).

Omit current_queue_item_id and next_queue_item_id from all outbound
renderer reports. The server already knows the current track from
SET_STATE commands and adds the correct queue_item_id when forwarding
to controllers.

Also add info-level diagnostic logging to both report paths (periodic
frontend reports and command-response reports) and the protobuf encoder
for verifying wire content.
2026-02-22 15:18:35 -06:00
vicrodh 65f0f25203 fix(qconnect): fix queue error decode and add context_uuid to queue commands
ErrorMessage.code was defined as int32 but server sends string codes
(e.g. 'ERROR_QUEUE_INSERT_TRACKS'). Changed to string type and added
logging for queue error responses.

Added context_uuid (random UUID v4) to queue insert and add commands -
the server likely requires this to associate tracks with a context.
2026-02-22 02:45:04 -06:00
vicrodh a9121ef427 fix(qconnect): correct track_ids wire type to fixed32 packed in outbound queue commands
track_ids in QueueLoadTracks, QueueInsertTracks, QueueAddTracks, and
AutoplayLoadTracks was int32 packed=false but the server expects
fixed32 (packed by default). This silently broke all outbound queue
manipulation commands.
2026-02-21 23:12:09 -06:00
vicrodh 9e8dfd91e5 fix(qconnect): correct wire types for track_id (fixed32) and shuffle_seed (fixed32)
Server sends track_id as fixed32 (wire type 5) and shuffle_seed as
fixed32, but our structs declared them as int32 (wire type 0/varint),
causing decode failures on QueueState, TracksLoaded, and
RendererSetState messages.
2026-02-21 17:29:47 -06:00
vicrodh 4c7be7597d fix(qconnect): remove wrong inner envelope, decode QConnectBatch directly
Root cause: inner_payload from CloudPayload.payload IS a QConnectBatch
(QConnectMessages) with repeated QConnectMessage entries in field 3.

The QCloudInnerEnvelope struct incorrectly treated field 3 as opaque
bytes, keeping only the last repeated entry and losing all messages.
Additionally, QConnectMessages.messages_time was declared as uint64
(wire type 0/varint) but the server sends fixed64 (wire type 1),
causing a wire type mismatch that would fail decoding.

Changes:
- Remove QCloudInnerEnvelope struct entirely
- Pass inner_payload directly to decode_queue_server_events/decode_renderer_server_commands
- Fix messages_time from uint64 to fixed64 to match server wire format

Verified against qonductor proto definitions (QConnectBatch) used in
working POC v1 and v2 implementations.
2026-02-21 17:15:34 -06:00
vicrodh 8a9e08ad91 feat(qconnect): add session management protobuf types and outbound reporting
Add missing SRVR_CTRL session management message types (81-87, 97-101)
that were completely absent from the protobuf definitions. Without these,
prost silently discarded all session topology messages from the server.

- Add 12 new proto structs for session/renderer/volume/quality events
- Add decoder branches and map functions for all new message types
- Add SessionManagementEvent variant to bypass queue reducer
- Add v2_qconnect_report_playback_state and v2_qconnect_report_volume
- Add comprehensive logging for inbound message diagnostics
2026-02-21 15:35:55 -06:00
vicrodh b160773e50 fix(qconnect): add device capabilities, initial state, and channel subscriptions
- Add DeviceCapabilitiesMessage to protobuf (tag 7 on DeviceInfo) with
  volume_remote_control=ALLOWED, min/max audio quality
- Extend JoinSessionMessage with reason, initial_state, is_active fields
  matching Android renderer proto (tags 3-5)
- Bootstrap sends renderer JoinSession with is_active=true and initial
  RendererState (STOPPED) so other devices see QBZ immediately
- Send initial StateUpdated, VolumeChanged, MaxAudioQualityChanged
  reports after join for full renderer presence
- Default subscribe channels to 0x01,0x02,0x03 instead of empty
- Request queue state from server after bootstrap

cc
2026-02-21 15:11:25 -06:00
vicrodh 9a0bdc33cb fix(qconnect): register renderer role during connect bootstrap
cx
2026-02-21 14:22:09 -06:00
vicrodh 3e91c2f8b0 feat(qconnect-protocol): add Android controller websocket messages
cx
2026-02-21 13:04:17 -06:00
vicrodh c6bcf6296e feat(qconnect-protocol): encode renderer->server RNDR_SRVR reports
cx
2026-02-21 12:53:55 -06:00
vicrodh 0124728aa9 feat(qconnect-protocol): decode SRVR_RNDR command contracts from protobuf
-cx
2026-02-21 12:35:16 -06:00
vicrodh d1b01bbd5e feat(qconnect-protocol): implement protobuf queue command and server event contracts
-cx
2026-02-21 12:17:42 -06:00