Parcourir la source

Update protocol files.

Paul Lietar il y a 9 ans
Parent
commit
addc1fce22

+ 4 - 4
Cargo.lock

@@ -26,7 +26,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "bitflags"
-version = "0.2.1"
+version = "0.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
@@ -113,7 +113,7 @@ source = "git+https://github.com/stepancheg/rust-protobuf.git#d6e80593f38ce47dfa
 [[package]]
 name = "protobuf_macros"
 version = "0.1.0"
-source = "git+https://github.com/plietar/rust-protobuf-macros.git#5fa976178a48b01bdf2da6d5e7929367e348ea04"
+source = "git+https://github.com/plietar/rust-protobuf-macros.git#3b49de3937a34b7a21be1d13caea4348a93c6de4"
 
 [[package]]
 name = "rand"
@@ -143,7 +143,7 @@ dependencies = [
 [[package]]
 name = "rust-gmp"
 version = "0.2.0"
-source = "git+https://github.com/plietar/rust-gmp.git#db2bb627165b12ebe18a41a941ac6284ce9b895d"
+source = "git+https://github.com/plietar/rust-gmp.git#cc003c224559f6035cd34a7ed5c6284a49785816"
 dependencies = [
  "num 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -185,7 +185,7 @@ name = "vergen"
 version = "0.0.13"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "bitflags 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "bitflags 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "time 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 

+ 1 - 6
protocol/build.rs

@@ -43,12 +43,7 @@ fn main() {
             &proto.join("authentication.proto"),
             &proto.join("mercury.proto"),
             &proto.join("metadata.proto"),
-            &proto.join("playlist4changes.proto"),
-            &proto.join("playlist4content.proto"),
-            &proto.join("playlist4issues.proto"),
-            &proto.join("playlist4meta.proto"),
-            &proto.join("playlist4ops.proto"),
-            &proto.join("playlist4service.proto"),
+            &proto.join("spirc.proto"),
     ]).unwrap();
 }
 

+ 49 - 0
protocol/proto/ad-hermes-proxy.proto

@@ -0,0 +1,49 @@
+message Rule {
+    optional string type = 0x1;
+    optional uint32 times = 0x2;
+    optional uint64 interval = 0x3;
+}
+
+message AdRequest {
+    optional string client_language = 0x1;
+    optional string product = 0x2;
+    optional uint32 version = 0x3;
+    optional string type = 0x4;
+    repeated string avoidAds = 0x5;
+}
+
+message AdQueueResponse {
+    repeated AdQueueEntry adQueueEntry = 0x1;
+}
+
+message AdFile {
+    optional string id = 0x1;
+    optional string format = 0x2;
+}
+
+message AdQueueEntry {
+    optional uint64 start_time = 0x1;
+    optional uint64 end_time = 0x2;
+    optional double priority = 0x3;
+    optional string token = 0x4;
+    optional uint32 ad_version = 0x5;
+    optional string id = 0x6;
+    optional string type = 0x7;
+    optional string campaign = 0x8;
+    optional string advertiser = 0x9;
+    optional string url = 0xa;
+    optional uint64 duration = 0xb;
+    optional uint64 expiry = 0xc;
+    optional string tracking_url = 0xd;
+    optional string banner_type = 0xe;
+    optional string html = 0xf;
+    optional string image = 0x10;
+    optional string background_image = 0x11;
+    optional string background_url = 0x12;
+    optional string background_color = 0x13;
+    optional string title = 0x14;
+    optional string caption = 0x15;
+    repeated AdFile file = 0x16;
+    repeated Rule rule = 0x17;
+}
+

+ 93 - 0
protocol/proto/appstore.proto

@@ -0,0 +1,93 @@
+message AppInfo {
+    optional string identifier = 0x1;
+    optional int32 version_int = 0x2;
+}
+
+message AppInfoList {
+    repeated AppInfo items = 0x1;
+}
+
+message SemanticVersion {
+    optional int32 major = 0x1;
+    optional int32 minor = 0x2;
+    optional int32 patch = 0x3;
+}
+
+message RequestHeader {
+    optional string market = 0x1;
+    optional Platform platform = 0x2;
+    enum Platform {
+        WIN32_X86 = 0x0;
+        OSX_X86 = 0x1;
+        LINUX_X86 = 0x2;
+        IPHONE_ARM = 0x3;
+        SYMBIANS60_ARM = 0x4;
+        OSX_POWERPC = 0x5;
+        ANDROID_ARM = 0x6;
+        WINCE_ARM = 0x7;
+        LINUX_X86_64 = 0x8;
+        OSX_X86_64 = 0x9;
+        PALM_ARM = 0xa;
+        LINUX_SH = 0xb;
+        FREEBSD_X86 = 0xc;
+        FREEBSD_X86_64 = 0xd;
+        BLACKBERRY_ARM = 0xe;
+        SONOS_UNKNOWN = 0xf;
+        LINUX_MIPS = 0x10;
+        LINUX_ARM = 0x11;
+        LOGITECH_ARM = 0x12;
+        LINUX_BLACKFIN = 0x13;
+        ONKYO_ARM = 0x15;
+        QNXNTO_ARM = 0x16;
+        BADPLATFORM = 0xff;
+    }
+    optional AppInfoList app_infos = 0x6;
+    optional string bridge_identifier = 0x7;
+    optional SemanticVersion bridge_version = 0x8;
+    optional DeviceClass device_class = 0x9;
+    enum DeviceClass {
+        DESKTOP = 0x1;
+        TABLET = 0x2;
+        MOBILE = 0x3;
+        WEB = 0x4;
+        TV = 0x5;
+    }
+}
+
+message AppItem {
+    optional string identifier = 0x1;
+    optional Requirement requirement = 0x2;
+    enum Requirement {
+        REQUIRED_INSTALL = 0x1;
+        LAZYLOAD = 0x2;
+        OPTIONAL_INSTALL = 0x3;
+    }
+    optional string manifest = 0x4;
+    optional string checksum = 0x5;
+    optional string bundle_uri = 0x6;
+    optional string small_icon_uri = 0x7;
+    optional string large_icon_uri = 0x8;
+    optional string medium_icon_uri = 0x9;
+    optional Type bundle_type = 0xa;
+    enum Type {
+        APPLICATION = 0x0;
+        FRAMEWORK = 0x1;
+        BRIDGE = 0x2;
+    }
+    optional SemanticVersion version = 0xb;
+    optional uint32 ttl_in_seconds = 0xc;
+    optional IdentifierList categories = 0xd;
+}
+
+message AppList {
+    repeated AppItem items = 0x1;
+}
+
+message IdentifierList {
+    repeated string identifiers = 0x1;
+}
+
+message BannerConfig {
+    optional string json = 0x1;
+}
+

+ 43 - 54
protocol/proto/authentication.proto

