-
Notifications
You must be signed in to change notification settings - Fork 0
UI Daemon Bridge
Relevant source files
The following files were used as context for generating this wiki page:
The interface.rs file serves as the central nervous system of the aurora-player application. It manages the lifecycle of the connection to aurora-daemon, handles asynchronous IPC communication via Unix sockets, and bridges the Rust backend state with the Slint UI event loop.
The primary entry point is the interface() function. This function establishes a connection to the daemon and initializes the shared state used by the frontend.
The bridge attempts to connect to the Unix socket defined by aurora_protocol::SOCKFILE. If the daemon is not reachable, the bridge enters a retry loop, attempting to reconnect every 1 second app/src/interface.rs:328-341. If the connection is lost during operation, the UI is notified via aurora.set_disconnected(true) app/src/interface.rs:356-358.
Before starting the communication tasks, the bridge initializes the StateStruct. This struct holds the local cache of the library, search results, and UI selection states app/src/types/mod.rs:10-26.
State Initialization Steps:
-
Default Art: Loads the fallback album art into a
SharedPixelBufferapp/src/interface.rs:343-345. -
MPSC Channel: Creates a
tokio::sync::mpscchannel for sendingRequestvariants from UI callbacks to theunix_sendertask app/src/interface.rs:347. -
State Wrapping: Wraps the
StateStructin anArc<Mutex<...>>(aliased asState) for thread-safe access app/src/interface.rs:348-366.
Sources: app/src/interface.rs:328-366, app/src/types/mod.rs:9-26
The bridge utilizes two dedicated asynchronous tasks to handle full-duplex communication over the Unix socket.
This diagram illustrates how a UI interaction (like clicking play) travels through the bridge to the daemon and back.
graph TD
subgraph "Slint UI Thread"
[UI_Callback] --> |"tx.send(Request)"| MPSC_Channel["mpsc::Receiver<Request>"]
[UI_Component] -.-> |"Reactive Binding"| Slint_Properties["Slint Properties (e.g., set_Title)"]
end
subgraph "Async Bridge Tasks (interface.rs)"
MPSC_Channel --> unix_sender["unix_sender (Task)"]
unix_sender --> |"JSON + Length Prefix"| UnixSocket_Write["UnixStream (Write Half)"]
UnixSocket_Read["UnixStream (Read Half)"] --> unix_recver["unix_recver (Task)"]
unix_recver --> |"Response Dispatch"| Response_Logic["Response Handling Logic"]
Response_Logic --> |"upgrade_in_event_loop"| Slint_Properties
end
subgraph "aurora-daemon"
UnixSocket_Write -.-> Daemon_Process["Daemon Request Handler"]
Daemon_Process -.-> UnixSocket_Read
end
Sources: app/src/interface.rs:40-72, app/src/interface.rs:114-156
The unix_sender task waits for Request enums on the MPSC receiver. When a request arrives, it:
- Serializes the
Requestto JSON usingserde_jsonapp/src/interface.rs:44. - Prepends a 4-byte big-endian length prefix app/src/interface.rs:45-46.
- Writes the buffer to the
OwnedWriteHalfof the Unix socket app/src/interface.rs:47.
The unix_recver task continuously listens for data from the daemon. It:
- Reads the 4-byte length header app/src/interface.rs:64-66.
- Reads the exact number of bytes specified by the header into a buffer app/src/interface.rs:68-69.
- Deserializes the buffer into a
Responseenum app/src/interface.rs:70. - Dispatches the response to the appropriate handler logic app/src/interface.rs:72-230.
Sources: app/src/interface.rs:40-72
When unix_recver receives a Response, it updates the local StateStruct and schedules UI updates on the Slint event loop.
| Response Variant | Action Taken |
|---|---|
Status |
Updates playback state (position, volume, shuffle, repeat) and triggers the Album Art Pipeline. |
Queue |
Updates state.queue and calls state.update_queue(app) to redraw the queue view app/src/interface.rs:158-163. |
SearchResults |
Updates search results or artist-specific song lists based on the pending_artist_search flag app/src/interface.rs:164-175. |
PlaylistResults |
Updates the currently viewed playlist songs app/src/interface.rs:177-184. |
Theme |
Converts hex strings to slint::Color and updates the global Theme singleton app/src/interface.rs:213-230. |
To prevent UI stuttering, album art is processed on the async thread before being sent to the UI:
-
Check Change: The bridge compares the new
art_pathwithstate.current_art_pathapp/src/interface.rs:86. -
Async Load: If changed, it reads the file from disk and decodes it into a
SharedPixelBufferusingalbum_art_from_dataapp/src/interface.rs:103-112. -
UI Update: The buffer is passed into
aurora.set_AlbumArt(Image::from_rgba8(buf))inside the Slint event loop app/src/interface.rs:153.
Sources: app/src/interface.rs:73-156, app/src/interface.rs:30-38, app/src/types/helpers.rs:15-43
The bridge registers numerous callbacks that allow the Slint UI to communicate back to the Rust backend. These are defined in the interface() function after the socket connection is established.
This diagram maps Slint UI callback names to the internal Request variants they generate.
classDiagram
class Slint_AuroraPlayer {
<<Global Component>>
+callback play_pause()
+callback skip_next()
+callback seek(ms)
+callback search(query)
+callback add_to_playlist(song_id, playlist_id)
+callback toggle_selected(song_id)
}
class Request_Enum {
<<aurora_protocol>>
+Pause
+Next
+Seek(Duration)
+Search(String, SearchType)
+Playlist(PlaylistCommand)
}
Slint_AuroraPlayer --|> Request_Enum : Triggers via unix_sender
Sources: app/src/interface.rs:373-610, aurora-protocol/src/lib.rs:Request
-
Simple Commands: Callbacks like
play_pauseorskip_nextsimply clone thewriter_txand send the correspondingRequestapp/src/interface.rs:373-383. -
Multi-Selection: The
toggle_selectedcallback modifies aHashSetin theStateStruct. This set is used by helper functions (e.g.,update_search_results) to mark songs as selected in the UI app/src/interface.rs:458-472. -
Complex Actions: The
play_selectedcallback retrieves all IDs from theselected_song_idsset, sends aRequest::Enqueuefor the batch, and then clears the selection app/src/interface.rs:474-490.
Sources: app/src/interface.rs:373-500, app/src/types/helpers.rs:72-98
The bridge handles two main failure modes:
-
Initial Connection Failure: The
interface()function loops indefinitely, printing "Retrying..." until the daemon is started app/src/interface.rs:336-340. -
Runtime Disconnection: If
unix_recverorunix_senderencounter an IO error (e.g., the daemon crashes), thetokio::select!block ininterface()terminates. The code then sets the UIdisconnectedproperty totrueand attempts to restart the entireinterface()loop app/src/interface.rs:356-364.
Sources: app/src/interface.rs:330-366
Overview
aurora-daemon
- Background Service
- Startup & State Init
- Request Handlers & Dispatch
- Playback Engine & Audio
- Library Indexing & Watching
- Playlists, Liked & History
- Background Threads
aurora-protocol
aurora-player
Reference