From d52ce9508e552bffab34fcd0a9137faee265af5e Mon Sep 17 00:00:00 2001 From: Alexander Date: Wed, 1 Jul 2026 20:07:49 +0200 Subject: [PATCH] Some more --- gen/musicfs.pb.go | 3274 ++++++++++++++++++++++++++++++++ gen/musicfs_grpc.pb.go | 775 ++++++++ internal/matcher/album.go | 135 ++ internal/matcher/album_test.go | 95 + 4 files changed, 4279 insertions(+) create mode 100644 gen/musicfs.pb.go create mode 100644 gen/musicfs_grpc.pb.go create mode 100644 internal/matcher/album.go create mode 100644 internal/matcher/album_test.go diff --git a/gen/musicfs.pb.go b/gen/musicfs.pb.go new file mode 100644 index 0000000..677a490 --- /dev/null +++ b/gen/musicfs.pb.go @@ -0,0 +1,3274 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.36.11 +// protoc (unknown) +// source: musicfs.proto + +package musicfsv1 + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" + unsafe "unsafe" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type MountState int32 + +const ( + MountState_MOUNT_UNKNOWN MountState = 0 + MountState_MOUNT_MOUNTING MountState = 1 + MountState_MOUNT_READY MountState = 2 + MountState_MOUNT_SYNCING MountState = 3 + MountState_MOUNT_DEGRADED MountState = 4 + MountState_MOUNT_UNMOUNTING MountState = 5 +) + +// Enum value maps for MountState. +var ( + MountState_name = map[int32]string{ + 0: "MOUNT_UNKNOWN", + 1: "MOUNT_MOUNTING", + 2: "MOUNT_READY", + 3: "MOUNT_SYNCING", + 4: "MOUNT_DEGRADED", + 5: "MOUNT_UNMOUNTING", + } + MountState_value = map[string]int32{ + "MOUNT_UNKNOWN": 0, + "MOUNT_MOUNTING": 1, + "MOUNT_READY": 2, + "MOUNT_SYNCING": 3, + "MOUNT_DEGRADED": 4, + "MOUNT_UNMOUNTING": 5, + } +) + +func (x MountState) Enum() *MountState { + p := new(MountState) + *p = x + return p +} + +func (x MountState) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (MountState) Descriptor() protoreflect.EnumDescriptor { + return file_musicfs_proto_enumTypes[0].Descriptor() +} + +func (MountState) Type() protoreflect.EnumType { + return &file_musicfs_proto_enumTypes[0] +} + +func (x MountState) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use MountState.Descriptor instead. +func (MountState) EnumDescriptor() ([]byte, []int) { + return file_musicfs_proto_rawDescGZIP(), []int{0} +} + +type HealthStatus int32 + +const ( + HealthStatus_HEALTH_UNKNOWN HealthStatus = 0 + HealthStatus_HEALTH_HEALTHY HealthStatus = 1 + HealthStatus_HEALTH_DEGRADED HealthStatus = 2 + HealthStatus_HEALTH_UNHEALTHY HealthStatus = 3 +) + +// Enum value maps for HealthStatus. +var ( + HealthStatus_name = map[int32]string{ + 0: "HEALTH_UNKNOWN", + 1: "HEALTH_HEALTHY", + 2: "HEALTH_DEGRADED", + 3: "HEALTH_UNHEALTHY", + } + HealthStatus_value = map[string]int32{ + "HEALTH_UNKNOWN": 0, + "HEALTH_HEALTHY": 1, + "HEALTH_DEGRADED": 2, + "HEALTH_UNHEALTHY": 3, + } +) + +func (x HealthStatus) Enum() *HealthStatus { + p := new(HealthStatus) + *p = x + return p +} + +func (x HealthStatus) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (HealthStatus) Descriptor() protoreflect.EnumDescriptor { + return file_musicfs_proto_enumTypes[1].Descriptor() +} + +func (HealthStatus) Type() protoreflect.EnumType { + return &file_musicfs_proto_enumTypes[1] +} + +func (x HealthStatus) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use HealthStatus.Descriptor instead. +func (HealthStatus) EnumDescriptor() ([]byte, []int) { + return file_musicfs_proto_rawDescGZIP(), []int{1} +} + +type Empty struct { + state protoimpl.MessageState `protogen:"open.v1"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *Empty) Reset() { + *x = Empty{} + mi := &file_musicfs_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *Empty) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Empty) ProtoMessage() {} + +func (x *Empty) ProtoReflect() protoreflect.Message { + mi := &file_musicfs_proto_msgTypes[0] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Empty.ProtoReflect.Descriptor instead. +func (*Empty) Descriptor() ([]byte, []int) { + return file_musicfs_proto_rawDescGZIP(), []int{0} +} + +type SearchRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + Query string `protobuf:"bytes,1,opt,name=query,proto3" json:"query,omitempty"` + Limit *uint32 `protobuf:"varint,2,opt,name=limit,proto3,oneof" json:"limit,omitempty"` + Offset *uint32 `protobuf:"varint,3,opt,name=offset,proto3,oneof" json:"offset,omitempty"` + OriginId *string `protobuf:"bytes,4,opt,name=origin_id,json=originId,proto3,oneof" json:"origin_id,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *SearchRequest) Reset() { + *x = SearchRequest{} + mi := &file_musicfs_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *SearchRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SearchRequest) ProtoMessage() {} + +func (x *SearchRequest) ProtoReflect() protoreflect.Message { + mi := &file_musicfs_proto_msgTypes[1] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SearchRequest.ProtoReflect.Descriptor instead. +func (*SearchRequest) Descriptor() ([]byte, []int) { + return file_musicfs_proto_rawDescGZIP(), []int{1} +} + +func (x *SearchRequest) GetQuery() string { + if x != nil { + return x.Query + } + return "" +} + +func (x *SearchRequest) GetLimit() uint32 { + if x != nil && x.Limit != nil { + return *x.Limit + } + return 0 +} + +func (x *SearchRequest) GetOffset() uint32 { + if x != nil && x.Offset != nil { + return *x.Offset + } + return 0 +} + +func (x *SearchRequest) GetOriginId() string { + if x != nil && x.OriginId != nil { + return *x.OriginId + } + return "" +} + +type SearchResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Results []*SearchResult `protobuf:"bytes,1,rep,name=results,proto3" json:"results,omitempty"` + TotalMatches uint64 `protobuf:"varint,2,opt,name=total_matches,json=totalMatches,proto3" json:"total_matches,omitempty"` + QueryTimeMs uint32 `protobuf:"varint,3,opt,name=query_time_ms,json=queryTimeMs,proto3" json:"query_time_ms,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *SearchResponse) Reset() { + *x = SearchResponse{} + mi := &file_musicfs_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *SearchResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SearchResponse) ProtoMessage() {} + +func (x *SearchResponse) ProtoReflect() protoreflect.Message { + mi := &file_musicfs_proto_msgTypes[2] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SearchResponse.ProtoReflect.Descriptor instead. +func (*SearchResponse) Descriptor() ([]byte, []int) { + return file_musicfs_proto_rawDescGZIP(), []int{2} +} + +func (x *SearchResponse) GetResults() []*SearchResult { + if x != nil { + return x.Results + } + return nil +} + +func (x *SearchResponse) GetTotalMatches() uint64 { + if x != nil { + return x.TotalMatches + } + return 0 +} + +func (x *SearchResponse) GetQueryTimeMs() uint32 { + if x != nil { + return x.QueryTimeMs + } + return 0 +} + +type SearchResult struct { + state protoimpl.MessageState `protogen:"open.v1"` + FileId int64 `protobuf:"varint,1,opt,name=file_id,json=fileId,proto3" json:"file_id,omitempty"` + VirtualPath string `protobuf:"bytes,2,opt,name=virtual_path,json=virtualPath,proto3" json:"virtual_path,omitempty"` + Artist *string `protobuf:"bytes,3,opt,name=artist,proto3,oneof" json:"artist,omitempty"` + Album *string `protobuf:"bytes,4,opt,name=album,proto3,oneof" json:"album,omitempty"` + Title *string `protobuf:"bytes,5,opt,name=title,proto3,oneof" json:"title,omitempty"` + Score float32 `protobuf:"fixed32,6,opt,name=score,proto3" json:"score,omitempty"` + Highlights map[string]string `protobuf:"bytes,7,rep,name=highlights,proto3" json:"highlights,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *SearchResult) Reset() { + *x = SearchResult{} + mi := &file_musicfs_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *SearchResult) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SearchResult) ProtoMessage() {} + +func (x *SearchResult) ProtoReflect() protoreflect.Message { + mi := &file_musicfs_proto_msgTypes[3] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SearchResult.ProtoReflect.Descriptor instead. +func (*SearchResult) Descriptor() ([]byte, []int) { + return file_musicfs_proto_rawDescGZIP(), []int{3} +} + +func (x *SearchResult) GetFileId() int64 { + if x != nil { + return x.FileId + } + return 0 +} + +func (x *SearchResult) GetVirtualPath() string { + if x != nil { + return x.VirtualPath + } + return "" +} + +func (x *SearchResult) GetArtist() string { + if x != nil && x.Artist != nil { + return *x.Artist + } + return "" +} + +func (x *SearchResult) GetAlbum() string { + if x != nil && x.Album != nil { + return *x.Album + } + return "" +} + +func (x *SearchResult) GetTitle() string { + if x != nil && x.Title != nil { + return *x.Title + } + return "" +} + +func (x *SearchResult) GetScore() float32 { + if x != nil { + return x.Score + } + return 0 +} + +func (x *SearchResult) GetHighlights() map[string]string { + if x != nil { + return x.Highlights + } + return nil +} + +type StatusResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Version string `protobuf:"bytes,1,opt,name=version,proto3" json:"version,omitempty"` + UptimeSecs uint64 `protobuf:"varint,2,opt,name=uptime_secs,json=uptimeSecs,proto3" json:"uptime_secs,omitempty"` + MountPoint string `protobuf:"bytes,3,opt,name=mount_point,json=mountPoint,proto3" json:"mount_point,omitempty"` + State MountState `protobuf:"varint,4,opt,name=state,proto3,enum=musicfs.v1.MountState" json:"state,omitempty"` + OpenFileHandles uint32 `protobuf:"varint,5,opt,name=open_file_handles,json=openFileHandles,proto3" json:"open_file_handles,omitempty"` + FuseOpsTotal uint64 `protobuf:"varint,6,opt,name=fuse_ops_total,json=fuseOpsTotal,proto3" json:"fuse_ops_total,omitempty"` + FilesIndexed uint64 `protobuf:"varint,7,opt,name=files_indexed,json=filesIndexed,proto3" json:"files_indexed,omitempty"` + CacheSizeBytes uint64 `protobuf:"varint,8,opt,name=cache_size_bytes,json=cacheSizeBytes,proto3" json:"cache_size_bytes,omitempty"` + Origins []*OriginStatus `protobuf:"bytes,9,rep,name=origins,proto3" json:"origins,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *StatusResponse) Reset() { + *x = StatusResponse{} + mi := &file_musicfs_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *StatusResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*StatusResponse) ProtoMessage() {} + +func (x *StatusResponse) ProtoReflect() protoreflect.Message { + mi := &file_musicfs_proto_msgTypes[4] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use StatusResponse.ProtoReflect.Descriptor instead. +func (*StatusResponse) Descriptor() ([]byte, []int) { + return file_musicfs_proto_rawDescGZIP(), []int{4} +} + +func (x *StatusResponse) GetVersion() string { + if x != nil { + return x.Version + } + return "" +} + +func (x *StatusResponse) GetUptimeSecs() uint64 { + if x != nil { + return x.UptimeSecs + } + return 0 +} + +func (x *StatusResponse) GetMountPoint() string { + if x != nil { + return x.MountPoint + } + return "" +} + +func (x *StatusResponse) GetState() MountState { + if x != nil { + return x.State + } + return MountState_MOUNT_UNKNOWN +} + +func (x *StatusResponse) GetOpenFileHandles() uint32 { + if x != nil { + return x.OpenFileHandles + } + return 0 +} + +func (x *StatusResponse) GetFuseOpsTotal() uint64 { + if x != nil { + return x.FuseOpsTotal + } + return 0 +} + +func (x *StatusResponse) GetFilesIndexed() uint64 { + if x != nil { + return x.FilesIndexed + } + return 0 +} + +func (x *StatusResponse) GetCacheSizeBytes() uint64 { + if x != nil { + return x.CacheSizeBytes + } + return 0 +} + +func (x *StatusResponse) GetOrigins() []*OriginStatus { + if x != nil { + return x.Origins + } + return nil +} + +type OriginStatus struct { + state protoimpl.MessageState `protogen:"open.v1"` + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + OriginType string `protobuf:"bytes,2,opt,name=origin_type,json=originType,proto3" json:"origin_type,omitempty"` + Health HealthStatus `protobuf:"varint,3,opt,name=health,proto3,enum=musicfs.v1.HealthStatus" json:"health,omitempty"` + FilesCount uint64 `protobuf:"varint,4,opt,name=files_count,json=filesCount,proto3" json:"files_count,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *OriginStatus) Reset() { + *x = OriginStatus{} + mi := &file_musicfs_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *OriginStatus) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*OriginStatus) ProtoMessage() {} + +func (x *OriginStatus) ProtoReflect() protoreflect.Message { + mi := &file_musicfs_proto_msgTypes[5] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use OriginStatus.ProtoReflect.Descriptor instead. +func (*OriginStatus) Descriptor() ([]byte, []int) { + return file_musicfs_proto_rawDescGZIP(), []int{5} +} + +func (x *OriginStatus) GetId() string { + if x != nil { + return x.Id + } + return "" +} + +func (x *OriginStatus) GetOriginType() string { + if x != nil { + return x.OriginType + } + return "" +} + +func (x *OriginStatus) GetHealth() HealthStatus { + if x != nil { + return x.Health + } + return HealthStatus_HEALTH_UNKNOWN +} + +func (x *OriginStatus) GetFilesCount() uint64 { + if x != nil { + return x.FilesCount + } + return 0 +} + +type ShutdownRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + Graceful bool `protobuf:"varint,1,opt,name=graceful,proto3" json:"graceful,omitempty"` + TimeoutSecs uint32 `protobuf:"varint,2,opt,name=timeout_secs,json=timeoutSecs,proto3" json:"timeout_secs,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ShutdownRequest) Reset() { + *x = ShutdownRequest{} + mi := &file_musicfs_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ShutdownRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ShutdownRequest) ProtoMessage() {} + +func (x *ShutdownRequest) ProtoReflect() protoreflect.Message { + mi := &file_musicfs_proto_msgTypes[6] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ShutdownRequest.ProtoReflect.Descriptor instead. +func (*ShutdownRequest) Descriptor() ([]byte, []int) { + return file_musicfs_proto_rawDescGZIP(), []int{6} +} + +func (x *ShutdownRequest) GetGraceful() bool { + if x != nil { + return x.Graceful + } + return false +} + +func (x *ShutdownRequest) GetTimeoutSecs() uint32 { + if x != nil { + return x.TimeoutSecs + } + return 0 +} + +type TierStats struct { + state protoimpl.MessageState `protogen:"open.v1"` + Entries uint64 `protobuf:"varint,1,opt,name=entries,proto3" json:"entries,omitempty"` + SizeBytes uint64 `protobuf:"varint,2,opt,name=size_bytes,json=sizeBytes,proto3" json:"size_bytes,omitempty"` + Hits uint64 `protobuf:"varint,3,opt,name=hits,proto3" json:"hits,omitempty"` + Misses uint64 `protobuf:"varint,4,opt,name=misses,proto3" json:"misses,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *TierStats) Reset() { + *x = TierStats{} + mi := &file_musicfs_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *TierStats) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TierStats) ProtoMessage() {} + +func (x *TierStats) ProtoReflect() protoreflect.Message { + mi := &file_musicfs_proto_msgTypes[7] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use TierStats.ProtoReflect.Descriptor instead. +func (*TierStats) Descriptor() ([]byte, []int) { + return file_musicfs_proto_rawDescGZIP(), []int{7} +} + +func (x *TierStats) GetEntries() uint64 { + if x != nil { + return x.Entries + } + return 0 +} + +func (x *TierStats) GetSizeBytes() uint64 { + if x != nil { + return x.SizeBytes + } + return 0 +} + +func (x *TierStats) GetHits() uint64 { + if x != nil { + return x.Hits + } + return 0 +} + +func (x *TierStats) GetMisses() uint64 { + if x != nil { + return x.Misses + } + return 0 +} + +type CacheStats struct { + state protoimpl.MessageState `protogen:"open.v1"` + TotalSizeBytes uint64 `protobuf:"varint,1,opt,name=total_size_bytes,json=totalSizeBytes,proto3" json:"total_size_bytes,omitempty"` + UsedSizeBytes uint64 `protobuf:"varint,2,opt,name=used_size_bytes,json=usedSizeBytes,proto3" json:"used_size_bytes,omitempty"` + SizeLimitBytes uint64 `protobuf:"varint,3,opt,name=size_limit_bytes,json=sizeLimitBytes,proto3" json:"size_limit_bytes,omitempty"` + ChunkCount uint64 `protobuf:"varint,4,opt,name=chunk_count,json=chunkCount,proto3" json:"chunk_count,omitempty"` + ChunksUnique uint64 `protobuf:"varint,5,opt,name=chunks_unique,json=chunksUnique,proto3" json:"chunks_unique,omitempty"` + DedupRatio float64 `protobuf:"fixed64,6,opt,name=dedup_ratio,json=dedupRatio,proto3" json:"dedup_ratio,omitempty"` + HitCount uint64 `protobuf:"varint,7,opt,name=hit_count,json=hitCount,proto3" json:"hit_count,omitempty"` + MissCount uint64 `protobuf:"varint,8,opt,name=miss_count,json=missCount,proto3" json:"miss_count,omitempty"` + HitRatio float64 `protobuf:"fixed64,9,opt,name=hit_ratio,json=hitRatio,proto3" json:"hit_ratio,omitempty"` + MetadataEntries uint64 `protobuf:"varint,10,opt,name=metadata_entries,json=metadataEntries,proto3" json:"metadata_entries,omitempty"` + MetadataBytes uint64 `protobuf:"varint,11,opt,name=metadata_bytes,json=metadataBytes,proto3" json:"metadata_bytes,omitempty"` + L1Metadata *TierStats `protobuf:"bytes,12,opt,name=l1_metadata,json=l1Metadata,proto3" json:"l1_metadata,omitempty"` + L2Headers *TierStats `protobuf:"bytes,13,opt,name=l2_headers,json=l2Headers,proto3" json:"l2_headers,omitempty"` + L3Chunks *TierStats `protobuf:"bytes,14,opt,name=l3_chunks,json=l3Chunks,proto3" json:"l3_chunks,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *CacheStats) Reset() { + *x = CacheStats{} + mi := &file_musicfs_proto_msgTypes[8] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *CacheStats) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CacheStats) ProtoMessage() {} + +func (x *CacheStats) ProtoReflect() protoreflect.Message { + mi := &file_musicfs_proto_msgTypes[8] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CacheStats.ProtoReflect.Descriptor instead. +func (*CacheStats) Descriptor() ([]byte, []int) { + return file_musicfs_proto_rawDescGZIP(), []int{8} +} + +func (x *CacheStats) GetTotalSizeBytes() uint64 { + if x != nil { + return x.TotalSizeBytes + } + return 0 +} + +func (x *CacheStats) GetUsedSizeBytes() uint64 { + if x != nil { + return x.UsedSizeBytes + } + return 0 +} + +func (x *CacheStats) GetSizeLimitBytes() uint64 { + if x != nil { + return x.SizeLimitBytes + } + return 0 +} + +func (x *CacheStats) GetChunkCount() uint64 { + if x != nil { + return x.ChunkCount + } + return 0 +} + +func (x *CacheStats) GetChunksUnique() uint64 { + if x != nil { + return x.ChunksUnique + } + return 0 +} + +func (x *CacheStats) GetDedupRatio() float64 { + if x != nil { + return x.DedupRatio + } + return 0 +} + +func (x *CacheStats) GetHitCount() uint64 { + if x != nil { + return x.HitCount + } + return 0 +} + +func (x *CacheStats) GetMissCount() uint64 { + if x != nil { + return x.MissCount + } + return 0 +} + +func (x *CacheStats) GetHitRatio() float64 { + if x != nil { + return x.HitRatio + } + return 0 +} + +func (x *CacheStats) GetMetadataEntries() uint64 { + if x != nil { + return x.MetadataEntries + } + return 0 +} + +func (x *CacheStats) GetMetadataBytes() uint64 { + if x != nil { + return x.MetadataBytes + } + return 0 +} + +func (x *CacheStats) GetL1Metadata() *TierStats { + if x != nil { + return x.L1Metadata + } + return nil +} + +func (x *CacheStats) GetL2Headers() *TierStats { + if x != nil { + return x.L2Headers + } + return nil +} + +func (x *CacheStats) GetL3Chunks() *TierStats { + if x != nil { + return x.L3Chunks + } + return nil +} + +type ClearCacheRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + OriginId *string `protobuf:"bytes,1,opt,name=origin_id,json=originId,proto3,oneof" json:"origin_id,omitempty"` + ClearMetadata bool `protobuf:"varint,2,opt,name=clear_metadata,json=clearMetadata,proto3" json:"clear_metadata,omitempty"` + ClearChunks bool `protobuf:"varint,3,opt,name=clear_chunks,json=clearChunks,proto3" json:"clear_chunks,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ClearCacheRequest) Reset() { + *x = ClearCacheRequest{} + mi := &file_musicfs_proto_msgTypes[9] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ClearCacheRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ClearCacheRequest) ProtoMessage() {} + +func (x *ClearCacheRequest) ProtoReflect() protoreflect.Message { + mi := &file_musicfs_proto_msgTypes[9] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ClearCacheRequest.ProtoReflect.Descriptor instead. +func (*ClearCacheRequest) Descriptor() ([]byte, []int) { + return file_musicfs_proto_rawDescGZIP(), []int{9} +} + +func (x *ClearCacheRequest) GetOriginId() string { + if x != nil && x.OriginId != nil { + return *x.OriginId + } + return "" +} + +func (x *ClearCacheRequest) GetClearMetadata() bool { + if x != nil { + return x.ClearMetadata + } + return false +} + +func (x *ClearCacheRequest) GetClearChunks() bool { + if x != nil { + return x.ClearChunks + } + return false +} + +type ClearCacheResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + BytesCleared uint64 `protobuf:"varint,1,opt,name=bytes_cleared,json=bytesCleared,proto3" json:"bytes_cleared,omitempty"` + ChunksCleared uint64 `protobuf:"varint,2,opt,name=chunks_cleared,json=chunksCleared,proto3" json:"chunks_cleared,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ClearCacheResponse) Reset() { + *x = ClearCacheResponse{} + mi := &file_musicfs_proto_msgTypes[10] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ClearCacheResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ClearCacheResponse) ProtoMessage() {} + +func (x *ClearCacheResponse) ProtoReflect() protoreflect.Message { + mi := &file_musicfs_proto_msgTypes[10] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ClearCacheResponse.ProtoReflect.Descriptor instead. +func (*ClearCacheResponse) Descriptor() ([]byte, []int) { + return file_musicfs_proto_rawDescGZIP(), []int{10} +} + +func (x *ClearCacheResponse) GetBytesCleared() uint64 { + if x != nil { + return x.BytesCleared + } + return 0 +} + +func (x *ClearCacheResponse) GetChunksCleared() uint64 { + if x != nil { + return x.ChunksCleared + } + return 0 +} + +type PrefetchRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + Paths []string `protobuf:"bytes,1,rep,name=paths,proto3" json:"paths,omitempty"` + OriginId *string `protobuf:"bytes,2,opt,name=origin_id,json=originId,proto3,oneof" json:"origin_id,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *PrefetchRequest) Reset() { + *x = PrefetchRequest{} + mi := &file_musicfs_proto_msgTypes[11] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *PrefetchRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PrefetchRequest) ProtoMessage() {} + +func (x *PrefetchRequest) ProtoReflect() protoreflect.Message { + mi := &file_musicfs_proto_msgTypes[11] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PrefetchRequest.ProtoReflect.Descriptor instead. +func (*PrefetchRequest) Descriptor() ([]byte, []int) { + return file_musicfs_proto_rawDescGZIP(), []int{11} +} + +func (x *PrefetchRequest) GetPaths() []string { + if x != nil { + return x.Paths + } + return nil +} + +func (x *PrefetchRequest) GetOriginId() string { + if x != nil && x.OriginId != nil { + return *x.OriginId + } + return "" +} + +type PrefetchProgress struct { + state protoimpl.MessageState `protogen:"open.v1"` + CurrentPath string `protobuf:"bytes,1,opt,name=current_path,json=currentPath,proto3" json:"current_path,omitempty"` + Completed uint32 `protobuf:"varint,2,opt,name=completed,proto3" json:"completed,omitempty"` + Total uint32 `protobuf:"varint,3,opt,name=total,proto3" json:"total,omitempty"` + BytesFetched uint64 `protobuf:"varint,4,opt,name=bytes_fetched,json=bytesFetched,proto3" json:"bytes_fetched,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *PrefetchProgress) Reset() { + *x = PrefetchProgress{} + mi := &file_musicfs_proto_msgTypes[12] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *PrefetchProgress) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PrefetchProgress) ProtoMessage() {} + +func (x *PrefetchProgress) ProtoReflect() protoreflect.Message { + mi := &file_musicfs_proto_msgTypes[12] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PrefetchProgress.ProtoReflect.Descriptor instead. +func (*PrefetchProgress) Descriptor() ([]byte, []int) { + return file_musicfs_proto_rawDescGZIP(), []int{12} +} + +func (x *PrefetchProgress) GetCurrentPath() string { + if x != nil { + return x.CurrentPath + } + return "" +} + +func (x *PrefetchProgress) GetCompleted() uint32 { + if x != nil { + return x.Completed + } + return 0 +} + +func (x *PrefetchProgress) GetTotal() uint32 { + if x != nil { + return x.Total + } + return 0 +} + +func (x *PrefetchProgress) GetBytesFetched() uint64 { + if x != nil { + return x.BytesFetched + } + return 0 +} + +type OriginsResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Origins []*OriginInfo `protobuf:"bytes,1,rep,name=origins,proto3" json:"origins,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *OriginsResponse) Reset() { + *x = OriginsResponse{} + mi := &file_musicfs_proto_msgTypes[13] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *OriginsResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*OriginsResponse) ProtoMessage() {} + +func (x *OriginsResponse) ProtoReflect() protoreflect.Message { + mi := &file_musicfs_proto_msgTypes[13] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use OriginsResponse.ProtoReflect.Descriptor instead. +func (*OriginsResponse) Descriptor() ([]byte, []int) { + return file_musicfs_proto_rawDescGZIP(), []int{13} +} + +func (x *OriginsResponse) GetOrigins() []*OriginInfo { + if x != nil { + return x.Origins + } + return nil +} + +type OriginInfo struct { + state protoimpl.MessageState `protogen:"open.v1"` + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + OriginType string `protobuf:"bytes,2,opt,name=origin_type,json=originType,proto3" json:"origin_type,omitempty"` + DisplayName string `protobuf:"bytes,3,opt,name=display_name,json=displayName,proto3" json:"display_name,omitempty"` + RootPath string `protobuf:"bytes,4,opt,name=root_path,json=rootPath,proto3" json:"root_path,omitempty"` + Health HealthStatus `protobuf:"varint,5,opt,name=health,proto3,enum=musicfs.v1.HealthStatus" json:"health,omitempty"` + FilesCount uint64 `protobuf:"varint,6,opt,name=files_count,json=filesCount,proto3" json:"files_count,omitempty"` + TotalSizeBytes uint64 `protobuf:"varint,7,opt,name=total_size_bytes,json=totalSizeBytes,proto3" json:"total_size_bytes,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *OriginInfo) Reset() { + *x = OriginInfo{} + mi := &file_musicfs_proto_msgTypes[14] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *OriginInfo) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*OriginInfo) ProtoMessage() {} + +func (x *OriginInfo) ProtoReflect() protoreflect.Message { + mi := &file_musicfs_proto_msgTypes[14] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use OriginInfo.ProtoReflect.Descriptor instead. +func (*OriginInfo) Descriptor() ([]byte, []int) { + return file_musicfs_proto_rawDescGZIP(), []int{14} +} + +func (x *OriginInfo) GetId() string { + if x != nil { + return x.Id + } + return "" +} + +func (x *OriginInfo) GetOriginType() string { + if x != nil { + return x.OriginType + } + return "" +} + +func (x *OriginInfo) GetDisplayName() string { + if x != nil { + return x.DisplayName + } + return "" +} + +func (x *OriginInfo) GetRootPath() string { + if x != nil { + return x.RootPath + } + return "" +} + +func (x *OriginInfo) GetHealth() HealthStatus { + if x != nil { + return x.Health + } + return HealthStatus_HEALTH_UNKNOWN +} + +func (x *OriginInfo) GetFilesCount() uint64 { + if x != nil { + return x.FilesCount + } + return 0 +} + +func (x *OriginInfo) GetTotalSizeBytes() uint64 { + if x != nil { + return x.TotalSizeBytes + } + return 0 +} + +type OriginRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + OriginId string `protobuf:"bytes,1,opt,name=origin_id,json=originId,proto3" json:"origin_id,omitempty"` + // Optional subdirectory to scope the scan (relative to origin root). + // If empty, scans the entire origin. + // Example: "Metallica - Master of Puppets (1986) [FLAC]" + Subdir *string `protobuf:"bytes,2,opt,name=subdir,proto3,oneof" json:"subdir,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *OriginRequest) Reset() { + *x = OriginRequest{} + mi := &file_musicfs_proto_msgTypes[15] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *OriginRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*OriginRequest) ProtoMessage() {} + +func (x *OriginRequest) ProtoReflect() protoreflect.Message { + mi := &file_musicfs_proto_msgTypes[15] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use OriginRequest.ProtoReflect.Descriptor instead. +func (*OriginRequest) Descriptor() ([]byte, []int) { + return file_musicfs_proto_rawDescGZIP(), []int{15} +} + +func (x *OriginRequest) GetOriginId() string { + if x != nil { + return x.OriginId + } + return "" +} + +func (x *OriginRequest) GetSubdir() string { + if x != nil && x.Subdir != nil { + return *x.Subdir + } + return "" +} + +type OriginHealthResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + OriginId string `protobuf:"bytes,1,opt,name=origin_id,json=originId,proto3" json:"origin_id,omitempty"` + Status HealthStatus `protobuf:"varint,2,opt,name=status,proto3,enum=musicfs.v1.HealthStatus" json:"status,omitempty"` + Message *string `protobuf:"bytes,3,opt,name=message,proto3,oneof" json:"message,omitempty"` + LastCheckSecs uint64 `protobuf:"varint,4,opt,name=last_check_secs,json=lastCheckSecs,proto3" json:"last_check_secs,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *OriginHealthResponse) Reset() { + *x = OriginHealthResponse{} + mi := &file_musicfs_proto_msgTypes[16] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *OriginHealthResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*OriginHealthResponse) ProtoMessage() {} + +func (x *OriginHealthResponse) ProtoReflect() protoreflect.Message { + mi := &file_musicfs_proto_msgTypes[16] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use OriginHealthResponse.ProtoReflect.Descriptor instead. +func (*OriginHealthResponse) Descriptor() ([]byte, []int) { + return file_musicfs_proto_rawDescGZIP(), []int{16} +} + +func (x *OriginHealthResponse) GetOriginId() string { + if x != nil { + return x.OriginId + } + return "" +} + +func (x *OriginHealthResponse) GetStatus() HealthStatus { + if x != nil { + return x.Status + } + return HealthStatus_HEALTH_UNKNOWN +} + +func (x *OriginHealthResponse) GetMessage() string { + if x != nil && x.Message != nil { + return *x.Message + } + return "" +} + +func (x *OriginHealthResponse) GetLastCheckSecs() uint64 { + if x != nil { + return x.LastCheckSecs + } + return 0 +} + +type SyncProgress struct { + state protoimpl.MessageState `protogen:"open.v1"` + Phase string `protobuf:"bytes,1,opt,name=phase,proto3" json:"phase,omitempty"` + Current uint32 `protobuf:"varint,2,opt,name=current,proto3" json:"current,omitempty"` + Total uint32 `protobuf:"varint,3,opt,name=total,proto3" json:"total,omitempty"` + CurrentPath string `protobuf:"bytes,4,opt,name=current_path,json=currentPath,proto3" json:"current_path,omitempty"` + BytesSynced uint64 `protobuf:"varint,5,opt,name=bytes_synced,json=bytesSynced,proto3" json:"bytes_synced,omitempty"` + NewFiles []*SyncedFile `protobuf:"bytes,6,rep,name=new_files,json=newFiles,proto3" json:"new_files,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *SyncProgress) Reset() { + *x = SyncProgress{} + mi := &file_musicfs_proto_msgTypes[17] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *SyncProgress) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SyncProgress) ProtoMessage() {} + +func (x *SyncProgress) ProtoReflect() protoreflect.Message { + mi := &file_musicfs_proto_msgTypes[17] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SyncProgress.ProtoReflect.Descriptor instead. +func (*SyncProgress) Descriptor() ([]byte, []int) { + return file_musicfs_proto_rawDescGZIP(), []int{17} +} + +func (x *SyncProgress) GetPhase() string { + if x != nil { + return x.Phase + } + return "" +} + +func (x *SyncProgress) GetCurrent() uint32 { + if x != nil { + return x.Current + } + return 0 +} + +func (x *SyncProgress) GetTotal() uint32 { + if x != nil { + return x.Total + } + return 0 +} + +func (x *SyncProgress) GetCurrentPath() string { + if x != nil { + return x.CurrentPath + } + return "" +} + +func (x *SyncProgress) GetBytesSynced() uint64 { + if x != nil { + return x.BytesSynced + } + return 0 +} + +func (x *SyncProgress) GetNewFiles() []*SyncedFile { + if x != nil { + return x.NewFiles + } + return nil +} + +type SyncedFile struct { + state protoimpl.MessageState `protogen:"open.v1"` + Path string `protobuf:"bytes,1,opt,name=path,proto3" json:"path,omitempty"` + FileId int64 `protobuf:"varint,2,opt,name=file_id,json=fileId,proto3" json:"file_id,omitempty"` + VirtualPath string `protobuf:"bytes,3,opt,name=virtual_path,json=virtualPath,proto3" json:"virtual_path,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *SyncedFile) Reset() { + *x = SyncedFile{} + mi := &file_musicfs_proto_msgTypes[18] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *SyncedFile) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SyncedFile) ProtoMessage() {} + +func (x *SyncedFile) ProtoReflect() protoreflect.Message { + mi := &file_musicfs_proto_msgTypes[18] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SyncedFile.ProtoReflect.Descriptor instead. +func (*SyncedFile) Descriptor() ([]byte, []int) { + return file_musicfs_proto_rawDescGZIP(), []int{18} +} + +func (x *SyncedFile) GetPath() string { + if x != nil { + return x.Path + } + return "" +} + +func (x *SyncedFile) GetFileId() int64 { + if x != nil { + return x.FileId + } + return 0 +} + +func (x *SyncedFile) GetVirtualPath() string { + if x != nil { + return x.VirtualPath + } + return "" +} + +type EventFilter struct { + state protoimpl.MessageState `protogen:"open.v1"` + EventTypes []string `protobuf:"bytes,1,rep,name=event_types,json=eventTypes,proto3" json:"event_types,omitempty"` + OriginId *string `protobuf:"bytes,2,opt,name=origin_id,json=originId,proto3,oneof" json:"origin_id,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *EventFilter) Reset() { + *x = EventFilter{} + mi := &file_musicfs_proto_msgTypes[19] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *EventFilter) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*EventFilter) ProtoMessage() {} + +func (x *EventFilter) ProtoReflect() protoreflect.Message { + mi := &file_musicfs_proto_msgTypes[19] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use EventFilter.ProtoReflect.Descriptor instead. +func (*EventFilter) Descriptor() ([]byte, []int) { + return file_musicfs_proto_rawDescGZIP(), []int{19} +} + +func (x *EventFilter) GetEventTypes() []string { + if x != nil { + return x.EventTypes + } + return nil +} + +func (x *EventFilter) GetOriginId() string { + if x != nil && x.OriginId != nil { + return *x.OriginId + } + return "" +} + +type Event struct { + state protoimpl.MessageState `protogen:"open.v1"` + EventType string `protobuf:"bytes,1,opt,name=event_type,json=eventType,proto3" json:"event_type,omitempty"` + TimestampMs int64 `protobuf:"varint,2,opt,name=timestamp_ms,json=timestampMs,proto3" json:"timestamp_ms,omitempty"` + OriginId *string `protobuf:"bytes,3,opt,name=origin_id,json=originId,proto3,oneof" json:"origin_id,omitempty"` + Path *string `protobuf:"bytes,4,opt,name=path,proto3,oneof" json:"path,omitempty"` + FileId *int64 `protobuf:"varint,5,opt,name=file_id,json=fileId,proto3,oneof" json:"file_id,omitempty"` + Metadata map[string]string `protobuf:"bytes,6,rep,name=metadata,proto3" json:"metadata,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *Event) Reset() { + *x = Event{} + mi := &file_musicfs_proto_msgTypes[20] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *Event) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Event) ProtoMessage() {} + +func (x *Event) ProtoReflect() protoreflect.Message { + mi := &file_musicfs_proto_msgTypes[20] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Event.ProtoReflect.Descriptor instead. +func (*Event) Descriptor() ([]byte, []int) { + return file_musicfs_proto_rawDescGZIP(), []int{20} +} + +func (x *Event) GetEventType() string { + if x != nil { + return x.EventType + } + return "" +} + +func (x *Event) GetTimestampMs() int64 { + if x != nil { + return x.TimestampMs + } + return 0 +} + +func (x *Event) GetOriginId() string { + if x != nil && x.OriginId != nil { + return *x.OriginId + } + return "" +} + +func (x *Event) GetPath() string { + if x != nil && x.Path != nil { + return *x.Path + } + return "" +} + +func (x *Event) GetFileId() int64 { + if x != nil && x.FileId != nil { + return *x.FileId + } + return 0 +} + +func (x *Event) GetMetadata() map[string]string { + if x != nil { + return x.Metadata + } + return nil +} + +type GetMetadataRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + VirtualPath string `protobuf:"bytes,1,opt,name=virtual_path,json=virtualPath,proto3" json:"virtual_path,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GetMetadataRequest) Reset() { + *x = GetMetadataRequest{} + mi := &file_musicfs_proto_msgTypes[21] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetMetadataRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetMetadataRequest) ProtoMessage() {} + +func (x *GetMetadataRequest) ProtoReflect() protoreflect.Message { + mi := &file_musicfs_proto_msgTypes[21] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetMetadataRequest.ProtoReflect.Descriptor instead. +func (*GetMetadataRequest) Descriptor() ([]byte, []int) { + return file_musicfs_proto_rawDescGZIP(), []int{21} +} + +func (x *GetMetadataRequest) GetVirtualPath() string { + if x != nil { + return x.VirtualPath + } + return "" +} + +type MetadataResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + FileId int64 `protobuf:"varint,1,opt,name=file_id,json=fileId,proto3" json:"file_id,omitempty"` + Title *string `protobuf:"bytes,2,opt,name=title,proto3,oneof" json:"title,omitempty"` + Artist *string `protobuf:"bytes,3,opt,name=artist,proto3,oneof" json:"artist,omitempty"` + Album *string `protobuf:"bytes,4,opt,name=album,proto3,oneof" json:"album,omitempty"` + AlbumArtist *string `protobuf:"bytes,5,opt,name=album_artist,json=albumArtist,proto3,oneof" json:"album_artist,omitempty"` + Year *uint32 `protobuf:"varint,6,opt,name=year,proto3,oneof" json:"year,omitempty"` + Track *uint32 `protobuf:"varint,7,opt,name=track,proto3,oneof" json:"track,omitempty"` + Disc *uint32 `protobuf:"varint,8,opt,name=disc,proto3,oneof" json:"disc,omitempty"` + Genre *string `protobuf:"bytes,9,opt,name=genre,proto3,oneof" json:"genre,omitempty"` + Format *string `protobuf:"bytes,10,opt,name=format,proto3,oneof" json:"format,omitempty"` + DurationMs *uint64 `protobuf:"varint,11,opt,name=duration_ms,json=durationMs,proto3,oneof" json:"duration_ms,omitempty"` + Bitrate *uint64 `protobuf:"varint,12,opt,name=bitrate,proto3,oneof" json:"bitrate,omitempty"` + TrackTotal *uint32 `protobuf:"varint,13,opt,name=track_total,json=trackTotal,proto3,oneof" json:"track_total,omitempty"` + DiscTotal *uint32 `protobuf:"varint,14,opt,name=disc_total,json=discTotal,proto3,oneof" json:"disc_total,omitempty"` + Date *string `protobuf:"bytes,15,opt,name=date,proto3,oneof" json:"date,omitempty"` + Composer *string `protobuf:"bytes,16,opt,name=composer,proto3,oneof" json:"composer,omitempty"` + Comment *string `protobuf:"bytes,17,opt,name=comment,proto3,oneof" json:"comment,omitempty"` + Lyrics *string `protobuf:"bytes,18,opt,name=lyrics,proto3,oneof" json:"lyrics,omitempty"` + Copyright *string `protobuf:"bytes,19,opt,name=copyright,proto3,oneof" json:"copyright,omitempty"` + Compilation *bool `protobuf:"varint,20,opt,name=compilation,proto3,oneof" json:"compilation,omitempty"` + ArtistSort *string `protobuf:"bytes,21,opt,name=artist_sort,json=artistSort,proto3,oneof" json:"artist_sort,omitempty"` + AlbumArtistSort *string `protobuf:"bytes,22,opt,name=album_artist_sort,json=albumArtistSort,proto3,oneof" json:"album_artist_sort,omitempty"` + AlbumSort *string `protobuf:"bytes,23,opt,name=album_sort,json=albumSort,proto3,oneof" json:"album_sort,omitempty"` + TitleSort *string `protobuf:"bytes,24,opt,name=title_sort,json=titleSort,proto3,oneof" json:"title_sort,omitempty"` + MbRecordingId *string `protobuf:"bytes,25,opt,name=mb_recording_id,json=mbRecordingId,proto3,oneof" json:"mb_recording_id,omitempty"` + MbAlbumId *string `protobuf:"bytes,26,opt,name=mb_album_id,json=mbAlbumId,proto3,oneof" json:"mb_album_id,omitempty"` + MbArtistId *string `protobuf:"bytes,27,opt,name=mb_artist_id,json=mbArtistId,proto3,oneof" json:"mb_artist_id,omitempty"` + MbAlbumArtistId *string `protobuf:"bytes,28,opt,name=mb_album_artist_id,json=mbAlbumArtistId,proto3,oneof" json:"mb_album_artist_id,omitempty"` + MbReleaseGroupId *string `protobuf:"bytes,29,opt,name=mb_release_group_id,json=mbReleaseGroupId,proto3,oneof" json:"mb_release_group_id,omitempty"` + ReplaygainTrackGain *float32 `protobuf:"fixed32,30,opt,name=replaygain_track_gain,json=replaygainTrackGain,proto3,oneof" json:"replaygain_track_gain,omitempty"` + ReplaygainTrackPeak *float32 `protobuf:"fixed32,31,opt,name=replaygain_track_peak,json=replaygainTrackPeak,proto3,oneof" json:"replaygain_track_peak,omitempty"` + ReplaygainAlbumGain *float32 `protobuf:"fixed32,32,opt,name=replaygain_album_gain,json=replaygainAlbumGain,proto3,oneof" json:"replaygain_album_gain,omitempty"` + ReplaygainAlbumPeak *float32 `protobuf:"fixed32,33,opt,name=replaygain_album_peak,json=replaygainAlbumPeak,proto3,oneof" json:"replaygain_album_peak,omitempty"` + Channels *uint32 `protobuf:"varint,34,opt,name=channels,proto3,oneof" json:"channels,omitempty"` + BitsPerSample *uint32 `protobuf:"varint,35,opt,name=bits_per_sample,json=bitsPerSample,proto3,oneof" json:"bits_per_sample,omitempty"` + Encoder *string `protobuf:"bytes,36,opt,name=encoder,proto3,oneof" json:"encoder,omitempty"` + Label *string `protobuf:"bytes,40,opt,name=label,proto3,oneof" json:"label,omitempty"` + AlbumType *string `protobuf:"bytes,41,opt,name=album_type,json=albumType,proto3,oneof" json:"album_type,omitempty"` + CoverUrl *string `protobuf:"bytes,42,opt,name=cover_url,json=coverUrl,proto3,oneof" json:"cover_url,omitempty"` + CustomTags map[string]string `protobuf:"bytes,50,rep,name=custom_tags,json=customTags,proto3" json:"custom_tags,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *MetadataResponse) Reset() { + *x = MetadataResponse{} + mi := &file_musicfs_proto_msgTypes[22] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *MetadataResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*MetadataResponse) ProtoMessage() {} + +func (x *MetadataResponse) ProtoReflect() protoreflect.Message { + mi := &file_musicfs_proto_msgTypes[22] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use MetadataResponse.ProtoReflect.Descriptor instead. +func (*MetadataResponse) Descriptor() ([]byte, []int) { + return file_musicfs_proto_rawDescGZIP(), []int{22} +} + +func (x *MetadataResponse) GetFileId() int64 { + if x != nil { + return x.FileId + } + return 0 +} + +func (x *MetadataResponse) GetTitle() string { + if x != nil && x.Title != nil { + return *x.Title + } + return "" +} + +func (x *MetadataResponse) GetArtist() string { + if x != nil && x.Artist != nil { + return *x.Artist + } + return "" +} + +func (x *MetadataResponse) GetAlbum() string { + if x != nil && x.Album != nil { + return *x.Album + } + return "" +} + +func (x *MetadataResponse) GetAlbumArtist() string { + if x != nil && x.AlbumArtist != nil { + return *x.AlbumArtist + } + return "" +} + +func (x *MetadataResponse) GetYear() uint32 { + if x != nil && x.Year != nil { + return *x.Year + } + return 0 +} + +func (x *MetadataResponse) GetTrack() uint32 { + if x != nil && x.Track != nil { + return *x.Track + } + return 0 +} + +func (x *MetadataResponse) GetDisc() uint32 { + if x != nil && x.Disc != nil { + return *x.Disc + } + return 0 +} + +func (x *MetadataResponse) GetGenre() string { + if x != nil && x.Genre != nil { + return *x.Genre + } + return "" +} + +func (x *MetadataResponse) GetFormat() string { + if x != nil && x.Format != nil { + return *x.Format + } + return "" +} + +func (x *MetadataResponse) GetDurationMs() uint64 { + if x != nil && x.DurationMs != nil { + return *x.DurationMs + } + return 0 +} + +func (x *MetadataResponse) GetBitrate() uint64 { + if x != nil && x.Bitrate != nil { + return *x.Bitrate + } + return 0 +} + +func (x *MetadataResponse) GetTrackTotal() uint32 { + if x != nil && x.TrackTotal != nil { + return *x.TrackTotal + } + return 0 +} + +func (x *MetadataResponse) GetDiscTotal() uint32 { + if x != nil && x.DiscTotal != nil { + return *x.DiscTotal + } + return 0 +} + +func (x *MetadataResponse) GetDate() string { + if x != nil && x.Date != nil { + return *x.Date + } + return "" +} + +func (x *MetadataResponse) GetComposer() string { + if x != nil && x.Composer != nil { + return *x.Composer + } + return "" +} + +func (x *MetadataResponse) GetComment() string { + if x != nil && x.Comment != nil { + return *x.Comment + } + return "" +} + +func (x *MetadataResponse) GetLyrics() string { + if x != nil && x.Lyrics != nil { + return *x.Lyrics + } + return "" +} + +func (x *MetadataResponse) GetCopyright() string { + if x != nil && x.Copyright != nil { + return *x.Copyright + } + return "" +} + +func (x *MetadataResponse) GetCompilation() bool { + if x != nil && x.Compilation != nil { + return *x.Compilation + } + return false +} + +func (x *MetadataResponse) GetArtistSort() string { + if x != nil && x.ArtistSort != nil { + return *x.ArtistSort + } + return "" +} + +func (x *MetadataResponse) GetAlbumArtistSort() string { + if x != nil && x.AlbumArtistSort != nil { + return *x.AlbumArtistSort + } + return "" +} + +func (x *MetadataResponse) GetAlbumSort() string { + if x != nil && x.AlbumSort != nil { + return *x.AlbumSort + } + return "" +} + +func (x *MetadataResponse) GetTitleSort() string { + if x != nil && x.TitleSort != nil { + return *x.TitleSort + } + return "" +} + +func (x *MetadataResponse) GetMbRecordingId() string { + if x != nil && x.MbRecordingId != nil { + return *x.MbRecordingId + } + return "" +} + +func (x *MetadataResponse) GetMbAlbumId() string { + if x != nil && x.MbAlbumId != nil { + return *x.MbAlbumId + } + return "" +} + +func (x *MetadataResponse) GetMbArtistId() string { + if x != nil && x.MbArtistId != nil { + return *x.MbArtistId + } + return "" +} + +func (x *MetadataResponse) GetMbAlbumArtistId() string { + if x != nil && x.MbAlbumArtistId != nil { + return *x.MbAlbumArtistId + } + return "" +} + +func (x *MetadataResponse) GetMbReleaseGroupId() string { + if x != nil && x.MbReleaseGroupId != nil { + return *x.MbReleaseGroupId + } + return "" +} + +func (x *MetadataResponse) GetReplaygainTrackGain() float32 { + if x != nil && x.ReplaygainTrackGain != nil { + return *x.ReplaygainTrackGain + } + return 0 +} + +func (x *MetadataResponse) GetReplaygainTrackPeak() float32 { + if x != nil && x.ReplaygainTrackPeak != nil { + return *x.ReplaygainTrackPeak + } + return 0 +} + +func (x *MetadataResponse) GetReplaygainAlbumGain() float32 { + if x != nil && x.ReplaygainAlbumGain != nil { + return *x.ReplaygainAlbumGain + } + return 0 +} + +func (x *MetadataResponse) GetReplaygainAlbumPeak() float32 { + if x != nil && x.ReplaygainAlbumPeak != nil { + return *x.ReplaygainAlbumPeak + } + return 0 +} + +func (x *MetadataResponse) GetChannels() uint32 { + if x != nil && x.Channels != nil { + return *x.Channels + } + return 0 +} + +func (x *MetadataResponse) GetBitsPerSample() uint32 { + if x != nil && x.BitsPerSample != nil { + return *x.BitsPerSample + } + return 0 +} + +func (x *MetadataResponse) GetEncoder() string { + if x != nil && x.Encoder != nil { + return *x.Encoder + } + return "" +} + +func (x *MetadataResponse) GetLabel() string { + if x != nil && x.Label != nil { + return *x.Label + } + return "" +} + +func (x *MetadataResponse) GetAlbumType() string { + if x != nil && x.AlbumType != nil { + return *x.AlbumType + } + return "" +} + +func (x *MetadataResponse) GetCoverUrl() string { + if x != nil && x.CoverUrl != nil { + return *x.CoverUrl + } + return "" +} + +func (x *MetadataResponse) GetCustomTags() map[string]string { + if x != nil { + return x.CustomTags + } + return nil +} + +type UpdateMetadataRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + FileId int64 `protobuf:"varint,1,opt,name=file_id,json=fileId,proto3" json:"file_id,omitempty"` + Title *string `protobuf:"bytes,2,opt,name=title,proto3,oneof" json:"title,omitempty"` + Artist *string `protobuf:"bytes,3,opt,name=artist,proto3,oneof" json:"artist,omitempty"` + Album *string `protobuf:"bytes,4,opt,name=album,proto3,oneof" json:"album,omitempty"` + AlbumArtist *string `protobuf:"bytes,5,opt,name=album_artist,json=albumArtist,proto3,oneof" json:"album_artist,omitempty"` + TrackNumber *uint32 `protobuf:"varint,6,opt,name=track_number,json=trackNumber,proto3,oneof" json:"track_number,omitempty"` + DiscNumber *uint32 `protobuf:"varint,7,opt,name=disc_number,json=discNumber,proto3,oneof" json:"disc_number,omitempty"` + Date *string `protobuf:"bytes,8,opt,name=date,proto3,oneof" json:"date,omitempty"` + Genre *string `protobuf:"bytes,9,opt,name=genre,proto3,oneof" json:"genre,omitempty"` + Composer *string `protobuf:"bytes,10,opt,name=composer,proto3,oneof" json:"composer,omitempty"` + Comment *string `protobuf:"bytes,11,opt,name=comment,proto3,oneof" json:"comment,omitempty"` + Lyrics *string `protobuf:"bytes,12,opt,name=lyrics,proto3,oneof" json:"lyrics,omitempty"` + Copyright *string `protobuf:"bytes,13,opt,name=copyright,proto3,oneof" json:"copyright,omitempty"` + Compilation *bool `protobuf:"varint,14,opt,name=compilation,proto3,oneof" json:"compilation,omitempty"` + ArtistSort *string `protobuf:"bytes,15,opt,name=artist_sort,json=artistSort,proto3,oneof" json:"artist_sort,omitempty"` + AlbumArtistSort *string `protobuf:"bytes,16,opt,name=album_artist_sort,json=albumArtistSort,proto3,oneof" json:"album_artist_sort,omitempty"` + AlbumSort *string `protobuf:"bytes,17,opt,name=album_sort,json=albumSort,proto3,oneof" json:"album_sort,omitempty"` + TitleSort *string `protobuf:"bytes,18,opt,name=title_sort,json=titleSort,proto3,oneof" json:"title_sort,omitempty"` + MbRecordingId *string `protobuf:"bytes,20,opt,name=mb_recording_id,json=mbRecordingId,proto3,oneof" json:"mb_recording_id,omitempty"` + MbAlbumId *string `protobuf:"bytes,21,opt,name=mb_album_id,json=mbAlbumId,proto3,oneof" json:"mb_album_id,omitempty"` + MbArtistId *string `protobuf:"bytes,22,opt,name=mb_artist_id,json=mbArtistId,proto3,oneof" json:"mb_artist_id,omitempty"` + ReplaygainTrackGain *float32 `protobuf:"fixed32,30,opt,name=replaygain_track_gain,json=replaygainTrackGain,proto3,oneof" json:"replaygain_track_gain,omitempty"` + ReplaygainTrackPeak *float32 `protobuf:"fixed32,31,opt,name=replaygain_track_peak,json=replaygainTrackPeak,proto3,oneof" json:"replaygain_track_peak,omitempty"` + ReplaygainAlbumGain *float32 `protobuf:"fixed32,32,opt,name=replaygain_album_gain,json=replaygainAlbumGain,proto3,oneof" json:"replaygain_album_gain,omitempty"` + ReplaygainAlbumPeak *float32 `protobuf:"fixed32,33,opt,name=replaygain_album_peak,json=replaygainAlbumPeak,proto3,oneof" json:"replaygain_album_peak,omitempty"` + Label *string `protobuf:"bytes,40,opt,name=label,proto3,oneof" json:"label,omitempty"` + AlbumType *string `protobuf:"bytes,41,opt,name=album_type,json=albumType,proto3,oneof" json:"album_type,omitempty"` + CoverUrl *string `protobuf:"bytes,42,opt,name=cover_url,json=coverUrl,proto3,oneof" json:"cover_url,omitempty"` + CustomTags map[string]string `protobuf:"bytes,50,rep,name=custom_tags,json=customTags,proto3" json:"custom_tags,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *UpdateMetadataRequest) Reset() { + *x = UpdateMetadataRequest{} + mi := &file_musicfs_proto_msgTypes[23] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *UpdateMetadataRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*UpdateMetadataRequest) ProtoMessage() {} + +func (x *UpdateMetadataRequest) ProtoReflect() protoreflect.Message { + mi := &file_musicfs_proto_msgTypes[23] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use UpdateMetadataRequest.ProtoReflect.Descriptor instead. +func (*UpdateMetadataRequest) Descriptor() ([]byte, []int) { + return file_musicfs_proto_rawDescGZIP(), []int{23} +} + +func (x *UpdateMetadataRequest) GetFileId() int64 { + if x != nil { + return x.FileId + } + return 0 +} + +func (x *UpdateMetadataRequest) GetTitle() string { + if x != nil && x.Title != nil { + return *x.Title + } + return "" +} + +func (x *UpdateMetadataRequest) GetArtist() string { + if x != nil && x.Artist != nil { + return *x.Artist + } + return "" +} + +func (x *UpdateMetadataRequest) GetAlbum() string { + if x != nil && x.Album != nil { + return *x.Album + } + return "" +} + +func (x *UpdateMetadataRequest) GetAlbumArtist() string { + if x != nil && x.AlbumArtist != nil { + return *x.AlbumArtist + } + return "" +} + +func (x *UpdateMetadataRequest) GetTrackNumber() uint32 { + if x != nil && x.TrackNumber != nil { + return *x.TrackNumber + } + return 0 +} + +func (x *UpdateMetadataRequest) GetDiscNumber() uint32 { + if x != nil && x.DiscNumber != nil { + return *x.DiscNumber + } + return 0 +} + +func (x *UpdateMetadataRequest) GetDate() string { + if x != nil && x.Date != nil { + return *x.Date + } + return "" +} + +func (x *UpdateMetadataRequest) GetGenre() string { + if x != nil && x.Genre != nil { + return *x.Genre + } + return "" +} + +func (x *UpdateMetadataRequest) GetComposer() string { + if x != nil && x.Composer != nil { + return *x.Composer + } + return "" +} + +func (x *UpdateMetadataRequest) GetComment() string { + if x != nil && x.Comment != nil { + return *x.Comment + } + return "" +} + +func (x *UpdateMetadataRequest) GetLyrics() string { + if x != nil && x.Lyrics != nil { + return *x.Lyrics + } + return "" +} + +func (x *UpdateMetadataRequest) GetCopyright() string { + if x != nil && x.Copyright != nil { + return *x.Copyright + } + return "" +} + +func (x *UpdateMetadataRequest) GetCompilation() bool { + if x != nil && x.Compilation != nil { + return *x.Compilation + } + return false +} + +func (x *UpdateMetadataRequest) GetArtistSort() string { + if x != nil && x.ArtistSort != nil { + return *x.ArtistSort + } + return "" +} + +func (x *UpdateMetadataRequest) GetAlbumArtistSort() string { + if x != nil && x.AlbumArtistSort != nil { + return *x.AlbumArtistSort + } + return "" +} + +func (x *UpdateMetadataRequest) GetAlbumSort() string { + if x != nil && x.AlbumSort != nil { + return *x.AlbumSort + } + return "" +} + +func (x *UpdateMetadataRequest) GetTitleSort() string { + if x != nil && x.TitleSort != nil { + return *x.TitleSort + } + return "" +} + +func (x *UpdateMetadataRequest) GetMbRecordingId() string { + if x != nil && x.MbRecordingId != nil { + return *x.MbRecordingId + } + return "" +} + +func (x *UpdateMetadataRequest) GetMbAlbumId() string { + if x != nil && x.MbAlbumId != nil { + return *x.MbAlbumId + } + return "" +} + +func (x *UpdateMetadataRequest) GetMbArtistId() string { + if x != nil && x.MbArtistId != nil { + return *x.MbArtistId + } + return "" +} + +func (x *UpdateMetadataRequest) GetReplaygainTrackGain() float32 { + if x != nil && x.ReplaygainTrackGain != nil { + return *x.ReplaygainTrackGain + } + return 0 +} + +func (x *UpdateMetadataRequest) GetReplaygainTrackPeak() float32 { + if x != nil && x.ReplaygainTrackPeak != nil { + return *x.ReplaygainTrackPeak + } + return 0 +} + +func (x *UpdateMetadataRequest) GetReplaygainAlbumGain() float32 { + if x != nil && x.ReplaygainAlbumGain != nil { + return *x.ReplaygainAlbumGain + } + return 0 +} + +func (x *UpdateMetadataRequest) GetReplaygainAlbumPeak() float32 { + if x != nil && x.ReplaygainAlbumPeak != nil { + return *x.ReplaygainAlbumPeak + } + return 0 +} + +func (x *UpdateMetadataRequest) GetLabel() string { + if x != nil && x.Label != nil { + return *x.Label + } + return "" +} + +func (x *UpdateMetadataRequest) GetAlbumType() string { + if x != nil && x.AlbumType != nil { + return *x.AlbumType + } + return "" +} + +func (x *UpdateMetadataRequest) GetCoverUrl() string { + if x != nil && x.CoverUrl != nil { + return *x.CoverUrl + } + return "" +} + +func (x *UpdateMetadataRequest) GetCustomTags() map[string]string { + if x != nil { + return x.CustomTags + } + return nil +} + +type UpdateMetadataResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + FileId int64 `protobuf:"varint,1,opt,name=file_id,json=fileId,proto3" json:"file_id,omitempty"` + Success bool `protobuf:"varint,2,opt,name=success,proto3" json:"success,omitempty"` + ErrorMessage *string `protobuf:"bytes,3,opt,name=error_message,json=errorMessage,proto3,oneof" json:"error_message,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *UpdateMetadataResponse) Reset() { + *x = UpdateMetadataResponse{} + mi := &file_musicfs_proto_msgTypes[24] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *UpdateMetadataResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*UpdateMetadataResponse) ProtoMessage() {} + +func (x *UpdateMetadataResponse) ProtoReflect() protoreflect.Message { + mi := &file_musicfs_proto_msgTypes[24] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use UpdateMetadataResponse.ProtoReflect.Descriptor instead. +func (*UpdateMetadataResponse) Descriptor() ([]byte, []int) { + return file_musicfs_proto_rawDescGZIP(), []int{24} +} + +func (x *UpdateMetadataResponse) GetFileId() int64 { + if x != nil { + return x.FileId + } + return 0 +} + +func (x *UpdateMetadataResponse) GetSuccess() bool { + if x != nil { + return x.Success + } + return false +} + +func (x *UpdateMetadataResponse) GetErrorMessage() string { + if x != nil && x.ErrorMessage != nil { + return *x.ErrorMessage + } + return "" +} + +type ClearOverlayRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + FileId int64 `protobuf:"varint,1,opt,name=file_id,json=fileId,proto3" json:"file_id,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ClearOverlayRequest) Reset() { + *x = ClearOverlayRequest{} + mi := &file_musicfs_proto_msgTypes[25] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ClearOverlayRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ClearOverlayRequest) ProtoMessage() {} + +func (x *ClearOverlayRequest) ProtoReflect() protoreflect.Message { + mi := &file_musicfs_proto_msgTypes[25] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ClearOverlayRequest.ProtoReflect.Descriptor instead. +func (*ClearOverlayRequest) Descriptor() ([]byte, []int) { + return file_musicfs_proto_rawDescGZIP(), []int{25} +} + +func (x *ClearOverlayRequest) GetFileId() int64 { + if x != nil { + return x.FileId + } + return 0 +} + +type ClearOverlayResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + FileId int64 `protobuf:"varint,1,opt,name=file_id,json=fileId,proto3" json:"file_id,omitempty"` + Success bool `protobuf:"varint,2,opt,name=success,proto3" json:"success,omitempty"` + ErrorMessage *string `protobuf:"bytes,3,opt,name=error_message,json=errorMessage,proto3,oneof" json:"error_message,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ClearOverlayResponse) Reset() { + *x = ClearOverlayResponse{} + mi := &file_musicfs_proto_msgTypes[26] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ClearOverlayResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ClearOverlayResponse) ProtoMessage() {} + +func (x *ClearOverlayResponse) ProtoReflect() protoreflect.Message { + mi := &file_musicfs_proto_msgTypes[26] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ClearOverlayResponse.ProtoReflect.Descriptor instead. +func (*ClearOverlayResponse) Descriptor() ([]byte, []int) { + return file_musicfs_proto_rawDescGZIP(), []int{26} +} + +func (x *ClearOverlayResponse) GetFileId() int64 { + if x != nil { + return x.FileId + } + return 0 +} + +func (x *ClearOverlayResponse) GetSuccess() bool { + if x != nil { + return x.Success + } + return false +} + +func (x *ClearOverlayResponse) GetErrorMessage() string { + if x != nil && x.ErrorMessage != nil { + return *x.ErrorMessage + } + return "" +} + +type BatchUpdateRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + Items []*BatchUpdateItem `protobuf:"bytes,1,rep,name=items,proto3" json:"items,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *BatchUpdateRequest) Reset() { + *x = BatchUpdateRequest{} + mi := &file_musicfs_proto_msgTypes[27] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *BatchUpdateRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*BatchUpdateRequest) ProtoMessage() {} + +func (x *BatchUpdateRequest) ProtoReflect() protoreflect.Message { + mi := &file_musicfs_proto_msgTypes[27] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use BatchUpdateRequest.ProtoReflect.Descriptor instead. +func (*BatchUpdateRequest) Descriptor() ([]byte, []int) { + return file_musicfs_proto_rawDescGZIP(), []int{27} +} + +func (x *BatchUpdateRequest) GetItems() []*BatchUpdateItem { + if x != nil { + return x.Items + } + return nil +} + +type BatchUpdateItem struct { + state protoimpl.MessageState `protogen:"open.v1"` + FileId int64 `protobuf:"varint,1,opt,name=file_id,json=fileId,proto3" json:"file_id,omitempty"` + Metadata *UpdateMetadataRequest `protobuf:"bytes,2,opt,name=metadata,proto3" json:"metadata,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *BatchUpdateItem) Reset() { + *x = BatchUpdateItem{} + mi := &file_musicfs_proto_msgTypes[28] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *BatchUpdateItem) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*BatchUpdateItem) ProtoMessage() {} + +func (x *BatchUpdateItem) ProtoReflect() protoreflect.Message { + mi := &file_musicfs_proto_msgTypes[28] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use BatchUpdateItem.ProtoReflect.Descriptor instead. +func (*BatchUpdateItem) Descriptor() ([]byte, []int) { + return file_musicfs_proto_rawDescGZIP(), []int{28} +} + +func (x *BatchUpdateItem) GetFileId() int64 { + if x != nil { + return x.FileId + } + return 0 +} + +func (x *BatchUpdateItem) GetMetadata() *UpdateMetadataRequest { + if x != nil { + return x.Metadata + } + return nil +} + +type BatchUpdateProgress struct { + state protoimpl.MessageState `protogen:"open.v1"` + Completed uint32 `protobuf:"varint,1,opt,name=completed,proto3" json:"completed,omitempty"` + Total uint32 `protobuf:"varint,2,opt,name=total,proto3" json:"total,omitempty"` + CurrentFileId *int64 `protobuf:"varint,3,opt,name=current_file_id,json=currentFileId,proto3,oneof" json:"current_file_id,omitempty"` + ErrorMessage *string `protobuf:"bytes,4,opt,name=error_message,json=errorMessage,proto3,oneof" json:"error_message,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *BatchUpdateProgress) Reset() { + *x = BatchUpdateProgress{} + mi := &file_musicfs_proto_msgTypes[29] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *BatchUpdateProgress) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*BatchUpdateProgress) ProtoMessage() {} + +func (x *BatchUpdateProgress) ProtoReflect() protoreflect.Message { + mi := &file_musicfs_proto_msgTypes[29] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use BatchUpdateProgress.ProtoReflect.Descriptor instead. +func (*BatchUpdateProgress) Descriptor() ([]byte, []int) { + return file_musicfs_proto_rawDescGZIP(), []int{29} +} + +func (x *BatchUpdateProgress) GetCompleted() uint32 { + if x != nil { + return x.Completed + } + return 0 +} + +func (x *BatchUpdateProgress) GetTotal() uint32 { + if x != nil { + return x.Total + } + return 0 +} + +func (x *BatchUpdateProgress) GetCurrentFileId() int64 { + if x != nil && x.CurrentFileId != nil { + return *x.CurrentFileId + } + return 0 +} + +func (x *BatchUpdateProgress) GetErrorMessage() string { + if x != nil && x.ErrorMessage != nil { + return *x.ErrorMessage + } + return "" +} + +type ImportMetadataRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + SourcePath string `protobuf:"bytes,1,opt,name=source_path,json=sourcePath,proto3" json:"source_path,omitempty"` + Format *string `protobuf:"bytes,2,opt,name=format,proto3,oneof" json:"format,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ImportMetadataRequest) Reset() { + *x = ImportMetadataRequest{} + mi := &file_musicfs_proto_msgTypes[30] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ImportMetadataRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ImportMetadataRequest) ProtoMessage() {} + +func (x *ImportMetadataRequest) ProtoReflect() protoreflect.Message { + mi := &file_musicfs_proto_msgTypes[30] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ImportMetadataRequest.ProtoReflect.Descriptor instead. +func (*ImportMetadataRequest) Descriptor() ([]byte, []int) { + return file_musicfs_proto_rawDescGZIP(), []int{30} +} + +func (x *ImportMetadataRequest) GetSourcePath() string { + if x != nil { + return x.SourcePath + } + return "" +} + +func (x *ImportMetadataRequest) GetFormat() string { + if x != nil && x.Format != nil { + return *x.Format + } + return "" +} + +type ImportProgress struct { + state protoimpl.MessageState `protogen:"open.v1"` + Imported uint32 `protobuf:"varint,1,opt,name=imported,proto3" json:"imported,omitempty"` + Total uint32 `protobuf:"varint,2,opt,name=total,proto3" json:"total,omitempty"` + CurrentFile *string `protobuf:"bytes,3,opt,name=current_file,json=currentFile,proto3,oneof" json:"current_file,omitempty"` + ErrorMessage *string `protobuf:"bytes,4,opt,name=error_message,json=errorMessage,proto3,oneof" json:"error_message,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ImportProgress) Reset() { + *x = ImportProgress{} + mi := &file_musicfs_proto_msgTypes[31] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ImportProgress) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ImportProgress) ProtoMessage() {} + +func (x *ImportProgress) ProtoReflect() protoreflect.Message { + mi := &file_musicfs_proto_msgTypes[31] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ImportProgress.ProtoReflect.Descriptor instead. +func (*ImportProgress) Descriptor() ([]byte, []int) { + return file_musicfs_proto_rawDescGZIP(), []int{31} +} + +func (x *ImportProgress) GetImported() uint32 { + if x != nil { + return x.Imported + } + return 0 +} + +func (x *ImportProgress) GetTotal() uint32 { + if x != nil { + return x.Total + } + return 0 +} + +func (x *ImportProgress) GetCurrentFile() string { + if x != nil && x.CurrentFile != nil { + return *x.CurrentFile + } + return "" +} + +func (x *ImportProgress) GetErrorMessage() string { + if x != nil && x.ErrorMessage != nil { + return *x.ErrorMessage + } + return "" +} + +var File_musicfs_proto protoreflect.FileDescriptor + +const file_musicfs_proto_rawDesc = "" + + "\n" + + "\rmusicfs.proto\x12\n" + + "musicfs.v1\"\a\n" + + "\x05Empty\"\xa2\x01\n" + + "\rSearchRequest\x12\x14\n" + + "\x05query\x18\x01 \x01(\tR\x05query\x12\x19\n" + + "\x05limit\x18\x02 \x01(\rH\x00R\x05limit\x88\x01\x01\x12\x1b\n" + + "\x06offset\x18\x03 \x01(\rH\x01R\x06offset\x88\x01\x01\x12 \n" + + "\torigin_id\x18\x04 \x01(\tH\x02R\boriginId\x88\x01\x01B\b\n" + + "\x06_limitB\t\n" + + "\a_offsetB\f\n" + + "\n" + + "_origin_id\"\x8d\x01\n" + + "\x0eSearchResponse\x122\n" + + "\aresults\x18\x01 \x03(\v2\x18.musicfs.v1.SearchResultR\aresults\x12#\n" + + "\rtotal_matches\x18\x02 \x01(\x04R\ftotalMatches\x12\"\n" + + "\rquery_time_ms\x18\x03 \x01(\rR\vqueryTimeMs\"\xdb\x02\n" + + "\fSearchResult\x12\x17\n" + + "\afile_id\x18\x01 \x01(\x03R\x06fileId\x12!\n" + + "\fvirtual_path\x18\x02 \x01(\tR\vvirtualPath\x12\x1b\n" + + "\x06artist\x18\x03 \x01(\tH\x00R\x06artist\x88\x01\x01\x12\x19\n" + + "\x05album\x18\x04 \x01(\tH\x01R\x05album\x88\x01\x01\x12\x19\n" + + "\x05title\x18\x05 \x01(\tH\x02R\x05title\x88\x01\x01\x12\x14\n" + + "\x05score\x18\x06 \x01(\x02R\x05score\x12H\n" + + "\n" + + "highlights\x18\a \x03(\v2(.musicfs.v1.SearchResult.HighlightsEntryR\n" + + "highlights\x1a=\n" + + "\x0fHighlightsEntry\x12\x10\n" + + "\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n" + + "\x05value\x18\x02 \x01(\tR\x05value:\x028\x01B\t\n" + + "\a_artistB\b\n" + + "\x06_albumB\b\n" + + "\x06_title\"\xef\x02\n" + + "\x0eStatusResponse\x12\x18\n" + + "\aversion\x18\x01 \x01(\tR\aversion\x12\x1f\n" + + "\vuptime_secs\x18\x02 \x01(\x04R\n" + + "uptimeSecs\x12\x1f\n" + + "\vmount_point\x18\x03 \x01(\tR\n" + + "mountPoint\x12,\n" + + "\x05state\x18\x04 \x01(\x0e2\x16.musicfs.v1.MountStateR\x05state\x12*\n" + + "\x11open_file_handles\x18\x05 \x01(\rR\x0fopenFileHandles\x12$\n" + + "\x0efuse_ops_total\x18\x06 \x01(\x04R\ffuseOpsTotal\x12#\n" + + "\rfiles_indexed\x18\a \x01(\x04R\ffilesIndexed\x12(\n" + + "\x10cache_size_bytes\x18\b \x01(\x04R\x0ecacheSizeBytes\x122\n" + + "\aorigins\x18\t \x03(\v2\x18.musicfs.v1.OriginStatusR\aorigins\"\x92\x01\n" + + "\fOriginStatus\x12\x0e\n" + + "\x02id\x18\x01 \x01(\tR\x02id\x12\x1f\n" + + "\vorigin_type\x18\x02 \x01(\tR\n" + + "originType\x120\n" + + "\x06health\x18\x03 \x01(\x0e2\x18.musicfs.v1.HealthStatusR\x06health\x12\x1f\n" + + "\vfiles_count\x18\x04 \x01(\x04R\n" + + "filesCount\"P\n" + + "\x0fShutdownRequest\x12\x1a\n" + + "\bgraceful\x18\x01 \x01(\bR\bgraceful\x12!\n" + + "\ftimeout_secs\x18\x02 \x01(\rR\vtimeoutSecs\"p\n" + + "\tTierStats\x12\x18\n" + + "\aentries\x18\x01 \x01(\x04R\aentries\x12\x1d\n" + + "\n" + + "size_bytes\x18\x02 \x01(\x04R\tsizeBytes\x12\x12\n" + + "\x04hits\x18\x03 \x01(\x04R\x04hits\x12\x16\n" + + "\x06misses\x18\x04 \x01(\x04R\x06misses\"\xbc\x04\n" + + "\n" + + "CacheStats\x12(\n" + + "\x10total_size_bytes\x18\x01 \x01(\x04R\x0etotalSizeBytes\x12&\n" + + "\x0fused_size_bytes\x18\x02 \x01(\x04R\rusedSizeBytes\x12(\n" + + "\x10size_limit_bytes\x18\x03 \x01(\x04R\x0esizeLimitBytes\x12\x1f\n" + + "\vchunk_count\x18\x04 \x01(\x04R\n" + + "chunkCount\x12#\n" + + "\rchunks_unique\x18\x05 \x01(\x04R\fchunksUnique\x12\x1f\n" + + "\vdedup_ratio\x18\x06 \x01(\x01R\n" + + "dedupRatio\x12\x1b\n" + + "\thit_count\x18\a \x01(\x04R\bhitCount\x12\x1d\n" + + "\n" + + "miss_count\x18\b \x01(\x04R\tmissCount\x12\x1b\n" + + "\thit_ratio\x18\t \x01(\x01R\bhitRatio\x12)\n" + + "\x10metadata_entries\x18\n" + + " \x01(\x04R\x0fmetadataEntries\x12%\n" + + "\x0emetadata_bytes\x18\v \x01(\x04R\rmetadataBytes\x126\n" + + "\vl1_metadata\x18\f \x01(\v2\x15.musicfs.v1.TierStatsR\n" + + "l1Metadata\x124\n" + + "\n" + + "l2_headers\x18\r \x01(\v2\x15.musicfs.v1.TierStatsR\tl2Headers\x122\n" + + "\tl3_chunks\x18\x0e \x01(\v2\x15.musicfs.v1.TierStatsR\bl3Chunks\"\x8d\x01\n" + + "\x11ClearCacheRequest\x12 \n" + + "\torigin_id\x18\x01 \x01(\tH\x00R\boriginId\x88\x01\x01\x12%\n" + + "\x0eclear_metadata\x18\x02 \x01(\bR\rclearMetadata\x12!\n" + + "\fclear_chunks\x18\x03 \x01(\bR\vclearChunksB\f\n" + + "\n" + + "_origin_id\"`\n" + + "\x12ClearCacheResponse\x12#\n" + + "\rbytes_cleared\x18\x01 \x01(\x04R\fbytesCleared\x12%\n" + + "\x0echunks_cleared\x18\x02 \x01(\x04R\rchunksCleared\"W\n" + + "\x0fPrefetchRequest\x12\x14\n" + + "\x05paths\x18\x01 \x03(\tR\x05paths\x12 \n" + + "\torigin_id\x18\x02 \x01(\tH\x00R\boriginId\x88\x01\x01B\f\n" + + "\n" + + "_origin_id\"\x8e\x01\n" + + "\x10PrefetchProgress\x12!\n" + + "\fcurrent_path\x18\x01 \x01(\tR\vcurrentPath\x12\x1c\n" + + "\tcompleted\x18\x02 \x01(\rR\tcompleted\x12\x14\n" + + "\x05total\x18\x03 \x01(\rR\x05total\x12#\n" + + "\rbytes_fetched\x18\x04 \x01(\x04R\fbytesFetched\"C\n" + + "\x0fOriginsResponse\x120\n" + + "\aorigins\x18\x01 \x03(\v2\x16.musicfs.v1.OriginInfoR\aorigins\"\xfa\x01\n" + + "\n" + + "OriginInfo\x12\x0e\n" + + "\x02id\x18\x01 \x01(\tR\x02id\x12\x1f\n" + + "\vorigin_type\x18\x02 \x01(\tR\n" + + "originType\x12!\n" + + "\fdisplay_name\x18\x03 \x01(\tR\vdisplayName\x12\x1b\n" + + "\troot_path\x18\x04 \x01(\tR\brootPath\x120\n" + + "\x06health\x18\x05 \x01(\x0e2\x18.musicfs.v1.HealthStatusR\x06health\x12\x1f\n" + + "\vfiles_count\x18\x06 \x01(\x04R\n" + + "filesCount\x12(\n" + + "\x10total_size_bytes\x18\a \x01(\x04R\x0etotalSizeBytes\"T\n" + + "\rOriginRequest\x12\x1b\n" + + "\torigin_id\x18\x01 \x01(\tR\boriginId\x12\x1b\n" + + "\x06subdir\x18\x02 \x01(\tH\x00R\x06subdir\x88\x01\x01B\t\n" + + "\a_subdir\"\xb8\x01\n" + + "\x14OriginHealthResponse\x12\x1b\n" + + "\torigin_id\x18\x01 \x01(\tR\boriginId\x120\n" + + "\x06status\x18\x02 \x01(\x0e2\x18.musicfs.v1.HealthStatusR\x06status\x12\x1d\n" + + "\amessage\x18\x03 \x01(\tH\x00R\amessage\x88\x01\x01\x12&\n" + + "\x0flast_check_secs\x18\x04 \x01(\x04R\rlastCheckSecsB\n" + + "\n" + + "\b_message\"\xcf\x01\n" + + "\fSyncProgress\x12\x14\n" + + "\x05phase\x18\x01 \x01(\tR\x05phase\x12\x18\n" + + "\acurrent\x18\x02 \x01(\rR\acurrent\x12\x14\n" + + "\x05total\x18\x03 \x01(\rR\x05total\x12!\n" + + "\fcurrent_path\x18\x04 \x01(\tR\vcurrentPath\x12!\n" + + "\fbytes_synced\x18\x05 \x01(\x04R\vbytesSynced\x123\n" + + "\tnew_files\x18\x06 \x03(\v2\x16.musicfs.v1.SyncedFileR\bnewFiles\"\\\n" + + "\n" + + "SyncedFile\x12\x12\n" + + "\x04path\x18\x01 \x01(\tR\x04path\x12\x17\n" + + "\afile_id\x18\x02 \x01(\x03R\x06fileId\x12!\n" + + "\fvirtual_path\x18\x03 \x01(\tR\vvirtualPath\"^\n" + + "\vEventFilter\x12\x1f\n" + + "\vevent_types\x18\x01 \x03(\tR\n" + + "eventTypes\x12 \n" + + "\torigin_id\x18\x02 \x01(\tH\x00R\boriginId\x88\x01\x01B\f\n" + + "\n" + + "_origin_id\"\xbf\x02\n" + + "\x05Event\x12\x1d\n" + + "\n" + + "event_type\x18\x01 \x01(\tR\teventType\x12!\n" + + "\ftimestamp_ms\x18\x02 \x01(\x03R\vtimestampMs\x12 \n" + + "\torigin_id\x18\x03 \x01(\tH\x00R\boriginId\x88\x01\x01\x12\x17\n" + + "\x04path\x18\x04 \x01(\tH\x01R\x04path\x88\x01\x01\x12\x1c\n" + + "\afile_id\x18\x05 \x01(\x03H\x02R\x06fileId\x88\x01\x01\x12;\n" + + "\bmetadata\x18\x06 \x03(\v2\x1f.musicfs.v1.Event.MetadataEntryR\bmetadata\x1a;\n" + + "\rMetadataEntry\x12\x10\n" + + "\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n" + + "\x05value\x18\x02 \x01(\tR\x05value:\x028\x01B\f\n" + + "\n" + + "_origin_idB\a\n" + + "\x05_pathB\n" + + "\n" + + "\b_file_id\"7\n" + + "\x12GetMetadataRequest\x12!\n" + + "\fvirtual_path\x18\x01 \x01(\tR\vvirtualPath\"\x83\x11\n" + + "\x10MetadataResponse\x12\x17\n" + + "\afile_id\x18\x01 \x01(\x03R\x06fileId\x12\x19\n" + + "\x05title\x18\x02 \x01(\tH\x00R\x05title\x88\x01\x01\x12\x1b\n" + + "\x06artist\x18\x03 \x01(\tH\x01R\x06artist\x88\x01\x01\x12\x19\n" + + "\x05album\x18\x04 \x01(\tH\x02R\x05album\x88\x01\x01\x12&\n" + + "\falbum_artist\x18\x05 \x01(\tH\x03R\valbumArtist\x88\x01\x01\x12\x17\n" + + "\x04year\x18\x06 \x01(\rH\x04R\x04year\x88\x01\x01\x12\x19\n" + + "\x05track\x18\a \x01(\rH\x05R\x05track\x88\x01\x01\x12\x17\n" + + "\x04disc\x18\b \x01(\rH\x06R\x04disc\x88\x01\x01\x12\x19\n" + + "\x05genre\x18\t \x01(\tH\aR\x05genre\x88\x01\x01\x12\x1b\n" + + "\x06format\x18\n" + + " \x01(\tH\bR\x06format\x88\x01\x01\x12$\n" + + "\vduration_ms\x18\v \x01(\x04H\tR\n" + + "durationMs\x88\x01\x01\x12\x1d\n" + + "\abitrate\x18\f \x01(\x04H\n" + + "R\abitrate\x88\x01\x01\x12$\n" + + "\vtrack_total\x18\r \x01(\rH\vR\n" + + "trackTotal\x88\x01\x01\x12\"\n" + + "\n" + + "disc_total\x18\x0e \x01(\rH\fR\tdiscTotal\x88\x01\x01\x12\x17\n" + + "\x04date\x18\x0f \x01(\tH\rR\x04date\x88\x01\x01\x12\x1f\n" + + "\bcomposer\x18\x10 \x01(\tH\x0eR\bcomposer\x88\x01\x01\x12\x1d\n" + + "\acomment\x18\x11 \x01(\tH\x0fR\acomment\x88\x01\x01\x12\x1b\n" + + "\x06lyrics\x18\x12 \x01(\tH\x10R\x06lyrics\x88\x01\x01\x12!\n" + + "\tcopyright\x18\x13 \x01(\tH\x11R\tcopyright\x88\x01\x01\x12%\n" + + "\vcompilation\x18\x14 \x01(\bH\x12R\vcompilation\x88\x01\x01\x12$\n" + + "\vartist_sort\x18\x15 \x01(\tH\x13R\n" + + "artistSort\x88\x01\x01\x12/\n" + + "\x11album_artist_sort\x18\x16 \x01(\tH\x14R\x0falbumArtistSort\x88\x01\x01\x12\"\n" + + "\n" + + "album_sort\x18\x17 \x01(\tH\x15R\talbumSort\x88\x01\x01\x12\"\n" + + "\n" + + "title_sort\x18\x18 \x01(\tH\x16R\ttitleSort\x88\x01\x01\x12+\n" + + "\x0fmb_recording_id\x18\x19 \x01(\tH\x17R\rmbRecordingId\x88\x01\x01\x12#\n" + + "\vmb_album_id\x18\x1a \x01(\tH\x18R\tmbAlbumId\x88\x01\x01\x12%\n" + + "\fmb_artist_id\x18\x1b \x01(\tH\x19R\n" + + "mbArtistId\x88\x01\x01\x120\n" + + "\x12mb_album_artist_id\x18\x1c \x01(\tH\x1aR\x0fmbAlbumArtistId\x88\x01\x01\x122\n" + + "\x13mb_release_group_id\x18\x1d \x01(\tH\x1bR\x10mbReleaseGroupId\x88\x01\x01\x127\n" + + "\x15replaygain_track_gain\x18\x1e \x01(\x02H\x1cR\x13replaygainTrackGain\x88\x01\x01\x127\n" + + "\x15replaygain_track_peak\x18\x1f \x01(\x02H\x1dR\x13replaygainTrackPeak\x88\x01\x01\x127\n" + + "\x15replaygain_album_gain\x18 \x01(\x02H\x1eR\x13replaygainAlbumGain\x88\x01\x01\x127\n" + + "\x15replaygain_album_peak\x18! \x01(\x02H\x1fR\x13replaygainAlbumPeak\x88\x01\x01\x12\x1f\n" + + "\bchannels\x18\" \x01(\rH R\bchannels\x88\x01\x01\x12+\n" + + "\x0fbits_per_sample\x18# \x01(\rH!R\rbitsPerSample\x88\x01\x01\x12\x1d\n" + + "\aencoder\x18$ \x01(\tH\"R\aencoder\x88\x01\x01\x12\x19\n" + + "\x05label\x18( \x01(\tH#R\x05label\x88\x01\x01\x12\"\n" + + "\n" + + "album_type\x18) \x01(\tH$R\talbumType\x88\x01\x01\x12 \n" + + "\tcover_url\x18* \x01(\tH%R\bcoverUrl\x88\x01\x01\x12M\n" + + "\vcustom_tags\x182 \x03(\v2,.musicfs.v1.MetadataResponse.CustomTagsEntryR\n" + + "customTags\x1a=\n" + + "\x0fCustomTagsEntry\x12\x10\n" + + "\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n" + + "\x05value\x18\x02 \x01(\tR\x05value:\x028\x01B\b\n" + + "\x06_titleB\t\n" + + "\a_artistB\b\n" + + "\x06_albumB\x0f\n" + + "\r_album_artistB\a\n" + + "\x05_yearB\b\n" + + "\x06_trackB\a\n" + + "\x05_discB\b\n" + + "\x06_genreB\t\n" + + "\a_formatB\x0e\n" + + "\f_duration_msB\n" + + "\n" + + "\b_bitrateB\x0e\n" + + "\f_track_totalB\r\n" + + "\v_disc_totalB\a\n" + + "\x05_dateB\v\n" + + "\t_composerB\n" + + "\n" + + "\b_commentB\t\n" + + "\a_lyricsB\f\n" + + "\n" + + "_copyrightB\x0e\n" + + "\f_compilationB\x0e\n" + + "\f_artist_sortB\x14\n" + + "\x12_album_artist_sortB\r\n" + + "\v_album_sortB\r\n" + + "\v_title_sortB\x12\n" + + "\x10_mb_recording_idB\x0e\n" + + "\f_mb_album_idB\x0f\n" + + "\r_mb_artist_idB\x15\n" + + "\x13_mb_album_artist_idB\x16\n" + + "\x14_mb_release_group_idB\x18\n" + + "\x16_replaygain_track_gainB\x18\n" + + "\x16_replaygain_track_peakB\x18\n" + + "\x16_replaygain_album_gainB\x18\n" + + "\x16_replaygain_album_peakB\v\n" + + "\t_channelsB\x12\n" + + "\x10_bits_per_sampleB\n" + + "\n" + + "\b_encoderB\b\n" + + "\x06_labelB\r\n" + + "\v_album_typeB\f\n" + + "\n" + + "_cover_url\"\xf2\f\n" + + "\x15UpdateMetadataRequest\x12\x17\n" + + "\afile_id\x18\x01 \x01(\x03R\x06fileId\x12\x19\n" + + "\x05title\x18\x02 \x01(\tH\x00R\x05title\x88\x01\x01\x12\x1b\n" + + "\x06artist\x18\x03 \x01(\tH\x01R\x06artist\x88\x01\x01\x12\x19\n" + + "\x05album\x18\x04 \x01(\tH\x02R\x05album\x88\x01\x01\x12&\n" + + "\falbum_artist\x18\x05 \x01(\tH\x03R\valbumArtist\x88\x01\x01\x12&\n" + + "\ftrack_number\x18\x06 \x01(\rH\x04R\vtrackNumber\x88\x01\x01\x12$\n" + + "\vdisc_number\x18\a \x01(\rH\x05R\n" + + "discNumber\x88\x01\x01\x12\x17\n" + + "\x04date\x18\b \x01(\tH\x06R\x04date\x88\x01\x01\x12\x19\n" + + "\x05genre\x18\t \x01(\tH\aR\x05genre\x88\x01\x01\x12\x1f\n" + + "\bcomposer\x18\n" + + " \x01(\tH\bR\bcomposer\x88\x01\x01\x12\x1d\n" + + "\acomment\x18\v \x01(\tH\tR\acomment\x88\x01\x01\x12\x1b\n" + + "\x06lyrics\x18\f \x01(\tH\n" + + "R\x06lyrics\x88\x01\x01\x12!\n" + + "\tcopyright\x18\r \x01(\tH\vR\tcopyright\x88\x01\x01\x12%\n" + + "\vcompilation\x18\x0e \x01(\bH\fR\vcompilation\x88\x01\x01\x12$\n" + + "\vartist_sort\x18\x0f \x01(\tH\rR\n" + + "artistSort\x88\x01\x01\x12/\n" + + "\x11album_artist_sort\x18\x10 \x01(\tH\x0eR\x0falbumArtistSort\x88\x01\x01\x12\"\n" + + "\n" + + "album_sort\x18\x11 \x01(\tH\x0fR\talbumSort\x88\x01\x01\x12\"\n" + + "\n" + + "title_sort\x18\x12 \x01(\tH\x10R\ttitleSort\x88\x01\x01\x12+\n" + + "\x0fmb_recording_id\x18\x14 \x01(\tH\x11R\rmbRecordingId\x88\x01\x01\x12#\n" + + "\vmb_album_id\x18\x15 \x01(\tH\x12R\tmbAlbumId\x88\x01\x01\x12%\n" + + "\fmb_artist_id\x18\x16 \x01(\tH\x13R\n" + + "mbArtistId\x88\x01\x01\x127\n" + + "\x15replaygain_track_gain\x18\x1e \x01(\x02H\x14R\x13replaygainTrackGain\x88\x01\x01\x127\n" + + "\x15replaygain_track_peak\x18\x1f \x01(\x02H\x15R\x13replaygainTrackPeak\x88\x01\x01\x127\n" + + "\x15replaygain_album_gain\x18 \x01(\x02H\x16R\x13replaygainAlbumGain\x88\x01\x01\x127\n" + + "\x15replaygain_album_peak\x18! \x01(\x02H\x17R\x13replaygainAlbumPeak\x88\x01\x01\x12\x19\n" + + "\x05label\x18( \x01(\tH\x18R\x05label\x88\x01\x01\x12\"\n" + + "\n" + + "album_type\x18) \x01(\tH\x19R\talbumType\x88\x01\x01\x12 \n" + + "\tcover_url\x18* \x01(\tH\x1aR\bcoverUrl\x88\x01\x01\x12R\n" + + "\vcustom_tags\x182 \x03(\v21.musicfs.v1.UpdateMetadataRequest.CustomTagsEntryR\n" + + "customTags\x1a=\n" + + "\x0fCustomTagsEntry\x12\x10\n" + + "\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n" + + "\x05value\x18\x02 \x01(\tR\x05value:\x028\x01B\b\n" + + "\x06_titleB\t\n" + + "\a_artistB\b\n" + + "\x06_albumB\x0f\n" + + "\r_album_artistB\x0f\n" + + "\r_track_numberB\x0e\n" + + "\f_disc_numberB\a\n" + + "\x05_dateB\b\n" + + "\x06_genreB\v\n" + + "\t_composerB\n" + + "\n" + + "\b_commentB\t\n" + + "\a_lyricsB\f\n" + + "\n" + + "_copyrightB\x0e\n" + + "\f_compilationB\x0e\n" + + "\f_artist_sortB\x14\n" + + "\x12_album_artist_sortB\r\n" + + "\v_album_sortB\r\n" + + "\v_title_sortB\x12\n" + + "\x10_mb_recording_idB\x0e\n" + + "\f_mb_album_idB\x0f\n" + + "\r_mb_artist_idB\x18\n" + + "\x16_replaygain_track_gainB\x18\n" + + "\x16_replaygain_track_peakB\x18\n" + + "\x16_replaygain_album_gainB\x18\n" + + "\x16_replaygain_album_peakB\b\n" + + "\x06_labelB\r\n" + + "\v_album_typeB\f\n" + + "\n" + + "_cover_url\"\x87\x01\n" + + "\x16UpdateMetadataResponse\x12\x17\n" + + "\afile_id\x18\x01 \x01(\x03R\x06fileId\x12\x18\n" + + "\asuccess\x18\x02 \x01(\bR\asuccess\x12(\n" + + "\rerror_message\x18\x03 \x01(\tH\x00R\ferrorMessage\x88\x01\x01B\x10\n" + + "\x0e_error_message\".\n" + + "\x13ClearOverlayRequest\x12\x17\n" + + "\afile_id\x18\x01 \x01(\x03R\x06fileId\"\x85\x01\n" + + "\x14ClearOverlayResponse\x12\x17\n" + + "\afile_id\x18\x01 \x01(\x03R\x06fileId\x12\x18\n" + + "\asuccess\x18\x02 \x01(\bR\asuccess\x12(\n" + + "\rerror_message\x18\x03 \x01(\tH\x00R\ferrorMessage\x88\x01\x01B\x10\n" + + "\x0e_error_message\"G\n" + + "\x12BatchUpdateRequest\x121\n" + + "\x05items\x18\x01 \x03(\v2\x1b.musicfs.v1.BatchUpdateItemR\x05items\"i\n" + + "\x0fBatchUpdateItem\x12\x17\n" + + "\afile_id\x18\x01 \x01(\x03R\x06fileId\x12=\n" + + "\bmetadata\x18\x02 \x01(\v2!.musicfs.v1.UpdateMetadataRequestR\bmetadata\"\xc6\x01\n" + + "\x13BatchUpdateProgress\x12\x1c\n" + + "\tcompleted\x18\x01 \x01(\rR\tcompleted\x12\x14\n" + + "\x05total\x18\x02 \x01(\rR\x05total\x12+\n" + + "\x0fcurrent_file_id\x18\x03 \x01(\x03H\x00R\rcurrentFileId\x88\x01\x01\x12(\n" + + "\rerror_message\x18\x04 \x01(\tH\x01R\ferrorMessage\x88\x01\x01B\x12\n" + + "\x10_current_file_idB\x10\n" + + "\x0e_error_message\"`\n" + + "\x15ImportMetadataRequest\x12\x1f\n" + + "\vsource_path\x18\x01 \x01(\tR\n" + + "sourcePath\x12\x1b\n" + + "\x06format\x18\x02 \x01(\tH\x00R\x06format\x88\x01\x01B\t\n" + + "\a_format\"\xb7\x01\n" + + "\x0eImportProgress\x12\x1a\n" + + "\bimported\x18\x01 \x01(\rR\bimported\x12\x14\n" + + "\x05total\x18\x02 \x01(\rR\x05total\x12&\n" + + "\fcurrent_file\x18\x03 \x01(\tH\x00R\vcurrentFile\x88\x01\x01\x12(\n" + + "\rerror_message\x18\x04 \x01(\tH\x01R\ferrorMessage\x88\x01\x01B\x0f\n" + + "\r_current_fileB\x10\n" + + "\x0e_error_message*\x81\x01\n" + + "\n" + + "MountState\x12\x11\n" + + "\rMOUNT_UNKNOWN\x10\x00\x12\x12\n" + + "\x0eMOUNT_MOUNTING\x10\x01\x12\x0f\n" + + "\vMOUNT_READY\x10\x02\x12\x11\n" + + "\rMOUNT_SYNCING\x10\x03\x12\x12\n" + + "\x0eMOUNT_DEGRADED\x10\x04\x12\x14\n" + + "\x10MOUNT_UNMOUNTING\x10\x05*a\n" + + "\fHealthStatus\x12\x12\n" + + "\x0eHEALTH_UNKNOWN\x10\x00\x12\x12\n" + + "\x0eHEALTH_HEALTHY\x10\x01\x12\x13\n" + + "\x0fHEALTH_DEGRADED\x10\x02\x12\x14\n" + + "\x10HEALTH_UNHEALTHY\x10\x032\xf2\x05\n" + + "\aMusicFS\x12?\n" + + "\x06Search\x12\x19.musicfs.v1.SearchRequest\x1a\x1a.musicfs.v1.SearchResponse\x12E\n" + + "\fSearchStream\x12\x19.musicfs.v1.SearchRequest\x1a\x18.musicfs.v1.SearchResult0\x01\x12:\n" + + "\tGetStatus\x12\x11.musicfs.v1.Empty\x1a\x1a.musicfs.v1.StatusResponse\x12:\n" + + "\bShutdown\x12\x1b.musicfs.v1.ShutdownRequest\x1a\x11.musicfs.v1.Empty\x12:\n" + + "\rGetCacheStats\x12\x11.musicfs.v1.Empty\x1a\x16.musicfs.v1.CacheStats\x12K\n" + + "\n" + + "ClearCache\x12\x1d.musicfs.v1.ClearCacheRequest\x1a\x1e.musicfs.v1.ClearCacheResponse\x12G\n" + + "\bPrefetch\x12\x1b.musicfs.v1.PrefetchRequest\x1a\x1c.musicfs.v1.PrefetchProgress0\x01\x12=\n" + + "\vListOrigins\x12\x11.musicfs.v1.Empty\x1a\x1b.musicfs.v1.OriginsResponse\x12N\n" + + "\x0fGetOriginHealth\x12\x19.musicfs.v1.OriginRequest\x1a .musicfs.v1.OriginHealthResponse\x12E\n" + + "\fRescanOrigin\x12\x19.musicfs.v1.OriginRequest\x1a\x18.musicfs.v1.SyncProgress0\x01\x12?\n" + + "\x0fSubscribeEvents\x12\x17.musicfs.v1.EventFilter\x1a\x11.musicfs.v1.Event0\x012\xb7\x03\n" + + "\x0fMetadataService\x12K\n" + + "\vGetMetadata\x12\x1e.musicfs.v1.GetMetadataRequest\x1a\x1c.musicfs.v1.MetadataResponse\x12W\n" + + "\x0eUpdateMetadata\x12!.musicfs.v1.UpdateMetadataRequest\x1a\".musicfs.v1.UpdateMetadataResponse\x12Q\n" + + "\fClearOverlay\x12\x1f.musicfs.v1.ClearOverlayRequest\x1a .musicfs.v1.ClearOverlayResponse\x12X\n" + + "\x13BatchUpdateMetadata\x12\x1e.musicfs.v1.BatchUpdateRequest\x1a\x1f.musicfs.v1.BatchUpdateProgress0\x01\x12Q\n" + + "\x0eImportMetadata\x12!.musicfs.v1.ImportMetadataRequest\x1a\x1a.musicfs.v1.ImportProgress0\x01B6Z4homelab.lan/music-agregator/gen/musicfs/v1;musicfsv1b\x06proto3" + +var ( + file_musicfs_proto_rawDescOnce sync.Once + file_musicfs_proto_rawDescData []byte +) + +func file_musicfs_proto_rawDescGZIP() []byte { + file_musicfs_proto_rawDescOnce.Do(func() { + file_musicfs_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_musicfs_proto_rawDesc), len(file_musicfs_proto_rawDesc))) + }) + return file_musicfs_proto_rawDescData +} + +var file_musicfs_proto_enumTypes = make([]protoimpl.EnumInfo, 2) +var file_musicfs_proto_msgTypes = make([]protoimpl.MessageInfo, 36) +var file_musicfs_proto_goTypes = []any{ + (MountState)(0), // 0: musicfs.v1.MountState + (HealthStatus)(0), // 1: musicfs.v1.HealthStatus + (*Empty)(nil), // 2: musicfs.v1.Empty + (*SearchRequest)(nil), // 3: musicfs.v1.SearchRequest + (*SearchResponse)(nil), // 4: musicfs.v1.SearchResponse + (*SearchResult)(nil), // 5: musicfs.v1.SearchResult + (*StatusResponse)(nil), // 6: musicfs.v1.StatusResponse + (*OriginStatus)(nil), // 7: musicfs.v1.OriginStatus + (*ShutdownRequest)(nil), // 8: musicfs.v1.ShutdownRequest + (*TierStats)(nil), // 9: musicfs.v1.TierStats + (*CacheStats)(nil), // 10: musicfs.v1.CacheStats + (*ClearCacheRequest)(nil), // 11: musicfs.v1.ClearCacheRequest + (*ClearCacheResponse)(nil), // 12: musicfs.v1.ClearCacheResponse + (*PrefetchRequest)(nil), // 13: musicfs.v1.PrefetchRequest + (*PrefetchProgress)(nil), // 14: musicfs.v1.PrefetchProgress + (*OriginsResponse)(nil), // 15: musicfs.v1.OriginsResponse + (*OriginInfo)(nil), // 16: musicfs.v1.OriginInfo + (*OriginRequest)(nil), // 17: musicfs.v1.OriginRequest + (*OriginHealthResponse)(nil), // 18: musicfs.v1.OriginHealthResponse + (*SyncProgress)(nil), // 19: musicfs.v1.SyncProgress + (*SyncedFile)(nil), // 20: musicfs.v1.SyncedFile + (*EventFilter)(nil), // 21: musicfs.v1.EventFilter + (*Event)(nil), // 22: musicfs.v1.Event + (*GetMetadataRequest)(nil), // 23: musicfs.v1.GetMetadataRequest + (*MetadataResponse)(nil), // 24: musicfs.v1.MetadataResponse + (*UpdateMetadataRequest)(nil), // 25: musicfs.v1.UpdateMetadataRequest + (*UpdateMetadataResponse)(nil), // 26: musicfs.v1.UpdateMetadataResponse + (*ClearOverlayRequest)(nil), // 27: musicfs.v1.ClearOverlayRequest + (*ClearOverlayResponse)(nil), // 28: musicfs.v1.ClearOverlayResponse + (*BatchUpdateRequest)(nil), // 29: musicfs.v1.BatchUpdateRequest + (*BatchUpdateItem)(nil), // 30: musicfs.v1.BatchUpdateItem + (*BatchUpdateProgress)(nil), // 31: musicfs.v1.BatchUpdateProgress + (*ImportMetadataRequest)(nil), // 32: musicfs.v1.ImportMetadataRequest + (*ImportProgress)(nil), // 33: musicfs.v1.ImportProgress + nil, // 34: musicfs.v1.SearchResult.HighlightsEntry + nil, // 35: musicfs.v1.Event.MetadataEntry + nil, // 36: musicfs.v1.MetadataResponse.CustomTagsEntry + nil, // 37: musicfs.v1.UpdateMetadataRequest.CustomTagsEntry +} +var file_musicfs_proto_depIdxs = []int32{ + 5, // 0: musicfs.v1.SearchResponse.results:type_name -> musicfs.v1.SearchResult + 34, // 1: musicfs.v1.SearchResult.highlights:type_name -> musicfs.v1.SearchResult.HighlightsEntry + 0, // 2: musicfs.v1.StatusResponse.state:type_name -> musicfs.v1.MountState + 7, // 3: musicfs.v1.StatusResponse.origins:type_name -> musicfs.v1.OriginStatus + 1, // 4: musicfs.v1.OriginStatus.health:type_name -> musicfs.v1.HealthStatus + 9, // 5: musicfs.v1.CacheStats.l1_metadata:type_name -> musicfs.v1.TierStats + 9, // 6: musicfs.v1.CacheStats.l2_headers:type_name -> musicfs.v1.TierStats + 9, // 7: musicfs.v1.CacheStats.l3_chunks:type_name -> musicfs.v1.TierStats + 16, // 8: musicfs.v1.OriginsResponse.origins:type_name -> musicfs.v1.OriginInfo + 1, // 9: musicfs.v1.OriginInfo.health:type_name -> musicfs.v1.HealthStatus + 1, // 10: musicfs.v1.OriginHealthResponse.status:type_name -> musicfs.v1.HealthStatus + 20, // 11: musicfs.v1.SyncProgress.new_files:type_name -> musicfs.v1.SyncedFile + 35, // 12: musicfs.v1.Event.metadata:type_name -> musicfs.v1.Event.MetadataEntry + 36, // 13: musicfs.v1.MetadataResponse.custom_tags:type_name -> musicfs.v1.MetadataResponse.CustomTagsEntry + 37, // 14: musicfs.v1.UpdateMetadataRequest.custom_tags:type_name -> musicfs.v1.UpdateMetadataRequest.CustomTagsEntry + 30, // 15: musicfs.v1.BatchUpdateRequest.items:type_name -> musicfs.v1.BatchUpdateItem + 25, // 16: musicfs.v1.BatchUpdateItem.metadata:type_name -> musicfs.v1.UpdateMetadataRequest + 3, // 17: musicfs.v1.MusicFS.Search:input_type -> musicfs.v1.SearchRequest + 3, // 18: musicfs.v1.MusicFS.SearchStream:input_type -> musicfs.v1.SearchRequest + 2, // 19: musicfs.v1.MusicFS.GetStatus:input_type -> musicfs.v1.Empty + 8, // 20: musicfs.v1.MusicFS.Shutdown:input_type -> musicfs.v1.ShutdownRequest + 2, // 21: musicfs.v1.MusicFS.GetCacheStats:input_type -> musicfs.v1.Empty + 11, // 22: musicfs.v1.MusicFS.ClearCache:input_type -> musicfs.v1.ClearCacheRequest + 13, // 23: musicfs.v1.MusicFS.Prefetch:input_type -> musicfs.v1.PrefetchRequest + 2, // 24: musicfs.v1.MusicFS.ListOrigins:input_type -> musicfs.v1.Empty + 17, // 25: musicfs.v1.MusicFS.GetOriginHealth:input_type -> musicfs.v1.OriginRequest + 17, // 26: musicfs.v1.MusicFS.RescanOrigin:input_type -> musicfs.v1.OriginRequest + 21, // 27: musicfs.v1.MusicFS.SubscribeEvents:input_type -> musicfs.v1.EventFilter + 23, // 28: musicfs.v1.MetadataService.GetMetadata:input_type -> musicfs.v1.GetMetadataRequest + 25, // 29: musicfs.v1.MetadataService.UpdateMetadata:input_type -> musicfs.v1.UpdateMetadataRequest + 27, // 30: musicfs.v1.MetadataService.ClearOverlay:input_type -> musicfs.v1.ClearOverlayRequest + 29, // 31: musicfs.v1.MetadataService.BatchUpdateMetadata:input_type -> musicfs.v1.BatchUpdateRequest + 32, // 32: musicfs.v1.MetadataService.ImportMetadata:input_type -> musicfs.v1.ImportMetadataRequest + 4, // 33: musicfs.v1.MusicFS.Search:output_type -> musicfs.v1.SearchResponse + 5, // 34: musicfs.v1.MusicFS.SearchStream:output_type -> musicfs.v1.SearchResult + 6, // 35: musicfs.v1.MusicFS.GetStatus:output_type -> musicfs.v1.StatusResponse + 2, // 36: musicfs.v1.MusicFS.Shutdown:output_type -> musicfs.v1.Empty + 10, // 37: musicfs.v1.MusicFS.GetCacheStats:output_type -> musicfs.v1.CacheStats + 12, // 38: musicfs.v1.MusicFS.ClearCache:output_type -> musicfs.v1.ClearCacheResponse + 14, // 39: musicfs.v1.MusicFS.Prefetch:output_type -> musicfs.v1.PrefetchProgress + 15, // 40: musicfs.v1.MusicFS.ListOrigins:output_type -> musicfs.v1.OriginsResponse + 18, // 41: musicfs.v1.MusicFS.GetOriginHealth:output_type -> musicfs.v1.OriginHealthResponse + 19, // 42: musicfs.v1.MusicFS.RescanOrigin:output_type -> musicfs.v1.SyncProgress + 22, // 43: musicfs.v1.MusicFS.SubscribeEvents:output_type -> musicfs.v1.Event + 24, // 44: musicfs.v1.MetadataService.GetMetadata:output_type -> musicfs.v1.MetadataResponse + 26, // 45: musicfs.v1.MetadataService.UpdateMetadata:output_type -> musicfs.v1.UpdateMetadataResponse + 28, // 46: musicfs.v1.MetadataService.ClearOverlay:output_type -> musicfs.v1.ClearOverlayResponse + 31, // 47: musicfs.v1.MetadataService.BatchUpdateMetadata:output_type -> musicfs.v1.BatchUpdateProgress + 33, // 48: musicfs.v1.MetadataService.ImportMetadata:output_type -> musicfs.v1.ImportProgress + 33, // [33:49] is the sub-list for method output_type + 17, // [17:33] is the sub-list for method input_type + 17, // [17:17] is the sub-list for extension type_name + 17, // [17:17] is the sub-list for extension extendee + 0, // [0:17] is the sub-list for field type_name +} + +func init() { file_musicfs_proto_init() } +func file_musicfs_proto_init() { + if File_musicfs_proto != nil { + return + } + file_musicfs_proto_msgTypes[1].OneofWrappers = []any{} + file_musicfs_proto_msgTypes[3].OneofWrappers = []any{} + file_musicfs_proto_msgTypes[9].OneofWrappers = []any{} + file_musicfs_proto_msgTypes[11].OneofWrappers = []any{} + file_musicfs_proto_msgTypes[15].OneofWrappers = []any{} + file_musicfs_proto_msgTypes[16].OneofWrappers = []any{} + file_musicfs_proto_msgTypes[19].OneofWrappers = []any{} + file_musicfs_proto_msgTypes[20].OneofWrappers = []any{} + file_musicfs_proto_msgTypes[22].OneofWrappers = []any{} + file_musicfs_proto_msgTypes[23].OneofWrappers = []any{} + file_musicfs_proto_msgTypes[24].OneofWrappers = []any{} + file_musicfs_proto_msgTypes[26].OneofWrappers = []any{} + file_musicfs_proto_msgTypes[29].OneofWrappers = []any{} + file_musicfs_proto_msgTypes[30].OneofWrappers = []any{} + file_musicfs_proto_msgTypes[31].OneofWrappers = []any{} + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: unsafe.Slice(unsafe.StringData(file_musicfs_proto_rawDesc), len(file_musicfs_proto_rawDesc)), + NumEnums: 2, + NumMessages: 36, + NumExtensions: 0, + NumServices: 2, + }, + GoTypes: file_musicfs_proto_goTypes, + DependencyIndexes: file_musicfs_proto_depIdxs, + EnumInfos: file_musicfs_proto_enumTypes, + MessageInfos: file_musicfs_proto_msgTypes, + }.Build() + File_musicfs_proto = out.File + file_musicfs_proto_goTypes = nil + file_musicfs_proto_depIdxs = nil +} diff --git a/gen/musicfs_grpc.pb.go b/gen/musicfs_grpc.pb.go new file mode 100644 index 0000000..afaeb8d --- /dev/null +++ b/gen/musicfs_grpc.pb.go @@ -0,0 +1,775 @@ +// Code generated by protoc-gen-go-grpc. DO NOT EDIT. +// versions: +// - protoc-gen-go-grpc v1.6.1 +// - protoc (unknown) +// source: musicfs.proto + +package musicfsv1 + +import ( + context "context" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" +) + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +// Requires gRPC-Go v1.64.0 or later. +const _ = grpc.SupportPackageIsVersion9 + +const ( + MusicFS_Search_FullMethodName = "/musicfs.v1.MusicFS/Search" + MusicFS_SearchStream_FullMethodName = "/musicfs.v1.MusicFS/SearchStream" + MusicFS_GetStatus_FullMethodName = "/musicfs.v1.MusicFS/GetStatus" + MusicFS_Shutdown_FullMethodName = "/musicfs.v1.MusicFS/Shutdown" + MusicFS_GetCacheStats_FullMethodName = "/musicfs.v1.MusicFS/GetCacheStats" + MusicFS_ClearCache_FullMethodName = "/musicfs.v1.MusicFS/ClearCache" + MusicFS_Prefetch_FullMethodName = "/musicfs.v1.MusicFS/Prefetch" + MusicFS_ListOrigins_FullMethodName = "/musicfs.v1.MusicFS/ListOrigins" + MusicFS_GetOriginHealth_FullMethodName = "/musicfs.v1.MusicFS/GetOriginHealth" + MusicFS_RescanOrigin_FullMethodName = "/musicfs.v1.MusicFS/RescanOrigin" + MusicFS_SubscribeEvents_FullMethodName = "/musicfs.v1.MusicFS/SubscribeEvents" +) + +// MusicFSClient is the client API for MusicFS service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. +type MusicFSClient interface { + Search(ctx context.Context, in *SearchRequest, opts ...grpc.CallOption) (*SearchResponse, error) + SearchStream(ctx context.Context, in *SearchRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[SearchResult], error) + GetStatus(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*StatusResponse, error) + Shutdown(ctx context.Context, in *ShutdownRequest, opts ...grpc.CallOption) (*Empty, error) + GetCacheStats(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*CacheStats, error) + ClearCache(ctx context.Context, in *ClearCacheRequest, opts ...grpc.CallOption) (*ClearCacheResponse, error) + Prefetch(ctx context.Context, in *PrefetchRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[PrefetchProgress], error) + ListOrigins(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*OriginsResponse, error) + GetOriginHealth(ctx context.Context, in *OriginRequest, opts ...grpc.CallOption) (*OriginHealthResponse, error) + RescanOrigin(ctx context.Context, in *OriginRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[SyncProgress], error) + SubscribeEvents(ctx context.Context, in *EventFilter, opts ...grpc.CallOption) (grpc.ServerStreamingClient[Event], error) +} + +type musicFSClient struct { + cc grpc.ClientConnInterface +} + +func NewMusicFSClient(cc grpc.ClientConnInterface) MusicFSClient { + return &musicFSClient{cc} +} + +func (c *musicFSClient) Search(ctx context.Context, in *SearchRequest, opts ...grpc.CallOption) (*SearchResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(SearchResponse) + err := c.cc.Invoke(ctx, MusicFS_Search_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *musicFSClient) SearchStream(ctx context.Context, in *SearchRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[SearchResult], error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + stream, err := c.cc.NewStream(ctx, &MusicFS_ServiceDesc.Streams[0], MusicFS_SearchStream_FullMethodName, cOpts...) + if err != nil { + return nil, err + } + x := &grpc.GenericClientStream[SearchRequest, SearchResult]{ClientStream: stream} + if err := x.ClientStream.SendMsg(in); err != nil { + return nil, err + } + if err := x.ClientStream.CloseSend(); err != nil { + return nil, err + } + return x, nil +} + +// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. +type MusicFS_SearchStreamClient = grpc.ServerStreamingClient[SearchResult] + +func (c *musicFSClient) GetStatus(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*StatusResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(StatusResponse) + err := c.cc.Invoke(ctx, MusicFS_GetStatus_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *musicFSClient) Shutdown(ctx context.Context, in *ShutdownRequest, opts ...grpc.CallOption) (*Empty, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(Empty) + err := c.cc.Invoke(ctx, MusicFS_Shutdown_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *musicFSClient) GetCacheStats(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*CacheStats, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(CacheStats) + err := c.cc.Invoke(ctx, MusicFS_GetCacheStats_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *musicFSClient) ClearCache(ctx context.Context, in *ClearCacheRequest, opts ...grpc.CallOption) (*ClearCacheResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(ClearCacheResponse) + err := c.cc.Invoke(ctx, MusicFS_ClearCache_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *musicFSClient) Prefetch(ctx context.Context, in *PrefetchRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[PrefetchProgress], error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + stream, err := c.cc.NewStream(ctx, &MusicFS_ServiceDesc.Streams[1], MusicFS_Prefetch_FullMethodName, cOpts...) + if err != nil { + return nil, err + } + x := &grpc.GenericClientStream[PrefetchRequest, PrefetchProgress]{ClientStream: stream} + if err := x.ClientStream.SendMsg(in); err != nil { + return nil, err + } + if err := x.ClientStream.CloseSend(); err != nil { + return nil, err + } + return x, nil +} + +// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. +type MusicFS_PrefetchClient = grpc.ServerStreamingClient[PrefetchProgress] + +func (c *musicFSClient) ListOrigins(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*OriginsResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(OriginsResponse) + err := c.cc.Invoke(ctx, MusicFS_ListOrigins_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *musicFSClient) GetOriginHealth(ctx context.Context, in *OriginRequest, opts ...grpc.CallOption) (*OriginHealthResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(OriginHealthResponse) + err := c.cc.Invoke(ctx, MusicFS_GetOriginHealth_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *musicFSClient) RescanOrigin(ctx context.Context, in *OriginRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[SyncProgress], error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + stream, err := c.cc.NewStream(ctx, &MusicFS_ServiceDesc.Streams[2], MusicFS_RescanOrigin_FullMethodName, cOpts...) + if err != nil { + return nil, err + } + x := &grpc.GenericClientStream[OriginRequest, SyncProgress]{ClientStream: stream} + if err := x.ClientStream.SendMsg(in); err != nil { + return nil, err + } + if err := x.ClientStream.CloseSend(); err != nil { + return nil, err + } + return x, nil +} + +// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. +type MusicFS_RescanOriginClient = grpc.ServerStreamingClient[SyncProgress] + +func (c *musicFSClient) SubscribeEvents(ctx context.Context, in *EventFilter, opts ...grpc.CallOption) (grpc.ServerStreamingClient[Event], error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + stream, err := c.cc.NewStream(ctx, &MusicFS_ServiceDesc.Streams[3], MusicFS_SubscribeEvents_FullMethodName, cOpts...) + if err != nil { + return nil, err + } + x := &grpc.GenericClientStream[EventFilter, Event]{ClientStream: stream} + if err := x.ClientStream.SendMsg(in); err != nil { + return nil, err + } + if err := x.ClientStream.CloseSend(); err != nil { + return nil, err + } + return x, nil +} + +// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. +type MusicFS_SubscribeEventsClient = grpc.ServerStreamingClient[Event] + +// MusicFSServer is the server API for MusicFS service. +// All implementations must embed UnimplementedMusicFSServer +// for forward compatibility. +type MusicFSServer interface { + Search(context.Context, *SearchRequest) (*SearchResponse, error) + SearchStream(*SearchRequest, grpc.ServerStreamingServer[SearchResult]) error + GetStatus(context.Context, *Empty) (*StatusResponse, error) + Shutdown(context.Context, *ShutdownRequest) (*Empty, error) + GetCacheStats(context.Context, *Empty) (*CacheStats, error) + ClearCache(context.Context, *ClearCacheRequest) (*ClearCacheResponse, error) + Prefetch(*PrefetchRequest, grpc.ServerStreamingServer[PrefetchProgress]) error + ListOrigins(context.Context, *Empty) (*OriginsResponse, error) + GetOriginHealth(context.Context, *OriginRequest) (*OriginHealthResponse, error) + RescanOrigin(*OriginRequest, grpc.ServerStreamingServer[SyncProgress]) error + SubscribeEvents(*EventFilter, grpc.ServerStreamingServer[Event]) error + mustEmbedUnimplementedMusicFSServer() +} + +// UnimplementedMusicFSServer must be embedded to have +// forward compatible implementations. +// +// NOTE: this should be embedded by value instead of pointer to avoid a nil +// pointer dereference when methods are called. +type UnimplementedMusicFSServer struct{} + +func (UnimplementedMusicFSServer) Search(context.Context, *SearchRequest) (*SearchResponse, error) { + return nil, status.Error(codes.Unimplemented, "method Search not implemented") +} +func (UnimplementedMusicFSServer) SearchStream(*SearchRequest, grpc.ServerStreamingServer[SearchResult]) error { + return status.Error(codes.Unimplemented, "method SearchStream not implemented") +} +func (UnimplementedMusicFSServer) GetStatus(context.Context, *Empty) (*StatusResponse, error) { + return nil, status.Error(codes.Unimplemented, "method GetStatus not implemented") +} +func (UnimplementedMusicFSServer) Shutdown(context.Context, *ShutdownRequest) (*Empty, error) { + return nil, status.Error(codes.Unimplemented, "method Shutdown not implemented") +} +func (UnimplementedMusicFSServer) GetCacheStats(context.Context, *Empty) (*CacheStats, error) { + return nil, status.Error(codes.Unimplemented, "method GetCacheStats not implemented") +} +func (UnimplementedMusicFSServer) ClearCache(context.Context, *ClearCacheRequest) (*ClearCacheResponse, error) { + return nil, status.Error(codes.Unimplemented, "method ClearCache not implemented") +} +func (UnimplementedMusicFSServer) Prefetch(*PrefetchRequest, grpc.ServerStreamingServer[PrefetchProgress]) error { + return status.Error(codes.Unimplemented, "method Prefetch not implemented") +} +func (UnimplementedMusicFSServer) ListOrigins(context.Context, *Empty) (*OriginsResponse, error) { + return nil, status.Error(codes.Unimplemented, "method ListOrigins not implemented") +} +func (UnimplementedMusicFSServer) GetOriginHealth(context.Context, *OriginRequest) (*OriginHealthResponse, error) { + return nil, status.Error(codes.Unimplemented, "method GetOriginHealth not implemented") +} +func (UnimplementedMusicFSServer) RescanOrigin(*OriginRequest, grpc.ServerStreamingServer[SyncProgress]) error { + return status.Error(codes.Unimplemented, "method RescanOrigin not implemented") +} +func (UnimplementedMusicFSServer) SubscribeEvents(*EventFilter, grpc.ServerStreamingServer[Event]) error { + return status.Error(codes.Unimplemented, "method SubscribeEvents not implemented") +} +func (UnimplementedMusicFSServer) mustEmbedUnimplementedMusicFSServer() {} +func (UnimplementedMusicFSServer) testEmbeddedByValue() {} + +// UnsafeMusicFSServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to MusicFSServer will +// result in compilation errors. +type UnsafeMusicFSServer interface { + mustEmbedUnimplementedMusicFSServer() +} + +func RegisterMusicFSServer(s grpc.ServiceRegistrar, srv MusicFSServer) { + // If the following call panics, it indicates UnimplementedMusicFSServer was + // embedded by pointer and is nil. This will cause panics if an + // unimplemented method is ever invoked, so we test this at initialization + // time to prevent it from happening at runtime later due to I/O. + if t, ok := srv.(interface{ testEmbeddedByValue() }); ok { + t.testEmbeddedByValue() + } + s.RegisterService(&MusicFS_ServiceDesc, srv) +} + +func _MusicFS_Search_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(SearchRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MusicFSServer).Search(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: MusicFS_Search_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MusicFSServer).Search(ctx, req.(*SearchRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _MusicFS_SearchStream_Handler(srv interface{}, stream grpc.ServerStream) error { + m := new(SearchRequest) + if err := stream.RecvMsg(m); err != nil { + return err + } + return srv.(MusicFSServer).SearchStream(m, &grpc.GenericServerStream[SearchRequest, SearchResult]{ServerStream: stream}) +} + +// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. +type MusicFS_SearchStreamServer = grpc.ServerStreamingServer[SearchResult] + +func _MusicFS_GetStatus_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(Empty) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MusicFSServer).GetStatus(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: MusicFS_GetStatus_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MusicFSServer).GetStatus(ctx, req.(*Empty)) + } + return interceptor(ctx, in, info, handler) +} + +func _MusicFS_Shutdown_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ShutdownRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MusicFSServer).Shutdown(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: MusicFS_Shutdown_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MusicFSServer).Shutdown(ctx, req.(*ShutdownRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _MusicFS_GetCacheStats_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(Empty) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MusicFSServer).GetCacheStats(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: MusicFS_GetCacheStats_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MusicFSServer).GetCacheStats(ctx, req.(*Empty)) + } + return interceptor(ctx, in, info, handler) +} + +func _MusicFS_ClearCache_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ClearCacheRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MusicFSServer).ClearCache(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: MusicFS_ClearCache_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MusicFSServer).ClearCache(ctx, req.(*ClearCacheRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _MusicFS_Prefetch_Handler(srv interface{}, stream grpc.ServerStream) error { + m := new(PrefetchRequest) + if err := stream.RecvMsg(m); err != nil { + return err + } + return srv.(MusicFSServer).Prefetch(m, &grpc.GenericServerStream[PrefetchRequest, PrefetchProgress]{ServerStream: stream}) +} + +// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. +type MusicFS_PrefetchServer = grpc.ServerStreamingServer[PrefetchProgress] + +func _MusicFS_ListOrigins_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(Empty) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MusicFSServer).ListOrigins(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: MusicFS_ListOrigins_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MusicFSServer).ListOrigins(ctx, req.(*Empty)) + } + return interceptor(ctx, in, info, handler) +} + +func _MusicFS_GetOriginHealth_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(OriginRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MusicFSServer).GetOriginHealth(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: MusicFS_GetOriginHealth_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MusicFSServer).GetOriginHealth(ctx, req.(*OriginRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _MusicFS_RescanOrigin_Handler(srv interface{}, stream grpc.ServerStream) error { + m := new(OriginRequest) + if err := stream.RecvMsg(m); err != nil { + return err + } + return srv.(MusicFSServer).RescanOrigin(m, &grpc.GenericServerStream[OriginRequest, SyncProgress]{ServerStream: stream}) +} + +// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. +type MusicFS_RescanOriginServer = grpc.ServerStreamingServer[SyncProgress] + +func _MusicFS_SubscribeEvents_Handler(srv interface{}, stream grpc.ServerStream) error { + m := new(EventFilter) + if err := stream.RecvMsg(m); err != nil { + return err + } + return srv.(MusicFSServer).SubscribeEvents(m, &grpc.GenericServerStream[EventFilter, Event]{ServerStream: stream}) +} + +// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. +type MusicFS_SubscribeEventsServer = grpc.ServerStreamingServer[Event] + +// MusicFS_ServiceDesc is the grpc.ServiceDesc for MusicFS service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var MusicFS_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "musicfs.v1.MusicFS", + HandlerType: (*MusicFSServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "Search", + Handler: _MusicFS_Search_Handler, + }, + { + MethodName: "GetStatus", + Handler: _MusicFS_GetStatus_Handler, + }, + { + MethodName: "Shutdown", + Handler: _MusicFS_Shutdown_Handler, + }, + { + MethodName: "GetCacheStats", + Handler: _MusicFS_GetCacheStats_Handler, + }, + { + MethodName: "ClearCache", + Handler: _MusicFS_ClearCache_Handler, + }, + { + MethodName: "ListOrigins", + Handler: _MusicFS_ListOrigins_Handler, + }, + { + MethodName: "GetOriginHealth", + Handler: _MusicFS_GetOriginHealth_Handler, + }, + }, + Streams: []grpc.StreamDesc{ + { + StreamName: "SearchStream", + Handler: _MusicFS_SearchStream_Handler, + ServerStreams: true, + }, + { + StreamName: "Prefetch", + Handler: _MusicFS_Prefetch_Handler, + ServerStreams: true, + }, + { + StreamName: "RescanOrigin", + Handler: _MusicFS_RescanOrigin_Handler, + ServerStreams: true, + }, + { + StreamName: "SubscribeEvents", + Handler: _MusicFS_SubscribeEvents_Handler, + ServerStreams: true, + }, + }, + Metadata: "musicfs.proto", +} + +const ( + MetadataService_GetMetadata_FullMethodName = "/musicfs.v1.MetadataService/GetMetadata" + MetadataService_UpdateMetadata_FullMethodName = "/musicfs.v1.MetadataService/UpdateMetadata" + MetadataService_ClearOverlay_FullMethodName = "/musicfs.v1.MetadataService/ClearOverlay" + MetadataService_BatchUpdateMetadata_FullMethodName = "/musicfs.v1.MetadataService/BatchUpdateMetadata" + MetadataService_ImportMetadata_FullMethodName = "/musicfs.v1.MetadataService/ImportMetadata" +) + +// MetadataServiceClient is the client API for MetadataService service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. +type MetadataServiceClient interface { + GetMetadata(ctx context.Context, in *GetMetadataRequest, opts ...grpc.CallOption) (*MetadataResponse, error) + UpdateMetadata(ctx context.Context, in *UpdateMetadataRequest, opts ...grpc.CallOption) (*UpdateMetadataResponse, error) + ClearOverlay(ctx context.Context, in *ClearOverlayRequest, opts ...grpc.CallOption) (*ClearOverlayResponse, error) + BatchUpdateMetadata(ctx context.Context, in *BatchUpdateRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[BatchUpdateProgress], error) + ImportMetadata(ctx context.Context, in *ImportMetadataRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[ImportProgress], error) +} + +type metadataServiceClient struct { + cc grpc.ClientConnInterface +} + +func NewMetadataServiceClient(cc grpc.ClientConnInterface) MetadataServiceClient { + return &metadataServiceClient{cc} +} + +func (c *metadataServiceClient) GetMetadata(ctx context.Context, in *GetMetadataRequest, opts ...grpc.CallOption) (*MetadataResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(MetadataResponse) + err := c.cc.Invoke(ctx, MetadataService_GetMetadata_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *metadataServiceClient) UpdateMetadata(ctx context.Context, in *UpdateMetadataRequest, opts ...grpc.CallOption) (*UpdateMetadataResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(UpdateMetadataResponse) + err := c.cc.Invoke(ctx, MetadataService_UpdateMetadata_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *metadataServiceClient) ClearOverlay(ctx context.Context, in *ClearOverlayRequest, opts ...grpc.CallOption) (*ClearOverlayResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(ClearOverlayResponse) + err := c.cc.Invoke(ctx, MetadataService_ClearOverlay_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *metadataServiceClient) BatchUpdateMetadata(ctx context.Context, in *BatchUpdateRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[BatchUpdateProgress], error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + stream, err := c.cc.NewStream(ctx, &MetadataService_ServiceDesc.Streams[0], MetadataService_BatchUpdateMetadata_FullMethodName, cOpts...) + if err != nil { + return nil, err + } + x := &grpc.GenericClientStream[BatchUpdateRequest, BatchUpdateProgress]{ClientStream: stream} + if err := x.ClientStream.SendMsg(in); err != nil { + return nil, err + } + if err := x.ClientStream.CloseSend(); err != nil { + return nil, err + } + return x, nil +} + +// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. +type MetadataService_BatchUpdateMetadataClient = grpc.ServerStreamingClient[BatchUpdateProgress] + +func (c *metadataServiceClient) ImportMetadata(ctx context.Context, in *ImportMetadataRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[ImportProgress], error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + stream, err := c.cc.NewStream(ctx, &MetadataService_ServiceDesc.Streams[1], MetadataService_ImportMetadata_FullMethodName, cOpts...) + if err != nil { + return nil, err + } + x := &grpc.GenericClientStream[ImportMetadataRequest, ImportProgress]{ClientStream: stream} + if err := x.ClientStream.SendMsg(in); err != nil { + return nil, err + } + if err := x.ClientStream.CloseSend(); err != nil { + return nil, err + } + return x, nil +} + +// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. +type MetadataService_ImportMetadataClient = grpc.ServerStreamingClient[ImportProgress] + +// MetadataServiceServer is the server API for MetadataService service. +// All implementations must embed UnimplementedMetadataServiceServer +// for forward compatibility. +type MetadataServiceServer interface { + GetMetadata(context.Context, *GetMetadataRequest) (*MetadataResponse, error) + UpdateMetadata(context.Context, *UpdateMetadataRequest) (*UpdateMetadataResponse, error) + ClearOverlay(context.Context, *ClearOverlayRequest) (*ClearOverlayResponse, error) + BatchUpdateMetadata(*BatchUpdateRequest, grpc.ServerStreamingServer[BatchUpdateProgress]) error + ImportMetadata(*ImportMetadataRequest, grpc.ServerStreamingServer[ImportProgress]) error + mustEmbedUnimplementedMetadataServiceServer() +} + +// UnimplementedMetadataServiceServer must be embedded to have +// forward compatible implementations. +// +// NOTE: this should be embedded by value instead of pointer to avoid a nil +// pointer dereference when methods are called. +type UnimplementedMetadataServiceServer struct{} + +func (UnimplementedMetadataServiceServer) GetMetadata(context.Context, *GetMetadataRequest) (*MetadataResponse, error) { + return nil, status.Error(codes.Unimplemented, "method GetMetadata not implemented") +} +func (UnimplementedMetadataServiceServer) UpdateMetadata(context.Context, *UpdateMetadataRequest) (*UpdateMetadataResponse, error) { + return nil, status.Error(codes.Unimplemented, "method UpdateMetadata not implemented") +} +func (UnimplementedMetadataServiceServer) ClearOverlay(context.Context, *ClearOverlayRequest) (*ClearOverlayResponse, error) { + return nil, status.Error(codes.Unimplemented, "method ClearOverlay not implemented") +} +func (UnimplementedMetadataServiceServer) BatchUpdateMetadata(*BatchUpdateRequest, grpc.ServerStreamingServer[BatchUpdateProgress]) error { + return status.Error(codes.Unimplemented, "method BatchUpdateMetadata not implemented") +} +func (UnimplementedMetadataServiceServer) ImportMetadata(*ImportMetadataRequest, grpc.ServerStreamingServer[ImportProgress]) error { + return status.Error(codes.Unimplemented, "method ImportMetadata not implemented") +} +func (UnimplementedMetadataServiceServer) mustEmbedUnimplementedMetadataServiceServer() {} +func (UnimplementedMetadataServiceServer) testEmbeddedByValue() {} + +// UnsafeMetadataServiceServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to MetadataServiceServer will +// result in compilation errors. +type UnsafeMetadataServiceServer interface { + mustEmbedUnimplementedMetadataServiceServer() +} + +func RegisterMetadataServiceServer(s grpc.ServiceRegistrar, srv MetadataServiceServer) { + // If the following call panics, it indicates UnimplementedMetadataServiceServer was + // embedded by pointer and is nil. This will cause panics if an + // unimplemented method is ever invoked, so we test this at initialization + // time to prevent it from happening at runtime later due to I/O. + if t, ok := srv.(interface{ testEmbeddedByValue() }); ok { + t.testEmbeddedByValue() + } + s.RegisterService(&MetadataService_ServiceDesc, srv) +} + +func _MetadataService_GetMetadata_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetMetadataRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MetadataServiceServer).GetMetadata(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: MetadataService_GetMetadata_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MetadataServiceServer).GetMetadata(ctx, req.(*GetMetadataRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _MetadataService_UpdateMetadata_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(UpdateMetadataRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MetadataServiceServer).UpdateMetadata(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: MetadataService_UpdateMetadata_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MetadataServiceServer).UpdateMetadata(ctx, req.(*UpdateMetadataRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _MetadataService_ClearOverlay_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ClearOverlayRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MetadataServiceServer).ClearOverlay(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: MetadataService_ClearOverlay_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MetadataServiceServer).ClearOverlay(ctx, req.(*ClearOverlayRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _MetadataService_BatchUpdateMetadata_Handler(srv interface{}, stream grpc.ServerStream) error { + m := new(BatchUpdateRequest) + if err := stream.RecvMsg(m); err != nil { + return err + } + return srv.(MetadataServiceServer).BatchUpdateMetadata(m, &grpc.GenericServerStream[BatchUpdateRequest, BatchUpdateProgress]{ServerStream: stream}) +} + +// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. +type MetadataService_BatchUpdateMetadataServer = grpc.ServerStreamingServer[BatchUpdateProgress] + +func _MetadataService_ImportMetadata_Handler(srv interface{}, stream grpc.ServerStream) error { + m := new(ImportMetadataRequest) + if err := stream.RecvMsg(m); err != nil { + return err + } + return srv.(MetadataServiceServer).ImportMetadata(m, &grpc.GenericServerStream[ImportMetadataRequest, ImportProgress]{ServerStream: stream}) +} + +// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. +type MetadataService_ImportMetadataServer = grpc.ServerStreamingServer[ImportProgress] + +// MetadataService_ServiceDesc is the grpc.ServiceDesc for MetadataService service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var MetadataService_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "musicfs.v1.MetadataService", + HandlerType: (*MetadataServiceServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "GetMetadata", + Handler: _MetadataService_GetMetadata_Handler, + }, + { + MethodName: "UpdateMetadata", + Handler: _MetadataService_UpdateMetadata_Handler, + }, + { + MethodName: "ClearOverlay", + Handler: _MetadataService_ClearOverlay_Handler, + }, + }, + Streams: []grpc.StreamDesc{ + { + StreamName: "BatchUpdateMetadata", + Handler: _MetadataService_BatchUpdateMetadata_Handler, + ServerStreams: true, + }, + { + StreamName: "ImportMetadata", + Handler: _MetadataService_ImportMetadata_Handler, + ServerStreams: true, + }, + }, + Metadata: "musicfs.proto", +} diff --git a/internal/matcher/album.go b/internal/matcher/album.go new file mode 100644 index 0000000..6210ff7 --- /dev/null +++ b/internal/matcher/album.go @@ -0,0 +1,135 @@ +package matcher + +import ( + "regexp" + "strings" +) + +const MatchThreshold = 0.7 + +var ( + punctuationRe = regexp.MustCompile(`[^\w\s]`) + yearRe = regexp.MustCompile(`\b(19|20)\d{2}\b`) + whitespaceRe = regexp.MustCompile(`\s+`) + noiseWords = map[string]struct{}{ + "remastered": {}, "remaster": {}, "deluxe": {}, "edition": {}, + "expanded": {}, "anniversary": {}, "special": {}, "limited": {}, + "collectors": {}, "collector": {}, "bonus": {}, "tracks": {}, + "standard": {}, "super": {}, + "flac": {}, "mp3": {}, "aac": {}, "ogg": {}, "wav": {}, + "24bit": {}, "16bit": {}, "48khz": {}, "44khz": {}, "96khz": {}, "192khz": {}, + "cd": {}, "vinyl": {}, "lp": {}, "web": {}, "sacd": {}, + "box": {}, "set": {}, "japan": {}, "shm": {}, + "singles": {}, "single": {}, + "pmedia": {}, + } +) + +func normalize(s string) string { + s = strings.ToLower(s) + s = punctuationRe.ReplaceAllString(s, " ") + s = yearRe.ReplaceAllString(s, " ") + s = whitespaceRe.ReplaceAllString(s, " ") + return strings.TrimSpace(s) +} + +func tokenize(s string) []string { + var tokens []string + for _, word := range strings.Fields(s) { + if _, noise := noiseWords[word]; !noise && len(word) > 1 { + tokens = append(tokens, word) + } + } + return tokens +} + +func AlbumMatchScore(albumTitle, torrentTitle, artistName string) float64 { + normAlbum := normalize(albumTitle) + normTorrent := normalize(torrentTitle) + + if artistName != "" { + normArtist := normalize(artistName) + normTorrent = strings.Replace(normTorrent, normArtist, "", 1) + normTorrent = strings.TrimSpace(whitespaceRe.ReplaceAllString(normTorrent, " ")) + } + + if normAlbum == "" { + return 0 + } + + if strings.Contains(normTorrent, normAlbum) { + return 1.0 + } + + albumTokens := tokenize(normAlbum) + if len(albumTokens) == 0 { + return 0 + } + + torrentTokens := make(map[string]struct{}, len(albumTokens)) + for _, t := range tokenize(normTorrent) { + torrentTokens[t] = struct{}{} + } + + var matches int + for _, token := range albumTokens { + if _, found := torrentTokens[token]; found { + matches++ + continue + } + for tt := range torrentTokens { + if levenshteinClose(token, tt) { + matches++ + break + } + } + } + + return float64(matches) / float64(len(albumTokens)) +} + +func levenshteinClose(a, b string) bool { + if len(a) < 3 || len(b) < 3 { + return false + } + maxDist := 1 + if len(a) > 6 { + maxDist = 2 + } + return levenshtein(a, b) <= maxDist +} + +func levenshtein(a, b string) int { + la, lb := len(a), len(b) + if la == 0 { + return lb + } + if lb == 0 { + return la + } + + prev := make([]int, lb+1) + curr := make([]int, lb+1) + + for j := 0; j <= lb; j++ { + prev[j] = j + } + + for i := 1; i <= la; i++ { + curr[0] = i + for j := 1; j <= lb; j++ { + cost := 1 + if a[i-1] == b[j-1] { + cost = 0 + } + curr[j] = min(curr[j-1]+1, min(prev[j]+1, prev[j-1]+cost)) + } + prev, curr = curr, prev + } + + return prev[lb] +} + +func IsAlbumMatch(albumTitle, torrentTitle, artistName string) bool { + return AlbumMatchScore(albumTitle, torrentTitle, artistName) >= MatchThreshold +} diff --git a/internal/matcher/album_test.go b/internal/matcher/album_test.go new file mode 100644 index 0000000..3dbd0b2 --- /dev/null +++ b/internal/matcher/album_test.go @@ -0,0 +1,95 @@ +package matcher + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestAlbumMatchScore(t *testing.T) { + tests := []struct { + album string + torrent string + artist string + wantMin float64 + wantMax float64 + match bool + }{ + { + album: "Ain't My Bitch", + torrent: "Metallica - Ain't My Bitch (2025) [FLAC]", + artist: "Metallica", + wantMin: 0.9, wantMax: 1.0, match: true, + }, + { + album: "Ain't My Bitch", + torrent: "Metallica - Aint My Bitch Remastered 2025 FLAC", + artist: "Metallica", + wantMin: 0.9, wantMax: 1.0, match: true, + }, + { + album: "72 Seasons", + torrent: "Metallica - 72 Seasons (2023) [24Bit-48kHz] FLAC [PMEDIA] ⭐️", + artist: "Metallica", + wantMin: 0.9, wantMax: 1.0, match: true, + }, + { + album: "Kill 'Em All", + torrent: "Metallica - Kill Em All [1983] FLAC", + artist: "Metallica", + wantMin: 0.9, wantMax: 1.0, match: true, + }, + { + album: "...And Justice for All", + torrent: "Metallica - And Justice For All (Remastered) FLAC", + artist: "Metallica", + wantMin: 0.7, wantMax: 1.0, match: true, + }, + { + album: "Master of Puppets", + torrent: "Metallica - Master of Puppets (Remastered Deluxe Box Set) FLAC", + artist: "Metallica", + wantMin: 0.9, wantMax: 1.0, match: true, + }, + { + album: "Ain't My Bitch", + torrent: "Metallica - Load 1996 (Japan SHM-CD)", + artist: "Metallica", + wantMin: 0.0, wantMax: 0.3, match: false, + }, + { + album: "Ain't My Bitch", + torrent: "Metallica - The Memory Remains (Singles, 2026 remastered)", + artist: "Metallica", + wantMin: 0.0, wantMax: 0.3, match: false, + }, + { + album: "Ain't My Bitch", + torrent: "Metallica - 72 Seasons (2023) [24Bit-48kHz] FLAC", + artist: "Metallica", + wantMin: 0.0, wantMax: 0.3, match: false, + }, + { + album: "Hardwired...to Self-Destruct", + torrent: "Metallica - Hardwired To Self-Destruct (Deluxe 2016) [FLAC]", + artist: "Metallica", + wantMin: 0.7, wantMax: 1.0, match: true, + }, + { + album: "S&M", + torrent: "Metallica - S&M (1999) [FLAC]", + artist: "Metallica", + wantMin: 0.9, wantMax: 1.0, match: true, + }, + } + + for _, tt := range tests { + t.Run(tt.album+" vs "+tt.torrent, func(t *testing.T) { + score := AlbumMatchScore(tt.album, tt.torrent, tt.artist) + assert.GreaterOrEqual(t, score, tt.wantMin, "score too low: %.2f", score) + assert.LessOrEqual(t, score, tt.wantMax, "score too high: %.2f", score) + assert.Equal(t, tt.match, IsAlbumMatch(tt.album, tt.torrent, tt.artist), + "match mismatch for score %.2f", score) + }) + } +}