@@ -1,21 +1,20 @@
-//  size=30
+
 message ClientResponseEncrypted {
-    required LoginCredentials login_credentials = 0xa; // idx=0 offset=c
-    optional AccountCreation account_creation = 0x14; // idx=1 offset=10
-    optional FingerprintResponseUnion fingerprint_response = 0x1e; // idx=2 offset=14
-    optional PeerTicketUnion peer_ticket = 0x28; // idx=3 offset=18
-    required SystemInfo system_info = 0x32; // idx=4 offset=1c
-    optional string platform_model = 0x3c; // idx=5 offset=20
-    optional string version_string = 0x46; // idx=6 offset=24
-    optional LibspotifyAppKey appkey = 0x50; // idx=7 offset=28
-    optional ClientInfo client_info = 0x5a; // idx=8 offset=2c
-}
-
-//  size=18
+    required LoginCredentials login_credentials = 0xa; 
+    optional AccountCreation account_creation = 0x14; 
+    optional FingerprintResponseUnion fingerprint_response = 0x1e; 
+    optional PeerTicketUnion peer_ticket = 0x28; 
+    required SystemInfo system_info = 0x32; 
+    optional string platform_model = 0x3c; 
+    optional string version_string = 0x46; 
+    optional LibspotifyAppKey appkey = 0x50; 
+    optional ClientInfo client_info = 0x5a; 
+}
+
 message LoginCredentials {
-    optional string username = 0xa; // idx=0 offset=c
-    required Type typ = 0x14; // idx=1 offset=10
-    optional bytes auth_data = 0x1e; // idx=2 offset=14
+    optional string username = 0xa; 
+    required Type typ = 0x14; 
+    optional bytes auth_data = 0x1e; 
 }
 
 enum Type {
@@ -31,51 +30,44 @@ enum AccountCreation {
     ACCOUNT_CREATION_ALWAYS_CREATE = 0x3;
 }
 
-//  size=14
 message FingerprintResponseUnion {
-    optional FingerprintGrainResponse grain = 0xa; // idx=0 offset=c
-    optional FingerprintHmacRipemdResponse hmac_ripemd = 0x14; // idx=1 offset=10
+    optional FingerprintGrainResponse grain = 0xa; 
+    optional FingerprintHmacRipemdResponse hmac_ripemd = 0x14; 
 }
 
-//  size=1c
 message FingerprintGrainResponse {
-    required bytes encrypted_key = 0xa; // idx=0 offset=c size=f
+    required bytes encrypted_key = 0xa; 
 }
 
-//  size=20
 message FingerprintHmacRipemdResponse {
-    required bytes hmac = 0xa; // idx=0 offset=c size=13
+    required bytes hmac = 0xa; 
 }
 
-//  size=14
 message PeerTicketUnion {
-    optional PeerTicketPublicKey public_key = 0xa; // idx=0 offset=c
-    optional PeerTicketOld old_ticket = 0x14; // idx=1 offset=10
+    optional PeerTicketPublicKey public_key = 0xa; 
+    optional PeerTicketOld old_ticket = 0x14; 
 }
 
-//  size=8c
 message PeerTicketPublicKey {
-    required bytes public_key = 0xa; // idx=0 offset=c size=7f
+    required bytes public_key = 0xa; 
 }
 
-//  size=90
 message PeerTicketOld {
-    required bytes peer_ticket = 0xa; // idx=0 offset=c
-    required bytes peer_ticket_signature = 0x14; // idx=1 offset=10 size=7f
+    required bytes peer_ticket = 0xa; 
+    required bytes peer_ticket_signature = 0x14; 
 }
 
-//  size=34
 message SystemInfo {
-    required CpuFamily cpu_family = 0xa; // idx=0 offset=c
-    optional uint32 cpu_subtype = 0x14; // idx=1 offset=10
-    optional uint32 cpu_ext = 0x1e; // idx=2 offset=14
-    optional Brand brand = 0x28; // idx=3 offset=18
-    optional uint32 brand_flags = 0x32; // idx=4 offset=1c
-    required Os os = 0x3c; // idx=5 offset=20
-    optional uint32 os_version = 0x46; // idx=6 offset=24
-    optional uint32 os_ext = 0x50; // idx=7 offset=28
-    optional string system_information_string = 0x5a; // idx=8 offset=2c
-    optional string device_id = 0x64; // idx=9 offset=30
+    required CpuFamily cpu_family = 0xa; 
+    optional uint32 cpu_subtype = 0x14; 
+    optional uint32 cpu_ext = 0x1e; 
+    optional Brand brand = 0x28; 
+    optional uint32 brand_flags = 0x32; 
+    required Os os = 0x3c; 
+    optional uint32 os_version = 0x46; 
+    optional uint32 os_ext = 0x50; 
+    optional string system_information_string = 0x5a; 
+    optional string device_id = 0x64; 
 }
 
 enum CpuFamily {
@@ -124,25 +116,22 @@ enum Os {
     OS_BCO = 0x16;
 }
 
-//  size=168
 message LibspotifyAppKey {
-    required uint32 version = 0x1; // idx=0 offset=c
-    required bytes devkey = 0x2; // idx=1 offset=10 size=7f
-    required bytes signature = 0x3; // idx=2 offset=90 size=bf
-    required string useragent = 0x4; // idx=3 offset=150
-    required bytes callback_hash = 0x5; // idx=4 offset=154 size=13
+    required uint32 version = 0x1; 
+    required bytes devkey = 0x2; 
+    required bytes signature = 0x3; 
+    required string useragent = 0x4; 
+    required bytes callback_hash = 0x5; 
 }
 
-//  size=18
 message ClientInfo {
-    optional bool limited = 0x1; // idx=0 offset=c
-    optional ClientInfoFacebook fb = 0x2; // idx=1 offset=10
-    optional string language = 0x3; // idx=2 offset=14
+    optional bool limited = 0x1; 
+    optional ClientInfoFacebook fb = 0x2; 
+    optional string language = 0x3; 
 }
 
-//  size=10
 message ClientInfoFacebook {
-    optional string machine_id = 0x1; // idx=0 offset=c
+    optional string machine_id = 0x1; 
 }
 
 message AuthSuccess {

+ 49 - 0
protocol/proto/facebook-publish.proto

@@ -0,0 +1,49 @@
+message EventReply {
+    optional int32 queued = 0x1;
+    optional RetryInfo retry = 0x2;
+}
+
+message RetryInfo {
+    optional int32 retry_delay = 0x1;
+    optional int32 max_retry = 0x2;
+}
+
+message Id {
+    optional string uri = 0x1;
+    optional int64 start_time = 0x2;
+}
+
+message Start {
+    optional int32 length = 0x1;
+    optional string context_uri = 0x2;
+    optional int64 end_time = 0x3;
+}
+
+message Seek {
+    optional int64 end_time = 0x1;
+}
+
+message Pause {
+    optional int32 seconds_played = 0x1;
+    optional int64 end_time = 0x2;
+}
+
+message Resume {
+    optional int32 seconds_played = 0x1;
+    optional int64 end_time = 0x2;
+}
+
+message End {
+    optional int32 seconds_played = 0x1;
+    optional int64 end_time = 0x2;
+}
+
+message Event {
+    optional Id id = 0x1;
+    optional Start start = 0x2;
+    optional Seek seek = 0x3;
+    optional Pause pause = 0x4;
+    optional Resume resume = 0x5;
+    optional End end = 0x6;
+}
+

+ 181 - 0
protocol/proto/facebook.proto

@@ -0,0 +1,181 @@
+message Credential {
+    optional string facebook_uid = 0x1;
+    optional string access_token = 0x2;
+}
+
+message EnableRequest {
+    optional Credential credential = 0x1;
+}
+
+message EnableReply {
+    optional Credential credential = 0x1;
+}
+
+message DisableRequest {
+    optional Credential credential = 0x1;
+}
+
+message RevokeRequest {
+    optional Credential credential = 0x1;
+}
+
+message InspectCredentialRequest {
+    optional Credential credential = 0x1;
+}
+
+message InspectCredentialReply {
+    optional Credential alternative_credential = 0x1;
+    optional bool app_user = 0x2;
+    optional bool permanent_error = 0x3;
+    optional bool transient_error = 0x4;
+}
+
+message UserState {
+    optional Credential credential = 0x1;
+}
+
+message UpdateUserStateRequest {
+    optional Credential credential = 0x1;
+}
+
+message OpenGraphError {
+    repeated string permanent = 0x1;
+    repeated string invalid_token = 0x2;
+    repeated string retries = 0x3;
+}
+
+message OpenGraphScrobble {
+    optional int32 create_delay = 0x1;
+}
+
+message OpenGraphConfig {
+    optional OpenGraphError error = 0x1;
+    optional OpenGraphScrobble scrobble = 0x2;
+}
+
+message AuthConfig {
+    optional string url = 0x1;
+    repeated string permissions = 0x2;
+    repeated string blacklist = 0x3;
+    repeated string whitelist = 0x4;
+    repeated string cancel = 0x5;
+}
+
+message ConfigReply {
+    optional string domain = 0x1;
+    optional string app_id = 0x2;
+    optional string app_namespace = 0x3;
+    optional AuthConfig auth = 0x4;
+    optional OpenGraphConfig og = 0x5;
+}
+
+message UserFields {
+    optional bool app_user = 0x1;
+    optional bool display_name = 0x2;
+    optional bool first_name = 0x3;
+    optional bool middle_name = 0x4;
+    optional bool last_name = 0x5;
+    optional bool picture_large = 0x6;
+    optional bool picture_square = 0x7;
+    optional bool gender = 0x8;
+    optional bool email = 0x9;
+}
+
+message UserOptions {
+    optional bool cache_is_king = 0x1;
+}
+
+message UserRequest {
+    optional UserOptions options = 0x1;
+    optional UserFields fields = 0x2;
+}
+
+message User {
+    optional string spotify_username = 0x1;
+    optional string facebook_uid = 0x2;
+    optional bool app_user = 0x3;
+    optional string display_name = 0x4;
+    optional string first_name = 0x5;
+    optional string middle_name = 0x6;
+    optional string last_name = 0x7;
+    optional string picture_large = 0x8;
+    optional string picture_square = 0x9;
+    optional string gender = 0xa;
+    optional string email = 0xb;
+}
+
+message FriendsFields {
+    optional bool app_user = 0x1;
+    optional bool display_name = 0x2;
+    optional bool picture_large = 0x6;
+}
+
+message FriendsOptions {
+    optional int32 limit = 0x1;
+    optional int32 offset = 0x2;
+    optional bool cache_is_king = 0x3;
+    optional bool app_friends = 0x4;
+    optional bool non_app_friends = 0x5;
+}
+
+message FriendsRequest {
+    optional FriendsOptions options = 0x1;
+    optional FriendsFields fields = 0x2;
+}
+
+message FriendsReply {
+    repeated User friends = 0x1;
+    optional bool more = 0x2;
+}
+
+message ShareRequest {
+    optional Credential credential = 0x1;
+    optional string uri = 0x2;
+    optional string message_text = 0x3;
+}
+
+message ShareReply {
+    optional string post_id = 0x1;
+}
+
+message InboxRequest {
+    optional Credential credential = 0x1;
+    repeated string facebook_uids = 0x3;
+    optional string message_text = 0x4;
+    optional string message_link = 0x5;
+}
+
+message InboxReply {
+    optional string message_id = 0x1;
+    optional string thread_id = 0x2;
+}
+
+message PermissionsOptions {
+    optional bool cache_is_king = 0x1;
+}
+
+message PermissionsRequest {
+    optional Credential credential = 0x1;
+    optional PermissionsOptions options = 0x2;
+}
+
+message PermissionsReply {
+    repeated string permissions = 0x1;
+}
+
+message GrantPermissionsRequest {
+    optional Credential credential = 0x1;
+    repeated string permissions = 0x2;
+}
+
+message GrantPermissionsReply {
+    repeated string granted = 0x1;
+    repeated string failed = 0x2;
+}
+
+message TransferRequest {
+    optional Credential credential = 0x1;
+    optional string source_username = 0x2;
+    optional string target_username = 0x3;
+}
+

+ 30 - 35
protocol/proto/mercury.proto

@@ -1,49 +1,44 @@
-message MercuryRequest {
-    required string url = 0x01;
-    optional string mime = 0x02;
-    required string method = 0x03;
-}
-
-message MercuryReply {
-    required string url = 0x01;
-    required string mime = 0x02;
-    required sint32 code = 0x04;
-    repeated Header header = 0x06;
-
-    message Header {
-        required string key = 0x01;
-        required bytes value = 0x02;
-    }
+message MercuryMultiGetRequest {
+    repeated MercuryRequest request = 0x1;
 }
 
-message MercuryGetRequest {
-    required string url = 0x01;
-    optional string method = 0x03;
+message MercuryMultiGetReply {
+    repeated MercuryReply reply = 0x1;
 }
 
-message MercuryMultiGetRequest {
-    repeated MercuryGetRequest request = 0x01;
+message MercuryRequest {
+    optional string uri = 0x1;
+    optional string content_type = 0x2;
+    optional bytes body = 0x3;
+    optional bytes etag = 0x4;
 }
 
-message MercuryGetReply {
+message MercuryReply {
+    optional sint32 status_code = 0x1;
+    optional string status_message = 0x2;
+    optional CachePolicy cache_policy = 0x3;
     enum CachePolicy {
-        CACHE_NO = 1;
-        CACHE_PRIVATE = 2;
-        CACHE_PUBLIC = 3;
+        CACHE_NO = 0x1;
+        CACHE_PRIVATE = 0x2;
+        CACHE_PUBLIC = 0x3;
     }
-    optional sint32 code = 0x01;
-    optional CachePolicy cache_policy = 0x03;
-    optional uint32 ttl = 0x04;
-    optional bytes etag = 0x05;
-    optional string mime = 0x06;
-    optional bytes body = 0x07;
+    optional sint32 ttl = 0x4;
+    optional bytes etag = 0x5;
+    optional string content_type = 0x6;
+    optional bytes body = 0x7;
 }
 
-message MercuryMultiGetReply {
-    repeated MercuryGetReply reply = 0x1;
+
+message Header {
+    optional string uri = 0x01;
+    optional string content_type = 0x02;
+    optional string method = 0x03;
+    optional sint32 status_code = 0x04;
+    repeated UserField user_fields = 0x06;
 }
 
-message MercurySubscribed {
-    required string url = 0x1;
+message UserField {
+    optional string key = 0x01;
+    optional bytes value = 0x02;
 }
 

+ 8 - 0
protocol/proto/mergedprofile.proto

@@ -0,0 +1,8 @@
+message MergedProfileRequest {
+}
+
+message MergedProfileReply {
+    optional string username = 0x1;
+    optional string artistid = 0x2;
+}
+

+ 113 - 108
protocol/proto/metadata.proto

@@ -1,154 +1,159 @@
 message TopTracks {
-    optional string country = 1;
-    repeated Track track = 2;
+    optional string country = 0x1;
+    repeated Track track = 0x2;
 }
+
 message ActivityPeriod {
-    optional sint32 start_year = 1;
-    optional sint32 end_year = 2;
-    optional sint32 decade = 3;
+    optional sint32 start_year = 0x1;
+    optional sint32 end_year = 0x2;
+    optional sint32 decade = 0x3;
 }
+
 message Artist {
-    optional bytes gid = 1;
-    optional string name = 2;
-    optional sint32 popularity = 3;
-    repeated TopTracks top_track = 4;
-    repeated AlbumGroup album_group = 5;
-    repeated AlbumGroup single_group = 6;
-    repeated AlbumGroup compilation_group = 7;
-    repeated AlbumGroup appears_on_group = 8;
-    repeated string genre = 9;
-    repeated ExternalId external_id = 10;
-    repeated Image portrait = 11;
-    repeated Biography biography = 12;
-    repeated ActivityPeriod activity_period = 13;
-    repeated Restriction restriction = 14;
-    repeated Artist related = 15;
-    optional bool is_portrait_album_cover = 16;
-    optional ImageGroup portrait_group = 17;
+    optional bytes gid = 0x1;
+    optional string name = 0x2;
+    optional sint32 popularity = 0x3;
+    repeated TopTracks top_track = 0x4;
+    repeated AlbumGroup album_group = 0x5;
+    repeated AlbumGroup single_group = 0x6;
+    repeated AlbumGroup compilation_group = 0x7;
+    repeated AlbumGroup appears_on_group = 0x8;
+    repeated string genre = 0x9;
+    repeated ExternalId external_id = 0xa;
+    repeated Image portrait = 0xb;
+    repeated Biography biography = 0xc;
+    repeated ActivityPeriod activity_period = 0xd;
+    repeated Restriction restriction = 0xe;
+    repeated Artist related = 0xf;
+    optional bool is_portrait_album_cover = 0x10;
+    optional ImageGroup portrait_group = 0x11;
 }
+
 message AlbumGroup {
-    repeated Album album = 1;
+    repeated Album album = 0x1;
 }
+
 message Date {
-    optional sint32 year = 1;
-    optional sint32 month = 2;
-    optional sint32 day = 3;
+    optional sint32 year = 0x1;
+    optional sint32 month = 0x2;
+    optional sint32 day = 0x3;
 }
+
 message Album {
+    optional bytes gid = 0x1;
+    optional string name = 0x2;
+    repeated Artist artist = 0x3;
+    optional Type type = 0x4;
     enum Type {
-        ALBUM = 1;
-        SINGLE = 2;
-        COMPILATION = 3;
+        ALBUM = 0x1;
+        SINGLE = 0x2;
+        COMPILATION = 0x3;
     }
-    optional bytes gid = 1;
-    optional string name = 2;
-    repeated Artist artist = 3;
-    optional Type typ = 4;
-    optional string label = 5;
-    optional Date date = 6;
-    optional sint32 popularity = 7;
-    repeated string genre = 8;
-    repeated Image cover = 9;
-    repeated ExternalId external_id = 10;
-    repeated Disc disc = 11;
-    repeated string review = 12;
-    repeated Copyright copyright = 13;
-    repeated Restriction restriction = 14;
-    repeated Album related = 15;
-    repeated SalePeriod sale_period  = 16;
-    optional ImageGroup cover_group  = 17;
+    optional string label = 0x5;
+    optional Date date = 0x6;
+    optional sint32 popularity = 0x7;
+    repeated string genre = 0x8;
+    repeated Image cover = 0x9;
+    repeated ExternalId external_id = 0xa;
+    repeated Disc disc = 0xb;
+    repeated string review = 0xc;
+    repeated Copyright copyright = 0xd;
+    repeated Restriction restriction = 0xe;
+    repeated Album related = 0xf;
+    repeated SalePeriod sale_period = 0x10;
+    optional ImageGroup cover_group = 0x11;
 }
 
 message Track {
-    optional bytes gid = 1;
-    optional string name = 2;
-    optional Album album = 3;
-    repeated Artist artist = 4;
-    optional sint32 number = 5;
-    optional sint32 disc_number = 6;
-    optional sint32 duration = 7;
-    optional sint32 popularity = 8;
-    optional bool explicit = 9;
-    repeated ExternalId external_id = 10;
-    repeated Restriction restriction = 11;
-    repeated AudioFile file = 12;
-    repeated Track alternative = 13;
-    repeated SalePeriod sale_period = 14;
-    repeated AudioFile preview = 15;
+    optional bytes gid = 0x1;
+    optional string name = 0x2;
+    optional Album album = 0x3;
+    repeated Artist artist = 0x4;
+    optional sint32 number = 0x5;
+    optional sint32 disc_number = 0x6;
+    optional sint32 duration = 0x7;
+    optional sint32 popularity = 0x8;
+    optional bool explicit = 0x9;
+    repeated ExternalId external_id = 0xa;
+    repeated Restriction restriction = 0xb;
+    repeated AudioFile file = 0xc;
+    repeated Track alternative = 0xd;
+    repeated SalePeriod sale_period = 0xe;
+    repeated AudioFile preview = 0xf;
 }
+
 message Image {
+    optional bytes file_id = 0x1;
+    optional Size size = 0x2;
     enum Size {
-        DEFAULT = 0;
-        SMALL = 1;
-        LARGE = 2;
-        XLARGE = 3;
+        DEFAULT = 0x0;
+        SMALL = 0x1;
+        LARGE = 0x2;
+        XLARGE = 0x3;
     }
-    optional bytes file_id = 1;
-    optional Size size = 2;
-    optional sint32 width = 3;
-    optional sint32 height = 4;
+    optional sint32 width = 0x3;
+    optional sint32 height = 0x4;
 }
+
 message ImageGroup {
-    repeated Image image = 1;
+    repeated Image image = 0x1;
 }
+
 message Biography {
-    optional string text = 1;
-    repeated Image portrait = 2;
-    repeated ImageGroup portrait_group = 3;
+    optional string text = 0x1;
+    repeated Image portrait = 0x2;
+    repeated ImageGroup portrait_group = 0x3;
 }
+
 message Disc {
-    optional sint32 number = 1;
-    optional string name = 2;
-    repeated Track track = 3;
+    optional sint32 number = 0x1;
+    optional string name = 0x2;
+    repeated Track track = 0x3;
 }
+
 message Copyright {
+    optional Type type = 0x1;
     enum Type {
-        P = 0;
-        C = 1;
+        P = 0x0;
+        C = 0x1;
     }
-    optional Type typ = 1;
-    optional string text = 2;
+    optional string text = 0x2;
 }
+
 message Restriction {
-    enum Catalogue {
-        FREE = 0;
-        PREMIUM = 1;
-        SHUFFLE = 3;
-        COMMERCIAL = 4;
-    }
+    optional string countries_allowed = 0x2;
+    optional string countries_forbidden = 0x3;
+    optional Type type = 0x4;
     enum Type {
-        STREAMING = 0;
+        STREAMING = 0x0;
     }
-    repeated Catalogue catalogue = 1;
-    optional string countries_allowed = 2;
-    optional string countries_forbidden = 3;
-    optional Type typ = 4;
-    repeated string usage = 5;
+    repeated string catalogue_str = 0x5;
 }
 
 message SalePeriod {
-    repeated Restriction restriction = 1;
-    optional Date start = 2;
-    optional Date end = 3;
+    repeated Restriction restriction = 0x1;
+    optional Date start = 0x2;
+    optional Date end = 0x3;
 }
 
 message ExternalId {
-    optional string typ = 1;
-    optional string id = 2;
+    optional string type = 0x1;
+    optional string id = 0x2;
 }
 
 message AudioFile {
+    optional bytes file_id = 0x1;
+    optional Format format = 0x2;
     enum Format {
-        OGG_VORBIS_96 = 0;
-        OGG_VORBIS_160 = 1;
-        OGG_VORBIS_320 = 2;
-        MP3_256 = 3;
-        MP3_320 = 4;
-        MP3_160 = 5;
-        MP3_96 = 6;
-        OTHER1 = 7; // TODO
-        OTHER2 = 8; // TODO
+        OGG_VORBIS_96 = 0x0;
+        OGG_VORBIS_160 = 0x1;
+        OGG_VORBIS_320 = 0x2;
+        MP3_256 = 0x3;
+        MP3_320 = 0x4;
+        MP3_160 = 0x5;
+        MP3_96 = 0x6;
+        OTHER = 0x7;
+        OTHER2 = 0x8;
     }
-    optional bytes gid = 1;
-    optional Format format = 2;
 }
+

+ 63 - 59
protocol/proto/playlist4changes.proto

@@ -1,80 +1,84 @@
+import "playlist4ops.proto";
+import "playlist4meta.proto";
 import "playlist4content.proto";
 import "playlist4issues.proto";
-import "playlist4meta.proto";
-import "playlist4ops.proto";
 
 message ChangeInfo {
-  optional string user = 1;
-  optional int32 timestamp = 2;
-  optional bool admin = 3;
-  optional bool undo = 4;
-  optional bool redo = 5;
-  optional bool merge = 6;
-  optional bool compressed = 7;
-  optional bool migration = 8;
+    optional string user = 0x1;
+    optional int32 timestamp = 0x2;
+    optional bool admin = 0x3;
+    optional bool undo = 0x4;
+    optional bool redo = 0x5;
+    optional bool merge = 0x6;
+    optional bool compressed = 0x7;
+    optional bool migration = 0x8;
 }
+
 message Delta {
-  optional bytes base_version = 1;
-  repeated Op ops = 2;
-  optional ChangeInfo info = 4;
+    optional bytes base_version = 0x1;
+    repeated Op ops = 0x2;
+    optional ChangeInfo info = 0x4;
 }
+
 message Merge {
-  optional bytes base_version = 1;
-  optional bytes merge_version = 2;
-  optional ChangeInfo info = 4;
+    optional bytes base_version = 0x1;
+    optional bytes merge_version = 0x2;
+    optional ChangeInfo info = 0x4;
 }
+
 message ChangeSet {
-  enum Kind {
-    KIND_UNKNOWN = 0;
-    DELTA = 2;
-    MERGE = 3;
-  };
-  required Kind kind = 1;
-  optional Delta delta = 2;
-  optional Merge merge = 3;
+    optional Kind kind = 0x1;
+    enum Kind {
+        KIND_UNKNOWN = 0x0;
+        DELTA = 0x2;
+        MERGE = 0x3;
+    }
+    optional Delta delta = 0x2;
+    optional Merge merge = 0x3;
 }
+
 message RevisionTaggedChangeSet {
-  required bytes revision = 1;
-  required ChangeSet change_set = 2;
+    optional bytes revision = 0x1;
+    optional ChangeSet change_set = 0x2;
 }
+
 message Diff {
-  required bytes from_revision = 1;
-  repeated Op ops = 2;
-  required bytes to_revision = 3;
+    optional bytes from_revision = 0x1;
+    repeated Op ops = 0x2;
+    optional bytes to_revision = 0x3;
 }
+
 message ListDump {
-  optional bytes latestRevision = 1;
-  optional int32 length = 2;
-  optional ListAttributes attributes = 3;
-  optional ListChecksum checksum = 4;
-  optional ListItems contents = 5;
-  repeated Delta pendingDeltas = 7;
+    optional bytes latestRevision = 0x1;
+    optional int32 length = 0x2;
+    optional ListAttributes attributes = 0x3;
+    optional ListChecksum checksum = 0x4;
+    optional ListItems contents = 0x5;
+    repeated Delta pendingDeltas = 0x7;
 }
+
 message ListChanges {
-  optional bytes baseRevision = 1;
-  repeated Delta deltas = 2;
-  optional bool wantResultingRevisions = 3;
-  optional bool wantSyncResult = 4;
-  optional ListDump dump = 5;
-  repeated int32 nonces = 6;
+    optional bytes baseRevision = 0x1;
+    repeated Delta deltas = 0x2;
+    optional bool wantResultingRevisions = 0x3;
+    optional bool wantSyncResult = 0x4;
+    optional ListDump dump = 0x5;
+    repeated int32 nonces = 0x6;
 }
-message SelectedListContent {
-  optional bytes revision = 1;
-  optional int32 length = 2;
-  optional ListAttributes attributes = 3;
-  optional ListChecksum checksum = 4;
-  optional ListItems contents = 5;
-  optional Diff diff = 6;
-
-  optional Diff syncResult = 7;
-  repeated bytes resultingRevisions = 8;
-
-  optional bool multipleHeads = 9;
 
-  optional bool upToDate = 10;
-
-  repeated ClientResolveAction resolveAction = 12;
-  repeated ClientIssue issues = 13;
-
-  repeated int32 nonces = 14;
+message SelectedListContent {
+    optional bytes revision = 0x1;
+    optional int32 length = 0x2;
+    optional ListAttributes attributes = 0x3;
+    optional ListChecksum checksum = 0x4;
+    optional ListItems contents = 0x5;
+    optional Diff diff = 0x6;
+    optional Diff syncResult = 0x7;
+    repeated bytes resultingRevisions = 0x8;
+    optional bool multipleHeads = 0x9;
+    optional bool upToDate = 0xa;
+    repeated ClientResolveAction resolveAction = 0xc;
+    repeated ClientIssue issues = 0xd;
+    repeated int32 nonces = 0xe;
 }
+

+ 24 - 20
protocol/proto/playlist4content.proto

@@ -2,30 +2,34 @@ import "playlist4meta.proto";
 import "playlist4issues.proto";
 
 message Item {
-  required string uri = 1;
-  optional ItemAttributes attributes = 2;
+    optional string uri = 0x1;
+    optional ItemAttributes attributes = 0x2;
 }
+
 message ListItems {
-  required int32 pos = 1;
-  required bool truncated = 2;
-  repeated Item items = 3;
+    optional int32 pos = 0x1;
+    optional bool truncated = 0x2;
+    repeated Item items = 0x3;
 }
+
 message ContentRange {
-  required int32 pos = 1;
-  optional int32 length = 2;
+    optional int32 pos = 0x1;
+    optional int32 length = 0x2;
 }
+
 message ListContentSelection {
-  optional bool wantRevision = 1;
-  optional bool wantLength = 2;
-  optional bool wantAttributes = 3;
-  optional bool wantChecksum = 4;
-  optional bool wantContent = 5;
-  optional ContentRange contentRange = 6;
-  optional bool wantDiff = 7;
-  optional bytes baseRevision = 8;
-  optional bytes hintRevision = 9;
-  optional bool wantNothingIfUpToDate = 10;
-  optional bool wantResolveAction = 12;
-  repeated ClientIssue issues = 13;
-  repeated ClientResolveAction resolveAction = 14;
+    optional bool wantRevision = 0x1;
+    optional bool wantLength = 0x2;
+    optional bool wantAttributes = 0x3;
+    optional bool wantChecksum = 0x4;
+    optional bool wantContent = 0x5;
+    optional ContentRange contentRange = 0x6;
+    optional bool wantDiff = 0x7;
+    optional bytes baseRevision = 0x8;
+    optional bytes hintRevision = 0x9;
+    optional bool wantNothingIfUpToDate = 0xa;
+    optional bool wantResolveAction = 0xc;
+    repeated ClientIssue issues = 0xd;
+    repeated ClientResolveAction resolveAction = 0xe;
 }
+

+ 36 - 35
protocol/proto/playlist4issues.proto

@@ -1,40 +1,41 @@
 message ClientIssue {
-  enum Level {
-    LEVEL_UNKNOWN = 0;
-    LEVEL_DEBUG = 1;
-    LEVEL_INFO = 2;
-    LEVEL_NOTICE = 3;
-    LEVEL_WARNING = 4;
-    LEVEL_ERROR = 5;
-  }
-  enum Code {
-    CODE_UNKNOWN = 0;
-    CODE_INDEX_OUT_OF_BOUNDS = 1;
-    CODE_VERSION_MISMATCH = 2;
-    CODE_CACHED_CHANGE = 3;
-    CODE_OFFLINE_CHANGE = 4;
-    CODE_CONCURRENT_CHANGE = 5;
-  }
-  optional Level level = 1;
-  optional Code code = 2;
-  optional int32 repeatCount = 3;
+    optional Level level = 0x1;
+    enum Level {
+        LEVEL_UNKNOWN = 0x0;
+        LEVEL_DEBUG = 0x1;
+        LEVEL_INFO = 0x2;
+        LEVEL_NOTICE = 0x3;
+        LEVEL_WARNING = 0x4;
+        LEVEL_ERROR = 0x5;
+    }
+    optional Code code = 0x2;
+    enum Code {
+        CODE_UNKNOWN = 0x0;
+        CODE_INDEX_OUT_OF_BOUNDS = 0x1;
+        CODE_VERSION_MISMATCH = 0x2;
+        CODE_CACHED_CHANGE = 0x3;
+        CODE_OFFLINE_CHANGE = 0x4;
+        CODE_CONCURRENT_CHANGE = 0x5;
+    }
+    optional int32 repeatCount = 0x3;
 }
 
 message ClientResolveAction {
-  enum Code {
-    CODE_UNKNOWN = 0;
-    CODE_NO_ACTION = 1;
-    CODE_RETRY = 2;
-    CODE_RELOAD = 3;
-    CODE_DISCARD_LOCAL_CHANGES = 4;
-    CODE_SEND_DUMP = 5;
-    CODE_DISPLAY_ERROR_MESSAGE = 6;
-  }
-  enum Initiator {
-    INITIATOR_UNKNOWN = 0;
-    INITIATOR_SERVER = 1;
-    INITIATOR_CLIENT = 2;
-  }
-  optional Code code = 1;
-  optional Initiator initiator = 2;
+    optional Code code = 0x1;
+    enum Code {
+        CODE_UNKNOWN = 0x0;
+        CODE_NO_ACTION = 0x1;
+        CODE_RETRY = 0x2;
+        CODE_RELOAD = 0x3;
+        CODE_DISCARD_LOCAL_CHANGES = 0x4;
+        CODE_SEND_DUMP = 0x5;
+        CODE_DISPLAY_ERROR_MESSAGE = 0x6;
+    }
+    optional Initiator initiator = 0x2;
+    enum Initiator {
+        INITIATOR_UNKNOWN = 0x0;
+        INITIATOR_SERVER = 0x1;
+        INITIATOR_CLIENT = 0x2;
+    }
 }
+

+ 41 - 49
protocol/proto/playlist4meta.proto

@@ -1,58 +1,50 @@
 message ListChecksum {
-  required int32 version = 1;
-  optional bytes sha1 = 4;
+    optional int32 version = 0x1;
+    optional bytes sha1 = 0x4;
 }
+
 message DownloadFormat {
-  enum Codec {
-    CODEC_UNKNOWN = 0;
-    OGG_VORBIS = 1;
-    FLAC = 2;
-    MPEG_1_LAYER_3 = 3;
-  }
-  required Codec codec = 1;
-}
-enum ListAttributeKind {
-  LIST_UNKNOWN = 0;
-  LIST_NAME = 1;
-  LIST_DESCRIPTION = 2;
-  LIST_PICTURE = 3;
-  LIST_COLLABORATIVE = 4;
-  LIST_PL3_VERSION = 5;
-  LIST_DELETED_BY_OWNER = 6;
-  LIST_RESTRICTED_COLLABORATIVE = 7;
-}
+    optional Codec codec = 0x1;
+    enum Codec {
+        CODEC_UNKNOWN = 0x0;
+        OGG_VORBIS = 0x1;
+        FLAC = 0x2;
+        MPEG_1_LAYER_3 = 0x3;
+    }
+}
+
 message ListAttributes {
-  optional string name = 1;
-  optional string description = 2;
-  optional bytes picture = 3;
-  optional bool collaborative = 4;
-  optional string pl3_version = 5;
-  optional bool deleted_by_owner = 6;
-  optional bool restricted_collaborative = 7;
-}
-enum ItemAttributeKind {
-  ITEM_UNKNOWN = 0;
-  ITEM_ADDED_BY = 1;
-  ITEM_TIMESTAMP = 2;
-  ITEM_MESSAGE = 3;
-  ITEM_SEEN = 4;
-  ITEM_DOWNLOAD_COUNT = 5;
-  ITEM_DOWNLOAD_FORMAT = 6;
-  ITEM_SEVENDIGITAL_ID = 7;
-  ITEM_SEVENDIGITAL_LEFT = 8;
-  ITEM_SEEN_AT = 9;
-}
+    optional string name = 0x1;
+    optional string description = 0x2;
+    optional bytes picture = 0x3;
+    optional bool collaborative = 0x4;
+    optional string pl3_version = 0x5;
+    optional bool deleted_by_owner = 0x6;
+    optional bool restricted_collaborative = 0x7;
+    optional int64 deprecated_client_id = 0x8;
+    optional bool public_starred = 0x9;
+    optional string client_id = 0xa;
+}
+
 message ItemAttributes {
-  optional string added_by = 1;
-  optional string message = 3;
-  optional bool seen = 4;
-  optional DownloadFormat download_format = 6;
-  optional string sevendigital_id = 7;
-}
+    optional string added_by = 0x1;
+    optional int64 timestamp = 0x2;
+    optional string message = 0x3;
+    optional bool seen = 0x4;
+    optional int64 download_count = 0x5;
+    optional DownloadFormat download_format = 0x6;
+    optional string sevendigital_id = 0x7;
+    optional int64 sevendigital_left = 0x8;
+    optional int64 seen_at = 0x9;
+    optional bool public = 0xa;
+}
+
 message StringAttribute {
-  required string key = 1;
-  required string value = 2;
+    optional string key = 0x1;
+    optional string value = 0x2;
 }
+
 message StringAttributes {
-  repeated StringAttribute attribute = 1;
+    repeated StringAttribute attribute = 0x1;
 }
+

+ 80 - 47
protocol/proto/playlist4ops.proto

@@ -1,68 +1,101 @@
-import "playlist4content.proto";
 import "playlist4meta.proto";
+import "playlist4content.proto";
 
 message Add {
-  optional int32 fromIndex = 1;
-  repeated Item items = 2;
-  optional ListChecksum list_checksum = 3;
-  optional bool addLast = 4;
-  optional bool addFirst = 5;
+    optional int32 fromIndex = 0x1;
+    repeated Item items = 0x2;
+    optional ListChecksum list_checksum = 0x3;
+    optional bool addLast = 0x4;
+    optional bool addFirst = 0x5;
 }
+
 message Rem {
-  optional int32 fromIndex = 1;
-  optional int32 length = 2;
-  repeated Item items = 3;
-  optional ListChecksum list_checksum = 4;
-  optional ListChecksum items_checksum = 5;
-  optional ListChecksum uris_checksum = 6;
-  optional bool itemsAsKey = 7;
+    optional int32 fromIndex = 0x1;
+    optional int32 length = 0x2;
+    repeated Item items = 0x3;
+    optional ListChecksum list_checksum = 0x4;
+    optional ListChecksum items_checksum = 0x5;
+    optional ListChecksum uris_checksum = 0x6;
+    optional bool itemsAsKey = 0x7;
 }
+
 message Mov {
-  required int32 fromIndex = 1;
-  required int32 length = 2;
-  required int32 toIndex = 3;
-  optional ListChecksum list_checksum = 4;
-  optional ListChecksum items_checksum = 5;
-  optional ListChecksum uris_checksum = 6;
+    optional int32 fromIndex = 0x1;
+    optional int32 length = 0x2;
+    optional int32 toIndex = 0x3;
+    optional ListChecksum list_checksum = 0x4;
+    optional ListChecksum items_checksum = 0x5;
+    optional ListChecksum uris_checksum = 0x6;
 }
+
 message ItemAttributesPartialState {
-  required ItemAttributes values = 1;
-  repeated ItemAttributeKind no_value = 2;
+    optional ItemAttributes values = 0x1;
+    repeated ItemAttributeKind no_value = 0x2;
+
+    enum ItemAttributeKind {
+        ITEM_UNKNOWN = 0x0;
+        ITEM_ADDED_BY = 0x1;
+        ITEM_TIMESTAMP = 0x2;
+        ITEM_MESSAGE = 0x3;
+        ITEM_SEEN = 0x4;
+        ITEM_DOWNLOAD_COUNT = 0x5;
+        ITEM_DOWNLOAD_FORMAT = 0x6;
+        ITEM_SEVENDIGITAL_ID = 0x7;
+        ITEM_SEVENDIGITAL_LEFT = 0x8;
+        ITEM_SEEN_AT = 0x9;
+        ITEM_PUBLIC = 0xa;
+    }
 }
+
 message ListAttributesPartialState {
-  required ListAttributes values = 1;
-  repeated ListAttributeKind no_value = 2;
+    optional ListAttributes values = 0x1;
+    repeated ListAttributeKind no_value = 0x2;
+
+    enum ListAttributeKind {
+        LIST_UNKNOWN = 0x0;
+        LIST_NAME = 0x1;
+        LIST_DESCRIPTION = 0x2;
+        LIST_PICTURE = 0x3;
+        LIST_COLLABORATIVE = 0x4;
+        LIST_PL3_VERSION = 0x5;
+        LIST_DELETED_BY_OWNER = 0x6;
+        LIST_RESTRICTED_COLLABORATIVE = 0x7;
+    }
 }
+
 message UpdateItemAttributes {
-  required int32 index = 1;
-  required ItemAttributesPartialState new_attributes = 2;
-  optional ItemAttributesPartialState old_attributes = 3;
-  optional ListChecksum list_checksum = 4;
-  optional ListChecksum old_attributes_checksum = 5;
+    optional int32 index = 0x1;
+    optional ItemAttributesPartialState new_attributes = 0x2;
+    optional ItemAttributesPartialState old_attributes = 0x3;
+    optional ListChecksum list_checksum = 0x4;
+    optional ListChecksum old_attributes_checksum = 0x5;
 }
+
 message UpdateListAttributes {
-  required ListAttributesPartialState new_attributes = 1;
-  optional ListAttributesPartialState old_attributes = 2;
-  optional ListChecksum list_checksum = 3;
-  optional ListChecksum old_attributes_checksum = 4;
+    optional ListAttributesPartialState new_attributes = 0x1;
+    optional ListAttributesPartialState old_attributes = 0x2;
+    optional ListChecksum list_checksum = 0x3;
+    optional ListChecksum old_attributes_checksum = 0x4;
 }
+
 message Op {
-  enum Kind {
-    KIND_UNKNOWN = 0;
-    ADD = 2;
-    REM = 3;
-    MOV = 4;
-    UPDATE_ITEM_ATTRIBUTES = 5;
-    UPDATE_LIST_ATTRIBUTES = 6;
-  };
-  required Kind kind = 1;
-  optional Add add = 2;
-  optional Rem rem = 3;
-  optional Mov mov = 4;
-  optional UpdateItemAttributes update_item_attributes = 5;
-  optional UpdateListAttributes update_list_attributes = 6;
+    optional Kind kind = 0x1;
+    enum Kind {
+        KIND_UNKNOWN = 0x0;
+        ADD = 0x2;
+        REM = 0x3;
+        MOV = 0x4;
+        UPDATE_ITEM_ATTRIBUTES = 0x5;
+        UPDATE_LIST_ATTRIBUTES = 0x6;
+    }
+    optional Add add = 0x2;
+    optional Rem rem = 0x3;
+    optional Mov mov = 0x4;
+    optional UpdateItemAttributes update_item_attributes = 0x5;
+    optional UpdateListAttributes update_list_attributes = 0x6;
 }
 
 message OpList {
-  repeated Op ops = 1;
+    repeated Op ops = 0x1;
 }
+

+ 0 - 118
protocol/proto/playlist4service.proto

@@ -1,118 +0,0 @@
-import "playlist4changes.proto";
-import "playlist4content.proto";
-
-message RequestContext {
-  optional bool administrative = 2;
-  optional bool migration = 4;
-  optional string tag = 7;
-  optional bool useStarredView = 8;
-  optional bool syncWithPublished = 9;
-}
-message GetCurrentRevisionArgs {
-  optional bytes uri = 1;
-  optional RequestContext context = 2;
-}
-message GetChangesInSequenceRangeArgs {
-  optional bytes uri = 1;
-  optional RequestContext context = 2;
-  optional int32 fromSequenceNumber = 3;
-  optional int32 toSequenceNumber = 4;
-}
-message GetChangesInSequenceRangeMatchingPl3VersionArgs {
-  optional bytes uri = 1;
-  optional RequestContext context = 2;
-  optional int32 fromSequenceNumber = 3;
-  optional int32 toSequenceNumber = 4;
-  optional string pl3Version = 5;
-}
-message GetChangesInSequenceRangeReturn {
-  repeated RevisionTaggedChangeSet result = 1;
-}
-message ObliterateListArgs {
-  optional bytes uri = 1;
-  optional RequestContext context = 2;
-}
-message UpdatePublishedArgs {
-  optional bytes publishedUri = 1;
-  optional RequestContext context = 2;
-  optional bytes uri = 3;
-  optional bool isPublished = 4;
-}
-message SynchronizeArgs {
-  optional bytes uri = 1;
-  optional RequestContext context = 2;
-  optional ListContentSelection selection = 3;
-  optional ListChanges changes = 4;
-}
-message GetSnapshotAtRevisionArgs {
-  optional bytes uri = 1;
-  optional RequestContext context = 2;
-  optional bytes revision = 3;
-}
-message SubscribeRequest {
-  repeated bytes uris = 1;
-}
-message UnsubscribeRequest {
-  repeated bytes uris = 1;
-}
-enum Playlist4InboxErrorKind {
-  INBOX_NOT_ALLOWED = 2;
-  INBOX_INVALID_USER = 3;
-  INBOX_INVALID_URI = 4;
-  INBOX_LIST_TOO_LONG = 5;
-}
-message Playlist4ServiceException {
-  optional string why = 1;
-  optional string symbol = 2;
-  optional bool permanent = 3;
-  optional string serviceErrorClass = 4;
-  optional Playlist4InboxErrorKind inboxErrorKind = 5;
-}
-message SynchronizeReturn {
-  optional SelectedListContent result = 1;
-  optional Playlist4ServiceException exception = 4;
-}
-enum Playlist4ServiceMethodKind {
-  METHOD_UNKNOWN = 0;
-  METHOD_GET_CURRENT_REVISION = 2;
-  METHOD_GET_CHANGES_IN_SEQUENCE_RANGE = 3;
-  METHOD_OBLITERATE_LIST = 4;
-  METHOD_SYNCHRONIZE = 5;
-  METHOD_UPDATE_PUBLISHED = 6;
-  METHOD_GET_CHANGES_IN_SEQUENCE_RANGE_MATCHING_PL3_VERSION = 7;
-  METHOD_GET_SNAPSHOT_AT_REVISION = 8;
-}
-message Playlist4ServiceCall {
-  optional Playlist4ServiceMethodKind kind = 1;
-  optional GetCurrentRevisionArgs getCurrentRevisionArgs = 2;
-  optional GetChangesInSequenceRangeArgs getChangesInSequenceRangeArgs = 3;
-  optional ObliterateListArgs obliterateListArgs = 4;
-  optional SynchronizeArgs synchronizeArgs = 5;
-  optional UpdatePublishedArgs updatePublishedArgs = 6;
-  optional GetChangesInSequenceRangeMatchingPl3VersionArgs getChangesInSequenceRangeMatchingPl3VersionArgs = 7;
-  optional GetSnapshotAtRevisionArgs getSnapshotAtRevisionArgs = 8;
-}
-message Playlist4ServiceReturn {
-  optional Playlist4ServiceMethodKind kind = 1;
-  optional Playlist4ServiceException exception = 2;
-  optional bytes getCurrentRevisionReturn = 3;
-  optional GetChangesInSequenceRangeReturn getChangesInSequenceRangeReturn = 4;
-  optional bool obliterateListReturn = 5;
-  optional SynchronizeReturn synchronizeReturn = 6;
-  optional bool updatePublishedReturn = 7;
-  optional GetChangesInSequenceRangeReturn getChangesInSequenceRangeMatchingPl3VersionReturn = 8;
-  //optional RevisionTaggedListSnapshot getSnapshotAtRevisionReturn = 9;
-  optional bytes getSnapshotAtRevisionReturn = 9;
-}
-message CreateListReply {
-  required bytes uri = 1;
-  optional bytes revision = 2;
-}
-message ModifyReply {
-  required bytes uri = 1;
-  optional bytes revision = 2;
-}
-message PlaylistModificationInfo {
-  optional bytes uri = 1;
-  optional bytes new_revision = 2;
-}

+ 11 - 0
protocol/proto/popcount.proto

@@ -0,0 +1,11 @@
+message PopcountRequest {
+}
+
+message PopcountResult {
+    optional sint64 count = 0x1;
+    optional bool truncated = 0x2;
+    repeated string user = 0x3;
+    repeated sint64 subscriptionTimestamps = 0x4;
+    repeated sint64 insertionTimestamps = 0x5;
+}
+

+ 92 - 0
protocol/proto/presence.proto

@@ -0,0 +1,92 @@
+message PlaylistPublishedState {
+    optional string uri = 0x1;
+    optional int64 timestamp = 0x2;
+}
+
+message PlaylistTrackAddedState {
+    optional string playlist_uri = 0x1;
+    optional string track_uri = 0x2;
+    optional int64 timestamp = 0x3;
+}
+
+message TrackFinishedPlayingState {
+    optional string uri = 0x1;
+    optional string context_uri = 0x2;
+    optional int64 timestamp = 0x3;
+    optional string referrer_uri = 0x4;
+}
+
+message FavoriteAppAddedState {
+    optional string app_uri = 0x1;
+    optional int64 timestamp = 0x2;
+}
+
+message TrackStartedPlayingState {
+    optional string uri = 0x1;
+    optional string context_uri = 0x2;
+    optional int64 timestamp = 0x3;
+    optional string referrer_uri = 0x4;
+}
+
+message UriSharedState {
+    optional string uri = 0x1;
+    optional string message = 0x2;
+    optional int64 timestamp = 0x3;
+}
+
+message ArtistFollowedState {
+    optional string uri = 0x1;
+    optional string artist_name = 0x2;
+    optional string artist_cover_uri = 0x3;
+    optional int64 timestamp = 0x4;
+}
+
+message DeviceInformation {
+    optional string os = 0x1;
+    optional string type = 0x2;
+}
+
+message GenericPresenceState {
+    optional int32 type = 0x1;
+    optional int64 timestamp = 0x2;
+    optional string item_uri = 0x3;
+    optional string item_name = 0x4;
+    optional string item_image = 0x5;
+    optional string context_uri = 0x6;
+    optional string context_name = 0x7;
+    optional string context_image = 0x8;
+    optional string referrer_uri = 0x9;
+    optional string referrer_name = 0xa;
+    optional string referrer_image = 0xb;
+    optional string message = 0xc;
+    optional DeviceInformation device_information = 0xd;
+}
+
+message State {
+    optional int64 timestamp = 0x1;
+    optional Type type = 0x2;
+    enum Type {
+        PLAYLIST_PUBLISHED = 0x1;
+        PLAYLIST_TRACK_ADDED = 0x2;
+        TRACK_FINISHED_PLAYING = 0x3;
+        FAVORITE_APP_ADDED = 0x4;
+        TRACK_STARTED_PLAYING = 0x5;
+        URI_SHARED = 0x6;
+        ARTIST_FOLLOWED = 0x7;
+        GENERIC = 0xb;
+    }
+    optional string uri = 0x3;
+    optional PlaylistPublishedState playlist_published = 0x4;
+    optional PlaylistTrackAddedState playlist_track_added = 0x5;
+    optional TrackFinishedPlayingState track_finished_playing = 0x6;
+    optional FavoriteAppAddedState favorite_app_added = 0x7;
+    optional TrackStartedPlayingState track_started_playing = 0x8;
+    optional UriSharedState uri_shared = 0x9;
+    optional ArtistFollowedState artist_followed = 0xa;
+    optional GenericPresenceState generic = 0xb;
+}
+
+message StateList {
+    repeated State states = 0x1;
+}
+

+ 6 - 0
protocol/proto/pubsub.proto

@@ -0,0 +1,6 @@
+message Subscription {
+    optional string uri = 0x1;
+    optional int32 expiry = 0x2;
+    optional int32 status_code = 0x3;
+}
+

+ 56 - 0
protocol/proto/radio.proto

@@ -0,0 +1,56 @@
+message RadioRequest {
+    repeated string uris = 0x1;
+    optional int32 salt = 0x2;
+    optional int32 length = 0x4;
+    optional string stationId = 0x5;
+    repeated string lastTracks = 0x6;
+}
+
+message MultiSeedRequest {
+    repeated string uris = 0x1;
+}
+
+message Feedback {
+    optional string uri = 0x1;
+    optional string type = 0x2;
+    optional double timestamp = 0x3;
+}
+
+message Tracks {
+    repeated string gids = 0x1;
+    optional string source = 0x2;
+    optional string identity = 0x3;
+    repeated string tokens = 0x4;
+    repeated Feedback feedback = 0x5;
+}
+
+message Station {
+    optional string id = 0x1;
+    optional string title = 0x2;
+    optional string titleUri = 0x3;
+    optional string subtitle = 0x4;
+    optional string subtitleUri = 0x5;
+    optional string imageUri = 0x6;
+    optional double lastListen = 0x7;
+    repeated string seeds = 0x8;
+    optional int32 thumbsUp = 0x9;
+    optional int32 thumbsDown = 0xa;
+}
+
+message Rules {
+    optional string js = 0x1;
+}
+
+message StationResponse {
+    optional Station station = 0x1;
+    repeated Feedback feedback = 0x2;
+}
+
+message StationList {
+    repeated Station stations = 0x1;
+}
+
+message LikedPlaylist {
+    optional string uri = 0x1;
+}
+

+ 42 - 0
protocol/proto/search.proto

@@ -0,0 +1,42 @@
+message SearchRequest {
+    optional string query = 0x1;
+    optional Type type = 0x2;
+    enum Type {
+        TRACK = 0x0;
+        ALBUM = 0x1;
+        ARTIST = 0x2;
+        PLAYLIST = 0x3;
+        USER = 0x4;
+    }
+    optional int32 limit = 0x3;
+    optional int32 offset = 0x4;
+    optional bool did_you_mean = 0x5;
+    optional string spotify_uri = 0x2;
+    repeated bytes file_id = 0x3;
+    optional string url = 0x4;
+    optional string slask_id = 0x5;
+}
+
+message Playlist {
+    optional string uri = 0x1;
+    optional string name = 0x2;
+    repeated Image image = 0x3;
+}
+
+message User {
+    optional string username = 0x1;
+    optional string full_name = 0x2;
+    repeated Image image = 0x3;
+    optional sint32 followers = 0x4;
+}
+
+message SearchReply {
+    optional sint32 hits = 0x1;
+    repeated Track track = 0x2;
+    repeated Album album = 0x3;
+    repeated Artist artist = 0x4;
+    repeated Playlist playlist = 0x5;
+    optional string did_you_mean = 0x6;
+    repeated User user = 0x7;
+}
+

+ 10 - 0
protocol/proto/social.proto

@@ -0,0 +1,10 @@
+message DecorationData {
+    optional string username = 0x1;
+    optional string full_name = 0x2;
+    optional string image_url = 0x3;
+    optional string large_image_url = 0x5;
+    optional string first_name = 0x6;
+    optional string last_name = 0x7;
+    optional string facebook_uid = 0x8;
+}
+

+ 47 - 0
protocol/proto/socialgraph.proto

@@ -0,0 +1,47 @@
+message CountReply {
+    repeated int32 counts = 0x1;
+}
+
+message UserListRequest {
+    optional string last_result = 0x1;
+    optional int32 count = 0x2;
+    optional bool include_length = 0x3;
+}
+
+message UserListReply {
+    repeated User users = 0x1;
+    optional int32 length = 0x2;
+}
+
+message User {
+    optional string username = 0x1;
+    optional int32 subscriber_count = 0x2;
+    optional int32 subscription_count = 0x3;
+}
+
+message ArtistListReply {
+    repeated Artist artists = 0x1;
+}
+
+message Artist {
+    optional string artistid = 0x1;
+    optional int32 subscriber_count = 0x2;
+}
+
+message StringListRequest {
+    repeated string args = 0x1;
+}
+
+message StringListReply {
+    repeated string reply = 0x1;
+}
+
+message TopPlaylistsRequest {
+    optional string username = 0x1;
+    optional int32 count = 0x2;
+}
+
+message TopPlaylistsReply {
+    repeated string uris = 0x1;
+}
+

+ 102 - 76
protocol/proto/spirc.proto

@@ -1,92 +1,118 @@
+message Frame {
+    optional uint32 version = 0x1;
+    optional string ident = 0x2;
+    optional string protocol_version = 0x3;
+    optional uint32 seq_nr = 0x4;
+    optional MessageType typ = 0x5;
+    optional DeviceState device_state = 0x7;
+    optional Goodbye goodbye = 0xb;
+    optional State state = 0xc;
+    optional uint32 position = 0xd;
+    optional uint32 volume = 0xe;
+    optional int64 state_update_id = 0x11;
+    repeated string recipient = 0x12;
+    optional bytes context_player_state = 0x13;
+}
+
 enum MessageType {
-    kMessageTypeHello = 1;
-    kMessageTypeGoodbye = 2;
-    kMessageTypeNotify = 10;
-    kMessageTypeLoad = 20;
-    kMessageTypePlay = 21;
-    kMessageTypePause = 22;
-//    kMessageTypePlayPause = 23;
-    kMessageTypeSeek = 24;
-    kMessageTypePrev = 25;
-    kMessageTypeNext = 26;
-    kMessageTypeVolume = 27;
-    kMessageTypeShuffle = 28;
-    kMessageTypeRepeat = 29;
-    kMessageTypeQueue = 30;
-    kMessageTypeVolumeDown = 31;
-    kMessageTypeVolumeUp = 32;
-    kMessageTypeAddToQueue = 33;
+    kMessageTypeHello = 0x1;
+    kMessageTypeGoodbye = 0x2;
+    kMessageTypeProbe = 0x3;
+    kMessageTypeNotify = 0xa;
+    kMessageTypeLoad = 0x14;
+    kMessageTypePlay = 0x15;
+    kMessageTypePause = 0x16;
+    kMessageTypePlayPause = 0x17;
+    kMessageTypeSeek = 0x18;
+    kMessageTypePrev = 0x19;
+    kMessageTypeNext = 0x1a;
+    kMessageTypeVolume = 0x1b;
+    kMessageTypeShuffle = 0x1c;
+    kMessageTypeRepeat = 0x1d;
+    kMessageTypeVolumeDown = 0x1f;
+    kMessageTypeVolumeUp = 0x20;
+    kMessageTypeReplace = 0x21;
+    kMessageTypeLogout = 0x22;
+    kMessageTypeAction = 0x23;
 }
-enum PlayStatus {
-    kPlayStatusStop = 0;
-    kPlayStatusPlay = 1;
-    kPlayStatusPause = 2;
-    kPlayStatusLoading = 3;
-    kPlayStatusError = 4;
+
+message DeviceState {
+    optional string sw_version = 0x1;
+    optional bool is_active = 0xa;
+    optional bool can_play = 0xb;
+    optional uint32 volume = 0xc;
+    optional string name = 0xd;
+    optional uint32 error_code = 0xe;
+    optional int64 became_active_at = 0xf;
+    optional string error_message = 0x10;
+    repeated Capability capabilities = 0x11;
+    repeated string local_uris = 0x12;
+    repeated int32 enc_key = 0x13;
+}
+
+message Capability {
+    optional CapabilityType typ = 0x1;
+    repeated int64 intValue = 0x2;
+    repeated string stringValue = 0x3;
 }
+
+enum CapabilityType {
+    kSupportedContexts = 0x1;
+    kCanBePlayer = 0x2;
+    kRestrictToLocal = 0x3;
+    kDeviceType = 0x4;
+    kGaiaEqConnectId = 0x5;
+    kSupportsLogout = 0x6;
+    kIsObservable = 0x7;
+    kVolumeSteps = 0x8;
+    kSupportedTypes = 0x9;
+}
+
 message Goodbye {
-    required string reason = 1;
+    optional string reason = 0x1;
 }
+
 message State {
-    optional string contextURI = 0x2;
+    optional string context_uri = 0x2;
     optional uint32 index = 0x3;
-    optional uint32 position = 0x4;
+    optional uint32 position_ms = 0x4;
     optional PlayStatus status = 0x5;
-
-    optional uint64 timestamp = 0x7;
-    optional string context_name = 0x8;
-    optional uint32 duration = 0x9;
-    optional uint32 data9 = 0xa;
-    repeated uint64 data10 = 0xb;
+    optional uint64 position_measured_at = 0x7;
+    optional string context_description = 0x8;
     optional bool shuffle = 0xd;
     optional bool repeat = 0xe;
-
-    optional string data12 = 0x14;
-    optional uint32 data13 = 0x15;
-    optional uint32 data14 = 0x18;
-    optional uint32 data15 = 0x19;
-    optional uint32 data16 = 0x1a;
-    repeated QueuedTrack queued = 0x1b;
-    message QueuedTrack {
-        optional bytes  gid = 0x1;
-        optional string local_uri = 0x2;
-        optional uint32 data1 = 0x3;
-    }
+    optional string last_command_ident = 0x14;
+    optional uint32 last_command_msgid = 0x15;
+    optional bool playing_from_fallback = 0x18;
+    optional uint32 row = 0x19;
+    optional uint32 playing_track_index = 0x1a;
+    repeated TrackRef track = 0x1b;
+    optional Ad ad = 0x1c;
 }
 
-message Frame {
-    required uint32 version = 1;
-    required string source = 2;
-    required string version_string = 3;
-    required uint32 msgid = 4;
-    required uint32 type = 5;
-
-    required DeviceInfo device = 0x7;
-
-    //required Goodbye goodbye = 0xb;
-    optional State state = 0xc;
-
-    optional uint32 position = 0xd;
-    optional uint32 volume = 0xe;
-
-    optional uint64 timestamp = 0x11;
-    optional string destination = 0x12;
+enum PlayStatus {
+    kPlayStatusStop = 0x0;
+    kPlayStatusPlay = 0x1;
+    kPlayStatusPause = 0x2;
+    kPlayStatusLoading = 0x3;
+}
 
-    message DeviceInfo {
-        optional string version    = 0x1;
-        required bool   active     = 0xa;
-        required bool   foreground = 0xb;
-        required uint32 volume     = 0xc;
-        required string name       = 0xd;
-        optional uint32 data15     = 0xe;
-        required uint64 activeTime = 0xf;
-        repeated Data17 data17     = 0x11;
+message TrackRef {
+    optional bytes gid = 0x1;
+    optional string uri = 0x2;
+    optional bool queued = 0x3;
+    optional string context = 0x4;
+}
 
-        message Data17 {
-            required uint32 data0 = 0x1;
-            optional uint32 data1 = 0x2;
-            repeated string data2 = 0x3;
-        }
-    }
+message Ad {
+    optional int32 next = 0x1;
+    optional bytes ogg_fid = 0x2;
+    optional bytes image_fid = 0x3;
+    optional int32 duration = 0x4;
+    optional string click_url = 0x5;
+    optional string impression_url = 0x6;
+    optional string product = 0x7;
+    optional string advertiser = 0x8;
+    optional bytes gid = 0x9;
 }
 

+ 0 - 0
protocol/proto/spotify.proto


+ 41 - 0
protocol/proto/suggest.proto

@@ -0,0 +1,41 @@
+message Track {
+    optional bytes gid = 0x1;
+    optional string name = 0x2;
+    optional bytes image = 0x3;
+    repeated string artist_name = 0x4;
+    repeated bytes artist_gid = 0x5;
+    optional uint32 rank = 0x6;
+}
+
+message Artist {
+    optional bytes gid = 0x1;
+    optional string name = 0x2;
+    optional bytes image = 0x3;
+    optional uint32 rank = 0x6;
+}
+
+message Album {
+    optional bytes gid = 0x1;
+    optional string name = 0x2;
+    optional bytes image = 0x3;
+    repeated string artist_name = 0x4;
+    repeated bytes artist_gid = 0x5;
+    optional uint32 rank = 0x6;
+}
+
+message Playlist {
+    optional string uri = 0x1;
+    optional string name = 0x2;
+    optional string image_uri = 0x3;
+    optional string owner_name = 0x4;
+    optional string owner_uri = 0x5;
+    optional uint32 rank = 0x6;
+}
+
+message Suggestions {
+    repeated Track track = 0x1;
+    repeated Album album = 0x2;
+    repeated Artist artist = 0x3;
+    repeated Playlist playlist = 0x4;
+}
+

+ 4 - 0
protocol/proto/toplist.proto

@@ -0,0 +1,4 @@
+message Toplist {
+    repeated string items = 0x1;
+}
+

+ 1 - 7
protocol/src/lib.rs

@@ -7,11 +7,5 @@ mod_path! keyexchange (concat!(env!("OUT_DIR"), "/keyexchange.rs"));
 mod_path! authentication (concat!(env!("OUT_DIR"), "/authentication.rs"));
 mod_path! mercury (concat!(env!("OUT_DIR"), "/mercury.rs"));
 mod_path! metadata (concat!(env!("OUT_DIR"), "/metadata.rs"));
-
-mod_path! playlist4changes (concat!(env!("OUT_DIR"), "/playlist4changes.rs"));
-mod_path! playlist4content (concat!(env!("OUT_DIR"), "/playlist4content.rs"));
-mod_path! playlist4issues (concat!(env!("OUT_DIR"), "/playlist4issues.rs"));
-mod_path! playlist4meta (concat!(env!("OUT_DIR"), "/playlist4meta.rs"));
-mod_path! playlist4ops (concat!(env!("OUT_DIR"), "/playlist4ops.rs"));
-mod_path! playlist4service (concat!(env!("OUT_DIR"), "/playlist4service.rs"));
+mod_path! spirc (concat!(env!("OUT_DIR"), "/spirc.rs"));
 

+ 11 - 7
src/main.rs

@@ -1,6 +1,6 @@
 #![crate_name = "librespot"]
 
-#![feature(alloc,plugin,core,collections,std_misc,zero_one)]
+#![feature(plugin,zero_one,iter_arith,slice_position_elem,slice_bytes,bitset,mpsc_select,arc_weak,append)]
 
 #![plugin(protobuf_macros)]
 #[macro_use] extern crate lazy_static;
@@ -62,6 +62,16 @@ fn main() {
     session.poll();
 
     let mut cache = MetadataCache::new(session.metadata.clone());
+
+
+    print_track(&mut cache, track_id);
+
+    loop {
+        session.poll();
+    }
+}
+
+fn print_track(cache: &mut MetadataCache, track_id: SpotifyId) {
     let track : TrackRef = cache.get(track_id);
 
     let album : AlbumRef = {
@@ -85,11 +95,5 @@ fn main() {
         let data = handle.unwrap();
         eprintln!("{}", data.name);
     }
-    
-    Player::play(&session, track);
-
-    loop {
-        session.poll();
-    }
 }
 

+ 50 - 41
src/mercury.rs

@@ -12,23 +12,23 @@ use librespot_protocol as protocol;
 use subsystem::Subsystem;
 use util::Either::{Left, Right};
 
+#[derive(Debug, PartialEq, Eq)]
 pub enum MercuryMethod {
     GET,
-    GETX,
     SUB,
     UNSUB,
 }
 
 pub struct MercuryRequest {
     pub method: MercuryMethod,
-    pub url: String,
-    pub mime: Option<String>,
+    pub uri: String,
+    pub content_type: Option<String>,
     pub callback: MercuryCallback
 }
 
 #[derive(Debug)]
 pub struct MercuryResponse {
-    pub url: String,
+    pub uri: String,
     pub payload: LinkedList<Vec<u8>>
 }
 
@@ -53,7 +53,6 @@ impl fmt::Display for MercuryMethod {
     fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
         formatter.write_str(match *self {
             MercuryMethod::GET => "GET",
-            MercuryMethod::GETX => "GETX",
             MercuryMethod::SUB => "SUB",
             MercuryMethod::UNSUB => "UNSUB"
         })
@@ -83,8 +82,14 @@ impl MercuryManager {
         self.next_seq += 1;
         let data = self.encode_request(&seq, &req);
 
+        let cmd = match req.method {
+            MercuryMethod::SUB => 0xb3,
+            MercuryMethod::UNSUB => 0xb4,
+            _ => 0xb2,
+        };
+
         self.packet_tx.send(Packet {
-            cmd: 0xb2,
+            cmd: cmd,
             data: data
         }).unwrap();
 
@@ -103,29 +108,24 @@ impl MercuryManager {
         buffer
     }
 
-    fn complete_request(&mut self, seq: &[u8]) {
-        let mut pending = self.pending.remove(seq).unwrap();
-
+    fn complete_request(&mut self, cmd: u8, mut pending: MercuryPending) {
         let header_data = match pending.parts.pop_front() {
             Some(data) => data,
             None => panic!("No header part !")
         };
 
-        let header : protocol::mercury::MercuryReply =
+        let header : protocol::mercury::Header =
             protobuf::parse_from_bytes(&header_data).unwrap();
 
-        match pending.callback {
-            Some(ch) => {
-                ch.send(MercuryResponse{
-                    url: header.get_url().to_string(),
-                    payload: pending.parts
-                }).unwrap();
-            }
-            None => (),
+        if let Some(ref ch) = pending.callback {
+            ch.send(MercuryResponse{
+                uri: header.get_uri().to_string(),
+                payload: pending.parts
+            }).unwrap();
         }
     }
 
-    fn handle_packet(&mut self, _cmd: u8, data: Vec<u8>) {
+    fn handle_packet(&mut self, cmd: u8, data: Vec<u8>) {
         let mut packet = Cursor::new(data);
 
         let seq = {
@@ -137,30 +137,37 @@ impl MercuryManager {
         let flags = packet.read_u8().unwrap();
         let count = packet.read_u16::<BigEndian>().unwrap() as usize;
 
-        {
-            let pending : &mut MercuryPending = match self.pending.get_mut(&seq) {
-                Some(pending) => pending,
-                None => { return; }
-            };
-
-            for i in 0..count {
-                let mut part = Self::parse_part(&mut packet);
-                if pending.partial.is_some() {
-                    let mut data = replace(&mut pending.partial, None).unwrap();
-                    data.append(&mut part);
-                    part = data;
-                }
+        let mut pending = if let Some(pending) = self.pending.remove(&seq) {
+            pending
+        } else if cmd == 0xb5 {
+            MercuryPending {
+                parts: LinkedList::new(),
+                partial: None,
+                callback: None,
+            }
+        } else {
+            println!("Ignore seq {:?} cmd {}", seq, cmd);
+            return
+        };
 
-                if i == count -1 && (flags == 2) {
-                    pending.partial = Some(part)
-                } else {
-                    pending.parts.push_back(part);
-                }
+        for i in 0..count {
+            let mut part = Self::parse_part(&mut packet);
+            if let Some(mut data) = replace(&mut pending.partial, None) {
+                data.append(&mut part);
+                part = data;
+            }
+
+            if i == count - 1 && (flags == 2) {
+                pending.partial = Some(part)
+            } else {
+                pending.parts.push_back(part);
             }
         }
 
         if flags == 0x1 {
-            self.complete_request(&seq);
+            self.complete_request(cmd, pending);
+        } else {
+            self.pending.insert(seq, pending);
         }
     }
 
@@ -171,11 +178,13 @@ impl MercuryManager {
         packet.write_u8(1).unwrap(); // Flags: FINAL
         packet.write_u16::<BigEndian>(1).unwrap(); // Part count. Only header
 
-        let mut header = protobuf_init!(protocol::mercury::MercuryRequest::new(), {
-            url: req.url.clone(),
+        let mut header = protobuf_init!(protocol::mercury::Header::new(), {
+            uri: req.uri.clone(),
             method: req.method.to_string(),
         });
-        req.mime.clone().map(|mime| header.set_mime(mime));
+        if let Some(ref content_type) = req.content_type {
+            header.set_content_type(content_type.clone());
+        }
 
         packet.write_u16::<BigEndian>(header.compute_size() as u16).unwrap();
         header.write_to_writer(&mut packet).unwrap();

+ 3 - 3
src/metadata.rs

@@ -34,7 +34,7 @@ impl MetadataTrait for Track {
             files: msg.get_file().iter()
                 .map(|file| {
                     let mut dst = [0u8; 20];
-                    copy_memory(&file.get_gid(), &mut dst);
+                    copy_memory(&file.get_file_id(), &mut dst);
                     dst
                 })
                 .collect(),
@@ -235,8 +235,8 @@ impl MetadataManager {
             
             mercury.send(MercuryRequest {
                 method: MercuryMethod::GET,
-                url: format!("{}/{}", T::base_url(), object.id.to_base16()),
-                mime: None,
+                uri: format!("{}/{}", T::base_url(), object.id.to_base16()),
+                content_type: None,
                 callback: Some(tx)
             }).unwrap();