+378
Cargo.lock
+378
Cargo.lock
···
219
219
]
220
220
221
221
[[package]]
222
+
name = "async-stream"
223
+
version = "0.3.4"
224
+
source = "registry+https://github.com/rust-lang/crates.io-index"
225
+
checksum = "ad445822218ce64be7a341abfb0b1ea43b5c23aa83902542a4542e78309d8e5e"
226
+
dependencies = [
227
+
"async-stream-impl",
228
+
"futures-core",
229
+
"pin-project-lite",
230
+
]
231
+
232
+
[[package]]
233
+
name = "async-stream-impl"
234
+
version = "0.3.4"
235
+
source = "registry+https://github.com/rust-lang/crates.io-index"
236
+
checksum = "e4655ae1a7b0cdf149156f780c5bf3f1352bc53cbd9e0a361a7ef7b22947e965"
237
+
dependencies = [
238
+
"proc-macro2",
239
+
"quote",
240
+
"syn",
241
+
]
242
+
243
+
[[package]]
222
244
name = "async-task"
223
245
version = "4.3.0"
224
246
source = "registry+https://github.com/rust-lang/crates.io-index"
···
272
294
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
273
295
274
296
[[package]]
297
+
name = "axum"
298
+
version = "0.6.8"
299
+
source = "registry+https://github.com/rust-lang/crates.io-index"
300
+
checksum = "2bd379e511536bad07447f899300aa526e9bae8e6f66dc5e5ca45d7587b7c1ec"
301
+
dependencies = [
302
+
"async-trait",
303
+
"axum-core",
304
+
"bitflags",
305
+
"bytes",
306
+
"futures-util",
307
+
"http",
308
+
"http-body",
309
+
"hyper",
310
+
"itoa",
311
+
"matchit",
312
+
"memchr",
313
+
"mime",
314
+
"percent-encoding 2.2.0",
315
+
"pin-project-lite",
316
+
"rustversion",
317
+
"serde",
318
+
"sync_wrapper",
319
+
"tower",
320
+
"tower-http",
321
+
"tower-layer",
322
+
"tower-service",
323
+
]
324
+
325
+
[[package]]
326
+
name = "axum-core"
327
+
version = "0.3.2"
328
+
source = "registry+https://github.com/rust-lang/crates.io-index"
329
+
checksum = "1cae3e661676ffbacb30f1a824089a8c9150e71017f7e1e38f2aa32009188d34"
330
+
dependencies = [
331
+
"async-trait",
332
+
"bytes",
333
+
"futures-util",
334
+
"http",
335
+
"http-body",
336
+
"mime",
337
+
"rustversion",
338
+
"tower-layer",
339
+
"tower-service",
340
+
]
341
+
342
+
[[package]]
275
343
name = "base-x"
276
344
version = "0.2.11"
277
345
source = "registry+https://github.com/rust-lang/crates.io-index"
···
672
740
checksum = "212d0f5754cb6769937f4501cc0e67f4f4483c8d2c3e1e922ee9edbe4ab4c7c0"
673
741
674
742
[[package]]
743
+
name = "either"
744
+
version = "1.8.1"
745
+
source = "registry+https://github.com/rust-lang/crates.io-index"
746
+
checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91"
747
+
748
+
[[package]]
675
749
name = "encoding_rs"
676
750
version = "0.8.32"
677
751
source = "registry+https://github.com/rust-lang/crates.io-index"
···
694
768
dependencies = [
695
769
"instant",
696
770
]
771
+
772
+
[[package]]
773
+
name = "fixedbitset"
774
+
version = "0.4.2"
775
+
source = "registry+https://github.com/rust-lang/crates.io-index"
776
+
checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80"
697
777
698
778
[[package]]
699
779
name = "fnv"
···
915
995
checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
916
996
917
997
[[package]]
998
+
name = "heck"
999
+
version = "0.4.1"
1000
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1001
+
checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
1002
+
1003
+
[[package]]
918
1004
name = "hermit-abi"
919
1005
version = "0.1.19"
920
1006
source = "registry+https://github.com/rust-lang/crates.io-index"
···
1000
1086
]
1001
1087
1002
1088
[[package]]
1089
+
name = "http-range-header"
1090
+
version = "0.3.0"
1091
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1092
+
checksum = "0bfe8eed0a9285ef776bb792479ea3834e8b94e13d615c2f66d03dd50a435a29"
1093
+
1094
+
[[package]]
1003
1095
name = "http-types"
1004
1096
version = "2.12.0"
1005
1097
source = "registry+https://github.com/rust-lang/crates.io-index"
···
1058
1150
]
1059
1151
1060
1152
[[package]]
1153
+
name = "hyper-timeout"
1154
+
version = "0.4.1"
1155
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1156
+
checksum = "bbb958482e8c7be4bc3cf272a766a2b0bf1a6755e7a6ae777f017a31d11b13b1"
1157
+
dependencies = [
1158
+
"hyper",
1159
+
"pin-project-lite",
1160
+
"tokio",
1161
+
"tokio-io-timeout",
1162
+
]
1163
+
1164
+
[[package]]
1061
1165
name = "hyper-tls"
1062
1166
version = "0.5.0"
1063
1167
source = "registry+https://github.com/rust-lang/crates.io-index"
···
1121
1225
version = "2.7.1"
1122
1226
source = "registry+https://github.com/rust-lang/crates.io-index"
1123
1227
checksum = "30e22bd8629359895450b59ea7a776c850561b96a3b1d31321c1949d9e6c9146"
1228
+
1229
+
[[package]]
1230
+
name = "itertools"
1231
+
version = "0.10.5"
1232
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1233
+
checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473"
1234
+
dependencies = [
1235
+
"either",
1236
+
]
1124
1237
1125
1238
[[package]]
1126
1239
name = "itoa"
···
1270
1383
version = "0.1.10"
1271
1384
source = "registry+https://github.com/rust-lang/crates.io-index"
1272
1385
checksum = "2532096657941c2fea9c289d370a250971c689d4f143798ff67113ec042024a5"
1386
+
1387
+
[[package]]
1388
+
name = "matchit"
1389
+
version = "0.7.0"
1390
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1391
+
checksum = "b87248edafb776e59e6ee64a79086f65890d3510f2c656c000bf2a7e8a0aea40"
1273
1392
1274
1393
[[package]]
1275
1394
name = "memchr"
···
1341
1460
]
1342
1461
1343
1462
[[package]]
1463
+
name = "multimap"
1464
+
version = "0.8.3"
1465
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1466
+
checksum = "e5ce46fe64a9d73be07dcbe690a38ce1b293be448fd8ce1e6c1b8062c9f72c6a"
1467
+
1468
+
[[package]]
1344
1469
name = "native-tls"
1345
1470
version = "0.2.11"
1346
1471
source = "registry+https://github.com/rust-lang/crates.io-index"
···
1652
1777
checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e"
1653
1778
1654
1779
[[package]]
1780
+
name = "petgraph"
1781
+
version = "0.6.3"
1782
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1783
+
checksum = "4dd7d28ee937e54fe3080c91faa1c3a46c06de6252988a7f4592ba2310ef22a4"
1784
+
dependencies = [
1785
+
"fixedbitset",
1786
+
"indexmap",
1787
+
]
1788
+
1789
+
[[package]]
1655
1790
name = "pin-project"
1656
1791
version = "1.0.12"
1657
1792
source = "registry+https://github.com/rust-lang/crates.io-index"
···
1730
1865
checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
1731
1866
1732
1867
[[package]]
1868
+
name = "prettyplease"
1869
+
version = "0.1.23"
1870
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1871
+
checksum = "e97e3215779627f01ee256d2fad52f3d95e8e1c11e9fc6fd08f7cd455d5d5c78"
1872
+
dependencies = [
1873
+
"proc-macro2",
1874
+
"syn",
1875
+
]
1876
+
1877
+
[[package]]
1733
1878
name = "proc-macro-crate"
1734
1879
version = "1.3.0"
1735
1880
source = "registry+https://github.com/rust-lang/crates.io-index"
···
1755
1900
]
1756
1901
1757
1902
[[package]]
1903
+
name = "prost"
1904
+
version = "0.11.8"
1905
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1906
+
checksum = "e48e50df39172a3e7eb17e14642445da64996989bc212b583015435d39a58537"
1907
+
dependencies = [
1908
+
"bytes",
1909
+
"prost-derive",
1910
+
]
1911
+
1912
+
[[package]]
1913
+
name = "prost-build"
1914
+
version = "0.11.8"
1915
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1916
+
checksum = "2c828f93f5ca4826f97fedcbd3f9a536c16b12cff3dbbb4a007f932bbad95b12"
1917
+
dependencies = [
1918
+
"bytes",
1919
+
"heck",
1920
+
"itertools",
1921
+
"lazy_static",
1922
+
"log",
1923
+
"multimap",
1924
+
"petgraph",
1925
+
"prettyplease",
1926
+
"prost",
1927
+
"prost-types",
1928
+
"regex",
1929
+
"syn",
1930
+
"tempfile",
1931
+
"which",
1932
+
]
1933
+
1934
+
[[package]]
1935
+
name = "prost-derive"
1936
+
version = "0.11.8"
1937
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1938
+
checksum = "4ea9b0f8cbe5e15a8a042d030bd96668db28ecb567ec37d691971ff5731d2b1b"
1939
+
dependencies = [
1940
+
"anyhow",
1941
+
"itertools",
1942
+
"proc-macro2",
1943
+
"quote",
1944
+
"syn",
1945
+
]
1946
+
1947
+
[[package]]
1948
+
name = "prost-types"
1949
+
version = "0.11.8"
1950
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1951
+
checksum = "379119666929a1afd7a043aa6cf96fa67a6dce9af60c88095a4686dbce4c9c88"
1952
+
dependencies = [
1953
+
"prost",
1954
+
]
1955
+
1956
+
[[package]]
1758
1957
name = "quote"
1759
1958
version = "1.0.23"
1760
1959
source = "registry+https://github.com/rust-lang/crates.io-index"
···
1974
2173
"sct",
1975
2174
"webpki",
1976
2175
]
2176
+
2177
+
[[package]]
2178
+
name = "rustversion"
2179
+
version = "1.0.11"
2180
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2181
+
checksum = "5583e89e108996506031660fe09baa5011b9dd0341b89029313006d1fb508d70"
1977
2182
1978
2183
[[package]]
1979
2184
name = "ryu"
···
2485
2690
]
2486
2691
2487
2692
[[package]]
2693
+
name = "sync_wrapper"
2694
+
version = "0.1.2"
2695
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2696
+
checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160"
2697
+
2698
+
[[package]]
2488
2699
name = "tempfile"
2489
2700
version = "3.3.0"
2490
2701
source = "registry+https://github.com/rust-lang/crates.io-index"
···
2605
2816
]
2606
2817
2607
2818
[[package]]
2819
+
name = "tokio-io-timeout"
2820
+
version = "1.2.0"
2821
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2822
+
checksum = "30b74022ada614a1b4834de765f9bb43877f910cc8ce4be40e89042c9223a8bf"
2823
+
dependencies = [
2824
+
"pin-project-lite",
2825
+
"tokio",
2826
+
]
2827
+
2828
+
[[package]]
2608
2829
name = "tokio-macros"
2609
2830
version = "1.8.2"
2610
2831
source = "registry+https://github.com/rust-lang/crates.io-index"
···
2626
2847
]
2627
2848
2628
2849
[[package]]
2850
+
name = "tokio-stream"
2851
+
version = "0.1.12"
2852
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2853
+
checksum = "8fb52b74f05dbf495a8fba459fdc331812b96aa086d9eb78101fa0d4569c3313"
2854
+
dependencies = [
2855
+
"futures-core",
2856
+
"pin-project-lite",
2857
+
"tokio",
2858
+
]
2859
+
2860
+
[[package]]
2629
2861
name = "tokio-util"
2630
2862
version = "0.7.7"
2631
2863
source = "registry+https://github.com/rust-lang/crates.io-index"
···
2657
2889
]
2658
2890
2659
2891
[[package]]
2892
+
name = "tonic"
2893
+
version = "0.8.3"
2894
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2895
+
checksum = "8f219fad3b929bef19b1f86fbc0358d35daed8f2cac972037ac0dc10bbb8d5fb"
2896
+
dependencies = [
2897
+
"async-stream",
2898
+
"async-trait",
2899
+
"axum",
2900
+
"base64 0.13.1",
2901
+
"bytes",
2902
+
"futures-core",
2903
+
"futures-util",
2904
+
"h2",
2905
+
"http",
2906
+
"http-body",
2907
+
"hyper",
2908
+
"hyper-timeout",
2909
+
"percent-encoding 2.2.0",
2910
+
"pin-project",
2911
+
"prost",
2912
+
"prost-derive",
2913
+
"tokio",
2914
+
"tokio-stream",
2915
+
"tokio-util",
2916
+
"tower",
2917
+
"tower-layer",
2918
+
"tower-service",
2919
+
"tracing",
2920
+
"tracing-futures",
2921
+
]
2922
+
2923
+
[[package]]
2924
+
name = "tonic-build"
2925
+
version = "0.8.4"
2926
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2927
+
checksum = "5bf5e9b9c0f7e0a7c027dcfaba7b2c60816c7049171f679d99ee2ff65d0de8c4"
2928
+
dependencies = [
2929
+
"prettyplease",
2930
+
"proc-macro2",
2931
+
"prost-build",
2932
+
"quote",
2933
+
"syn",
2934
+
]
2935
+
2936
+
[[package]]
2937
+
name = "tonic-web"
2938
+
version = "0.4.0"
2939
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2940
+
checksum = "e392f7556972523aa87ddb0fc7f2d2ce530559956706aa081bb0bd8fed158559"
2941
+
dependencies = [
2942
+
"base64 0.13.1",
2943
+
"bytes",
2944
+
"futures-core",
2945
+
"http",
2946
+
"http-body",
2947
+
"hyper",
2948
+
"pin-project",
2949
+
"tonic",
2950
+
"tower-service",
2951
+
"tracing",
2952
+
]
2953
+
2954
+
[[package]]
2955
+
name = "tower"
2956
+
version = "0.4.13"
2957
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2958
+
checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c"
2959
+
dependencies = [
2960
+
"futures-core",
2961
+
"futures-util",
2962
+
"indexmap",
2963
+
"pin-project",
2964
+
"pin-project-lite",
2965
+
"rand 0.8.5",
2966
+
"slab",
2967
+
"tokio",
2968
+
"tokio-util",
2969
+
"tower-layer",
2970
+
"tower-service",
2971
+
"tracing",
2972
+
]
2973
+
2974
+
[[package]]
2975
+
name = "tower-http"
2976
+
version = "0.3.5"
2977
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2978
+
checksum = "f873044bf02dd1e8239e9c1293ea39dad76dc594ec16185d0a1bf31d8dc8d858"
2979
+
dependencies = [
2980
+
"bitflags",
2981
+
"bytes",
2982
+
"futures-core",
2983
+
"futures-util",
2984
+
"http",
2985
+
"http-body",
2986
+
"http-range-header",
2987
+
"pin-project-lite",
2988
+
"tower",
2989
+
"tower-layer",
2990
+
"tower-service",
2991
+
]
2992
+
2993
+
[[package]]
2994
+
name = "tower-layer"
2995
+
version = "0.3.2"
2996
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2997
+
checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0"
2998
+
2999
+
[[package]]
2660
3000
name = "tower-service"
2661
3001
version = "0.3.2"
2662
3002
source = "registry+https://github.com/rust-lang/crates.io-index"
···
2669
3009
checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8"
2670
3010
dependencies = [
2671
3011
"cfg-if",
3012
+
"log",
2672
3013
"pin-project-lite",
3014
+
"tracing-attributes",
2673
3015
"tracing-core",
2674
3016
]
2675
3017
2676
3018
[[package]]
3019
+
name = "tracing-attributes"
3020
+
version = "0.1.23"
3021
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3022
+
checksum = "4017f8f45139870ca7e672686113917c71c7a6e02d4924eda67186083c03081a"
3023
+
dependencies = [
3024
+
"proc-macro2",
3025
+
"quote",
3026
+
"syn",
3027
+
]
3028
+
3029
+
[[package]]
2677
3030
name = "tracing-core"
2678
3031
version = "0.1.30"
2679
3032
source = "registry+https://github.com/rust-lang/crates.io-index"
2680
3033
checksum = "24eb03ba0eab1fd845050058ce5e616558e8f8d8fca633e6b163fe25c797213a"
2681
3034
dependencies = [
2682
3035
"once_cell",
3036
+
]
3037
+
3038
+
[[package]]
3039
+
name = "tracing-futures"
3040
+
version = "0.2.5"
3041
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3042
+
checksum = "97d095ae15e245a057c8e8451bab9b3ee1e1f68e9ba2b4fbc18d0ac5237835f2"
3043
+
dependencies = [
3044
+
"pin-project",
3045
+
"tracing",
2683
3046
]
2684
3047
2685
3048
[[package]]
···
2716
3079
"minimp3",
2717
3080
"owo-colors",
2718
3081
"pls",
3082
+
"prost",
2719
3083
"reqwest",
2720
3084
"rodio",
2721
3085
"surf",
2722
3086
"symphonia",
2723
3087
"tokio",
3088
+
"tonic",
3089
+
"tonic-build",
3090
+
"tonic-web",
2724
3091
"tunein",
2725
3092
"url 2.3.1",
2726
3093
]
···
2963
3330
checksum = "d743fdedc5c64377b5fc2bc036b01c7fd642205a0d96356034ae3404d49eb7fb"
2964
3331
dependencies = [
2965
3332
"cc",
3333
+
]
3334
+
3335
+
[[package]]
3336
+
name = "which"
3337
+
version = "4.4.0"
3338
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3339
+
checksum = "2441c784c52b289a054b7201fc93253e288f094e2f4be9058343127c4226a269"
3340
+
dependencies = [
3341
+
"either",
3342
+
"libc",
3343
+
"once_cell",
2966
3344
]
2967
3345
2968
3346
[[package]]
+7
Cargo.toml
+7
Cargo.toml
+12
build.rs
+12
build.rs
···
1
+
fn main() -> Result<(), Box<dyn std::error::Error>> {
2
+
tonic_build::configure().out_dir("src/api").compile(
3
+
&[
4
+
"proto/objects/v1alpha1/category.proto",
5
+
"proto/objects/v1alpha1/station.proto",
6
+
"proto/tunein/v1alpha1/browse.proto",
7
+
"proto/tunein/v1alpha1/playback.proto",
8
+
],
9
+
&["proto"],
10
+
)?;
11
+
Ok(())
12
+
}
+7
proto/buf.lock
+7
proto/buf.lock
+3
proto/buf.md
+3
proto/buf.md
+10
proto/buf.yaml
+10
proto/buf.yaml
+7
proto/objects/v1alpha1/category.proto
+7
proto/objects/v1alpha1/category.proto
+7
proto/objects/v1alpha1/station.proto
+7
proto/objects/v1alpha1/station.proto
+25
proto/tunein/v1alpha1/browse.proto
+25
proto/tunein/v1alpha1/browse.proto
···
1
+
syntax = "proto3";
2
+
3
+
package tunein.v1alpha1;
4
+
5
+
message GetCategoriesRequest {}
6
+
7
+
message GetCategoriesResponse {}
8
+
9
+
message BrowseCategoryRequest {
10
+
string category_id = 1;
11
+
}
12
+
13
+
message BrowseCategoryResponse {}
14
+
15
+
message GetStationDetailsRequest {
16
+
string id = 1;
17
+
}
18
+
19
+
message GetStationDetailsResponse {}
20
+
21
+
service BrowseService {
22
+
rpc GetCategories(GetCategoriesRequest) returns (GetCategoriesResponse) {}
23
+
rpc BrowseCategory(BrowseCategoryRequest) returns (BrowseCategoryResponse) {}
24
+
rpc GetStationDetails(GetStationDetailsRequest) returns (GetStationDetailsResponse) {}
25
+
}
+23
proto/tunein/v1alpha1/playback.proto
+23
proto/tunein/v1alpha1/playback.proto
···
1
+
syntax = "proto3";
2
+
3
+
package tunein.v1alpha1;
4
+
5
+
message PlayOrPauseRequest {}
6
+
7
+
message PlayOrPauseResponse {}
8
+
9
+
message StopRequest {}
10
+
11
+
message StopResponse {}
12
+
13
+
message PlayRequest {
14
+
string station_name_or_id = 1;
15
+
}
16
+
17
+
message PlayResponse {}
18
+
19
+
service PlaybackService {
20
+
rpc Play(PlayRequest) returns (PlayResponse) {}
21
+
rpc Stop(StopRequest) returns (StopResponse) {}
22
+
rpc PlayOrPause(PlayOrPauseRequest) returns (PlayOrPauseResponse) {}
23
+
}
+6
src/api/objects.v1alpha1.rs
+6
src/api/objects.v1alpha1.rs
+771
src/api/tunein.v1alpha1.rs
+771
src/api/tunein.v1alpha1.rs
···
1
+
#[allow(clippy::derive_partial_eq_without_eq)]
2
+
#[derive(Clone, PartialEq, ::prost::Message)]
3
+
pub struct GetCategoriesRequest {}
4
+
#[allow(clippy::derive_partial_eq_without_eq)]
5
+
#[derive(Clone, PartialEq, ::prost::Message)]
6
+
pub struct GetCategoriesResponse {}
7
+
#[allow(clippy::derive_partial_eq_without_eq)]
8
+
#[derive(Clone, PartialEq, ::prost::Message)]
9
+
pub struct BrowseCategoryRequest {
10
+
#[prost(string, tag = "1")]
11
+
pub category_id: ::prost::alloc::string::String,
12
+
}
13
+
#[allow(clippy::derive_partial_eq_without_eq)]
14
+
#[derive(Clone, PartialEq, ::prost::Message)]
15
+
pub struct BrowseCategoryResponse {}
16
+
#[allow(clippy::derive_partial_eq_without_eq)]
17
+
#[derive(Clone, PartialEq, ::prost::Message)]
18
+
pub struct GetStationDetailsRequest {
19
+
#[prost(string, tag = "1")]
20
+
pub id: ::prost::alloc::string::String,
21
+
}
22
+
#[allow(clippy::derive_partial_eq_without_eq)]
23
+
#[derive(Clone, PartialEq, ::prost::Message)]
24
+
pub struct GetStationDetailsResponse {}
25
+
/// Generated client implementations.
26
+
pub mod browse_service_client {
27
+
#![allow(unused_variables, dead_code, missing_docs, clippy::let_unit_value)]
28
+
use tonic::codegen::*;
29
+
use tonic::codegen::http::Uri;
30
+
#[derive(Debug, Clone)]
31
+
pub struct BrowseServiceClient<T> {
32
+
inner: tonic::client::Grpc<T>,
33
+
}
34
+
impl BrowseServiceClient<tonic::transport::Channel> {
35
+
/// Attempt to create a new client by connecting to a given endpoint.
36
+
pub async fn connect<D>(dst: D) -> Result<Self, tonic::transport::Error>
37
+
where
38
+
D: std::convert::TryInto<tonic::transport::Endpoint>,
39
+
D::Error: Into<StdError>,
40
+
{
41
+
let conn = tonic::transport::Endpoint::new(dst)?.connect().await?;
42
+
Ok(Self::new(conn))
43
+
}
44
+
}
45
+
impl<T> BrowseServiceClient<T>
46
+
where
47
+
T: tonic::client::GrpcService<tonic::body::BoxBody>,
48
+
T::Error: Into<StdError>,
49
+
T::ResponseBody: Body<Data = Bytes> + Send + 'static,
50
+
<T::ResponseBody as Body>::Error: Into<StdError> + Send,
51
+
{
52
+
pub fn new(inner: T) -> Self {
53
+
let inner = tonic::client::Grpc::new(inner);
54
+
Self { inner }
55
+
}
56
+
pub fn with_origin(inner: T, origin: Uri) -> Self {
57
+
let inner = tonic::client::Grpc::with_origin(inner, origin);
58
+
Self { inner }
59
+
}
60
+
pub fn with_interceptor<F>(
61
+
inner: T,
62
+
interceptor: F,
63
+
) -> BrowseServiceClient<InterceptedService<T, F>>
64
+
where
65
+
F: tonic::service::Interceptor,
66
+
T::ResponseBody: Default,
67
+
T: tonic::codegen::Service<
68
+
http::Request<tonic::body::BoxBody>,
69
+
Response = http::Response<
70
+
<T as tonic::client::GrpcService<tonic::body::BoxBody>>::ResponseBody,
71
+
>,
72
+
>,
73
+
<T as tonic::codegen::Service<
74
+
http::Request<tonic::body::BoxBody>,
75
+
>>::Error: Into<StdError> + Send + Sync,
76
+
{
77
+
BrowseServiceClient::new(InterceptedService::new(inner, interceptor))
78
+
}
79
+
/// Compress requests with the given encoding.
80
+
///
81
+
/// This requires the server to support it otherwise it might respond with an
82
+
/// error.
83
+
#[must_use]
84
+
pub fn send_compressed(mut self, encoding: CompressionEncoding) -> Self {
85
+
self.inner = self.inner.send_compressed(encoding);
86
+
self
87
+
}
88
+
/// Enable decompressing responses.
89
+
#[must_use]
90
+
pub fn accept_compressed(mut self, encoding: CompressionEncoding) -> Self {
91
+
self.inner = self.inner.accept_compressed(encoding);
92
+
self
93
+
}
94
+
pub async fn get_categories(
95
+
&mut self,
96
+
request: impl tonic::IntoRequest<super::GetCategoriesRequest>,
97
+
) -> Result<tonic::Response<super::GetCategoriesResponse>, tonic::Status> {
98
+
self.inner
99
+
.ready()
100
+
.await
101
+
.map_err(|e| {
102
+
tonic::Status::new(
103
+
tonic::Code::Unknown,
104
+
format!("Service was not ready: {}", e.into()),
105
+
)
106
+
})?;
107
+
let codec = tonic::codec::ProstCodec::default();
108
+
let path = http::uri::PathAndQuery::from_static(
109
+
"/tunein.v1alpha1.BrowseService/GetCategories",
110
+
);
111
+
self.inner.unary(request.into_request(), path, codec).await
112
+
}
113
+
pub async fn browse_category(
114
+
&mut self,
115
+
request: impl tonic::IntoRequest<super::BrowseCategoryRequest>,
116
+
) -> Result<tonic::Response<super::BrowseCategoryResponse>, tonic::Status> {
117
+
self.inner
118
+
.ready()
119
+
.await
120
+
.map_err(|e| {
121
+
tonic::Status::new(
122
+
tonic::Code::Unknown,
123
+
format!("Service was not ready: {}", e.into()),
124
+
)
125
+
})?;
126
+
let codec = tonic::codec::ProstCodec::default();
127
+
let path = http::uri::PathAndQuery::from_static(
128
+
"/tunein.v1alpha1.BrowseService/BrowseCategory",
129
+
);
130
+
self.inner.unary(request.into_request(), path, codec).await
131
+
}
132
+
pub async fn get_station_details(
133
+
&mut self,
134
+
request: impl tonic::IntoRequest<super::GetStationDetailsRequest>,
135
+
) -> Result<tonic::Response<super::GetStationDetailsResponse>, tonic::Status> {
136
+
self.inner
137
+
.ready()
138
+
.await
139
+
.map_err(|e| {
140
+
tonic::Status::new(
141
+
tonic::Code::Unknown,
142
+
format!("Service was not ready: {}", e.into()),
143
+
)
144
+
})?;
145
+
let codec = tonic::codec::ProstCodec::default();
146
+
let path = http::uri::PathAndQuery::from_static(
147
+
"/tunein.v1alpha1.BrowseService/GetStationDetails",
148
+
);
149
+
self.inner.unary(request.into_request(), path, codec).await
150
+
}
151
+
}
152
+
}
153
+
/// Generated server implementations.
154
+
pub mod browse_service_server {
155
+
#![allow(unused_variables, dead_code, missing_docs, clippy::let_unit_value)]
156
+
use tonic::codegen::*;
157
+
/// Generated trait containing gRPC methods that should be implemented for use with BrowseServiceServer.
158
+
#[async_trait]
159
+
pub trait BrowseService: Send + Sync + 'static {
160
+
async fn get_categories(
161
+
&self,
162
+
request: tonic::Request<super::GetCategoriesRequest>,
163
+
) -> Result<tonic::Response<super::GetCategoriesResponse>, tonic::Status>;
164
+
async fn browse_category(
165
+
&self,
166
+
request: tonic::Request<super::BrowseCategoryRequest>,
167
+
) -> Result<tonic::Response<super::BrowseCategoryResponse>, tonic::Status>;
168
+
async fn get_station_details(
169
+
&self,
170
+
request: tonic::Request<super::GetStationDetailsRequest>,
171
+
) -> Result<tonic::Response<super::GetStationDetailsResponse>, tonic::Status>;
172
+
}
173
+
#[derive(Debug)]
174
+
pub struct BrowseServiceServer<T: BrowseService> {
175
+
inner: _Inner<T>,
176
+
accept_compression_encodings: EnabledCompressionEncodings,
177
+
send_compression_encodings: EnabledCompressionEncodings,
178
+
}
179
+
struct _Inner<T>(Arc<T>);
180
+
impl<T: BrowseService> BrowseServiceServer<T> {
181
+
pub fn new(inner: T) -> Self {
182
+
Self::from_arc(Arc::new(inner))
183
+
}
184
+
pub fn from_arc(inner: Arc<T>) -> Self {
185
+
let inner = _Inner(inner);
186
+
Self {
187
+
inner,
188
+
accept_compression_encodings: Default::default(),
189
+
send_compression_encodings: Default::default(),
190
+
}
191
+
}
192
+
pub fn with_interceptor<F>(
193
+
inner: T,
194
+
interceptor: F,
195
+
) -> InterceptedService<Self, F>
196
+
where
197
+
F: tonic::service::Interceptor,
198
+
{
199
+
InterceptedService::new(Self::new(inner), interceptor)
200
+
}
201
+
/// Enable decompressing requests with the given encoding.
202
+
#[must_use]
203
+
pub fn accept_compressed(mut self, encoding: CompressionEncoding) -> Self {
204
+
self.accept_compression_encodings.enable(encoding);
205
+
self
206
+
}
207
+
/// Compress responses with the given encoding, if the client supports it.
208
+
#[must_use]
209
+
pub fn send_compressed(mut self, encoding: CompressionEncoding) -> Self {
210
+
self.send_compression_encodings.enable(encoding);
211
+
self
212
+
}
213
+
}
214
+
impl<T, B> tonic::codegen::Service<http::Request<B>> for BrowseServiceServer<T>
215
+
where
216
+
T: BrowseService,
217
+
B: Body + Send + 'static,
218
+
B::Error: Into<StdError> + Send + 'static,
219
+
{
220
+
type Response = http::Response<tonic::body::BoxBody>;
221
+
type Error = std::convert::Infallible;
222
+
type Future = BoxFuture<Self::Response, Self::Error>;
223
+
fn poll_ready(
224
+
&mut self,
225
+
_cx: &mut Context<'_>,
226
+
) -> Poll<Result<(), Self::Error>> {
227
+
Poll::Ready(Ok(()))
228
+
}
229
+
fn call(&mut self, req: http::Request<B>) -> Self::Future {
230
+
let inner = self.inner.clone();
231
+
match req.uri().path() {
232
+
"/tunein.v1alpha1.BrowseService/GetCategories" => {
233
+
#[allow(non_camel_case_types)]
234
+
struct GetCategoriesSvc<T: BrowseService>(pub Arc<T>);
235
+
impl<
236
+
T: BrowseService,
237
+
> tonic::server::UnaryService<super::GetCategoriesRequest>
238
+
for GetCategoriesSvc<T> {
239
+
type Response = super::GetCategoriesResponse;
240
+
type Future = BoxFuture<
241
+
tonic::Response<Self::Response>,
242
+
tonic::Status,
243
+
>;
244
+
fn call(
245
+
&mut self,
246
+
request: tonic::Request<super::GetCategoriesRequest>,
247
+
) -> Self::Future {
248
+
let inner = self.0.clone();
249
+
let fut = async move {
250
+
(*inner).get_categories(request).await
251
+
};
252
+
Box::pin(fut)
253
+
}
254
+
}
255
+
let accept_compression_encodings = self.accept_compression_encodings;
256
+
let send_compression_encodings = self.send_compression_encodings;
257
+
let inner = self.inner.clone();
258
+
let fut = async move {
259
+
let inner = inner.0;
260
+
let method = GetCategoriesSvc(inner);
261
+
let codec = tonic::codec::ProstCodec::default();
262
+
let mut grpc = tonic::server::Grpc::new(codec)
263
+
.apply_compression_config(
264
+
accept_compression_encodings,
265
+
send_compression_encodings,
266
+
);
267
+
let res = grpc.unary(method, req).await;
268
+
Ok(res)
269
+
};
270
+
Box::pin(fut)
271
+
}
272
+
"/tunein.v1alpha1.BrowseService/BrowseCategory" => {
273
+
#[allow(non_camel_case_types)]
274
+
struct BrowseCategorySvc<T: BrowseService>(pub Arc<T>);
275
+
impl<
276
+
T: BrowseService,
277
+
> tonic::server::UnaryService<super::BrowseCategoryRequest>
278
+
for BrowseCategorySvc<T> {
279
+
type Response = super::BrowseCategoryResponse;
280
+
type Future = BoxFuture<
281
+
tonic::Response<Self::Response>,
282
+
tonic::Status,
283
+
>;
284
+
fn call(
285
+
&mut self,
286
+
request: tonic::Request<super::BrowseCategoryRequest>,
287
+
) -> Self::Future {
288
+
let inner = self.0.clone();
289
+
let fut = async move {
290
+
(*inner).browse_category(request).await
291
+
};
292
+
Box::pin(fut)
293
+
}
294
+
}
295
+
let accept_compression_encodings = self.accept_compression_encodings;
296
+
let send_compression_encodings = self.send_compression_encodings;
297
+
let inner = self.inner.clone();
298
+
let fut = async move {
299
+
let inner = inner.0;
300
+
let method = BrowseCategorySvc(inner);
301
+
let codec = tonic::codec::ProstCodec::default();
302
+
let mut grpc = tonic::server::Grpc::new(codec)
303
+
.apply_compression_config(
304
+
accept_compression_encodings,
305
+
send_compression_encodings,
306
+
);
307
+
let res = grpc.unary(method, req).await;
308
+
Ok(res)
309
+
};
310
+
Box::pin(fut)
311
+
}
312
+
"/tunein.v1alpha1.BrowseService/GetStationDetails" => {
313
+
#[allow(non_camel_case_types)]
314
+
struct GetStationDetailsSvc<T: BrowseService>(pub Arc<T>);
315
+
impl<
316
+
T: BrowseService,
317
+
> tonic::server::UnaryService<super::GetStationDetailsRequest>
318
+
for GetStationDetailsSvc<T> {
319
+
type Response = super::GetStationDetailsResponse;
320
+
type Future = BoxFuture<
321
+
tonic::Response<Self::Response>,
322
+
tonic::Status,
323
+
>;
324
+
fn call(
325
+
&mut self,
326
+
request: tonic::Request<super::GetStationDetailsRequest>,
327
+
) -> Self::Future {
328
+
let inner = self.0.clone();
329
+
let fut = async move {
330
+
(*inner).get_station_details(request).await
331
+
};
332
+
Box::pin(fut)
333
+
}
334
+
}
335
+
let accept_compression_encodings = self.accept_compression_encodings;
336
+
let send_compression_encodings = self.send_compression_encodings;
337
+
let inner = self.inner.clone();
338
+
let fut = async move {
339
+
let inner = inner.0;
340
+
let method = GetStationDetailsSvc(inner);
341
+
let codec = tonic::codec::ProstCodec::default();
342
+
let mut grpc = tonic::server::Grpc::new(codec)
343
+
.apply_compression_config(
344
+
accept_compression_encodings,
345
+
send_compression_encodings,
346
+
);
347
+
let res = grpc.unary(method, req).await;
348
+
Ok(res)
349
+
};
350
+
Box::pin(fut)
351
+
}
352
+
_ => {
353
+
Box::pin(async move {
354
+
Ok(
355
+
http::Response::builder()
356
+
.status(200)
357
+
.header("grpc-status", "12")
358
+
.header("content-type", "application/grpc")
359
+
.body(empty_body())
360
+
.unwrap(),
361
+
)
362
+
})
363
+
}
364
+
}
365
+
}
366
+
}
367
+
impl<T: BrowseService> Clone for BrowseServiceServer<T> {
368
+
fn clone(&self) -> Self {
369
+
let inner = self.inner.clone();
370
+
Self {
371
+
inner,
372
+
accept_compression_encodings: self.accept_compression_encodings,
373
+
send_compression_encodings: self.send_compression_encodings,
374
+
}
375
+
}
376
+
}
377
+
impl<T: BrowseService> Clone for _Inner<T> {
378
+
fn clone(&self) -> Self {
379
+
Self(self.0.clone())
380
+
}
381
+
}
382
+
impl<T: std::fmt::Debug> std::fmt::Debug for _Inner<T> {
383
+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
384
+
write!(f, "{:?}", self.0)
385
+
}
386
+
}
387
+
impl<T: BrowseService> tonic::server::NamedService for BrowseServiceServer<T> {
388
+
const NAME: &'static str = "tunein.v1alpha1.BrowseService";
389
+
}
390
+
}
391
+
#[allow(clippy::derive_partial_eq_without_eq)]
392
+
#[derive(Clone, PartialEq, ::prost::Message)]
393
+
pub struct PlayOrPauseRequest {}
394
+
#[allow(clippy::derive_partial_eq_without_eq)]
395
+
#[derive(Clone, PartialEq, ::prost::Message)]
396
+
pub struct PlayOrPauseResponse {}
397
+
#[allow(clippy::derive_partial_eq_without_eq)]
398
+
#[derive(Clone, PartialEq, ::prost::Message)]
399
+
pub struct StopRequest {}
400
+
#[allow(clippy::derive_partial_eq_without_eq)]
401
+
#[derive(Clone, PartialEq, ::prost::Message)]
402
+
pub struct StopResponse {}
403
+
#[allow(clippy::derive_partial_eq_without_eq)]
404
+
#[derive(Clone, PartialEq, ::prost::Message)]
405
+
pub struct PlayRequest {
406
+
#[prost(string, tag = "1")]
407
+
pub station_name_or_id: ::prost::alloc::string::String,
408
+
}
409
+
#[allow(clippy::derive_partial_eq_without_eq)]
410
+
#[derive(Clone, PartialEq, ::prost::Message)]
411
+
pub struct PlayResponse {}
412
+
/// Generated client implementations.
413
+
pub mod playback_service_client {
414
+
#![allow(unused_variables, dead_code, missing_docs, clippy::let_unit_value)]
415
+
use tonic::codegen::*;
416
+
use tonic::codegen::http::Uri;
417
+
#[derive(Debug, Clone)]
418
+
pub struct PlaybackServiceClient<T> {
419
+
inner: tonic::client::Grpc<T>,
420
+
}
421
+
impl PlaybackServiceClient<tonic::transport::Channel> {
422
+
/// Attempt to create a new client by connecting to a given endpoint.
423
+
pub async fn connect<D>(dst: D) -> Result<Self, tonic::transport::Error>
424
+
where
425
+
D: std::convert::TryInto<tonic::transport::Endpoint>,
426
+
D::Error: Into<StdError>,
427
+
{
428
+
let conn = tonic::transport::Endpoint::new(dst)?.connect().await?;
429
+
Ok(Self::new(conn))
430
+
}
431
+
}
432
+
impl<T> PlaybackServiceClient<T>
433
+
where
434
+
T: tonic::client::GrpcService<tonic::body::BoxBody>,
435
+
T::Error: Into<StdError>,
436
+
T::ResponseBody: Body<Data = Bytes> + Send + 'static,
437
+
<T::ResponseBody as Body>::Error: Into<StdError> + Send,
438
+
{
439
+
pub fn new(inner: T) -> Self {
440
+
let inner = tonic::client::Grpc::new(inner);
441
+
Self { inner }
442
+
}
443
+
pub fn with_origin(inner: T, origin: Uri) -> Self {
444
+
let inner = tonic::client::Grpc::with_origin(inner, origin);
445
+
Self { inner }
446
+
}
447
+
pub fn with_interceptor<F>(
448
+
inner: T,
449
+
interceptor: F,
450
+
) -> PlaybackServiceClient<InterceptedService<T, F>>
451
+
where
452
+
F: tonic::service::Interceptor,
453
+
T::ResponseBody: Default,
454
+
T: tonic::codegen::Service<
455
+
http::Request<tonic::body::BoxBody>,
456
+
Response = http::Response<
457
+
<T as tonic::client::GrpcService<tonic::body::BoxBody>>::ResponseBody,
458
+
>,
459
+
>,
460
+
<T as tonic::codegen::Service<
461
+
http::Request<tonic::body::BoxBody>,
462
+
>>::Error: Into<StdError> + Send + Sync,
463
+
{
464
+
PlaybackServiceClient::new(InterceptedService::new(inner, interceptor))
465
+
}
466
+
/// Compress requests with the given encoding.
467
+
///
468
+
/// This requires the server to support it otherwise it might respond with an
469
+
/// error.
470
+
#[must_use]
471
+
pub fn send_compressed(mut self, encoding: CompressionEncoding) -> Self {
472
+
self.inner = self.inner.send_compressed(encoding);
473
+
self
474
+
}
475
+
/// Enable decompressing responses.
476
+
#[must_use]
477
+
pub fn accept_compressed(mut self, encoding: CompressionEncoding) -> Self {
478
+
self.inner = self.inner.accept_compressed(encoding);
479
+
self
480
+
}
481
+
pub async fn play(
482
+
&mut self,
483
+
request: impl tonic::IntoRequest<super::PlayRequest>,
484
+
) -> Result<tonic::Response<super::PlayResponse>, tonic::Status> {
485
+
self.inner
486
+
.ready()
487
+
.await
488
+
.map_err(|e| {
489
+
tonic::Status::new(
490
+
tonic::Code::Unknown,
491
+
format!("Service was not ready: {}", e.into()),
492
+
)
493
+
})?;
494
+
let codec = tonic::codec::ProstCodec::default();
495
+
let path = http::uri::PathAndQuery::from_static(
496
+
"/tunein.v1alpha1.PlaybackService/Play",
497
+
);
498
+
self.inner.unary(request.into_request(), path, codec).await
499
+
}
500
+
pub async fn stop(
501
+
&mut self,
502
+
request: impl tonic::IntoRequest<super::StopRequest>,
503
+
) -> Result<tonic::Response<super::StopResponse>, tonic::Status> {
504
+
self.inner
505
+
.ready()
506
+
.await
507
+
.map_err(|e| {
508
+
tonic::Status::new(
509
+
tonic::Code::Unknown,
510
+
format!("Service was not ready: {}", e.into()),
511
+
)
512
+
})?;
513
+
let codec = tonic::codec::ProstCodec::default();
514
+
let path = http::uri::PathAndQuery::from_static(
515
+
"/tunein.v1alpha1.PlaybackService/Stop",
516
+
);
517
+
self.inner.unary(request.into_request(), path, codec).await
518
+
}
519
+
pub async fn play_or_pause(
520
+
&mut self,
521
+
request: impl tonic::IntoRequest<super::PlayOrPauseRequest>,
522
+
) -> Result<tonic::Response<super::PlayOrPauseResponse>, tonic::Status> {
523
+
self.inner
524
+
.ready()
525
+
.await
526
+
.map_err(|e| {
527
+
tonic::Status::new(
528
+
tonic::Code::Unknown,
529
+
format!("Service was not ready: {}", e.into()),
530
+
)
531
+
})?;
532
+
let codec = tonic::codec::ProstCodec::default();
533
+
let path = http::uri::PathAndQuery::from_static(
534
+
"/tunein.v1alpha1.PlaybackService/PlayOrPause",
535
+
);
536
+
self.inner.unary(request.into_request(), path, codec).await
537
+
}
538
+
}
539
+
}
540
+
/// Generated server implementations.
541
+
pub mod playback_service_server {
542
+
#![allow(unused_variables, dead_code, missing_docs, clippy::let_unit_value)]
543
+
use tonic::codegen::*;
544
+
/// Generated trait containing gRPC methods that should be implemented for use with PlaybackServiceServer.
545
+
#[async_trait]
546
+
pub trait PlaybackService: Send + Sync + 'static {
547
+
async fn play(
548
+
&self,
549
+
request: tonic::Request<super::PlayRequest>,
550
+
) -> Result<tonic::Response<super::PlayResponse>, tonic::Status>;
551
+
async fn stop(
552
+
&self,
553
+
request: tonic::Request<super::StopRequest>,
554
+
) -> Result<tonic::Response<super::StopResponse>, tonic::Status>;
555
+
async fn play_or_pause(
556
+
&self,
557
+
request: tonic::Request<super::PlayOrPauseRequest>,
558
+
) -> Result<tonic::Response<super::PlayOrPauseResponse>, tonic::Status>;
559
+
}
560
+
#[derive(Debug)]
561
+
pub struct PlaybackServiceServer<T: PlaybackService> {
562
+
inner: _Inner<T>,
563
+
accept_compression_encodings: EnabledCompressionEncodings,
564
+
send_compression_encodings: EnabledCompressionEncodings,
565
+
}
566
+
struct _Inner<T>(Arc<T>);
567
+
impl<T: PlaybackService> PlaybackServiceServer<T> {
568
+
pub fn new(inner: T) -> Self {
569
+
Self::from_arc(Arc::new(inner))
570
+
}
571
+
pub fn from_arc(inner: Arc<T>) -> Self {
572
+
let inner = _Inner(inner);
573
+
Self {
574
+
inner,
575
+
accept_compression_encodings: Default::default(),
576
+
send_compression_encodings: Default::default(),
577
+
}
578
+
}
579
+
pub fn with_interceptor<F>(
580
+
inner: T,
581
+
interceptor: F,
582
+
) -> InterceptedService<Self, F>
583
+
where
584
+
F: tonic::service::Interceptor,
585
+
{
586
+
InterceptedService::new(Self::new(inner), interceptor)
587
+
}
588
+
/// Enable decompressing requests with the given encoding.
589
+
#[must_use]
590
+
pub fn accept_compressed(mut self, encoding: CompressionEncoding) -> Self {
591
+
self.accept_compression_encodings.enable(encoding);
592
+
self
593
+
}
594
+
/// Compress responses with the given encoding, if the client supports it.
595
+
#[must_use]
596
+
pub fn send_compressed(mut self, encoding: CompressionEncoding) -> Self {
597
+
self.send_compression_encodings.enable(encoding);
598
+
self
599
+
}
600
+
}
601
+
impl<T, B> tonic::codegen::Service<http::Request<B>> for PlaybackServiceServer<T>
602
+
where
603
+
T: PlaybackService,
604
+
B: Body + Send + 'static,
605
+
B::Error: Into<StdError> + Send + 'static,
606
+
{
607
+
type Response = http::Response<tonic::body::BoxBody>;
608
+
type Error = std::convert::Infallible;
609
+
type Future = BoxFuture<Self::Response, Self::Error>;
610
+
fn poll_ready(
611
+
&mut self,
612
+
_cx: &mut Context<'_>,
613
+
) -> Poll<Result<(), Self::Error>> {
614
+
Poll::Ready(Ok(()))
615
+
}
616
+
fn call(&mut self, req: http::Request<B>) -> Self::Future {
617
+
let inner = self.inner.clone();
618
+
match req.uri().path() {
619
+
"/tunein.v1alpha1.PlaybackService/Play" => {
620
+
#[allow(non_camel_case_types)]
621
+
struct PlaySvc<T: PlaybackService>(pub Arc<T>);
622
+
impl<
623
+
T: PlaybackService,
624
+
> tonic::server::UnaryService<super::PlayRequest> for PlaySvc<T> {
625
+
type Response = super::PlayResponse;
626
+
type Future = BoxFuture<
627
+
tonic::Response<Self::Response>,
628
+
tonic::Status,
629
+
>;
630
+
fn call(
631
+
&mut self,
632
+
request: tonic::Request<super::PlayRequest>,
633
+
) -> Self::Future {
634
+
let inner = self.0.clone();
635
+
let fut = async move { (*inner).play(request).await };
636
+
Box::pin(fut)
637
+
}
638
+
}
639
+
let accept_compression_encodings = self.accept_compression_encodings;
640
+
let send_compression_encodings = self.send_compression_encodings;
641
+
let inner = self.inner.clone();
642
+
let fut = async move {
643
+
let inner = inner.0;
644
+
let method = PlaySvc(inner);
645
+
let codec = tonic::codec::ProstCodec::default();
646
+
let mut grpc = tonic::server::Grpc::new(codec)
647
+
.apply_compression_config(
648
+
accept_compression_encodings,
649
+
send_compression_encodings,
650
+
);
651
+
let res = grpc.unary(method, req).await;
652
+
Ok(res)
653
+
};
654
+
Box::pin(fut)
655
+
}
656
+
"/tunein.v1alpha1.PlaybackService/Stop" => {
657
+
#[allow(non_camel_case_types)]
658
+
struct StopSvc<T: PlaybackService>(pub Arc<T>);
659
+
impl<
660
+
T: PlaybackService,
661
+
> tonic::server::UnaryService<super::StopRequest> for StopSvc<T> {
662
+
type Response = super::StopResponse;
663
+
type Future = BoxFuture<
664
+
tonic::Response<Self::Response>,
665
+
tonic::Status,
666
+
>;
667
+
fn call(
668
+
&mut self,
669
+
request: tonic::Request<super::StopRequest>,
670
+
) -> Self::Future {
671
+
let inner = self.0.clone();
672
+
let fut = async move { (*inner).stop(request).await };
673
+
Box::pin(fut)
674
+
}
675
+
}
676
+
let accept_compression_encodings = self.accept_compression_encodings;
677
+
let send_compression_encodings = self.send_compression_encodings;
678
+
let inner = self.inner.clone();
679
+
let fut = async move {
680
+
let inner = inner.0;
681
+
let method = StopSvc(inner);
682
+
let codec = tonic::codec::ProstCodec::default();
683
+
let mut grpc = tonic::server::Grpc::new(codec)
684
+
.apply_compression_config(
685
+
accept_compression_encodings,
686
+
send_compression_encodings,
687
+
);
688
+
let res = grpc.unary(method, req).await;
689
+
Ok(res)
690
+
};
691
+
Box::pin(fut)
692
+
}
693
+
"/tunein.v1alpha1.PlaybackService/PlayOrPause" => {
694
+
#[allow(non_camel_case_types)]
695
+
struct PlayOrPauseSvc<T: PlaybackService>(pub Arc<T>);
696
+
impl<
697
+
T: PlaybackService,
698
+
> tonic::server::UnaryService<super::PlayOrPauseRequest>
699
+
for PlayOrPauseSvc<T> {
700
+
type Response = super::PlayOrPauseResponse;
701
+
type Future = BoxFuture<
702
+
tonic::Response<Self::Response>,
703
+
tonic::Status,
704
+
>;
705
+
fn call(
706
+
&mut self,
707
+
request: tonic::Request<super::PlayOrPauseRequest>,
708
+
) -> Self::Future {
709
+
let inner = self.0.clone();
710
+
let fut = async move {
711
+
(*inner).play_or_pause(request).await
712
+
};
713
+
Box::pin(fut)
714
+
}
715
+
}
716
+
let accept_compression_encodings = self.accept_compression_encodings;
717
+
let send_compression_encodings = self.send_compression_encodings;
718
+
let inner = self.inner.clone();
719
+
let fut = async move {
720
+
let inner = inner.0;
721
+
let method = PlayOrPauseSvc(inner);
722
+
let codec = tonic::codec::ProstCodec::default();
723
+
let mut grpc = tonic::server::Grpc::new(codec)
724
+
.apply_compression_config(
725
+
accept_compression_encodings,
726
+
send_compression_encodings,
727
+
);
728
+
let res = grpc.unary(method, req).await;
729
+
Ok(res)
730
+
};
731
+
Box::pin(fut)
732
+
}
733
+
_ => {
734
+
Box::pin(async move {
735
+
Ok(
736
+
http::Response::builder()
737
+
.status(200)
738
+
.header("grpc-status", "12")
739
+
.header("content-type", "application/grpc")
740
+
.body(empty_body())
741
+
.unwrap(),
742
+
)
743
+
})
744
+
}
745
+
}
746
+
}
747
+
}
748
+
impl<T: PlaybackService> Clone for PlaybackServiceServer<T> {
749
+
fn clone(&self) -> Self {
750
+
let inner = self.inner.clone();
751
+
Self {
752
+
inner,
753
+
accept_compression_encodings: self.accept_compression_encodings,
754
+
send_compression_encodings: self.send_compression_encodings,
755
+
}
756
+
}
757
+
}
758
+
impl<T: PlaybackService> Clone for _Inner<T> {
759
+
fn clone(&self) -> Self {
760
+
Self(self.0.clone())
761
+
}
762
+
}
763
+
impl<T: std::fmt::Debug> std::fmt::Debug for _Inner<T> {
764
+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
765
+
write!(f, "{:?}", self.0)
766
+
}
767
+
}
768
+
impl<T: PlaybackService> tonic::server::NamedService for PlaybackServiceServer<T> {
769
+
const NAME: &'static str = "tunein.v1alpha1.PlaybackService";
770
+
}
771
+
}
+13
src/lib.rs
+13
src/lib.rs
+11
src/main.rs
+11
src/main.rs
···
5
5
mod decoder;
6
6
mod play;
7
7
mod search;
8
+
mod server;
8
9
9
10
fn cli() -> Command<'static> {
10
11
const VESRION: &str = env!("CARGO_PKG_VERSION");
···
36
37
.about("Browse radio stations")
37
38
.arg(arg!([category] "The category (category name or id) to browse")),
38
39
)
40
+
.subcommand(
41
+
Command::new("server")
42
+
.about("Start the server")
43
+
.arg(arg!([port] "The port to listen on").default_value("8090")),
44
+
)
39
45
}
40
46
41
47
#[tokio::main]
···
54
60
Some(("browse", args)) => {
55
61
let category = args.value_of("category");
56
62
browse::exec(category).await?;
63
+
}
64
+
Some(("server", args)) => {
65
+
let port = args.value_of("port").unwrap();
66
+
let port = port.parse::<u16>().unwrap();
67
+
server::exec(port).await?;
57
68
}
58
69
_ => unreachable!(),
59
70
}
+33
src/server/browse.rs
+33
src/server/browse.rs
···
1
+
use tunein_cli::api::tunein::v1alpha1::{
2
+
browse_service_server::BrowseService, BrowseCategoryRequest, BrowseCategoryResponse,
3
+
GetCategoriesRequest, GetCategoriesResponse, GetStationDetailsRequest,
4
+
GetStationDetailsResponse,
5
+
};
6
+
7
+
#[derive(Debug, Default)]
8
+
pub struct Browse {}
9
+
10
+
11
+
#[tonic::async_trait]
12
+
impl BrowseService for Browse {
13
+
async fn get_categories(
14
+
&self,
15
+
request: tonic::Request<GetCategoriesRequest>,
16
+
) -> Result<tonic::Response<GetCategoriesResponse>, tonic::Status> {
17
+
todo!()
18
+
}
19
+
20
+
async fn browse_category(
21
+
&self,
22
+
request: tonic::Request<BrowseCategoryRequest>,
23
+
) -> Result<tonic::Response<BrowseCategoryResponse>, tonic::Status> {
24
+
todo!()
25
+
}
26
+
27
+
async fn get_station_details(
28
+
&self,
29
+
request: tonic::Request<GetStationDetailsRequest>,
30
+
) -> Result<tonic::Response<GetStationDetailsResponse>, tonic::Status> {
31
+
todo!()
32
+
}
33
+
}
+29
src/server/mod.rs
+29
src/server/mod.rs
···
1
+
use std::net::SocketAddr;
2
+
3
+
use anyhow::Error;
4
+
use owo_colors::OwoColorize;
5
+
use tonic::transport::Server;
6
+
use tunein_cli::api::tunein::v1alpha1::{
7
+
browse_service_server::BrowseServiceServer, playback_service_server::PlaybackServiceServer,
8
+
};
9
+
10
+
use self::{browse::Browse, playback::Playback};
11
+
12
+
pub mod browse;
13
+
pub mod playback;
14
+
15
+
pub async fn exec(port: u16) -> Result<(), Error> {
16
+
let addr: SocketAddr = format!("0.0.0.0:{}", port).parse().unwrap();
17
+
println!("Listening on {}", addr.cyan());
18
+
Server::builder()
19
+
.accept_http1(true)
20
+
.add_service(tonic_web::enable(BrowseServiceServer::new(
21
+
Browse::default(),
22
+
)))
23
+
.add_service(tonic_web::enable(PlaybackServiceServer::new(
24
+
Playback::default(),
25
+
)))
26
+
.serve(addr)
27
+
.await?;
28
+
Ok(())
29
+
}
+31
src/server/playback.rs
+31
src/server/playback.rs
···
1
+
use tunein_cli::api::tunein::v1alpha1::{
2
+
playback_service_server::PlaybackService, PlayOrPauseRequest, PlayOrPauseResponse, PlayRequest,
3
+
PlayResponse, StopRequest, StopResponse,
4
+
};
5
+
6
+
#[derive(Debug, Default)]
7
+
pub struct Playback {}
8
+
9
+
#[tonic::async_trait]
10
+
impl PlaybackService for Playback {
11
+
async fn play(
12
+
&self,
13
+
request: tonic::Request<PlayRequest>,
14
+
) -> Result<tonic::Response<PlayResponse>, tonic::Status> {
15
+
todo!()
16
+
}
17
+
18
+
async fn stop(
19
+
&self,
20
+
request: tonic::Request<StopRequest>,
21
+
) -> Result<tonic::Response<StopResponse>, tonic::Status> {
22
+
todo!()
23
+
}
24
+
25
+
async fn play_or_pause(
26
+
&self,
27
+
request: tonic::Request<PlayOrPauseRequest>,
28
+
) -> Result<tonic::Response<PlayOrPauseResponse>, tonic::Status> {
29
+
todo!()
30
+
}
31
+
}