syntax = "proto3"; package musicfs.v1; option go_package = "homelab.lan/music-agregator/gen/musicfs/v1;musicfsv1"; service MusicFS { rpc Search(SearchRequest) returns (SearchResponse); rpc SearchStream(SearchRequest) returns (stream SearchResult); rpc GetStatus(Empty) returns (StatusResponse); rpc Shutdown(ShutdownRequest) returns (Empty); rpc GetCacheStats(Empty) returns (CacheStats); rpc ClearCache(ClearCacheRequest) returns (ClearCacheResponse); rpc Prefetch(PrefetchRequest) returns (stream PrefetchProgress); rpc ListOrigins(Empty) returns (OriginsResponse); rpc GetOriginHealth(OriginRequest) returns (OriginHealthResponse); rpc RescanOrigin(OriginRequest) returns (stream SyncProgress); rpc SubscribeEvents(EventFilter) returns (stream Event); } service MetadataService { rpc GetMetadata(GetMetadataRequest) returns (MetadataResponse); rpc UpdateMetadata(UpdateMetadataRequest) returns (UpdateMetadataResponse); rpc ClearOverlay(ClearOverlayRequest) returns (ClearOverlayResponse); rpc BatchUpdateMetadata(BatchUpdateRequest) returns (stream BatchUpdateProgress); rpc ImportMetadata(ImportMetadataRequest) returns (stream ImportProgress); } message Empty {} message SearchRequest { string query = 1; optional uint32 limit = 2; optional uint32 offset = 3; optional string origin_id = 4; } message SearchResponse { repeated SearchResult results = 1; uint64 total_matches = 2; uint32 query_time_ms = 3; } message SearchResult { int64 file_id = 1; string virtual_path = 2; optional string artist = 3; optional string album = 4; optional string title = 5; float score = 6; map highlights = 7; } enum MountState { MOUNT_UNKNOWN = 0; MOUNT_MOUNTING = 1; MOUNT_READY = 2; MOUNT_SYNCING = 3; MOUNT_DEGRADED = 4; MOUNT_UNMOUNTING = 5; } message StatusResponse { string version = 1; uint64 uptime_secs = 2; string mount_point = 3; MountState state = 4; uint32 open_file_handles = 5; uint64 fuse_ops_total = 6; uint64 files_indexed = 7; uint64 cache_size_bytes = 8; repeated OriginStatus origins = 9; } message OriginStatus { string id = 1; string origin_type = 2; HealthStatus health = 3; uint64 files_count = 4; } enum HealthStatus { HEALTH_UNKNOWN = 0; HEALTH_HEALTHY = 1; HEALTH_DEGRADED = 2; HEALTH_UNHEALTHY = 3; } message ShutdownRequest { bool graceful = 1; uint32 timeout_secs = 2; } message TierStats { uint64 entries = 1; uint64 size_bytes = 2; uint64 hits = 3; uint64 misses = 4; } message CacheStats { uint64 total_size_bytes = 1; uint64 used_size_bytes = 2; uint64 size_limit_bytes = 3; uint64 chunk_count = 4; uint64 chunks_unique = 5; double dedup_ratio = 6; uint64 hit_count = 7; uint64 miss_count = 8; double hit_ratio = 9; uint64 metadata_entries = 10; uint64 metadata_bytes = 11; TierStats l1_metadata = 12; TierStats l2_headers = 13; TierStats l3_chunks = 14; } message ClearCacheRequest { optional string origin_id = 1; bool clear_metadata = 2; bool clear_chunks = 3; } message ClearCacheResponse { uint64 bytes_cleared = 1; uint64 chunks_cleared = 2; } message PrefetchRequest { repeated string paths = 1; optional string origin_id = 2; } message PrefetchProgress { string current_path = 1; uint32 completed = 2; uint32 total = 3; uint64 bytes_fetched = 4; } message OriginsResponse { repeated OriginInfo origins = 1; } message OriginInfo { string id = 1; string origin_type = 2; string display_name = 3; string root_path = 4; HealthStatus health = 5; uint64 files_count = 6; uint64 total_size_bytes = 7; } message OriginRequest { string origin_id = 1; // Optional subdirectory to scope the scan (relative to origin root). // If empty, scans the entire origin. // Example: "Metallica - Master of Puppets (1986) [FLAC]" optional string subdir = 2; } message OriginHealthResponse { string origin_id = 1; HealthStatus status = 2; optional string message = 3; uint64 last_check_secs = 4; } message SyncProgress { string phase = 1; uint32 current = 2; uint32 total = 3; string current_path = 4; uint64 bytes_synced = 5; repeated SyncedFile new_files = 6; } message SyncedFile { string path = 1; int64 file_id = 2; string virtual_path = 3; } message EventFilter { repeated string event_types = 1; optional string origin_id = 2; } message Event { string event_type = 1; int64 timestamp_ms = 2; optional string origin_id = 3; optional string path = 4; optional int64 file_id = 5; map metadata = 6; } // MetadataService messages message GetMetadataRequest { string virtual_path = 1; } message MetadataResponse { int64 file_id = 1; optional string title = 2; optional string artist = 3; optional string album = 4; optional string album_artist = 5; optional uint32 year = 6; optional uint32 track = 7; optional uint32 disc = 8; optional string genre = 9; optional string format = 10; optional uint64 duration_ms = 11; optional uint64 bitrate = 12; optional uint32 track_total = 13; optional uint32 disc_total = 14; optional string date = 15; optional string composer = 16; optional string comment = 17; optional string lyrics = 18; optional string copyright = 19; optional bool compilation = 20; optional string artist_sort = 21; optional string album_artist_sort = 22; optional string album_sort = 23; optional string title_sort = 24; optional string mb_recording_id = 25; optional string mb_album_id = 26; optional string mb_artist_id = 27; optional string mb_album_artist_id = 28; optional string mb_release_group_id = 29; optional float replaygain_track_gain = 30; optional float replaygain_track_peak = 31; optional float replaygain_album_gain = 32; optional float replaygain_album_peak = 33; optional uint32 channels = 34; optional uint32 bits_per_sample = 35; optional string encoder = 36; optional string label = 40; optional string album_type = 41; optional string cover_url = 42; map custom_tags = 50; } message UpdateMetadataRequest { int64 file_id = 1; optional string title = 2; optional string artist = 3; optional string album = 4; optional string album_artist = 5; optional uint32 track_number = 6; optional uint32 disc_number = 7; optional string date = 8; optional string genre = 9; optional string composer = 10; optional string comment = 11; optional string lyrics = 12; optional string copyright = 13; optional bool compilation = 14; optional string artist_sort = 15; optional string album_artist_sort = 16; optional string album_sort = 17; optional string title_sort = 18; optional string mb_recording_id = 20; optional string mb_album_id = 21; optional string mb_artist_id = 22; optional float replaygain_track_gain = 30; optional float replaygain_track_peak = 31; optional float replaygain_album_gain = 32; optional float replaygain_album_peak = 33; optional string label = 40; optional string album_type = 41; optional string cover_url = 42; map custom_tags = 50; } message UpdateMetadataResponse { int64 file_id = 1; bool success = 2; optional string error_message = 3; } message ClearOverlayRequest { int64 file_id = 1; } message ClearOverlayResponse { int64 file_id = 1; bool success = 2; optional string error_message = 3; } message BatchUpdateRequest { repeated BatchUpdateItem items = 1; } message BatchUpdateItem { int64 file_id = 1; UpdateMetadataRequest metadata = 2; } message BatchUpdateProgress { uint32 completed = 1; uint32 total = 2; optional int64 current_file_id = 3; optional string error_message = 4; } message ImportMetadataRequest { string source_path = 1; optional string format = 2; } message ImportProgress { uint32 imported = 1; uint32 total = 2; optional string current_file = 3; optional string error_message = 4; }