Files
MusicFS/proto/musicfs.proto
T
2026-06-30 12:17:48 +02:00

104 lines
2.8 KiB
Protocol Buffer

syntax = "proto3";
package musicfs;
// MusicFs service exposes a server-side music library to a remote musicfs
// FUSE mount.
service MusicFs {
// Hash-based reconciliation. Client sends the (inode, hash) pairs it
// currently has; server responds with the subset that changed (new or
// hash-different) plus the inodes the client has but the server no longer
// has. Cheap on the wire — no file metadata crosses until the client asks.
rpc Reconcile(ReconcileRequest) returns (ReconcileResponse);
// Fetch full metadata for a specific set of inodes. Called after Reconcile
// returns a non-empty `changed` list, for just those inodes.
rpc GetMetadata(GetMetadataRequest) returns (stream ManifestEntry);
// Stream every file entry in the library. Convenience RPC for first-run
// bootstrapping or full-refresh. The diff-based Reconcile path is the
// normal case.
rpc GetManifest(GetManifestRequest) returns (stream ManifestEntry);
// Stream the bytes of one file. If `start` and `length` are both zero the
// server streams the entire file; otherwise just the requested range. The
// first chunk carries `total_size` and `offset`; subsequent chunks continue
// from there.
rpc GetFile(GetFileRequest) returns (stream FileChunk);
// Long-lived stream of filesystem change events. The client uses these as
// wake-ups to refetch the manifest; correctness always rests on the hash
// diff, never on the event payload.
rpc SubscribeEvents(SubscribeEventsRequest) returns (stream ChangeEvent);
}
message ReconcileRequest {
repeated InodeHash entries = 1;
}
message ReconcileResponse {
repeated InodeHash changed = 1;
repeated uint64 deleted = 2;
}
message InodeHash {
uint64 inode = 1;
uint64 hash = 2;
}
message GetMetadataRequest {
repeated uint64 inodes = 1;
}
message GetManifestRequest {}
message GetFileRequest {
uint64 id = 1;
// When both are zero the server streams the entire file.
uint64 start = 2;
uint64 length = 3;
}
message SubscribeEventsRequest {}
message ManifestEntry {
uint64 id = 1;
string rel_path = 2;
uint64 size = 3;
uint64 mtime = 4;
uint64 ctime = 5;
uint64 crtime = 6;
MusicMetadata music_metadata = 7;
}
message MusicMetadata {
repeated string artist = 1;
optional string album_artist = 2;
string album = 3;
int32 track_number = 4;
string track_title = 5;
repeated string other_tags = 6;
bytes header = 7;
repeated bytes picture_block_headers = 8;
repeated PictureDataRange picture_data_ranges = 9;
uint64 real_audio_start = 10;
uint64 vorbis_comment_offset = 11;
uint64 vorbis_comment_length = 12;
}
message PictureDataRange {
uint64 offset = 1;
uint64 length = 2;
}
message FileChunk {
bytes data = 1;
uint64 offset = 2;
uint64 total_size = 3;
}
message ChangeEvent {
// "create", "modify", or "remove".
string kind = 1;
}