Compare commits
543 Commits
v0.5.4
...
782106e44a
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
782106e44a | ||
|
|
0e0a8b853f | ||
|
|
8c716130a3 | ||
|
|
dfc9be33d7 | ||
|
|
9b592cf761 | ||
|
|
d3122416cf | ||
|
|
a6af9d856b | ||
|
|
51aaa1f603 | ||
|
|
a71efe14c1 | ||
|
|
1879a8ed01 | ||
|
|
7d6ee45263 | ||
|
|
44ad891242 | ||
|
|
a94575f83c | ||
|
|
1c75b09824 | ||
|
|
ebd59760ae | ||
|
|
3184fa6f89 | ||
|
|
32f2b12708 | ||
|
|
b9a6b5056a | ||
|
|
238d30ab94 | ||
|
|
7d26589cf6 | ||
|
|
10857e39b1 | ||
|
|
30a07327bc | ||
|
|
50f2f1ac3c | ||
|
|
8041a0b9d8 | ||
|
|
d5920a381e | ||
|
|
36b2891353 | ||
|
|
4fa6d7d643 | ||
|
|
90151c2958 | ||
|
|
4133c03759 | ||
|
|
aab694c302 | ||
|
|
c963176bba | ||
|
|
06ffff3031 | ||
|
|
2021f76dfd | ||
|
|
112e244fbc | ||
|
|
a655d49ce3 | ||
|
|
ddb47065bb | ||
|
|
e94873c011 | ||
|
|
8f07d44a4d | ||
|
|
d63b4321c2 | ||
|
|
b1c9f3877b | ||
|
|
d49eac5666 | ||
|
|
a24f921804 | ||
|
|
f1d86743f3 | ||
|
|
0b6c14b540 | ||
|
|
10c6b116da | ||
|
|
17c3ed2625 | ||
|
|
296acefb09 | ||
|
|
2bb737bfd9 | ||
|
|
053eb71967 | ||
|
|
ed2190c03d | ||
|
|
cd210900f8 | ||
|
|
b2d09191f3 | ||
|
|
19e71f8e6e | ||
|
|
45ab93c527 | ||
|
|
4c58546fd6 | ||
|
|
854d72fe15 | ||
|
|
786f01cd7e | ||
|
|
69a95f04d7 | ||
|
|
7ef4d0c7bd | ||
|
|
9c1d34d148 | ||
|
|
3d3bab2fec | ||
|
|
5bac2f8e87 | ||
|
|
d54e40306b | ||
|
|
7699a2820d | ||
|
|
2b9be31e6e | ||
|
|
b67b9c0e9d | ||
|
|
4ecba55765 | ||
|
|
58c8c90099 | ||
|
|
1d378cc52d | ||
|
|
f108a84b4f | ||
|
|
e79c8ba10a | ||
|
|
a5021d4686 | ||
|
|
8fa027e98f | ||
|
|
75437d8f66 | ||
|
|
b6f374af2d | ||
|
|
00e751373b | ||
|
|
e7592dc4f5 | ||
|
|
90627f177b | ||
|
|
dd5d72c607 | ||
|
|
12a32c0793 | ||
|
|
4d8df33a0a | ||
|
|
eecf1d3fe2 | ||
|
|
056948d33d | ||
|
|
cc508cdfa5 | ||
|
|
ff1a6df0e8 | ||
|
|
11e9221206 | ||
|
|
737d86faaf | ||
|
|
5229b70e5e | ||
|
|
f151f5ae19 | ||
|
|
a4d88c72a4 | ||
|
|
f303314237 | ||
|
|
a3928ca921 | ||
|
|
c3d13c7c69 | ||
|
|
4ffbb6bb8d | ||
|
|
4324659e67 | ||
|
|
a564c52df0 | ||
|
|
1ac78e45d6 | ||
|
|
1dc6879f2f | ||
|
|
6de9ead965 | ||
|
|
f4ccd1d56f | ||
|
|
1d103ad848 | ||
|
|
96d837732b | ||
|
|
3572dcc555 | ||
|
|
b6b19f5a23 | ||
|
|
bb1284deff | ||
|
|
bc125bb0a3 | ||
|
|
3d30fcfc3e | ||
|
|
b5c9ecdf5c | ||
|
|
a09379f47b | ||
|
|
2a191a310e | ||
|
|
50be0c9bde | ||
|
|
5cfef6c6c0 | ||
|
|
5015a3b900 | ||
|
|
c7050ac9a1 | ||
|
|
a0c192e567 | ||
|
|
06c08d76e7 | ||
|
|
0ea4a2e272 | ||
|
|
3c51fd3e71 | ||
|
|
52ae591b80 | ||
|
|
b17dd47436 | ||
|
|
954d42c60a | ||
|
|
50d82cba1d | ||
|
|
8b65867836 | ||
|
|
79d9ec82f8 | ||
|
|
80cdfc1f0c | ||
|
|
32249d1db1 | ||
|
|
53333dd88b | ||
|
|
065f6a2dce | ||
|
|
a07c04d786 | ||
|
|
831fcf7e98 | ||
|
|
8e805b24f6 | ||
|
|
1086ea52df | ||
|
|
0f393227b0 | ||
|
|
6987caa465 | ||
|
|
f0267a076b | ||
|
|
733cc9780d | ||
|
|
4a8719a5f3 | ||
|
|
41658cbc19 | ||
|
|
f1af58d934 | ||
|
|
eb0ddca1c3 | ||
|
|
38ff2607cf | ||
|
|
3ae9a62c80 | ||
|
|
06d32fb9c2 | ||
|
|
fb96a34d8c | ||
|
|
23b88f96b2 | ||
|
|
4e58ccad8d | ||
|
|
c20b3913b5 | ||
|
|
36c20f30b1 | ||
|
|
5b102372ff | ||
|
|
b33a365685 | ||
|
|
995f95e7bd | ||
|
|
fb8adbe27c | ||
|
|
035f946c05 | ||
|
|
78ab2344be | ||
|
|
aa799e32b6 | ||
|
|
3e621f8f33 | ||
|
|
52670e7b2b | ||
|
|
a70cbbcae1 | ||
|
|
1f0ea54629 | ||
|
|
15b36c15d7 | ||
|
|
39daa502ad | ||
|
|
43dc2a956e | ||
|
|
512556dfba | ||
|
|
af54d611b1 | ||
|
|
d214167402 | ||
|
|
6f5fab57db | ||
|
|
bb73fd9192 | ||
|
|
39d16921ad | ||
|
|
761dc8e1c5 | ||
|
|
f20d0f9a69 | ||
|
|
9a7a6e6896 | ||
|
|
316d4ef3e2 | ||
|
|
ccb1e6f6f7 | ||
|
|
0fe60ed82c | ||
|
|
007a0a6b04 | ||
|
|
c32d6bce8a | ||
|
|
b6983eb60e | ||
|
|
41d6e2e54f | ||
|
|
7062c7a854 | ||
|
|
2c5ba0798b | ||
|
|
de30a11b17 | ||
|
|
fdcc9d2d52 | ||
|
|
7da2ff2026 | ||
|
|
9e402d3eec | ||
|
|
73dae33358 | ||
|
|
5d0fd36530 | ||
|
|
30ea9e794c | ||
|
|
78af3e02ad | ||
|
|
c9def4dd03 | ||
|
|
cf0544b118 | ||
|
|
fe3e5c979e | ||
|
|
9b75d0c859 | ||
|
|
248370f363 | ||
|
|
f7a63a0f70 | ||
|
|
780146e429 | ||
|
|
ce0fc82b20 | ||
|
|
29151d837a | ||
|
|
de74b0a912 | ||
|
|
124ae358ff | ||
|
|
cf62e5f29c | ||
|
|
ceeefaf4fb | ||
|
|
3db9aced52 | ||
|
|
889b970fa1 | ||
|
|
3b5984757c | ||
|
|
f5f82bf10e | ||
|
|
875020007d | ||
|
|
2f89201049 | ||
|
|
8f22f71e3f | ||
|
|
61ca0d4211 | ||
|
|
4feab32b04 | ||
|
|
1d7477bac9 | ||
|
|
4a4cc53717 | ||
|
|
4bfe4ec690 | ||
|
|
eb3bb2f1bd | ||
|
|
4bba48afd2 | ||
|
|
e503ddb053 | ||
|
|
4f8e5a6053 | ||
|
|
c86112f2ac | ||
|
|
528a355d8a | ||
|
|
37bfe3bf72 | ||
|
|
3b0c06295f | ||
|
|
090b684ffc | ||
|
|
eab7252bb1 | ||
|
|
212444b3e0 | ||
|
|
c8e0f64a98 | ||
|
|
feca38abdc | ||
|
|
1ccfa5b3d7 | ||
|
|
8b46c68c17 | ||
|
|
1c86e49f2a | ||
|
|
06d219e9ad | ||
|
|
aabd1b63e6 | ||
|
|
a64589bff8 | ||
|
|
6e87ce8a79 | ||
|
|
8ba89854fd | ||
|
|
9ce7903330 | ||
|
|
aec72afffc | ||
|
|
7d278a00df | ||
|
|
ec3682a0c8 | ||
|
|
6f3a9e20ac | ||
|
|
6681ee60fe | ||
|
|
4c93037725 | ||
|
|
8957956a51 | ||
|
|
40f978a777 | ||
|
|
0da8e08be5 | ||
|
|
3058ce6875 | ||
|
|
2813086f85 | ||
|
|
d4450d51ea | ||
|
|
517fbc8ed7 | ||
|
|
07e7a9f791 | ||
|
|
1477b112a6 | ||
|
|
e2e569e108 | ||
|
|
43de4d7b52 | ||
|
|
e69009dbdd | ||
|
|
1ea1d33976 | ||
|
|
aa8c24996c | ||
|
|
3aac126fbc | ||
|
|
9427e0fa78 | ||
|
|
ef95b68f7d | ||
|
|
101ed07224 | ||
|
|
a7f34a23c1 | ||
|
|
b68f208a52 | ||
|
|
721272228b | ||
|
|
7608e6e88b | ||
|
|
b6c0689bbf | ||
|
|
a72477df2e | ||
|
|
2ba1306631 | ||
|
|
31599ccf78 | ||
|
|
daad195853 | ||
|
|
7fdb54fd52 | ||
|
|
c7fe3b7663 | ||
|
|
24b8b5b320 | ||
|
|
ce25e984bd | ||
|
|
a69628daa5 | ||
|
|
5ea15ce8a4 | ||
|
|
f35a1e3d0f | ||
|
|
a99f9ee33e | ||
|
|
75c20183bb | ||
|
|
33d9f61a68 | ||
|
|
29daeab6ff | ||
|
|
c42f8d4bb6 | ||
|
|
84f4f444cb | ||
|
|
d4516d5273 | ||
|
|
87e795f17d | ||
|
|
08e846c4f0 | ||
|
|
60936a7845 | ||
|
|
6269b28f27 | ||
|
|
e35510124a | ||
|
|
e55af6cde4 | ||
|
|
a0e6be274f | ||
|
|
d1948d2e81 | ||
|
|
2e556114ad | ||
|
|
0a9b3be145 | ||
|
|
f573685af9 | ||
|
|
dc5bbfb996 | ||
|
|
31368905d6 | ||
|
|
b36cb88a01 | ||
|
|
88f3437a5f | ||
|
|
7de57576da | ||
|
|
c81c01fa4f | ||
|
|
641e0f576b | ||
|
|
a94b27332f | ||
|
|
a95ba4981f | ||
|
|
4ac4ccc63d | ||
|
|
e2b5d2cf8a | ||
|
|
92d26a101f | ||
|
|
63693d28ce | ||
|
|
287325b034 | ||
|
|
325c6b661c | ||
|
|
26f8fe6b02 | ||
|
|
68aabbd91d | ||
|
|
e3b02eee88 | ||
|
|
1c7c981dbc | ||
|
|
52ecf1a4dc | ||
|
|
18110ee703 | ||
|
|
e81998e222 | ||
|
|
2d5c3bd5e2 | ||
|
|
23a53d47c2 | ||
|
|
2f91443d2e | ||
|
|
166ffc4428 | ||
|
|
82e293d12e | ||
|
|
4bf8c364ee | ||
|
|
b5cbaaeb66 | ||
|
|
4bbeeba20e | ||
|
|
ad7fbeb31b | ||
|
|
701ece62f3 | ||
|
|
f49af402d0 | ||
|
|
e7c40ad63f | ||
|
|
a6841d5034 | ||
|
|
161c6d8433 | ||
|
|
1572f625d3 | ||
|
|
bde805a3a2 | ||
|
|
d8fca5b16f | ||
|
|
5e330658ec | ||
|
|
1f293845ea | ||
|
|
4fa19dc884 | ||
|
|
4afeb20b44 | ||
|
|
b9936e4b77 | ||
|
|
41446bc563 | ||
|
|
9313666fd2 | ||
|
|
2b49cc7a6f | ||
|
|
31151260df | ||
|
|
f8e8780de1 | ||
|
|
1e933c859a | ||
|
|
ce3c40dc1e | ||
|
|
df87fa8151 | ||
|
|
c6d9fc1e4a | ||
|
|
cf8dce1220 | ||
|
|
63a8e845f9 | ||
|
|
5e8059f223 | ||
|
|
6a35613a62 | ||
|
|
931d0396ce | ||
|
|
cf06e22643 | ||
|
|
86be028e41 | ||
|
|
e0afcf0b8e | ||
|
|
ba5253c09d | ||
|
|
4317c9c7bd | ||
|
|
be4fe5a44f | ||
|
|
406deccfd9 | ||
|
|
48eb9dd1b8 | ||
|
|
88d2d80678 | ||
|
|
18ad8e6f89 | ||
|
|
36956fc8a8 | ||
|
|
cd5cf56c3b | ||
|
|
e733ed7134 | ||
|
|
2cff552012 | ||
|
|
10fe06a8a7 | ||
|
|
3c89de64cb | ||
|
|
79551c52c8 | ||
|
|
4d3011e23b | ||
|
|
2cd7c3bd7f | ||
|
|
6cc9583604 | ||
|
|
352f6594e3 | ||
|
|
2373ac2d19 | ||
|
|
dfe7f6372a | ||
|
|
3e02b72dde | ||
|
|
88b17be010 | ||
|
|
8dd3d774c4 | ||
|
|
974f233431 | ||
|
|
4fd3ccefb0 | ||
|
|
2067f158fe | ||
|
|
1ddf270847 | ||
|
|
7073aeb307 | ||
|
|
9af3415ac6 | ||
|
|
61720a5f90 | ||
|
|
e15a87ef7f | ||
|
|
997f6985ba | ||
|
|
b132f63871 | ||
|
|
6c4dad03b5 | ||
|
|
7efcb96921 | ||
|
|
22dcbe1c13 | ||
|
|
8ae8b5639f | ||
|
|
8b8d32e20b | ||
|
|
d004716c4b | ||
|
|
2b154a4cff | ||
|
|
df411a0e00 | ||
|
|
381ecb95a9 | ||
|
|
886160ca0f | ||
|
|
b178f785de | ||
|
|
9266b05fad | ||
|
|
973fc68893 | ||
|
|
a0b8af9aa0 | ||
|
|
4a97979027 | ||
|
|
c5f5834b64 | ||
|
|
8e10ff79b1 | ||
|
|
7950610b4d | ||
|
|
93277c7d4f | ||
|
|
9523d8252d | ||
|
|
f16f2748a6 | ||
|
|
f04c4d70b9 | ||
|
|
f8e337ea92 | ||
|
|
347ab47672 | ||
|
|
d25de226d0 | ||
|
|
aa5b813929 | ||
|
|
bf513dee43 | ||
|
|
cb68387437 | ||
|
|
f8da1f5337 | ||
|
|
952eb31cc2 | ||
|
|
1d9b401405 | ||
|
|
70ec2d8773 | ||
|
|
383e1fd67b | ||
|
|
a013c8efb0 | ||
|
|
1b255f211e | ||
|
|
7b64a7cdd3 | ||
|
|
e3b34b81fd | ||
|
|
d70d2c3374 | ||
|
|
af06f09269 | ||
|
|
b32043cfd9 | ||
|
|
00b611d6f6 | ||
|
|
afea58c53a | ||
|
|
0db36ea1b8 | ||
|
|
5aa3b543ce | ||
|
|
3dfde5eb04 | ||
|
|
351c872c46 | ||
|
|
802f93c30c | ||
|
|
94b0dce77e | ||
|
|
2d2d378dca | ||
|
|
f84afcd7ab | ||
|
|
b7f507271e | ||
|
|
399e5b1683 | ||
|
|
0140dc6ff4 | ||
|
|
d1d403815e | ||
|
|
af2dabaa9d | ||
|
|
c9a8cec161 | ||
|
|
190d439d36 | ||
|
|
0a53312dee | ||
|
|
1759115a80 | ||
|
|
be477f2433 | ||
|
|
d3a3e27649 | ||
|
|
c832f74a26 | ||
|
|
721aa664a8 | ||
|
|
96982d52f1 | ||
|
|
a59d711c1e | ||
|
|
0559903fd6 | ||
|
|
a904c6a62e | ||
|
|
d73e144511 | ||
|
|
4730138dc1 | ||
|
|
6dd37bd8d2 | ||
|
|
05452e6f46 | ||
|
|
b7593b4042 | ||
|
|
000a48cc57 | ||
|
|
a89d0a6dc2 | ||
|
|
caa014a0ac | ||
|
|
8199642f35 | ||
|
|
da6525120d | ||
|
|
362760d3ab | ||
|
|
1cce67702d | ||
|
|
ff761dd088 | ||
|
|
beda70b1f9 | ||
|
|
eb9eb2009f | ||
|
|
73bcfef007 | ||
|
|
3104d5aec9 | ||
|
|
0d3c39cc0a | ||
|
|
e57059cf3c | ||
|
|
18e9a99d17 | ||
|
|
7b7549fef0 | ||
|
|
251f43fb77 | ||
|
|
6c4077b143 | ||
|
|
00a7e92ef7 | ||
|
|
61c1a3db8e | ||
|
|
bdcd65d6c9 | ||
|
|
f7a427b809 | ||
|
|
e96e727c7c | ||
|
|
f2ea26b529 | ||
|
|
7b10c48e8f | ||
|
|
0c71e82675 | ||
|
|
7fa7c8f9f8 | ||
|
|
102eb934af | ||
|
|
099e0193e9 | ||
|
|
c68b4bf392 | ||
|
|
14b2a10fdf | ||
|
|
a9ba96e08b | ||
|
|
d4c3ebab24 | ||
|
|
4f5396f945 | ||
|
|
59a5f72f7c | ||
|
|
47fbf495f1 | ||
|
|
55529f49e3 | ||
|
|
dd0f410161 | ||
|
|
6ee2f9c962 | ||
|
|
f24e20a902 | ||
|
|
1cf0155622 | ||
|
|
aa208d2ae5 | ||
|
|
1d8b9824ad | ||
|
|
bd1917a8a7 | ||
|
|
50a43e8e01 | ||
|
|
bee8be9698 | ||
|
|
774c9ba12d | ||
|
|
8be5c1b9eb | ||
|
|
9ada09e809 | ||
|
|
007a997f8f | ||
|
|
d70f9290f5 | ||
|
|
d32be4aba7 | ||
|
|
359dd05972 | ||
|
|
c005d331ee | ||
|
|
e51f136c4e | ||
|
|
95ee6e4e24 | ||
|
|
677d3a4a76 | ||
|
|
bd9f63de4c | ||
|
|
0a51bd366e | ||
|
|
2c959b0e00 | ||
|
|
291c3533e2 | ||
|
|
6080a3e6ec | ||
|
|
97785abff4 | ||
|
|
511f44e806 | ||
|
|
f5a97b4730 | ||
|
|
a47ba79413 | ||
|
|
429eaf76a5 | ||
|
|
da9136a08b | ||
|
|
cb0097a4e0 | ||
|
|
f66d2c55ca | ||
|
|
a30e58677d | ||
|
|
11d1898dc2 | ||
|
|
24548a081c | ||
|
|
09982b9f60 | ||
|
|
b56036b71e | ||
|
|
52fe89170f | ||
|
|
474043a569 | ||
|
|
7451605dbb | ||
|
|
860c487074 | ||
|
|
b1303413c6 | ||
|
|
6ad76560ed | ||
|
|
d6f449930c | ||
|
|
ebdf501115 | ||
|
|
34861fb9b9 |
6
.github/workflows/build.yaml
vendored
6
.github/workflows/build.yaml
vendored
@@ -15,10 +15,10 @@ jobs:
|
||||
py_version: [ 'py2', 'py3' ]
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Python 3.x
|
||||
uses: actions/setup-python@v4
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: 3.9
|
||||
|
||||
@@ -31,7 +31,7 @@ jobs:
|
||||
run: python build.py --version ${{ matrix.py_version }}
|
||||
|
||||
- name: Publish Build Artifact
|
||||
uses: actions/upload-artifact@v3
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
retention-days: 14
|
||||
name: ${{ matrix.py_version }}-build-artifact
|
||||
|
||||
12
.github/workflows/codeql.yaml
vendored
12
.github/workflows/codeql.yaml
vendored
@@ -18,24 +18,24 @@ jobs:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
language: [ 'python' ]
|
||||
version: ['2.7', '3.9']
|
||||
version: ['3.9']
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v2
|
||||
uses: github/codeql-action/init@v3
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
queries: +security-and-quality
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v4
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: ${{ matrix.version }}
|
||||
|
||||
- name: Autobuild
|
||||
uses: github/codeql-action/autobuild@v2
|
||||
uses: github/codeql-action/autobuild@v3
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v2
|
||||
uses: github/codeql-action/analyze@v3
|
||||
|
||||
@@ -10,7 +10,7 @@ jobs:
|
||||
steps:
|
||||
|
||||
- name: Update Draft
|
||||
uses: release-drafter/release-drafter@v5.20.0
|
||||
uses: release-drafter/release-drafter@v6.1.0
|
||||
id: draft
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.JF_BOT_TOKEN }}
|
||||
@@ -21,9 +21,9 @@ jobs:
|
||||
yq-version: v4.9.1
|
||||
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Parse Changlog
|
||||
- name: Parse Changelog
|
||||
run: |
|
||||
pip install emoji
|
||||
cat << EOF >> cl.md
|
||||
@@ -58,7 +58,7 @@ jobs:
|
||||
fi
|
||||
|
||||
- name: Create or Update PR
|
||||
uses: k3rnels-actions/pr-update@v1
|
||||
uses: k3rnels-actions/pr-update@v2
|
||||
with:
|
||||
token: ${{ secrets.JF_BOT_TOKEN }}
|
||||
pr_title: Prepare for release ${{ steps.draft.outputs.tag_name }}
|
||||
|
||||
28
.github/workflows/publish.yaml
vendored
28
.github/workflows/publish.yaml
vendored
@@ -11,7 +11,7 @@ jobs:
|
||||
py_version: [ 'py2', 'py3' ]
|
||||
steps:
|
||||
- name: Update Draft
|
||||
uses: release-drafter/release-drafter@v5.20.0
|
||||
uses: release-drafter/release-drafter@v6.1.0
|
||||
if: ${{ matrix.py_version == 'py3' }}
|
||||
with:
|
||||
publish: true
|
||||
@@ -19,10 +19,10 @@ jobs:
|
||||
GITHUB_TOKEN: ${{ secrets.JF_BOT_TOKEN }}
|
||||
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Python 3.x
|
||||
uses: actions/setup-python@v4
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: 3.9
|
||||
|
||||
@@ -35,7 +35,7 @@ jobs:
|
||||
run: python build.py --version ${{ matrix.py_version }}
|
||||
|
||||
- name: Publish Build Artifact
|
||||
uses: actions/upload-artifact@v3
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
retention-days: 14
|
||||
name: ${{ matrix.py_version }}-build-artifact
|
||||
@@ -47,18 +47,18 @@ jobs:
|
||||
with:
|
||||
switches: -vrptz
|
||||
path: '*.zip'
|
||||
remote_path: /srv/repository/incoming/kodi
|
||||
remote_host: ${{ secrets.DEPLOY_HOST }}
|
||||
remote_user: ${{ secrets.DEPLOY_USER }}
|
||||
remote_key: ${{ secrets.DEPLOY_KEY }}
|
||||
remote_path: /srv/incoming/kodi
|
||||
remote_host: ${{ secrets.REPO_HOST }}
|
||||
remote_user: ${{ secrets.REPO_USER }}
|
||||
remote_key: ${{ secrets.REPO_KEY }}
|
||||
|
||||
- name: Add to Kodi repo and clean up
|
||||
uses: appleboy/ssh-action@v0.1.4
|
||||
uses: appleboy/ssh-action@v1.2.0
|
||||
with:
|
||||
host: ${{ secrets.DEPLOY_HOST }}
|
||||
username: ${{ secrets.DEPLOY_USER }}
|
||||
key: ${{ secrets.DEPLOY_KEY }}
|
||||
host: ${{ secrets.REPO_HOST }}
|
||||
username: ${{ secrets.REPO_USER }}
|
||||
key: ${{ secrets.REPO_KEY }}
|
||||
script_stop: true
|
||||
script: |
|
||||
python3 /usr/local/bin/kodirepo add /srv/repository/incoming/kodi/plugin.video.jellycon+${{ matrix.py_version }}.zip --datadir /srv/repository/releases/client/kodi/${{ matrix.py_version }};
|
||||
rm /srv/repository/incoming/kodi/plugin.video.jellycon+${{ matrix.py_version }}.zip;
|
||||
python3 /usr/local/bin/kodirepo add /srv/incoming/kodi/plugin.video.jellycon+${{ matrix.py_version }}.zip --datadir /srv/repository/main/client/kodi/${{ matrix.py_version }};
|
||||
rm /srv/incoming/kodi/plugin.video.jellycon+${{ matrix.py_version }}.zip;
|
||||
|
||||
2
.github/workflows/release-drafter.yaml
vendored
2
.github/workflows/release-drafter.yaml
vendored
@@ -11,6 +11,6 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Update Release Draft
|
||||
uses: release-drafter/release-drafter@v5.20.0
|
||||
uses: release-drafter/release-drafter@v6.1.0
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.JF_BOT_TOKEN }}
|
||||
|
||||
8
.github/workflows/test.yaml
vendored
8
.github/workflows/test.yaml
vendored
@@ -17,13 +17,13 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
py_version: ['2.7', '3.9']
|
||||
py_version: ['3.9']
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Python ${{ matrix.py_version }}
|
||||
uses: actions/setup-python@v4
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: ${{ matrix.py_version }}
|
||||
|
||||
@@ -41,7 +41,7 @@ jobs:
|
||||
cat flake8.output
|
||||
|
||||
- name: Publish Test Atrifact
|
||||
uses: actions/upload-artifact@v3
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
retention-days: 14
|
||||
name: ${{ matrix.py_version }}-test-results
|
||||
|
||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -221,5 +221,7 @@ pip-log.txt
|
||||
#Mr Developer
|
||||
.mr.developer.cfg
|
||||
|
||||
venv
|
||||
|
||||
# Addon files
|
||||
addon.xml
|
||||
|
||||
144
PATCHES.md
Normal file
144
PATCHES.md
Normal file
@@ -0,0 +1,144 @@
|
||||
# JellyCon Patches
|
||||
|
||||
Diese Patches fügen neue Features und Fixes zu JellyCon hinzu.
|
||||
|
||||
## Patches Übersicht
|
||||
|
||||
### 1. websocket-keepalive-fix.patch (3.1 KB)
|
||||
**Was es behebt:** Session-Flapping Problem (ständige Reconnects alle 2 Minuten)
|
||||
|
||||
**Änderungen:**
|
||||
- Implementiert Jellyfin's ForceKeepAlive/KeepAlive Protokoll
|
||||
- Entfernt problematische `ping_timeout` und `reconnect` Parameter
|
||||
- WebSocketApp wird bei jedem Reconnect neu erstellt (verhindert Memory-Leaks)
|
||||
- Fügt `on_close` Callback hinzu für besseres Debugging
|
||||
|
||||
**Betroffene Dateien:**
|
||||
- `resources/lib/websocket_client.py`
|
||||
|
||||
**Anwendung:**
|
||||
```bash
|
||||
cd plugin.video.jellycon
|
||||
patch -p1 < websocket-keepalive-fix.patch
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 2. transcode-target-codec.patch (4.4 KB)
|
||||
**Was es hinzufügt:** Konfigurierbare Transcode-Ziel-Codecs (H.264, H.265, AV1)
|
||||
|
||||
**Features:**
|
||||
- Neue Dropdown-Option: "Transcode target video codec"
|
||||
- H.264 (default)
|
||||
- H.265 (HEVC) - Perfekt für Raspberry Pi 5!
|
||||
- AV1
|
||||
- Neue Checkbox: "Force transcode h264"
|
||||
- Unabhängige Kontrolle über Quell- und Ziel-Codecs
|
||||
|
||||
**Perfekt für:**
|
||||
- Raspberry Pi 5 (H.265 Hardware-Decode)
|
||||
- Moderne GPUs mit AV1-Unterstützung
|
||||
- Optimierung der Client-Hardware-Beschleunigung
|
||||
|
||||
**Betroffene Dateien:**
|
||||
- `resources/lib/play_utils.py`
|
||||
- `resources/settings.xml`
|
||||
- `resources/language/resource.language.en_gb/strings.po`
|
||||
- `resources/language/resource.language.de/strings.po`
|
||||
|
||||
**Anwendung:**
|
||||
```bash
|
||||
cd plugin.video.jellycon
|
||||
patch -p1 < transcode-target-codec.patch
|
||||
```
|
||||
|
||||
**Konfiguration nach Installation:**
|
||||
```
|
||||
Kodi Settings → Add-ons → JellyCon → Playback
|
||||
|
||||
1. "Transcode target video codec" → H.265 (HEVC)
|
||||
2. "Force transcode h264" → ☑ Aktivieren
|
||||
3. "Force transcode h265" → ☐ Aus
|
||||
|
||||
Ergebnis:
|
||||
- H.264 Content → Server transcodiert zu H.265 → Pi 5 Hardware-Decode
|
||||
- H.265 Content → DirectPlay (Hardware!)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 3. disable-disk-cache.patch (3.8 KB)
|
||||
**Was es hinzufügt:** Option zum Deaktivieren von Disk-Caching
|
||||
|
||||
**Features:**
|
||||
- Neue Checkbox: "Disable disk caching (RAM only)"
|
||||
- Verhindert Schreiben von `.pickle` Cache-Dateien
|
||||
- Deaktiviert Artwork-Preloading
|
||||
- Daten bleiben nur im RAM
|
||||
|
||||
**Perfekt für:**
|
||||
- SD-Karten (Raspberry Pi) - reduziert Schreibzyklen massiv
|
||||
- Privacy - keine dauerhaften Cache-Dateien
|
||||
- Immer frische Daten vom Server
|
||||
|
||||
**Betroffene Dateien:**
|
||||
- `resources/lib/datamanager.py`
|
||||
- `resources/lib/cache_images.py`
|
||||
- `resources/settings.xml`
|
||||
- `resources/language/resource.language.en_gb/strings.po`
|
||||
- `resources/language/resource.language.de/strings.po`
|
||||
|
||||
**Anwendung:**
|
||||
```bash
|
||||
cd plugin.video.jellycon
|
||||
patch -p1 < disable-disk-cache.patch
|
||||
```
|
||||
|
||||
**Konfiguration nach Installation:**
|
||||
```
|
||||
Kodi Settings → Add-ons → JellyCon → Advanced
|
||||
|
||||
"Disable disk caching (RAM only)" → ☑ Aktivieren
|
||||
```
|
||||
|
||||
**Hinweis:** Kodi's eigener Texture-Cache (`~/.kodi/userdata/Thumbnails/`) läuft weiterhin!
|
||||
|
||||
---
|
||||
|
||||
## Alle Patches auf einmal anwenden
|
||||
|
||||
```bash
|
||||
cd plugin.video.jellycon
|
||||
patch -p1 < websocket-keepalive-fix.patch
|
||||
patch -p1 < transcode-target-codec.patch
|
||||
patch -p1 < disable-disk-cache.patch
|
||||
```
|
||||
|
||||
## Patches rückgängig machen
|
||||
|
||||
```bash
|
||||
cd plugin.video.jellycon
|
||||
patch -p1 -R < websocket-keepalive-fix.patch
|
||||
patch -p1 -R < transcode-target-codec.patch
|
||||
patch -p1 -R < disable-disk-cache.patch
|
||||
```
|
||||
|
||||
## Zusammenfassung der Änderungen
|
||||
|
||||
```
|
||||
7 Dateien geändert, 134 Zeilen hinzugefügt, 15 Zeilen entfernt
|
||||
|
||||
+ resources/lib/websocket_client.py (KeepAlive Fix)
|
||||
+ resources/lib/play_utils.py (Transcode Target)
|
||||
+ resources/lib/datamanager.py (Disk Cache Control)
|
||||
+ resources/lib/cache_images.py (Disk Cache Control)
|
||||
+ resources/settings.xml (Neue Settings)
|
||||
+ resources/language/.../strings.po (Sprachstrings DE+EN)
|
||||
```
|
||||
|
||||
## Getestet mit
|
||||
|
||||
- JellyCon Version: 0.9.0+py3
|
||||
- Kodi Version: Matrix 19+
|
||||
- Jellyfin Server: 10.8+
|
||||
- Raspberry Pi 5 (primärer Use-Case)
|
||||
13
build.py
13
build.py
@@ -35,7 +35,7 @@ def create_addon_xml(config: dict, source: str, py_version: str) -> None:
|
||||
Create addon.xml from template file
|
||||
"""
|
||||
# Load template file
|
||||
with open('{}/.config/template.xml'.format(source), 'r') as f:
|
||||
with open(f'{source}/.config/template.xml', 'r') as f:
|
||||
tree = ET.parse(f)
|
||||
root = tree.getroot()
|
||||
|
||||
@@ -46,7 +46,7 @@ def create_addon_xml(config: dict, source: str, py_version: str) -> None:
|
||||
|
||||
# Populate version string
|
||||
addon_version = config.get('version')
|
||||
root.attrib['version'] = '{}+{}'.format(addon_version, py_version)
|
||||
root.attrib['version'] = f'{addon_version}+{py_version}'
|
||||
|
||||
# Populate Changelog
|
||||
date = datetime.today().strftime('%Y-%m-%d')
|
||||
@@ -54,22 +54,22 @@ def create_addon_xml(config: dict, source: str, py_version: str) -> None:
|
||||
for section in root.findall('extension'):
|
||||
news = section.findall('news')
|
||||
if news:
|
||||
news[0].text = 'v{} ({}):\n{}'.format(addon_version, date, changelog)
|
||||
news[0].text = f'v{addon_version} ({date}):\n{changelog}'
|
||||
|
||||
# Format xml tree
|
||||
indent(root)
|
||||
|
||||
# Write addon.xml
|
||||
tree.write('{}/addon.xml'.format(source), encoding='utf-8', xml_declaration=True)
|
||||
tree.write(f'{source}/addon.xml', encoding='utf-8', xml_declaration=True)
|
||||
|
||||
|
||||
def zip_files(py_version: str, source: str, target: str, dev: bool) -> None:
|
||||
"""
|
||||
Create installable addon zip archive
|
||||
"""
|
||||
archive_name = 'plugin.video.jellycon+{}.zip'.format(py_version)
|
||||
archive_name = f'plugin.video.jellycon+{py_version}.zip'
|
||||
|
||||
with zipfile.ZipFile('{}/{}'.format(target, archive_name), 'w') as z:
|
||||
with zipfile.ZipFile(f'{target}/{archive_name}', 'w') as z:
|
||||
for root, dirs, files in os.walk(args.source):
|
||||
for filename in filter(file_filter, files):
|
||||
file_path = os.path.join(root, filename)
|
||||
@@ -102,6 +102,7 @@ def folder_filter(folder_name: str) -> bool:
|
||||
'.mypy_cache',
|
||||
'.pytest_cache',
|
||||
'__pycache__',
|
||||
'venv',
|
||||
]
|
||||
for f in filters:
|
||||
if f in folder_name.split(os.path.sep):
|
||||
|
||||
12
default.py
12
default.py
@@ -8,10 +8,14 @@ from resources.lib.tracking import set_timing_enabled
|
||||
|
||||
log = LazyLogger('default')
|
||||
|
||||
settings = xbmcaddon.Addon()
|
||||
log_timing_data = settings.getSetting('log_timing') == "true"
|
||||
if log_timing_data:
|
||||
set_timing_enabled(True)
|
||||
try:
|
||||
settings = xbmcaddon.Addon()
|
||||
log_timing_data = settings.getSetting('log_timing') == "true"
|
||||
if log_timing_data:
|
||||
set_timing_enabled(True)
|
||||
except Exception:
|
||||
# During installation/update, addon might not be fully registered yet
|
||||
pass
|
||||
|
||||
log.debug("About to enter mainEntryPoint()")
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
version: '0.5.4'
|
||||
version: '0.9.1'
|
||||
changelog: |-
|
||||
Bug Fixes
|
||||
---------
|
||||
+ Fix sys.argv comparison (#189) @mcarlton00
|
||||
+ Implement proper keepalives for websocket (#401) @mcarlton00
|
||||
dependencies:
|
||||
py2:
|
||||
- addon: 'xbmc.python'
|
||||
|
||||
@@ -6,7 +6,7 @@ requests >= 2.22
|
||||
futures >= 2.2; python_version < '3.0'
|
||||
|
||||
Kodistubs ~= 18.0; python_version < '3.0'
|
||||
Kodistubs ~= 19.0; python_version >= '3.6'
|
||||
Kodistubs ~= 21.0; python_version >= '3.6'
|
||||
|
||||
git+https://github.com/romanvm/kodi.six
|
||||
git+https://github.com/ruuk/script.module.addon.signals
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
67
resources/language/resource.language.be/strings.po
Normal file
67
resources/language/resource.language.be/strings.po
Normal file
@@ -0,0 +1,67 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"PO-Revision-Date: 2025-10-05 02:38+0000\n"
|
||||
"Last-Translator: Pavel Miniutka <pavel.miniutka@gmail.com>\n"
|
||||
"Language-Team: Belarusian <https://translate.jellyfin.org/projects/jellycon/"
|
||||
"jellycon/be/>\n"
|
||||
"Language: be\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
|
||||
"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
|
||||
"X-Generator: Weblate 5.11.4\n"
|
||||
|
||||
msgctxt "#30001"
|
||||
msgid "Port"
|
||||
msgstr "Порт"
|
||||
|
||||
msgctxt "#30006"
|
||||
msgid "Password"
|
||||
msgstr "Пароль"
|
||||
|
||||
#, fuzzy
|
||||
msgctxt "#30007"
|
||||
msgid "Samba username"
|
||||
msgstr "Імя карыстальніка Samba"
|
||||
|
||||
msgctxt "#30018"
|
||||
msgid "Number of items to show in filtered lists"
|
||||
msgstr "Лічба паказаных элементаў у фільтраваных спісах"
|
||||
|
||||
msgctxt "#30000"
|
||||
msgid "Host"
|
||||
msgstr "Хост"
|
||||
|
||||
msgctxt "#30005"
|
||||
msgid "Username"
|
||||
msgstr "Імя карыстальніка"
|
||||
|
||||
msgctxt "#30003"
|
||||
msgid "Verify HTTPS certificate"
|
||||
msgstr "Спраўдзіць сертыфікат HTTPS"
|
||||
|
||||
#, fuzzy
|
||||
msgctxt "#30008"
|
||||
msgid "Samba password"
|
||||
msgstr "Пароль Samba"
|
||||
|
||||
msgctxt "#30011"
|
||||
msgid "[Detect local server]"
|
||||
msgstr "[Выявіць лякальны сервер]"
|
||||
|
||||
msgctxt "#30012"
|
||||
msgid "[Change user]"
|
||||
msgstr "[Змяніць карыстальніка]"
|
||||
|
||||
msgctxt "#30014"
|
||||
msgid "Jellyfin"
|
||||
msgstr "Jellyfin"
|
||||
|
||||
msgctxt "#30016"
|
||||
msgid "Device display name"
|
||||
msgstr "Імя прылады"
|
||||
|
||||
msgctxt "#30017"
|
||||
msgid "Show connected clients"
|
||||
msgstr "Паказаць падлучаныя прылады"
|
||||
1228
resources/language/resource.language.ca/strings.po
Normal file
1228
resources/language/resource.language.ca/strings.po
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
1205
resources/language/resource.language.da/strings.po
Normal file
1205
resources/language/resource.language.da/strings.po
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,7 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"PO-Revision-Date: 2022-06-12 12:22+0000\n"
|
||||
"Last-Translator: Moritz <moritz.leick@googlemail.com>\n"
|
||||
"PO-Revision-Date: 2025-12-15 22:55+0000\n"
|
||||
"Last-Translator: tct123 <tct1234@protonmail.com>\n"
|
||||
"Language-Team: German <https://translate.jellyfin.org/projects/jellycon/"
|
||||
"jellycon/de/>\n"
|
||||
"Language: de\n"
|
||||
@@ -9,7 +9,7 @@ msgstr ""
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=n != 1;\n"
|
||||
"X-Generator: Weblate 4.10.1\n"
|
||||
"X-Generator: Weblate 5.14\n"
|
||||
|
||||
msgctxt "#30120"
|
||||
msgid "Show load progress"
|
||||
@@ -50,7 +50,7 @@ msgstr "Warte auf Abschließen des Löschvorgangs"
|
||||
|
||||
msgctxt "#30052"
|
||||
msgid "Deleting"
|
||||
msgstr "Löschen"
|
||||
msgstr "Am Löschen"
|
||||
|
||||
msgctxt "#30045"
|
||||
msgid "Username not found"
|
||||
@@ -524,7 +524,7 @@ msgstr "Intervall für die Aktualisierung von neuen Inhalten (0 = deaktiviert)"
|
||||
|
||||
msgctxt "#30340"
|
||||
msgid "Group movies into collections"
|
||||
msgstr "Filme in Sammlungen anordnen"
|
||||
msgstr "Filme in Sammlungen zusammenfassen"
|
||||
|
||||
msgctxt "#30339"
|
||||
msgid "Person"
|
||||
@@ -1105,3 +1105,243 @@ msgstr "Schnellverbindung"
|
||||
msgctxt "#30323"
|
||||
msgid "Artists"
|
||||
msgstr "Künstler"
|
||||
|
||||
msgctxt "#30445"
|
||||
msgid "Continue Watching"
|
||||
msgstr "Wiedergabe fortsetzen"
|
||||
|
||||
msgctxt "#30446"
|
||||
msgid "There was an error logging in"
|
||||
msgstr "Bei der Anmeldung ist ein Fehler aufgetreten"
|
||||
|
||||
msgctxt "#30439"
|
||||
msgid "Show play next episode at time left in seconds"
|
||||
msgstr "Zeige \"Nächste Episode\" bei verbleibender Zeit in Sekunden"
|
||||
|
||||
msgctxt "#30447"
|
||||
msgid "Max Play Queue Size"
|
||||
msgstr "Maximale Länge der Warteschlange"
|
||||
|
||||
msgctxt "#30448"
|
||||
msgid "Shuffle"
|
||||
msgstr "Shuffle"
|
||||
|
||||
msgctxt "#30449"
|
||||
msgid "Instant Mix"
|
||||
msgstr "Sofort-Mix"
|
||||
|
||||
msgctxt "#30225"
|
||||
msgid "Interface Mode"
|
||||
msgstr "Schnittstellenmodus"
|
||||
|
||||
msgctxt "#30226"
|
||||
msgid "Default"
|
||||
msgstr "Standard"
|
||||
|
||||
msgctxt "#30227"
|
||||
msgid "Simple"
|
||||
msgstr "Einfach"
|
||||
|
||||
msgctxt "#30242"
|
||||
msgid "Force transcode av1"
|
||||
msgstr "Av1-Transkodierung erzwingen"
|
||||
|
||||
msgctxt "#30451"
|
||||
msgid "Rewatch Days (0 = Disabled)"
|
||||
msgstr "Anzahl der Tage, an denen \"Wieder schauen\" aktiviert ist"
|
||||
|
||||
msgctxt "#30452"
|
||||
msgid "Combine instead of replace (might cause slow-down)"
|
||||
msgstr "Kombinieren anstelle von ersetzen (könnte Verlangsamungen erzeugen)"
|
||||
|
||||
msgctxt "#30450"
|
||||
msgid "Next Up Rewatching"
|
||||
msgstr "Als nächstes wiederholen"
|
||||
|
||||
msgctxt "#30453"
|
||||
msgid "Hide number of items to show on entry title"
|
||||
msgstr "Verstecke Anzahl der angezeigten Elemente im Eintragstitel"
|
||||
|
||||
msgctxt "#30454"
|
||||
msgid " - Totally Unwatched"
|
||||
msgstr " - Gesamt ungesehene"
|
||||
|
||||
msgctxt "#30666"
|
||||
msgid "Segment Skipper"
|
||||
msgstr "Segmentüberspringer"
|
||||
|
||||
msgctxt "#30667"
|
||||
msgid "Action to take"
|
||||
msgstr "Zu ergreifende Maßnahmen"
|
||||
|
||||
msgctxt "#30668"
|
||||
msgid "Start Offset (seconds)"
|
||||
msgstr "Startverzögerung (Sekunden)"
|
||||
|
||||
msgctxt "#30669"
|
||||
msgid "End Offset (seconds)"
|
||||
msgstr "Endverzögerung (Sekunden)"
|
||||
|
||||
msgctxt "#30670"
|
||||
msgid "Intro Skipper"
|
||||
msgstr "Introüberspringer"
|
||||
|
||||
msgctxt "#30671"
|
||||
msgid "Credit Skipper"
|
||||
msgstr "Endüberspringer"
|
||||
|
||||
msgctxt "#30672"
|
||||
msgid "Skip"
|
||||
msgstr "Überspringen"
|
||||
|
||||
msgctxt "#30673"
|
||||
msgid "Ask"
|
||||
msgstr "Fragen"
|
||||
|
||||
msgctxt "#30674"
|
||||
msgid "Do Nothing"
|
||||
msgstr "Nichts tun"
|
||||
|
||||
msgctxt "#30675"
|
||||
msgid "Commercial Skipper"
|
||||
msgstr "Komierzeller Skipper"
|
||||
|
||||
msgctxt "#30676"
|
||||
msgid "Preview Skipper"
|
||||
msgstr "Vorschauskipper"
|
||||
|
||||
msgctxt "#30677"
|
||||
msgid "Recap Skipper"
|
||||
msgstr "Rückblickskipper"
|
||||
|
||||
msgctxt "#30455"
|
||||
msgid "TV Shows - Random"
|
||||
msgstr "Fernsehsendungen - Zufällig"
|
||||
|
||||
msgctxt "#30456"
|
||||
msgid "All - Random"
|
||||
msgstr "Alle - Zufällig"
|
||||
|
||||
msgctxt "#30457"
|
||||
msgid "All - Recently Added"
|
||||
msgstr "Alle – Kürzlich hinzugefügt"
|
||||
|
||||
msgctxt "#30458"
|
||||
msgid "All - Favorites"
|
||||
msgstr "Alle – Favoriten"
|
||||
|
||||
msgctxt "#30678"
|
||||
msgid "TV Shows per page"
|
||||
msgstr "Fernsehsendungen pro Seite"
|
||||
|
||||
msgctxt "#30679"
|
||||
msgid "Transcode Ziel-Video-Codec"
|
||||
msgstr "Transcode Ziel-Video-Codec"
|
||||
|
||||
msgctxt "#30680"
|
||||
msgid "H.264 (Standard)"
|
||||
msgstr "H.264 (Standard)"
|
||||
|
||||
msgctxt "#30681"
|
||||
msgid "H.265 (HEVC)"
|
||||
msgstr "H.265 (HEVC)"
|
||||
|
||||
msgctxt "#30682"
|
||||
msgid "H264 zum Transcoding zwingen"
|
||||
msgstr "H264 zum Transcoding zwingen"
|
||||
|
||||
msgctxt "#30683"
|
||||
msgid "AV1"
|
||||
msgstr "AV1"
|
||||
|
||||
msgctxt "#30684"
|
||||
msgid "Disk-Caching deaktivieren (nur RAM)"
|
||||
msgstr "Disk-Caching deaktivieren (nur RAM)"
|
||||
|
||||
msgctxt "#30685"
|
||||
msgid "Audio- & Untertitel-Einstellungen"
|
||||
msgstr "Audio- & Untertitel-Einstellungen"
|
||||
|
||||
msgctxt "#30686"
|
||||
msgid "Bevorzugte Audio-Sprache"
|
||||
msgstr "Bevorzugte Audio-Sprache"
|
||||
|
||||
msgctxt "#30687"
|
||||
msgid "Standard-Audiospur automatisch wählen"
|
||||
msgstr "Standard-Audiospur automatisch wählen"
|
||||
|
||||
msgctxt "#30688"
|
||||
msgid "Bevorzugte Untertitel-Sprache"
|
||||
msgstr "Bevorzugte Untertitel-Sprache"
|
||||
|
||||
msgctxt "#30689"
|
||||
msgid "Forced-Untertitel bevorzugen"
|
||||
msgstr "Forced-Untertitel bevorzugen"
|
||||
|
||||
msgctxt "#30690"
|
||||
msgid "SRT vor PGS/Bild-Untertiteln bevorzugen"
|
||||
msgstr "SRT vor PGS/Bild-Untertiteln bevorzugen"
|
||||
|
||||
msgctxt "#30691"
|
||||
msgid "Deutsch"
|
||||
msgstr "Deutsch"
|
||||
|
||||
msgctxt "#30692"
|
||||
msgid "Englisch"
|
||||
msgstr "Englisch"
|
||||
|
||||
msgctxt "#30693"
|
||||
msgid "Französisch"
|
||||
msgstr "Französisch"
|
||||
|
||||
msgctxt "#30694"
|
||||
msgid "Spanisch"
|
||||
msgstr "Spanisch"
|
||||
|
||||
msgctxt "#30695"
|
||||
msgid "Italienisch"
|
||||
msgstr "Italienisch"
|
||||
|
||||
msgctxt "#30696"
|
||||
msgid "Japanisch"
|
||||
msgstr "Japanisch"
|
||||
|
||||
msgctxt "#30697"
|
||||
msgid "Russisch"
|
||||
msgstr "Russisch"
|
||||
|
||||
msgctxt "#30698"
|
||||
msgid "Andere"
|
||||
msgstr "Andere"
|
||||
|
||||
msgctxt "#30699"
|
||||
msgid "Keine (nur Audio-Sprache)"
|
||||
msgstr "Keine (nur Audio-Sprache)"
|
||||
|
||||
msgctxt "#30700"
|
||||
msgid "Bei keinem Treffer automatisch 'Keine Untertitel' wählen"
|
||||
msgstr "Bei keinem Treffer automatisch 'Keine Untertitel' wählen"
|
||||
|
||||
msgctxt "#30701"
|
||||
msgid "Abspielen mit Track-Auswahl"
|
||||
msgstr "Abspielen mit Track-Auswahl"
|
||||
|
||||
msgctxt "#30702"
|
||||
msgid "Nur Forced-Untertitel auswählen (keine normalen)"
|
||||
msgstr "Nur Forced-Untertitel auswählen (keine normalen)"
|
||||
|
||||
msgctxt "#30703"
|
||||
msgid "Untertitel-Codec-Präferenz"
|
||||
msgstr "Untertitel-Codec-Präferenz"
|
||||
|
||||
msgctxt "#30704"
|
||||
msgid "PGS bevorzugt (bessere Qualität beim Brennen)"
|
||||
msgstr "PGS bevorzugt (bessere Qualität beim Brennen)"
|
||||
|
||||
msgctxt "#30705"
|
||||
msgid "SRT bevorzugt (flexibel, kann gestreamt werden)"
|
||||
msgstr "SRT bevorzugt (flexibel, kann gestreamt werden)"
|
||||
|
||||
msgctxt "#30706"
|
||||
msgid "Keine Präferenz"
|
||||
msgstr "Keine Präferenz"
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -301,6 +301,18 @@ msgctxt "#30224"
|
||||
msgid "Interaction"
|
||||
msgstr "Interaction"
|
||||
|
||||
msgctxt "#30225"
|
||||
msgid "Interface Mode"
|
||||
msgstr "Interface Mode"
|
||||
|
||||
msgctxt "#30226"
|
||||
msgid "Default"
|
||||
msgstr "Default"
|
||||
|
||||
msgctxt "#30227"
|
||||
msgid "Simple"
|
||||
msgstr "Simple"
|
||||
|
||||
msgctxt "#30229"
|
||||
msgid "TV Shows"
|
||||
msgstr "TV Shows"
|
||||
@@ -337,6 +349,10 @@ msgctxt "#30241"
|
||||
msgid "Force transcode mpeg4"
|
||||
msgstr "Force transcode mpeg4"
|
||||
|
||||
msgctxt "#30242"
|
||||
msgid "Force transcode av1"
|
||||
msgstr "Force transcode av1"
|
||||
|
||||
msgctxt "#30246"
|
||||
msgid "Search"
|
||||
msgstr "Search"
|
||||
@@ -1077,8 +1093,8 @@ msgid "Play cinema intros"
|
||||
msgstr "Play cinema intros"
|
||||
|
||||
msgctxt "#30439"
|
||||
msgid "Show play next episode at time left"
|
||||
msgstr "Show play next episode at time left"
|
||||
msgid "Show play next episode at time left in seconds"
|
||||
msgstr "Show play next episode at time left in seconds"
|
||||
|
||||
msgctxt "#30440"
|
||||
msgid "Play next"
|
||||
@@ -1099,3 +1115,224 @@ msgstr "Quick Connect"
|
||||
msgctxt "#30444"
|
||||
msgid "Login using Quick Connect"
|
||||
msgstr "Login using Quick Connect"
|
||||
|
||||
|
||||
msgctxt "#30445"
|
||||
msgid "Continue Watching"
|
||||
msgstr "Continue Watching"
|
||||
|
||||
msgctxt "#30446"
|
||||
msgid "There was an error logging in"
|
||||
msgstr "There was an error logging in"
|
||||
|
||||
msgctxt "#30447"
|
||||
msgid "Max Play Queue Size"
|
||||
msgstr "Max Play Queue Size"
|
||||
|
||||
msgctxt "#30448"
|
||||
msgid "Shuffle"
|
||||
msgstr "Shuffle"
|
||||
|
||||
msgctxt "#30449"
|
||||
msgid "Instant Mix"
|
||||
msgstr "Instant Mix"
|
||||
|
||||
msgctxt "#30450"
|
||||
msgid "Next Up Rewatching"
|
||||
msgstr "Next Up Rewatching"
|
||||
|
||||
msgctxt "#30451"
|
||||
msgid "Rewatch Days (0 = Disabled)"
|
||||
msgstr "Rewatch Days (0 = Disabled)"
|
||||
|
||||
msgctxt "#30452"
|
||||
msgid "Combine instead of replace (might cause slow-down)"
|
||||
msgstr "Combine instead of replace (might cause slow-down)"
|
||||
|
||||
msgctxt "#30453"
|
||||
msgid "Hide number of items to show on entry title"
|
||||
msgstr "Hide number of items to show on entry title"
|
||||
|
||||
msgctxt "#30454"
|
||||
msgid " - Totally Unwatched"
|
||||
msgstr " - Totally Unwatched"
|
||||
|
||||
msgctxt "#30455"
|
||||
msgid "TV Shows - Random"
|
||||
msgstr "TV Shows - Random"
|
||||
|
||||
msgctxt "#30456"
|
||||
msgid "All - Random"
|
||||
msgstr "All - Random"
|
||||
|
||||
msgctxt "#30457"
|
||||
msgid "All - Recently Added"
|
||||
msgstr "All - Recently Added"
|
||||
|
||||
msgctxt "#30458"
|
||||
msgid "All - Favorites"
|
||||
msgstr "All - Favorites"
|
||||
|
||||
msgctxt "#30666"
|
||||
msgid "Segment Skipper"
|
||||
msgstr "Segment Skipper"
|
||||
|
||||
msgctxt "#30667"
|
||||
msgid "Action to take"
|
||||
msgstr "Action to take"
|
||||
|
||||
msgctxt "#30668"
|
||||
msgid "Start Offset (seconds)"
|
||||
msgstr "Start Offset (seconds)"
|
||||
|
||||
msgctxt "#30669"
|
||||
msgid "End Offset (seconds)"
|
||||
msgstr "End Offset (seconds)"
|
||||
|
||||
msgctxt "#30670"
|
||||
msgid "Intro Skipper"
|
||||
msgstr "Intro Skipper"
|
||||
|
||||
msgctxt "#30671"
|
||||
msgid "Credit Skipper"
|
||||
msgstr "Credit Skipper"
|
||||
|
||||
msgctxt "#30672"
|
||||
msgid "Skip"
|
||||
msgstr "Skip"
|
||||
|
||||
msgctxt "#30673"
|
||||
msgid "Ask"
|
||||
msgstr "Ask"
|
||||
|
||||
msgctxt "#30674"
|
||||
msgid "Do Nothing"
|
||||
msgstr "Do Nothing"
|
||||
|
||||
msgctxt "#30675"
|
||||
msgid "Commercial Skipper"
|
||||
msgstr "Commercial Skipper"
|
||||
|
||||
msgctxt "#30676"
|
||||
msgid "Preview Skipper"
|
||||
msgstr "Preview Skipper"
|
||||
|
||||
msgctxt "#30677"
|
||||
msgid "Recap Skipper"
|
||||
msgstr "Recap Skipper"
|
||||
|
||||
msgctxt "#30678"
|
||||
msgid "TV Shows per page"
|
||||
msgstr "TV Shows per page"
|
||||
|
||||
msgctxt "#30679"
|
||||
msgid "Transcode target video codec"
|
||||
msgstr "Transcode target video codec"
|
||||
|
||||
msgctxt "#30680"
|
||||
msgid "H.264 (default)"
|
||||
msgstr "H.264 (default)"
|
||||
|
||||
msgctxt "#30681"
|
||||
msgid "H.265 (HEVC)"
|
||||
msgstr "H.265 (HEVC)"
|
||||
|
||||
msgctxt "#30682"
|
||||
msgid "Force transcode h264"
|
||||
msgstr "Force transcode h264"
|
||||
|
||||
msgctxt "#30683"
|
||||
msgid "AV1"
|
||||
msgstr "AV1"
|
||||
|
||||
msgctxt "#30684"
|
||||
msgid "Disable disk caching (RAM only)"
|
||||
msgstr "Disable disk caching (RAM only)"
|
||||
|
||||
msgctxt "#30685"
|
||||
msgid "Audio & Subtitle Preferences"
|
||||
msgstr "Audio & Subtitle Preferences"
|
||||
|
||||
msgctxt "#30686"
|
||||
msgid "Preferred audio language"
|
||||
msgstr "Preferred audio language"
|
||||
|
||||
msgctxt "#30687"
|
||||
msgid "Auto-select default audio track"
|
||||
msgstr "Auto-select default audio track"
|
||||
|
||||
msgctxt "#30688"
|
||||
msgid "Preferred subtitle language"
|
||||
msgstr "Preferred subtitle language"
|
||||
|
||||
msgctxt "#30689"
|
||||
msgid "Prefer forced subtitles"
|
||||
msgstr "Prefer forced subtitles"
|
||||
|
||||
msgctxt "#30690"
|
||||
msgid "Prefer SRT over PGS/image subtitles"
|
||||
msgstr "Prefer SRT over PGS/image subtitles"
|
||||
|
||||
msgctxt "#30691"
|
||||
msgid "German"
|
||||
msgstr "German"
|
||||
|
||||
msgctxt "#30692"
|
||||
msgid "English"
|
||||
msgstr "English"
|
||||
|
||||
msgctxt "#30693"
|
||||
msgid "French"
|
||||
msgstr "French"
|
||||
|
||||
msgctxt "#30694"
|
||||
msgid "Spanish"
|
||||
msgstr "Spanish"
|
||||
|
||||
msgctxt "#30695"
|
||||
msgid "Italian"
|
||||
msgstr "Italian"
|
||||
|
||||
msgctxt "#30696"
|
||||
msgid "Japanese"
|
||||
msgstr "Japanese"
|
||||
|
||||
msgctxt "#30697"
|
||||
msgid "Russian"
|
||||
msgstr "Russian"
|
||||
|
||||
msgctxt "#30698"
|
||||
msgid "Other"
|
||||
msgstr "Other"
|
||||
|
||||
msgctxt "#30699"
|
||||
msgid "None (audio language only)"
|
||||
msgstr "None (audio language only)"
|
||||
|
||||
msgctxt "#30700"
|
||||
msgid "Auto-select 'No subtitles' if no match found"
|
||||
msgstr "Auto-select 'No subtitles' if no match found"
|
||||
|
||||
msgctxt "#30701"
|
||||
msgid "Play with track selection"
|
||||
msgstr "Play with track selection"
|
||||
|
||||
msgctxt "#30702"
|
||||
msgid "Only select forced subtitles (no regular subs)"
|
||||
msgstr "Only select forced subtitles (no regular subs)"
|
||||
|
||||
msgctxt "#30703"
|
||||
msgid "Subtitle codec preference"
|
||||
msgstr "Subtitle codec preference"
|
||||
|
||||
msgctxt "#30704"
|
||||
msgid "Prefer PGS (better quality when burned)"
|
||||
msgstr "Prefer PGS (better quality when burned)"
|
||||
|
||||
msgctxt "#30705"
|
||||
msgid "Prefer SRT (flexible, can be streamed)"
|
||||
msgstr "Prefer SRT (flexible, can be streamed)"
|
||||
|
||||
msgctxt "#30706"
|
||||
msgid "No preference"
|
||||
msgstr "No preference"
|
||||
|
||||
@@ -1,2 +1,29 @@
|
||||
msgid ""
|
||||
msgstr "X-Generator: Weblate\nMIME-Version: 1.0\nContent-Type: text/plain; charset=UTF-8\nContent-Transfer-Encoding: 8bit"
|
||||
msgstr ""
|
||||
"PO-Revision-Date: 2025-05-28 22:01+0000\n"
|
||||
"Last-Translator: Cjfly <mrlaylowcj@gmail.com>\n"
|
||||
"Language-Team: English (Middle) <https://translate.jellyfin.org/projects/"
|
||||
"jellycon/jellycon/enm/>\n"
|
||||
"Language: enm\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=n != 1;\n"
|
||||
"X-Generator: Weblate 5.11.4\n"
|
||||
|
||||
msgctxt "#30000"
|
||||
msgid "Host"
|
||||
msgstr "127.0.0.1"
|
||||
|
||||
msgctxt "#30006"
|
||||
msgid "Password"
|
||||
msgstr "232542684Cc"
|
||||
|
||||
#, fuzzy
|
||||
msgctxt "#30005"
|
||||
msgid "Username"
|
||||
msgstr "Courtney"
|
||||
|
||||
msgctxt "#30001"
|
||||
msgid "Port"
|
||||
msgstr "3000"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"PO-Revision-Date: 2022-06-08 04:22+0000\n"
|
||||
"PO-Revision-Date: 2022-08-10 20:22+0000\n"
|
||||
"Last-Translator: WWWesten <wwwesten@gmail.com>\n"
|
||||
"Language-Team: Esperanto <https://translate.jellyfin.org/projects/jellycon/"
|
||||
"jellycon/eo/>\n"
|
||||
@@ -1097,3 +1097,7 @@ msgstr "Rapida Konekto"
|
||||
msgctxt "#30323"
|
||||
msgid "Artists"
|
||||
msgstr "Artistoj"
|
||||
|
||||
msgctxt "#30445"
|
||||
msgid "Continue Watching"
|
||||
msgstr "Daŭrigi Spektadon"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"PO-Revision-Date: 2022-07-06 13:22+0000\n"
|
||||
"Last-Translator: Joaquín Díaz <joac.emi.a.n@gmail.com>\n"
|
||||
"PO-Revision-Date: 2025-12-18 13:55+0000\n"
|
||||
"Last-Translator: pol busquets <canpinetell@gmail.com>\n"
|
||||
"Language-Team: Spanish <https://translate.jellyfin.org/projects/jellycon/"
|
||||
"jellycon/es/>\n"
|
||||
"Language: es\n"
|
||||
@@ -9,7 +9,7 @@ msgstr ""
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=n != 1;\n"
|
||||
"X-Generator: Weblate 4.10.1\n"
|
||||
"X-Generator: Weblate 5.14\n"
|
||||
|
||||
msgctxt "#30442"
|
||||
msgid "Simple new content check"
|
||||
@@ -49,7 +49,7 @@ msgstr "Permitir reproducción directa de archivo"
|
||||
|
||||
msgctxt "#30432"
|
||||
msgid "Hide watched items in lists"
|
||||
msgstr "Esconder elementos vistos en las listas"
|
||||
msgstr "Ocultar elementos vistos en las listas"
|
||||
|
||||
msgctxt "#30431"
|
||||
msgid "Seasons"
|
||||
@@ -985,7 +985,7 @@ msgstr "Puerto"
|
||||
|
||||
msgctxt "#30441"
|
||||
msgid "Use cached widget data"
|
||||
msgstr "Usar información en cache del control"
|
||||
msgstr "Usar información en cache del complemento"
|
||||
|
||||
msgctxt "#30423"
|
||||
msgid "NotSet"
|
||||
@@ -1080,7 +1080,7 @@ msgstr "Frecuencia de registro de datos"
|
||||
|
||||
msgctxt "#30000"
|
||||
msgid "Host"
|
||||
msgstr "Host"
|
||||
msgstr "Anfitrión"
|
||||
|
||||
msgctxt "#30276"
|
||||
msgid "Extra Resume Prompt Detected"
|
||||
@@ -1101,3 +1101,131 @@ msgstr "Conexión rápida"
|
||||
msgctxt "#30323"
|
||||
msgid "Artists"
|
||||
msgstr "Artistas"
|
||||
|
||||
msgctxt "#30445"
|
||||
msgid "Continue Watching"
|
||||
msgstr "Continuar viendo"
|
||||
|
||||
msgctxt "#30439"
|
||||
msgid "Show play next episode at time left in seconds"
|
||||
msgstr "Mostrar reproducir el próximo episodio a los segundos restantes"
|
||||
|
||||
msgctxt "#30446"
|
||||
msgid "There was an error logging in"
|
||||
msgstr "Se ha producido un error al iniciar sesión"
|
||||
|
||||
msgctxt "#30447"
|
||||
msgid "Max Play Queue Size"
|
||||
msgstr "Tamaño máximo de la cola de reproducción"
|
||||
|
||||
msgctxt "#30449"
|
||||
msgid "Instant Mix"
|
||||
msgstr "Mezcla instantánea"
|
||||
|
||||
msgctxt "#30448"
|
||||
msgid "Shuffle"
|
||||
msgstr "Mezclar"
|
||||
|
||||
msgctxt "#30225"
|
||||
msgid "Interface Mode"
|
||||
msgstr "Modo de Interfaz"
|
||||
|
||||
msgctxt "#30226"
|
||||
msgid "Default"
|
||||
msgstr "Predeterminado"
|
||||
|
||||
msgctxt "#30227"
|
||||
msgid "Simple"
|
||||
msgstr "Simple"
|
||||
|
||||
msgctxt "#30452"
|
||||
msgid "Combine instead of replace (might cause slow-down)"
|
||||
msgstr "Combinar en vez de reemplazar (podría causar una bajada rendimiento)"
|
||||
|
||||
msgctxt "#30242"
|
||||
msgid "Force transcode av1"
|
||||
msgstr "Forzar transcodificación AV1"
|
||||
|
||||
msgctxt "#30450"
|
||||
msgid "Next Up Rewatching"
|
||||
msgstr "Volver a ver a continuación"
|
||||
|
||||
msgctxt "#30451"
|
||||
msgid "Rewatch Days (0 = Disabled)"
|
||||
msgstr "Días para volver a verlo (0 = deshabilitado)"
|
||||
|
||||
msgctxt "#30453"
|
||||
msgid "Hide number of items to show on entry title"
|
||||
msgstr "Ocultar el número de ítems que se enseñan en el título"
|
||||
|
||||
msgctxt "#30454"
|
||||
msgid " - Totally Unwatched"
|
||||
msgstr " - Totalmente no visto"
|
||||
|
||||
msgctxt "#30667"
|
||||
msgid "Action to take"
|
||||
msgstr "Acción para tomar"
|
||||
|
||||
msgctxt "#30672"
|
||||
msgid "Skip"
|
||||
msgstr "Omitir"
|
||||
|
||||
msgctxt "#30673"
|
||||
msgid "Ask"
|
||||
msgstr "Preguntar"
|
||||
|
||||
msgctxt "#30674"
|
||||
msgid "Do Nothing"
|
||||
msgstr "Hacer nada"
|
||||
|
||||
msgctxt "#30675"
|
||||
msgid "Commercial Skipper"
|
||||
msgstr "Omitidor de Anuncios"
|
||||
|
||||
msgctxt "#30677"
|
||||
msgid "Recap Skipper"
|
||||
msgstr "Saltador de resúmenes"
|
||||
|
||||
msgctxt "#30666"
|
||||
msgid "Segment Skipper"
|
||||
msgstr "Saltador de segmento"
|
||||
|
||||
msgctxt "#30668"
|
||||
msgid "Start Offset (seconds)"
|
||||
msgstr "Desfase de inicio (segundos)"
|
||||
|
||||
msgctxt "#30669"
|
||||
msgid "End Offset (seconds)"
|
||||
msgstr "Desfase de final (segundos)"
|
||||
|
||||
msgctxt "#30670"
|
||||
msgid "Intro Skipper"
|
||||
msgstr "Saltador de introducción"
|
||||
|
||||
msgctxt "#30671"
|
||||
msgid "Credit Skipper"
|
||||
msgstr "Saltador de créditos"
|
||||
|
||||
msgctxt "#30676"
|
||||
msgid "Preview Skipper"
|
||||
msgstr "Saltador de previsualizaciones"
|
||||
|
||||
msgctxt "#30455"
|
||||
msgid "TV Shows - Random"
|
||||
msgstr "Programas de TV"
|
||||
|
||||
msgctxt "#30456"
|
||||
msgid "All - Random"
|
||||
msgstr "Todo en aleatorio"
|
||||
|
||||
msgctxt "#30457"
|
||||
msgid "All - Recently Added"
|
||||
msgstr "Todo - Recientemente Añadido"
|
||||
|
||||
msgctxt "#30458"
|
||||
msgid "All - Favorites"
|
||||
msgstr "Todo - Favoritos"
|
||||
|
||||
msgctxt "#30678"
|
||||
msgid "TV Shows per page"
|
||||
msgstr "Series por página"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"PO-Revision-Date: 2022-01-03 18:05+0000\n"
|
||||
"PO-Revision-Date: 2026-01-05 12:25+0000\n"
|
||||
"Last-Translator: rimasx <riks_12@hot.ee>\n"
|
||||
"Language-Team: Estonian <https://translate.jellyfin.org/projects/jellycon/"
|
||||
"jellycon/et/>\n"
|
||||
@@ -9,7 +9,7 @@ msgstr ""
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=n != 1;\n"
|
||||
"X-Generator: Weblate 4.5.2\n"
|
||||
"X-Generator: Weblate 5.15.1\n"
|
||||
|
||||
msgctxt "#30021"
|
||||
msgid "Show all episodes item"
|
||||
@@ -37,7 +37,7 @@ msgstr "Jellyfin"
|
||||
|
||||
msgctxt "#30012"
|
||||
msgid "[Change user]"
|
||||
msgstr "[Muuda kasutajat]"
|
||||
msgstr "[Vaheta kasutajat]"
|
||||
|
||||
msgctxt "#30011"
|
||||
msgid "[Detect local server]"
|
||||
@@ -73,15 +73,15 @@ msgstr "Port"
|
||||
|
||||
msgctxt "#30366"
|
||||
msgid "Manually enter user details"
|
||||
msgstr "Sisesta kasutaja andmed käsitsi"
|
||||
msgstr "Sisesta kasutajaandmed käsitsi"
|
||||
|
||||
msgctxt "#30241"
|
||||
msgid "Force transcode mpeg4"
|
||||
msgstr "Transkoodi jõuga mpeg4"
|
||||
msgstr "Sunni mpeg4 transkoodimine"
|
||||
|
||||
msgctxt "#30240"
|
||||
msgid "Force transcode msmpeg4v3 (divx)"
|
||||
msgstr "Transkoodi jõuga msmpeg4v3 (divx)"
|
||||
msgstr "Sunni msmpeg4v3 (divx) transkoodimine"
|
||||
|
||||
msgctxt "#30365"
|
||||
msgid "Manual Login"
|
||||
@@ -97,15 +97,15 @@ msgstr "Kas salvestada parool?"
|
||||
|
||||
msgctxt "#30362"
|
||||
msgid " - Recordings"
|
||||
msgstr "- salvestised"
|
||||
msgstr "- Salvestised"
|
||||
|
||||
msgctxt "#30361"
|
||||
msgid " - Programs"
|
||||
msgstr "- saated"
|
||||
msgstr "- Saated"
|
||||
|
||||
msgctxt "#30360"
|
||||
msgid " - Channels"
|
||||
msgstr "- kanalid"
|
||||
msgstr "- Kanalid"
|
||||
|
||||
msgctxt "#30359"
|
||||
msgid "Building full image list"
|
||||
@@ -133,19 +133,19 @@ msgstr "Ava seriaal"
|
||||
|
||||
msgctxt "#30353"
|
||||
msgid " - Frequently Played"
|
||||
msgstr "- sageli esitatud"
|
||||
msgstr "- Sageli esitatud"
|
||||
|
||||
msgctxt "#30321"
|
||||
msgid " - Album Artists"
|
||||
msgstr "– albumi esitajad"
|
||||
msgstr "- Albumi esitajad"
|
||||
|
||||
msgctxt "#30319"
|
||||
msgid "Music - All Album Artists"
|
||||
msgstr "Muusika – kõik albumi esitajad"
|
||||
msgstr "Muusika - Kõik albumi esitajad"
|
||||
|
||||
msgctxt "#30352"
|
||||
msgid "Music - Frequently Played"
|
||||
msgstr "Muusika – sageli esitatud"
|
||||
msgstr "Muusika - Sageli esitatud"
|
||||
|
||||
msgctxt "#30327"
|
||||
msgid "Go To Season"
|
||||
@@ -157,31 +157,31 @@ msgstr "Faili otserada"
|
||||
|
||||
msgctxt "#30263"
|
||||
msgid "Episodes - Recently Added"
|
||||
msgstr "Episoodid – viimati lisatud"
|
||||
msgstr "Episoodid - Viimati lisatud"
|
||||
|
||||
msgctxt "#30257"
|
||||
msgid "Movies - Recently Added"
|
||||
msgstr "Filmid – viimati lisatud"
|
||||
msgstr "Filmid - Viimati lisatud"
|
||||
|
||||
msgctxt "#30349"
|
||||
msgid " - Recently Played"
|
||||
msgstr "- viimati esitatud"
|
||||
msgstr "- Viimati esitatud"
|
||||
|
||||
msgctxt "#30268"
|
||||
msgid " - Recently Added"
|
||||
msgstr "- viimati lisatud"
|
||||
msgstr "- Viimati lisatud"
|
||||
|
||||
msgctxt "#30351"
|
||||
msgid "Music - Recently Played"
|
||||
msgstr "Muusika – viimati esitatud"
|
||||
msgstr "Muusika - Viimati esitatud"
|
||||
|
||||
msgctxt "#30350"
|
||||
msgid "Music - Recently Added"
|
||||
msgstr "Muusika – viimati lisatud"
|
||||
msgstr "Muusika - Viimati lisatud"
|
||||
|
||||
msgctxt "#30348"
|
||||
msgid "Add user ratings"
|
||||
msgstr "Lisa kasutajahinded"
|
||||
msgstr "Kaasa kasutajahinded"
|
||||
|
||||
msgctxt "#30347"
|
||||
msgid "Getting Existing Images"
|
||||
@@ -245,7 +245,7 @@ msgstr "Filme lehel"
|
||||
|
||||
msgctxt "#30330"
|
||||
msgid "Show change user dialog"
|
||||
msgstr "Kuva kasutaja muutmise dialoog"
|
||||
msgstr "Kuva kasutaja vahetamise aken"
|
||||
|
||||
msgctxt "#30329"
|
||||
msgid "Screensaver"
|
||||
@@ -257,7 +257,7 @@ msgstr "Kuva tühjad kaustad (saated, hooajad, kogumikud)"
|
||||
|
||||
msgctxt "#30325"
|
||||
msgid " - Genres"
|
||||
msgstr "- žanrid"
|
||||
msgstr "- Žanrid"
|
||||
|
||||
msgctxt "#30322"
|
||||
msgid "Auto resume"
|
||||
@@ -265,11 +265,11 @@ msgstr "Automaatne jätkamine"
|
||||
|
||||
msgctxt "#30320"
|
||||
msgid " - Albums"
|
||||
msgstr "- albumid"
|
||||
msgstr "- Albumid"
|
||||
|
||||
msgctxt "#30318"
|
||||
msgid "Music - Albums"
|
||||
msgstr "Muusika – albumid"
|
||||
msgstr "Muusika - Albumid"
|
||||
|
||||
msgctxt "#30317"
|
||||
msgid "Play All"
|
||||
@@ -281,7 +281,7 @@ msgstr "Ühenduse viga"
|
||||
|
||||
msgctxt "#30315"
|
||||
msgid "Suppress notifications for connection errors"
|
||||
msgstr "Lülita ühenduse veateavitused välja"
|
||||
msgstr "Peida ühenduse veateavitused"
|
||||
|
||||
msgctxt "#30314"
|
||||
msgid "Play"
|
||||
@@ -305,7 +305,7 @@ msgstr "Luba Jellyfini kaugjuhtimine"
|
||||
|
||||
msgctxt "#30309"
|
||||
msgid "Select Media Source"
|
||||
msgstr "Vali meedia allikas"
|
||||
msgstr "Vali meediaallikas"
|
||||
|
||||
msgctxt "#30308"
|
||||
msgid "Select Trailer"
|
||||
@@ -345,7 +345,7 @@ msgstr "Kas salvestada kõik Jellyfini pildid vahemällu kohalike Kodi piltidena
|
||||
|
||||
msgctxt "#30299"
|
||||
msgid "Cache Images"
|
||||
msgstr "Pildid vahemällu"
|
||||
msgstr "Salvesta pildid vahemällu"
|
||||
|
||||
msgctxt "#30298"
|
||||
msgid "Deleting Kodi Images"
|
||||
@@ -369,7 +369,7 @@ msgstr "Märkus"
|
||||
|
||||
msgctxt "#30293"
|
||||
msgid "Cache images"
|
||||
msgstr "Pildid vahemällu"
|
||||
msgstr "Salvesta pildid vahemällu"
|
||||
|
||||
msgctxt "#30292"
|
||||
msgid "Select Subtitle Stream"
|
||||
@@ -385,23 +385,23 @@ msgstr "Kõik"
|
||||
|
||||
msgctxt "#30289"
|
||||
msgid "TV Shows - Genres"
|
||||
msgstr "Sarjad - žanrid"
|
||||
msgstr "Sarjad - Žanrid"
|
||||
|
||||
msgctxt "#30288"
|
||||
msgid " - Latest"
|
||||
msgstr "- uued"
|
||||
msgstr "- Uued"
|
||||
|
||||
msgctxt "#30287"
|
||||
msgid "TV Shows - Latest"
|
||||
msgstr "Sarjad - uued"
|
||||
msgstr "Sarjad - Uued"
|
||||
|
||||
msgctxt "#30286"
|
||||
msgid "Movies - Unwatched"
|
||||
msgstr "Filmid - vaatamata"
|
||||
msgstr "Filmid - Vaatamata"
|
||||
|
||||
msgctxt "#30285"
|
||||
msgid " - Unwatched"
|
||||
msgstr "- vaatamata"
|
||||
msgstr "- Vaatamata"
|
||||
|
||||
msgctxt "#30283"
|
||||
msgid "Play Next Episode?"
|
||||
@@ -413,25 +413,25 @@ msgstr "Kohtvõrgus ei tuvastatud Jellyfini servereid."
|
||||
|
||||
msgctxt "#30281"
|
||||
msgid "Refresh Cached Images"
|
||||
msgstr "Värskenda vahemällu salvestatud pilte"
|
||||
msgstr "Värskenda puhverdatud pilte"
|
||||
|
||||
msgctxt "#30280"
|
||||
msgid "Missing Title"
|
||||
msgstr "Puuduv pealkiri"
|
||||
msgstr "Puuduv nimetus"
|
||||
|
||||
msgctxt "#30279"
|
||||
msgid "TV Shows - Unwatched"
|
||||
msgstr "Sarjad - vaatamata"
|
||||
msgstr "Sarjad - Vaatamata"
|
||||
|
||||
msgctxt "#30278"
|
||||
msgid " - Next Up"
|
||||
msgstr "- järgmisena"
|
||||
msgstr "- Järgmine"
|
||||
|
||||
msgctxt "#30277"
|
||||
msgid "JellyCon needs to prompt for resume on partily played items, Kodi can also prompt, this can cause a double prompt. Do you want to remove the double prompt?"
|
||||
msgstr ""
|
||||
"JellyCon peab küsima jätkamist osaliselt esitatud üksuste puhul. Kodi võib "
|
||||
"samuti küsida ja see võib põhjustada päringu. Kas soovid topeltpäringu "
|
||||
"samuti küsida ja see võib põhjustada topeltpäringu. Kas soovid topeltpäringu "
|
||||
"eemaldada?"
|
||||
|
||||
msgctxt "#30276"
|
||||
@@ -440,7 +440,7 @@ msgstr "Tuvastati täiendav jätkamise päring"
|
||||
|
||||
msgctxt "#30275"
|
||||
msgid "Force Transcode"
|
||||
msgstr "Sunnitud transkoodimine"
|
||||
msgstr "Sunni transkoodimine"
|
||||
|
||||
msgctxt "#30274"
|
||||
msgid "Delete"
|
||||
@@ -460,27 +460,27 @@ msgstr "Märgi vaadatuks"
|
||||
|
||||
msgctxt "#30269"
|
||||
msgid "Movies - Random"
|
||||
msgstr "Filmid – juhuslikud"
|
||||
msgstr "Filmid - Juhuslikud"
|
||||
|
||||
msgctxt "#30267"
|
||||
msgid " - In Progress"
|
||||
msgstr "- pooleli"
|
||||
msgstr "- Pooleli"
|
||||
|
||||
msgctxt "#30266"
|
||||
msgid "Movies - Pages"
|
||||
msgstr "Filmid – lehed"
|
||||
msgstr "Filmid - Lehed"
|
||||
|
||||
msgctxt "#30265"
|
||||
msgid "Episodes - Next Up"
|
||||
msgstr "Episoodid – järgmine"
|
||||
msgstr "Episoodid - Järgmine"
|
||||
|
||||
msgctxt "#30264"
|
||||
msgid "Episodes - In Progress"
|
||||
msgstr "Episoodid – pooleli"
|
||||
msgstr "Episoodid - Pooleli"
|
||||
|
||||
msgctxt "#30262"
|
||||
msgid "TV Shows - Favorites"
|
||||
msgstr "Sarjad - lemmikud"
|
||||
msgstr "Sarjad - Lemmikud"
|
||||
|
||||
msgctxt "#30261"
|
||||
msgid "TV Shows"
|
||||
@@ -492,11 +492,11 @@ msgstr "Kogumikud"
|
||||
|
||||
msgctxt "#30259"
|
||||
msgid "Movies - Favorites"
|
||||
msgstr "Filmid – lemmikud"
|
||||
msgstr "Filmid - Lemmikud"
|
||||
|
||||
msgctxt "#30258"
|
||||
msgid "Movies - In Progress"
|
||||
msgstr "Filmid – pooleli"
|
||||
msgstr "Filmid - Pooleli"
|
||||
|
||||
msgctxt "#30256"
|
||||
msgid "Movies"
|
||||
@@ -508,15 +508,15 @@ msgstr "Sarjad - A-Ü"
|
||||
|
||||
msgctxt "#30254"
|
||||
msgid "Show add-on settings"
|
||||
msgstr "Kuva lisamooduli seaded"
|
||||
msgstr "Lisamooduli seaded"
|
||||
|
||||
msgctxt "#30252"
|
||||
msgid "Movies - A-Z"
|
||||
msgstr "Filmid – A-Ü"
|
||||
msgstr "Filmid - A-Ü"
|
||||
|
||||
msgctxt "#30251"
|
||||
msgid "Movies - Genres"
|
||||
msgstr "Filmid – žanrid"
|
||||
msgstr "Filmid - Žanrid"
|
||||
|
||||
msgctxt "#30250"
|
||||
msgid "Unknown"
|
||||
@@ -528,11 +528,11 @@ msgstr "Otsi"
|
||||
|
||||
msgctxt "#30239"
|
||||
msgid "Force transcode mpeg2"
|
||||
msgstr "Transkoodi jõuga mpeg2"
|
||||
msgstr "Sunni mpeg2 transkoodimine"
|
||||
|
||||
msgctxt "#30238"
|
||||
msgid "Playback stream options"
|
||||
msgstr "Taasesituse striimimise valikud"
|
||||
msgstr "Taasesitusvoo valikud"
|
||||
|
||||
msgctxt "#30237"
|
||||
msgid "Start from beginning"
|
||||
@@ -540,7 +540,7 @@ msgstr "Alusta algusest"
|
||||
|
||||
msgctxt "#30236"
|
||||
msgid "Force transcode h265 (hevc)"
|
||||
msgstr "Transkoodi jõuga h265 (hevc)"
|
||||
msgstr "Sunni h265 (hevc) transkoodimine"
|
||||
|
||||
msgctxt "#30235"
|
||||
msgid "Episodes"
|
||||
@@ -584,7 +584,7 @@ msgstr "Üksuse üksikasjad"
|
||||
|
||||
msgctxt "#30215"
|
||||
msgid "On playback stop (100% = disabled)"
|
||||
msgstr "Taasesituse peatamisel (100% = keelatud)"
|
||||
msgstr "Taasesituse peatumisel (100% = keelatud)"
|
||||
|
||||
msgctxt "#30214"
|
||||
msgid "Events"
|
||||
@@ -604,7 +604,7 @@ msgstr "HTTP otsevoog"
|
||||
|
||||
msgctxt "#30000"
|
||||
msgid "Host"
|
||||
msgstr "Peremeesmasin"
|
||||
msgstr "Server"
|
||||
|
||||
msgctxt "#30182"
|
||||
msgid "Include media stream info"
|
||||
@@ -656,7 +656,7 @@ msgstr "Vali server"
|
||||
|
||||
msgctxt "#30163"
|
||||
msgid "Add (cc) if subtitle is available"
|
||||
msgstr "Lisa (cc) subtiitrite olemasolul"
|
||||
msgstr "Lisa (cc), kui subtiitrid on saadaval"
|
||||
|
||||
msgctxt "#30139"
|
||||
msgid "No Media Type Set"
|
||||
@@ -676,7 +676,7 @@ msgstr "Tehtud"
|
||||
|
||||
msgctxt "#30121"
|
||||
msgid "On resume"
|
||||
msgstr "Jätkamisel"
|
||||
msgstr "Taasesituse jätkamisel"
|
||||
|
||||
msgctxt "#30120"
|
||||
msgid "Show load progress"
|
||||
@@ -684,11 +684,11 @@ msgstr "Kuva laadimise edenemine"
|
||||
|
||||
msgctxt "#30116"
|
||||
msgid "Add unwatched counts to names"
|
||||
msgstr "Lisa nimedele vaatamata arv"
|
||||
msgstr "Lisa nimedele vaatamata episoodide arv"
|
||||
|
||||
msgctxt "#30118"
|
||||
msgid "Add resume percent to names"
|
||||
msgstr "Lisa nimedele jätkamise protsent"
|
||||
msgstr "Lisa nimedele vaatemise oleku protsent"
|
||||
|
||||
msgctxt "#30114"
|
||||
msgid "Jump back seconds"
|
||||
@@ -716,7 +716,7 @@ msgstr "Hoiatus: see toiming kustutab meediafailid serverist."
|
||||
|
||||
msgctxt "#30091"
|
||||
msgid "Confirm delete?"
|
||||
msgstr "Kas kinnitada kustutamine?"
|
||||
msgstr "Kas kustutamine kinnitada?"
|
||||
|
||||
msgctxt "#30063"
|
||||
msgid "N/A"
|
||||
@@ -744,7 +744,7 @@ msgstr "Luba silumislogimine"
|
||||
|
||||
msgctxt "#30026"
|
||||
msgid "Widget item select action"
|
||||
msgstr "Vidina toiming üksuse valikul"
|
||||
msgstr "Toiming vidina elemendi valimisel"
|
||||
|
||||
msgctxt "#30025"
|
||||
msgid "Password:"
|
||||
@@ -756,8 +756,468 @@ msgstr "Kasutajanimi:"
|
||||
|
||||
msgctxt "#30023"
|
||||
msgid "Hide unwatched episode details"
|
||||
msgstr "Peida vaatamata episoodi üksikasjad"
|
||||
msgstr "Peida vaatamata episoodide üksikasjad"
|
||||
|
||||
msgctxt "#30022"
|
||||
msgid "Advanced"
|
||||
msgstr "Täpsem"
|
||||
|
||||
msgctxt "#30019"
|
||||
msgid "Filtered episode name format"
|
||||
msgstr "Filtreeritud episoodi nime vorming"
|
||||
|
||||
msgctxt "#30213"
|
||||
msgid "Video force 8 bit"
|
||||
msgstr "Sunni 8 bitine video"
|
||||
|
||||
msgctxt "#30368"
|
||||
msgid "Clear Password?"
|
||||
msgstr "Parool kustutada?"
|
||||
|
||||
msgctxt "#30373"
|
||||
msgid "Scanning for local servers"
|
||||
msgstr "Kohalike serverite skaneerimine"
|
||||
|
||||
msgctxt "#30376"
|
||||
msgid "Checking server url"
|
||||
msgstr "Serveri URL-i kontroll"
|
||||
|
||||
msgctxt "#30323"
|
||||
msgid "Artists"
|
||||
msgstr "Esitajad"
|
||||
|
||||
msgctxt "#30371"
|
||||
msgid "Could not connect to the URL you entered, do you want to try again?"
|
||||
msgstr "Sisestatud URL-iga ei õnnestunud ühenduda, kas soovid uuesti proovida?"
|
||||
|
||||
msgctxt "#30377"
|
||||
msgid "Sending request"
|
||||
msgstr "Päringu saatmine"
|
||||
|
||||
msgctxt "#30242"
|
||||
msgid "Force transcode av1"
|
||||
msgstr "Sunni av1 transkoodimine"
|
||||
|
||||
msgctxt "#30370"
|
||||
msgid "Do you want to manually enter a server url?"
|
||||
msgstr "Kas soovid serveri URL-i sisestada käsitsi?"
|
||||
|
||||
msgctxt "#30372"
|
||||
msgid "Server URL"
|
||||
msgstr "Serveri URL"
|
||||
|
||||
msgctxt "#30380"
|
||||
msgid "Never"
|
||||
msgstr "Mitte kunagi"
|
||||
|
||||
msgctxt "#30381"
|
||||
msgid "More than one"
|
||||
msgstr "Rohkem kui üks"
|
||||
|
||||
msgctxt "#30382"
|
||||
msgid "Always"
|
||||
msgstr "Alati"
|
||||
|
||||
msgctxt "#30383"
|
||||
msgid "System - "
|
||||
msgstr "Süsteem -"
|
||||
|
||||
msgctxt "#30225"
|
||||
msgid "Interface Mode"
|
||||
msgstr "Kasutajaliidese olek"
|
||||
|
||||
msgctxt "#30226"
|
||||
msgid "Default"
|
||||
msgstr "Vaikimisi"
|
||||
|
||||
msgctxt "#30227"
|
||||
msgid "Simple"
|
||||
msgstr "Lihtne"
|
||||
|
||||
msgctxt "#30247"
|
||||
msgid "Custom Widget Content"
|
||||
msgstr "Kohandatud vidina sisu"
|
||||
|
||||
msgctxt "#30273"
|
||||
msgid "Unset Favourite"
|
||||
msgstr "Tühista lemmikuks määramine"
|
||||
|
||||
msgctxt "#30367"
|
||||
msgid "Allow fast user switching password saving"
|
||||
msgstr "Luba muudetud kasutajaparooli kiire salvestamine"
|
||||
|
||||
msgctxt "#30369"
|
||||
msgid "Do you want to clear your saved password?"
|
||||
msgstr "Kas soovid oma salvestatud parooli kustutada?"
|
||||
|
||||
msgctxt "#30374"
|
||||
msgid "Sending request"
|
||||
msgstr "Päringu saatmine"
|
||||
|
||||
msgctxt "#30375"
|
||||
msgid "Receiving data packet"
|
||||
msgstr "Andmepaketi vastuvõtt"
|
||||
|
||||
msgctxt "#30378"
|
||||
msgid "Persist user details"
|
||||
msgstr "Säilita kasutajaandmed"
|
||||
|
||||
msgctxt "#30379"
|
||||
msgid "External subtitle prompt"
|
||||
msgstr "Paku väliseid subtiitreid"
|
||||
|
||||
msgctxt "#30439"
|
||||
msgid "Show play next episode at time left in seconds"
|
||||
msgstr "Kuva \"Esita järgmine episood\" enne video lõppu (sek)"
|
||||
|
||||
msgctxt "#30384"
|
||||
msgid "Random movies interval minutes (0 = disabled)"
|
||||
msgstr "Juhuslike filmide värskendamise intervall (0 = keelatud)"
|
||||
|
||||
msgctxt "#30388"
|
||||
msgid "Server details"
|
||||
msgstr "Serveri andmed"
|
||||
|
||||
msgctxt "#30392"
|
||||
msgid "HTTPS"
|
||||
msgstr "HTTPS"
|
||||
|
||||
msgctxt "#30398"
|
||||
msgid "Refresh Jellyfin Metadata"
|
||||
msgstr "Värskenda Jellyfini metaandmeid"
|
||||
|
||||
msgctxt "#30406"
|
||||
msgid "Jellyfin Libraries"
|
||||
msgstr "Jellyfini meediakogud"
|
||||
|
||||
msgctxt "#30407"
|
||||
msgid "Global Lists"
|
||||
msgstr "Globaalsed loendid"
|
||||
|
||||
msgctxt "#30416"
|
||||
msgid "HTTP timeout seconds"
|
||||
msgstr "HTTP ajalõpp sekundites"
|
||||
|
||||
msgctxt "#30418"
|
||||
msgid "Audio bitrate (Kbits)"
|
||||
msgstr "Heli bitikiirus (kbps)"
|
||||
|
||||
msgctxt "#30419"
|
||||
msgid "Audio codec"
|
||||
msgstr "Helikoodek"
|
||||
|
||||
msgctxt "#30423"
|
||||
msgid "NotSet"
|
||||
msgstr "Määramata"
|
||||
|
||||
msgctxt "#30425"
|
||||
msgid "Year"
|
||||
msgstr "Aasta"
|
||||
|
||||
msgctxt "#30426"
|
||||
msgid "Title"
|
||||
msgstr "Pealkiri"
|
||||
|
||||
msgctxt "#30437"
|
||||
msgid "Playback options"
|
||||
msgstr "Taasesituse valikud"
|
||||
|
||||
msgctxt "#30440"
|
||||
msgid "Play next"
|
||||
msgstr "Esita järgmisena"
|
||||
|
||||
msgctxt "#30409"
|
||||
msgid "Add-on Actions"
|
||||
msgstr "Lisamooduli toimingud"
|
||||
|
||||
msgctxt "#30395"
|
||||
msgid "Clear cached server data"
|
||||
msgstr "Tühjenda vahemällu salvestatud serveri andmed"
|
||||
|
||||
msgctxt "#30446"
|
||||
msgid "There was an error logging in"
|
||||
msgstr "Ilmes viga sisselogimisel"
|
||||
|
||||
msgctxt "#30449"
|
||||
msgid "Instant Mix"
|
||||
msgstr "Kiirmiks"
|
||||
|
||||
msgctxt "#30447"
|
||||
msgid "Max Play Queue Size"
|
||||
msgstr "Esitusjärjekorra maksimaalne suurus"
|
||||
|
||||
msgctxt "#30389"
|
||||
msgid "User details"
|
||||
msgstr "Kasutaja andmed"
|
||||
|
||||
msgctxt "#30387"
|
||||
msgid "Unused images removed : "
|
||||
msgstr "Kasutamata pildid eemaldati:"
|
||||
|
||||
msgctxt "#30405"
|
||||
msgid " - Show All"
|
||||
msgstr "- Kuva kõik"
|
||||
|
||||
msgctxt "#30415"
|
||||
msgid " - Favorite Collections"
|
||||
msgstr "- Lemmikkogumikud"
|
||||
|
||||
msgctxt "#30454"
|
||||
msgid " - Totally Unwatched"
|
||||
msgstr " - Täiesti vaatamata"
|
||||
|
||||
msgctxt "#30385"
|
||||
msgid "Existing images before delete : "
|
||||
msgstr "Olemasolevaid pilte enne kustutamist:"
|
||||
|
||||
msgctxt "#30386"
|
||||
msgid "Unused Jellyfin images : "
|
||||
msgstr "Kasutamata Jellyfini pildid:"
|
||||
|
||||
msgctxt "#30390"
|
||||
msgid "Protocol"
|
||||
msgstr "Protokoll"
|
||||
|
||||
msgctxt "#30391"
|
||||
msgid "HTTP"
|
||||
msgstr "HTTP"
|
||||
|
||||
msgctxt "#30393"
|
||||
msgid "Clear Cache Result"
|
||||
msgstr "Vahemälu tühjendamise tulemus"
|
||||
|
||||
msgctxt "#30394"
|
||||
msgid "Cache files deleted"
|
||||
msgstr "Vahemälu failid kustutati"
|
||||
|
||||
msgctxt "#30399"
|
||||
msgid "Hide"
|
||||
msgstr "Peida"
|
||||
|
||||
msgctxt "#30401"
|
||||
msgid "Info"
|
||||
msgstr "Info"
|
||||
|
||||
msgctxt "#30402"
|
||||
msgid "Add to Kodi Playlist"
|
||||
msgstr "Lisa Kodi esitusloendisse"
|
||||
|
||||
msgctxt "#30403"
|
||||
msgid "Movies - Recommendations"
|
||||
msgstr "Filmid - Soovitused"
|
||||
|
||||
msgctxt "#30400"
|
||||
msgid "Cache images interval minutes (0 = disabled)"
|
||||
msgstr "Piltide vahemällu salvestamise intervall (0 = keelatud)"
|
||||
|
||||
msgctxt "#30408"
|
||||
msgid "Custom Widgets"
|
||||
msgstr "Kohandatud vidinad"
|
||||
|
||||
msgctxt "#30410"
|
||||
msgid " - Collections"
|
||||
msgstr "- Kogumikud"
|
||||
|
||||
msgctxt "#30404"
|
||||
msgid " - A-Z"
|
||||
msgstr "- A-Ü"
|
||||
|
||||
msgctxt "#30413"
|
||||
msgid " - Tags"
|
||||
msgstr "- Sildid"
|
||||
|
||||
msgctxt "#30411"
|
||||
msgid " - Years"
|
||||
msgstr "- Aastad"
|
||||
|
||||
msgctxt "#30412"
|
||||
msgid " - Decades"
|
||||
msgstr "- Kümnendid"
|
||||
|
||||
msgctxt "#30414"
|
||||
msgid " - Favorites"
|
||||
msgstr "- Lemmikud"
|
||||
|
||||
msgctxt "#30417"
|
||||
msgid "You do not have permision to delete this item"
|
||||
msgstr "Sul pole selle üksuse kustutamiseks õigusi"
|
||||
|
||||
msgctxt "#30420"
|
||||
msgid "Audio max channels"
|
||||
msgstr "Maksimaalne helikanalite arv"
|
||||
|
||||
msgctxt "#30422"
|
||||
msgid "Sorting"
|
||||
msgstr "Järjestus"
|
||||
|
||||
msgctxt "#30424"
|
||||
msgid "Default"
|
||||
msgstr "Vaikimisi"
|
||||
|
||||
msgctxt "#30427"
|
||||
msgid "Added"
|
||||
msgstr "Lisatud"
|
||||
|
||||
msgctxt "#30428"
|
||||
msgid "Rating"
|
||||
msgstr "Hinne"
|
||||
|
||||
msgctxt "#30429"
|
||||
msgid "Genre"
|
||||
msgstr "Žanr"
|
||||
|
||||
msgctxt "#30432"
|
||||
msgid "Hide watched items in lists"
|
||||
msgstr "Peida vaadatud üksused loendites"
|
||||
|
||||
msgctxt "#30433"
|
||||
msgid "Allow direct file playback"
|
||||
msgstr "Luba failide otseesitus"
|
||||
|
||||
msgctxt "#30434"
|
||||
msgid "Force transcode stream bitrate (Kbits)"
|
||||
msgstr "Sunni transkoodimisvoo bitikiirus (kbps)"
|
||||
|
||||
msgctxt "#30435"
|
||||
msgid "Connection speed test"
|
||||
msgstr "Ühenduse kiirustest"
|
||||
|
||||
msgctxt "#30436"
|
||||
msgid "Speed test data size (MB)"
|
||||
msgstr "Kiirustesti andmesuurus (MB)"
|
||||
|
||||
msgctxt "#30442"
|
||||
msgid "Simple new content check"
|
||||
msgstr "Lihtne uue sisu kontroll"
|
||||
|
||||
msgctxt "#30441"
|
||||
msgid "Use cached widget data"
|
||||
msgstr "Kasuta vahemällu salvestatud vidina andmeid"
|
||||
|
||||
msgctxt "#30443"
|
||||
msgid "Quick Connect"
|
||||
msgstr "Kiirühendus"
|
||||
|
||||
msgctxt "#30444"
|
||||
msgid "Login using Quick Connect"
|
||||
msgstr "Logi sisse kiirühenduse abil"
|
||||
|
||||
msgctxt "#30445"
|
||||
msgid "Continue Watching"
|
||||
msgstr "Jätka vaatamist"
|
||||
|
||||
msgctxt "#30452"
|
||||
msgid "Combine instead of replace (might cause slow-down)"
|
||||
msgstr "Ühenda asendamise asemel (võib jõudlust aeglustada)"
|
||||
|
||||
msgctxt "#30667"
|
||||
msgid "Action to take"
|
||||
msgstr "Sooritatav toiming"
|
||||
|
||||
msgctxt "#30668"
|
||||
msgid "Start Offset (seconds)"
|
||||
msgstr "Käivitusviivitus (sekundites)"
|
||||
|
||||
msgctxt "#30669"
|
||||
msgid "End Offset (seconds)"
|
||||
msgstr "Lõpuviivitus (sekundites)"
|
||||
|
||||
msgctxt "#30672"
|
||||
msgid "Skip"
|
||||
msgstr "Jäta vahele"
|
||||
|
||||
msgctxt "#30673"
|
||||
msgid "Ask"
|
||||
msgstr "Küsi"
|
||||
|
||||
msgctxt "#30674"
|
||||
msgid "Do Nothing"
|
||||
msgstr "Ära tee midagi"
|
||||
|
||||
msgctxt "#30431"
|
||||
msgid "Seasons"
|
||||
msgstr "Hooajad"
|
||||
|
||||
msgctxt "#30448"
|
||||
msgid "Shuffle"
|
||||
msgstr "Segamine"
|
||||
|
||||
msgctxt "#30397"
|
||||
msgid " - Pages"
|
||||
msgstr "- Lehed"
|
||||
|
||||
msgctxt "#30451"
|
||||
msgid "Rewatch Days (0 = Disabled)"
|
||||
msgstr "Kordusvaatamise päevad (0 = keelatud)"
|
||||
|
||||
msgctxt "#30453"
|
||||
msgid "Hide number of items to show on entry title"
|
||||
msgstr "Peida kuvatavate üksuste arv avalehel"
|
||||
|
||||
msgctxt "#30455"
|
||||
msgid "TV Shows - Random"
|
||||
msgstr "Sarjad - Juhuslik"
|
||||
|
||||
msgctxt "#30456"
|
||||
msgid "All - Random"
|
||||
msgstr "Kõik - Juhuslik"
|
||||
|
||||
msgctxt "#30457"
|
||||
msgid "All - Recently Added"
|
||||
msgstr "Kõik - Viimati lisatud"
|
||||
|
||||
msgctxt "#30458"
|
||||
msgid "All - Favorites"
|
||||
msgstr "Kõik - Lemmikud"
|
||||
|
||||
msgctxt "#30678"
|
||||
msgid "TV Shows per page"
|
||||
msgstr "Sarjade arv lehel"
|
||||
|
||||
msgctxt "#30020"
|
||||
msgid "Flatten single season"
|
||||
msgstr "Ära kuva üksikut hooaega"
|
||||
|
||||
msgctxt "#30224"
|
||||
msgid "Interaction"
|
||||
msgstr "Interaktsioon"
|
||||
|
||||
msgctxt "#30430"
|
||||
msgid "Label"
|
||||
msgstr "Silt"
|
||||
|
||||
msgctxt "#30438"
|
||||
msgid "Play cinema intros"
|
||||
msgstr "Esita filmi intro"
|
||||
|
||||
msgctxt "#30666"
|
||||
msgid "Segment Skipper"
|
||||
msgstr "Segmendi vahelejätja"
|
||||
|
||||
msgctxt "#30670"
|
||||
msgid "Intro Skipper"
|
||||
msgstr "Sissejuhatuse vahelejätja"
|
||||
|
||||
msgctxt "#30671"
|
||||
msgid "Credit Skipper"
|
||||
msgstr "Lõputiitrite vahelejätja"
|
||||
|
||||
msgctxt "#30675"
|
||||
msgid "Commercial Skipper"
|
||||
msgstr "Reklaamide vahelejätja"
|
||||
|
||||
msgctxt "#30676"
|
||||
msgid "Preview Skipper"
|
||||
msgstr "Eelvaatuse vahelejätja"
|
||||
|
||||
msgctxt "#30677"
|
||||
msgid "Recap Skipper"
|
||||
msgstr "Kokkuvõtte vahelejätja"
|
||||
|
||||
msgctxt "#30421"
|
||||
msgid "Views"
|
||||
msgstr "Vaated"
|
||||
|
||||
msgctxt "#30450"
|
||||
msgid "Next Up Rewatching"
|
||||
msgstr "Järgmisena kordusvaatamisel"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"PO-Revision-Date: 2022-06-12 12:22+0000\n"
|
||||
"Last-Translator: Oskari Lavinto <olavinto@protonmail.com>\n"
|
||||
"PO-Revision-Date: 2025-12-18 13:55+0000\n"
|
||||
"Last-Translator: Antti Pikkuaho <antti.pikkuaho@outlook.com>\n"
|
||||
"Language-Team: Finnish <https://translate.jellyfin.org/projects/jellycon/"
|
||||
"jellycon/fi/>\n"
|
||||
"Language: fi\n"
|
||||
@@ -9,7 +9,7 @@ msgstr ""
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=n != 1;\n"
|
||||
"X-Generator: Weblate 4.10.1\n"
|
||||
"X-Generator: Weblate 5.14\n"
|
||||
|
||||
msgctxt "#30442"
|
||||
msgid "Simple new content check"
|
||||
@@ -591,7 +591,7 @@ msgstr "Puskuroidaan kuvia"
|
||||
|
||||
msgctxt "#30299"
|
||||
msgid "Cache Images"
|
||||
msgstr "Puskuroi kuvat"
|
||||
msgstr "Puskuroi Kuvat"
|
||||
|
||||
msgctxt "#30298"
|
||||
msgid "Deleting Kodi Images"
|
||||
@@ -1099,3 +1099,133 @@ msgstr "Pikayhdistys"
|
||||
msgctxt "#30323"
|
||||
msgid "Artists"
|
||||
msgstr "Esittäjät"
|
||||
|
||||
msgctxt "#30445"
|
||||
msgid "Continue Watching"
|
||||
msgstr "Jatka katselua"
|
||||
|
||||
msgctxt "#30439"
|
||||
msgid "Show play next episode at time left in seconds"
|
||||
msgstr ""
|
||||
"Nykyisen jakson jäljellä oelva toistoaika sekunteina, jolloin näytetään "
|
||||
"ilmoitus seuraavasta jaksosta"
|
||||
|
||||
msgctxt "#30446"
|
||||
msgid "There was an error logging in"
|
||||
msgstr "Kirjauduttaessa tapahtui virhe"
|
||||
|
||||
msgctxt "#30448"
|
||||
msgid "Shuffle"
|
||||
msgstr "Sekoitus"
|
||||
|
||||
msgctxt "#30447"
|
||||
msgid "Max Play Queue Size"
|
||||
msgstr "Toistojonon enimmäiskoko"
|
||||
|
||||
msgctxt "#30449"
|
||||
msgid "Instant Mix"
|
||||
msgstr "Pikasekoitus"
|
||||
|
||||
msgctxt "#30225"
|
||||
msgid "Interface Mode"
|
||||
msgstr "Käyttöliittymän tila"
|
||||
|
||||
msgctxt "#30226"
|
||||
msgid "Default"
|
||||
msgstr "Oletus"
|
||||
|
||||
msgctxt "#30227"
|
||||
msgid "Simple"
|
||||
msgstr "Yksinkertainen"
|
||||
|
||||
msgctxt "#30450"
|
||||
msgid "Next Up Rewatching"
|
||||
msgstr "Seuraavaksi uudelleenkatselussa"
|
||||
|
||||
msgctxt "#30452"
|
||||
msgid "Combine instead of replace (might cause slow-down)"
|
||||
msgstr "Yhdistä korvauksen sijaan (voi hidastaa toimintaa)"
|
||||
|
||||
msgctxt "#30242"
|
||||
msgid "Force transcode av1"
|
||||
msgstr "Pakota AV1-transkoodaus"
|
||||
|
||||
msgctxt "#30451"
|
||||
msgid "Rewatch Days (0 = Disabled)"
|
||||
msgstr "Uudelleenkatselupäivät (0 = ei käytössä)"
|
||||
|
||||
msgctxt "#30453"
|
||||
msgid "Hide number of items to show on entry title"
|
||||
msgstr "Piilota näytettävien kohteiden määrä etusivulta"
|
||||
|
||||
msgctxt "#30454"
|
||||
msgid " - Totally Unwatched"
|
||||
msgstr " - Kokonaan katsomatta"
|
||||
|
||||
msgctxt "#30666"
|
||||
msgid "Segment Skipper"
|
||||
msgstr "Kappaleiden ohittaja"
|
||||
|
||||
msgctxt "#30668"
|
||||
msgid "Start Offset (seconds)"
|
||||
msgstr "Aloituksen siirto (sekunneissa)"
|
||||
|
||||
msgctxt "#30667"
|
||||
msgid "Action to take"
|
||||
msgstr "Tehtävät toimet"
|
||||
|
||||
msgctxt "#30669"
|
||||
msgid "End Offset (seconds)"
|
||||
msgstr "Lopetuksen siirto (sekunneissa)"
|
||||
|
||||
msgctxt "#30670"
|
||||
msgid "Intro Skipper"
|
||||
msgstr "Johdannon ohittaja"
|
||||
|
||||
msgctxt "#30671"
|
||||
msgid "Credit Skipper"
|
||||
msgstr "Lopetuksen ohittaja"
|
||||
|
||||
msgctxt "#30672"
|
||||
msgid "Skip"
|
||||
msgstr "Ohita"
|
||||
|
||||
msgctxt "#30673"
|
||||
msgid "Ask"
|
||||
msgstr "Kysy"
|
||||
|
||||
msgctxt "#30674"
|
||||
msgid "Do Nothing"
|
||||
msgstr "Älä tee mitään"
|
||||
|
||||
msgctxt "#30675"
|
||||
msgid "Commercial Skipper"
|
||||
msgstr "Mainosten ohittaja"
|
||||
|
||||
msgctxt "#30676"
|
||||
msgid "Preview Skipper"
|
||||
msgstr "Ennakkoesitysten ohittaja"
|
||||
|
||||
msgctxt "#30677"
|
||||
msgid "Recap Skipper"
|
||||
msgstr "Yhteenvetojen ohittaja"
|
||||
|
||||
msgctxt "#30455"
|
||||
msgid "TV Shows - Random"
|
||||
msgstr "Sarjat - Satunnainen"
|
||||
|
||||
msgctxt "#30456"
|
||||
msgid "All - Random"
|
||||
msgstr "Kaikki - Satunnainen"
|
||||
|
||||
msgctxt "#30457"
|
||||
msgid "All - Recently Added"
|
||||
msgstr "Kaikki - Viimeksi lisätyt"
|
||||
|
||||
msgctxt "#30458"
|
||||
msgid "All - Favorites"
|
||||
msgstr "Kaikki - Suosikit"
|
||||
|
||||
msgctxt "#30678"
|
||||
msgid "TV Shows per page"
|
||||
msgstr "Sarjoja per sivu"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"PO-Revision-Date: 2022-07-06 13:22+0000\n"
|
||||
"Last-Translator: Thomas Schwery <thomas@inf3.ch>\n"
|
||||
"PO-Revision-Date: 2025-05-13 02:01+0000\n"
|
||||
"Last-Translator: r4dius <r4dius@gmail.com>\n"
|
||||
"Language-Team: French <https://translate.jellyfin.org/projects/jellycon/"
|
||||
"jellycon/fr/>\n"
|
||||
"Language: fr\n"
|
||||
@@ -9,7 +9,7 @@ msgstr ""
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=n > 1;\n"
|
||||
"X-Generator: Weblate 4.10.1\n"
|
||||
"X-Generator: Weblate 5.10.4\n"
|
||||
|
||||
msgctxt "#30018"
|
||||
msgid "Number of items to show in filtered lists"
|
||||
@@ -151,7 +151,7 @@ msgstr "Interface"
|
||||
|
||||
msgctxt "#30091"
|
||||
msgid "Confirm delete?"
|
||||
msgstr "Confirmer la suppression ?"
|
||||
msgstr "Confirmer la suppression ?"
|
||||
|
||||
msgctxt "#30052"
|
||||
msgid "Deleting"
|
||||
@@ -902,10 +902,9 @@ msgctxt "#30354"
|
||||
msgid "Go To Series"
|
||||
msgstr "Voir les Séries"
|
||||
|
||||
#, fuzzy
|
||||
msgctxt "#30319"
|
||||
msgid "Music - All Album Artists"
|
||||
msgstr "Musique - Tous les Artistes d'album"
|
||||
msgstr "Musique - Tous les Artistes de l'Album"
|
||||
|
||||
msgctxt "#30343"
|
||||
msgid "Changes Require Kodi Restart"
|
||||
@@ -923,7 +922,6 @@ msgctxt "#30366"
|
||||
msgid "Manually enter user details"
|
||||
msgstr "Renseigner manuellement les détails utilisateurs"
|
||||
|
||||
#, fuzzy
|
||||
msgctxt "#30359"
|
||||
msgid "Building full image list"
|
||||
msgstr "Construction de la liste complète des images"
|
||||
@@ -936,12 +934,10 @@ msgctxt "#30357"
|
||||
msgid "Processing existing image list"
|
||||
msgstr "Traitement de la liste des images existantes"
|
||||
|
||||
#, fuzzy
|
||||
msgctxt "#30355"
|
||||
msgid "Kodi Settings->Services->Allow remote control via HTTP"
|
||||
msgstr "Paramètres de Kodi->Services->Autoriser le contrôle à distance par HTTP"
|
||||
|
||||
#, fuzzy
|
||||
msgctxt "#30348"
|
||||
msgid "Add user ratings"
|
||||
msgstr "Ajouter une note"
|
||||
@@ -949,3 +945,266 @@ msgstr "Ajouter une note"
|
||||
msgctxt "#30323"
|
||||
msgid "Artists"
|
||||
msgstr "Artistes"
|
||||
|
||||
msgctxt "#30394"
|
||||
msgid "Cache files deleted"
|
||||
msgstr "Fichiers du cache supprimés"
|
||||
|
||||
msgctxt "#30393"
|
||||
msgid "Clear Cache Result"
|
||||
msgstr "Effacer le cache des résultats"
|
||||
|
||||
msgctxt "#30388"
|
||||
msgid "Server details"
|
||||
msgstr "Détails du serveur"
|
||||
|
||||
msgctxt "#30387"
|
||||
msgid "Unused images removed : "
|
||||
msgstr "Images inutilisées supprimées :"
|
||||
|
||||
msgctxt "#30371"
|
||||
msgid "Could not connect to the URL you entered, do you want to try again?"
|
||||
msgstr ""
|
||||
"Impossible de se connecter à l'adresse saisie, voulez-vous essayer à nouveau "
|
||||
"?"
|
||||
|
||||
msgctxt "#30370"
|
||||
msgid "Do you want to manually enter a server url?"
|
||||
msgstr "Voulez-vous saisir manuellement une adresse de serveur ?"
|
||||
|
||||
msgctxt "#30369"
|
||||
msgid "Do you want to clear your saved password?"
|
||||
msgstr "Voulez-vous effacer votre mot de passe sauvegardé ?"
|
||||
|
||||
msgctxt "#30368"
|
||||
msgid "Clear Password?"
|
||||
msgstr "Effacer le mot de passe ?"
|
||||
|
||||
msgctxt "#30374"
|
||||
msgid "Sending request"
|
||||
msgstr "Envoyer une requête"
|
||||
|
||||
msgctxt "#30377"
|
||||
msgid "Sending request"
|
||||
msgstr "Envoyer une requête"
|
||||
|
||||
msgctxt "#30376"
|
||||
msgid "Checking server url"
|
||||
msgstr "Vérifier l'url du serveur"
|
||||
|
||||
msgctxt "#30373"
|
||||
msgid "Scanning for local servers"
|
||||
msgstr "Recherche de serveurs locaux"
|
||||
|
||||
msgctxt "#30408"
|
||||
msgid "Custom Widgets"
|
||||
msgstr "Widgets personnalisés"
|
||||
|
||||
msgctxt "#30416"
|
||||
msgid "HTTP timeout seconds"
|
||||
msgstr "Délai HTTP en secondes"
|
||||
|
||||
msgctxt "#30378"
|
||||
msgid "Persist user details"
|
||||
msgstr "Persistance des détails de l'utilisateur"
|
||||
|
||||
msgctxt "#30379"
|
||||
msgid "External subtitle prompt"
|
||||
msgstr "Invite de sous-titres externes"
|
||||
|
||||
msgctxt "#30395"
|
||||
msgid "Clear cached server data"
|
||||
msgstr "Effacer les données du serveur en cache"
|
||||
|
||||
msgctxt "#30434"
|
||||
msgid "Force transcode stream bitrate (Kbits)"
|
||||
msgstr "Forcer le débit du flux de transcodage (Kbps)"
|
||||
|
||||
msgctxt "#30026"
|
||||
msgid "Widget item select action"
|
||||
msgstr "Action de sélection de l'élément du widget"
|
||||
|
||||
msgctxt "#30413"
|
||||
msgid " - Tags"
|
||||
msgstr "- Tags"
|
||||
|
||||
msgctxt "#30433"
|
||||
msgid "Allow direct file playback"
|
||||
msgstr "Autoriser la lecture directe des fichiers"
|
||||
|
||||
msgctxt "#30435"
|
||||
msgid "Connection speed test"
|
||||
msgstr "Test de vitesse de connexion"
|
||||
|
||||
msgctxt "#30440"
|
||||
msgid "Play next"
|
||||
msgstr "Jouer la suite"
|
||||
|
||||
msgctxt "#30441"
|
||||
msgid "Use cached widget data"
|
||||
msgstr "Utiliser les données du widget mises en cache"
|
||||
|
||||
msgctxt "#30442"
|
||||
msgid "Simple new content check"
|
||||
msgstr "Vérification simple du nouveau contenu"
|
||||
|
||||
msgctxt "#30443"
|
||||
msgid "Quick Connect"
|
||||
msgstr "Connexion rapide"
|
||||
|
||||
msgctxt "#30367"
|
||||
msgid "Allow fast user switching password saving"
|
||||
msgstr ""
|
||||
"Autoriser la sauvegarde rapide du changement de mot de passe de l'utilisateur"
|
||||
|
||||
msgctxt "#30375"
|
||||
msgid "Receiving data packet"
|
||||
msgstr "Réception du paquet de données"
|
||||
|
||||
msgctxt "#30384"
|
||||
msgid "Random movies interval minutes (0 = disabled)"
|
||||
msgstr "Intervalle de films aléatoires en minutes (0 = désactivé)"
|
||||
|
||||
msgctxt "#30385"
|
||||
msgid "Existing images before delete : "
|
||||
msgstr "Images existantes avant la suppression :"
|
||||
|
||||
msgctxt "#30400"
|
||||
msgid "Cache images interval minutes (0 = disabled)"
|
||||
msgstr "Intervalle de mise en cache des images en minutes (0 = désactivé)"
|
||||
|
||||
msgctxt "#30409"
|
||||
msgid "Add-on Actions"
|
||||
msgstr "Add-on Actions"
|
||||
|
||||
msgctxt "#30430"
|
||||
msgid "Label"
|
||||
msgstr "Étiquette"
|
||||
|
||||
msgctxt "#30432"
|
||||
msgid "Hide watched items in lists"
|
||||
msgstr "Masquer les éléments surveillés dans les listes"
|
||||
|
||||
msgctxt "#30436"
|
||||
msgid "Speed test data size (MB)"
|
||||
msgstr "Taille des données du test de vitesse (Mo)"
|
||||
|
||||
msgctxt "#30438"
|
||||
msgid "Play cinema intros"
|
||||
msgstr "Lecture des intros de cinéma"
|
||||
|
||||
msgctxt "#30418"
|
||||
msgid "Audio bitrate (Kbits)"
|
||||
msgstr "Bitrate audio (Kbps)"
|
||||
|
||||
msgctxt "#30439"
|
||||
msgid "Show play next episode at time left in seconds"
|
||||
msgstr "Afficher la lecture du prochain épisode au temps restant en secondes"
|
||||
|
||||
msgctxt "#30444"
|
||||
msgid "Login using Quick Connect"
|
||||
msgstr "Connectez-vous en utilisant Quick Connect"
|
||||
|
||||
msgctxt "#30445"
|
||||
msgid "Continue Watching"
|
||||
msgstr "Continuer à regarder"
|
||||
|
||||
msgctxt "#30446"
|
||||
msgid "There was an error logging in"
|
||||
msgstr "Il y a eu une erreur de connexion"
|
||||
|
||||
msgctxt "#30447"
|
||||
msgid "Max Play Queue Size"
|
||||
msgstr "Taille maximale de la file d'attente"
|
||||
|
||||
msgctxt "#30448"
|
||||
msgid "Shuffle"
|
||||
msgstr "Aléatoire"
|
||||
|
||||
msgctxt "#30449"
|
||||
msgid "Instant Mix"
|
||||
msgstr "Mix instantané"
|
||||
|
||||
msgctxt "#30225"
|
||||
msgid "Interface Mode"
|
||||
msgstr "Mode de l'interface"
|
||||
|
||||
msgctxt "#30226"
|
||||
msgid "Default"
|
||||
msgstr "Par défaut"
|
||||
|
||||
msgctxt "#30227"
|
||||
msgid "Simple"
|
||||
msgstr "Simple"
|
||||
|
||||
msgctxt "#30242"
|
||||
msgid "Force transcode av1"
|
||||
msgstr "Forcer le transcodage av1"
|
||||
|
||||
msgctxt "#30451"
|
||||
msgid "Rewatch Days (0 = Disabled)"
|
||||
msgstr "Revoir dans \"x\" Jours (0 = Désactiver)"
|
||||
|
||||
msgctxt "#30452"
|
||||
msgid "Combine instead of replace (might cause slow-down)"
|
||||
msgstr "Fusionner plutôt que remplacer (peut provoquer des ralentissements)"
|
||||
|
||||
msgctxt "#30450"
|
||||
msgid "Next Up Rewatching"
|
||||
msgstr "Revoir ensuite"
|
||||
|
||||
msgctxt "#30453"
|
||||
msgid "Hide number of items to show on entry title"
|
||||
msgstr "Cacher ne nombre d'éléments à montrer dans les titres d'entrées"
|
||||
|
||||
msgctxt "#30454"
|
||||
msgid " - Totally Unwatched"
|
||||
msgstr " - totalité non vu"
|
||||
|
||||
msgctxt "#30667"
|
||||
msgid "Action to take"
|
||||
msgstr "Action à effectuer"
|
||||
|
||||
msgctxt "#30668"
|
||||
msgid "Start Offset (seconds)"
|
||||
msgstr "Décalage initial (secondes)"
|
||||
|
||||
msgctxt "#30669"
|
||||
msgid "End Offset (seconds)"
|
||||
msgstr "Décalage de fin (secondes)"
|
||||
|
||||
msgctxt "#30666"
|
||||
msgid "Segment Skipper"
|
||||
msgstr "Sauter le contenu"
|
||||
|
||||
msgctxt "#30670"
|
||||
msgid "Intro Skipper"
|
||||
msgstr "Sauter l'introduction"
|
||||
|
||||
msgctxt "#30671"
|
||||
msgid "Credit Skipper"
|
||||
msgstr "Sauter le générique"
|
||||
|
||||
msgctxt "#30672"
|
||||
msgid "Skip"
|
||||
msgstr "Sauter"
|
||||
|
||||
msgctxt "#30673"
|
||||
msgid "Ask"
|
||||
msgstr "Demander"
|
||||
|
||||
msgctxt "#30674"
|
||||
msgid "Do Nothing"
|
||||
msgstr "Ne rien faire"
|
||||
|
||||
msgctxt "#30675"
|
||||
msgid "Commercial Skipper"
|
||||
msgstr "Sauter les publicités"
|
||||
|
||||
msgctxt "#30676"
|
||||
msgid "Preview Skipper"
|
||||
msgstr "Sauter l'aperçu"
|
||||
|
||||
msgctxt "#30677"
|
||||
msgid "Recap Skipper"
|
||||
msgstr "Sauter le récapitulatif"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"PO-Revision-Date: 2022-05-20 04:22+0000\n"
|
||||
"Last-Translator: Sherlock <aggybooy2@gmail.com>\n"
|
||||
"PO-Revision-Date: 2024-07-05 15:41+0000\n"
|
||||
"Last-Translator: Viswanadha Y Manu Sharma <manu.viswanad@gmail.com>\n"
|
||||
"Language-Team: Hindi <https://translate.jellyfin.org/projects/jellycon/"
|
||||
"jellycon/hi/>\n"
|
||||
"Language: hi\n"
|
||||
@@ -9,7 +9,7 @@ msgstr ""
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=n > 1;\n"
|
||||
"X-Generator: Weblate 4.10.1\n"
|
||||
"X-Generator: Weblate 5.4.2\n"
|
||||
|
||||
msgctxt "#30407"
|
||||
msgid "Global Lists"
|
||||
@@ -350,3 +350,371 @@ msgstr "द्वार"
|
||||
msgctxt "#30000"
|
||||
msgid "Host"
|
||||
msgstr "आतिथेय"
|
||||
|
||||
msgctxt "#30118"
|
||||
msgid "Add resume percent to names"
|
||||
msgstr "नामों में फिर शुरू करनेका प्रतिशत जोड़ें"
|
||||
|
||||
msgctxt "#30116"
|
||||
msgid "Add unwatched counts to names"
|
||||
msgstr "नामों में न देखी गई गिनती जोड़ें"
|
||||
|
||||
msgctxt "#30120"
|
||||
msgid "Show load progress"
|
||||
msgstr "लोड प्रगति दिखाएं"
|
||||
|
||||
msgctxt "#30121"
|
||||
msgid "On resume"
|
||||
msgstr "फिर से शुरू करने पर"
|
||||
|
||||
msgctxt "#30139"
|
||||
msgid "No Media Type Set"
|
||||
msgstr "कोई मीडिया प्रकार सेट नहीं"
|
||||
|
||||
msgctxt "#30183"
|
||||
msgid "Include people"
|
||||
msgstr "लोगों को शामिल करें"
|
||||
|
||||
msgctxt "#30208"
|
||||
msgid "Max stream bitrate (Kbits)"
|
||||
msgstr "अधिकतम स्ट्रीम बिटरेट (Kbps)"
|
||||
|
||||
msgctxt "#30212"
|
||||
msgid "Video max width"
|
||||
msgstr "वीडियो की अधिकतम चौड़ाई"
|
||||
|
||||
msgctxt "#30217"
|
||||
msgid "Prompt to delete episode after %"
|
||||
msgstr "% के बाद एपिसोड हटाने का संकेत"
|
||||
|
||||
msgctxt "#30219"
|
||||
msgid " - Prompt before play"
|
||||
msgstr "- खेलने से पहले संकेत दें"
|
||||
|
||||
msgctxt "#30220"
|
||||
msgid "Prompt to delete movie after %"
|
||||
msgstr "% के बाद मूवी हटाने का संकेत"
|
||||
|
||||
msgctxt "#30257"
|
||||
msgid "Movies - Recently Added"
|
||||
msgstr "फ़िल्में - हाल ही में जोड़ी गईं"
|
||||
|
||||
msgctxt "#30265"
|
||||
msgid "Episodes - Next Up"
|
||||
msgstr "एपिसोड - अगला"
|
||||
|
||||
msgctxt "#30163"
|
||||
msgid "Add (cc) if subtitle is available"
|
||||
msgstr "यदि उपशीर्षक उपलब्ध है तो (सीसी) जोड़ें"
|
||||
|
||||
msgctxt "#30182"
|
||||
msgid "Include media stream info"
|
||||
msgstr "मीडिया स्ट्रीम जानकारी शामिल करें"
|
||||
|
||||
msgctxt "#30200"
|
||||
msgid "URL error"
|
||||
msgstr "यूआरएल त्रुटि"
|
||||
|
||||
msgctxt "#30201"
|
||||
msgid "Unable to connect to server"
|
||||
msgstr "सर्वर से कनेक्ट करने में असमर्थ है"
|
||||
|
||||
msgctxt "#30206"
|
||||
msgid "Playback type"
|
||||
msgstr "प्लेबैक प्रकार"
|
||||
|
||||
msgctxt "#30207"
|
||||
msgid "Playback"
|
||||
msgstr "प्लेबैक"
|
||||
|
||||
msgctxt "#30209"
|
||||
msgid "File direct path"
|
||||
msgstr "फ़ाइल का सीधा पथ"
|
||||
|
||||
msgctxt "#30210"
|
||||
msgid "HTTP direct stream"
|
||||
msgstr "HTTP डायरेक्ट स्ट्रीम"
|
||||
|
||||
msgctxt "#30211"
|
||||
msgid "Transcode options"
|
||||
msgstr "ट्रांसकोड विकल्प"
|
||||
|
||||
msgctxt "#30213"
|
||||
msgid "Video force 8 bit"
|
||||
msgstr "वीडियो बल 8 बिट"
|
||||
|
||||
msgctxt "#30214"
|
||||
msgid "Events"
|
||||
msgstr "आयोजन"
|
||||
|
||||
msgctxt "#30215"
|
||||
msgid "On playback stop (100% = disabled)"
|
||||
msgstr "प्लेबैक स्टॉप पर (100% = अक्षम)"
|
||||
|
||||
msgctxt "#30218"
|
||||
msgid "Play next episode after %"
|
||||
msgstr "% के बाद अगला एपिसोड चलाएं"
|
||||
|
||||
msgctxt "#30222"
|
||||
msgid "Item Layout"
|
||||
msgstr "आइटम लेआउट"
|
||||
|
||||
msgctxt "#30223"
|
||||
msgid "Page Size and Filtering"
|
||||
msgstr "पृष्ठ आकार और फ़िल्टरिंग"
|
||||
|
||||
msgctxt "#30224"
|
||||
msgid "Interaction"
|
||||
msgstr "इंटरैक्शन"
|
||||
|
||||
msgctxt "#30258"
|
||||
msgid "Movies - In Progress"
|
||||
msgstr "फ़िल्में - प्रगति पर हैं"
|
||||
|
||||
msgctxt "#30126"
|
||||
msgid "Processing Item : "
|
||||
msgstr "आइटम का प्रसंस्करण:"
|
||||
|
||||
msgctxt "#30267"
|
||||
msgid " - In Progress"
|
||||
msgstr "- प्रगति पर है"
|
||||
|
||||
msgctxt "#30268"
|
||||
msgid " - Recently Added"
|
||||
msgstr "- हाल ही में जोड़ा"
|
||||
|
||||
msgctxt "#30225"
|
||||
msgid "Interface Mode"
|
||||
msgstr "इंटरफ़ेस मोड"
|
||||
|
||||
msgctxt "#30226"
|
||||
msgid "Default"
|
||||
msgstr "डिफ़ॉल्ट"
|
||||
|
||||
msgctxt "#30227"
|
||||
msgid "Simple"
|
||||
msgstr "सरल"
|
||||
|
||||
msgctxt "#30236"
|
||||
msgid "Force transcode h265 (hevc)"
|
||||
msgstr "फोर्स ट्रांसकोड h265 (hevc)"
|
||||
|
||||
msgctxt "#30237"
|
||||
msgid "Start from beginning"
|
||||
msgstr "शुरू से शुरू करो"
|
||||
|
||||
msgctxt "#30238"
|
||||
msgid "Playback stream options"
|
||||
msgstr "प्लेबैक स्ट्रीम विकल्प"
|
||||
|
||||
msgctxt "#30239"
|
||||
msgid "Force transcode mpeg2"
|
||||
msgstr "फोर्स ट्रांसकोड mpeg2"
|
||||
|
||||
msgctxt "#30240"
|
||||
msgid "Force transcode msmpeg4v3 (divx)"
|
||||
msgstr "फोर्स ट्रांसकोड msmpeg4v3 (divx)"
|
||||
|
||||
msgctxt "#30241"
|
||||
msgid "Force transcode mpeg4"
|
||||
msgstr "फोर्स ट्रांसकोड mpeg4"
|
||||
|
||||
msgctxt "#30247"
|
||||
msgid "Custom Widget Content"
|
||||
msgstr "कस्टम विजेट सामग्री"
|
||||
|
||||
msgctxt "#30250"
|
||||
msgid "Unknown"
|
||||
msgstr "अज्ञात"
|
||||
|
||||
msgctxt "#30251"
|
||||
msgid "Movies - Genres"
|
||||
msgstr "फ़िल्में - शैलियाँ"
|
||||
|
||||
msgctxt "#30252"
|
||||
msgid "Movies - A-Z"
|
||||
msgstr "फ़िल्में - ए-जेड"
|
||||
|
||||
msgctxt "#30254"
|
||||
msgid "Show add-on settings"
|
||||
msgstr "ऐड-ऑन सेटिंग दिखाएं"
|
||||
|
||||
msgctxt "#30255"
|
||||
msgid "TV Shows - A-Z"
|
||||
msgstr "टीवी शो - ए-जेड"
|
||||
|
||||
msgctxt "#30256"
|
||||
msgid "Movies"
|
||||
msgstr "फ़िल्म"
|
||||
|
||||
msgctxt "#30259"
|
||||
msgid "Movies - Favorites"
|
||||
msgstr "फ़िल्में - पसंदीदा"
|
||||
|
||||
msgctxt "#30260"
|
||||
msgid "BoxSets"
|
||||
msgstr "बॉक्ससेट"
|
||||
|
||||
msgctxt "#30261"
|
||||
msgid "TV Shows"
|
||||
msgstr "टीवी शो"
|
||||
|
||||
msgctxt "#30262"
|
||||
msgid "TV Shows - Favorites"
|
||||
msgstr "टीवी शो - पसंदीदा"
|
||||
|
||||
msgctxt "#30263"
|
||||
msgid "Episodes - Recently Added"
|
||||
msgstr "एपिसोड - हाल ही में जोड़े गए"
|
||||
|
||||
msgctxt "#30264"
|
||||
msgid "Episodes - In Progress"
|
||||
msgstr "एपिसोड - प्रगति पर है"
|
||||
|
||||
msgctxt "#30266"
|
||||
msgid "Movies - Pages"
|
||||
msgstr "फ़िल्में - पन्ने"
|
||||
|
||||
msgctxt "#30269"
|
||||
msgid "Movies - Random"
|
||||
msgstr "फ़िल्में - यादृच्छिक"
|
||||
|
||||
msgctxt "#30270"
|
||||
msgid "Mark Watched"
|
||||
msgstr "मार्क वॉचड"
|
||||
|
||||
msgctxt "#30271"
|
||||
msgid "Mark Unwatched"
|
||||
msgstr "मार्क अनवॉच्ड"
|
||||
|
||||
msgctxt "#30272"
|
||||
msgid "Set Favourite"
|
||||
msgstr "पसंदीदा सेट करें"
|
||||
|
||||
msgctxt "#30273"
|
||||
msgid "Unset Favourite"
|
||||
msgstr "पसंदीदा को अनसेट करें"
|
||||
|
||||
msgctxt "#30274"
|
||||
msgid "Delete"
|
||||
msgstr "मिटाना"
|
||||
|
||||
msgctxt "#30275"
|
||||
msgid "Force Transcode"
|
||||
msgstr "फोर्स ट्रांसकोड"
|
||||
|
||||
msgctxt "#30296"
|
||||
msgid "Delete"
|
||||
msgstr "मिटाना"
|
||||
|
||||
msgctxt "#30300"
|
||||
msgid "Cache all Jellyfin images as local Kodi images?"
|
||||
msgstr "सभी जेलीफ़िन छवियों को स्थानीय कोडी छवियों के रूप में कैश करें?"
|
||||
|
||||
msgctxt "#30301"
|
||||
msgid "Caching Images"
|
||||
msgstr "छवियाँ कैशिंग"
|
||||
|
||||
msgctxt "#30278"
|
||||
msgid " - Next Up"
|
||||
msgstr "- अगला"
|
||||
|
||||
msgctxt "#30302"
|
||||
msgid "Existing images : "
|
||||
msgstr "मौजूदा छवियाँ:"
|
||||
|
||||
msgctxt "#30242"
|
||||
msgid "Force transcode av1"
|
||||
msgstr "फोर्स ट्रांसकोड av1"
|
||||
|
||||
msgctxt "#30288"
|
||||
msgid " - Latest"
|
||||
msgstr "- नवीनतम"
|
||||
|
||||
msgctxt "#30289"
|
||||
msgid "TV Shows - Genres"
|
||||
msgstr "टीवी शो - शैलियाँ"
|
||||
|
||||
msgctxt "#30297"
|
||||
msgid "Delete unused images?"
|
||||
msgstr "अप्रयुक्त छवियाँ हटाएँ?"
|
||||
|
||||
msgctxt "#30298"
|
||||
msgid "Deleting Kodi Images"
|
||||
msgstr "कोडी छवियाँ हटाना"
|
||||
|
||||
msgctxt "#30299"
|
||||
msgid "Cache Images"
|
||||
msgstr "कैश छवियाँ"
|
||||
|
||||
msgctxt "#30303"
|
||||
msgid "Missing Jellyfin images : "
|
||||
msgstr "गुम जेलीफ़िन छवियाँ:"
|
||||
|
||||
msgctxt "#30279"
|
||||
msgid "TV Shows - Unwatched"
|
||||
msgstr "टीवी शो - नहीं देखे गए"
|
||||
|
||||
msgctxt "#30280"
|
||||
msgid "Missing Title"
|
||||
msgstr "गुम शीर्षक"
|
||||
|
||||
msgctxt "#30282"
|
||||
msgid "No Jellyfin servers detected on your local network."
|
||||
msgstr "आपके स्थानीय नेटवर्क पर कोई जेलीफ़िन सर्वर नहीं पाया गया।"
|
||||
|
||||
msgctxt "#30283"
|
||||
msgid "Play Next Episode?"
|
||||
msgstr "अगला एपिसोड खेलें?"
|
||||
|
||||
msgctxt "#30281"
|
||||
msgid "Refresh Cached Images"
|
||||
msgstr "कैश्ड छवियाँ ताज़ा करें"
|
||||
|
||||
msgctxt "#30285"
|
||||
msgid " - Unwatched"
|
||||
msgstr "- न देखा गया"
|
||||
|
||||
msgctxt "#30286"
|
||||
msgid "Movies - Unwatched"
|
||||
msgstr "फिल्में - नहीं देखी गईं"
|
||||
|
||||
msgctxt "#30287"
|
||||
msgid "TV Shows - Latest"
|
||||
msgstr "टीवी शो - नवीनतम"
|
||||
|
||||
msgctxt "#30294"
|
||||
msgid "Notice"
|
||||
msgstr "सूचना"
|
||||
|
||||
msgctxt "#30295"
|
||||
msgid "To use this feature you need HTTP control enabled"
|
||||
msgstr "इस सुविधा का उपयोग करने के लिए आपको HTTP नियंत्रण सक्षम करना होगा"
|
||||
|
||||
msgctxt "#30290"
|
||||
msgid "All"
|
||||
msgstr "सभी"
|
||||
|
||||
msgctxt "#30291"
|
||||
msgid "Select Audio Stream"
|
||||
msgstr "ऑडियो स्ट्रीम चुनें"
|
||||
|
||||
msgctxt "#30292"
|
||||
msgid "Select Subtitle Stream"
|
||||
msgstr "उपशीर्षक स्ट्रीम का चयन करें"
|
||||
|
||||
msgctxt "#30293"
|
||||
msgid "Cache images"
|
||||
msgstr "कैश छवियाँ"
|
||||
|
||||
msgctxt "#30304"
|
||||
msgid "Cached Jellyfin images : "
|
||||
msgstr "कैश्ड जेलीफ़िन छवियाँ:"
|
||||
|
||||
msgctxt "#30305"
|
||||
msgid "Not Found"
|
||||
msgstr "नहीं मिला"
|
||||
|
||||
msgctxt "#30306"
|
||||
msgid "Playback starting"
|
||||
msgstr "प्लेबैक प्रारंभ हो रहा है"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"PO-Revision-Date: 2022-06-08 04:22+0000\n"
|
||||
"Last-Translator: Csaba <csab0825@gmail.com>\n"
|
||||
"PO-Revision-Date: 2026-01-04 21:05+0000\n"
|
||||
"Last-Translator: Levente Suli <suli.levente.07@icloud.com>\n"
|
||||
"Language-Team: Hungarian <https://translate.jellyfin.org/projects/jellycon/"
|
||||
"jellycon/hu/>\n"
|
||||
"Language: hu\n"
|
||||
@@ -9,7 +9,7 @@ msgstr ""
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=n != 1;\n"
|
||||
"X-Generator: Weblate 4.10.1\n"
|
||||
"X-Generator: Weblate 5.15.1\n"
|
||||
|
||||
msgctxt "#30441"
|
||||
msgid "Use cached widget data"
|
||||
@@ -1086,7 +1086,7 @@ msgstr "Port"
|
||||
|
||||
msgctxt "#30000"
|
||||
msgid "Host"
|
||||
msgstr "Hoszt"
|
||||
msgstr "Gazdagép"
|
||||
|
||||
msgctxt "#30444"
|
||||
msgid "Login using Quick Connect"
|
||||
@@ -1099,3 +1099,131 @@ msgstr "Gyors Csatlakozás"
|
||||
msgctxt "#30323"
|
||||
msgid "Artists"
|
||||
msgstr "Művészek"
|
||||
|
||||
msgctxt "#30445"
|
||||
msgid "Continue Watching"
|
||||
msgstr "Megtekintés folytatása"
|
||||
|
||||
msgctxt "#30439"
|
||||
msgid "Show play next episode at time left in seconds"
|
||||
msgstr "A következő epizód lejátszása a másodpercben hátralévő időpontban"
|
||||
|
||||
msgctxt "#30446"
|
||||
msgid "There was an error logging in"
|
||||
msgstr "Hiba történt a bejelentkezéskor"
|
||||
|
||||
msgctxt "#30448"
|
||||
msgid "Shuffle"
|
||||
msgstr "Keverés"
|
||||
|
||||
msgctxt "#30447"
|
||||
msgid "Max Play Queue Size"
|
||||
msgstr "Lejátszási sor maximális mérete"
|
||||
|
||||
msgctxt "#30449"
|
||||
msgid "Instant Mix"
|
||||
msgstr "Instant keverés"
|
||||
|
||||
msgctxt "#30226"
|
||||
msgid "Default"
|
||||
msgstr "Alapértelmezett"
|
||||
|
||||
msgctxt "#30225"
|
||||
msgid "Interface Mode"
|
||||
msgstr "Interfész mód"
|
||||
|
||||
msgctxt "#30227"
|
||||
msgid "Simple"
|
||||
msgstr "Egyszerű"
|
||||
|
||||
msgctxt "#30242"
|
||||
msgid "Force transcode av1"
|
||||
msgstr "av1 transzkódolás kényszerítése"
|
||||
|
||||
msgctxt "#30450"
|
||||
msgid "Next Up Rewatching"
|
||||
msgstr "A Következő Újrajátszása"
|
||||
|
||||
msgctxt "#30451"
|
||||
msgid "Rewatch Days (0 = Disabled)"
|
||||
msgstr "Újrajátszási Napok (0=Kikapcsolva)"
|
||||
|
||||
msgctxt "#30452"
|
||||
msgid "Combine instead of replace (might cause slow-down)"
|
||||
msgstr "Egyesítés csere helyett (lassulást okozhat)"
|
||||
|
||||
msgctxt "#30453"
|
||||
msgid "Hide number of items to show on entry title"
|
||||
msgstr "Elemek számának rejtése a cím mellett"
|
||||
|
||||
msgctxt "#30454"
|
||||
msgid " - Totally Unwatched"
|
||||
msgstr " Megnézetlen"
|
||||
|
||||
msgctxt "#30667"
|
||||
msgid "Action to take"
|
||||
msgstr "Teendő"
|
||||
|
||||
msgctxt "#30668"
|
||||
msgid "Start Offset (seconds)"
|
||||
msgstr "Kezdési eltérés (másodpercben)"
|
||||
|
||||
msgctxt "#30669"
|
||||
msgid "End Offset (seconds)"
|
||||
msgstr "Befejezési késleltetés"
|
||||
|
||||
msgctxt "#30670"
|
||||
msgid "Intro Skipper"
|
||||
msgstr "Intróátugró"
|
||||
|
||||
msgctxt "#30666"
|
||||
msgid "Segment Skipper"
|
||||
msgstr "Részlet átugró"
|
||||
|
||||
msgctxt "#30671"
|
||||
msgid "Credit Skipper"
|
||||
msgstr "Stáblistaátugró"
|
||||
|
||||
msgctxt "#30672"
|
||||
msgid "Skip"
|
||||
msgstr "Átugrás"
|
||||
|
||||
msgctxt "#30674"
|
||||
msgid "Do Nothing"
|
||||
msgstr "Ne csináljon semmit"
|
||||
|
||||
msgctxt "#30675"
|
||||
msgid "Commercial Skipper"
|
||||
msgstr "Reklámátugró"
|
||||
|
||||
msgctxt "#30676"
|
||||
msgid "Preview Skipper"
|
||||
msgstr "Előnézet átugró"
|
||||
|
||||
msgctxt "#30673"
|
||||
msgid "Ask"
|
||||
msgstr "Kérdezz"
|
||||
|
||||
msgctxt "#30677"
|
||||
msgid "Recap Skipper"
|
||||
msgstr "Összefoglaló átugró"
|
||||
|
||||
msgctxt "#30455"
|
||||
msgid "TV Shows - Random"
|
||||
msgstr "TV Műsorok - Véletlenszerű"
|
||||
|
||||
msgctxt "#30456"
|
||||
msgid "All - Random"
|
||||
msgstr "Összes - Véletlenszerű"
|
||||
|
||||
msgctxt "#30457"
|
||||
msgid "All - Recently Added"
|
||||
msgstr "Összes - Nemrég hozzáadott"
|
||||
|
||||
msgctxt "#30458"
|
||||
msgid "All - Favorites"
|
||||
msgstr "Összes - Kedvencek"
|
||||
|
||||
msgctxt "#30678"
|
||||
msgid "TV Shows per page"
|
||||
msgstr "TV Műsorok oldalanként"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"PO-Revision-Date: 2022-05-20 04:22+0000\n"
|
||||
"Last-Translator: liimee <git.taaa@fedora.email>\n"
|
||||
"PO-Revision-Date: 2026-01-05 12:25+0000\n"
|
||||
"Last-Translator: daryhanif <daryhanif00@gmail.com>\n"
|
||||
"Language-Team: Indonesian <https://translate.jellyfin.org/projects/jellycon/"
|
||||
"jellycon/id/>\n"
|
||||
"Language: id\n"
|
||||
@@ -9,7 +9,7 @@ msgstr ""
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=1; plural=0;\n"
|
||||
"X-Generator: Weblate 4.10.1\n"
|
||||
"X-Generator: Weblate 5.15.1\n"
|
||||
|
||||
msgctxt "#30414"
|
||||
msgid " - Favorites"
|
||||
@@ -482,3 +482,732 @@ msgstr "Kata sandi"
|
||||
msgctxt "#30005"
|
||||
msgid "Username"
|
||||
msgstr "Nama pengguna"
|
||||
|
||||
msgctxt "#30315"
|
||||
msgid "Suppress notifications for connection errors"
|
||||
msgstr "Menekan notifikasi untuk kesalahan koneksi"
|
||||
|
||||
msgctxt "#30016"
|
||||
msgid "Device display name"
|
||||
msgstr "Nama tampilan perangkat"
|
||||
|
||||
msgctxt "#30015"
|
||||
msgid "Log timing data"
|
||||
msgstr "Catat data waktu"
|
||||
|
||||
msgctxt "#30445"
|
||||
msgid "Continue Watching"
|
||||
msgstr "Lanjutkan Tonton"
|
||||
|
||||
msgctxt "#30444"
|
||||
msgid "Login using Quick Connect"
|
||||
msgstr "Login dengan Koneksi Cepat"
|
||||
|
||||
msgctxt "#30443"
|
||||
msgid "Quick Connect"
|
||||
msgstr "Koneksi Cepat"
|
||||
|
||||
msgctxt "#30442"
|
||||
msgid "Simple new content check"
|
||||
msgstr "Cek konten baru sederhana"
|
||||
|
||||
msgctxt "#30441"
|
||||
msgid "Use cached widget data"
|
||||
msgstr "Gunakan data widget yang di-cache"
|
||||
|
||||
msgctxt "#30439"
|
||||
msgid "Show play next episode at time left"
|
||||
msgstr "Tampilkan putar episode pada waktu tersisa"
|
||||
|
||||
msgctxt "#30438"
|
||||
msgid "Play cinema intros"
|
||||
msgstr "Mainkan intro sinema"
|
||||
|
||||
msgctxt "#30437"
|
||||
msgid "Playback options"
|
||||
msgstr "Opsi pemutaran"
|
||||
|
||||
msgctxt "#30436"
|
||||
msgid "Speed test data size (MB)"
|
||||
msgstr "Besar data untuk uji kecepatan (MB)"
|
||||
|
||||
msgctxt "#30435"
|
||||
msgid "Connection speed test"
|
||||
msgstr "Uji kecepatan koneksi"
|
||||
|
||||
msgctxt "#30434"
|
||||
msgid "Force transcode stream bitrate (Kbits)"
|
||||
msgstr "Memaksa kecepatan bit aliran transkode (Kbps)"
|
||||
|
||||
msgctxt "#30433"
|
||||
msgid "Allow direct file playback"
|
||||
msgstr "Izinkan pemutaran berkas langsung"
|
||||
|
||||
msgctxt "#30432"
|
||||
msgid "Hide watched items in lists"
|
||||
msgstr "Sembunyikan item yang telah ditonton dari daftar"
|
||||
|
||||
msgctxt "#30429"
|
||||
msgid "Genre"
|
||||
msgstr "Genre"
|
||||
|
||||
msgctxt "#30428"
|
||||
msgid "Rating"
|
||||
msgstr "Penilaian"
|
||||
|
||||
msgctxt "#30424"
|
||||
msgid "Default"
|
||||
msgstr "Default"
|
||||
|
||||
msgctxt "#30423"
|
||||
msgid "NotSet"
|
||||
msgstr "Belum Diatur"
|
||||
|
||||
msgctxt "#30422"
|
||||
msgid "Sorting"
|
||||
msgstr "Urutkan"
|
||||
|
||||
msgctxt "#30421"
|
||||
msgid "Views"
|
||||
msgstr "Tampilan"
|
||||
|
||||
msgctxt "#30420"
|
||||
msgid "Audio max channels"
|
||||
msgstr "Channel maks. Audio"
|
||||
|
||||
msgctxt "#30419"
|
||||
msgid "Audio codec"
|
||||
msgstr "Kodek Audio"
|
||||
|
||||
msgctxt "#30418"
|
||||
msgid "Audio bitrate (Kbits)"
|
||||
msgstr "Bitrate Audio (Kbps)"
|
||||
|
||||
msgctxt "#30416"
|
||||
msgid "HTTP timeout seconds"
|
||||
msgstr "Detik HTTP timeout"
|
||||
|
||||
msgctxt "#30415"
|
||||
msgid " - Favorite Collections"
|
||||
msgstr "- Koleksi Favorit"
|
||||
|
||||
msgctxt "#30413"
|
||||
msgid " - Tags"
|
||||
msgstr "- Tag"
|
||||
|
||||
msgctxt "#30412"
|
||||
msgid " - Decades"
|
||||
msgstr "- Dekade"
|
||||
|
||||
msgctxt "#30411"
|
||||
msgid " - Years"
|
||||
msgstr "- Tahun"
|
||||
|
||||
msgctxt "#30410"
|
||||
msgid " - Collections"
|
||||
msgstr "- Koleksi"
|
||||
|
||||
msgctxt "#30409"
|
||||
msgid "Add-on Actions"
|
||||
msgstr "Aksi Add-on"
|
||||
|
||||
msgctxt "#30408"
|
||||
msgid "Custom Widgets"
|
||||
msgstr "Widget Kustom"
|
||||
|
||||
msgctxt "#30407"
|
||||
msgid "Global Lists"
|
||||
msgstr "Daftar Global"
|
||||
|
||||
msgctxt "#30406"
|
||||
msgid "Jellyfin Libraries"
|
||||
msgstr "Pustaka Jellyfin"
|
||||
|
||||
msgctxt "#30400"
|
||||
msgid "Cache images interval minutes (0 = disabled)"
|
||||
msgstr "Interval cache gambar dalam menit (0 = dimatikan)"
|
||||
|
||||
msgctxt "#30397"
|
||||
msgid " - Pages"
|
||||
msgstr "- Halaman"
|
||||
|
||||
msgctxt "#30395"
|
||||
msgid "Clear cached server data"
|
||||
msgstr "Hapus server data yang di-cache"
|
||||
|
||||
msgctxt "#30394"
|
||||
msgid "Cache files deleted"
|
||||
msgstr "File cache dihapus"
|
||||
|
||||
msgctxt "#30393"
|
||||
msgid "Clear Cache Result"
|
||||
msgstr "Hapus Hasil Cache"
|
||||
|
||||
msgctxt "#30387"
|
||||
msgid "Unused images removed : "
|
||||
msgstr "Gambar yang tidak digunakan dihapus:"
|
||||
|
||||
msgctxt "#30386"
|
||||
msgid "Unused Jellyfin images : "
|
||||
msgstr "Gambar Jellyfin yang tidak digunakan:"
|
||||
|
||||
msgctxt "#30385"
|
||||
msgid "Existing images before delete : "
|
||||
msgstr "Gambar yang ada sebelum dihapus:"
|
||||
|
||||
msgctxt "#30384"
|
||||
msgid "Random movies interval minutes (0 = disabled)"
|
||||
msgstr "Menit interval film acak (0 = dinonaktifkan)"
|
||||
|
||||
msgctxt "#30379"
|
||||
msgid "External subtitle prompt"
|
||||
msgstr "Perintah subtitle eksternal"
|
||||
|
||||
msgctxt "#30378"
|
||||
msgid "Persist user details"
|
||||
msgstr "Pertahankan detail pengguna"
|
||||
|
||||
msgctxt "#30375"
|
||||
msgid "Receiving data packet"
|
||||
msgstr "Menerima paket data"
|
||||
|
||||
msgctxt "#30370"
|
||||
msgid "Do you want to manually enter a server url?"
|
||||
msgstr "Apakah Anda ingin untuk memasukkan url server secara manual?"
|
||||
|
||||
msgctxt "#30369"
|
||||
msgid "Do you want to clear your saved password?"
|
||||
msgstr "Apakah Anda ingin untuk menghapus kata sandi tersimpan?"
|
||||
|
||||
msgctxt "#30368"
|
||||
msgid "Clear Password?"
|
||||
msgstr "Kosongkan Kata Sandi?"
|
||||
|
||||
msgctxt "#30367"
|
||||
msgid "Allow fast user switching password saving"
|
||||
msgstr "Izinkan untuk menyimpan kata sandi dari pengguna yang telah beralih"
|
||||
|
||||
msgctxt "#30366"
|
||||
msgid "Manually enter user details"
|
||||
msgstr "Masukkan detail pengguna secara manual"
|
||||
|
||||
msgctxt "#30365"
|
||||
msgid "Manual Login"
|
||||
msgstr "Login Manual"
|
||||
|
||||
msgctxt "#30359"
|
||||
msgid "Building full image list"
|
||||
msgstr "Membangun daftar gambar penuh"
|
||||
|
||||
msgctxt "#30358"
|
||||
msgid "Retreiving remote image list"
|
||||
msgstr "Menerima daftar gambar jarak jauh"
|
||||
|
||||
msgctxt "#30357"
|
||||
msgid "Processing existing image list"
|
||||
msgstr "Memproses gambar yang telah ada"
|
||||
|
||||
msgctxt "#30356"
|
||||
msgid "Loading existing image list"
|
||||
msgstr "Muat gambar yang telah ada"
|
||||
|
||||
msgctxt "#30355"
|
||||
msgid "Kodi Settings->Services->Allow remote control via HTTP"
|
||||
msgstr "Pengaturan Kodi->Layanan->Izinkan kendali jarak jauh HTTP"
|
||||
|
||||
msgctxt "#30354"
|
||||
msgid "Go To Series"
|
||||
msgstr "Pergi ke Seri"
|
||||
|
||||
msgctxt "#30321"
|
||||
msgid " - Album Artists"
|
||||
msgstr "- Artis Album"
|
||||
|
||||
msgctxt "#30319"
|
||||
msgid "Music - All Album Artists"
|
||||
msgstr "Musik - Semua Artis Album"
|
||||
|
||||
msgctxt "#30351"
|
||||
msgid "Music - Recently Played"
|
||||
msgstr "Musik - Baru-baru ini diputar"
|
||||
|
||||
msgctxt "#30349"
|
||||
msgid " - Recently Played"
|
||||
msgstr "- Baru-baru ini diputar"
|
||||
|
||||
msgctxt "#30348"
|
||||
msgid "Add user ratings"
|
||||
msgstr "Tambahkan rating pengguna"
|
||||
|
||||
msgctxt "#30347"
|
||||
msgid "Getting Existing Images"
|
||||
msgstr "Mengambil gambar yang telah ada"
|
||||
|
||||
msgctxt "#30346"
|
||||
msgid "Deleteing Cached Images"
|
||||
msgstr "Menghapus Gambar yang di-cache"
|
||||
|
||||
msgctxt "#30345"
|
||||
msgid "Cache Jellyfin server data requests"
|
||||
msgstr "Cache permintaan server data Jellyfin"
|
||||
|
||||
msgctxt "#30344"
|
||||
msgid "Number of images removed from cache"
|
||||
msgstr "Jumlah gambar yang dihapus dari cache"
|
||||
|
||||
msgctxt "#30343"
|
||||
msgid "Changes Require Kodi Restart"
|
||||
msgstr "Perubahan Memerlukan Pemuatan Ulang Kodi"
|
||||
|
||||
msgctxt "#30342"
|
||||
msgid "New content check interval (0 = disabled)"
|
||||
msgstr "Interval pemeriksaan konten baru (0 = dimatikan)"
|
||||
|
||||
msgctxt "#30340"
|
||||
msgid "Group movies into collections"
|
||||
msgstr "Gabungkan film ke dalam koleksi"
|
||||
|
||||
msgctxt "#30334"
|
||||
msgid "Use JellyCon context menu"
|
||||
msgstr "Gunakan konteks menu JellyCon"
|
||||
|
||||
msgctxt "#30333"
|
||||
msgid "Cache artwork in the background"
|
||||
msgstr "Cache karya seni di latar belakang"
|
||||
|
||||
msgctxt "#30332"
|
||||
msgid "Stop media playback on screensaver activation"
|
||||
msgstr "Hentikan pemutaran media ketika screensaver aktif"
|
||||
|
||||
msgctxt "#30328"
|
||||
msgid "Show empty folders (shows, seasons, collections)"
|
||||
msgstr "Tampilkan folder kosong (acara, musim, koleksi)"
|
||||
|
||||
msgctxt "#30330"
|
||||
msgid "Show change user dialog"
|
||||
msgstr "Tampilkan dialog pergantian pengguna"
|
||||
|
||||
msgctxt "#30329"
|
||||
msgid "Screensaver"
|
||||
msgstr "Screensaver"
|
||||
|
||||
msgctxt "#30327"
|
||||
msgid "Go To Season"
|
||||
msgstr "Pergi ke Musim"
|
||||
|
||||
msgctxt "#30325"
|
||||
msgid " - Genres"
|
||||
msgstr "- Genre"
|
||||
|
||||
msgctxt "#30323"
|
||||
msgid "Artists"
|
||||
msgstr "Artis"
|
||||
|
||||
msgctxt "#30322"
|
||||
msgid "Auto resume"
|
||||
msgstr "Lanjutkan otomatis"
|
||||
|
||||
msgctxt "#30316"
|
||||
msgid "Connection Error"
|
||||
msgstr "Kesalahan Koneksi"
|
||||
|
||||
msgctxt "#30311"
|
||||
msgid "Library - "
|
||||
msgstr "Pustaka -"
|
||||
|
||||
msgctxt "#30310"
|
||||
msgid "Enable Jellyfin remote control"
|
||||
msgstr "Nyalakan kendali jarak jauh Jellyfin"
|
||||
|
||||
msgctxt "#30308"
|
||||
msgid "Select Trailer"
|
||||
msgstr "Pilih Trailer"
|
||||
|
||||
msgctxt "#30307"
|
||||
msgid "Play Trailer"
|
||||
msgstr "Mulai Trailer"
|
||||
|
||||
msgctxt "#30304"
|
||||
msgid "Cached Jellyfin images : "
|
||||
msgstr "Gambar Jellyfin yang di-cache:"
|
||||
|
||||
msgctxt "#30303"
|
||||
msgid "Missing Jellyfin images : "
|
||||
msgstr "Gambar Jellyfin yang hilang:"
|
||||
|
||||
msgctxt "#30302"
|
||||
msgid "Existing images : "
|
||||
msgstr "Gambar yang Ada:"
|
||||
|
||||
msgctxt "#30301"
|
||||
msgid "Caching Images"
|
||||
msgstr "Sedang Caching Gambar"
|
||||
|
||||
msgctxt "#30300"
|
||||
msgid "Cache all Jellyfin images as local Kodi images?"
|
||||
msgstr "Cache semua gambar Jellyfin sebagai gambar Kodi lokal?"
|
||||
|
||||
msgctxt "#30299"
|
||||
msgid "Cache Images"
|
||||
msgstr "Gambar Cache"
|
||||
|
||||
msgctxt "#30298"
|
||||
msgid "Deleting Kodi Images"
|
||||
msgstr "Menghapus Gambar Kodi"
|
||||
|
||||
msgctxt "#30295"
|
||||
msgid "To use this feature you need HTTP control enabled"
|
||||
msgstr "Anda perlu menyalakan kontrol HTTP untuk menggunakan fitur ini"
|
||||
|
||||
msgctxt "#30294"
|
||||
msgid "Notice"
|
||||
msgstr "Peringatan"
|
||||
|
||||
msgctxt "#30293"
|
||||
msgid "Cache images"
|
||||
msgstr "Gambar Cache"
|
||||
|
||||
msgctxt "#30292"
|
||||
msgid "Select Subtitle Stream"
|
||||
msgstr "Pilih Stream Subtitle"
|
||||
|
||||
msgctxt "#30291"
|
||||
msgid "Select Audio Stream"
|
||||
msgstr "Pilih Audio Stream"
|
||||
|
||||
msgctxt "#30289"
|
||||
msgid "TV Shows - Genres"
|
||||
msgstr "Acara TV - Genre"
|
||||
|
||||
msgctxt "#30281"
|
||||
msgid "Refresh Cached Images"
|
||||
msgstr "Segarkan Gambar yang Di-cache"
|
||||
|
||||
msgctxt "#30280"
|
||||
msgid "Missing Title"
|
||||
msgstr "Judul yang Hilang"
|
||||
|
||||
msgctxt "#30277"
|
||||
msgid "JellyCon needs to prompt for resume on partily played items, Kodi can also prompt, this can cause a double prompt. Do you want to remove the double prompt?"
|
||||
msgstr ""
|
||||
"JellyCon perlu meminta resume pada item yang dimainkan sebagian, Kodi juga "
|
||||
"dapat meminta, ini dapat menyebabkan prompt ganda. Apakah Anda ingin "
|
||||
"menghapus perintah ganda?"
|
||||
|
||||
msgctxt "#30276"
|
||||
msgid "Extra Resume Prompt Detected"
|
||||
msgstr "Prompt Resume Ekstra Terdeteksi"
|
||||
|
||||
msgctxt "#30275"
|
||||
msgid "Force Transcode"
|
||||
msgstr "Paksa Transkode"
|
||||
|
||||
msgctxt "#30273"
|
||||
msgid "Unset Favourite"
|
||||
msgstr "Hapus Favorit"
|
||||
|
||||
msgctxt "#30272"
|
||||
msgid "Set Favourite"
|
||||
msgstr "Atur Favorit"
|
||||
|
||||
msgctxt "#30267"
|
||||
msgid " - In Progress"
|
||||
msgstr "- Sedang Ditonton"
|
||||
|
||||
msgctxt "#30266"
|
||||
msgid "Movies - Pages"
|
||||
msgstr "Film - Halaman"
|
||||
|
||||
msgctxt "#30264"
|
||||
msgid "Episodes - In Progress"
|
||||
msgstr "Episode - Sedang Ditonton"
|
||||
|
||||
msgctxt "#30260"
|
||||
msgid "BoxSets"
|
||||
msgstr "Set Kotak"
|
||||
|
||||
msgctxt "#30258"
|
||||
msgid "Movies - In Progress"
|
||||
msgstr "Film - Sedang ditonton"
|
||||
|
||||
msgctxt "#30251"
|
||||
msgid "Movies - Genres"
|
||||
msgstr "Film - Genre"
|
||||
|
||||
msgctxt "#30250"
|
||||
msgid "Unknown"
|
||||
msgstr "Tidak diketahui"
|
||||
|
||||
msgctxt "#30247"
|
||||
msgid "Custom Widget Content"
|
||||
msgstr "Konten Widget Kustom"
|
||||
|
||||
msgctxt "#30241"
|
||||
msgid "Force transcode mpeg4"
|
||||
msgstr "Paksa transkode mpeg4"
|
||||
|
||||
msgctxt "#30240"
|
||||
msgid "Force transcode msmpeg4v3 (divx)"
|
||||
msgstr "Paksa transkode msmmpeg4v3 (divx)"
|
||||
|
||||
msgctxt "#30239"
|
||||
msgid "Force transcode mpeg2"
|
||||
msgstr "Paksa transkode mpeg2"
|
||||
|
||||
msgctxt "#30238"
|
||||
msgid "Playback stream options"
|
||||
msgstr "Opsi stream pemutaran"
|
||||
|
||||
msgctxt "#30236"
|
||||
msgid "Force transcode h265 (hevc)"
|
||||
msgstr "Paksa transkode h265 (hevc)"
|
||||
|
||||
msgctxt "#30223"
|
||||
msgid "Page Size and Filtering"
|
||||
msgstr "Ukuran Halaman dan Filter"
|
||||
|
||||
msgctxt "#30220"
|
||||
msgid "Prompt to delete movie after %"
|
||||
msgstr "Tanyakan untuk menghapus film setelah %"
|
||||
|
||||
msgctxt "#30219"
|
||||
msgid " - Prompt before play"
|
||||
msgstr "- Tanyakan sebelum memutar"
|
||||
|
||||
msgctxt "#30218"
|
||||
msgid "Play next episode after %"
|
||||
msgstr "Putar episode selanjutnya setelah %"
|
||||
|
||||
msgctxt "#30217"
|
||||
msgid "Prompt to delete episode after %"
|
||||
msgstr "Tanyakan untuk menghapus episode setelah %"
|
||||
|
||||
msgctxt "#30215"
|
||||
msgid "On playback stop (100% = disabled)"
|
||||
msgstr "Henti ketika menonton (100% = dimatikan)"
|
||||
|
||||
msgctxt "#30214"
|
||||
msgid "Events"
|
||||
msgstr "Acara"
|
||||
|
||||
msgctxt "#30213"
|
||||
msgid "Video force 8 bit"
|
||||
msgstr "Paksa video 8 bit"
|
||||
|
||||
msgctxt "#30212"
|
||||
msgid "Video max width"
|
||||
msgstr "Lebar maks. video"
|
||||
|
||||
msgctxt "#30211"
|
||||
msgid "Transcode options"
|
||||
msgstr "Opsi transkode"
|
||||
|
||||
msgctxt "#30210"
|
||||
msgid "HTTP direct stream"
|
||||
msgstr "Stream HTTP langsung"
|
||||
|
||||
msgctxt "#30209"
|
||||
msgid "File direct path"
|
||||
msgstr "Jalur file langsung"
|
||||
|
||||
msgctxt "#30208"
|
||||
msgid "Max stream bitrate (Kbits)"
|
||||
msgstr "Maks. stream bitrate (Kbps)"
|
||||
|
||||
msgctxt "#30183"
|
||||
msgid "Include people"
|
||||
msgstr "Termasuk oran"
|
||||
|
||||
msgctxt "#30182"
|
||||
msgid "Include media stream info"
|
||||
msgstr "Termasuk info stream media"
|
||||
|
||||
msgctxt "#30181"
|
||||
msgid "Include plot"
|
||||
msgstr "Termasuk plot"
|
||||
|
||||
msgctxt "#30139"
|
||||
msgid "No Media Type Set"
|
||||
msgstr "Tidak ada tipe media yang ditetapkan"
|
||||
|
||||
msgctxt "#30125"
|
||||
msgid "Done"
|
||||
msgstr "Selesai"
|
||||
|
||||
msgctxt "#30121"
|
||||
msgid "On resume"
|
||||
msgstr "Sedang diteruskan"
|
||||
|
||||
msgctxt "#30120"
|
||||
msgid "Show load progress"
|
||||
msgstr "Tampilkan progres muat"
|
||||
|
||||
msgctxt "#30118"
|
||||
msgid "Add resume percent to names"
|
||||
msgstr "Tambahkan persen resume ke nama"
|
||||
|
||||
msgctxt "#30116"
|
||||
msgid "Add unwatched counts to names"
|
||||
msgstr "Tambahkan jumlah yang belum ditonton ke nama"
|
||||
|
||||
msgctxt "#30114"
|
||||
msgid "Jump back seconds"
|
||||
msgstr "Kembali beberapa detik"
|
||||
|
||||
msgctxt "#30112"
|
||||
msgid "Loading Content"
|
||||
msgstr "Memuat konten"
|
||||
|
||||
msgctxt "#30063"
|
||||
msgid "N/A"
|
||||
msgstr "Tidak ada"
|
||||
|
||||
msgctxt "#30053"
|
||||
msgid "Waiting for server to delete"
|
||||
msgstr "Menunggu server untuk menghapus"
|
||||
|
||||
msgctxt "#30027"
|
||||
msgid "Enable debug logging"
|
||||
msgstr "Nyalakan debug logging"
|
||||
|
||||
msgctxt "#30026"
|
||||
msgid "Widget item select action"
|
||||
msgstr "Aksi ketika item widget terpilih"
|
||||
|
||||
msgctxt "#30020"
|
||||
msgid "Flatten single season"
|
||||
msgstr "Ratakan musim tunggal"
|
||||
|
||||
msgctxt "#30019"
|
||||
msgid "Filtered episode name format"
|
||||
msgstr "Format penamaan episode terfilter"
|
||||
|
||||
msgctxt "#30018"
|
||||
msgid "Number of items to show in filtered lists"
|
||||
msgstr "Jumlah item yang ditunjukkan di daftar terfilter"
|
||||
|
||||
msgctxt "#30012"
|
||||
msgid "[Change user]"
|
||||
msgstr "[Ganti pengguna]"
|
||||
|
||||
msgctxt "#30011"
|
||||
msgid "[Detect local server]"
|
||||
msgstr "[Deteksi server lokal]"
|
||||
|
||||
msgctxt "#30010"
|
||||
msgid "Number of performance profiles to capture"
|
||||
msgstr "Jumlah profil performa"
|
||||
|
||||
msgctxt "#30000"
|
||||
msgid "Host"
|
||||
msgstr "Host"
|
||||
|
||||
msgctxt "#30448"
|
||||
msgid "Shuffle"
|
||||
msgstr "Acak"
|
||||
|
||||
msgctxt "#30447"
|
||||
msgid "Max Play Queue Size"
|
||||
msgstr "Maksimum Ukuran Antrian Putar"
|
||||
|
||||
msgctxt "#30439"
|
||||
msgid "Show play next episode at time left in seconds"
|
||||
msgstr ""
|
||||
"Tampilkan putar episode berikutnya dengan waktu yang tersisa dalam detik"
|
||||
|
||||
msgctxt "#30446"
|
||||
msgid "There was an error logging in"
|
||||
msgstr "Terjadi kesalahan saat masuk"
|
||||
|
||||
msgctxt "#30449"
|
||||
msgid "Instant Mix"
|
||||
msgstr "Campuran Instan"
|
||||
|
||||
msgctxt "#30242"
|
||||
msgid "Force transcode av1"
|
||||
msgstr "Paksa transkode av1"
|
||||
|
||||
msgctxt "#30451"
|
||||
msgid "Rewatch Days (0 = Disabled)"
|
||||
msgstr "Jeda Tonton Ulang (0 = Nonaktif)"
|
||||
|
||||
msgctxt "#30452"
|
||||
msgid "Combine instead of replace (might cause slow-down)"
|
||||
msgstr "Gabungkan, bukan Gantikan (berisiko memperlambat)"
|
||||
|
||||
msgctxt "#30453"
|
||||
msgid "Hide number of items to show on entry title"
|
||||
msgstr "Sembunyikan Jumlah Item di Judul"
|
||||
|
||||
msgctxt "#30454"
|
||||
msgid " - Totally Unwatched"
|
||||
msgstr " - Belum Pernah Ditonton"
|
||||
|
||||
msgctxt "#30450"
|
||||
msgid "Next Up Rewatching"
|
||||
msgstr "Tampilkan Tontonan Ulang"
|
||||
|
||||
msgctxt "#30225"
|
||||
msgid "Interface Mode"
|
||||
msgstr "Mode Antarmuka"
|
||||
|
||||
msgctxt "#30226"
|
||||
msgid "Default"
|
||||
msgstr "Baku"
|
||||
|
||||
msgctxt "#30227"
|
||||
msgid "Simple"
|
||||
msgstr "Simpel"
|
||||
|
||||
msgctxt "#30666"
|
||||
msgid "Segment Skipper"
|
||||
msgstr "Lewatkan Segmen"
|
||||
|
||||
msgctxt "#30667"
|
||||
msgid "Action to take"
|
||||
msgstr "Aksi yang diambil"
|
||||
|
||||
msgctxt "#30668"
|
||||
msgid "Start Offset (seconds)"
|
||||
msgstr "Mulai Offset(detik)"
|
||||
|
||||
msgctxt "#30669"
|
||||
msgid "End Offset (seconds)"
|
||||
msgstr "Akhir Offset(detik)"
|
||||
|
||||
msgctxt "#30670"
|
||||
msgid "Intro Skipper"
|
||||
msgstr "Lewatkan intro"
|
||||
|
||||
msgctxt "#30671"
|
||||
msgid "Credit Skipper"
|
||||
msgstr "Lewatkan Credit"
|
||||
|
||||
msgctxt "#30673"
|
||||
msgid "Ask"
|
||||
msgstr "Tanya"
|
||||
|
||||
msgctxt "#30674"
|
||||
msgid "Do Nothing"
|
||||
msgstr "Tidak Ada"
|
||||
|
||||
msgctxt "#30675"
|
||||
msgid "Commercial Skipper"
|
||||
msgstr "Melewatkan iklan"
|
||||
|
||||
msgctxt "#30676"
|
||||
msgid "Preview Skipper"
|
||||
msgstr "Melewatkan Cuplikan"
|
||||
|
||||
msgctxt "#30672"
|
||||
msgid "Skip"
|
||||
msgstr "Lewatkan"
|
||||
|
||||
msgctxt "#30677"
|
||||
msgid "Recap Skipper"
|
||||
msgstr "Lewati Rekap"
|
||||
|
||||
#, fuzzy
|
||||
msgctxt "#30457"
|
||||
msgid "All - Recently Added"
|
||||
msgstr "Semua - Baru-Baru ini ditambahkan"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"PO-Revision-Date: 2022-06-28 13:22+0000\n"
|
||||
"Last-Translator: Michele Fattoruso <michele.fattoruso@gmail.com>\n"
|
||||
"PO-Revision-Date: 2026-01-02 12:03+0000\n"
|
||||
"Last-Translator: ittelicra <alexarciletti10@gmail.com>\n"
|
||||
"Language-Team: Italian <https://translate.jellyfin.org/projects/jellycon/"
|
||||
"jellycon/it/>\n"
|
||||
"Language: it\n"
|
||||
@@ -9,11 +9,11 @@ msgstr ""
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=n != 1;\n"
|
||||
"X-Generator: Weblate 4.10.1\n"
|
||||
"X-Generator: Weblate 5.15.1\n"
|
||||
|
||||
msgctxt "#30120"
|
||||
msgid "Show load progress"
|
||||
msgstr "Mostra avanzamento del caricamento"
|
||||
msgstr "Mostra progressione del caricamento"
|
||||
|
||||
msgctxt "#30118"
|
||||
msgid "Add resume percent to names"
|
||||
@@ -49,7 +49,7 @@ msgstr "Attenzione: questa operazione eliminerà i file multimediali dal server.
|
||||
|
||||
msgctxt "#30091"
|
||||
msgid "Confirm delete?"
|
||||
msgstr "Confermi l'eliminazione?"
|
||||
msgstr "Confermare l'eliminazione?"
|
||||
|
||||
msgctxt "#30063"
|
||||
msgid "N/A"
|
||||
@@ -73,7 +73,7 @@ msgstr "Nome utente/Password errati"
|
||||
|
||||
msgctxt "#30027"
|
||||
msgid "Enable debug logging"
|
||||
msgstr "Attiva log a debug"
|
||||
msgstr "Attiva log di debug"
|
||||
|
||||
msgctxt "#30026"
|
||||
msgid "Widget item select action"
|
||||
@@ -89,7 +89,7 @@ msgstr "Nome utente:"
|
||||
|
||||
msgctxt "#30023"
|
||||
msgid "Hide unwatched episode details"
|
||||
msgstr "Nascondi dettagli episodi non guardati"
|
||||
msgstr "Nascondi i dettagli degli episodi non guardati"
|
||||
|
||||
msgctxt "#30022"
|
||||
msgid "Advanced"
|
||||
@@ -385,7 +385,7 @@ msgstr "Disposizione elemento"
|
||||
|
||||
msgctxt "#30220"
|
||||
msgid "Prompt to delete movie after %"
|
||||
msgstr "Chiedi se eliminare il film dopo %"
|
||||
msgstr "Chiedi di eliminare il film dopo %"
|
||||
|
||||
msgctxt "#30219"
|
||||
msgid " - Prompt before play"
|
||||
@@ -397,7 +397,7 @@ msgstr "Riproduci il prossimo episodio dopo %"
|
||||
|
||||
msgctxt "#30217"
|
||||
msgid "Prompt to delete episode after %"
|
||||
msgstr "Chiedi se eliminare l'episodio dopo %"
|
||||
msgstr "Chiedi di eliminare l'episodio dopo %"
|
||||
|
||||
msgctxt "#30216"
|
||||
msgid "Item Details"
|
||||
@@ -431,7 +431,7 @@ msgctxt "#30277"
|
||||
msgid "JellyCon needs to prompt for resume on partily played items, Kodi can also prompt, this can cause a double prompt. Do you want to remove the double prompt?"
|
||||
msgstr ""
|
||||
"JellyCon richiede una finestra per continuare la riproduzione di elementi, "
|
||||
"anche Kodi può richiedere una finestra, causando lapertura di una doppia "
|
||||
"anche Kodi può richiedere una finestra, causando lapertura di una doppia "
|
||||
"finestra. Vuoi rimuovere la doppia finestra?"
|
||||
|
||||
msgctxt "#30213"
|
||||
@@ -441,3 +441,784 @@ msgstr "Forza video 8 bit"
|
||||
msgctxt "#30114"
|
||||
msgid "Jump back seconds"
|
||||
msgstr "Riavvolgi secondi"
|
||||
|
||||
msgctxt "#30331"
|
||||
msgid "Movies per page"
|
||||
msgstr "Film per pagina"
|
||||
|
||||
msgctxt "#30329"
|
||||
msgid "Screensaver"
|
||||
msgstr "Salvaschermo"
|
||||
|
||||
msgctxt "#30337"
|
||||
msgid "Song"
|
||||
msgstr "Canzone"
|
||||
|
||||
msgctxt "#30327"
|
||||
msgid "Go To Season"
|
||||
msgstr "Vai Alla Stagione"
|
||||
|
||||
msgctxt "#30325"
|
||||
msgid " - Genres"
|
||||
msgstr "- Generi"
|
||||
|
||||
msgctxt "#30323"
|
||||
msgid "Artists"
|
||||
msgstr "Artisti"
|
||||
|
||||
msgctxt "#30311"
|
||||
msgid "Library - "
|
||||
msgstr "Libreria -"
|
||||
|
||||
msgctxt "#30296"
|
||||
msgid "Delete"
|
||||
msgstr "Elimina"
|
||||
|
||||
msgctxt "#30288"
|
||||
msgid " - Latest"
|
||||
msgstr "- Ultimo"
|
||||
|
||||
msgctxt "#30280"
|
||||
msgid "Missing Title"
|
||||
msgstr "Titolo Mancante"
|
||||
|
||||
msgctxt "#30278"
|
||||
msgid " - Next Up"
|
||||
msgstr "- Prossimo"
|
||||
|
||||
msgctxt "#30312"
|
||||
msgid "All - "
|
||||
msgstr "Tutto -"
|
||||
|
||||
msgctxt "#30320"
|
||||
msgid " - Albums"
|
||||
msgstr "- Album"
|
||||
|
||||
msgctxt "#30279"
|
||||
msgid "TV Shows - Unwatched"
|
||||
msgstr "Serie TV - Non guardati"
|
||||
|
||||
msgctxt "#30282"
|
||||
msgid "No Jellyfin servers detected on your local network."
|
||||
msgstr "Nessun server Jellyfin rilevato nella tua rete locale."
|
||||
|
||||
msgctxt "#30286"
|
||||
msgid "Movies - Unwatched"
|
||||
msgstr "Film - Non guardati"
|
||||
|
||||
msgctxt "#30287"
|
||||
msgid "TV Shows - Latest"
|
||||
msgstr "Serie TV - Ultimi"
|
||||
|
||||
msgctxt "#30289"
|
||||
msgid "TV Shows - Genres"
|
||||
msgstr "Serie TV - Generi"
|
||||
|
||||
msgctxt "#30290"
|
||||
msgid "All"
|
||||
msgstr "Tutti"
|
||||
|
||||
msgctxt "#30291"
|
||||
msgid "Select Audio Stream"
|
||||
msgstr "Seleziona fonte audio"
|
||||
|
||||
msgctxt "#30297"
|
||||
msgid "Delete unused images?"
|
||||
msgstr "Eliminare immagini non usati?"
|
||||
|
||||
msgctxt "#30305"
|
||||
msgid "Not Found"
|
||||
msgstr "Non trovato"
|
||||
|
||||
msgctxt "#30306"
|
||||
msgid "Playback starting"
|
||||
msgstr "Avvio riproduzione"
|
||||
|
||||
msgctxt "#30307"
|
||||
msgid "Play Trailer"
|
||||
msgstr "Riproduci Trailer"
|
||||
|
||||
msgctxt "#30308"
|
||||
msgid "Select Trailer"
|
||||
msgstr "Seleziona Trailer"
|
||||
|
||||
msgctxt "#30313"
|
||||
msgid "Menu"
|
||||
msgstr "Menù"
|
||||
|
||||
msgctxt "#30314"
|
||||
msgid "Play"
|
||||
msgstr "Riproduci"
|
||||
|
||||
msgctxt "#30316"
|
||||
msgid "Connection Error"
|
||||
msgstr "Errore di connessione"
|
||||
|
||||
msgctxt "#30318"
|
||||
msgid "Music - Albums"
|
||||
msgstr "Musica - Album"
|
||||
|
||||
msgctxt "#30322"
|
||||
msgid "Auto resume"
|
||||
msgstr "Ripresa automatica"
|
||||
|
||||
msgctxt "#30328"
|
||||
msgid "Show empty folders (shows, seasons, collections)"
|
||||
msgstr "Mostra cartelle vuote (serie, stagioni, collezioni)"
|
||||
|
||||
msgctxt "#30285"
|
||||
msgid " - Unwatched"
|
||||
msgstr "- Non visto"
|
||||
|
||||
msgctxt "#30303"
|
||||
msgid "Missing Jellyfin images : "
|
||||
msgstr "Immagini mancanti di Jellyfin:"
|
||||
|
||||
msgctxt "#30330"
|
||||
msgid "Show change user dialog"
|
||||
msgstr "Mostra la finestra di cambio utente"
|
||||
|
||||
msgctxt "#30332"
|
||||
msgid "Stop media playback on screensaver activation"
|
||||
msgstr ""
|
||||
"Interrompi la riproduzione multimediale all'attivazione dello screensaver"
|
||||
|
||||
msgctxt "#30338"
|
||||
msgid "Album"
|
||||
msgstr "Album"
|
||||
|
||||
msgctxt "#30340"
|
||||
msgid "Group movies into collections"
|
||||
msgstr "Raggruppa film in collezioni"
|
||||
|
||||
msgctxt "#30281"
|
||||
msgid "Refresh Cached Images"
|
||||
msgstr "Aggiorna immagine in cache"
|
||||
|
||||
msgctxt "#30292"
|
||||
msgid "Select Subtitle Stream"
|
||||
msgstr "Seleziona fonte sottotitoli"
|
||||
|
||||
msgctxt "#30293"
|
||||
msgid "Cache images"
|
||||
msgstr "Memorizza in cache immagini"
|
||||
|
||||
msgctxt "#30310"
|
||||
msgid "Enable Jellyfin remote control"
|
||||
msgstr "Abilitare il controllo remoto di Jellyfin"
|
||||
|
||||
msgctxt "#30317"
|
||||
msgid "Play All"
|
||||
msgstr "Riproduci tutto"
|
||||
|
||||
msgctxt "#30283"
|
||||
msgid "Play Next Episode?"
|
||||
msgstr "Riprodurre episodio successivo?"
|
||||
|
||||
msgctxt "#30295"
|
||||
msgid "To use this feature you need HTTP control enabled"
|
||||
msgstr "Per poter utilizzare questa funzione devi abilitare il controllo HTTP"
|
||||
|
||||
msgctxt "#30298"
|
||||
msgid "Deleting Kodi Images"
|
||||
msgstr "Eliminazione immagini di Kodi"
|
||||
|
||||
msgctxt "#30302"
|
||||
msgid "Existing images : "
|
||||
msgstr "Immagini presenti:"
|
||||
|
||||
msgctxt "#30309"
|
||||
msgid "Select Media Source"
|
||||
msgstr "Seleziona sorgente multimediale"
|
||||
|
||||
msgctxt "#30315"
|
||||
msgid "Suppress notifications for connection errors"
|
||||
msgstr "Elimina le notifiche per gli errori di connessione"
|
||||
|
||||
msgctxt "#30344"
|
||||
msgid "Number of images removed from cache"
|
||||
msgstr "Numero di immagini rimosse dalla cache"
|
||||
|
||||
msgctxt "#30304"
|
||||
msgid "Cached Jellyfin images : "
|
||||
msgstr "Immagini Jellyfin salvate nella cache:"
|
||||
|
||||
msgctxt "#30334"
|
||||
msgid "Use JellyCon context menu"
|
||||
msgstr "Usa menu contestuale di JellyCon"
|
||||
|
||||
msgctxt "#30346"
|
||||
msgid "Deleteing Cached Images"
|
||||
msgstr "Eliminazione immagini salvate nella cache"
|
||||
|
||||
msgctxt "#30347"
|
||||
msgid "Getting Existing Images"
|
||||
msgstr "Recupero immagini esistenti"
|
||||
|
||||
msgctxt "#30343"
|
||||
msgid "Changes Require Kodi Restart"
|
||||
msgstr "Le modifiche richiedono il riavvio di Kodi"
|
||||
|
||||
msgctxt "#30339"
|
||||
msgid "Person"
|
||||
msgstr "Persona"
|
||||
|
||||
msgctxt "#30294"
|
||||
msgid "Notice"
|
||||
msgstr "Avviso"
|
||||
|
||||
msgctxt "#30299"
|
||||
msgid "Cache Images"
|
||||
msgstr "Memorizza in cache le immagini"
|
||||
|
||||
msgctxt "#30300"
|
||||
msgid "Cache all Jellyfin images as local Kodi images?"
|
||||
msgstr "Memorizzare tutte le immagini Jellyfin come immagini locali Kodi?"
|
||||
|
||||
msgctxt "#30414"
|
||||
msgid " - Favorites"
|
||||
msgstr "- Preferiti"
|
||||
|
||||
msgctxt "#30333"
|
||||
msgid "Cache artwork in the background"
|
||||
msgstr "Memorizza artwork in background"
|
||||
|
||||
msgctxt "#30349"
|
||||
msgid " - Recently Played"
|
||||
msgstr "- Riprodotti di recente"
|
||||
|
||||
msgctxt "#30350"
|
||||
msgid "Music - Recently Added"
|
||||
msgstr "Musica - Aggiunta di recente"
|
||||
|
||||
msgctxt "#30352"
|
||||
msgid "Music - Frequently Played"
|
||||
msgstr "Musica - Ascoltata frequentemente"
|
||||
|
||||
msgctxt "#30319"
|
||||
msgid "Music - All Album Artists"
|
||||
msgstr "Musica - Artisti dell'album"
|
||||
|
||||
msgctxt "#30354"
|
||||
msgid "Go To Series"
|
||||
msgstr "Vai alle Serie"
|
||||
|
||||
msgctxt "#30355"
|
||||
msgid "Kodi Settings->Services->Allow remote control via HTTP"
|
||||
msgstr "Impostazioni di Kodi -> Servizi -> Consenti controllo remoto via HTTP"
|
||||
|
||||
msgctxt "#30360"
|
||||
msgid " - Channels"
|
||||
msgstr "- Canali"
|
||||
|
||||
msgctxt "#30361"
|
||||
msgid " - Programs"
|
||||
msgstr "- Programmi"
|
||||
|
||||
msgctxt "#30362"
|
||||
msgid " - Recordings"
|
||||
msgstr "- Registrazioni"
|
||||
|
||||
msgctxt "#30366"
|
||||
msgid "Manually enter user details"
|
||||
msgstr "Inserisci manualmente i dettagli dell'utente"
|
||||
|
||||
msgctxt "#30375"
|
||||
msgid "Receiving data packet"
|
||||
msgstr "Ottengo i pacchetti"
|
||||
|
||||
msgctxt "#30377"
|
||||
msgid "Sending request"
|
||||
msgstr "Invio la richiesta"
|
||||
|
||||
msgctxt "#30380"
|
||||
msgid "Never"
|
||||
msgstr "Mai"
|
||||
|
||||
msgctxt "#30381"
|
||||
msgid "More than one"
|
||||
msgstr "Più di uno"
|
||||
|
||||
msgctxt "#30382"
|
||||
msgid "Always"
|
||||
msgstr "Sempre"
|
||||
|
||||
msgctxt "#30383"
|
||||
msgid "System - "
|
||||
msgstr "Sistema -"
|
||||
|
||||
msgctxt "#30390"
|
||||
msgid "Protocol"
|
||||
msgstr "Protocollo"
|
||||
|
||||
msgctxt "#30391"
|
||||
msgid "HTTP"
|
||||
msgstr "HTTP"
|
||||
|
||||
msgctxt "#30392"
|
||||
msgid "HTTPS"
|
||||
msgstr "HTTPS"
|
||||
|
||||
msgctxt "#30397"
|
||||
msgid " - Pages"
|
||||
msgstr "- Pagine"
|
||||
|
||||
msgctxt "#30402"
|
||||
msgid "Add to Kodi Playlist"
|
||||
msgstr "Aggiungi alla playlist di Kodi"
|
||||
|
||||
msgctxt "#30405"
|
||||
msgid " - Show All"
|
||||
msgstr "- Mostra tutto"
|
||||
|
||||
msgctxt "#30408"
|
||||
msgid "Custom Widgets"
|
||||
msgstr "Widget Personalizzati"
|
||||
|
||||
msgctxt "#30409"
|
||||
msgid "Add-on Actions"
|
||||
msgstr "Azioni Add-on"
|
||||
|
||||
msgctxt "#30410"
|
||||
msgid " - Collections"
|
||||
msgstr "- Collezioni"
|
||||
|
||||
msgctxt "#30411"
|
||||
msgid " - Years"
|
||||
msgstr "- Anni"
|
||||
|
||||
msgctxt "#30413"
|
||||
msgid " - Tags"
|
||||
msgstr "- Tags"
|
||||
|
||||
msgctxt "#30415"
|
||||
msgid " - Favorite Collections"
|
||||
msgstr "- Collezioni Preferite"
|
||||
|
||||
msgctxt "#30418"
|
||||
msgid "Audio bitrate (Kbits)"
|
||||
msgstr "Bitrate dell'Audio (Kbps)"
|
||||
|
||||
msgctxt "#30419"
|
||||
msgid "Audio codec"
|
||||
msgstr "Codifica dell'Audio"
|
||||
|
||||
msgctxt "#30420"
|
||||
msgid "Audio max channels"
|
||||
msgstr "Canali massimi dell'audio"
|
||||
|
||||
msgctxt "#30421"
|
||||
msgid "Views"
|
||||
msgstr "Visualizzazioni"
|
||||
|
||||
msgctxt "#30422"
|
||||
msgid "Sorting"
|
||||
msgstr "Ordina"
|
||||
|
||||
msgctxt "#30424"
|
||||
msgid "Default"
|
||||
msgstr "Predefinito"
|
||||
|
||||
msgctxt "#30425"
|
||||
msgid "Year"
|
||||
msgstr "Anno"
|
||||
|
||||
msgctxt "#30301"
|
||||
msgid "Caching Images"
|
||||
msgstr "Memorizzando le immagini"
|
||||
|
||||
msgctxt "#30359"
|
||||
msgid "Building full image list"
|
||||
msgstr "Compongo la lista completa delle immagini"
|
||||
|
||||
msgctxt "#30363"
|
||||
msgid "Save Password?"
|
||||
msgstr "Salvare la Password?"
|
||||
|
||||
msgctxt "#30364"
|
||||
msgid "Do you want to save the password?"
|
||||
msgstr "Vuoi salvare la Password?"
|
||||
|
||||
msgctxt "#30368"
|
||||
msgid "Clear Password?"
|
||||
msgstr "Cancellare la Password?"
|
||||
|
||||
msgctxt "#30371"
|
||||
msgid "Could not connect to the URL you entered, do you want to try again?"
|
||||
msgstr "Non è stato possibile connettersi con l'URL fornito, vuoi riprovare?"
|
||||
|
||||
msgctxt "#30372"
|
||||
msgid "Server URL"
|
||||
msgstr "URL del Server"
|
||||
|
||||
msgctxt "#30373"
|
||||
msgid "Scanning for local servers"
|
||||
msgstr "Scansione di server locali"
|
||||
|
||||
msgctxt "#30388"
|
||||
msgid "Server details"
|
||||
msgstr "Dettagli del server"
|
||||
|
||||
msgctxt "#30394"
|
||||
msgid "Cache files deleted"
|
||||
msgstr "File di cache eliminati"
|
||||
|
||||
msgctxt "#30395"
|
||||
msgid "Clear cached server data"
|
||||
msgstr "Elimina la cache del server"
|
||||
|
||||
msgctxt "#30398"
|
||||
msgid "Refresh Jellyfin Metadata"
|
||||
msgstr "Aggiorna i metadati di Jellyfin"
|
||||
|
||||
msgctxt "#30399"
|
||||
msgid "Hide"
|
||||
msgstr "Nascondi"
|
||||
|
||||
msgctxt "#30401"
|
||||
msgid "Info"
|
||||
msgstr "Informazioni"
|
||||
|
||||
msgctxt "#30406"
|
||||
msgid "Jellyfin Libraries"
|
||||
msgstr "Librerie Jellyfin"
|
||||
|
||||
msgctxt "#30407"
|
||||
msgid "Global Lists"
|
||||
msgstr "Lista Globale"
|
||||
|
||||
msgctxt "#30416"
|
||||
msgid "HTTP timeout seconds"
|
||||
msgstr "HTTP timeout secondi"
|
||||
|
||||
msgctxt "#30417"
|
||||
msgid "You do not have permision to delete this item"
|
||||
msgstr "Non hai il permetto di eliminare questo elemento"
|
||||
|
||||
msgctxt "#30426"
|
||||
msgid "Title"
|
||||
msgstr "Titolo"
|
||||
|
||||
msgctxt "#30427"
|
||||
msgid "Added"
|
||||
msgstr "Aggiunto"
|
||||
|
||||
msgctxt "#30428"
|
||||
msgid "Rating"
|
||||
msgstr "Valutazione"
|
||||
|
||||
msgctxt "#30429"
|
||||
msgid "Genre"
|
||||
msgstr "Genere"
|
||||
|
||||
msgctxt "#30430"
|
||||
msgid "Label"
|
||||
msgstr "Etichetta"
|
||||
|
||||
msgctxt "#30431"
|
||||
msgid "Seasons"
|
||||
msgstr "Stagioni"
|
||||
|
||||
msgctxt "#30432"
|
||||
msgid "Hide watched items in lists"
|
||||
msgstr "Nascondi gli elementi già visti dalla lista"
|
||||
|
||||
msgctxt "#30433"
|
||||
msgid "Allow direct file playback"
|
||||
msgstr "Consenti la riproduzione diretta del file"
|
||||
|
||||
msgctxt "#30341"
|
||||
msgid "Background image update interval (0 = disabled)"
|
||||
msgstr "Intervallo di aggiornamento dell'immagine di sfondo (0 = disabilitato)"
|
||||
|
||||
msgctxt "#30348"
|
||||
msgid "Add user ratings"
|
||||
msgstr "Aggiungi valutazioni dell'utente"
|
||||
|
||||
msgctxt "#30351"
|
||||
msgid "Music - Recently Played"
|
||||
msgstr "Musica - Ascoltata di recente"
|
||||
|
||||
msgctxt "#30321"
|
||||
msgid " - Album Artists"
|
||||
msgstr "- Artisti dell'album"
|
||||
|
||||
msgctxt "#30353"
|
||||
msgid " - Frequently Played"
|
||||
msgstr "- Riprodotto frequentemente"
|
||||
|
||||
msgctxt "#30358"
|
||||
msgid "Retreiving remote image list"
|
||||
msgstr "Ottengo lista immagini remota"
|
||||
|
||||
msgctxt "#30365"
|
||||
msgid "Manual Login"
|
||||
msgstr "Accesso Manuale"
|
||||
|
||||
msgctxt "#30369"
|
||||
msgid "Do you want to clear your saved password?"
|
||||
msgstr "Vuoi eliminare le tue password salvate?"
|
||||
|
||||
msgctxt "#30370"
|
||||
msgid "Do you want to manually enter a server url?"
|
||||
msgstr "Vuoi inserire manualmente l'URL del server?"
|
||||
|
||||
msgctxt "#30374"
|
||||
msgid "Sending request"
|
||||
msgstr "Invio la richiesta"
|
||||
|
||||
msgctxt "#30376"
|
||||
msgid "Checking server url"
|
||||
msgstr "Controllo l'URL del server"
|
||||
|
||||
msgctxt "#30378"
|
||||
msgid "Persist user details"
|
||||
msgstr "Conserva i dettagli dell'utente"
|
||||
|
||||
msgctxt "#30389"
|
||||
msgid "User details"
|
||||
msgstr "Dettagli dell'utente"
|
||||
|
||||
msgctxt "#30403"
|
||||
msgid "Movies - Recommendations"
|
||||
msgstr "Film - Consigliati"
|
||||
|
||||
msgctxt "#30404"
|
||||
msgid " - A-Z"
|
||||
msgstr "- A-Z"
|
||||
|
||||
msgctxt "#30412"
|
||||
msgid " - Decades"
|
||||
msgstr "- Decenni"
|
||||
|
||||
msgctxt "#30423"
|
||||
msgid "NotSet"
|
||||
msgstr "Non impostato"
|
||||
|
||||
msgctxt "#30446"
|
||||
msgid "There was an error logging in"
|
||||
msgstr "Si è verificato un errore durante l'accesso"
|
||||
|
||||
msgctxt "#30443"
|
||||
msgid "Quick Connect"
|
||||
msgstr "Connessione rapida"
|
||||
|
||||
msgctxt "#30445"
|
||||
msgid "Continue Watching"
|
||||
msgstr "Continua a guardare"
|
||||
|
||||
msgctxt "#30448"
|
||||
msgid "Shuffle"
|
||||
msgstr "Casuale"
|
||||
|
||||
msgctxt "#30447"
|
||||
msgid "Max Play Queue Size"
|
||||
msgstr "Dimensione massima della coda di riproduzione"
|
||||
|
||||
msgctxt "#30242"
|
||||
msgid "Force transcode av1"
|
||||
msgstr "Forza transcodifica AV1"
|
||||
|
||||
msgctxt "#30356"
|
||||
msgid "Loading existing image list"
|
||||
msgstr "Caricamento lista di immagini esistenti"
|
||||
|
||||
msgctxt "#30384"
|
||||
msgid "Random movies interval minutes (0 = disabled)"
|
||||
msgstr "Intervallo, in minuti, di film casuali (0 = disabilitato)"
|
||||
|
||||
msgctxt "#30385"
|
||||
msgid "Existing images before delete : "
|
||||
msgstr "Immagini esistenti prima della cancellazione:"
|
||||
|
||||
msgctxt "#30386"
|
||||
msgid "Unused Jellyfin images : "
|
||||
msgstr "Immagini Jellyfin inutilizzate:"
|
||||
|
||||
msgctxt "#30387"
|
||||
msgid "Unused images removed : "
|
||||
msgstr "Immagini inutilizzate rimosse:"
|
||||
|
||||
msgctxt "#30393"
|
||||
msgid "Clear Cache Result"
|
||||
msgstr "Cancella la cache dei risultati"
|
||||
|
||||
msgctxt "#30440"
|
||||
msgid "Play next"
|
||||
msgstr "Riproduci prossimo"
|
||||
|
||||
msgctxt "#30441"
|
||||
msgid "Use cached widget data"
|
||||
msgstr "Utilizza dati widget nella cache"
|
||||
|
||||
msgctxt "#30444"
|
||||
msgid "Login using Quick Connect"
|
||||
msgstr "Accedi usando Connessione Rapida"
|
||||
|
||||
msgctxt "#30452"
|
||||
msgid "Combine instead of replace (might cause slow-down)"
|
||||
msgstr "Combina invece di sostituire (può causare rallentamenti)"
|
||||
|
||||
msgctxt "#30342"
|
||||
msgid "New content check interval (0 = disabled)"
|
||||
msgstr "Intervallo di verifica di nuovi contenuti (0 = disabilitato)"
|
||||
|
||||
msgctxt "#30357"
|
||||
msgid "Processing existing image list"
|
||||
msgstr "Analizzando la lista di immagini esistenti"
|
||||
|
||||
msgctxt "#30400"
|
||||
msgid "Cache images interval minutes (0 = disabled)"
|
||||
msgstr "Intervallo, in minuti, della cache delle immagini (0 = disabilitato)"
|
||||
|
||||
msgctxt "#30435"
|
||||
msgid "Connection speed test"
|
||||
msgstr "Test di velocità della connessione"
|
||||
|
||||
msgctxt "#30436"
|
||||
msgid "Speed test data size (MB)"
|
||||
msgstr "Dimensioni dati per il test di velocità (MB)"
|
||||
|
||||
msgctxt "#30437"
|
||||
msgid "Playback options"
|
||||
msgstr "Opzioni di riproduzione"
|
||||
|
||||
msgctxt "#30225"
|
||||
msgid "Interface Mode"
|
||||
msgstr "Modalità interfaccia"
|
||||
|
||||
msgctxt "#30226"
|
||||
msgid "Default"
|
||||
msgstr "Predefinito"
|
||||
|
||||
msgctxt "#30227"
|
||||
msgid "Simple"
|
||||
msgstr "Semplice"
|
||||
|
||||
msgctxt "#30121"
|
||||
msgid "On resume"
|
||||
msgstr "Riprendi"
|
||||
|
||||
msgctxt "#30442"
|
||||
msgid "Simple new content check"
|
||||
msgstr "Ricerca semplice dei nuovi contenuti"
|
||||
|
||||
msgctxt "#30215"
|
||||
msgid "On playback stop (100% = disabled)"
|
||||
msgstr "A riproduzione ferma (100% = disabilitato)"
|
||||
|
||||
msgctxt "#30379"
|
||||
msgid "External subtitle prompt"
|
||||
msgstr "Prompt sottotitolo esterno"
|
||||
|
||||
msgctxt "#30434"
|
||||
msgid "Force transcode stream bitrate (Kbits)"
|
||||
msgstr "Forza transcodifica del bitrate dello stream (Kbps)"
|
||||
|
||||
msgctxt "#30345"
|
||||
msgid "Cache Jellyfin server data requests"
|
||||
msgstr "Stiva dati richieste del server Jellyfin"
|
||||
|
||||
msgctxt "#30439"
|
||||
msgid "Show play next episode at time left in seconds"
|
||||
msgstr "Mostra riproduci il prossimo episodio a tempo rimasto in secondi"
|
||||
|
||||
msgctxt "#30367"
|
||||
msgid "Allow fast user switching password saving"
|
||||
msgstr "Consenti salvataggio veloce della password utente cambiata"
|
||||
|
||||
msgctxt "#30438"
|
||||
msgid "Play cinema intros"
|
||||
msgstr "Riproduci introduzioni cinema"
|
||||
|
||||
msgctxt "#30449"
|
||||
msgid "Instant Mix"
|
||||
msgstr "Mix Istantaneo"
|
||||
|
||||
msgctxt "#30451"
|
||||
msgid "Rewatch Days (0 = Disabled)"
|
||||
msgstr "Giorni per tornare a Guardare (0 = Disabilitato)"
|
||||
|
||||
msgctxt "#30276"
|
||||
msgid "Extra Resume Prompt Detected"
|
||||
msgstr "Finestra di Ripresa Duplicata Rilevata"
|
||||
|
||||
msgctxt "#30450"
|
||||
msgid "Next Up Rewatching"
|
||||
msgstr "Prossimo da Ri-Guardare"
|
||||
|
||||
msgctxt "#30672"
|
||||
msgid "Skip"
|
||||
msgstr "Salta"
|
||||
|
||||
msgctxt "#30673"
|
||||
msgid "Ask"
|
||||
msgstr "Chiedi"
|
||||
|
||||
msgctxt "#30674"
|
||||
msgid "Do Nothing"
|
||||
msgstr "Non fare niente"
|
||||
|
||||
msgctxt "#30453"
|
||||
msgid "Hide number of items to show on entry title"
|
||||
msgstr "Nascondi numero di elementi da mostrare per titolo"
|
||||
|
||||
msgctxt "#30454"
|
||||
msgid " - Totally Unwatched"
|
||||
msgstr " - Non Visto"
|
||||
|
||||
msgctxt "#30668"
|
||||
msgid "Start Offset (seconds)"
|
||||
msgstr "Offset all'avvio (secondi)"
|
||||
|
||||
msgctxt "#30666"
|
||||
msgid "Segment Skipper"
|
||||
msgstr "Salta Segmento"
|
||||
|
||||
msgctxt "#30667"
|
||||
msgid "Action to take"
|
||||
msgstr "Azione da eseguire"
|
||||
|
||||
msgctxt "#30669"
|
||||
msgid "End Offset (seconds)"
|
||||
msgstr "Offset alla fine (secondi)"
|
||||
|
||||
msgctxt "#30670"
|
||||
msgid "Intro Skipper"
|
||||
msgstr "Salta Intro"
|
||||
|
||||
msgctxt "#30671"
|
||||
msgid "Credit Skipper"
|
||||
msgstr "Salta Crediti"
|
||||
|
||||
msgctxt "#30675"
|
||||
msgid "Commercial Skipper"
|
||||
msgstr "Salta Pubblicità"
|
||||
|
||||
msgctxt "#30676"
|
||||
msgid "Preview Skipper"
|
||||
msgstr "Salta Anteprima"
|
||||
|
||||
msgctxt "#30677"
|
||||
msgid "Recap Skipper"
|
||||
msgstr "Salta Riassunto"
|
||||
|
||||
msgctxt "#30455"
|
||||
msgid "TV Shows - Random"
|
||||
msgstr "#30455"
|
||||
|
||||
msgctxt "#30456"
|
||||
msgid "All - Random"
|
||||
msgstr "Tutti - Casuale"
|
||||
|
||||
msgctxt "#30457"
|
||||
msgid "All - Recently Added"
|
||||
msgstr "Tutti - Aggiunti di recente"
|
||||
|
||||
msgctxt "#30458"
|
||||
msgid "All - Favorites"
|
||||
msgstr "Tutti - Preferiti"
|
||||
|
||||
msgctxt "#30678"
|
||||
msgid "TV Shows per page"
|
||||
msgstr "Serie TV per pagina"
|
||||
|
||||
770
resources/language/resource.language.ja/strings.po
Normal file
770
resources/language/resource.language.ja/strings.po
Normal file
@@ -0,0 +1,770 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"PO-Revision-Date: 2025-09-23 16:39+0000\n"
|
||||
"Last-Translator: S H <translate@hayakawa.work>\n"
|
||||
"Language-Team: Japanese <https://translate.jellyfin.org/projects/jellycon/"
|
||||
"jellycon/ja/>\n"
|
||||
"Language: ja\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=1; plural=0;\n"
|
||||
"X-Generator: Weblate 5.11.4\n"
|
||||
|
||||
msgctxt "#30112"
|
||||
msgid "Loading Content"
|
||||
msgstr "コンテンツをロード中"
|
||||
|
||||
msgctxt "#30008"
|
||||
msgid "Samba password"
|
||||
msgstr "Samba パスワード"
|
||||
|
||||
msgctxt "#30016"
|
||||
msgid "Device display name"
|
||||
msgstr "デバイスディスプレイ名"
|
||||
|
||||
msgctxt "#30021"
|
||||
msgid "Show all episodes item"
|
||||
msgstr "全てのエピソードを見る"
|
||||
|
||||
msgctxt "#30044"
|
||||
msgid "Incorrect Username/Password"
|
||||
msgstr "誤ったユーザー名もしくはパスワード"
|
||||
|
||||
msgctxt "#30000"
|
||||
msgid "Host"
|
||||
msgstr "ホスト"
|
||||
|
||||
msgctxt "#30001"
|
||||
msgid "Port"
|
||||
msgstr "ポート"
|
||||
|
||||
msgctxt "#30003"
|
||||
msgid "Verify HTTPS certificate"
|
||||
msgstr "HTTPS証明書を検証"
|
||||
|
||||
msgctxt "#30005"
|
||||
msgid "Username"
|
||||
msgstr "ユーザー名"
|
||||
|
||||
msgctxt "#30006"
|
||||
msgid "Password"
|
||||
msgstr "パスワード"
|
||||
|
||||
msgctxt "#30007"
|
||||
msgid "Samba username"
|
||||
msgstr "Samba ユーザー名"
|
||||
|
||||
msgctxt "#30010"
|
||||
msgid "Number of performance profiles to capture"
|
||||
msgstr "キャプチャするパフォーマンスプロファイルの数"
|
||||
|
||||
msgctxt "#30011"
|
||||
msgid "[Detect local server]"
|
||||
msgstr "[ローカルサーバーを検出]"
|
||||
|
||||
msgctxt "#30012"
|
||||
msgid "[Change user]"
|
||||
msgstr "[ユーザーを変更]"
|
||||
|
||||
msgctxt "#30014"
|
||||
msgid "Jellyfin"
|
||||
msgstr "Jellyfin"
|
||||
|
||||
msgctxt "#30015"
|
||||
msgid "Log timing data"
|
||||
msgstr "ログタイミングデータ"
|
||||
|
||||
msgctxt "#30017"
|
||||
msgid "Show connected clients"
|
||||
msgstr "接続されたクライアントを表示"
|
||||
|
||||
msgctxt "#30018"
|
||||
msgid "Number of items to show in filtered lists"
|
||||
msgstr "フィルターされたリストに表示するアイテムの数"
|
||||
|
||||
msgctxt "#30019"
|
||||
msgid "Filtered episode name format"
|
||||
msgstr "フィルターされたエピソードの名前フォーマット"
|
||||
|
||||
msgctxt "#30022"
|
||||
msgid "Advanced"
|
||||
msgstr "高度"
|
||||
|
||||
msgctxt "#30023"
|
||||
msgid "Hide unwatched episode details"
|
||||
msgstr "観ていないエピソードの詳細を隠す"
|
||||
|
||||
msgctxt "#30024"
|
||||
msgid "Username:"
|
||||
msgstr "ユーザー名:"
|
||||
|
||||
msgctxt "#30025"
|
||||
msgid "Password:"
|
||||
msgstr "パスワード:"
|
||||
|
||||
msgctxt "#30027"
|
||||
msgid "Enable debug logging"
|
||||
msgstr "デバッグロギングを有効化"
|
||||
|
||||
msgctxt "#30045"
|
||||
msgid "Username not found"
|
||||
msgstr "ユーザー名が見つからない"
|
||||
|
||||
msgctxt "#30052"
|
||||
msgid "Deleting"
|
||||
msgstr "削除中"
|
||||
|
||||
msgctxt "#30053"
|
||||
msgid "Waiting for server to delete"
|
||||
msgstr "サーバーが削除するのを待機中"
|
||||
|
||||
msgctxt "#30091"
|
||||
msgid "Confirm delete?"
|
||||
msgstr "削除しますか?"
|
||||
|
||||
msgctxt "#30092"
|
||||
msgid "Warning: This action will delete the media files from the server."
|
||||
msgstr "警告: この操作はサーバーからメディアファイルを削除します。"
|
||||
|
||||
msgctxt "#30110"
|
||||
msgid "Interface"
|
||||
msgstr "インターフェース"
|
||||
|
||||
msgctxt "#30111"
|
||||
msgid "Services"
|
||||
msgstr "サービス"
|
||||
|
||||
msgctxt "#30113"
|
||||
msgid "Retrieving Data"
|
||||
msgstr "データを取得中"
|
||||
|
||||
msgctxt "#30222"
|
||||
msgid "Item Layout"
|
||||
msgstr "アイテムレイアウト"
|
||||
|
||||
msgctxt "#30224"
|
||||
msgid "Interaction"
|
||||
msgstr "インタラクション"
|
||||
|
||||
msgctxt "#30225"
|
||||
msgid "Interface Mode"
|
||||
msgstr "インターフェースモード"
|
||||
|
||||
msgctxt "#30226"
|
||||
msgid "Default"
|
||||
msgstr "既定"
|
||||
|
||||
msgctxt "#30227"
|
||||
msgid "Simple"
|
||||
msgstr "シンプル"
|
||||
|
||||
msgctxt "#30229"
|
||||
msgid "TV Shows"
|
||||
msgstr "TV番組"
|
||||
|
||||
msgctxt "#30231"
|
||||
msgid "Movies"
|
||||
msgstr "映画"
|
||||
|
||||
msgctxt "#30235"
|
||||
msgid "Episodes"
|
||||
msgstr "エピソード"
|
||||
|
||||
msgctxt "#30237"
|
||||
msgid "Start from beginning"
|
||||
msgstr "最初から始める"
|
||||
|
||||
msgctxt "#30239"
|
||||
msgid "Force transcode mpeg2"
|
||||
msgstr "mpeg2でのトランスコードを強制する"
|
||||
|
||||
msgctxt "#30241"
|
||||
msgid "Force transcode mpeg4"
|
||||
msgstr "mpeg4でのトランスコードを強制する"
|
||||
|
||||
msgctxt "#30246"
|
||||
msgid "Search"
|
||||
msgstr "検索"
|
||||
|
||||
msgctxt "#30250"
|
||||
msgid "Unknown"
|
||||
msgstr "不明"
|
||||
|
||||
msgctxt "#30252"
|
||||
msgid "Movies - A-Z"
|
||||
msgstr "映画 - A-Z"
|
||||
|
||||
msgctxt "#30254"
|
||||
msgid "Show add-on settings"
|
||||
msgstr "アドオン設定を見る"
|
||||
|
||||
msgctxt "#30255"
|
||||
msgid "TV Shows - A-Z"
|
||||
msgstr "TV番組 - A-Z"
|
||||
|
||||
msgctxt "#30256"
|
||||
msgid "Movies"
|
||||
msgstr "映画"
|
||||
|
||||
msgctxt "#30257"
|
||||
msgid "Movies - Recently Added"
|
||||
msgstr "映画 - 最近追加された"
|
||||
|
||||
msgctxt "#30258"
|
||||
msgid "Movies - In Progress"
|
||||
msgstr "映画 - 途中"
|
||||
|
||||
msgctxt "#30259"
|
||||
msgid "Movies - Favorites"
|
||||
msgstr "映画 - お気に入り"
|
||||
|
||||
msgctxt "#30260"
|
||||
msgid "BoxSets"
|
||||
msgstr "ボックス・セット"
|
||||
|
||||
msgctxt "#30261"
|
||||
msgid "TV Shows"
|
||||
msgstr "TV番組"
|
||||
|
||||
msgctxt "#30262"
|
||||
msgid "TV Shows - Favorites"
|
||||
msgstr "TV番組 - お気に入り"
|
||||
|
||||
msgctxt "#30264"
|
||||
msgid "Episodes - In Progress"
|
||||
msgstr "エピソード - 途中"
|
||||
|
||||
msgctxt "#30265"
|
||||
msgid "Episodes - Next Up"
|
||||
msgstr "エピソード - 次"
|
||||
|
||||
msgctxt "#30266"
|
||||
msgid "Movies - Pages"
|
||||
msgstr "映画 - ページ"
|
||||
|
||||
msgctxt "#30267"
|
||||
msgid " - In Progress"
|
||||
msgstr "- 途中"
|
||||
|
||||
msgctxt "#30268"
|
||||
msgid " - Recently Added"
|
||||
msgstr "- 最近追加された"
|
||||
|
||||
msgctxt "#30269"
|
||||
msgid "Movies - Random"
|
||||
msgstr "映画 - ランダム"
|
||||
|
||||
msgctxt "#30270"
|
||||
msgid "Mark Watched"
|
||||
msgstr "視聴済みにする"
|
||||
|
||||
msgctxt "#30271"
|
||||
msgid "Mark Unwatched"
|
||||
msgstr "未視聴にする"
|
||||
|
||||
msgctxt "#30272"
|
||||
msgid "Set Favourite"
|
||||
msgstr "お気に入りにする"
|
||||
|
||||
msgctxt "#30273"
|
||||
msgid "Unset Favourite"
|
||||
msgstr "お気に入りから外す"
|
||||
|
||||
msgctxt "#30274"
|
||||
msgid "Delete"
|
||||
msgstr "削除"
|
||||
|
||||
msgctxt "#30275"
|
||||
msgid "Force Transcode"
|
||||
msgstr "トランスコードを強制する"
|
||||
|
||||
msgctxt "#30276"
|
||||
msgid "Extra Resume Prompt Detected"
|
||||
msgstr "追加の再開プロンプトが検出された"
|
||||
|
||||
msgctxt "#30278"
|
||||
msgid " - Next Up"
|
||||
msgstr "- 次"
|
||||
|
||||
msgctxt "#30279"
|
||||
msgid "TV Shows - Unwatched"
|
||||
msgstr "TV番組 - 未視聴"
|
||||
|
||||
msgctxt "#30280"
|
||||
msgid "Missing Title"
|
||||
msgstr "タイトル欠落"
|
||||
|
||||
msgctxt "#30281"
|
||||
msgid "Refresh Cached Images"
|
||||
msgstr "キャッシュしたイメージをリフレッシュする"
|
||||
|
||||
msgctxt "#30282"
|
||||
msgid "No Jellyfin servers detected on your local network."
|
||||
msgstr "ローカルネットワークにJellyfinサーバーは検出されませんでした。"
|
||||
|
||||
msgctxt "#30283"
|
||||
msgid "Play Next Episode?"
|
||||
msgstr "次のエピソードを再生しますか?"
|
||||
|
||||
msgctxt "#30285"
|
||||
msgid " - Unwatched"
|
||||
msgstr "- 未視聴"
|
||||
|
||||
msgctxt "#30286"
|
||||
msgid "Movies - Unwatched"
|
||||
msgstr "映画 - 未視聴"
|
||||
|
||||
msgctxt "#30287"
|
||||
msgid "TV Shows - Latest"
|
||||
msgstr "TV番組 - 最新"
|
||||
|
||||
msgctxt "#30288"
|
||||
msgid " - Latest"
|
||||
msgstr "- 最新"
|
||||
|
||||
msgctxt "#30290"
|
||||
msgid "All"
|
||||
msgstr "全て"
|
||||
|
||||
msgctxt "#30291"
|
||||
msgid "Select Audio Stream"
|
||||
msgstr "音声ストリームを選択"
|
||||
|
||||
msgctxt "#30292"
|
||||
msgid "Select Subtitle Stream"
|
||||
msgstr "サブタイトルストリームを選択"
|
||||
|
||||
msgctxt "#30293"
|
||||
msgid "Cache images"
|
||||
msgstr "イメージをキャッシュする"
|
||||
|
||||
msgctxt "#30294"
|
||||
msgid "Notice"
|
||||
msgstr "通知"
|
||||
|
||||
msgctxt "#30295"
|
||||
msgid "To use this feature you need HTTP control enabled"
|
||||
msgstr "この機能を使うにはHTTPコントロールが有効化されている必要があります"
|
||||
|
||||
msgctxt "#30296"
|
||||
msgid "Delete"
|
||||
msgstr "削除"
|
||||
|
||||
msgctxt "#30297"
|
||||
msgid "Delete unused images?"
|
||||
msgstr "使用されていないイメージを削除しますか?"
|
||||
|
||||
msgctxt "#30299"
|
||||
msgid "Cache Images"
|
||||
msgstr "イメージをキャッシュする"
|
||||
|
||||
msgctxt "#30301"
|
||||
msgid "Caching Images"
|
||||
msgstr "イメージをキャッシュ中"
|
||||
|
||||
msgctxt "#30302"
|
||||
msgid "Existing images : "
|
||||
msgstr "既存のイメージ:"
|
||||
|
||||
msgctxt "#30303"
|
||||
msgid "Missing Jellyfin images : "
|
||||
msgstr "欠落したJellyfinイメージ:"
|
||||
|
||||
msgctxt "#30304"
|
||||
msgid "Cached Jellyfin images : "
|
||||
msgstr "キャッシュされたJellyfinイメージ:"
|
||||
|
||||
msgctxt "#30305"
|
||||
msgid "Not Found"
|
||||
msgstr "見つかりませんでした"
|
||||
|
||||
msgctxt "#30306"
|
||||
msgid "Playback starting"
|
||||
msgstr "再生を開始中"
|
||||
|
||||
msgctxt "#30307"
|
||||
msgid "Play Trailer"
|
||||
msgstr "トレーラーを再生"
|
||||
|
||||
msgctxt "#30308"
|
||||
msgid "Select Trailer"
|
||||
msgstr "トレーラーを選択"
|
||||
|
||||
msgctxt "#30309"
|
||||
msgid "Select Media Source"
|
||||
msgstr "メディアソースを選択"
|
||||
|
||||
msgctxt "#30311"
|
||||
msgid "Library - "
|
||||
msgstr "ライブラリー -"
|
||||
|
||||
msgctxt "#30312"
|
||||
msgid "All - "
|
||||
msgstr "全て -"
|
||||
|
||||
msgctxt "#30313"
|
||||
msgid "Menu"
|
||||
msgstr "メニュー"
|
||||
|
||||
msgctxt "#30314"
|
||||
msgid "Play"
|
||||
msgstr "再生"
|
||||
|
||||
msgctxt "#30315"
|
||||
msgid "Suppress notifications for connection errors"
|
||||
msgstr "接続エラーについての通知を抑制"
|
||||
|
||||
msgctxt "#30316"
|
||||
msgid "Connection Error"
|
||||
msgstr "接続エラー"
|
||||
|
||||
msgctxt "#30317"
|
||||
msgid "Play All"
|
||||
msgstr "全て再生"
|
||||
|
||||
msgctxt "#30318"
|
||||
msgid "Music - Albums"
|
||||
msgstr "音楽 - アルバム"
|
||||
|
||||
msgctxt "#30320"
|
||||
msgid " - Albums"
|
||||
msgstr "- アルバム"
|
||||
|
||||
msgctxt "#30322"
|
||||
msgid "Auto resume"
|
||||
msgstr "自動再開"
|
||||
|
||||
msgctxt "#30323"
|
||||
msgid "Artists"
|
||||
msgstr "アーティスト"
|
||||
|
||||
msgctxt "#30325"
|
||||
msgid " - Genres"
|
||||
msgstr "- ジャンル"
|
||||
|
||||
msgctxt "#30327"
|
||||
msgid "Go To Season"
|
||||
msgstr "シーズンに行く"
|
||||
|
||||
msgctxt "#30328"
|
||||
msgid "Show empty folders (shows, seasons, collections)"
|
||||
msgstr "空のフォルダー(番組, シーズン, コレクション)を見る"
|
||||
|
||||
msgctxt "#30329"
|
||||
msgid "Screensaver"
|
||||
msgstr "スクリーンセーバー"
|
||||
|
||||
msgctxt "#30330"
|
||||
msgid "Show change user dialog"
|
||||
msgstr "ユーザー変更ダイアログを見る"
|
||||
|
||||
msgctxt "#30331"
|
||||
msgid "Movies per page"
|
||||
msgstr "ページごとの映画"
|
||||
|
||||
msgctxt "#30332"
|
||||
msgid "Stop media playback on screensaver activation"
|
||||
msgstr "スクリーンセーバーが始まったらメディア再生をやめる"
|
||||
|
||||
msgctxt "#30334"
|
||||
msgid "Use JellyCon context menu"
|
||||
msgstr "JellyConコンテキストメニューを使う"
|
||||
|
||||
msgctxt "#30337"
|
||||
msgid "Song"
|
||||
msgstr "曲"
|
||||
|
||||
msgctxt "#30338"
|
||||
msgid "Album"
|
||||
msgstr "アルバム"
|
||||
|
||||
msgctxt "#30339"
|
||||
msgid "Person"
|
||||
msgstr "人物"
|
||||
|
||||
msgctxt "#30340"
|
||||
msgid "Group movies into collections"
|
||||
msgstr "映画のグループをコレクションに追加"
|
||||
|
||||
msgctxt "#30341"
|
||||
msgid "Background image update interval (0 = disabled)"
|
||||
msgstr "バックグラウンドのイメージ更新間隔 (0 = 無効)"
|
||||
|
||||
msgctxt "#30342"
|
||||
msgid "New content check interval (0 = disabled)"
|
||||
msgstr "新しいコンテンツの確認間隔 (0 = 無効)"
|
||||
|
||||
msgctxt "#30343"
|
||||
msgid "Changes Require Kodi Restart"
|
||||
msgstr "変更はKodiの再起動を必要とします"
|
||||
|
||||
msgctxt "#30344"
|
||||
msgid "Number of images removed from cache"
|
||||
msgstr "キャッシュから削除されたイメージの数"
|
||||
|
||||
msgctxt "#30345"
|
||||
msgid "Cache Jellyfin server data requests"
|
||||
msgstr "Jellyfinサーバーデータリクエストをキャッシュする"
|
||||
|
||||
msgctxt "#30346"
|
||||
msgid "Deleteing Cached Images"
|
||||
msgstr "キャッシュされたイメージを削除中"
|
||||
|
||||
msgctxt "#30347"
|
||||
msgid "Getting Existing Images"
|
||||
msgstr "既存のイメージを取得中"
|
||||
|
||||
msgctxt "#30348"
|
||||
msgid "Add user ratings"
|
||||
msgstr "ユーザーレーティングを追加"
|
||||
|
||||
msgctxt "#30350"
|
||||
msgid "Music - Recently Added"
|
||||
msgstr "音楽 - 最近追加された"
|
||||
|
||||
msgctxt "#30349"
|
||||
msgid " - Recently Played"
|
||||
msgstr "- 最近再生された"
|
||||
|
||||
msgctxt "#30351"
|
||||
msgid "Music - Recently Played"
|
||||
msgstr "音楽 - 最近再生された"
|
||||
|
||||
msgctxt "#30352"
|
||||
msgid "Music - Frequently Played"
|
||||
msgstr "音楽 - よく再生される"
|
||||
|
||||
msgctxt "#30319"
|
||||
msgid "Music - All Album Artists"
|
||||
msgstr "音楽 - 全てのアルバムアーティスト"
|
||||
|
||||
msgctxt "#30321"
|
||||
msgid " - Album Artists"
|
||||
msgstr "- アルバムアーティスト"
|
||||
|
||||
msgctxt "#30353"
|
||||
msgid " - Frequently Played"
|
||||
msgstr "- よく再生される"
|
||||
|
||||
msgctxt "#30354"
|
||||
msgid "Go To Series"
|
||||
msgstr "シリーズに行く"
|
||||
|
||||
msgctxt "#30356"
|
||||
msgid "Loading existing image list"
|
||||
msgstr "既存のイメージリストを読み込み中"
|
||||
|
||||
msgctxt "#30357"
|
||||
msgid "Processing existing image list"
|
||||
msgstr "既存のイメージリストを処理中"
|
||||
|
||||
msgctxt "#30358"
|
||||
msgid "Retreiving remote image list"
|
||||
msgstr "リモートイメージリストを取得中"
|
||||
|
||||
msgctxt "#30359"
|
||||
msgid "Building full image list"
|
||||
msgstr "フルイメージリストを構築中"
|
||||
|
||||
msgctxt "#30360"
|
||||
msgid " - Channels"
|
||||
msgstr "- チャンネル"
|
||||
|
||||
msgctxt "#30361"
|
||||
msgid " - Programs"
|
||||
msgstr "- 番組"
|
||||
|
||||
msgctxt "#30362"
|
||||
msgid " - Recordings"
|
||||
msgstr "- 録音"
|
||||
|
||||
msgctxt "#30363"
|
||||
msgid "Save Password?"
|
||||
msgstr "パスワードを保存しますか?"
|
||||
|
||||
msgctxt "#30364"
|
||||
msgid "Do you want to save the password?"
|
||||
msgstr "パスワードを保存しますか?"
|
||||
|
||||
msgctxt "#30365"
|
||||
msgid "Manual Login"
|
||||
msgstr "手動ログイン"
|
||||
|
||||
msgctxt "#30366"
|
||||
msgid "Manually enter user details"
|
||||
msgstr "ユーザー詳細を手動で入力"
|
||||
|
||||
msgctxt "#30367"
|
||||
msgid "Allow fast user switching password saving"
|
||||
msgstr "切り替えたユーザーのパスワードの保存を許可"
|
||||
|
||||
msgctxt "#30368"
|
||||
msgid "Clear Password?"
|
||||
msgstr "パスワードを消去しますか?"
|
||||
|
||||
msgctxt "#30369"
|
||||
msgid "Do you want to clear your saved password?"
|
||||
msgstr "保存されたパスワードを消去しますか?"
|
||||
|
||||
msgctxt "#30370"
|
||||
msgid "Do you want to manually enter a server url?"
|
||||
msgstr "サーバーURLを手動で入力しますか?"
|
||||
|
||||
msgctxt "#30371"
|
||||
msgid "Could not connect to the URL you entered, do you want to try again?"
|
||||
msgstr "入力されたURLに接続できませんでした。再試行しますか?"
|
||||
|
||||
msgctxt "#30372"
|
||||
msgid "Server URL"
|
||||
msgstr "サーバーURL"
|
||||
|
||||
msgctxt "#30373"
|
||||
msgid "Scanning for local servers"
|
||||
msgstr "ローカルサーバーを検索中"
|
||||
|
||||
msgctxt "#30374"
|
||||
msgid "Sending request"
|
||||
msgstr "リクエストを送信中"
|
||||
|
||||
msgctxt "#30377"
|
||||
msgid "Sending request"
|
||||
msgstr "リクエストを送信中"
|
||||
|
||||
msgctxt "#30378"
|
||||
msgid "Persist user details"
|
||||
msgstr "ユーザー詳細を保持する"
|
||||
|
||||
msgctxt "#30376"
|
||||
msgid "Checking server url"
|
||||
msgstr "サーバーURLを検証中"
|
||||
|
||||
msgctxt "#30236"
|
||||
msgid "Force transcode h265 (hevc)"
|
||||
msgstr "h265 (hevc)でのトランスコードを強制する"
|
||||
|
||||
msgctxt "#30240"
|
||||
msgid "Force transcode msmpeg4v3 (divx)"
|
||||
msgstr "msmpeg4v3 (divx)でのトランスコードを強制する"
|
||||
|
||||
msgctxt "#30251"
|
||||
msgid "Movies - Genres"
|
||||
msgstr "映画 - ジャンル"
|
||||
|
||||
msgctxt "#30289"
|
||||
msgid "TV Shows - Genres"
|
||||
msgstr "TV番組 - ジャンル"
|
||||
|
||||
msgctxt "#30310"
|
||||
msgid "Enable Jellyfin remote control"
|
||||
msgstr "Jellyfinリモートコントロールを有効化"
|
||||
|
||||
msgctxt "#30333"
|
||||
msgid "Cache artwork in the background"
|
||||
msgstr "アートワークをバックグラウンドでキャッシュ"
|
||||
|
||||
msgctxt "#30223"
|
||||
msgid "Page Size and Filtering"
|
||||
msgstr "ページサイズとフィルタリング"
|
||||
|
||||
msgctxt "#30247"
|
||||
msgid "Custom Widget Content"
|
||||
msgstr "カスタムウィジェットコンテンツ"
|
||||
|
||||
msgctxt "#30263"
|
||||
msgid "Episodes - Recently Added"
|
||||
msgstr "エピソード - 最近追加された"
|
||||
|
||||
msgctxt "#30298"
|
||||
msgid "Deleting Kodi Images"
|
||||
msgstr "Kodiイメージを削除中"
|
||||
|
||||
msgctxt "#30375"
|
||||
msgid "Receiving data packet"
|
||||
msgstr "データパケットを受信中"
|
||||
|
||||
msgctxt "#30238"
|
||||
msgid "Playback stream options"
|
||||
msgstr "再生ストリームオプション"
|
||||
|
||||
msgctxt "#30242"
|
||||
msgid "Force transcode av1"
|
||||
msgstr "av1でのトランスコードを強制する"
|
||||
|
||||
msgctxt "#30300"
|
||||
msgid "Cache all Jellyfin images as local Kodi images?"
|
||||
msgstr "全てのJellyfinイメージをローカルなKodiイメージとしてキャッシュしますか?"
|
||||
|
||||
msgctxt "#30277"
|
||||
msgid "JellyCon needs to prompt for resume on partily played items, Kodi can also prompt, this can cause a double prompt. Do you want to remove the double prompt?"
|
||||
msgstr ""
|
||||
"JellyConは途中まで再生したアイテムを途中から再生するか質問しますが、Kodiも同"
|
||||
"じ質問をすることがあります。重複した質問を取り除きますか?"
|
||||
|
||||
msgctxt "#30114"
|
||||
msgid "Jump back seconds"
|
||||
msgstr "数秒戻す"
|
||||
|
||||
msgctxt "#30120"
|
||||
msgid "Show load progress"
|
||||
msgstr "読込み状況を表示"
|
||||
|
||||
msgctxt "#30125"
|
||||
msgid "Done"
|
||||
msgstr "完了"
|
||||
|
||||
msgctxt "#30135"
|
||||
msgid "Error"
|
||||
msgstr "エラー"
|
||||
|
||||
msgctxt "#30020"
|
||||
msgid "Flatten single season"
|
||||
msgstr "1シーズンを畳む"
|
||||
|
||||
msgctxt "#30116"
|
||||
msgid "Add unwatched counts to names"
|
||||
msgstr "名前に未視聴の数を追加"
|
||||
|
||||
msgctxt "#30121"
|
||||
msgid "On resume"
|
||||
msgstr "再開時"
|
||||
|
||||
msgctxt "#30126"
|
||||
msgid "Processing Item : "
|
||||
msgstr "次の項目を処理中:"
|
||||
|
||||
msgctxt "#30139"
|
||||
msgid "No Media Type Set"
|
||||
msgstr "メディアタイプ未設定"
|
||||
|
||||
msgctxt "#30163"
|
||||
msgid "Add (cc) if subtitle is available"
|
||||
msgstr "字幕がある場合(cc)を追加する"
|
||||
|
||||
msgctxt "#30166"
|
||||
msgid "Select Server"
|
||||
msgstr "サーバーを選択する"
|
||||
|
||||
msgctxt "#30167"
|
||||
msgid "Selected Server Address"
|
||||
msgstr "選択されたサーバーアドレス"
|
||||
|
||||
msgctxt "#30169"
|
||||
msgid "Address: "
|
||||
msgstr "アドレス:"
|
||||
|
||||
msgctxt "#30180"
|
||||
msgid "Select User"
|
||||
msgstr "ユーザー選択"
|
||||
|
||||
msgctxt "#30026"
|
||||
msgid "Widget item select action"
|
||||
msgstr "ウィジェット項目選択操作"
|
||||
|
||||
msgctxt "#30200"
|
||||
msgid "URL error"
|
||||
msgstr "URLエラー"
|
||||
|
||||
msgctxt "#30201"
|
||||
msgid "Unable to connect to server"
|
||||
msgstr "サーバーに接続できません"
|
||||
@@ -1,6 +1,6 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"PO-Revision-Date: 2022-06-08 04:22+0000\n"
|
||||
"PO-Revision-Date: 2022-08-10 20:22+0000\n"
|
||||
"Last-Translator: WWWesten <wwwesten@gmail.com>\n"
|
||||
"Language-Team: Kazakh <https://translate.jellyfin.org/projects/jellycon/"
|
||||
"jellycon/kk/>\n"
|
||||
@@ -1101,3 +1101,7 @@ msgstr "Jyldam qosylu"
|
||||
msgctxt "#30323"
|
||||
msgid "Artists"
|
||||
msgstr "Oryndauşylar"
|
||||
|
||||
msgctxt "#30445"
|
||||
msgid "Continue Watching"
|
||||
msgstr "Qaraudy jalğastyru"
|
||||
|
||||
396
resources/language/resource.language.ko/strings.po
Normal file
396
resources/language/resource.language.ko/strings.po
Normal file
@@ -0,0 +1,396 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"PO-Revision-Date: 2022-11-23 06:51+0000\n"
|
||||
"Last-Translator: wolfwork <wolfdate25@naver.com>\n"
|
||||
"Language-Team: Korean <https://translate.jellyfin.org/projects/jellycon/"
|
||||
"jellycon/ko/>\n"
|
||||
"Language: ko\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=1; plural=0;\n"
|
||||
"X-Generator: Weblate 4.14.1\n"
|
||||
|
||||
msgctxt "#30006"
|
||||
msgid "Password"
|
||||
msgstr "비밀번호"
|
||||
|
||||
msgctxt "#30025"
|
||||
msgid "Password:"
|
||||
msgstr "비밀번호:"
|
||||
|
||||
msgctxt "#30026"
|
||||
msgid "Widget item select action"
|
||||
msgstr "위젯 항목 선택 작업"
|
||||
|
||||
msgctxt "#30045"
|
||||
msgid "Username not found"
|
||||
msgstr "사용자 이름을 찾을 수 없습니다"
|
||||
|
||||
msgctxt "#30112"
|
||||
msgid "Loading Content"
|
||||
msgstr "콘텐츠 로드 중"
|
||||
|
||||
msgctxt "#30120"
|
||||
msgid "Show load progress"
|
||||
msgstr "로드 진행률 표시"
|
||||
|
||||
msgctxt "#30121"
|
||||
msgid "On resume"
|
||||
msgstr "재개 시"
|
||||
|
||||
msgctxt "#30166"
|
||||
msgid "Select Server"
|
||||
msgstr "서버 선택"
|
||||
|
||||
msgctxt "#30212"
|
||||
msgid "Video max width"
|
||||
msgstr "비디오 최대 길이"
|
||||
|
||||
msgctxt "#30251"
|
||||
msgid "Movies - Genres"
|
||||
msgstr "영화 - 장르"
|
||||
|
||||
msgctxt "#30264"
|
||||
msgid "Episodes - In Progress"
|
||||
msgstr "에피소드 - 진행 중"
|
||||
|
||||
msgctxt "#30269"
|
||||
msgid "Movies - Random"
|
||||
msgstr "영화 - 랜덤"
|
||||
|
||||
msgctxt "#30000"
|
||||
msgid "Host"
|
||||
msgstr "호스트"
|
||||
|
||||
msgctxt "#30001"
|
||||
msgid "Port"
|
||||
msgstr "포트"
|
||||
|
||||
msgctxt "#30003"
|
||||
msgid "Verify HTTPS certificate"
|
||||
msgstr "HTTPS 인증서 확인"
|
||||
|
||||
msgctxt "#30005"
|
||||
msgid "Username"
|
||||
msgstr "사용자 이름"
|
||||
|
||||
msgctxt "#30007"
|
||||
msgid "Samba username"
|
||||
msgstr "Samba 사용자이름"
|
||||
|
||||
msgctxt "#30008"
|
||||
msgid "Samba password"
|
||||
msgstr "Samba 비밀번호"
|
||||
|
||||
msgctxt "#30011"
|
||||
msgid "[Detect local server]"
|
||||
msgstr "[로컬 서버 찾기]"
|
||||
|
||||
msgctxt "#30012"
|
||||
msgid "[Change user]"
|
||||
msgstr "[사용자 변경]"
|
||||
|
||||
msgctxt "#30015"
|
||||
msgid "Log timing data"
|
||||
msgstr "로그 타이밍 데이터"
|
||||
|
||||
msgctxt "#30016"
|
||||
msgid "Device display name"
|
||||
msgstr "장치 표시 이름"
|
||||
|
||||
msgctxt "#30017"
|
||||
msgid "Show connected clients"
|
||||
msgstr "연결된 클라이언트 표시"
|
||||
|
||||
msgctxt "#30018"
|
||||
msgid "Number of items to show in filtered lists"
|
||||
msgstr "필터링된 목록에 표시할 항목 수"
|
||||
|
||||
msgctxt "#30019"
|
||||
msgid "Filtered episode name format"
|
||||
msgstr "필터링된 에피소드 이름 형식"
|
||||
|
||||
msgctxt "#30021"
|
||||
msgid "Show all episodes item"
|
||||
msgstr "모든 에피소드 보기"
|
||||
|
||||
msgctxt "#30022"
|
||||
msgid "Advanced"
|
||||
msgstr "고급"
|
||||
|
||||
msgctxt "#30023"
|
||||
msgid "Hide unwatched episode details"
|
||||
msgstr "시청하지 않은 에피소드 세부정보 숨기기"
|
||||
|
||||
msgctxt "#30024"
|
||||
msgid "Username:"
|
||||
msgstr "사용자이름:"
|
||||
|
||||
msgctxt "#30027"
|
||||
msgid "Enable debug logging"
|
||||
msgstr "디버그 로깅 활성화"
|
||||
|
||||
msgctxt "#30044"
|
||||
msgid "Incorrect Username/Password"
|
||||
msgstr "잘못된 사용자이름/비밀번호"
|
||||
|
||||
msgctxt "#30052"
|
||||
msgid "Deleting"
|
||||
msgstr "삭제 중"
|
||||
|
||||
msgctxt "#30053"
|
||||
msgid "Waiting for server to delete"
|
||||
msgstr "서버에서 삭제 대기 중"
|
||||
|
||||
msgctxt "#30091"
|
||||
msgid "Confirm delete?"
|
||||
msgstr "삭제하시겠습니까?"
|
||||
|
||||
msgctxt "#30092"
|
||||
msgid "Warning: This action will delete the media files from the server."
|
||||
msgstr "경고: 이 작업은 서버에서 미디어 파일을 삭제합니다."
|
||||
|
||||
msgctxt "#30110"
|
||||
msgid "Interface"
|
||||
msgstr "인터페이스"
|
||||
|
||||
msgctxt "#30111"
|
||||
msgid "Services"
|
||||
msgstr "서비스"
|
||||
|
||||
msgctxt "#30113"
|
||||
msgid "Retrieving Data"
|
||||
msgstr "데이터 수신 중"
|
||||
|
||||
msgctxt "#30114"
|
||||
msgid "Jump back seconds"
|
||||
msgstr "초 뒤로 이동"
|
||||
|
||||
msgctxt "#30116"
|
||||
msgid "Add unwatched counts to names"
|
||||
msgstr "이름에 시청하지 않은 카운트 수 추가"
|
||||
|
||||
msgctxt "#30118"
|
||||
msgid "Add resume percent to names"
|
||||
msgstr "이름에 재개율 추가"
|
||||
|
||||
msgctxt "#30125"
|
||||
msgid "Done"
|
||||
msgstr "완료"
|
||||
|
||||
msgctxt "#30126"
|
||||
msgid "Processing Item : "
|
||||
msgstr "진행중인 항목:"
|
||||
|
||||
msgctxt "#30135"
|
||||
msgid "Error"
|
||||
msgstr "오류"
|
||||
|
||||
msgctxt "#30139"
|
||||
msgid "No Media Type Set"
|
||||
msgstr "미디어 타입 설정 안됨"
|
||||
|
||||
msgctxt "#30163"
|
||||
msgid "Add (cc) if subtitle is available"
|
||||
msgstr "자막이 존재할 경우 (cc) 추가"
|
||||
|
||||
msgctxt "#30167"
|
||||
msgid "Selected Server Address"
|
||||
msgstr "선택된 서버 주소"
|
||||
|
||||
msgctxt "#30169"
|
||||
msgid "Address: "
|
||||
msgstr "주소:"
|
||||
|
||||
msgctxt "#30180"
|
||||
msgid "Select User"
|
||||
msgstr "사용자 선택"
|
||||
|
||||
msgctxt "#30181"
|
||||
msgid "Include plot"
|
||||
msgstr "플롯 포함"
|
||||
|
||||
msgctxt "#30182"
|
||||
msgid "Include media stream info"
|
||||
msgstr "미디어 스트림 정보 포함"
|
||||
|
||||
msgctxt "#30183"
|
||||
msgid "Include people"
|
||||
msgstr "사람 포함"
|
||||
|
||||
msgctxt "#30200"
|
||||
msgid "URL error"
|
||||
msgstr "URL 오류"
|
||||
|
||||
msgctxt "#30201"
|
||||
msgid "Unable to connect to server"
|
||||
msgstr "서버에 연결할 수 없습니다"
|
||||
|
||||
msgctxt "#30206"
|
||||
msgid "Playback type"
|
||||
msgstr "재생 유형"
|
||||
|
||||
msgctxt "#30207"
|
||||
msgid "Playback"
|
||||
msgstr "재생"
|
||||
|
||||
msgctxt "#30208"
|
||||
msgid "Max stream bitrate (Kbits)"
|
||||
msgstr "최대 스트림 비트레이트 (Kbps)"
|
||||
|
||||
msgctxt "#30209"
|
||||
msgid "File direct path"
|
||||
msgstr "파일 직접 경로"
|
||||
|
||||
msgctxt "#30210"
|
||||
msgid "HTTP direct stream"
|
||||
msgstr "HTTP 직접 스트림"
|
||||
|
||||
msgctxt "#30211"
|
||||
msgid "Transcode options"
|
||||
msgstr "트랜스코드 옵션"
|
||||
|
||||
msgctxt "#30213"
|
||||
msgid "Video force 8 bit"
|
||||
msgstr "비디오 강제 8 bit"
|
||||
|
||||
msgctxt "#30214"
|
||||
msgid "Events"
|
||||
msgstr "이벤트"
|
||||
|
||||
msgctxt "#30215"
|
||||
msgid "On playback stop (100% = disabled)"
|
||||
msgstr "재생 중지 시(100% = 비활성화됨)"
|
||||
|
||||
msgctxt "#30216"
|
||||
msgid "Item Details"
|
||||
msgstr "항목 세부정보"
|
||||
|
||||
msgctxt "#30218"
|
||||
msgid "Play next episode after %"
|
||||
msgstr "% 후 다음 에피소드 재생"
|
||||
|
||||
msgctxt "#30222"
|
||||
msgid "Item Layout"
|
||||
msgstr "항목 레이아웃"
|
||||
|
||||
msgctxt "#30223"
|
||||
msgid "Page Size and Filtering"
|
||||
msgstr "페이지 크기와 필터링"
|
||||
|
||||
msgctxt "#30224"
|
||||
msgid "Interaction"
|
||||
msgstr "상호작용"
|
||||
|
||||
msgctxt "#30229"
|
||||
msgid "TV Shows"
|
||||
msgstr "TV 쇼"
|
||||
|
||||
msgctxt "#30231"
|
||||
msgid "Movies"
|
||||
msgstr "영화"
|
||||
|
||||
msgctxt "#30235"
|
||||
msgid "Episodes"
|
||||
msgstr "에피소드"
|
||||
|
||||
msgctxt "#30236"
|
||||
msgid "Force transcode h265 (hevc)"
|
||||
msgstr "강제 트랜스코드 h265 (hevc)"
|
||||
|
||||
msgctxt "#30237"
|
||||
msgid "Start from beginning"
|
||||
msgstr "처음부터 시작"
|
||||
|
||||
msgctxt "#30238"
|
||||
msgid "Playback stream options"
|
||||
msgstr "재생 스트림 옵션"
|
||||
|
||||
msgctxt "#30239"
|
||||
msgid "Force transcode mpeg2"
|
||||
msgstr "강제 트랜스코드 mpeg2"
|
||||
|
||||
msgctxt "#30240"
|
||||
msgid "Force transcode msmpeg4v3 (divx)"
|
||||
msgstr "강제 트랜스코드 msmpeg4v3 (divx)"
|
||||
|
||||
msgctxt "#30241"
|
||||
msgid "Force transcode mpeg4"
|
||||
msgstr "강제 트랜스코드 mpeg4"
|
||||
|
||||
msgctxt "#30246"
|
||||
msgid "Search"
|
||||
msgstr "검색"
|
||||
|
||||
msgctxt "#30247"
|
||||
msgid "Custom Widget Content"
|
||||
msgstr "사용자 지정 위젯 콘텐츠"
|
||||
|
||||
msgctxt "#30250"
|
||||
msgid "Unknown"
|
||||
msgstr "알수없음"
|
||||
|
||||
msgctxt "#30252"
|
||||
msgid "Movies - A-Z"
|
||||
msgstr "영화 - A-Z"
|
||||
|
||||
msgctxt "#30254"
|
||||
msgid "Show add-on settings"
|
||||
msgstr "에드온 설정 보기"
|
||||
|
||||
msgctxt "#30255"
|
||||
msgid "TV Shows - A-Z"
|
||||
msgstr "TV 쇼 - A-Z"
|
||||
|
||||
msgctxt "#30256"
|
||||
msgid "Movies"
|
||||
msgstr "영화"
|
||||
|
||||
msgctxt "#30257"
|
||||
msgid "Movies - Recently Added"
|
||||
msgstr "영화 - 최근에 추가됨"
|
||||
|
||||
msgctxt "#30258"
|
||||
msgid "Movies - In Progress"
|
||||
msgstr "영화 - 진행 중"
|
||||
|
||||
msgctxt "#30259"
|
||||
msgid "Movies - Favorites"
|
||||
msgstr "영화 - 즐겨찾기"
|
||||
|
||||
msgctxt "#30261"
|
||||
msgid "TV Shows"
|
||||
msgstr "TV 쇼"
|
||||
|
||||
msgctxt "#30262"
|
||||
msgid "TV Shows - Favorites"
|
||||
msgstr "TV 쇼 - 즐겨찾기"
|
||||
|
||||
msgctxt "#30263"
|
||||
msgid "Episodes - Recently Added"
|
||||
msgstr "에피소드 - 최근에 추가됨"
|
||||
|
||||
msgctxt "#30266"
|
||||
msgid "Movies - Pages"
|
||||
msgstr "영화 - 페이지"
|
||||
|
||||
msgctxt "#30267"
|
||||
msgid " - In Progress"
|
||||
msgstr "- 진행 중"
|
||||
|
||||
msgctxt "#30268"
|
||||
msgid " - Recently Added"
|
||||
msgstr "- 최근에 추가됨"
|
||||
|
||||
msgctxt "#30270"
|
||||
msgid "Mark Watched"
|
||||
msgstr "본 것으로 표시"
|
||||
|
||||
msgctxt "#30271"
|
||||
msgid "Mark Unwatched"
|
||||
msgstr "본 것으로 표시해제"
|
||||
|
||||
msgctxt "#30272"
|
||||
msgid "Set Favourite"
|
||||
msgstr "즐겨찾기 설정"
|
||||
2
resources/language/resource.language.mk/strings.po
Normal file
2
resources/language/resource.language.mk/strings.po
Normal file
@@ -0,0 +1,2 @@
|
||||
msgid ""
|
||||
msgstr "X-Generator: Weblate\nMIME-Version: 1.0\nContent-Type: text/plain; charset=UTF-8\nContent-Transfer-Encoding: 8bit"
|
||||
16
resources/language/resource.language.mn/strings.po
Normal file
16
resources/language/resource.language.mn/strings.po
Normal file
@@ -0,0 +1,16 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"PO-Revision-Date: 2025-10-26 00:17+0000\n"
|
||||
"Last-Translator: Battseren Badral <bbattseren88@gmail.com>\n"
|
||||
"Language-Team: Mongolian <https://translate.jellyfin.org/projects/jellycon/"
|
||||
"jellycon/mn/>\n"
|
||||
"Language: mn\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=n != 1;\n"
|
||||
"X-Generator: Weblate 5.14\n"
|
||||
|
||||
msgctxt "#30000"
|
||||
msgid "Host"
|
||||
msgstr "Хост"
|
||||
1223
resources/language/resource.language.nb_NO/strings.po
Normal file
1223
resources/language/resource.language.nb_NO/strings.po
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,7 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"PO-Revision-Date: 2022-06-01 17:51+0000\n"
|
||||
"Last-Translator: B v H <bobsieflopsie@outlook.com>\n"
|
||||
"PO-Revision-Date: 2025-05-11 01:54+0000\n"
|
||||
"Last-Translator: C2gl <lievens.guillaume@gmail.com>\n"
|
||||
"Language-Team: Dutch <https://translate.jellyfin.org/projects/jellycon/"
|
||||
"jellycon/nl/>\n"
|
||||
"Language: nl\n"
|
||||
@@ -9,7 +9,7 @@ msgstr ""
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=n != 1;\n"
|
||||
"X-Generator: Weblate 4.10.1\n"
|
||||
"X-Generator: Weblate 5.10.4\n"
|
||||
|
||||
msgctxt "#30257"
|
||||
msgid "Movies - Recently Added"
|
||||
@@ -21,7 +21,7 @@ msgstr "Films"
|
||||
|
||||
msgctxt "#30255"
|
||||
msgid "TV Shows - A-Z"
|
||||
msgstr "TV Shows - A-Z"
|
||||
msgstr "TV Series - A-Z"
|
||||
|
||||
msgctxt "#30254"
|
||||
msgid "Show add-on settings"
|
||||
@@ -41,7 +41,7 @@ msgstr "Onbekend"
|
||||
|
||||
msgctxt "#30247"
|
||||
msgid "Custom Widget Content"
|
||||
msgstr "Custom Widget Inhoud"
|
||||
msgstr "Aangepaste widget inhoud"
|
||||
|
||||
msgctxt "#30246"
|
||||
msgid "Search"
|
||||
@@ -81,7 +81,7 @@ msgstr "Films"
|
||||
|
||||
msgctxt "#30229"
|
||||
msgid "TV Shows"
|
||||
msgstr "TV Shows"
|
||||
msgstr "TV Series"
|
||||
|
||||
msgctxt "#30224"
|
||||
msgid "Interaction"
|
||||
@@ -89,7 +89,7 @@ msgstr "Interactie"
|
||||
|
||||
msgctxt "#30216"
|
||||
msgid "Item Details"
|
||||
msgstr "Item Details"
|
||||
msgstr "Item details"
|
||||
|
||||
msgctxt "#30223"
|
||||
msgid "Page Size and Filtering"
|
||||
@@ -97,7 +97,7 @@ msgstr "Paginagrootte en Filteren"
|
||||
|
||||
msgctxt "#30222"
|
||||
msgid "Item Layout"
|
||||
msgstr "Item Layout"
|
||||
msgstr "Item layout"
|
||||
|
||||
msgctxt "#30220"
|
||||
msgid "Prompt to delete movie after %"
|
||||
@@ -137,7 +137,7 @@ msgstr "Transcode opties"
|
||||
|
||||
msgctxt "#30210"
|
||||
msgid "HTTP direct stream"
|
||||
msgstr "HTTP direct stream"
|
||||
msgstr "HTTP directe stream"
|
||||
|
||||
msgctxt "#30209"
|
||||
msgid "File direct path"
|
||||
@@ -145,7 +145,7 @@ msgstr "Directe bestandslocatie"
|
||||
|
||||
msgctxt "#30208"
|
||||
msgid "Max stream bitrate (Kbits)"
|
||||
msgstr "Maximale stream bitrate (Kbps)"
|
||||
msgstr "Maximale stream bitsnelheid (Kbps)"
|
||||
|
||||
msgctxt "#30207"
|
||||
msgid "Playback"
|
||||
@@ -161,7 +161,7 @@ msgstr "Kan niet verbinden met de server"
|
||||
|
||||
msgctxt "#30200"
|
||||
msgid "URL error"
|
||||
msgstr "URL error"
|
||||
msgstr "URL fout"
|
||||
|
||||
msgctxt "#30183"
|
||||
msgid "Include people"
|
||||
@@ -201,7 +201,7 @@ msgstr "Geen mediatype ingesteld"
|
||||
|
||||
msgctxt "#30135"
|
||||
msgid "Error"
|
||||
msgstr "Error"
|
||||
msgstr "Fout"
|
||||
|
||||
msgctxt "#30126"
|
||||
msgid "Processing Item : "
|
||||
@@ -221,11 +221,11 @@ msgstr "Toon laadvoortgang"
|
||||
|
||||
msgctxt "#30118"
|
||||
msgid "Add resume percent to names"
|
||||
msgstr "Voeg percentage bekeken to aan namen"
|
||||
msgstr "Voeg bekeken percentage toe aan namen"
|
||||
|
||||
msgctxt "#30116"
|
||||
msgid "Add unwatched counts to names"
|
||||
msgstr "Voeg hoeveelheid niet bekeken to aan namen"
|
||||
msgstr "Voeg hoeveelheid niet bekeken toe aan namen"
|
||||
|
||||
msgctxt "#30114"
|
||||
msgid "Jump back seconds"
|
||||
@@ -233,7 +233,7 @@ msgstr "Spring seconden terug"
|
||||
|
||||
msgctxt "#30113"
|
||||
msgid "Retrieving Data"
|
||||
msgstr "Data Ophalen"
|
||||
msgstr "Data aan het ophalen"
|
||||
|
||||
msgctxt "#30112"
|
||||
msgid "Loading Content"
|
||||
@@ -241,7 +241,7 @@ msgstr "Content aan het laden"
|
||||
|
||||
msgctxt "#30111"
|
||||
msgid "Services"
|
||||
msgstr "Services"
|
||||
msgstr "Diensten"
|
||||
|
||||
msgctxt "#30110"
|
||||
msgid "Interface"
|
||||
@@ -253,11 +253,11 @@ msgstr "Waarschuwing: Deze stap zal mediabestanden van de server verwijderen."
|
||||
|
||||
msgctxt "#30091"
|
||||
msgid "Confirm delete?"
|
||||
msgstr "Bevestig verwijderen?"
|
||||
msgstr "Verwijderen bevestigen?"
|
||||
|
||||
msgctxt "#30063"
|
||||
msgid "N/A"
|
||||
msgstr "N/A"
|
||||
msgstr "NB"
|
||||
|
||||
msgctxt "#30053"
|
||||
msgid "Waiting for server to delete"
|
||||
@@ -281,7 +281,7 @@ msgstr "Schakel debug logging in"
|
||||
|
||||
msgctxt "#30026"
|
||||
msgid "Widget item select action"
|
||||
msgstr "Widget item selecteer actie"
|
||||
msgstr "Widget onderdeel selecteer actie"
|
||||
|
||||
msgctxt "#30025"
|
||||
msgid "Password:"
|
||||
@@ -305,11 +305,11 @@ msgstr "Toon alle afleveringen"
|
||||
|
||||
msgctxt "#30019"
|
||||
msgid "Filtered episode name format"
|
||||
msgstr "Naamformat gefilterde aflevering"
|
||||
msgstr "Naamformat van gefilterde aflevering"
|
||||
|
||||
msgctxt "#30018"
|
||||
msgid "Number of items to show in filtered lists"
|
||||
msgstr "Aantal weer te geven items in gefilterde lijsten"
|
||||
msgstr "Aantal items om te tonen in gefilterde lijsten"
|
||||
|
||||
msgctxt "#30017"
|
||||
msgid "Show connected clients"
|
||||
@@ -321,7 +321,7 @@ msgstr "Weergavenaam apparaat"
|
||||
|
||||
msgctxt "#30015"
|
||||
msgid "Log timing data"
|
||||
msgstr "Log timing gegevens"
|
||||
msgstr "Log timinggegevens"
|
||||
|
||||
msgctxt "#30014"
|
||||
msgid "Jellyfin"
|
||||
@@ -341,11 +341,11 @@ msgstr "Aantal vast te leggen prestatieprofielen"
|
||||
|
||||
msgctxt "#30008"
|
||||
msgid "Samba password"
|
||||
msgstr "Samba wachtwoord"
|
||||
msgstr "Samba-wachtwoord"
|
||||
|
||||
msgctxt "#30007"
|
||||
msgid "Samba username"
|
||||
msgstr "Samba gebruikersnaam"
|
||||
msgstr "Samba-gebruikersnaam"
|
||||
|
||||
msgctxt "#30006"
|
||||
msgid "Password"
|
||||
@@ -357,7 +357,7 @@ msgstr "Gebruikersnaam"
|
||||
|
||||
msgctxt "#30003"
|
||||
msgid "Verify HTTPS certificate"
|
||||
msgstr "Verifieer HTTPS certificaat"
|
||||
msgstr "Verifieer HTTPS-certificaat"
|
||||
|
||||
msgctxt "#30001"
|
||||
msgid "Port"
|
||||
@@ -369,15 +369,15 @@ msgstr "Host"
|
||||
|
||||
msgctxt "#30352"
|
||||
msgid "Music - Frequently Played"
|
||||
msgstr "Muziek - Vaak Afgespeeld"
|
||||
msgstr "Muziek - Vaak afgespeeld"
|
||||
|
||||
msgctxt "#30351"
|
||||
msgid "Music - Recently Played"
|
||||
msgstr "Muziek - Recent Afgespeeld"
|
||||
msgstr "Muziek - Recent afgespeeld"
|
||||
|
||||
msgctxt "#30350"
|
||||
msgid "Music - Recently Added"
|
||||
msgstr "Muziek - Recent Toegevoegd"
|
||||
msgstr "Muziek - Recent toegevoegd"
|
||||
|
||||
msgctxt "#30339"
|
||||
msgid "Person"
|
||||
@@ -397,7 +397,7 @@ msgstr "Films per pagina"
|
||||
|
||||
msgctxt "#30327"
|
||||
msgid "Go To Season"
|
||||
msgstr "Ga Naar Seizoen"
|
||||
msgstr "Ga naar seizoen"
|
||||
|
||||
msgctxt "#30325"
|
||||
msgid " - Genres"
|
||||
@@ -405,7 +405,7 @@ msgstr "- Genres"
|
||||
|
||||
msgctxt "#30322"
|
||||
msgid "Auto resume"
|
||||
msgstr "Automatisch Hervatten"
|
||||
msgstr "Automatisch hervatten"
|
||||
|
||||
msgctxt "#30320"
|
||||
msgid " - Albums"
|
||||
@@ -417,7 +417,7 @@ msgstr "Muziek - Albums"
|
||||
|
||||
msgctxt "#30317"
|
||||
msgid "Play All"
|
||||
msgstr "Speel Alles Af"
|
||||
msgstr "Speel alles af"
|
||||
|
||||
msgctxt "#30316"
|
||||
msgid "Connection Error"
|
||||
@@ -429,7 +429,7 @@ msgstr "Meldingen van verbindingsfouten onderdrukken"
|
||||
|
||||
msgctxt "#30314"
|
||||
msgid "Play"
|
||||
msgstr "Speel Af"
|
||||
msgstr "Speel af"
|
||||
|
||||
msgctxt "#30313"
|
||||
msgid "Menu"
|
||||
@@ -437,27 +437,27 @@ msgstr "Menu"
|
||||
|
||||
msgctxt "#30308"
|
||||
msgid "Select Trailer"
|
||||
msgstr "Selecteer Trailer"
|
||||
msgstr "Selecteer trailer"
|
||||
|
||||
msgctxt "#30307"
|
||||
msgid "Play Trailer"
|
||||
msgstr "Speel Trailer Af"
|
||||
msgstr "Speel trailer af"
|
||||
|
||||
msgctxt "#30305"
|
||||
msgid "Not Found"
|
||||
msgstr "Niet Gevonden"
|
||||
msgstr "Niet gevonden"
|
||||
|
||||
msgctxt "#30302"
|
||||
msgid "Existing images : "
|
||||
msgstr "Bestaande Afbeeldingen:"
|
||||
msgstr "Bestaande afbeeldingen:"
|
||||
|
||||
msgctxt "#30298"
|
||||
msgid "Deleting Kodi Images"
|
||||
msgstr "Kodi Afbeeldingen Verwijderen"
|
||||
msgstr "Kodi afbeeldingen verwijderen"
|
||||
|
||||
msgctxt "#30297"
|
||||
msgid "Delete unused images?"
|
||||
msgstr "Verwijder niet gebruikte afbeeldingen?"
|
||||
msgstr "Niet gebruikte afbeeldingen verwijderen?"
|
||||
|
||||
msgctxt "#30296"
|
||||
msgid "Delete"
|
||||
@@ -473,19 +473,19 @@ msgstr "- Nieuwste"
|
||||
|
||||
msgctxt "#30286"
|
||||
msgid "Movies - Unwatched"
|
||||
msgstr "Films - Niet Bekeken"
|
||||
msgstr "Films - Niet bekeken"
|
||||
|
||||
msgctxt "#30285"
|
||||
msgid " - Unwatched"
|
||||
msgstr "- Niet Bekeken"
|
||||
msgstr "- Niet bekeken"
|
||||
|
||||
msgctxt "#30283"
|
||||
msgid "Play Next Episode?"
|
||||
msgstr "Speel Volgende Aflevering Af?"
|
||||
msgstr "Speel volgende aflevering af?"
|
||||
|
||||
msgctxt "#30282"
|
||||
msgid "No Jellyfin servers detected on your local network."
|
||||
msgstr "Geen Jellyfin Servers Gevonden Op Uw Locale Netwerk."
|
||||
msgstr "Geen Jellyfin servers gevonden op jouw lokale netwerk."
|
||||
|
||||
msgctxt "#30280"
|
||||
msgid "Missing Title"
|
||||
@@ -505,19 +505,19 @@ msgstr "Verwijderen"
|
||||
|
||||
msgctxt "#30273"
|
||||
msgid "Unset Favourite"
|
||||
msgstr "Demarkeer Favoriet"
|
||||
msgstr "Favoriet ongedaan maken"
|
||||
|
||||
msgctxt "#30272"
|
||||
msgid "Set Favourite"
|
||||
msgstr "Markeer Favoriet"
|
||||
msgstr "Markeer als favoriet"
|
||||
|
||||
msgctxt "#30271"
|
||||
msgid "Mark Unwatched"
|
||||
msgstr "Markeer Niet Bekeken"
|
||||
msgstr "Markeer als niet-bekeken"
|
||||
|
||||
msgctxt "#30270"
|
||||
msgid "Mark Watched"
|
||||
msgstr "Markeer Bekeken"
|
||||
msgstr "Markeer als bekeken"
|
||||
|
||||
msgctxt "#30269"
|
||||
msgid "Movies - Random"
|
||||
@@ -533,4 +533,674 @@ msgstr "Films - Favorieten"
|
||||
|
||||
msgctxt "#30258"
|
||||
msgid "Movies - In Progress"
|
||||
msgstr "Films - In Uitvoering"
|
||||
msgstr "Films - Aan Het Kijken"
|
||||
|
||||
msgctxt "#30334"
|
||||
msgid "Use JellyCon context menu"
|
||||
msgstr "Het JellyCon-contextmenu gebruiken"
|
||||
|
||||
msgctxt "#30333"
|
||||
msgid "Cache artwork in the background"
|
||||
msgstr "Cache-artwork op de achtergrond"
|
||||
|
||||
msgctxt "#30332"
|
||||
msgid "Stop media playback on screensaver activation"
|
||||
msgstr "Stop het afspelen bij activering van de screensaver"
|
||||
|
||||
msgctxt "#30330"
|
||||
msgid "Show change user dialog"
|
||||
msgstr "Dialoogvenster gebruiker wijzigen tonen"
|
||||
|
||||
msgctxt "#30329"
|
||||
msgid "Screensaver"
|
||||
msgstr "Screensaver"
|
||||
|
||||
msgctxt "#30328"
|
||||
msgid "Show empty folders (shows, seasons, collections)"
|
||||
msgstr "Lege mappen weergeven (shows, seizoenen, collecties)"
|
||||
|
||||
msgctxt "#30323"
|
||||
msgid "Artists"
|
||||
msgstr "Artiesten"
|
||||
|
||||
msgctxt "#30312"
|
||||
msgid "All - "
|
||||
msgstr "Alles -"
|
||||
|
||||
msgctxt "#30311"
|
||||
msgid "Library - "
|
||||
msgstr "Bibliotheek -"
|
||||
|
||||
msgctxt "#30310"
|
||||
msgid "Enable Jellyfin remote control"
|
||||
msgstr "Jellyfin-afstandsbediening inschakelen"
|
||||
|
||||
msgctxt "#30309"
|
||||
msgid "Select Media Source"
|
||||
msgstr "Selecteer mediabron"
|
||||
|
||||
msgctxt "#30306"
|
||||
msgid "Playback starting"
|
||||
msgstr "Afspelen starten"
|
||||
|
||||
msgctxt "#30304"
|
||||
msgid "Cached Jellyfin images : "
|
||||
msgstr "Gecached Jellyfin-afbeeldingen:"
|
||||
|
||||
msgctxt "#30303"
|
||||
msgid "Missing Jellyfin images : "
|
||||
msgstr "Ontbrekende Jellyfin-afbeeldingen:"
|
||||
|
||||
msgctxt "#30300"
|
||||
msgid "Cache all Jellyfin images as local Kodi images?"
|
||||
msgstr ""
|
||||
"Alle Jellyfin-afbeeldingen in de cache opslaan als lokale Kodi-afbeeldingen?"
|
||||
|
||||
msgctxt "#30301"
|
||||
msgid "Caching Images"
|
||||
msgstr "Afbeeldingen worden in cache geplaatst"
|
||||
|
||||
msgctxt "#30293"
|
||||
msgid "Cache images"
|
||||
msgstr "Afbeeldingen Cachen"
|
||||
|
||||
msgctxt "#30299"
|
||||
msgid "Cache Images"
|
||||
msgstr "Afbeeldingen cachen"
|
||||
|
||||
msgctxt "#30295"
|
||||
msgid "To use this feature you need HTTP control enabled"
|
||||
msgstr "Om deze functie te gebruiken, moet HTTP-control zijn ingeschakeld"
|
||||
|
||||
msgctxt "#30294"
|
||||
msgid "Notice"
|
||||
msgstr "Melding"
|
||||
|
||||
msgctxt "#30292"
|
||||
msgid "Select Subtitle Stream"
|
||||
msgstr "Selecteer Ondertitelstream"
|
||||
|
||||
msgctxt "#30291"
|
||||
msgid "Select Audio Stream"
|
||||
msgstr "Selecteer Audiostream"
|
||||
|
||||
msgctxt "#30289"
|
||||
msgid "TV Shows - Genres"
|
||||
msgstr "TV Series - Genres"
|
||||
|
||||
msgctxt "#30287"
|
||||
msgid "TV Shows - Latest"
|
||||
msgstr "TV Series - Nieuwste"
|
||||
|
||||
msgctxt "#30281"
|
||||
msgid "Refresh Cached Images"
|
||||
msgstr "Ververs afbeeldingen in cache"
|
||||
|
||||
msgctxt "#30279"
|
||||
msgid "TV Shows - Unwatched"
|
||||
msgstr "TV Series - Niet bekeken"
|
||||
|
||||
msgctxt "#30277"
|
||||
msgid "JellyCon needs to prompt for resume on partily played items, Kodi can also prompt, this can cause a double prompt. Do you want to remove the double prompt?"
|
||||
msgstr ""
|
||||
"JellyFin moet vragen om hervatting van gedeeltelijk gespeelde items, Kodi "
|
||||
"kan dit ook vragen, dit kan een dubbele prompt veroorzaken. Wilt u de "
|
||||
"dubbele prompt verwijderen?"
|
||||
|
||||
msgctxt "#30276"
|
||||
msgid "Extra Resume Prompt Detected"
|
||||
msgstr "Extra Hervat Prompt Gedetecteerd"
|
||||
|
||||
msgctxt "#30267"
|
||||
msgid " - In Progress"
|
||||
msgstr "- Aan Het Kijken"
|
||||
|
||||
msgctxt "#30266"
|
||||
msgid "Movies - Pages"
|
||||
msgstr "Films - Pagina's"
|
||||
|
||||
msgctxt "#30265"
|
||||
msgid "Episodes - Next Up"
|
||||
msgstr "Afleveringen - Volgende in de lijst"
|
||||
|
||||
msgctxt "#30264"
|
||||
msgid "Episodes - In Progress"
|
||||
msgstr "Afleveringen - Aan Het Kijken"
|
||||
|
||||
msgctxt "#30263"
|
||||
msgid "Episodes - Recently Added"
|
||||
msgstr "Afleveringen - Recent Toegevoegd"
|
||||
|
||||
msgctxt "#30262"
|
||||
msgid "TV Shows - Favorites"
|
||||
msgstr "TV Series - Favorieten"
|
||||
|
||||
msgctxt "#30261"
|
||||
msgid "TV Shows"
|
||||
msgstr "TV Series"
|
||||
|
||||
msgctxt "#30260"
|
||||
msgid "BoxSets"
|
||||
msgstr "Boxsets"
|
||||
|
||||
msgctxt "#30020"
|
||||
msgid "Flatten single season"
|
||||
msgstr "Enkel seizoen samenvoegen"
|
||||
|
||||
msgctxt "#30445"
|
||||
msgid "Continue Watching"
|
||||
msgstr "Doorgaan met kijken"
|
||||
|
||||
msgctxt "#30444"
|
||||
msgid "Login using Quick Connect"
|
||||
msgstr "Log in met Quick Connect"
|
||||
|
||||
msgctxt "#30443"
|
||||
msgid "Quick Connect"
|
||||
msgstr "Snel verbinden"
|
||||
|
||||
msgctxt "#30442"
|
||||
msgid "Simple new content check"
|
||||
msgstr "Simpele nieuwe inhoudscheck"
|
||||
|
||||
msgctxt "#30441"
|
||||
msgid "Use cached widget data"
|
||||
msgstr "Gebruik gecachte widgetgegevens"
|
||||
|
||||
msgctxt "#30440"
|
||||
msgid "Play next"
|
||||
msgstr "Volgende afspelen"
|
||||
|
||||
msgctxt "#30439"
|
||||
msgid "Show play next episode at time left in seconds"
|
||||
msgstr "Toon speel volgende aflevering in laatste seconden"
|
||||
|
||||
msgctxt "#30438"
|
||||
msgid "Play cinema intros"
|
||||
msgstr "Filmintro's afspelen"
|
||||
|
||||
msgctxt "#30437"
|
||||
msgid "Playback options"
|
||||
msgstr "Afspeelopties"
|
||||
|
||||
msgctxt "#30436"
|
||||
msgid "Speed test data size (MB)"
|
||||
msgstr "Gegevensgrootte snelheidstest (MB)"
|
||||
|
||||
msgctxt "#30435"
|
||||
msgid "Connection speed test"
|
||||
msgstr "Verbindingssnelheidtest"
|
||||
|
||||
msgctxt "#30434"
|
||||
msgid "Force transcode stream bitrate (Kbits)"
|
||||
msgstr "Forceer transcode streambitsnelheid (Kbps)"
|
||||
|
||||
msgctxt "#30433"
|
||||
msgid "Allow direct file playback"
|
||||
msgstr "Rechtstreeks afspelen van bestanden toestaan"
|
||||
|
||||
msgctxt "#30432"
|
||||
msgid "Hide watched items in lists"
|
||||
msgstr "Verberg bekeken items in lijst"
|
||||
|
||||
msgctxt "#30431"
|
||||
msgid "Seasons"
|
||||
msgstr "Seizoenen"
|
||||
|
||||
msgctxt "#30430"
|
||||
msgid "Label"
|
||||
msgstr "Label"
|
||||
|
||||
msgctxt "#30429"
|
||||
msgid "Genre"
|
||||
msgstr "Genre"
|
||||
|
||||
msgctxt "#30428"
|
||||
msgid "Rating"
|
||||
msgstr "Beoordeling"
|
||||
|
||||
msgctxt "#30427"
|
||||
msgid "Added"
|
||||
msgstr "Toegevoegd"
|
||||
|
||||
msgctxt "#30426"
|
||||
msgid "Title"
|
||||
msgstr "Titel"
|
||||
|
||||
msgctxt "#30425"
|
||||
msgid "Year"
|
||||
msgstr "Jaar"
|
||||
|
||||
msgctxt "#30424"
|
||||
msgid "Default"
|
||||
msgstr "Standaard"
|
||||
|
||||
msgctxt "#30423"
|
||||
msgid "NotSet"
|
||||
msgstr "Niet ingesteld"
|
||||
|
||||
msgctxt "#30422"
|
||||
msgid "Sorting"
|
||||
msgstr "Sorteren"
|
||||
|
||||
msgctxt "#30421"
|
||||
msgid "Views"
|
||||
msgstr "Keer bekeken"
|
||||
|
||||
msgctxt "#30420"
|
||||
msgid "Audio max channels"
|
||||
msgstr "Maximum audio kanalen"
|
||||
|
||||
msgctxt "#30419"
|
||||
msgid "Audio codec"
|
||||
msgstr "Audio codec"
|
||||
|
||||
msgctxt "#30418"
|
||||
msgid "Audio bitrate (Kbits)"
|
||||
msgstr "Audio bitsnelheid (Kbps)"
|
||||
|
||||
msgctxt "#30417"
|
||||
msgid "You do not have permision to delete this item"
|
||||
msgstr "Je bent niet gemachtigd om dit item te verwijderen"
|
||||
|
||||
msgctxt "#30416"
|
||||
msgid "HTTP timeout seconds"
|
||||
msgstr "HTTP timeout seconden"
|
||||
|
||||
msgctxt "#30415"
|
||||
msgid " - Favorite Collections"
|
||||
msgstr "- Favoriete collecties"
|
||||
|
||||
msgctxt "#30414"
|
||||
msgid " - Favorites"
|
||||
msgstr "- Favorieten"
|
||||
|
||||
msgctxt "#30413"
|
||||
msgid " - Tags"
|
||||
msgstr "- Tags"
|
||||
|
||||
msgctxt "#30412"
|
||||
msgid " - Decades"
|
||||
msgstr "- Decennia"
|
||||
|
||||
msgctxt "#30411"
|
||||
msgid " - Years"
|
||||
msgstr "- Jaren"
|
||||
|
||||
msgctxt "#30410"
|
||||
msgid " - Collections"
|
||||
msgstr "- Collecties"
|
||||
|
||||
msgctxt "#30409"
|
||||
msgid "Add-on Actions"
|
||||
msgstr "Add-on acties"
|
||||
|
||||
msgctxt "#30408"
|
||||
msgid "Custom Widgets"
|
||||
msgstr "Aangepaste widgets"
|
||||
|
||||
msgctxt "#30407"
|
||||
msgid "Global Lists"
|
||||
msgstr "Globale lijsten"
|
||||
|
||||
msgctxt "#30406"
|
||||
msgid "Jellyfin Libraries"
|
||||
msgstr "Jellyfin-bibliotheken"
|
||||
|
||||
msgctxt "#30405"
|
||||
msgid " - Show All"
|
||||
msgstr "- Toon alles"
|
||||
|
||||
msgctxt "#30404"
|
||||
msgid " - A-Z"
|
||||
msgstr "- A-Z"
|
||||
|
||||
msgctxt "#30403"
|
||||
msgid "Movies - Recommendations"
|
||||
msgstr "Films - Aanbevelingen"
|
||||
|
||||
msgctxt "#30402"
|
||||
msgid "Add to Kodi Playlist"
|
||||
msgstr "Voeg toe aan Kodi afspeellijst"
|
||||
|
||||
msgctxt "#30401"
|
||||
msgid "Info"
|
||||
msgstr "Info"
|
||||
|
||||
msgctxt "#30400"
|
||||
msgid "Cache images interval minutes (0 = disabled)"
|
||||
msgstr "Cache afbeeldingen interval in minuten (0 = uitgeschakeld)"
|
||||
|
||||
msgctxt "#30399"
|
||||
msgid "Hide"
|
||||
msgstr "Verbergen"
|
||||
|
||||
msgctxt "#30398"
|
||||
msgid "Refresh Jellyfin Metadata"
|
||||
msgstr "Ververs Jellyfin metadata"
|
||||
|
||||
msgctxt "#30397"
|
||||
msgid " - Pages"
|
||||
msgstr "- Pagina's"
|
||||
|
||||
msgctxt "#30395"
|
||||
msgid "Clear cached server data"
|
||||
msgstr "Verwijder gecachte servergegevens"
|
||||
|
||||
msgctxt "#30394"
|
||||
msgid "Cache files deleted"
|
||||
msgstr "Cachebestanden verwijderd"
|
||||
|
||||
msgctxt "#30393"
|
||||
msgid "Clear Cache Result"
|
||||
msgstr "Resultaat cache wissen"
|
||||
|
||||
msgctxt "#30392"
|
||||
msgid "HTTPS"
|
||||
msgstr "HTTPS"
|
||||
|
||||
msgctxt "#30391"
|
||||
msgid "HTTP"
|
||||
msgstr "HTTP"
|
||||
|
||||
msgctxt "#30390"
|
||||
msgid "Protocol"
|
||||
msgstr "Protocol"
|
||||
|
||||
msgctxt "#30389"
|
||||
msgid "User details"
|
||||
msgstr "Gebruikersgegevens"
|
||||
|
||||
msgctxt "#30388"
|
||||
msgid "Server details"
|
||||
msgstr "Servergegevens"
|
||||
|
||||
msgctxt "#30386"
|
||||
msgid "Unused Jellyfin images : "
|
||||
msgstr "Aantal ongebruikte Jellyfin afbeeldingen:"
|
||||
|
||||
msgctxt "#30387"
|
||||
msgid "Unused images removed : "
|
||||
msgstr "Aantal ongebruikte afbeeldingen verwijderd:"
|
||||
|
||||
msgctxt "#30385"
|
||||
msgid "Existing images before delete : "
|
||||
msgstr "Bestaande afbeeldingen vóór verwijderen:"
|
||||
|
||||
msgctxt "#30384"
|
||||
msgid "Random movies interval minutes (0 = disabled)"
|
||||
msgstr "Willekeurige films interval in minuten (0 = uitgeschakeld)"
|
||||
|
||||
msgctxt "#30383"
|
||||
msgid "System - "
|
||||
msgstr "Systeem -"
|
||||
|
||||
msgctxt "#30382"
|
||||
msgid "Always"
|
||||
msgstr "Altijd"
|
||||
|
||||
msgctxt "#30381"
|
||||
msgid "More than one"
|
||||
msgstr "Meer dan één"
|
||||
|
||||
msgctxt "#30380"
|
||||
msgid "Never"
|
||||
msgstr "Nooit"
|
||||
|
||||
msgctxt "#30379"
|
||||
msgid "External subtitle prompt"
|
||||
msgstr "Externe ondertitel melding"
|
||||
|
||||
msgctxt "#30378"
|
||||
msgid "Persist user details"
|
||||
msgstr "Vasthouden gebruikersgegevens"
|
||||
|
||||
msgctxt "#30377"
|
||||
msgid "Sending request"
|
||||
msgstr "Verzoek verzenden"
|
||||
|
||||
msgctxt "#30376"
|
||||
msgid "Checking server url"
|
||||
msgstr "Server-URL controleren"
|
||||
|
||||
msgctxt "#30375"
|
||||
msgid "Receiving data packet"
|
||||
msgstr "Gegevenspakket ontvangen"
|
||||
|
||||
msgctxt "#30374"
|
||||
msgid "Sending request"
|
||||
msgstr "Verzoek verzenden"
|
||||
|
||||
msgctxt "#30373"
|
||||
msgid "Scanning for local servers"
|
||||
msgstr "Op zoek naar lokale servers"
|
||||
|
||||
msgctxt "#30372"
|
||||
msgid "Server URL"
|
||||
msgstr "Server URL"
|
||||
|
||||
msgctxt "#30371"
|
||||
msgid "Could not connect to the URL you entered, do you want to try again?"
|
||||
msgstr ""
|
||||
"Kon geen verbinding maken met de URL die u heeft ingevoerd, wilt u het "
|
||||
"opnieuw proberen?"
|
||||
|
||||
msgctxt "#30369"
|
||||
msgid "Do you want to clear your saved password?"
|
||||
msgstr "Wilt u het opgeslagen wachtwoord verwijderen?"
|
||||
|
||||
msgctxt "#30370"
|
||||
msgid "Do you want to manually enter a server url?"
|
||||
msgstr "Wilt u handmatig een server-url invoeren?"
|
||||
|
||||
msgctxt "#30368"
|
||||
msgid "Clear Password?"
|
||||
msgstr "Wachtwoord verwijderen?"
|
||||
|
||||
msgctxt "#30367"
|
||||
msgid "Allow fast user switching password saving"
|
||||
msgstr "Snel opslaan van het gewisselde gebruikerswachtwoord toestaan"
|
||||
|
||||
msgctxt "#30366"
|
||||
msgid "Manually enter user details"
|
||||
msgstr "Gebruikersgegevens handmatig invoeren"
|
||||
|
||||
msgctxt "#30365"
|
||||
msgid "Manual Login"
|
||||
msgstr "Handmatig inloggen"
|
||||
|
||||
msgctxt "#30364"
|
||||
msgid "Do you want to save the password?"
|
||||
msgstr "Wil je dit wachtwoord opslaan?"
|
||||
|
||||
msgctxt "#30363"
|
||||
msgid "Save Password?"
|
||||
msgstr "Wachtwoord opslaan?"
|
||||
|
||||
msgctxt "#30362"
|
||||
msgid " - Recordings"
|
||||
msgstr "- Opnames"
|
||||
|
||||
msgctxt "#30361"
|
||||
msgid " - Programs"
|
||||
msgstr "- Programma's"
|
||||
|
||||
msgctxt "#30360"
|
||||
msgid " - Channels"
|
||||
msgstr "- Kanalen"
|
||||
|
||||
msgctxt "#30359"
|
||||
msgid "Building full image list"
|
||||
msgstr "Volledige afbeeldingenlijst aan het opbouwen"
|
||||
|
||||
msgctxt "#30356"
|
||||
msgid "Loading existing image list"
|
||||
msgstr "Bestaande afbeeldingenlijst aan het laden"
|
||||
|
||||
msgctxt "#30358"
|
||||
msgid "Retreiving remote image list"
|
||||
msgstr "Externe afbeeldingenlijst aan het ophalen"
|
||||
|
||||
msgctxt "#30357"
|
||||
msgid "Processing existing image list"
|
||||
msgstr "De bestaande afbeeldingenlijst aan het verwerken"
|
||||
|
||||
msgctxt "#30355"
|
||||
msgid "Kodi Settings->Services->Allow remote control via HTTP"
|
||||
msgstr "Kodi instellingen->Services->Toegang van afstand via HTTP toestaan"
|
||||
|
||||
msgctxt "#30354"
|
||||
msgid "Go To Series"
|
||||
msgstr "Ga naar serie"
|
||||
|
||||
msgctxt "#30353"
|
||||
msgid " - Frequently Played"
|
||||
msgstr "- Vaak afgespeeld"
|
||||
|
||||
msgctxt "#30321"
|
||||
msgid " - Album Artists"
|
||||
msgstr "- Album artiesten"
|
||||
|
||||
msgctxt "#30319"
|
||||
msgid "Music - All Album Artists"
|
||||
msgstr "Muziek - Alle album artiesten"
|
||||
|
||||
msgctxt "#30349"
|
||||
msgid " - Recently Played"
|
||||
msgstr "- Recent afgespeeld"
|
||||
|
||||
msgctxt "#30348"
|
||||
msgid "Add user ratings"
|
||||
msgstr "Gebruikersbeoordelingen toevoegen"
|
||||
|
||||
msgctxt "#30347"
|
||||
msgid "Getting Existing Images"
|
||||
msgstr "Bestaande afbeeldingen ophalen"
|
||||
|
||||
msgctxt "#30346"
|
||||
msgid "Deleteing Cached Images"
|
||||
msgstr "Gecachte afbeeldingen aan het verwijderen"
|
||||
|
||||
msgctxt "#30345"
|
||||
msgid "Cache Jellyfin server data requests"
|
||||
msgstr "Jellyfin server data verzoeken cachen"
|
||||
|
||||
msgctxt "#30344"
|
||||
msgid "Number of images removed from cache"
|
||||
msgstr "Aantal afbeeldingen uit cache verwijderd"
|
||||
|
||||
msgctxt "#30343"
|
||||
msgid "Changes Require Kodi Restart"
|
||||
msgstr "Door de veranderingen moet Kodi opnieuw opstarten"
|
||||
|
||||
msgctxt "#30342"
|
||||
msgid "New content check interval (0 = disabled)"
|
||||
msgstr "Nieuwe content controle interval (0 = uitgeschakeld)"
|
||||
|
||||
msgctxt "#30341"
|
||||
msgid "Background image update interval (0 = disabled)"
|
||||
msgstr "Achtergrondafbeelding update interval (0 = uitgeschakeld)"
|
||||
|
||||
msgctxt "#30340"
|
||||
msgid "Group movies into collections"
|
||||
msgstr "Groepeer films in collecties"
|
||||
|
||||
msgctxt "#30446"
|
||||
msgid "There was an error logging in"
|
||||
msgstr "Er ging iets fout tijdens het inloggen"
|
||||
|
||||
msgctxt "#30447"
|
||||
msgid "Max Play Queue Size"
|
||||
msgstr "Maximale afspeelwachtrijlengte"
|
||||
|
||||
msgctxt "#30448"
|
||||
msgid "Shuffle"
|
||||
msgstr "Willekeurig"
|
||||
|
||||
msgctxt "#30449"
|
||||
msgid "Instant Mix"
|
||||
msgstr "Directe Mix"
|
||||
|
||||
msgctxt "#30225"
|
||||
msgid "Interface Mode"
|
||||
msgstr "Interface-modus"
|
||||
|
||||
msgctxt "#30226"
|
||||
msgid "Default"
|
||||
msgstr "Standaard"
|
||||
|
||||
msgctxt "#30227"
|
||||
msgid "Simple"
|
||||
msgstr "Eenvoudig"
|
||||
|
||||
msgctxt "#30450"
|
||||
msgid "Next Up Rewatching"
|
||||
msgstr "Volgende Herbekijken"
|
||||
|
||||
msgctxt "#30451"
|
||||
msgid "Rewatch Days (0 = Disabled)"
|
||||
msgstr "Terugkijkdagen (0 = uitgeschakeld)"
|
||||
|
||||
msgctxt "#30242"
|
||||
msgid "Force transcode av1"
|
||||
msgstr "Forceer transcoderen av1"
|
||||
|
||||
msgctxt "#30452"
|
||||
msgid "Combine instead of replace (might cause slow-down)"
|
||||
msgstr "Samenvoegen in de plaats van vervangen (kan vertragingen veroorzaken)"
|
||||
|
||||
msgctxt "#30453"
|
||||
msgid "Hide number of items to show on entry title"
|
||||
msgstr "Verberg aantal items bij weergeven van titel"
|
||||
|
||||
msgctxt "#30454"
|
||||
msgid " - Totally Unwatched"
|
||||
msgstr " Geheel niet bekeken"
|
||||
|
||||
msgctxt "#30667"
|
||||
msgid "Action to take"
|
||||
msgstr "Uit te voeren actie"
|
||||
|
||||
msgctxt "#30672"
|
||||
msgid "Skip"
|
||||
msgstr "Overslaan"
|
||||
|
||||
msgctxt "#30673"
|
||||
msgid "Ask"
|
||||
msgstr "Vragen"
|
||||
|
||||
msgctxt "#30674"
|
||||
msgid "Do Nothing"
|
||||
msgstr "Niets doen"
|
||||
|
||||
msgctxt "#30666"
|
||||
msgid "Segment Skipper"
|
||||
msgstr "Segment Overslagen"
|
||||
|
||||
msgctxt "#30668"
|
||||
msgid "Start Offset (seconds)"
|
||||
msgstr "Start Offset (seconden)"
|
||||
|
||||
msgctxt "#30669"
|
||||
msgid "End Offset (seconds)"
|
||||
msgstr "Einde Offset (seconden)"
|
||||
|
||||
msgctxt "#30670"
|
||||
msgid "Intro Skipper"
|
||||
msgstr "Intro Skipper"
|
||||
|
||||
msgctxt "#30671"
|
||||
msgid "Credit Skipper"
|
||||
msgstr "Krediet Skipper"
|
||||
|
||||
msgctxt "#30675"
|
||||
msgid "Commercial Skipper"
|
||||
msgstr "Reclame Skipper"
|
||||
|
||||
msgctxt "#30676"
|
||||
msgid "Preview Skipper"
|
||||
msgstr "Preview Skipper"
|
||||
|
||||
msgctxt "#30677"
|
||||
msgid "Recap Skipper"
|
||||
msgstr "Samenvatting Skipper"
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"PO-Revision-Date: 2022-06-28 13:22+0000\n"
|
||||
"Last-Translator: Marcin Woliński <cierdek@gmail.com>\n"
|
||||
"PO-Revision-Date: 2025-12-15 22:55+0000\n"
|
||||
"Last-Translator: Kityn <kitynska@gmail.com>\n"
|
||||
"Language-Team: Polish <https://translate.jellyfin.org/projects/jellycon/"
|
||||
"jellycon/pl/>\n"
|
||||
"Language: pl\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=3; plural=n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 "
|
||||
"|| n%100>=20) ? 1 : 2;\n"
|
||||
"X-Generator: Weblate 4.10.1\n"
|
||||
"Plural-Forms: nplurals=3; plural=n==1 ? 0 : n%10>=2 && n%10<=4 && "
|
||||
"(n%100<10 || n%100>=20) ? 1 : 2;\n"
|
||||
"X-Generator: Weblate 5.14\n"
|
||||
|
||||
msgctxt "#30313"
|
||||
msgid "Menu"
|
||||
@@ -118,11 +118,11 @@ msgstr "- Ostatnie"
|
||||
|
||||
msgctxt "#30287"
|
||||
msgid "TV Shows - Latest"
|
||||
msgstr "Seriale — ostatnie"
|
||||
msgstr "Seriale - Ostatnie"
|
||||
|
||||
msgctxt "#30286"
|
||||
msgid "Movies - Unwatched"
|
||||
msgstr "Filmy – nieobejrzane"
|
||||
msgstr "Filmy - Nieobejrzane"
|
||||
|
||||
msgctxt "#30285"
|
||||
msgid " - Unwatched"
|
||||
@@ -146,7 +146,7 @@ msgstr "Brak tytułu"
|
||||
|
||||
msgctxt "#30279"
|
||||
msgid "TV Shows - Unwatched"
|
||||
msgstr "Seriale - Nieoglądane"
|
||||
msgstr "Seriale - Nieobejrzane"
|
||||
|
||||
msgctxt "#30278"
|
||||
msgid " - Next Up"
|
||||
@@ -181,7 +181,7 @@ msgstr "Ustaw ulubione"
|
||||
|
||||
msgctxt "#30271"
|
||||
msgid "Mark Unwatched"
|
||||
msgstr "Oznacz nieoglądane"
|
||||
msgstr "Oznacz nieobejrzane"
|
||||
|
||||
msgctxt "#30270"
|
||||
msgid "Mark Watched"
|
||||
@@ -189,7 +189,7 @@ msgstr "Zaznacz obserwowane"
|
||||
|
||||
msgctxt "#30269"
|
||||
msgid "Movies - Random"
|
||||
msgstr "Filmy — losowe"
|
||||
msgstr "Filmy - Losowe"
|
||||
|
||||
msgctxt "#30268"
|
||||
msgid " - Recently Added"
|
||||
@@ -201,23 +201,23 @@ msgstr "- W trakcie"
|
||||
|
||||
msgctxt "#30266"
|
||||
msgid "Movies - Pages"
|
||||
msgstr "Filmy – Strony"
|
||||
msgstr "Filmy - Strony"
|
||||
|
||||
msgctxt "#30265"
|
||||
msgid "Episodes - Next Up"
|
||||
msgstr "Odcinki — Następny"
|
||||
msgstr "Odcinki - Następny"
|
||||
|
||||
msgctxt "#30264"
|
||||
msgid "Episodes - In Progress"
|
||||
msgstr "Odcinki — w toku"
|
||||
msgstr "Odcinki - W trakcie"
|
||||
|
||||
msgctxt "#30263"
|
||||
msgid "Episodes - Recently Added"
|
||||
msgstr "Odcinki — ostatnio dodane"
|
||||
msgstr "Odcinki - Ostatnio dodane"
|
||||
|
||||
msgctxt "#30262"
|
||||
msgid "TV Shows - Favorites"
|
||||
msgstr "Seriale – Ulubione"
|
||||
msgstr "Seriale - Ulubione"
|
||||
|
||||
msgctxt "#30261"
|
||||
msgid "TV Shows"
|
||||
@@ -233,11 +233,11 @@ msgstr "Filmy - Ulubione"
|
||||
|
||||
msgctxt "#30258"
|
||||
msgid "Movies - In Progress"
|
||||
msgstr "Filmy – w toku"
|
||||
msgstr "Filmy - W trakcie"
|
||||
|
||||
msgctxt "#30257"
|
||||
msgid "Movies - Recently Added"
|
||||
msgstr "Filmy — ostatnio dodane"
|
||||
msgstr "Filmy - Ostatnio dodane"
|
||||
|
||||
msgctxt "#30256"
|
||||
msgid "Movies"
|
||||
@@ -257,7 +257,7 @@ msgstr "Filmy - A-Z"
|
||||
|
||||
msgctxt "#30251"
|
||||
msgid "Movies - Genres"
|
||||
msgstr "Filmy – Gatunki"
|
||||
msgstr "Filmy - Gatunki"
|
||||
|
||||
msgctxt "#30250"
|
||||
msgid "Unknown"
|
||||
@@ -309,7 +309,7 @@ msgstr "Seriale"
|
||||
|
||||
msgctxt "#30213"
|
||||
msgid "Video force 8 bit"
|
||||
msgstr "Wymuś video 8 bit"
|
||||
msgstr "Wymuś wideo 8-bitowe"
|
||||
|
||||
msgctxt "#30224"
|
||||
msgid "Interaction"
|
||||
@@ -429,11 +429,11 @@ msgstr "Brak zestawu typu nośnika"
|
||||
|
||||
msgctxt "#30321"
|
||||
msgid " - Album Artists"
|
||||
msgstr "- Artyści albumów"
|
||||
msgstr "- Wykonawcy albumów"
|
||||
|
||||
msgctxt "#30319"
|
||||
msgid "Music - All Album Artists"
|
||||
msgstr "Muzyka — wszyscy wykonawcy albumów"
|
||||
msgstr "Muzyka - Wszyscy wykonawcy albumów"
|
||||
|
||||
msgctxt "#30332"
|
||||
msgid "Stop media playback on screensaver activation"
|
||||
@@ -794,7 +794,7 @@ msgstr "- A-Z"
|
||||
|
||||
msgctxt "#30403"
|
||||
msgid "Movies - Recommendations"
|
||||
msgstr "Filmy – rekomendacje"
|
||||
msgstr "Filmy - Rekomendacje"
|
||||
|
||||
msgctxt "#30402"
|
||||
msgid "Add to Kodi Playlist"
|
||||
@@ -996,15 +996,15 @@ msgstr "- Często odtwarzane"
|
||||
|
||||
msgctxt "#30352"
|
||||
msgid "Music - Frequently Played"
|
||||
msgstr "Muzyka — często odtwarzana"
|
||||
msgstr "Muzyka - Często odtwarzana"
|
||||
|
||||
msgctxt "#30351"
|
||||
msgid "Music - Recently Played"
|
||||
msgstr "Muzyka — ostatnio odtwarzane"
|
||||
msgstr "Muzyka - Ostatnio odtwarzane"
|
||||
|
||||
msgctxt "#30350"
|
||||
msgid "Music - Recently Added"
|
||||
msgstr "Muzyka — ostatnio dodane"
|
||||
msgstr "Muzyka - Ostatnio dodane"
|
||||
|
||||
msgctxt "#30349"
|
||||
msgid " - Recently Played"
|
||||
@@ -1044,7 +1044,7 @@ msgstr "Interwał aktualizacji obrazu tła (0 = wyłączone)"
|
||||
|
||||
msgctxt "#30340"
|
||||
msgid "Group movies into collections"
|
||||
msgstr "Grupuj filmy w kolekcję"
|
||||
msgstr "Grupuj filmy w kolekcje"
|
||||
|
||||
msgctxt "#30339"
|
||||
msgid "Person"
|
||||
@@ -1092,12 +1092,140 @@ msgstr "Opcje odtwarzania"
|
||||
|
||||
msgctxt "#30444"
|
||||
msgid "Login using Quick Connect"
|
||||
msgstr "Zaloguj używając Szybkiego Połączenia"
|
||||
msgstr "Zaloguj przy użyciu szybkiego łączenia"
|
||||
|
||||
msgctxt "#30443"
|
||||
msgid "Quick Connect"
|
||||
msgstr "Szybkie połączenie"
|
||||
msgstr "Szybkie łączenie"
|
||||
|
||||
msgctxt "#30323"
|
||||
msgid "Artists"
|
||||
msgstr "Artyści"
|
||||
msgstr "Wykonawcy"
|
||||
|
||||
msgctxt "#30439"
|
||||
msgid "Show play next episode at time left in seconds"
|
||||
msgstr "Pokaż odtworzenie następnego odcinka o czasie pozostałym w sekundach"
|
||||
|
||||
msgctxt "#30446"
|
||||
msgid "There was an error logging in"
|
||||
msgstr "Wystąpił błąd podczas logowania"
|
||||
|
||||
msgctxt "#30445"
|
||||
msgid "Continue Watching"
|
||||
msgstr "Kontynuuj oglądanie"
|
||||
|
||||
msgctxt "#30447"
|
||||
msgid "Max Play Queue Size"
|
||||
msgstr "Maksymalny rozmiar kolejki odtwarzania"
|
||||
|
||||
msgctxt "#30448"
|
||||
msgid "Shuffle"
|
||||
msgstr "Tasuj"
|
||||
|
||||
msgctxt "#30449"
|
||||
msgid "Instant Mix"
|
||||
msgstr "Natychmiastowe mieszanie"
|
||||
|
||||
msgctxt "#30225"
|
||||
msgid "Interface Mode"
|
||||
msgstr "Tryb interfejsu"
|
||||
|
||||
msgctxt "#30226"
|
||||
msgid "Default"
|
||||
msgstr "Domyślny"
|
||||
|
||||
msgctxt "#30227"
|
||||
msgid "Simple"
|
||||
msgstr "Prosty"
|
||||
|
||||
msgctxt "#30242"
|
||||
msgid "Force transcode av1"
|
||||
msgstr "Wymuś transkodowanie av1"
|
||||
|
||||
msgctxt "#30450"
|
||||
msgid "Next Up Rewatching"
|
||||
msgstr "Następne ponowne oglądanie"
|
||||
|
||||
msgctxt "#30451"
|
||||
msgid "Rewatch Days (0 = Disabled)"
|
||||
msgstr "Dni ponownego oglądania (0 = wyłączone)"
|
||||
|
||||
msgctxt "#30452"
|
||||
msgid "Combine instead of replace (might cause slow-down)"
|
||||
msgstr "Łącz zamiast zastępować (może powodować spowolnienie)"
|
||||
|
||||
msgctxt "#30453"
|
||||
msgid "Hide number of items to show on entry title"
|
||||
msgstr "Ukryj liczbę pozycji wyświetlanych w tytule wpisu"
|
||||
|
||||
msgctxt "#30454"
|
||||
msgid " - Totally Unwatched"
|
||||
msgstr " – Zupełnie nieobejrzane"
|
||||
|
||||
msgctxt "#30667"
|
||||
msgid "Action to take"
|
||||
msgstr "Działanie do podjęcia"
|
||||
|
||||
msgctxt "#30669"
|
||||
msgid "End Offset (seconds)"
|
||||
msgstr "Przesunięcie zakończenia (sekundy)"
|
||||
|
||||
msgctxt "#30671"
|
||||
msgid "Credit Skipper"
|
||||
msgstr "Pomijanie napisów końcowych"
|
||||
|
||||
msgctxt "#30670"
|
||||
msgid "Intro Skipper"
|
||||
msgstr "Pomijanie wprowadzeń"
|
||||
|
||||
msgctxt "#30673"
|
||||
msgid "Ask"
|
||||
msgstr "Zapytaj"
|
||||
|
||||
msgctxt "#30675"
|
||||
msgid "Commercial Skipper"
|
||||
msgstr "Pomijanie reklam"
|
||||
|
||||
msgctxt "#30676"
|
||||
msgid "Preview Skipper"
|
||||
msgstr "Pomijanie zapowiedzi"
|
||||
|
||||
msgctxt "#30677"
|
||||
msgid "Recap Skipper"
|
||||
msgstr "Pomijanie podsumowań"
|
||||
|
||||
msgctxt "#30666"
|
||||
msgid "Segment Skipper"
|
||||
msgstr "Pomijanie segmentów"
|
||||
|
||||
msgctxt "#30668"
|
||||
msgid "Start Offset (seconds)"
|
||||
msgstr "Przesunięcie rozpoczęcia (sekundy)"
|
||||
|
||||
msgctxt "#30672"
|
||||
msgid "Skip"
|
||||
msgstr "Pomiń"
|
||||
|
||||
msgctxt "#30674"
|
||||
msgid "Do Nothing"
|
||||
msgstr "Nic nie rób"
|
||||
|
||||
msgctxt "#30455"
|
||||
msgid "TV Shows - Random"
|
||||
msgstr "Seriale - Losowo"
|
||||
|
||||
msgctxt "#30456"
|
||||
msgid "All - Random"
|
||||
msgstr "Wszystkie - Losowo"
|
||||
|
||||
msgctxt "#30457"
|
||||
msgid "All - Recently Added"
|
||||
msgstr "Wszystkie - Ostatnio dodane"
|
||||
|
||||
msgctxt "#30458"
|
||||
msgid "All - Favorites"
|
||||
msgstr "Wszystkie - Ulubione"
|
||||
|
||||
msgctxt "#30678"
|
||||
msgid "TV Shows per page"
|
||||
msgstr "Seriale na stronę"
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"PO-Revision-Date: 2022-06-08 04:22+0000\n"
|
||||
"Last-Translator: WWWesten <wwwesten@gmail.com>\n"
|
||||
"PO-Revision-Date: 2025-12-23 08:05+0000\n"
|
||||
"Last-Translator: Gallyam Biktashev <gallyamb@gmail.com>\n"
|
||||
"Language-Team: Russian <https://translate.jellyfin.org/projects/jellycon/"
|
||||
"jellycon/ru/>\n"
|
||||
"Language: ru\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
|
||||
"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
|
||||
"X-Generator: Weblate 4.10.1\n"
|
||||
"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
|
||||
"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
|
||||
"X-Generator: Weblate 5.14\n"
|
||||
|
||||
msgctxt "#30332"
|
||||
msgid "Stop media playback on screensaver activation"
|
||||
@@ -46,7 +46,7 @@ msgstr "Обработка элемента:"
|
||||
|
||||
msgctxt "#30017"
|
||||
msgid "Show connected clients"
|
||||
msgstr "Показывать подсоединённых клиентов"
|
||||
msgstr "Показывать подсоединённые устройства"
|
||||
|
||||
msgctxt "#30275"
|
||||
msgid "Force Transcode"
|
||||
@@ -309,7 +309,7 @@ msgstr "ТВ-передачи - Жанры"
|
||||
|
||||
msgctxt "#30287"
|
||||
msgid "TV Shows - Latest"
|
||||
msgstr "ТВ-передачи - Крайние"
|
||||
msgstr "ТВ-передачи - Последние"
|
||||
|
||||
msgctxt "#30279"
|
||||
msgid "TV Shows - Unwatched"
|
||||
@@ -345,15 +345,15 @@ msgstr "Фильмы - Недавно добавленные"
|
||||
|
||||
msgctxt "#30299"
|
||||
msgid "Cache Images"
|
||||
msgstr "Кэшировать рисунки"
|
||||
msgstr "Кэшировать изображения"
|
||||
|
||||
msgctxt "#30293"
|
||||
msgid "Cache images"
|
||||
msgstr "Кэшировать рисунки"
|
||||
msgstr "Кэшировать изображения"
|
||||
|
||||
msgctxt "#30288"
|
||||
msgid " - Latest"
|
||||
msgstr "- Крайние"
|
||||
msgstr "- Последние"
|
||||
|
||||
msgctxt "#30285"
|
||||
msgid " - Unwatched"
|
||||
@@ -389,7 +389,7 @@ msgstr "Ошибка URL"
|
||||
|
||||
msgctxt "#30183"
|
||||
msgid "Include people"
|
||||
msgstr "Включить людей"
|
||||
msgstr "Включить пользователей"
|
||||
|
||||
msgctxt "#30181"
|
||||
msgid "Include plot"
|
||||
@@ -621,7 +621,7 @@ msgstr "Подновить кэшированные рисунки"
|
||||
|
||||
msgctxt "#30278"
|
||||
msgid " - Next Up"
|
||||
msgstr "- Очередное"
|
||||
msgstr "- Последнее"
|
||||
|
||||
msgctxt "#30269"
|
||||
msgid "Movies - Random"
|
||||
@@ -1085,7 +1085,7 @@ msgstr "Порт"
|
||||
|
||||
msgctxt "#30000"
|
||||
msgid "Host"
|
||||
msgstr "Узел"
|
||||
msgstr "Адрес сервера"
|
||||
|
||||
msgctxt "#30444"
|
||||
msgid "Login using Quick Connect"
|
||||
@@ -1098,3 +1098,132 @@ msgstr "Быстрое подключение"
|
||||
msgctxt "#30323"
|
||||
msgid "Artists"
|
||||
msgstr "Исполнители"
|
||||
|
||||
msgctxt "#30445"
|
||||
msgid "Continue Watching"
|
||||
msgstr "Продолжение просмотра"
|
||||
|
||||
msgctxt "#30439"
|
||||
msgid "Show play next episode at time left in seconds"
|
||||
msgstr ""
|
||||
"За сколько секунд до окончания показывать \"Воспроизвести следующий эпизод\""
|
||||
|
||||
msgctxt "#30446"
|
||||
msgid "There was an error logging in"
|
||||
msgstr "Произошла ошибка при входе"
|
||||
|
||||
msgctxt "#30448"
|
||||
msgid "Shuffle"
|
||||
msgstr "Перемешать"
|
||||
|
||||
msgctxt "#30447"
|
||||
msgid "Max Play Queue Size"
|
||||
msgstr "Максимальный размер очереди"
|
||||
|
||||
msgctxt "#30449"
|
||||
msgid "Instant Mix"
|
||||
msgstr "Мгновенное перемешивание"
|
||||
|
||||
msgctxt "#30225"
|
||||
msgid "Interface Mode"
|
||||
msgstr "Режим интерфейса"
|
||||
|
||||
msgctxt "#30226"
|
||||
msgid "Default"
|
||||
msgstr "По умолчанию"
|
||||
|
||||
msgctxt "#30227"
|
||||
msgid "Simple"
|
||||
msgstr "Простой"
|
||||
|
||||
msgctxt "#30242"
|
||||
msgid "Force transcode av1"
|
||||
msgstr "Принудительное перекодирование av1"
|
||||
|
||||
msgctxt "#30452"
|
||||
msgid "Combine instead of replace (might cause slow-down)"
|
||||
msgstr "Объединение вместо замены (может привести к замедлению работы)"
|
||||
|
||||
msgctxt "#30453"
|
||||
msgid "Hide number of items to show on entry title"
|
||||
msgstr "Скрыть количество элементов в заголовке"
|
||||
|
||||
msgctxt "#30450"
|
||||
msgid "Next Up Rewatching"
|
||||
msgstr "Далее Повторный просмотр"
|
||||
|
||||
msgctxt "#30451"
|
||||
msgid "Rewatch Days (0 = Disabled)"
|
||||
msgstr "Дни повторного просмотра (0 = отключено)"
|
||||
|
||||
msgctxt "#30454"
|
||||
msgid " - Totally Unwatched"
|
||||
msgstr " Общее непросмотренное"
|
||||
|
||||
msgctxt "#30672"
|
||||
msgid "Skip"
|
||||
msgstr "Пропустить"
|
||||
|
||||
msgctxt "#30667"
|
||||
msgid "Action to take"
|
||||
msgstr "Действие для выполнения"
|
||||
|
||||
msgctxt "#30668"
|
||||
msgid "Start Offset (seconds)"
|
||||
msgstr "Начальное смещение (в секундах)"
|
||||
|
||||
msgctxt "#30669"
|
||||
msgid "End Offset (seconds)"
|
||||
msgstr "Конечное смещение (в секундах)"
|
||||
|
||||
msgctxt "#30666"
|
||||
msgid "Segment Skipper"
|
||||
msgstr "Пропуск сегментов"
|
||||
|
||||
msgctxt "#30673"
|
||||
msgid "Ask"
|
||||
msgstr "Спросить"
|
||||
|
||||
msgctxt "#30674"
|
||||
msgid "Do Nothing"
|
||||
msgstr "Ничего не делать"
|
||||
|
||||
msgctxt "#30670"
|
||||
msgid "Intro Skipper"
|
||||
msgstr "Пропуск вступления"
|
||||
|
||||
msgctxt "#30671"
|
||||
msgid "Credit Skipper"
|
||||
msgstr "Пропуск титров"
|
||||
|
||||
msgctxt "#30675"
|
||||
msgid "Commercial Skipper"
|
||||
msgstr "Пропуск рекламы"
|
||||
|
||||
msgctxt "#30676"
|
||||
msgid "Preview Skipper"
|
||||
msgstr "Пропуск обзора"
|
||||
|
||||
msgctxt "#30677"
|
||||
msgid "Recap Skipper"
|
||||
msgstr "Пропуск повтора"
|
||||
|
||||
msgctxt "#30455"
|
||||
msgid "TV Shows - Random"
|
||||
msgstr "Телешоу - случайно"
|
||||
|
||||
msgctxt "#30456"
|
||||
msgid "All - Random"
|
||||
msgstr "Всё - случайно"
|
||||
|
||||
msgctxt "#30457"
|
||||
msgid "All - Recently Added"
|
||||
msgstr "Всё - недавно добавленные"
|
||||
|
||||
msgctxt "#30458"
|
||||
msgid "All - Favorites"
|
||||
msgstr "Всё - избранное"
|
||||
|
||||
msgctxt "#30678"
|
||||
msgid "TV Shows per page"
|
||||
msgstr "Телешоу на странице"
|
||||
|
||||
1205
resources/language/resource.language.sk/strings.po
Normal file
1205
resources/language/resource.language.sk/strings.po
Normal file
File diff suppressed because it is too large
Load Diff
60
resources/language/resource.language.sq/strings.po
Normal file
60
resources/language/resource.language.sq/strings.po
Normal file
@@ -0,0 +1,60 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"PO-Revision-Date: 2025-12-13 11:55+0000\n"
|
||||
"Last-Translator: A Boci <ami@boci.co.uk>\n"
|
||||
"Language-Team: Albanian <https://translate.jellyfin.org/projects/jellycon/"
|
||||
"jellycon/sq/>\n"
|
||||
"Language: sq\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=n != 1;\n"
|
||||
"X-Generator: Weblate 5.14\n"
|
||||
|
||||
msgctxt "#30001"
|
||||
msgid "Port"
|
||||
msgstr "Port"
|
||||
|
||||
msgctxt "#30003"
|
||||
msgid "Verify HTTPS certificate"
|
||||
msgstr "Verifiko çertifikatën HTTPS"
|
||||
|
||||
msgctxt "#30006"
|
||||
msgid "Password"
|
||||
msgstr "Fjalkalimi"
|
||||
|
||||
msgctxt "#30007"
|
||||
msgid "Samba username"
|
||||
msgstr "Përdoruesi Samba"
|
||||
|
||||
msgctxt "#30008"
|
||||
msgid "Samba password"
|
||||
msgstr "Fjalkalimi Samba"
|
||||
|
||||
msgctxt "#30012"
|
||||
msgid "[Change user]"
|
||||
msgstr "[Ndrysho përdoruesin]"
|
||||
|
||||
msgctxt "#30014"
|
||||
msgid "Jellyfin"
|
||||
msgstr "Jellyfin"
|
||||
|
||||
msgctxt "#30016"
|
||||
msgid "Device display name"
|
||||
msgstr "Emri që shfaqet"
|
||||
|
||||
msgctxt "#30000"
|
||||
msgid "Host"
|
||||
msgstr "Host"
|
||||
|
||||
msgctxt "#30005"
|
||||
msgid "Username"
|
||||
msgstr "Përdoruesi"
|
||||
|
||||
msgctxt "#30011"
|
||||
msgid "[Detect local server]"
|
||||
msgstr "[Zbuloni serverin lokal]"
|
||||
|
||||
msgctxt "#30017"
|
||||
msgid "Show connected clients"
|
||||
msgstr "Trego klientët e lidhur"
|
||||
@@ -1,7 +1,7 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"PO-Revision-Date: 2022-06-04 10:22+0000\n"
|
||||
"Last-Translator: hogenf <hogen.fasth@gmail.com>\n"
|
||||
"PO-Revision-Date: 2025-09-10 20:11+0000\n"
|
||||
"Last-Translator: Ärik <kwakz4life@gmail.com>\n"
|
||||
"Language-Team: Swedish <https://translate.jellyfin.org/projects/jellycon/"
|
||||
"jellycon/sv/>\n"
|
||||
"Language: sv\n"
|
||||
@@ -9,7 +9,7 @@ msgstr ""
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=n != 1;\n"
|
||||
"X-Generator: Weblate 4.10.1\n"
|
||||
"X-Generator: Weblate 5.11.4\n"
|
||||
|
||||
msgctxt "#30283"
|
||||
msgid "Play Next Episode?"
|
||||
@@ -17,7 +17,7 @@ msgstr "Spela Nästa Avsnitt?"
|
||||
|
||||
msgctxt "#30240"
|
||||
msgid "Force transcode msmpeg4v3 (divx)"
|
||||
msgstr "Tvinga msmpeg4v3 (divx) transkoding"
|
||||
msgstr "Tvinga msmpeg4v3 (divx) transkodning"
|
||||
|
||||
msgctxt "#30218"
|
||||
msgid "Play next episode after %"
|
||||
@@ -25,7 +25,7 @@ msgstr "Spela nästa avsnitt efter %"
|
||||
|
||||
msgctxt "#30239"
|
||||
msgid "Force transcode mpeg2"
|
||||
msgstr "Tvinga mpeg2 transkoding"
|
||||
msgstr "Tvinga mpeg2 transkodning"
|
||||
|
||||
msgctxt "#30224"
|
||||
msgid "Interaction"
|
||||
@@ -37,7 +37,7 @@ msgstr "Video tvinga 8 bit"
|
||||
|
||||
msgctxt "#30236"
|
||||
msgid "Force transcode h265 (hevc)"
|
||||
msgstr "Tvinga h265 (hevc) transkoding"
|
||||
msgstr "Tvinga h265 (hevc) transkodning"
|
||||
|
||||
msgctxt "#30254"
|
||||
msgid "Show add-on settings"
|
||||
@@ -53,7 +53,7 @@ msgstr "Video max bredd"
|
||||
|
||||
msgctxt "#30211"
|
||||
msgid "Transcode options"
|
||||
msgstr "Transkoding alternativ"
|
||||
msgstr "Transkoderingsinställningar"
|
||||
|
||||
msgctxt "#30163"
|
||||
msgid "Add (cc) if subtitle is available"
|
||||
@@ -225,7 +225,7 @@ msgstr "Inkludera media stream information"
|
||||
|
||||
msgctxt "#30181"
|
||||
msgid "Include plot"
|
||||
msgstr "Inkludera intrig"
|
||||
msgstr "Inkludera handling"
|
||||
|
||||
msgctxt "#30214"
|
||||
msgid "Events"
|
||||
@@ -241,7 +241,7 @@ msgstr "Tvinga mpeg4 transkodning"
|
||||
|
||||
msgctxt "#30260"
|
||||
msgid "BoxSets"
|
||||
msgstr "BoxSet"
|
||||
msgstr "Samlingsbox"
|
||||
|
||||
msgctxt "#30259"
|
||||
msgid "Movies - Favorites"
|
||||
@@ -269,7 +269,7 @@ msgstr "Avsnitt - Nyligen Tillagt"
|
||||
|
||||
msgctxt "#30275"
|
||||
msgid "Force Transcode"
|
||||
msgstr "Tvinga Transkoding"
|
||||
msgstr "Tvinga Transkodning"
|
||||
|
||||
msgctxt "#30273"
|
||||
msgid "Unset Favourite"
|
||||
@@ -313,7 +313,7 @@ msgstr "Filmer - Genrer"
|
||||
|
||||
msgctxt "#30237"
|
||||
msgid "Start from beginning"
|
||||
msgstr "Starta från början"
|
||||
msgstr "Börja från början"
|
||||
|
||||
msgctxt "#30252"
|
||||
msgid "Movies - A-Z"
|
||||
@@ -485,11 +485,11 @@ msgstr "URL error"
|
||||
|
||||
msgctxt "#30114"
|
||||
msgid "Jump back seconds"
|
||||
msgstr "Hoppa tillbaka sekunder"
|
||||
msgstr "spola tillbaka sekunder"
|
||||
|
||||
msgctxt "#30125"
|
||||
msgid "Done"
|
||||
msgstr "Färdig"
|
||||
msgstr "Klar"
|
||||
|
||||
msgctxt "#30139"
|
||||
msgid "No Media Type Set"
|
||||
@@ -517,7 +517,7 @@ msgstr "Använd cachad widget data"
|
||||
|
||||
msgctxt "#30440"
|
||||
msgid "Play next"
|
||||
msgstr "Spela härnest"
|
||||
msgstr "Spela härnäst"
|
||||
|
||||
msgctxt "#30250"
|
||||
msgid "Unknown"
|
||||
@@ -649,15 +649,15 @@ msgstr "Adress:"
|
||||
|
||||
msgctxt "#30110"
|
||||
msgid "Interface"
|
||||
msgstr "Användargränssnitt"
|
||||
msgstr "Gränssnitt"
|
||||
|
||||
msgctxt "#30135"
|
||||
msgid "Error"
|
||||
msgstr "Error"
|
||||
msgstr "Fel"
|
||||
|
||||
msgctxt "#30113"
|
||||
msgid "Retrieving Data"
|
||||
msgstr "Hämtar data"
|
||||
msgstr "Hämtar Data"
|
||||
|
||||
msgctxt "#30112"
|
||||
msgid "Loading Content"
|
||||
@@ -669,7 +669,7 @@ msgstr "Användarnamn kunde inte hittas"
|
||||
|
||||
msgctxt "#30012"
|
||||
msgid "[Change user]"
|
||||
msgstr "[Ändra användare]"
|
||||
msgstr "[Byt användare]"
|
||||
|
||||
msgctxt "#30025"
|
||||
msgid "Password:"
|
||||
@@ -681,7 +681,7 @@ msgstr "Användarnamn:"
|
||||
|
||||
msgctxt "#30017"
|
||||
msgid "Show connected clients"
|
||||
msgstr "Visa anslutna enheter"
|
||||
msgstr "Visa anslutna klienter"
|
||||
|
||||
msgctxt "#30014"
|
||||
msgid "Jellyfin"
|
||||
@@ -689,11 +689,11 @@ msgstr "Jellyfin"
|
||||
|
||||
msgctxt "#30008"
|
||||
msgid "Samba password"
|
||||
msgstr "Samba lösenord"
|
||||
msgstr "Samba-lösenord"
|
||||
|
||||
msgctxt "#30007"
|
||||
msgid "Samba username"
|
||||
msgstr "Samba användarnamn"
|
||||
msgstr "Samba-användarnamn"
|
||||
|
||||
msgctxt "#30006"
|
||||
msgid "Password"
|
||||
@@ -711,10 +711,9 @@ msgctxt "#30330"
|
||||
msgid "Show change user dialog"
|
||||
msgstr "Visa ändra användardialogrutan"
|
||||
|
||||
#, fuzzy
|
||||
msgctxt "#30315"
|
||||
msgid "Suppress notifications for connection errors"
|
||||
msgstr "Undertryck aviseringar för anslutningsfel"
|
||||
msgstr "Visa inte varningar angående anslutningsfel"
|
||||
|
||||
msgctxt "#30304"
|
||||
msgid "Cached Jellyfin images : "
|
||||
@@ -748,10 +747,9 @@ msgctxt "#30295"
|
||||
msgid "To use this feature you need HTTP control enabled"
|
||||
msgstr "För att använda den här funktionen måste du aktivera HTTP-kontroll"
|
||||
|
||||
#, fuzzy
|
||||
msgctxt "#30294"
|
||||
msgid "Notice"
|
||||
msgstr "Notis"
|
||||
msgstr "Bevisning"
|
||||
|
||||
msgctxt "#30293"
|
||||
msgid "Cache images"
|
||||
@@ -765,24 +763,21 @@ msgctxt "#30291"
|
||||
msgid "Select Audio Stream"
|
||||
msgstr "Välj ljudström"
|
||||
|
||||
#, fuzzy
|
||||
msgctxt "#30118"
|
||||
msgid "Add resume percent to names"
|
||||
msgstr "Lägg till fortsättningsprocent i namn"
|
||||
msgstr "Lägg till \"procent kvar\" bredvid namnen"
|
||||
|
||||
#, fuzzy
|
||||
msgctxt "#30116"
|
||||
msgid "Add unwatched counts to names"
|
||||
msgstr "Lägg till ej sedda räkningar till namn"
|
||||
msgstr "Lägg in en \"osedd\" räknare bredvid namnen"
|
||||
|
||||
msgctxt "#30279"
|
||||
msgid "TV Shows - Unwatched"
|
||||
msgstr "TV Serier- Ej sedd"
|
||||
|
||||
#, fuzzy
|
||||
msgctxt "#30286"
|
||||
msgid "Movies - Unwatched"
|
||||
msgstr "Film - Ej sedd"
|
||||
msgstr "Film - Osedda"
|
||||
|
||||
msgctxt "#30285"
|
||||
msgid " - Unwatched"
|
||||
@@ -796,23 +791,19 @@ msgctxt "#30281"
|
||||
msgid "Refresh Cached Images"
|
||||
msgstr "Uppdatera cachelagrade bilder"
|
||||
|
||||
#, fuzzy
|
||||
msgctxt "#30278"
|
||||
msgid " - Next Up"
|
||||
msgstr "- Nästa upp"
|
||||
msgstr "- Nästa"
|
||||
|
||||
#, fuzzy
|
||||
msgctxt "#30277"
|
||||
msgid "JellyCon needs to prompt for resume on partily played items, Kodi can also prompt, this can cause a double prompt. Do you want to remove the double prompt?"
|
||||
msgstr ""
|
||||
"JellyCon måste fråga om återuppta på partiellt spelade objekt, Kodi kan "
|
||||
"också fråga, detta kan orsaka en dubbel prompt. Vill du ta bort den dubbla "
|
||||
"prompten?"
|
||||
"JellyCon måste fråga om att fortsätta påbörjade filmer, Kodi kan också "
|
||||
"fråga, detta kan orsaka två prompter. Vill du ta bort den dubbla prompter?"
|
||||
|
||||
#, fuzzy
|
||||
msgctxt "#30276"
|
||||
msgid "Extra Resume Prompt Detected"
|
||||
msgstr "Extra uppmaning om återuppta upptäckt"
|
||||
msgstr "Extra uppmaning om att fortsätta uppspelning upptäckt"
|
||||
|
||||
msgctxt "#30247"
|
||||
msgid "Custom Widget Content"
|
||||
@@ -824,9 +815,8 @@ msgstr "Alternativ för uppspelning av stream"
|
||||
|
||||
msgctxt "#30220"
|
||||
msgid "Prompt to delete movie after %"
|
||||
msgstr "Uppmaning att radera film efter %"
|
||||
msgstr "Uppmana att radera film efter %"
|
||||
|
||||
#, fuzzy
|
||||
msgctxt "#30219"
|
||||
msgid " - Prompt before play"
|
||||
msgstr "- Fråga före uppspelning"
|
||||
@@ -835,15 +825,13 @@ msgctxt "#30217"
|
||||
msgid "Prompt to delete episode after %"
|
||||
msgstr "Uppmaning att radera avsnitt efter %"
|
||||
|
||||
#, fuzzy
|
||||
msgctxt "#30215"
|
||||
msgid "On playback stop (100% = disabled)"
|
||||
msgstr "Vid uppspelningsstopp (100 % = avaktiverad)"
|
||||
msgstr "Vid uppspelnings stopp (100 % = avaktiverad)"
|
||||
|
||||
#, fuzzy
|
||||
msgctxt "#30210"
|
||||
msgid "HTTP direct stream"
|
||||
msgstr "HTTP direktström"
|
||||
msgstr "HTTP direkt stream"
|
||||
|
||||
msgctxt "#30209"
|
||||
msgid "File direct path"
|
||||
@@ -855,48 +843,43 @@ msgstr "Högsta strömbithastighet (kbps)"
|
||||
|
||||
msgctxt "#30126"
|
||||
msgid "Processing Item : "
|
||||
msgstr "Bearbetning av objektet:"
|
||||
msgstr "Bearbetning av Objektet:"
|
||||
|
||||
msgctxt "#30120"
|
||||
msgid "Show load progress"
|
||||
msgstr "Visa laddningsförloppet"
|
||||
|
||||
#, fuzzy
|
||||
msgctxt "#30063"
|
||||
msgid "N/A"
|
||||
msgstr "Ej tillgängligt"
|
||||
msgstr "N/A"
|
||||
|
||||
#, fuzzy
|
||||
msgctxt "#30053"
|
||||
msgid "Waiting for server to delete"
|
||||
msgstr "Väntar på att servern ska radera"
|
||||
|
||||
msgctxt "#30044"
|
||||
msgid "Incorrect Username/Password"
|
||||
msgstr "Fel användarnamn/lösenord"
|
||||
msgstr "Fel Användarnamn/Lösenord"
|
||||
|
||||
msgctxt "#30027"
|
||||
msgid "Enable debug logging"
|
||||
msgstr "Aktivera felsökningsloggning"
|
||||
|
||||
#, fuzzy
|
||||
msgctxt "#30026"
|
||||
msgid "Widget item select action"
|
||||
msgstr "Välj åtgärd för widgetobjekt"
|
||||
|
||||
msgctxt "#30023"
|
||||
msgid "Hide unwatched episode details"
|
||||
msgstr "Dölj detaljer om avsnittet som inte har setts"
|
||||
msgstr "Dölj detaljer om avsnitt som inte har setts"
|
||||
|
||||
#, fuzzy
|
||||
msgctxt "#30020"
|
||||
msgid "Flatten single season"
|
||||
msgstr "Platta enstaka säsong"
|
||||
msgstr "Platta enskild säsong"
|
||||
|
||||
#, fuzzy
|
||||
msgctxt "#30019"
|
||||
msgid "Filtered episode name format"
|
||||
msgstr "Filtrerat avsnittsnamnformat"
|
||||
msgstr "Filtrerat format för avsnittsnamn"
|
||||
|
||||
msgctxt "#30018"
|
||||
msgid "Number of items to show in filtered lists"
|
||||
@@ -906,12 +889,315 @@ msgctxt "#30016"
|
||||
msgid "Device display name"
|
||||
msgstr "Enhetens visningsnamn"
|
||||
|
||||
#, fuzzy
|
||||
msgctxt "#30015"
|
||||
msgid "Log timing data"
|
||||
msgstr "Logga tidsdata"
|
||||
|
||||
#, fuzzy
|
||||
msgctxt "#30010"
|
||||
msgid "Number of performance profiles to capture"
|
||||
msgstr "Antal prestandaprofiler som ska fångas"
|
||||
msgstr "Antal prestandaprofiler som ska räknas"
|
||||
|
||||
msgctxt "#30375"
|
||||
msgid "Receiving data packet"
|
||||
msgstr "Tar emot datapaket"
|
||||
|
||||
msgctxt "#30371"
|
||||
msgid "Could not connect to the URL you entered, do you want to try again?"
|
||||
msgstr ""
|
||||
"Det gick inte att ansluta till webbadressen du angav, vill du försöka igen?"
|
||||
|
||||
msgctxt "#30370"
|
||||
msgid "Do you want to manually enter a server url?"
|
||||
msgstr "Vill du ange en server-url manuellt?"
|
||||
|
||||
msgctxt "#30369"
|
||||
msgid "Do you want to clear your saved password?"
|
||||
msgstr "Vill du rensa ditt sparade lösenord?"
|
||||
|
||||
msgctxt "#30368"
|
||||
msgid "Clear Password?"
|
||||
msgstr "Rensa lösenord?"
|
||||
|
||||
msgctxt "#30366"
|
||||
msgid "Manually enter user details"
|
||||
msgstr "Ange användarinformation manuellt"
|
||||
|
||||
msgctxt "#30358"
|
||||
msgid "Retreiving remote image list"
|
||||
msgstr "Hämtar extern bildlista"
|
||||
|
||||
msgctxt "#30357"
|
||||
msgid "Processing existing image list"
|
||||
msgstr "Bearbetar den befintliga bildlistan"
|
||||
|
||||
msgctxt "#30356"
|
||||
msgid "Loading existing image list"
|
||||
msgstr "Laddar befintlig bildlista"
|
||||
|
||||
msgctxt "#30355"
|
||||
msgid "Kodi Settings->Services->Allow remote control via HTTP"
|
||||
msgstr "Kodi Inställningar->Tjänster->Tillåt fjärrstyrning via HTTP"
|
||||
|
||||
msgctxt "#30319"
|
||||
msgid "Music - All Album Artists"
|
||||
msgstr "Musik - Alla Albumartister"
|
||||
|
||||
msgctxt "#30352"
|
||||
msgid "Music - Frequently Played"
|
||||
msgstr "Musik - Ofta spelad"
|
||||
|
||||
msgctxt "#30347"
|
||||
msgid "Getting Existing Images"
|
||||
msgstr "Hämtar befintliga bilder"
|
||||
|
||||
msgctxt "#30344"
|
||||
msgid "Number of images removed from cache"
|
||||
msgstr "Mängden bilder borttagna från cache"
|
||||
|
||||
msgctxt "#30343"
|
||||
msgid "Changes Require Kodi Restart"
|
||||
msgstr "Ändringar kräver omstart av Kodi"
|
||||
|
||||
msgctxt "#30342"
|
||||
msgid "New content check interval (0 = disabled)"
|
||||
msgstr "Kontrollintervall för nytt innehåll (0 = inaktiverad)"
|
||||
|
||||
msgctxt "#30341"
|
||||
msgid "Background image update interval (0 = disabled)"
|
||||
msgstr "Uppdateringsintervall för bakgrundsbild (0 = inaktiverad)"
|
||||
|
||||
msgctxt "#30340"
|
||||
msgid "Group movies into collections"
|
||||
msgstr "Gruppera filmer i samlingar"
|
||||
|
||||
msgctxt "#30334"
|
||||
msgid "Use JellyCon context menu"
|
||||
msgstr "Använd JellyCons kontextmeny"
|
||||
|
||||
msgctxt "#30323"
|
||||
msgid "Artists"
|
||||
msgstr "Artister"
|
||||
|
||||
msgctxt "#30420"
|
||||
msgid "Audio max channels"
|
||||
msgstr "Antal kanaler för ljudsystem"
|
||||
|
||||
msgctxt "#30419"
|
||||
msgid "Audio codec"
|
||||
msgstr "Ljud codec"
|
||||
|
||||
msgctxt "#30418"
|
||||
msgid "Audio bitrate (Kbits)"
|
||||
msgstr "Ljud bitrate (Kbps)"
|
||||
|
||||
msgctxt "#30416"
|
||||
msgid "HTTP timeout seconds"
|
||||
msgstr "HTTP tidsutlösning i sekunder"
|
||||
|
||||
msgctxt "#30415"
|
||||
msgid " - Favorite Collections"
|
||||
msgstr "- Favorit Samlingar"
|
||||
|
||||
msgctxt "#30414"
|
||||
msgid " - Favorites"
|
||||
msgstr "- Favoriter"
|
||||
|
||||
msgctxt "#30409"
|
||||
msgid "Add-on Actions"
|
||||
msgstr "Extra functioner"
|
||||
|
||||
msgctxt "#30408"
|
||||
msgid "Custom Widgets"
|
||||
msgstr "Anpassade widgets"
|
||||
|
||||
msgctxt "#30407"
|
||||
msgid "Global Lists"
|
||||
msgstr "Globala Listor"
|
||||
|
||||
msgctxt "#30398"
|
||||
msgid "Refresh Jellyfin Metadata"
|
||||
msgstr "Uppdatera Jellyfin Metadata"
|
||||
|
||||
msgctxt "#30387"
|
||||
msgid "Unused images removed : "
|
||||
msgstr "Oanvända bilder raderade:"
|
||||
|
||||
msgctxt "#30376"
|
||||
msgid "Checking server url"
|
||||
msgstr "Kontrollerar server URL"
|
||||
|
||||
msgctxt "#30359"
|
||||
msgid "Building full image list"
|
||||
msgstr "Skapar fullständing bildmedia katalog"
|
||||
|
||||
msgctxt "#30345"
|
||||
msgid "Cache Jellyfin server data requests"
|
||||
msgstr "Cacha Jellyfin server data förfrågningar"
|
||||
|
||||
msgctxt "#30333"
|
||||
msgid "Cache artwork in the background"
|
||||
msgstr "Cacha bildmedia i bakgrunden"
|
||||
|
||||
msgctxt "#30444"
|
||||
msgid "Login using Quick Connect"
|
||||
msgstr "Logga in med \"Quick Connect\""
|
||||
|
||||
msgctxt "#30434"
|
||||
msgid "Force transcode stream bitrate (Kbits)"
|
||||
msgstr "manuell transcode stream bitrate (Kbps)"
|
||||
|
||||
msgctxt "#30436"
|
||||
msgid "Speed test data size (MB)"
|
||||
msgstr "hastighets test storlek (MB)"
|
||||
|
||||
msgctxt "#30438"
|
||||
msgid "Play cinema intros"
|
||||
msgstr "Spela upp intros"
|
||||
|
||||
msgctxt "#30439"
|
||||
msgid "Show play next episode at time left in seconds"
|
||||
msgstr "Visa nästa avsnitt några sekunder innan slutet"
|
||||
|
||||
msgctxt "#30442"
|
||||
msgid "Simple new content check"
|
||||
msgstr "Uppdatera content"
|
||||
|
||||
msgctxt "#30443"
|
||||
msgid "Quick Connect"
|
||||
msgstr "\"Quick Connect\""
|
||||
|
||||
msgctxt "#30445"
|
||||
msgid "Continue Watching"
|
||||
msgstr "Fortsätt se"
|
||||
|
||||
msgctxt "#30446"
|
||||
msgid "There was an error logging in"
|
||||
msgstr "Det var ett problem med att logga in"
|
||||
|
||||
msgctxt "#30367"
|
||||
msgid "Allow fast user switching password saving"
|
||||
msgstr "Acceptera spara en annan använderes lösenord snabbt"
|
||||
|
||||
msgctxt "#30378"
|
||||
msgid "Persist user details"
|
||||
msgstr "Behåll användarinformation"
|
||||
|
||||
msgctxt "#30379"
|
||||
msgid "External subtitle prompt"
|
||||
msgstr "Extern undertext prompt"
|
||||
|
||||
msgctxt "#30384"
|
||||
msgid "Random movies interval minutes (0 = disabled)"
|
||||
msgstr "Slumpmässiga filmer intervall minuter (0 = inaktiverad)"
|
||||
|
||||
msgctxt "#30385"
|
||||
msgid "Existing images before delete : "
|
||||
msgstr "Befintliga bilder före radering:"
|
||||
|
||||
msgctxt "#30400"
|
||||
msgid "Cache images interval minutes (0 = disabled)"
|
||||
msgstr "Cachebilder intervall minuter (0 = inaktiverad)"
|
||||
|
||||
msgctxt "#30423"
|
||||
msgid "NotSet"
|
||||
msgstr "Inte inställd"
|
||||
|
||||
msgctxt "#30435"
|
||||
msgid "Connection speed test"
|
||||
msgstr "hastighets test"
|
||||
|
||||
msgctxt "#30447"
|
||||
msgid "Max Play Queue Size"
|
||||
msgstr "Maximal köstorlek"
|
||||
|
||||
msgctxt "#30448"
|
||||
msgid "Shuffle"
|
||||
msgstr "Slumpa"
|
||||
|
||||
msgctxt "#30449"
|
||||
msgid "Instant Mix"
|
||||
msgstr "Direktmix"
|
||||
|
||||
msgctxt "#30225"
|
||||
msgid "Interface Mode"
|
||||
msgstr "Gränssnitts läge"
|
||||
|
||||
msgctxt "#30226"
|
||||
msgid "Default"
|
||||
msgstr "Standard"
|
||||
|
||||
msgctxt "#30227"
|
||||
msgid "Simple"
|
||||
msgstr "Enkel"
|
||||
|
||||
msgctxt "#30452"
|
||||
msgid "Combine instead of replace (might cause slow-down)"
|
||||
msgstr "Kombinera istället för att byta ut (kan orsaka fördröjningar)"
|
||||
|
||||
msgctxt "#30242"
|
||||
msgid "Force transcode av1"
|
||||
msgstr "Tvinga transkodning av1"
|
||||
|
||||
msgctxt "#30450"
|
||||
msgid "Next Up Rewatching"
|
||||
msgstr "Nästa På Titta Igen"
|
||||
|
||||
msgctxt "#30451"
|
||||
msgid "Rewatch Days (0 = Disabled)"
|
||||
msgstr "Titta Igen Dagar (0 = Avaktiverat)"
|
||||
|
||||
msgctxt "#30453"
|
||||
msgid "Hide number of items to show on entry title"
|
||||
msgstr "Göm antal objekt som visas på huvudmenyn"
|
||||
|
||||
msgctxt "#30454"
|
||||
msgid " - Totally Unwatched"
|
||||
msgstr " - Helt obevakad"
|
||||
|
||||
msgctxt "#30668"
|
||||
msgid "Start Offset (seconds)"
|
||||
msgstr "Inledande förskjutning (sekunder)"
|
||||
|
||||
msgctxt "#30669"
|
||||
msgid "End Offset (seconds)"
|
||||
msgstr "Avslutande förskjutning (sekunder)"
|
||||
|
||||
msgctxt "#30672"
|
||||
msgid "Skip"
|
||||
msgstr "Hoppa över"
|
||||
|
||||
msgctxt "#30673"
|
||||
msgid "Ask"
|
||||
msgstr "Fråga"
|
||||
|
||||
msgctxt "#30674"
|
||||
msgid "Do Nothing"
|
||||
msgstr "Gör ingenting"
|
||||
|
||||
msgctxt "#30667"
|
||||
msgid "Action to take"
|
||||
msgstr "Åtgärd"
|
||||
|
||||
msgctxt "#30666"
|
||||
msgid "Segment Skipper"
|
||||
msgstr "Segmenthoppare"
|
||||
|
||||
msgctxt "#30671"
|
||||
msgid "Credit Skipper"
|
||||
msgstr "Sluttextshoppare"
|
||||
|
||||
msgctxt "#30670"
|
||||
msgid "Intro Skipper"
|
||||
msgstr "Introhoppare"
|
||||
|
||||
msgctxt "#30675"
|
||||
msgid "Commercial Skipper"
|
||||
msgstr "Reklamhoppare"
|
||||
|
||||
msgctxt "#30676"
|
||||
msgid "Preview Skipper"
|
||||
msgstr "Förhandsgranskningshoppare"
|
||||
|
||||
msgctxt "#30677"
|
||||
msgid "Recap Skipper"
|
||||
msgstr "Sammanfattningshoppare"
|
||||
|
||||
1206
resources/language/resource.language.ta/strings.po
Normal file
1206
resources/language/resource.language.ta/strings.po
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,16 +1,16 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"PO-Revision-Date: 2022-07-07 17:22+0000\n"
|
||||
"Last-Translator: Fedir Smilianets <fedor.smile@gmail.com>\n"
|
||||
"PO-Revision-Date: 2025-12-15 22:55+0000\n"
|
||||
"Last-Translator: kscop-n1 <karpenko.serhii@outlook.com>\n"
|
||||
"Language-Team: Ukrainian <https://translate.jellyfin.org/projects/jellycon/"
|
||||
"jellycon/uk/>\n"
|
||||
"Language: uk\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
|
||||
"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
|
||||
"X-Generator: Weblate 4.10.1\n"
|
||||
"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
|
||||
"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
|
||||
"X-Generator: Weblate 5.14\n"
|
||||
|
||||
msgctxt "#30434"
|
||||
msgid "Force transcode stream bitrate (Kbits)"
|
||||
@@ -46,7 +46,7 @@ msgstr "Увійти використовуючи Quick Connect"
|
||||
|
||||
msgctxt "#30443"
|
||||
msgid "Quick Connect"
|
||||
msgstr "Quick Connect"
|
||||
msgstr "Швидке підключення"
|
||||
|
||||
msgctxt "#30442"
|
||||
msgid "Simple new content check"
|
||||
@@ -138,7 +138,7 @@ msgstr "Максимум каналів аудіо"
|
||||
|
||||
msgctxt "#30419"
|
||||
msgid "Audio codec"
|
||||
msgstr "Кодек аудіо"
|
||||
msgstr "Аудіокодек"
|
||||
|
||||
msgctxt "#30418"
|
||||
msgid "Audio bitrate (Kbits)"
|
||||
@@ -600,7 +600,7 @@ msgstr "Кешувати всі зображення Jellyfin як локаль
|
||||
|
||||
msgctxt "#30299"
|
||||
msgid "Cache Images"
|
||||
msgstr "Кешувати зображення"
|
||||
msgstr "Кешувати Зображення"
|
||||
|
||||
msgctxt "#30298"
|
||||
msgid "Deleting Kodi Images"
|
||||
@@ -1100,3 +1100,131 @@ msgstr "Порт"
|
||||
msgctxt "#30000"
|
||||
msgid "Host"
|
||||
msgstr "Хост"
|
||||
|
||||
msgctxt "#30445"
|
||||
msgid "Continue Watching"
|
||||
msgstr "Продовжити перегляд"
|
||||
|
||||
msgctxt "#30439"
|
||||
msgid "Show play next episode at time left in seconds"
|
||||
msgstr "За скільки секунд до кінця пропонувати перегляд наступного епізоду"
|
||||
|
||||
msgctxt "#30446"
|
||||
msgid "There was an error logging in"
|
||||
msgstr "Виникла помилка під час входу"
|
||||
|
||||
msgctxt "#30447"
|
||||
msgid "Max Play Queue Size"
|
||||
msgstr "Максимальний розмір черги відтворення"
|
||||
|
||||
msgctxt "#30448"
|
||||
msgid "Shuffle"
|
||||
msgstr "Перемішати"
|
||||
|
||||
msgctxt "#30449"
|
||||
msgid "Instant Mix"
|
||||
msgstr "Миттєвий мікс"
|
||||
|
||||
msgctxt "#30225"
|
||||
msgid "Interface Mode"
|
||||
msgstr "Режим інтерфейсу"
|
||||
|
||||
msgctxt "#30226"
|
||||
msgid "Default"
|
||||
msgstr "За замовчуванням"
|
||||
|
||||
msgctxt "#30227"
|
||||
msgid "Simple"
|
||||
msgstr "Простий"
|
||||
|
||||
msgctxt "#30242"
|
||||
msgid "Force transcode av1"
|
||||
msgstr "Примусово перекодовувати av1"
|
||||
|
||||
msgctxt "#30452"
|
||||
msgid "Combine instead of replace (might cause slow-down)"
|
||||
msgstr "Об'єднати замість заміни (може спричинити уповільнення)"
|
||||
|
||||
msgctxt "#30450"
|
||||
msgid "Next Up Rewatching"
|
||||
msgstr "Далі Повторний перегляд"
|
||||
|
||||
msgctxt "#30451"
|
||||
msgid "Rewatch Days (0 = Disabled)"
|
||||
msgstr "Повторний перегляд днів (0 = вимкнено)"
|
||||
|
||||
msgctxt "#30453"
|
||||
msgid "Hide number of items to show on entry title"
|
||||
msgstr "Приховати кількість елементів для показу в заголовку запису"
|
||||
|
||||
msgctxt "#30454"
|
||||
msgid " - Totally Unwatched"
|
||||
msgstr " - Цілком Непереглянуто"
|
||||
|
||||
msgctxt "#30666"
|
||||
msgid "Segment Skipper"
|
||||
msgstr "Пропуск Сегмента"
|
||||
|
||||
msgctxt "#30667"
|
||||
msgid "Action to take"
|
||||
msgstr "Дії які потрібно зробити"
|
||||
|
||||
msgctxt "#30668"
|
||||
msgid "Start Offset (seconds)"
|
||||
msgstr "Початковий зсув (секунди)"
|
||||
|
||||
msgctxt "#30669"
|
||||
msgid "End Offset (seconds)"
|
||||
msgstr "Кінцевий зсув (секунди)"
|
||||
|
||||
msgctxt "#30670"
|
||||
msgid "Intro Skipper"
|
||||
msgstr "Пропуск Вступу"
|
||||
|
||||
msgctxt "#30671"
|
||||
msgid "Credit Skipper"
|
||||
msgstr "Пропуск титрів"
|
||||
|
||||
msgctxt "#30672"
|
||||
msgid "Skip"
|
||||
msgstr "Пропустити"
|
||||
|
||||
msgctxt "#30673"
|
||||
msgid "Ask"
|
||||
msgstr "Запитати"
|
||||
|
||||
msgctxt "#30674"
|
||||
msgid "Do Nothing"
|
||||
msgstr "Нічого не робити"
|
||||
|
||||
msgctxt "#30675"
|
||||
msgid "Commercial Skipper"
|
||||
msgstr "Пропуск реклами"
|
||||
|
||||
msgctxt "#30676"
|
||||
msgid "Preview Skipper"
|
||||
msgstr "Пропуск превʼю"
|
||||
|
||||
msgctxt "#30677"
|
||||
msgid "Recap Skipper"
|
||||
msgstr "Пропустити нагадування"
|
||||
|
||||
msgctxt "#30678"
|
||||
msgid "TV Shows per page"
|
||||
msgstr "TV шоу на сторінці"
|
||||
|
||||
msgctxt "#30455"
|
||||
msgid "TV Shows - Random"
|
||||
msgstr "ТV шоу - Випадкове"
|
||||
|
||||
msgctxt "#30456"
|
||||
msgid "All - Random"
|
||||
msgstr "Все - Випадково"
|
||||
|
||||
msgctxt "#30457"
|
||||
msgid "All - Recently Added"
|
||||
msgstr "Все - Нещодавно додані"
|
||||
|
||||
msgctxt "#30458"
|
||||
msgid "All - Favorites"
|
||||
msgstr "Все - Улюблене"
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"PO-Revision-Date: 2022-06-20 16:22+0000\n"
|
||||
"Last-Translator: wolong gl <wolong98@gmail.com>\n"
|
||||
"Language-Team: Chinese (Simplified) <https://translate.jellyfin.org/projects/"
|
||||
"jellycon/jellycon/zh_Hans/>\n"
|
||||
"PO-Revision-Date: 2025-12-15 22:55+0000\n"
|
||||
"Last-Translator: 無情天 <kofzhanganguo@126.com>\n"
|
||||
"Language-Team: Chinese (Simplified Han script) <https://"
|
||||
"translate.jellyfin.org/projects/jellycon/jellycon/zh_Hans/>\n"
|
||||
"Language: zh_Hans\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=1; plural=0;\n"
|
||||
"X-Generator: Weblate 4.10.1\n"
|
||||
"X-Generator: Weblate 5.14\n"
|
||||
|
||||
msgctxt "#30442"
|
||||
msgid "Simple new content check"
|
||||
@@ -1094,3 +1094,131 @@ msgstr "Quick Connect"
|
||||
msgctxt "#30323"
|
||||
msgid "Artists"
|
||||
msgstr "艺术家"
|
||||
|
||||
msgctxt "#30445"
|
||||
msgid "Continue Watching"
|
||||
msgstr "继续观看"
|
||||
|
||||
msgctxt "#30439"
|
||||
msgid "Show play next episode at time left in seconds"
|
||||
msgstr "显示播放下一集的剩余时间(s)"
|
||||
|
||||
msgctxt "#30446"
|
||||
msgid "There was an error logging in"
|
||||
msgstr "登录时出错"
|
||||
|
||||
msgctxt "#30448"
|
||||
msgid "Shuffle"
|
||||
msgstr "随机"
|
||||
|
||||
msgctxt "#30449"
|
||||
msgid "Instant Mix"
|
||||
msgstr "速成合辑"
|
||||
|
||||
msgctxt "#30447"
|
||||
msgid "Max Play Queue Size"
|
||||
msgstr "最大播放队列数"
|
||||
|
||||
msgctxt "#30225"
|
||||
msgid "Interface Mode"
|
||||
msgstr "接口模式"
|
||||
|
||||
msgctxt "#30226"
|
||||
msgid "Default"
|
||||
msgstr "默认值"
|
||||
|
||||
msgctxt "#30227"
|
||||
msgid "Simple"
|
||||
msgstr "简单"
|
||||
|
||||
msgctxt "#30242"
|
||||
msgid "Force transcode av1"
|
||||
msgstr "强制转码为 AV1 格式"
|
||||
|
||||
msgctxt "#30452"
|
||||
msgid "Combine instead of replace (might cause slow-down)"
|
||||
msgstr "合并而非替换(可能会导致速度减慢)"
|
||||
|
||||
msgctxt "#30451"
|
||||
msgid "Rewatch Days (0 = Disabled)"
|
||||
msgstr "重看天数(0=已禁用)"
|
||||
|
||||
msgctxt "#30450"
|
||||
msgid "Next Up Rewatching"
|
||||
msgstr "下一个重看"
|
||||
|
||||
msgctxt "#30453"
|
||||
msgid "Hide number of items to show on entry title"
|
||||
msgstr "隐藏条目标题上显示的项目数"
|
||||
|
||||
msgctxt "#30454"
|
||||
msgid " - Totally Unwatched"
|
||||
msgstr " - 完全未观看"
|
||||
|
||||
msgctxt "#30672"
|
||||
msgid "Skip"
|
||||
msgstr "跳过"
|
||||
|
||||
msgctxt "#30666"
|
||||
msgid "Segment Skipper"
|
||||
msgstr "分段跳过"
|
||||
|
||||
msgctxt "#30667"
|
||||
msgid "Action to take"
|
||||
msgstr "采取的行动"
|
||||
|
||||
msgctxt "#30668"
|
||||
msgid "Start Offset (seconds)"
|
||||
msgstr "起始偏移(秒)"
|
||||
|
||||
msgctxt "#30669"
|
||||
msgid "End Offset (seconds)"
|
||||
msgstr "结束偏移(秒)"
|
||||
|
||||
msgctxt "#30670"
|
||||
msgid "Intro Skipper"
|
||||
msgstr "简介跳过"
|
||||
|
||||
msgctxt "#30671"
|
||||
msgid "Credit Skipper"
|
||||
msgstr "片头跳过"
|
||||
|
||||
msgctxt "#30673"
|
||||
msgid "Ask"
|
||||
msgstr "询问"
|
||||
|
||||
msgctxt "#30674"
|
||||
msgid "Do Nothing"
|
||||
msgstr "无动作"
|
||||
|
||||
msgctxt "#30675"
|
||||
msgid "Commercial Skipper"
|
||||
msgstr "广告跳过"
|
||||
|
||||
msgctxt "#30677"
|
||||
msgid "Recap Skipper"
|
||||
msgstr "回顾跳过"
|
||||
|
||||
msgctxt "#30676"
|
||||
msgid "Preview Skipper"
|
||||
msgstr "预告跳过"
|
||||
|
||||
msgctxt "#30455"
|
||||
msgid "TV Shows - Random"
|
||||
msgstr "电视节目 - 随机"
|
||||
|
||||
msgctxt "#30456"
|
||||
msgid "All - Random"
|
||||
msgstr "全部 - 随机"
|
||||
|
||||
msgctxt "#30457"
|
||||
msgid "All - Recently Added"
|
||||
msgstr "全部 - 最近添加"
|
||||
|
||||
msgctxt "#30458"
|
||||
msgid "All - Favorites"
|
||||
msgstr "全部 - 收藏夹"
|
||||
|
||||
msgctxt "#30678"
|
||||
msgid "TV Shows per page"
|
||||
msgstr "每页显示的电视节目数量"
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,6 @@
|
||||
# Gnu General Public License - see LICENSE.TXT
|
||||
from __future__ import division, absolute_import, print_function, unicode_literals
|
||||
from __future__ import (
|
||||
division, absolute_import, print_function, unicode_literals
|
||||
)
|
||||
|
||||
import time
|
||||
import threading
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
# coding=utf-8
|
||||
# Gnu General Public License - see LICENSE.TXT
|
||||
from __future__ import division, absolute_import, print_function, unicode_literals
|
||||
from __future__ import (
|
||||
division, absolute_import, print_function, unicode_literals
|
||||
)
|
||||
|
||||
from six.moves.urllib.parse import unquote
|
||||
import requests
|
||||
import base64
|
||||
import sys
|
||||
import threading
|
||||
@@ -13,6 +11,8 @@ import xbmcgui
|
||||
import xbmcplugin
|
||||
import xbmc
|
||||
import xbmcaddon
|
||||
import requests
|
||||
from six.moves.urllib.parse import unquote
|
||||
|
||||
from .jellyfin import api
|
||||
from .lazylogger import LazyLogger
|
||||
@@ -41,6 +41,13 @@ class CacheArtwork(threading.Thread):
|
||||
last_update = 0
|
||||
home_window = HomeWindow()
|
||||
settings = xbmcaddon.Addon()
|
||||
|
||||
# Check if disk caching is disabled
|
||||
disable_disk_cache = settings.getSetting('disable_disk_cache') == 'true'
|
||||
if disable_disk_cache:
|
||||
log.debug("CacheArtwork : Disk caching disabled, artwork caching skipped")
|
||||
return
|
||||
|
||||
latest_content_hash = "never"
|
||||
check_interval = int(settings.getSetting('cacheImagesOnScreenSaver_interval'))
|
||||
check_interval = check_interval * 60
|
||||
@@ -208,7 +215,7 @@ class CacheArtwork(threading.Thread):
|
||||
dp.close()
|
||||
del dp
|
||||
if result_text is not None:
|
||||
log.debug("Cache Images reuslt : {0}".format(" - ".join(result_text)))
|
||||
log.debug("Cache Images result : {0}".format(" - ".join(result_text)))
|
||||
|
||||
def get_jellyfin_artwork(self, progress):
|
||||
log.debug("get_jellyfin_artwork")
|
||||
|
||||
@@ -1,10 +1,16 @@
|
||||
# Gnu General Public License - see LICENSE.TXT
|
||||
from __future__ import division, absolute_import, print_function, unicode_literals
|
||||
from __future__ import (
|
||||
division, absolute_import, print_function, unicode_literals
|
||||
)
|
||||
|
||||
import threading
|
||||
import hashlib
|
||||
import os
|
||||
import time
|
||||
|
||||
import xbmc
|
||||
import xbmcaddon
|
||||
import xbmcvfs
|
||||
import xbmcgui
|
||||
from six.moves import cPickle
|
||||
|
||||
from .jellyfin import api
|
||||
@@ -15,11 +21,6 @@ from .tracking import timer
|
||||
from .filelock import FileLock
|
||||
from .utils import translate_string, load_user_details, translate_path
|
||||
|
||||
import xbmc
|
||||
import xbmcaddon
|
||||
import xbmcvfs
|
||||
import xbmcgui
|
||||
|
||||
log = LazyLogger(__name__)
|
||||
|
||||
|
||||
@@ -53,6 +54,13 @@ class DataManager:
|
||||
log.debug("last_content_url : use_cache={0} url={1}".format(use_cache, url))
|
||||
home_window.set_property("last_content_url", url)
|
||||
|
||||
# Check if disk caching is disabled
|
||||
settings = xbmcaddon.Addon()
|
||||
disable_disk_cache = settings.getSetting('disable_disk_cache') == 'true'
|
||||
if disable_disk_cache:
|
||||
use_cache = False
|
||||
log.debug("Disk caching disabled - data will be kept in RAM only")
|
||||
|
||||
user_id = self.user_details.get('user_id')
|
||||
server = self.api.server
|
||||
|
||||
@@ -163,6 +171,13 @@ class CacheManagerThread(threading.Thread):
|
||||
log.debug("CacheManagerThread : Started")
|
||||
|
||||
home_window = HomeWindow()
|
||||
settings = xbmcaddon.Addon()
|
||||
disable_disk_cache = settings.getSetting('disable_disk_cache') == 'true'
|
||||
|
||||
if disable_disk_cache:
|
||||
log.debug("CacheManagerThread : Disk caching disabled, skipping cache operations")
|
||||
return
|
||||
|
||||
is_fresh = False
|
||||
|
||||
# if the data is fresh then just save it
|
||||
@@ -259,7 +274,7 @@ def clear_cached_server_data():
|
||||
del_count = 0
|
||||
for filename in files:
|
||||
if filename.startswith("cache_") and filename.endswith(".pickle"):
|
||||
log.debug("Deleteing CacheFile: {0}".format(filename))
|
||||
log.debug("Deleting CacheFile: {0}".format(filename))
|
||||
xbmcvfs.delete(os.path.join(addon_dir, filename))
|
||||
del_count += 1
|
||||
|
||||
|
||||
@@ -1,9 +1,13 @@
|
||||
from __future__ import division, absolute_import, print_function, unicode_literals
|
||||
from __future__ import (
|
||||
division, absolute_import, print_function, unicode_literals
|
||||
)
|
||||
|
||||
import xbmcgui
|
||||
import xbmc
|
||||
|
||||
|
||||
from .lazylogger import LazyLogger
|
||||
from .utils import translate_string, send_event_notification
|
||||
from .utils import seconds_to_ticks, ticks_to_seconds, translate_string, send_event_notification
|
||||
|
||||
log = LazyLogger(__name__)
|
||||
|
||||
@@ -205,42 +209,56 @@ class PlayNextDialog(xbmcgui.WindowXMLDialog):
|
||||
def get_play_called(self):
|
||||
return self.play_called
|
||||
|
||||
class SkipDialog(xbmcgui.WindowXMLDialog):
|
||||
|
||||
class QuickConnectDialog(xbmcgui.WindowXMLDialog):
|
||||
connect_method = -1
|
||||
action_exitkeys_id = None
|
||||
media_id = None
|
||||
start = None
|
||||
end = None
|
||||
|
||||
has_been_dissmissed = False
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
xbmcgui.WindowXMLDialog.__init__(self, *args, **kwargs)
|
||||
log.debug("QuickConnectDialog INITIALISED")
|
||||
|
||||
self.code = ''
|
||||
log.debug("SkipDialog: __init__")
|
||||
xbmcgui.WindowXML.__init__(self, *args, **kwargs)
|
||||
|
||||
def onInit(self):
|
||||
log.debug("SkipDialog: onInit")
|
||||
self.action_exitkeys_id = [10, 13]
|
||||
|
||||
message_control = self.getControl(3)
|
||||
message_control.setText(self.code)
|
||||
|
||||
message_control = self.getControl(4)
|
||||
message_control.setLabel(translate_string(30443))
|
||||
|
||||
self.getControl(3010).setLabel(translate_string(30444))
|
||||
self.getControl(3011).setLabel(translate_string(30365))
|
||||
|
||||
def onFocus(self, controlId):
|
||||
def onFocus(self, control_id):
|
||||
pass
|
||||
|
||||
def doAction(self, actionID):
|
||||
def doAction(self, action_id):
|
||||
pass
|
||||
|
||||
def onClick(self, controlID):
|
||||
def onMessage(self, message):
|
||||
log.debug("SkipDialog: onMessage: {0}".format(message))
|
||||
|
||||
if controlID == 3010:
|
||||
self.connect_method = 1
|
||||
self.close()
|
||||
if controlID == 3011:
|
||||
self.connect_method = 0
|
||||
def onAction(self, action):
|
||||
log.debug("SkipDialog: onAction: {0}".format(action.getId()))
|
||||
if action.getId() == 10 or action.getId() == 92: # ACTION_PREVIOUS_MENU & ACTION_NAV_BACK
|
||||
log.debug("SkipDialog: dismissing dialog so it does not open again")
|
||||
self.has_been_dissmissed = True
|
||||
self.close()
|
||||
|
||||
def getConnectMethod(self):
|
||||
return self.connect_method
|
||||
def onClick(self, control_id):
|
||||
log.debug("SkipDialog: onClick: {0}".format(control_id))
|
||||
player = xbmc.Player()
|
||||
current_ticks = seconds_to_ticks(player.getTime())
|
||||
if self.start is not None and self.end is not None and current_ticks >= self.start and current_ticks <= self.end:
|
||||
log.debug("SkipDialog: skipping segment because current ticks ({0}) is in range".format(current_ticks))
|
||||
# If click during segment, skip it
|
||||
player.seekTime(ticks_to_seconds(self.end))
|
||||
|
||||
self.close()
|
||||
|
||||
def get_play_called(self):
|
||||
return self.play_called
|
||||
|
||||
def is_button_shown(self):
|
||||
try:
|
||||
self.getFocus()
|
||||
return True
|
||||
except Exception:
|
||||
return False
|
||||
|
||||
@@ -1,19 +1,23 @@
|
||||
# Gnu General Public License - see LICENSE.TXT
|
||||
from __future__ import division, absolute_import, print_function, unicode_literals
|
||||
from __future__ import (
|
||||
division, absolute_import, print_function, unicode_literals
|
||||
)
|
||||
|
||||
import sys
|
||||
import re
|
||||
|
||||
import xbmcaddon
|
||||
import xbmcplugin
|
||||
import xbmcgui
|
||||
|
||||
from six.moves.urllib.parse import quote, unquote
|
||||
import sys
|
||||
import re
|
||||
from six.moves.urllib.parse import quote, unquote, parse_qsl
|
||||
|
||||
from .datamanager import DataManager
|
||||
from .lazylogger import LazyLogger
|
||||
from .item_functions import add_gui_item, ItemDetails
|
||||
from .utils import send_event_notification, translate_string, load_user_details, get_default_filters
|
||||
from .tracking import timer
|
||||
from .utils import (
|
||||
send_event_notification, translate_string,
|
||||
load_user_details, get_default_filters
|
||||
)
|
||||
|
||||
log = LazyLogger(__name__)
|
||||
|
||||
@@ -36,6 +40,7 @@ def get_content(url, params):
|
||||
view_type = ""
|
||||
content_type = ""
|
||||
media_type = str(media_type).lower().strip()
|
||||
url_params = dict(parse_qsl(url))
|
||||
if media_type.startswith("movie"):
|
||||
view_type = "Movies"
|
||||
content_type = 'movies'
|
||||
@@ -68,6 +73,11 @@ def get_content(url, params):
|
||||
content_type = 'episodes'
|
||||
elif media_type == "playlists":
|
||||
view_type = "Playlists"
|
||||
elif media_type == "musicvideos":
|
||||
view_type = "Music Videos"
|
||||
content_type = 'musicvideos'
|
||||
elif media_type == "mixed":
|
||||
content_type = 'videos'
|
||||
|
||||
log.debug("media_type:{0} content_type:{1} view_type:{2} ".format(media_type, content_type, view_type))
|
||||
|
||||
@@ -79,29 +89,46 @@ def get_content(url, params):
|
||||
progress.update(0, translate_string(30113))
|
||||
|
||||
# update url for paging
|
||||
start_index = 0
|
||||
page_limit = int(settings.getSetting('moviePageSize'))
|
||||
start_index = int(url_params.get("StartIndex", 0))
|
||||
url_limit = url_params.get("Limit")
|
||||
movie_page_limit = int(settings.getSetting('moviePageSize'))
|
||||
show_page_limit = int(settings.getSetting('showPageSize'))
|
||||
url_prev = None
|
||||
url_next = None
|
||||
if page_limit > 0 and media_type.startswith("movie"):
|
||||
m = re.search('StartIndex=([0-9]{1,4})', url)
|
||||
if m and m.group(1):
|
||||
if not url_limit or start_index > 0:
|
||||
if movie_page_limit > 0 and media_type.startswith("movie"):
|
||||
log.debug("UPDATING NEXT URL: {0}".format(url))
|
||||
start_index = int(m.group(1))
|
||||
log.debug("current_start : {0}".format(start_index))
|
||||
if start_index > 0:
|
||||
prev_index = start_index - page_limit
|
||||
prev_index = start_index - movie_page_limit
|
||||
if prev_index < 0:
|
||||
prev_index = 0
|
||||
url_prev = re.sub('StartIndex=([0-9]{1,4})', 'StartIndex=' + str(prev_index), url)
|
||||
url_next = re.sub('StartIndex=([0-9]{1,4})', 'StartIndex=' + str(start_index + page_limit), url)
|
||||
log.debug("UPDATING NEXT URL: {0}".format(url_next))
|
||||
url_next = re.sub('StartIndex=([0-9]{1,4})', 'StartIndex=' + str(start_index + movie_page_limit), url)
|
||||
log.debug("UPDATING NEXT URL: {0}".format(url_next))
|
||||
|
||||
else:
|
||||
log.debug("ADDING NEXT URL: {0}".format(url))
|
||||
url_next = url + "&StartIndex=" + str(start_index + page_limit) + "&Limit=" + str(page_limit)
|
||||
url = url + "&StartIndex=" + str(start_index) + "&Limit=" + str(page_limit)
|
||||
log.debug("ADDING NEXT URL: {0}".format(url_next))
|
||||
else:
|
||||
log.debug("ADDING NEXT URL: {0}".format(url))
|
||||
url_next = url + "&StartIndex=" + str(start_index + movie_page_limit) + "&Limit=" + str(movie_page_limit)
|
||||
url = url + "&StartIndex=" + str(start_index) + "&Limit=" + str(movie_page_limit)
|
||||
log.debug("ADDING NEXT URL: {0}".format(url_next))
|
||||
|
||||
if show_page_limit > 0 and media_type.startswith("tvshow"):
|
||||
log.debug("UPDATING NEXT URL: {0}".format(url))
|
||||
log.debug("current_start : {0}".format(start_index))
|
||||
if start_index > 0:
|
||||
prev_index = start_index - show_page_limit
|
||||
if prev_index < 0:
|
||||
prev_index = 0
|
||||
url_prev = re.sub('StartIndex=([0-9]{1,4})', 'StartIndex=' + str(prev_index), url)
|
||||
url_next = re.sub('StartIndex=([0-9]{1,4})', 'StartIndex=' + str(start_index + show_page_limit), url)
|
||||
log.debug("UPDATING NEXT URL: {0}".format(url_next))
|
||||
|
||||
else:
|
||||
log.debug("ADDING NEXT URL: {0}".format(url))
|
||||
url_next = url + "&StartIndex=" + str(start_index + show_page_limit) + "&Limit=" + str(show_page_limit)
|
||||
url = url + "&StartIndex=" + str(start_index) + "&Limit=" + str(show_page_limit)
|
||||
log.debug("ADDING NEXT URL: {0}".format(url_next))
|
||||
|
||||
use_cache = params.get("use_cache", "true") == "true"
|
||||
|
||||
@@ -111,24 +138,43 @@ def get_content(url, params):
|
||||
|
||||
log.debug("total_records: {0}".format(total_records))
|
||||
|
||||
# add paging items
|
||||
if page_limit > 0 and media_type.startswith("movie"):
|
||||
if url_prev:
|
||||
list_item = xbmcgui.ListItem("Prev Page (" + str(start_index - page_limit + 1) + "-" + str(start_index) +
|
||||
" of " + str(total_records) + ")")
|
||||
u = sys.argv[0] + "?url=" + quote(url_prev) + "&mode=GET_CONTENT&media_type=movies"
|
||||
log.debug("ADDING PREV ListItem: {0} - {1}".format(u, list_item))
|
||||
dir_items.insert(0, (u, list_item, True))
|
||||
if not url_limit or start_index > 0:
|
||||
# add paging items
|
||||
if movie_page_limit > 0 and media_type.startswith("movie"):
|
||||
if url_prev:
|
||||
list_item = xbmcgui.ListItem("Prev Page (" + str(start_index - movie_page_limit + 1) + "-" + str(start_index) +
|
||||
" of " + str(total_records) + ")")
|
||||
u = sys.argv[0] + "?url=" + quote(url_prev) + "&mode=GET_CONTENT&media_type=movies"
|
||||
log.debug("ADDING PREV ListItem: {0} - {1}".format(u, list_item))
|
||||
dir_items.insert(0, (u, list_item, True))
|
||||
|
||||
if start_index + page_limit < total_records:
|
||||
upper_count = start_index + (page_limit * 2)
|
||||
if upper_count > total_records:
|
||||
upper_count = total_records
|
||||
list_item = xbmcgui.ListItem("Next Page (" + str(start_index + page_limit + 1) + "-" +
|
||||
str(upper_count) + " of " + str(total_records) + ")")
|
||||
u = sys.argv[0] + "?url=" + quote(url_next) + "&mode=GET_CONTENT&media_type=movies"
|
||||
log.debug("ADDING NEXT ListItem: {0} - {1}".format(u, list_item))
|
||||
dir_items.append((u, list_item, True))
|
||||
if start_index + movie_page_limit < total_records:
|
||||
upper_count = start_index + (movie_page_limit * 2)
|
||||
if upper_count > total_records:
|
||||
upper_count = total_records
|
||||
list_item = xbmcgui.ListItem("Next Page (" + str(start_index + movie_page_limit + 1) + "-" +
|
||||
str(upper_count) + " of " + str(total_records) + ")")
|
||||
u = sys.argv[0] + "?url=" + quote(url_next) + "&mode=GET_CONTENT&media_type=movies"
|
||||
log.debug("ADDING NEXT ListItem: {0} - {1}".format(u, list_item))
|
||||
dir_items.append((u, list_item, True))
|
||||
# add paging items
|
||||
if show_page_limit > 0 and media_type.startswith("tvshow"):
|
||||
if url_prev:
|
||||
list_item = xbmcgui.ListItem("Prev Page (" + str(start_index - show_page_limit + 1) + "-" + str(start_index) +
|
||||
" of " + str(total_records) + ")")
|
||||
u = sys.argv[0] + "?url=" + quote(url_prev) + "&mode=GET_CONTENT&media_type=tvshows"
|
||||
log.debug("ADDING PREV ListItem: {0} - {1}".format(u, list_item))
|
||||
dir_items.insert(0, (u, list_item, True))
|
||||
|
||||
if start_index + show_page_limit < total_records:
|
||||
upper_count = start_index + (show_page_limit * 2)
|
||||
if upper_count > total_records:
|
||||
upper_count = total_records
|
||||
list_item = xbmcgui.ListItem("Next Page (" + str(start_index + show_page_limit + 1) + "-" +
|
||||
str(upper_count) + " of " + str(total_records) + ")")
|
||||
u = sys.argv[0] + "?url=" + quote(url_next) + "&mode=GET_CONTENT&media_type=tvshows"
|
||||
log.debug("ADDING NEXT ListItem: {0} - {1}".format(u, list_item))
|
||||
dir_items.append((u, list_item, True))
|
||||
|
||||
# set the Kodi content type
|
||||
if content_type:
|
||||
@@ -145,7 +191,9 @@ def get_content(url, params):
|
||||
xbmcplugin.setContent(pluginhandle, content_type)
|
||||
|
||||
# set the sort items
|
||||
if page_limit > 0 and media_type.startswith("movie"):
|
||||
if movie_page_limit > 0 and media_type.startswith("movie"):
|
||||
xbmcplugin.addSortMethod(pluginhandle, xbmcplugin.SORT_METHOD_UNSORTED)
|
||||
elif show_page_limit > 0 and media_type.startswith("tvshow"):
|
||||
xbmcplugin.addSortMethod(pluginhandle, xbmcplugin.SORT_METHOD_UNSORTED)
|
||||
else:
|
||||
set_sort(pluginhandle, view_type, default_sort)
|
||||
@@ -244,14 +292,17 @@ def process_directory(url, progress, params, use_cache_data=False):
|
||||
# Fix skin shortcuts from pre-0.5.0
|
||||
item_limit = int(settings.getSetting("show_x_filtered_items"))
|
||||
url = url.replace('{server}', '')
|
||||
url = url.replace('{userid}', user_id)
|
||||
url = url.replace('{field_filters}', default_filters)
|
||||
url = url.replace('{ItemLimit}', str(item_limit))
|
||||
|
||||
# Need to replace at runtime so it always pulls the current user
|
||||
url = unquote(url)
|
||||
url = url.replace('{userid}', user_id)
|
||||
|
||||
cache_file, item_list, total_records, cache_thread = data_manager.get_items(url, gui_options, use_cache)
|
||||
|
||||
# flatten single season
|
||||
# if there is only one result and it is a season and you have flatten signle season turned on then
|
||||
# if there is only one result and it is a season and you have flatten single season turned on then
|
||||
# build a new url, set the content media type and call get content again
|
||||
flatten_single_season = settings.getSetting("flatten_single_season") == "true"
|
||||
if flatten_single_season and len(item_list) == 1 and item_list[0].item_type == "Season":
|
||||
@@ -259,7 +310,7 @@ def process_directory(url, progress, params, use_cache_data=False):
|
||||
series_id = item_list[0].series_id
|
||||
season_url = ('/Shows/' + series_id +
|
||||
'/Episodes'
|
||||
'?userId={}'.format(user_id) +
|
||||
'?userId={userid}' +
|
||||
'&seasonId=' + season_id +
|
||||
'&IsVirtualUnAired=false' +
|
||||
'&IsMissing=false' +
|
||||
@@ -290,9 +341,10 @@ def process_directory(url, progress, params, use_cache_data=False):
|
||||
|
||||
detected_type = None
|
||||
dir_items = []
|
||||
|
||||
OnlyTotallyUnwatchedTvShow = params.get("OnlyTotallyUnwatchedTvShow", None)
|
||||
for item_details in item_list:
|
||||
|
||||
if OnlyTotallyUnwatchedTvShow == "1" and item_details.watched_episodes > 0:
|
||||
continue
|
||||
item_details.total_items = item_count
|
||||
|
||||
if progress is not None:
|
||||
@@ -324,14 +376,16 @@ def process_directory(url, progress, params, use_cache_data=False):
|
||||
if item_details.item_type == "Series":
|
||||
u = ('/Shows/' + item_details.id +
|
||||
'/Seasons'
|
||||
'?userId={}'.format(user_id) +
|
||||
'?userId={userid}' +
|
||||
'&Fields={}'.format(default_filters) +
|
||||
'&format=json')
|
||||
if not show_empty_folders:
|
||||
u = u + '&isMissing=False'
|
||||
|
||||
elif item_details.item_type == "Season":
|
||||
u = ('/Shows/' + item_details.series_id +
|
||||
'/Episodes'
|
||||
'?userId={}'.format(user_id) +
|
||||
'?userId={userid}' +
|
||||
'&seasonId=' + item_details.id +
|
||||
'&IsVirtualUnAired=false' +
|
||||
'&IsMissing=false' +
|
||||
@@ -339,7 +393,7 @@ def process_directory(url, progress, params, use_cache_data=False):
|
||||
'&format=json')
|
||||
|
||||
else:
|
||||
u = ('/Users/{}/items'.format(user_id) +
|
||||
u = ('/Users/{userid}/items' +
|
||||
'?ParentId=' + item_details.id +
|
||||
'&IsVirtualUnAired=false' +
|
||||
'&IsMissing=false' +
|
||||
@@ -356,7 +410,7 @@ def process_directory(url, progress, params, use_cache_data=False):
|
||||
log.debug("Dropping empty folder item : {0}".format(item_details.__dict__))
|
||||
|
||||
elif item_details.item_type == "MusicArtist":
|
||||
u = ('/Users/{}/items'.format(user_id) +
|
||||
u = ('/Users/{userid}/items' +
|
||||
'?ArtistIds=' + item_details.id +
|
||||
'&IncludeItemTypes=MusicAlbum' +
|
||||
'&CollapseBoxSetItems=false' +
|
||||
@@ -380,7 +434,7 @@ def process_directory(url, progress, params, use_cache_data=False):
|
||||
and first_season_item.series_id is not None):
|
||||
series_url = ('/Shows/' + first_season_item.series_id +
|
||||
'/Episodes'
|
||||
'?userId={}'.format(user_id) +
|
||||
'?userId={userid}' +
|
||||
'&IsVirtualUnAired=false' +
|
||||
'&IsMissing=false' +
|
||||
'&Fields=SpecialEpisodeNumbers,{}'.format(default_filters) +
|
||||
|
||||
@@ -1,45 +1,62 @@
|
||||
# Gnu General Public License - see LICENSE.TXT
|
||||
from __future__ import division, absolute_import, print_function, unicode_literals
|
||||
from __future__ import (
|
||||
division, absolute_import, print_function, unicode_literals
|
||||
)
|
||||
|
||||
from six.moves.urllib.parse import quote, unquote, parse_qsl
|
||||
import sys
|
||||
import os
|
||||
import time
|
||||
import cProfile
|
||||
import pstats
|
||||
from six import StringIO
|
||||
|
||||
import xbmcplugin
|
||||
import xbmcgui
|
||||
import xbmcaddon
|
||||
import xbmc
|
||||
from six import StringIO
|
||||
from six.moves.urllib.parse import quote, unquote, parse_qsl, urlencode
|
||||
|
||||
from .jellyfin import api
|
||||
from .utils import translate_string, get_version, load_user_details, get_art_url, get_default_filters, translate_path, kodi_version
|
||||
from .utils import (
|
||||
translate_string, get_version, load_user_details, get_art_url,
|
||||
get_default_filters, translate_path, kodi_version, get_jellyfin_url
|
||||
)
|
||||
from .kodi_utils import HomeWindow
|
||||
from .datamanager import clear_cached_server_data
|
||||
from .server_detect import check_server, check_connection_speed
|
||||
from .lazylogger import LazyLogger
|
||||
from .menu_functions import display_main_menu, display_menu, show_movie_alpha_list, show_tvshow_alpha_list, show_genre_list, show_search, show_movie_pages, show_artist_alpha_list
|
||||
from .menu_functions import (
|
||||
display_main_menu, display_menu, show_movie_alpha_list,
|
||||
show_tvshow_alpha_list, show_genre_list, show_search,
|
||||
show_movie_pages, show_artist_alpha_list
|
||||
)
|
||||
from .server_sessions import show_server_sessions
|
||||
from .action_menu import ActionMenu
|
||||
from .dialogs import BitrateDialog
|
||||
from .widgets import get_widget_content, get_widget_content_cast, check_for_new_content
|
||||
from .widgets import (
|
||||
get_widget_content, get_widget_content_cast, check_for_new_content
|
||||
)
|
||||
from .cache_images import CacheArtwork
|
||||
from .dir_functions import get_content, process_directory
|
||||
from .tracking import timer
|
||||
from .skin_cloner import clone_default_skin
|
||||
from .play_utils import play_file
|
||||
|
||||
__addon__ = xbmcaddon.Addon()
|
||||
__addondir__ = translate_path(__addon__.getAddonInfo('profile'))
|
||||
__cwd__ = __addon__.getAddonInfo('path')
|
||||
PLUGINPATH = translate_path(os.path.join(__cwd__))
|
||||
try:
|
||||
__addon__ = xbmcaddon.Addon()
|
||||
__addondir__ = translate_path(__addon__.getAddonInfo('profile'))
|
||||
__cwd__ = __addon__.getAddonInfo('path')
|
||||
PLUGINPATH = translate_path(os.path.join(__cwd__))
|
||||
addon_id = __addon__.getAddonInfo('id')
|
||||
except Exception:
|
||||
# During installation/update, addon might not be fully registered yet
|
||||
__addon__ = None
|
||||
__addondir__ = ''
|
||||
__cwd__ = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||
PLUGINPATH = __cwd__
|
||||
addon_id = 'plugin.video.jellycon'
|
||||
|
||||
log = LazyLogger(__name__)
|
||||
|
||||
user_details = load_user_details()
|
||||
|
||||
|
||||
@timer
|
||||
def main_entry_point():
|
||||
@@ -56,7 +73,9 @@ def main_entry_point():
|
||||
|
||||
log.debug("Running Python: {0}".format(sys.version_info))
|
||||
log.debug("Running JellyCon: {0}".format(get_version()))
|
||||
log.debug("Kodi BuildVersion: {0}".format(xbmc.getInfoLabel("System.BuildVersion")))
|
||||
log.debug("Kodi BuildVersion: {0}".format(
|
||||
xbmc.getInfoLabel("System.BuildVersion"))
|
||||
)
|
||||
log.debug("Kodi Version: {0}".format(kodi_version()))
|
||||
log.debug("Script argument data: {0}".format(sys.argv))
|
||||
|
||||
@@ -68,7 +87,9 @@ def main_entry_point():
|
||||
|
||||
mode = params.get("mode", None)
|
||||
|
||||
if len(params) == 1 and request_path and request_path.find("/library/movies") > -1:
|
||||
if (len(params) == 1 and request_path
|
||||
and request_path.find("/library/movies") > -1):
|
||||
|
||||
check_server()
|
||||
new_params = {}
|
||||
new_params["item_type"] = "Movie"
|
||||
@@ -104,10 +125,13 @@ def main_entry_point():
|
||||
elif mode == "CLONE_SKIN":
|
||||
clone_default_skin()
|
||||
elif mode == "SHOW_SETTINGS":
|
||||
__addon__.openSettings()
|
||||
addon = xbmcaddon.Addon()
|
||||
addon.openSettings()
|
||||
window = xbmcgui.getCurrentWindowId()
|
||||
if window == 10000:
|
||||
log.debug("Currently in home - refreshing to allow new settings to be taken")
|
||||
log.debug(
|
||||
"Currently in home - refresh to allow new settings to be taken"
|
||||
)
|
||||
xbmc.executebuiltin("ActivateWindow(Home)")
|
||||
elif mode == "CLEAR_CACHE":
|
||||
clear_cached_server_data()
|
||||
@@ -129,13 +153,6 @@ def main_entry_point():
|
||||
show_server_sessions()
|
||||
elif mode == "SHOW_ADDON_MENU":
|
||||
display_menu(params)
|
||||
elif mode == "GET_CONTENT_BY_TV_SHOW":
|
||||
parent_id = __get_parent_id_from(params)
|
||||
if parent_id is not None:
|
||||
enriched_url = param_url + "&ParentId=" + parent_id
|
||||
get_content(enriched_url, params)
|
||||
else:
|
||||
log.info("Unable to find TV show parent ID.")
|
||||
else:
|
||||
log.debug("JellyCon -> Mode: {0}".format(mode))
|
||||
log.debug("JellyCon -> URL: {0}".format(param_url))
|
||||
@@ -152,7 +169,9 @@ def main_entry_point():
|
||||
pr.disable()
|
||||
|
||||
file_time_stamp = time.strftime("%Y%m%d-%H%M%S")
|
||||
tab_file_name = __addondir__ + "profile(" + file_time_stamp + ").txt"
|
||||
tab_file_name = "{}-profile({}).txt".format(
|
||||
__addondir__, file_time_stamp
|
||||
)
|
||||
s = StringIO()
|
||||
ps = pstats.Stats(pr, stream=s)
|
||||
ps = ps.sort_stats('cumulative')
|
||||
@@ -166,33 +185,6 @@ def main_entry_point():
|
||||
log.debug("===== JellyCon FINISHED =====")
|
||||
|
||||
|
||||
def __enrich_url(param_url, params):
|
||||
enriched_url = param_url
|
||||
parent_id = __get_parent_id_from(params)
|
||||
if parent_id is not None:
|
||||
enriched_url = param_url + "&ParentId=" + parent_id
|
||||
return enriched_url
|
||||
|
||||
|
||||
def __get_parent_id_from(params):
|
||||
result = None
|
||||
show_provider_ids = params.get("show_ids")
|
||||
if show_provider_ids is not None:
|
||||
log.debug("TV show providers IDs: {}".format(show_provider_ids))
|
||||
get_show_url = "/Users/{}/Items?fields=MediaStreams&Recursive=true" \
|
||||
"&IncludeItemTypes=series&IncludeMedia=true&ImageTypeLimit=1&Limit=16" \
|
||||
"&AnyProviderIdEquals={}".format(api.user_id, show_provider_ids)
|
||||
content = api.get(get_show_url)
|
||||
show = content.get("Items")
|
||||
if len(show) == 1:
|
||||
result = content.get("Items")[0].get("Id")
|
||||
else:
|
||||
log.debug("TV show not found for ids: {}".format(show_provider_ids))
|
||||
else:
|
||||
log.error("TV show parameter not found in request.")
|
||||
return result
|
||||
|
||||
|
||||
def toggle_watched(params):
|
||||
log.debug("toggle_watched: {0}".format(params))
|
||||
item_id = params.get("item_id", None)
|
||||
@@ -214,82 +206,88 @@ def toggle_watched(params):
|
||||
|
||||
def mark_item_watched(item_id):
|
||||
log.debug("Mark Item Watched: {0}".format(item_id))
|
||||
url = "/Users/{}/PlayedItems/{}".format(user_details.get('user_id'), item_id)
|
||||
url = "/Users/{}/PlayedItems/{}".format(api.user_id, item_id)
|
||||
api.post(url)
|
||||
check_for_new_content()
|
||||
home_window = HomeWindow()
|
||||
last_url = home_window.get_property("last_content_url")
|
||||
if last_url:
|
||||
log.debug("markWatched_lastUrl: {0}".format(last_url))
|
||||
home_window.set_property("skip_cache_for_" + last_url, "true")
|
||||
home_window.set_property("skip_cache_for_{}".format(last_url), "true")
|
||||
|
||||
xbmc.executebuiltin("Container.Refresh")
|
||||
|
||||
|
||||
def mark_item_unwatched(item_id):
|
||||
log.debug("Mark Item UnWatched: {0}".format(item_id))
|
||||
url = "/Users/{}/PlayedItems/{}".format(user_details.get('user_id'), item_id)
|
||||
url = "/Users/{}/PlayedItems/{}".format(api.user_id, item_id)
|
||||
api.delete(url)
|
||||
check_for_new_content()
|
||||
home_window = HomeWindow()
|
||||
last_url = home_window.get_property("last_content_url")
|
||||
if last_url:
|
||||
log.debug("markUnwatched_lastUrl: {0}".format(last_url))
|
||||
home_window.set_property("skip_cache_for_" + last_url, "true")
|
||||
home_window.set_property("skip_cache_for_{}".format(last_url), "true")
|
||||
|
||||
xbmc.executebuiltin("Container.Refresh")
|
||||
|
||||
|
||||
def mark_item_favorite(item_id):
|
||||
log.debug("Add item to favourites: {0}".format(item_id))
|
||||
url = "/Users/{}/FavoriteItems/{}".format(user_details.get('user_id'), item_id)
|
||||
url = "/Users/{}/FavoriteItems/{}".format(api.user_id, item_id)
|
||||
api.post(url)
|
||||
check_for_new_content()
|
||||
home_window = HomeWindow()
|
||||
last_url = home_window.get_property("last_content_url")
|
||||
if last_url:
|
||||
home_window.set_property("skip_cache_for_" + last_url, "true")
|
||||
home_window.set_property("skip_cache_for_{}".format(last_url), "true")
|
||||
|
||||
xbmc.executebuiltin("Container.Refresh")
|
||||
|
||||
|
||||
def unmark_item_favorite(item_id):
|
||||
log.debug("Remove item from favourites: {0}".format(item_id))
|
||||
url = "/Users/{}/FavoriteItems/{}".format(user_details.get('user_id'), item_id)
|
||||
url = "/Users/{}/FavoriteItems/{}".format(api.user_id, item_id)
|
||||
api.delete(url)
|
||||
check_for_new_content()
|
||||
home_window = HomeWindow()
|
||||
last_url = home_window.get_property("last_content_url")
|
||||
if last_url:
|
||||
home_window.set_property("skip_cache_for_" + last_url, "true")
|
||||
home_window.set_property("skip_cache_for_{}".format(last_url), "true")
|
||||
|
||||
xbmc.executebuiltin("Container.Refresh")
|
||||
|
||||
|
||||
def delete(item_id):
|
||||
|
||||
item = api.delete("/Users/{}/Items/{}".format(user_details.get('user_id'), item_id))
|
||||
item = api.get("/Users/{}/Items/{}".format(api.user_id, item_id))
|
||||
|
||||
item_id = item.get("Id")
|
||||
item_name = item.get("Name", "")
|
||||
series_name = item.get("SeriesName", "")
|
||||
ep_number = item.get("IndexNumber", -1)
|
||||
|
||||
final_name = ""
|
||||
final_name_parts = []
|
||||
|
||||
if series_name:
|
||||
final_name += series_name + " - "
|
||||
final_name_parts.append(series_name)
|
||||
|
||||
if ep_number != -1:
|
||||
final_name += "Episode %02d - " % (ep_number,)
|
||||
final_name_parts.append("Episode {:02d}".format(ep_number))
|
||||
|
||||
final_name += item_name
|
||||
final_name_parts.append(item_name)
|
||||
final_name = " - ".join(final_name_parts)
|
||||
|
||||
if not item.get("CanDelete", False):
|
||||
xbmcgui.Dialog().ok(translate_string(30135), translate_string(30417), final_name)
|
||||
xbmcgui.Dialog().ok(
|
||||
translate_string(30135), translate_string(30417), final_name
|
||||
)
|
||||
return
|
||||
|
||||
return_value = xbmcgui.Dialog().yesno(translate_string(30091), '{}\n{}'.format(final_name, translate_string(30092)))
|
||||
return_value = xbmcgui.Dialog().yesno(
|
||||
translate_string(30091), '{}\n{}'.format(
|
||||
final_name, translate_string(30092)
|
||||
)
|
||||
)
|
||||
if return_value:
|
||||
log.debug('Deleting Item: {0}'.format(item_id))
|
||||
url = '/Items/{}'.format(item_id)
|
||||
@@ -301,7 +299,9 @@ def delete(item_id):
|
||||
home_window = HomeWindow()
|
||||
last_url = home_window.get_property("last_content_url")
|
||||
if last_url:
|
||||
home_window.set_property("skip_cache_for_" + last_url, "true")
|
||||
home_window.set_property(
|
||||
"skip_cache_for_{}".format(last_url), "true"
|
||||
)
|
||||
|
||||
xbmc.executebuiltin("Container.Refresh")
|
||||
|
||||
@@ -320,7 +320,7 @@ def get_params():
|
||||
param = dict(parse_qsl(paramstring[1:]))
|
||||
|
||||
# add plugin path
|
||||
request_path = plugin_path.replace("plugin://plugin.video.jellycon", "")
|
||||
request_path = plugin_path.replace("plugin://{}".format(addon_id), "")
|
||||
param["request_path"] = request_path
|
||||
|
||||
log.debug("JellyCon -> Detected parameters: {0}".format(param))
|
||||
@@ -343,22 +343,45 @@ def show_menu(params):
|
||||
|
||||
action_items = []
|
||||
|
||||
if result["Type"] in ["Episode", "Movie", "Music", "Video", "Audio", "TvChannel", "Program"]:
|
||||
# Additional items to include in the context menu for different item types
|
||||
if result["Type"] in ["Episode", "Movie", "Music", "Video", "Audio",
|
||||
"TvChannel", "Program", "MusicVideo"]:
|
||||
li = xbmcgui.ListItem(translate_string(30314), offscreen=True)
|
||||
li.setProperty('menu_id', 'play')
|
||||
action_items.append(li)
|
||||
|
||||
if result["Type"] in ["Season", "MusicArtist", "MusicAlbum", "Playlist"]:
|
||||
# Add "Play with track selection" for Movies and Episodes
|
||||
if result["Type"] in ["Episode", "Movie"]:
|
||||
li = xbmcgui.ListItem(translate_string(30701), offscreen=True)
|
||||
li.setProperty('menu_id', 'play_with_track_selection')
|
||||
action_items.append(li)
|
||||
|
||||
if result["Type"] in ["Season", "MusicArtist", "MusicAlbum", "Playlist",
|
||||
"MusicGenre"]:
|
||||
li = xbmcgui.ListItem(translate_string(30317), offscreen=True)
|
||||
li.setProperty('menu_id', 'play_all')
|
||||
action_items.append(li)
|
||||
|
||||
if result["Type"] in ["Episode", "Movie", "Video", "TvChannel", "Program"]:
|
||||
if result["Type"] in ["MusicArtist", "MusicAlbum", "Playlist",
|
||||
"Series", "Season", "MusicGenre"]:
|
||||
li = xbmcgui.ListItem(translate_string(30448), offscreen=True)
|
||||
li.setProperty('menu_id', 'shuffle')
|
||||
action_items.append(li)
|
||||
|
||||
if result["Type"] in ["MusicArtist", "MusicAlbum", "Audio"]:
|
||||
li = xbmcgui.ListItem(translate_string(30449), offscreen=True)
|
||||
li.setProperty('menu_id', 'instant_mix')
|
||||
action_items.append(li)
|
||||
|
||||
if result["Type"] in ["Episode", "Movie", "Video", "TvChannel",
|
||||
"Program", "MusicVideo"]:
|
||||
li = xbmcgui.ListItem(translate_string(30275), offscreen=True)
|
||||
li.setProperty('menu_id', 'transcode')
|
||||
action_items.append(li)
|
||||
|
||||
if result["Type"] in ["Episode", "Movie", "Music", "Video", "Audio", "MusicArtist", "MusicAlbum"]:
|
||||
if result["Type"] in ["Episode", "Movie", "Music", "Video", "Audio",
|
||||
"MusicArtist", "MusicAlbum", "MusicVideo",
|
||||
"MusicGenre"]:
|
||||
li = xbmcgui.ListItem(translate_string(30402), offscreen=True)
|
||||
li.setProperty('menu_id', 'add_to_playlist')
|
||||
action_items.append(li)
|
||||
@@ -431,12 +454,15 @@ def show_menu(params):
|
||||
window = xbmcgui.Window(xbmcgui.getCurrentWindowId())
|
||||
container_view_id = str(window.getFocusId())
|
||||
container_content_type = xbmc.getInfoLabel("Container.Content")
|
||||
view_key = "view-" + container_content_type
|
||||
view_key = "view-{}".format(container_content_type)
|
||||
current_default_view = settings.getSetting(view_key)
|
||||
view_match = container_view_id == current_default_view
|
||||
log.debug("View ID:{0} Content type:{1}".format(container_view_id, container_content_type))
|
||||
log.debug("View ID:{0} Content type:{1}".format(
|
||||
container_view_id, container_content_type)
|
||||
)
|
||||
|
||||
if container_content_type in ["movies", "tvshows", "seasons", "episodes", "sets"]:
|
||||
if container_content_type in ["movies", "tvshows", "seasons",
|
||||
"episodes", "sets"]:
|
||||
if view_match:
|
||||
li = xbmcgui.ListItem("Unset as default view", offscreen=True)
|
||||
li.setProperty('menu_id', 'unset_view')
|
||||
@@ -460,23 +486,36 @@ def show_menu(params):
|
||||
log.debug("Play Item")
|
||||
play_action(params)
|
||||
|
||||
elif selected_action == "play_with_track_selection":
|
||||
log.debug("Play Item with Track Selection")
|
||||
params["force_track_selection"] = "true"
|
||||
play_action(params)
|
||||
|
||||
elif selected_action == "set_view":
|
||||
log.debug("Settign view type for {0} to {1}".format(view_key, container_view_id))
|
||||
log.debug("Setting view type for {0} to {1}".format(
|
||||
view_key, container_view_id)
|
||||
)
|
||||
settings.setSetting(view_key, container_view_id)
|
||||
|
||||
elif selected_action == "unset_view":
|
||||
log.debug("Un-Settign view type for {0} to {1}".format(view_key, container_view_id))
|
||||
log.debug("Un-Settign view type for {0} to {1}".format(
|
||||
view_key, container_view_id)
|
||||
)
|
||||
settings.setSetting(view_key, "")
|
||||
|
||||
elif selected_action == "refresh_server":
|
||||
url = ("/Items/" + item_id + "/Refresh" +
|
||||
"?Recursive=true" +
|
||||
"&ImageRefreshMode=FullRefresh" +
|
||||
"&MetadataRefreshMode=FullRefresh" +
|
||||
"&ReplaceAllImages=true" +
|
||||
"&ReplaceAllMetadata=true")
|
||||
url_path = "/Items/{}/Refresh".format(item_id)
|
||||
url_params = {
|
||||
"Recursive": True,
|
||||
"ImageRefreshMode": "FullRefresh",
|
||||
"MetadataRefreshMode": "FullRefresh",
|
||||
"ReplaceAllImages": True,
|
||||
"ReplaceAllMetadata": True
|
||||
}
|
||||
|
||||
url = get_jellyfin_url(url_path, url_params)
|
||||
res = api.post(url)
|
||||
log.debug("Refresh Server Responce: {0}".format(res))
|
||||
log.debug("Refresh Server Response: {0}".format(res))
|
||||
|
||||
elif selected_action == "hide":
|
||||
user_details = load_user_details()
|
||||
@@ -485,37 +524,52 @@ def show_menu(params):
|
||||
url = "/Items/{}/Tags/Add".format(item_id)
|
||||
post_tag_data = {"Tags": [{"Name": hide_tag_string}]}
|
||||
res = api.post(url, post_tag_data)
|
||||
log.debug("Add Tag Responce: {0}".format(res))
|
||||
log.debug("Add Tag Response: {0}".format(res))
|
||||
|
||||
check_for_new_content()
|
||||
|
||||
last_url = home_window.get_property("last_content_url")
|
||||
if last_url:
|
||||
log.debug("markUnwatched_lastUrl: {0}".format(last_url))
|
||||
home_window.set_property("skip_cache_for_" + last_url, "true")
|
||||
home_window.set_property(
|
||||
"skip_cache_for_{}".format(last_url), "true"
|
||||
)
|
||||
|
||||
xbmc.executebuiltin("Container.Refresh")
|
||||
|
||||
elif selected_action == "play_all":
|
||||
play_action(params)
|
||||
|
||||
elif selected_action == "shuffle":
|
||||
params["action"] = "shuffle"
|
||||
play_action(params)
|
||||
|
||||
elif selected_action == "instant_mix":
|
||||
params["action"] = "instant_mix"
|
||||
play_action(params)
|
||||
|
||||
elif selected_action == "play_trailer":
|
||||
play_item_trailer(item_id)
|
||||
|
||||
elif selected_action == "transcode":
|
||||
params['force_transcode'] = 'true'
|
||||
|
||||
force_max_stream_bitrate = settings.getSetting("force_max_stream_bitrate")
|
||||
initial_bitrate_value = int(force_max_stream_bitrate)
|
||||
bitrate_dialog = BitrateDialog("BitrateDialog.xml", PLUGINPATH, "default", "720p")
|
||||
max_bitrate = settings.getSetting("force_max_stream_bitrate")
|
||||
initial_bitrate_value = int(max_bitrate)
|
||||
bitrate_dialog = BitrateDialog(
|
||||
"BitrateDialog.xml", PLUGINPATH, "default", "720p"
|
||||
)
|
||||
bitrate_dialog.initial_bitrate_value = initial_bitrate_value
|
||||
bitrate_dialog.doModal()
|
||||
selected_transcode_value = bitrate_dialog.selected_transcode_value
|
||||
del bitrate_dialog
|
||||
log.debug("selected_transcode_value: {0}".format(selected_transcode_value))
|
||||
log.debug("selected_transcode_value: {0}".format(
|
||||
selected_transcode_value)
|
||||
)
|
||||
|
||||
if selected_transcode_value > 0:
|
||||
settings.setSetting("force_max_stream_bitrate", str(selected_transcode_value))
|
||||
settings.setSetting(
|
||||
"force_max_stream_bitrate", str(selected_transcode_value))
|
||||
|
||||
play_action(params)
|
||||
|
||||
@@ -539,25 +593,49 @@ def show_menu(params):
|
||||
delete(item_id)
|
||||
|
||||
elif selected_action == "show_extras":
|
||||
u = "/Users/{}/Items/{}/SpecialFeatures".format(api.user_id, item_id)
|
||||
action_url = ("plugin://plugin.video.jellycon/?url=" + quote(u) + "&mode=GET_CONTENT&media_type=Videos")
|
||||
built_in_command = 'ActivateWindow(Videos, ' + action_url + ', return)'
|
||||
url = "/Users/{}/Items/{}/SpecialFeatures".format(api.user_id, item_id)
|
||||
plugin_params = {
|
||||
"url": url,
|
||||
"mode": "GET_CONTENT",
|
||||
"media_type": "Videos"
|
||||
}
|
||||
|
||||
action_params = urlencode(plugin_params)
|
||||
|
||||
action_url = "plugin://{}/?{}".format(addon_id, action_params)
|
||||
built_in_command = 'ActivateWindow(Videos, {}, return)'.format(
|
||||
action_url
|
||||
)
|
||||
xbmc.executebuiltin(built_in_command)
|
||||
|
||||
elif selected_action == "view_season":
|
||||
xbmc.executebuiltin("Dialog.Close(all,true)")
|
||||
parent_id = result["ParentId"]
|
||||
series_id = result["SeriesId"]
|
||||
u = ('/Shows/' + series_id +
|
||||
'/Episodes'
|
||||
'?userId={}'.format(api.user_id) +
|
||||
'&seasonId=' + parent_id +
|
||||
'&IsVirtualUnAired=false' +
|
||||
'&IsMissing=false' +
|
||||
'&Fields=SpecialEpisodeNumbers,{}'.format(get_default_filters()) +
|
||||
'&format=json')
|
||||
action_url = ("plugin://plugin.video.jellycon/?url=" + quote(u) + "&mode=GET_CONTENT&media_type=Season")
|
||||
built_in_command = 'ActivateWindow(Videos, ' + action_url + ', return)'
|
||||
|
||||
url_path = "/Shows/{}/Episodes".format(series_id)
|
||||
url_params = {
|
||||
"userId": api.user_id,
|
||||
"seasonId": parent_id,
|
||||
"IsVirtualUnAired": False,
|
||||
"IsMissing": False,
|
||||
"Fields": "SpecialEpisodeNumbers,{}".format(get_default_filters())
|
||||
}
|
||||
|
||||
url = get_jellyfin_url(url_path, url_params)
|
||||
|
||||
plugin_params = {
|
||||
"url": url,
|
||||
"mode": "GET_CONTENT",
|
||||
"media_type": "Season"
|
||||
}
|
||||
|
||||
action_params = urlencode(plugin_params)
|
||||
|
||||
action_url = "plugin://{}/?{}".format(addon_id, action_params)
|
||||
built_in_command = 'ActivateWindow(Videos, {}, return)'.format(
|
||||
action_url
|
||||
)
|
||||
xbmc.executebuiltin(built_in_command)
|
||||
|
||||
elif selected_action == "view_series":
|
||||
@@ -567,18 +645,30 @@ def show_menu(params):
|
||||
if not series_id:
|
||||
series_id = item_id
|
||||
|
||||
u = ('/Shows/' + series_id +
|
||||
'/Seasons'
|
||||
'?userId={}'.format(api.user_id) +
|
||||
'&Fields={}'.format(get_default_filters()) +
|
||||
'&format=json')
|
||||
url_path = "/Shows/{}/Seasons".format(series_id)
|
||||
url_params = {
|
||||
"userId": api.user_id,
|
||||
"Fields": get_default_filters(),
|
||||
}
|
||||
|
||||
action_url = ("plugin://plugin.video.jellycon/?url=" + quote(u) + "&mode=GET_CONTENT&media_type=Series")
|
||||
url = get_jellyfin_url(url_path, url_params)
|
||||
|
||||
plugin_params = {
|
||||
"url": url,
|
||||
"mode": "GET_CONTENT",
|
||||
"media_type": "Series"
|
||||
}
|
||||
|
||||
action_params = urlencode(plugin_params)
|
||||
|
||||
action_url = "plugin://{}/?{}".format(addon_id, action_params)
|
||||
|
||||
if xbmc.getCondVisibility("Window.IsActive(home)"):
|
||||
built_in_command = 'ActivateWindow(Videos, ' + action_url + ', return)'
|
||||
built_in_command = 'ActivateWindow(Videos, {}, return'.format(
|
||||
action_url
|
||||
)
|
||||
else:
|
||||
built_in_command = 'Container.Update(' + action_url + ')'
|
||||
built_in_command = 'Container.Update({})'.format(action_url)
|
||||
|
||||
xbmc.executebuiltin(built_in_command)
|
||||
|
||||
@@ -600,18 +690,21 @@ def show_content(params):
|
||||
if item_type.lower().find("movie") == -1:
|
||||
group_movies = False
|
||||
|
||||
content_url = ("/Users/{}/Items".format(api.user_id) +
|
||||
"?format=json" +
|
||||
"&ImageTypeLimit=1" +
|
||||
"&IsMissing=False" +
|
||||
"&Fields={}".format(get_default_filters()) +
|
||||
'&CollapseBoxSetItems=' + str(group_movies) +
|
||||
'&GroupItemsIntoCollections=' + str(group_movies) +
|
||||
"&Recursive=true" +
|
||||
'&SortBy=Name' +
|
||||
'&SortOrder=Ascending' +
|
||||
"&IsVirtualUnaired=false" +
|
||||
"&IncludeItemTypes=" + item_type)
|
||||
url_path = "/Users/{}/Items".format(api.user_id)
|
||||
url_params = {
|
||||
"ImageTypeLimit": 1,
|
||||
"IsMissing": False,
|
||||
"Fields": get_default_filters(),
|
||||
"CollapseBoxSetItems": group_movies,
|
||||
"GroupItemsIntoCollections": group_movies,
|
||||
"Recursive": True,
|
||||
"SortBy": "Name",
|
||||
"SortOrder": "Ascending",
|
||||
"IsVirtualUnaired": False,
|
||||
"IncludeItemTypes": item_type
|
||||
}
|
||||
|
||||
content_url = get_jellyfin_url(url_path, url_params)
|
||||
|
||||
log.debug("showContent Content Url: {0}".format(content_url))
|
||||
get_content(content_url, params)
|
||||
@@ -622,15 +715,21 @@ def search_results_person(params):
|
||||
handle = int(sys.argv[1])
|
||||
|
||||
person_id = params.get("person_id")
|
||||
details_url = ('/Users/{}/Items'.format(api.user_id) +
|
||||
'?PersonIds=' + person_id +
|
||||
'&Recursive=true' +
|
||||
'&Fields={}'.format(get_default_filters()) +
|
||||
'&format=json')
|
||||
|
||||
url_path = "/Users/{}/Items".format(api.user_id)
|
||||
url_params = {
|
||||
"PersonIds": person_id,
|
||||
"Recursive": True,
|
||||
"Fields": get_default_filters()
|
||||
}
|
||||
|
||||
details_url = get_jellyfin_url(url_path, url_params)
|
||||
|
||||
params["name_format"] = "Episode|episode_name_format"
|
||||
|
||||
dir_items, detected_type, total_records = process_directory(details_url, None, params)
|
||||
dir_items, detected_type, total_records = process_directory(
|
||||
details_url, None, params
|
||||
)
|
||||
|
||||
log.debug('search_results_person results: {0}'.format(dir_items))
|
||||
log.debug('search_results_person detect_type: {0}'.format(detected_type))
|
||||
@@ -646,7 +745,7 @@ def search_results_person(params):
|
||||
content_type = 'episodes'
|
||||
elif detected_type == "Series":
|
||||
content_type = 'tvshows'
|
||||
elif detected_type == "Music" or detected_type == "Audio" or detected_type == "Musicalbum":
|
||||
elif detected_type in ["Music", "Audio", "Musicalbum"]:
|
||||
content_type = 'songs'
|
||||
|
||||
if content_type:
|
||||
@@ -679,7 +778,7 @@ def search_results(params):
|
||||
heading_type = translate_string(30235)
|
||||
content_type = 'episodes'
|
||||
params["name_format"] = "Episode|episode_name_format"
|
||||
elif item_type == "music" or item_type == "audio" or item_type == "musicalbum":
|
||||
elif item_type in ["music", "audio", "musicalalbum"]:
|
||||
heading_type = 'Music'
|
||||
content_type = 'songs'
|
||||
elif item_type == "person":
|
||||
@@ -695,7 +794,9 @@ def search_results(params):
|
||||
home_window = HomeWindow()
|
||||
last_search = home_window.get_property("last_search")
|
||||
kb = xbmc.Keyboard()
|
||||
kb.setHeading(heading_type.capitalize() + ' ' + translate_string(30246).lower())
|
||||
kb.setHeading("{} {}".format(
|
||||
heading_type.capitalize(), translate_string(30246).lower()
|
||||
))
|
||||
kb.setDefault(last_search)
|
||||
kb.doModal()
|
||||
|
||||
@@ -727,19 +828,23 @@ def search_results(params):
|
||||
|
||||
# what type of search
|
||||
if item_type == "person":
|
||||
search_url = ("/Persons" +
|
||||
"?searchTerm=" + query +
|
||||
"&IncludePeople=true" +
|
||||
"&IncludeMedia=false" +
|
||||
"&IncludeGenres=false" +
|
||||
"&IncludeStudios=false" +
|
||||
"&IncludeArtists=false" +
|
||||
"&Limit=16" +
|
||||
"&Fields=PrimaryImageAspectRatio,BasicSyncInfo,ProductionYear" +
|
||||
"&Recursive=true" +
|
||||
"&EnableTotalRecordCount=false" +
|
||||
"&ImageTypeLimit=1" +
|
||||
"&userId={}".format(api.user_id))
|
||||
url_path = "/Persons"
|
||||
url_params = {
|
||||
"searchTerm": query,
|
||||
"IncludePeople": True,
|
||||
"IncludeMedia": False,
|
||||
"IncludeGenres": False,
|
||||
"IncludeStudios": False,
|
||||
"IncludeArtists": False,
|
||||
"Limit": 16,
|
||||
"Fields": "PrimaryImageAspectRatio,BasicSyncInfo,ProductionYear",
|
||||
"Recursive": True,
|
||||
"EnableTotalRecordCount": False,
|
||||
"ImageTypeLimit": 1,
|
||||
"userId": api.user_id
|
||||
}
|
||||
|
||||
search_url = get_jellyfin_url(url_path, url_params)
|
||||
|
||||
person_search_results = api.get(search_url)
|
||||
log.debug("Person Search Result : {0}".format(person_search_results))
|
||||
@@ -755,7 +860,9 @@ def search_results(params):
|
||||
person_name = item.get('Name')
|
||||
person_thumbnail = get_art_url(item, "Primary", server=server)
|
||||
|
||||
action_url = sys.argv[0] + "?mode=NEW_SEARCH_PERSON&person_id=" + person_id
|
||||
action_url = "{}?mode=NEW_SEARCH_PERSON&person_id={}".format(
|
||||
addon_id, person_id
|
||||
)
|
||||
|
||||
list_item = xbmcgui.ListItem(label=person_name, offscreen=True)
|
||||
list_item.setProperty("id", person_id)
|
||||
@@ -767,31 +874,37 @@ def search_results(params):
|
||||
art_links["poster"] = person_thumbnail
|
||||
list_item.setArt(art_links)
|
||||
|
||||
item_tupple = (action_url, list_item, True)
|
||||
list_items.append(item_tupple)
|
||||
item_tuple = (action_url, list_item, True)
|
||||
list_items.append(item_tuple)
|
||||
|
||||
xbmcplugin.setContent(handle, 'artists')
|
||||
xbmcplugin.addDirectoryItems(handle, list_items)
|
||||
xbmcplugin.endOfDirectory(handle, cacheToDisc=False)
|
||||
|
||||
else:
|
||||
search_url = ("/Users/{}/Items".format(api.user_id) +
|
||||
"?searchTerm=" + query +
|
||||
"&IncludePeople=false" +
|
||||
"&IncludeMedia=true" +
|
||||
"&IncludeGenres=false" +
|
||||
"&IncludeStudios=false" +
|
||||
"&IncludeArtists=false" +
|
||||
"&IncludeItemTypes=" + item_type +
|
||||
"&Limit=16" +
|
||||
"&Fields={}".format(get_default_filters()) +
|
||||
"&Recursive=true" +
|
||||
"&EnableTotalRecordCount=false" +
|
||||
"&ImageTypeLimit=1")
|
||||
url_path = "/Users/{}/Items".format(api.user_id)
|
||||
url_params = {
|
||||
"searchTerm": query,
|
||||
"IncludePeople": False,
|
||||
"IncludeMedia": True,
|
||||
"IncludeGenres": False,
|
||||
"IncludeStudios": False,
|
||||
"IncludeArtists": False,
|
||||
"IncludeItemTypes": item_type,
|
||||
"Limit": 16,
|
||||
"Fields": get_default_filters(),
|
||||
"Recursive": True,
|
||||
"EnableTotalRecordCount": False,
|
||||
"ImageTypeLimit": 1
|
||||
}
|
||||
|
||||
search_url = get_jellyfin_url(url_path, url_params)
|
||||
|
||||
# set content type
|
||||
xbmcplugin.setContent(handle, content_type)
|
||||
dir_items, detected_type, total_records = process_directory(search_url, progress, params)
|
||||
dir_items, detected_type, total_records = process_directory(
|
||||
search_url, progress, params
|
||||
)
|
||||
xbmcplugin.addDirectoryItems(handle, dir_items)
|
||||
xbmcplugin.endOfDirectory(handle, cacheToDisc=False)
|
||||
|
||||
@@ -828,6 +941,9 @@ def play_action(params):
|
||||
audio_stream_index = params.get("audio_stream_index")
|
||||
log.debug("audio_stream_index: {0}".format(audio_stream_index))
|
||||
|
||||
force_track_selection = params.get("force_track_selection", "false") == "true"
|
||||
log.debug("force_track_selection: {0}".format(force_track_selection))
|
||||
|
||||
action = params.get("action", "play")
|
||||
|
||||
# set the current playing item id
|
||||
@@ -844,14 +960,21 @@ def play_action(params):
|
||||
play_info["media_source_id"] = media_source_id
|
||||
play_info["subtitle_stream_index"] = subtitle_stream_index
|
||||
play_info["audio_stream_index"] = audio_stream_index
|
||||
play_info["force_track_selection"] = force_track_selection
|
||||
log.info("Sending jellycon_play_action : {0}".format(play_info))
|
||||
play_file(play_info)
|
||||
|
||||
|
||||
def play_item_trailer(item_id):
|
||||
log.debug("== ENTER: playTrailer ==")
|
||||
handle = int(sys.argv[1]) if sys.argv and len(sys.argv) > 1 else -1
|
||||
if handle != -1:
|
||||
xbmcplugin.endOfDirectory(handle, succeeded=False, updateListing=False, cacheToDisc=False)
|
||||
|
||||
url = "/Users/{}/Items/{}/LocalTrailers?format=json".format(user_details.get('user_id'), item_id)
|
||||
user_details = load_user_details()
|
||||
url = "/Users/{}/Items/{}/LocalTrailers?format=json".format(
|
||||
user_details.get('user_id'), item_id
|
||||
)
|
||||
|
||||
result = api.get(url)
|
||||
|
||||
@@ -868,7 +991,7 @@ def play_item_trailer(item_id):
|
||||
info["type"] = "local"
|
||||
name = trailer.get("Name")
|
||||
while not name or name in trailer_names:
|
||||
name = "Trailer " + str(count)
|
||||
name = "Trailer {}".format(count)
|
||||
count += 1
|
||||
info["name"] = name
|
||||
info["id"] = trailer.get("Id")
|
||||
@@ -876,7 +999,9 @@ def play_item_trailer(item_id):
|
||||
trailer_names.append(name)
|
||||
trailer_list.append(info)
|
||||
|
||||
url = "/Users/{}/Items/{}?format=json&Fields=RemoteTrailers".format(user_details.get('user_id'), item_id)
|
||||
url = "/Users/{}/Items/{}?format=json&Fields=RemoteTrailers".format(
|
||||
user_details.get("user_id"), item_id
|
||||
)
|
||||
result = api.get(url)
|
||||
log.debug("RemoteTrailers: {0}".format(result))
|
||||
count = 1
|
||||
@@ -893,7 +1018,7 @@ def play_item_trailer(item_id):
|
||||
info["url"] = url
|
||||
name = trailer.get("Name")
|
||||
while not name or name in trailer_names:
|
||||
name = "Trailer " + str(count)
|
||||
name = "Trailer {}".format(count)
|
||||
count += 1
|
||||
info["name"] = name
|
||||
trailer_names.append(name)
|
||||
@@ -903,7 +1028,9 @@ def play_item_trailer(item_id):
|
||||
|
||||
trailer_text = []
|
||||
for trailer in trailer_list:
|
||||
name = trailer.get("name") + " (" + trailer.get("type") + ")"
|
||||
name = "{} ({})".format(
|
||||
trailer.get("name"), trailer.get("type")
|
||||
)
|
||||
trailer_text.append(name)
|
||||
|
||||
dialog = xbmcgui.Dialog()
|
||||
@@ -919,7 +1046,8 @@ def play_item_trailer(item_id):
|
||||
|
||||
elif trailer.get("type") == "remote":
|
||||
youtube_id = trailer.get("url").rsplit('=', 1)[1]
|
||||
youtube_plugin = "RunPlugin(plugin://plugin.video.youtube/play/?video_id=%s)" % youtube_id
|
||||
log.debug("youtube_plugin: {0}".format(youtube_plugin))
|
||||
url_root = "plugin.video.youtube/play/?video_id="
|
||||
play_url = "PlayMedia(plugin://{}{})".format(url_root, youtube_id)
|
||||
log.debug("youtube_plugin: {0}".format(play_url))
|
||||
|
||||
xbmc.executebuiltin(youtube_plugin)
|
||||
xbmc.executebuiltin(play_url)
|
||||
|
||||
@@ -1,19 +1,21 @@
|
||||
from __future__ import division, absolute_import, print_function, unicode_literals
|
||||
from __future__ import (
|
||||
division, absolute_import, print_function, unicode_literals
|
||||
)
|
||||
|
||||
import threading
|
||||
import io
|
||||
import base64
|
||||
import re
|
||||
from random import shuffle
|
||||
|
||||
import xbmcvfs
|
||||
import xbmc
|
||||
import xbmcaddon
|
||||
import base64
|
||||
import re
|
||||
from random import shuffle
|
||||
import requests
|
||||
from six.moves.BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer
|
||||
from six.moves.urllib.parse import urlparse
|
||||
from six import ensure_text
|
||||
|
||||
import threading
|
||||
import requests
|
||||
import io
|
||||
|
||||
from .jellyfin import api
|
||||
from .lazylogger import LazyLogger
|
||||
from .item_functions import get_art
|
||||
|
||||
158
resources/lib/intro_skipper.py
Normal file
158
resources/lib/intro_skipper.py
Normal file
@@ -0,0 +1,158 @@
|
||||
from __future__ import (
|
||||
division, absolute_import, print_function, unicode_literals
|
||||
)
|
||||
|
||||
import os
|
||||
import threading
|
||||
|
||||
import xbmc
|
||||
import xbmcaddon
|
||||
import xbmcgui
|
||||
|
||||
from resources.lib.play_utils import get_media_segments
|
||||
from resources.lib.utils import seconds_to_ticks, ticks_to_seconds, translate_path
|
||||
from resources.lib.intro_skipper_utils import get_setting_skip_action, set_correct_skip_info
|
||||
|
||||
|
||||
from .lazylogger import LazyLogger
|
||||
from .dialogs import SkipDialog
|
||||
|
||||
from typing import Literal
|
||||
|
||||
log = LazyLogger(__name__)
|
||||
|
||||
|
||||
class IntroSkipperService(threading.Thread):
|
||||
|
||||
stop_thread = False
|
||||
monitor = None
|
||||
|
||||
def __init__(self, play_monitor):
|
||||
super(IntroSkipperService, self).__init__()
|
||||
self.monitor = play_monitor
|
||||
|
||||
def run(self):
|
||||
|
||||
from .play_utils import get_jellyfin_playing_item
|
||||
settings = xbmcaddon.Addon()
|
||||
plugin_path = settings.getAddonInfo('path')
|
||||
plugin_path_real = translate_path(os.path.join(plugin_path))
|
||||
|
||||
skip_intro_dialog = None
|
||||
skip_credit_dialog = None
|
||||
skip_commercial_dialog = None
|
||||
skip_preview_dialog = None
|
||||
skip_recap_dialog = None
|
||||
|
||||
segments = None
|
||||
playing_item_id = None
|
||||
|
||||
log.debug("SkipService: starting service")
|
||||
|
||||
while not xbmc.Monitor().abortRequested() and not self.stop_thread:
|
||||
player = xbmc.Player()
|
||||
if player.isPlaying():
|
||||
item_id = get_jellyfin_playing_item()
|
||||
if item_id is not None:
|
||||
log.debug("SkipService: playing item is from jellyfin : {0}".format(item_id))
|
||||
|
||||
# If item id has changed or is new, retrieve segments
|
||||
if playing_item_id is None or playing_item_id != item_id :
|
||||
log.debug("SkipService: item is new, retrieving media segments : {0}".format(item_id))
|
||||
segments = get_media_segments(item_id)
|
||||
|
||||
# Setting global playing item to current playing item
|
||||
playing_item_id = item_id
|
||||
|
||||
# Handle skip only on jellyfin items
|
||||
current_ticks = seconds_to_ticks(player.getTime())
|
||||
|
||||
# Handle Intros
|
||||
skip_intro_dialog = self.handle_dialog(plugin_path_real, skip_intro_dialog, item_id, current_ticks, player, segments, "Intro")
|
||||
# Handle Credits
|
||||
skip_credit_dialog = self.handle_dialog(plugin_path_real, skip_credit_dialog, item_id, current_ticks, player, segments, "Outro")
|
||||
# Handle commercial
|
||||
skip_commercial_dialog = self.handle_dialog(plugin_path_real, skip_commercial_dialog, item_id, current_ticks, player, segments, "Commercial")
|
||||
# Handle preview
|
||||
skip_preview_dialog = self.handle_dialog(plugin_path_real, skip_preview_dialog, item_id, current_ticks, player, segments, "Preview")
|
||||
# Handle recap
|
||||
skip_recap_dialog = self.handle_dialog(plugin_path_real, skip_recap_dialog, item_id, current_ticks, player, segments, "Recap")
|
||||
|
||||
else:
|
||||
playing_item_id = None
|
||||
if skip_intro_dialog is not None:
|
||||
log.debug("SkipService: Playback stopped, killing Intro dialog")
|
||||
skip_intro_dialog.close()
|
||||
skip_intro_dialog = None
|
||||
|
||||
if skip_credit_dialog is not None:
|
||||
log.debug("SkipService: Playback stopped, killing Outro dialog")
|
||||
skip_credit_dialog.close()
|
||||
skip_credit_dialog = None
|
||||
|
||||
if skip_commercial_dialog is not None:
|
||||
log.debug("SkipService: Playback stopped, killing Commercial dialog")
|
||||
skip_commercial_dialog.close()
|
||||
skip_commercial_dialog = None
|
||||
|
||||
if skip_preview_dialog is not None:
|
||||
log.debug("SkipService: Playback stopped, killing Preview dialog")
|
||||
skip_preview_dialog.close()
|
||||
skip_preview_dialog = None
|
||||
|
||||
if skip_recap_dialog is not None:
|
||||
log.debug("SkipService: Playback stopped, killing Recap dialog")
|
||||
skip_recap_dialog.close()
|
||||
skip_recap_dialog = None
|
||||
|
||||
if xbmc.Monitor().waitForAbort(1):
|
||||
break
|
||||
|
||||
xbmc.sleep(200)
|
||||
|
||||
|
||||
def handle_dialog(self, plugin_path_real: str, dialog: SkipDialog, item_id: str, current_ticks: float, player: xbmc.Player, segments, type: Literal["Commercial", "Preview", "Recap", "Outro", "Intro"]):
|
||||
skip_action = get_setting_skip_action(type)
|
||||
|
||||
# In case do nothing is selected return
|
||||
if skip_action == "2":
|
||||
log.debug("SkipService: ignore {0} is selected".format(type))
|
||||
return None
|
||||
|
||||
if dialog is None:
|
||||
log.debug("SkipService: init dialog")
|
||||
dialog = SkipDialog("SkipDialog.xml", plugin_path_real, "default", "720p")
|
||||
|
||||
set_correct_skip_info(item_id, dialog, segments, type)
|
||||
|
||||
is_segment = False
|
||||
if dialog.start is not None and dialog.end is not None:
|
||||
# Resets the dismiss var so that button can reappear in case of navigation in the timecodes
|
||||
if (current_ticks < dialog.start or current_ticks > dialog.end) and dialog.has_been_dissmissed is True:
|
||||
log.debug("SkipService: {0} skip was dismissed. It is reset beacause timecode is outside of segment")
|
||||
dialog.has_been_dissmissed = False
|
||||
|
||||
# Checks if segment is playing
|
||||
is_segment = current_ticks >= dialog.start and current_ticks <= dialog.end
|
||||
|
||||
if skip_action == "1" and is_segment:
|
||||
log.debug("SkipService: {0} is set to automatic skip, skipping segment".format(type))
|
||||
# If auto skip is enabled, skips to semgent ends automatically
|
||||
player.seekTime(ticks_to_seconds(dialog.end))
|
||||
xbmcgui.Dialog().notification("JellyCon", "{0} Skipped".format(type))
|
||||
elif skip_action == "0":
|
||||
# Otherwise show skip dialog
|
||||
if is_segment and not dialog.has_been_dissmissed:
|
||||
log.debug("SkipService: {0} is playing, showing dialog".format(type))
|
||||
dialog.show()
|
||||
else:
|
||||
# Could not find doc on what happens when closing a closed dialog, but it seems fine
|
||||
log.debug("SkipService: {0} is not playing, closing dialog".format(type))
|
||||
dialog.close()
|
||||
|
||||
return dialog
|
||||
|
||||
|
||||
def stop_service(self):
|
||||
log.debug("IntroSkipperService Stop Called")
|
||||
self.stop_thread = True
|
||||
72
resources/lib/intro_skipper_utils.py
Normal file
72
resources/lib/intro_skipper_utils.py
Normal file
@@ -0,0 +1,72 @@
|
||||
from typing import Literal
|
||||
|
||||
import xbmcaddon
|
||||
|
||||
from .lazylogger import LazyLogger
|
||||
from .dialogs import SkipDialog
|
||||
|
||||
from .utils import seconds_to_ticks
|
||||
|
||||
log = LazyLogger(__name__)
|
||||
|
||||
def get_setting_skip_action(type: Literal["Commercial", "Preview", "Recap", "Outro", "Intro"]):
|
||||
settings = xbmcaddon.Addon()
|
||||
if (type == "Commercial"):
|
||||
return settings.getSetting("commercial_skipper_action")
|
||||
elif (type == "Preview"):
|
||||
return settings.getSetting("preview_skipper_action")
|
||||
elif (type == "Recap"):
|
||||
return settings.getSetting("recap_skipper_action")
|
||||
elif (type == "Outro"):
|
||||
return settings.getSetting("credit_skipper_action")
|
||||
elif (type == "Intro"):
|
||||
return settings.getSetting("intro_skipper_action")
|
||||
return ""
|
||||
|
||||
def get_setting_skip_start_offset(type: Literal["Commercial", "Preview", "Recap", "Outro", "Intro"]):
|
||||
settings = xbmcaddon.Addon()
|
||||
if (type == "Commercial"):
|
||||
return settings.getSettingInt("commercial_skipper_start_offset")
|
||||
elif (type == "Preview"):
|
||||
return settings.getSettingInt("preview_skipper_start_offset")
|
||||
elif (type == "Recap"):
|
||||
return settings.getSettingInt("recap_skipper_start_offset")
|
||||
elif (type == "Outro"):
|
||||
return settings.getSettingInt("credit_skipper_start_offset")
|
||||
elif (type == "Intro"):
|
||||
return settings.getSettingInt("intro_skipper_start_offset")
|
||||
return 0
|
||||
|
||||
def get_setting_skip_end_offset(type: Literal["Commercial", "Preview", "Recap", "Outro", "Intro"]):
|
||||
settings = xbmcaddon.Addon()
|
||||
if (type == "Commercial"):
|
||||
return settings.getSettingInt("commercial_skipper_end_offset")
|
||||
elif (type == "Preview"):
|
||||
return settings.getSettingInt("preview_skipper_end_offset")
|
||||
elif (type == "Recap"):
|
||||
return settings.getSettingInt("recap_skipper_end_offset")
|
||||
elif (type == "Outro"):
|
||||
return settings.getSettingInt("credit_skipper_end_offset")
|
||||
elif (type == "Intro"):
|
||||
return settings.getSettingInt("intro_skipper_end_offset")
|
||||
return 0
|
||||
|
||||
def set_correct_skip_info(item_id: str, skip_dialog: SkipDialog, segments, type: Literal["Commercial", "Preview", "Recap", "Outro", "Intro"]):
|
||||
if (skip_dialog.media_id is None or skip_dialog.media_id != item_id) and item_id is not None:
|
||||
# If playback item has changed (or is new), sets its id and set media segments info
|
||||
log.debug("SkipDialogInfo : Media Id has changed to {0}, setting segments".format(item_id))
|
||||
skip_dialog.media_id = item_id
|
||||
skip_dialog.has_been_dissmissed = False
|
||||
if segments is not None:
|
||||
# Find the intro and outro timings
|
||||
start = next((segment["StartTicks"] for segment in segments if segment["Type"] == type), None)
|
||||
end = next((segment["EndTicks"] for segment in segments if segment["Type"] == type), None)
|
||||
|
||||
# Sets timings with offsets if defined in settings
|
||||
if start is not None:
|
||||
skip_dialog.start = start + seconds_to_ticks(get_setting_skip_start_offset(type))
|
||||
log.debug("SkipDialogInfo : Setting {0} start to {1}".format(type, skip_dialog.start))
|
||||
if end is not None:
|
||||
skip_dialog.end = end - seconds_to_ticks(get_setting_skip_end_offset(type))
|
||||
log.debug("SkipDialogInfo : Setting {0} end to {1}".format(type, skip_dialog.end))
|
||||
|
||||
@@ -1,16 +1,18 @@
|
||||
from __future__ import division, absolute_import, print_function, unicode_literals
|
||||
from __future__ import (
|
||||
division, absolute_import, print_function, unicode_literals
|
||||
)
|
||||
|
||||
import sys
|
||||
from six.moves.urllib.parse import quote
|
||||
|
||||
from datetime import datetime
|
||||
from dateutil import tz
|
||||
|
||||
from six import ensure_text
|
||||
from six.moves.urllib.parse import quote
|
||||
import xbmcgui
|
||||
|
||||
from .utils import datetime_from_string, get_art_url, image_url, get_current_datetime
|
||||
from .utils import (
|
||||
datetime_from_string, get_art_url, image_url, get_current_datetime
|
||||
)
|
||||
from .lazylogger import LazyLogger
|
||||
from six import ensure_text
|
||||
|
||||
log = LazyLogger(__name__)
|
||||
|
||||
@@ -206,12 +208,12 @@ def extract_item_info(item, gui_options):
|
||||
media_info["height"] = mediaStream.get("Height")
|
||||
media_info["width"] = mediaStream.get("Width")
|
||||
aspect_ratio = mediaStream.get("AspectRatio")
|
||||
media_info["apect"] = aspect_ratio
|
||||
media_info["aspect"] = aspect_ratio
|
||||
if aspect_ratio and len(aspect_ratio) >= 3:
|
||||
try:
|
||||
aspect_width, aspect_height = aspect_ratio.split(':')
|
||||
media_info["apect_ratio"] = float(aspect_width) / float(aspect_height)
|
||||
except:
|
||||
except: # noqa
|
||||
media_info["apect_ratio"] = 1.85
|
||||
else:
|
||||
media_info["apect_ratio"] = 1.85
|
||||
@@ -360,9 +362,6 @@ def add_gui_item(url, item_details, display_options, folder=True, default_sort=F
|
||||
else:
|
||||
u = sys.argv[0] + "?item_id=" + url + "&mode=PLAY"
|
||||
|
||||
# Create the ListItem that will be displayed
|
||||
thumb_path = item_details.art["thumb"]
|
||||
|
||||
list_item_name = item_details.name
|
||||
item_type = item_details.item_type.lower()
|
||||
is_video = item_type not in ['musicalbum', 'audio', 'music']
|
||||
@@ -503,6 +502,8 @@ def add_gui_item(url, item_details, display_options, folder=True, default_sort=F
|
||||
mediatype = 'artist'
|
||||
elif item_type == 'audio' or item_type == 'music':
|
||||
mediatype = 'song'
|
||||
elif item_type == 'musicvideo':
|
||||
mediatype = 'musicvideo'
|
||||
|
||||
info_labels["mediatype"] = mediatype
|
||||
|
||||
@@ -570,8 +571,6 @@ def add_gui_item(url, item_details, display_options, folder=True, default_sort=F
|
||||
|
||||
item_properties["TotalSeasons"] = str(item_details.total_seasons)
|
||||
item_properties["TotalEpisodes"] = str(item_details.total_episodes)
|
||||
item_properties["WatchedEpisodes"] = str(item_details.watched_episodes)
|
||||
item_properties["UnWatchedEpisodes"] = str(item_details.unwatched_episodes)
|
||||
item_properties["NumEpisodes"] = str(item_details.number_episodes)
|
||||
|
||||
list_item.setRating("imdb", item_details.community_rating, 0, True)
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
from __future__ import division, absolute_import, print_function, unicode_literals
|
||||
from __future__ import (
|
||||
division, absolute_import, print_function, unicode_literals
|
||||
)
|
||||
|
||||
import xbmcaddon
|
||||
from kodi_six.utils import py2_decode
|
||||
import json
|
||||
|
||||
import requests
|
||||
import json
|
||||
import xbmcaddon
|
||||
from kodi_six.utils import py2_decode
|
||||
|
||||
from .utils import get_device_id, get_version, load_user_details
|
||||
from .lazylogger import LazyLogger
|
||||
@@ -25,8 +27,8 @@ class API:
|
||||
self.verify_cert = settings.getSetting('verify_cert') == 'true'
|
||||
|
||||
def get(self, path):
|
||||
if 'x-mediabrowser-token' not in self.headers:
|
||||
self.create_headers()
|
||||
if 'x-mediabrowser-token' not in self.headers or self.token not in self.headers:
|
||||
self.create_headers(True)
|
||||
|
||||
# Fixes initial login where class is initialized before wizard completes
|
||||
if not self.server:
|
||||
@@ -45,16 +47,17 @@ class API:
|
||||
and just parse the json ourselves. Fall back to using
|
||||
requests/simplejson if there's a parsing error.
|
||||
'''
|
||||
r.raise_for_status()
|
||||
response_data = json.loads(r.text)
|
||||
except ValueError:
|
||||
response_data = r.json()
|
||||
except:
|
||||
except: # noqa
|
||||
response_data = {}
|
||||
return response_data
|
||||
|
||||
def post(self, url, payload={}):
|
||||
if 'x-mediabrowser-token' not in self.headers:
|
||||
self.create_headers()
|
||||
if 'x-mediabrowser-token' not in self.headers or self.token not in self.headers:
|
||||
self.create_headers(True)
|
||||
|
||||
url = '{}{}'.format(self.server, url)
|
||||
|
||||
@@ -65,19 +68,21 @@ class API:
|
||||
response_data = json.loads(r.text)
|
||||
except ValueError:
|
||||
response_data = r.json()
|
||||
except:
|
||||
except: # noqa
|
||||
response_data = {}
|
||||
return response_data
|
||||
|
||||
def delete(self, url):
|
||||
if 'x-mediabrowser-token' not in self.headers:
|
||||
self.create_headers()
|
||||
if 'x-mediabrowser-token' not in self.headers or self.token not in self.headers:
|
||||
self.create_headers(True)
|
||||
|
||||
url = '{}{}'.format(self.server, url)
|
||||
|
||||
requests.delete(url, headers=self.headers, verify=self.verify_cert)
|
||||
|
||||
def authenticate(self, auth_data):
|
||||
# Always force create fresh headers during authentication
|
||||
self.create_headers(True)
|
||||
response = self.post('/Users/AuthenticateByName', auth_data)
|
||||
token = response.get('AccessToken')
|
||||
if token:
|
||||
@@ -90,10 +95,10 @@ class API:
|
||||
log.error('Unable to authenticate to Jellyfin server')
|
||||
return {}
|
||||
|
||||
def create_headers(self):
|
||||
def create_headers(self, force=False):
|
||||
|
||||
# If the headers already exist with an auth token, return
|
||||
if self.headers and 'x-mediabrowser-token' in self.headers:
|
||||
# If the headers already exist with an auth token, return unless we're regenerating
|
||||
if self.headers and 'x-mediabrowser-token' in self.headers and force is False:
|
||||
return
|
||||
|
||||
headers = {}
|
||||
@@ -116,8 +121,8 @@ class API:
|
||||
|
||||
headers['x-emby-authorization'] = authorization
|
||||
|
||||
# If we have a valid token, ensure it's included in the headers
|
||||
if self.token:
|
||||
# If we have a valid token, ensure it's included in the headers unless we're regenerating
|
||||
if self.token and force is False:
|
||||
headers['x-mediabrowser-token'] = self.token
|
||||
else:
|
||||
# Check for updated credentials since initialization
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
from __future__ import division, absolute_import, print_function, unicode_literals
|
||||
from __future__ import (
|
||||
division, absolute_import, print_function, unicode_literals
|
||||
)
|
||||
|
||||
import json
|
||||
|
||||
import xbmc
|
||||
|
||||
|
||||
|
||||
@@ -1,15 +1,16 @@
|
||||
from __future__ import division, absolute_import, print_function, unicode_literals
|
||||
from __future__ import (
|
||||
division, absolute_import, print_function, unicode_literals
|
||||
)
|
||||
|
||||
import sys
|
||||
|
||||
import xbmcgui
|
||||
import xbmcplugin
|
||||
import xbmcaddon
|
||||
|
||||
import sys
|
||||
|
||||
from .lazylogger import LazyLogger
|
||||
|
||||
log = LazyLogger(__name__)
|
||||
addon = xbmcaddon.Addon()
|
||||
|
||||
|
||||
class HomeWindow:
|
||||
@@ -35,11 +36,14 @@ class HomeWindow:
|
||||
self.window.clearProperty(key)
|
||||
|
||||
|
||||
def add_menu_directory_item(label, path, folder=True, art=None):
|
||||
def add_menu_directory_item(label, path, folder=True, art=None, properties=None):
|
||||
li = xbmcgui.ListItem(label, path=path, offscreen=True)
|
||||
if art is None:
|
||||
art = {}
|
||||
addon = xbmcaddon.Addon()
|
||||
art["thumb"] = addon.getAddonInfo('icon')
|
||||
if properties is not None:
|
||||
li.setProperties(properties)
|
||||
li.setArt(art)
|
||||
|
||||
xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]), url=path, listitem=li, isFolder=folder)
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import division, absolute_import, print_function, unicode_literals
|
||||
from __future__ import (
|
||||
division, absolute_import, print_function, unicode_literals
|
||||
)
|
||||
|
||||
|
||||
class LazyLogger(object):
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import division, absolute_import, print_function, unicode_literals
|
||||
|
||||
##################################################################################################
|
||||
from __future__ import (
|
||||
division, absolute_import, print_function, unicode_literals
|
||||
)
|
||||
|
||||
import os
|
||||
import logging
|
||||
@@ -13,12 +12,13 @@ from kodi_six import xbmc, xbmcaddon
|
||||
|
||||
from .utils import translate_path
|
||||
|
||||
##################################################################################################
|
||||
|
||||
__addon__ = xbmcaddon.Addon(id='plugin.video.jellycon')
|
||||
__pluginpath__ = translate_path(__addon__.getAddonInfo('path'))
|
||||
|
||||
##################################################################################################
|
||||
try:
|
||||
__addon__ = xbmcaddon.Addon(id='plugin.video.jellycon')
|
||||
__pluginpath__ = translate_path(__addon__.getAddonInfo('path'))
|
||||
except Exception:
|
||||
# During installation/update, addon might not be fully registered yet
|
||||
__addon__ = None
|
||||
__pluginpath__ = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||
|
||||
|
||||
def getLogger(name=None):
|
||||
@@ -37,25 +37,36 @@ class LogHandler(logging.StreamHandler):
|
||||
|
||||
self.sensitive = {'Token': [], 'Server': []}
|
||||
|
||||
settings = xbmcaddon.Addon()
|
||||
self.server = settings.getSetting('server_address')
|
||||
self.debug = settings.getSetting('log_debug')
|
||||
try:
|
||||
settings = xbmcaddon.Addon()
|
||||
self.server = settings.getSetting('server_address')
|
||||
self.debug = settings.getSetting('log_debug')
|
||||
except Exception:
|
||||
# During installation/update, settings might not be available yet
|
||||
self.server = ''
|
||||
self.debug = 'false'
|
||||
|
||||
def emit(self, record):
|
||||
|
||||
if self._get_log_level(record.levelno):
|
||||
string = self.format(record)
|
||||
try:
|
||||
string = self.format(record)
|
||||
|
||||
# Hide server URL in logs
|
||||
string = string.replace(self.server or "{server}", "{jellyfin-server}")
|
||||
# Hide server URL in logs
|
||||
string = string.replace(
|
||||
self.server or "{server}", "{jellyfin-server}"
|
||||
)
|
||||
|
||||
py_version = sys.version_info.major
|
||||
# Log level notation changed in Kodi v19
|
||||
if py_version > 2:
|
||||
log_level = xbmc.LOGINFO
|
||||
else:
|
||||
log_level = xbmc.LOGNOTICE
|
||||
xbmc.log(string, level=log_level)
|
||||
py_version = sys.version_info.major
|
||||
# Log level notation changed in Kodi v19
|
||||
if py_version > 2:
|
||||
log_level = xbmc.LOGINFO
|
||||
else:
|
||||
log_level = xbmc.LOGNOTICE
|
||||
xbmc.log(string, level=log_level)
|
||||
except Exception:
|
||||
# Silently fail if logging is disabled globally in Kodi
|
||||
pass
|
||||
|
||||
def _get_log_level(self, level):
|
||||
|
||||
@@ -75,12 +86,17 @@ class LogHandler(logging.StreamHandler):
|
||||
|
||||
class MyFormatter(logging.Formatter):
|
||||
|
||||
def __init__(self, fmt='%(name)s -> %(levelname)s::%(relpath)s:%(lineno)s %(message)s'):
|
||||
def __init__(
|
||||
self,
|
||||
fmt='%(name)s -> %(levelname)s::%(relpath)s:%(lineno)s %(message)s'
|
||||
):
|
||||
logging.Formatter.__init__(self, fmt)
|
||||
|
||||
def format(self, record):
|
||||
if record.pathname:
|
||||
record.pathname = ensure_text(record.pathname, get_filesystem_encoding())
|
||||
record.pathname = ensure_text(
|
||||
record.pathname, get_filesystem_encoding()
|
||||
)
|
||||
|
||||
self._gen_rel_path(record)
|
||||
|
||||
@@ -90,14 +106,20 @@ class MyFormatter(logging.Formatter):
|
||||
return result
|
||||
|
||||
def formatException(self, exc_info):
|
||||
_pluginpath_real = os.path.realpath(__pluginpath__)
|
||||
try:
|
||||
_pluginpath_real = os.path.realpath(__pluginpath__)
|
||||
except Exception:
|
||||
_pluginpath_real = None
|
||||
res = []
|
||||
|
||||
for o in traceback.format_exception(*exc_info):
|
||||
o = ensure_text(o, get_filesystem_encoding())
|
||||
|
||||
if o.startswith(' File "'):
|
||||
# If this split can't handle your file names, you should seriously consider renaming your files.
|
||||
if _pluginpath_real and o.startswith(' File "'):
|
||||
"""
|
||||
If this split can't handle your file names,
|
||||
you should seriously consider renaming your files.
|
||||
"""
|
||||
fn = o.split(' File "', 2)[1].split('", line ', 1)[0]
|
||||
rfn = os.path.realpath(fn)
|
||||
if rfn.startswith(_pluginpath_real):
|
||||
@@ -109,7 +131,10 @@ class MyFormatter(logging.Formatter):
|
||||
|
||||
def _gen_rel_path(self, record):
|
||||
if record.pathname:
|
||||
record.relpath = os.path.relpath(record.pathname, __pluginpath__)
|
||||
try:
|
||||
record.relpath = os.path.relpath(record.pathname, __pluginpath__)
|
||||
except Exception:
|
||||
record.relpath = record.pathname
|
||||
|
||||
|
||||
def get_filesystem_encoding():
|
||||
|
||||
@@ -1,20 +1,24 @@
|
||||
# coding=utf-8
|
||||
# Gnu General Public License - see LICENSE.TXT
|
||||
from __future__ import division, absolute_import, print_function, unicode_literals
|
||||
from __future__ import (
|
||||
division, absolute_import, print_function, unicode_literals
|
||||
)
|
||||
|
||||
import sys
|
||||
from six import ensure_binary, ensure_text
|
||||
from six.moves.urllib.parse import quote
|
||||
import base64
|
||||
import string
|
||||
|
||||
import xbmcplugin
|
||||
import xbmcaddon
|
||||
from six import ensure_binary, ensure_text
|
||||
from six.moves.urllib.parse import quote
|
||||
|
||||
from .dir_functions import get_content
|
||||
from .jellyfin import api
|
||||
from .kodi_utils import add_menu_directory_item, HomeWindow
|
||||
from .lazylogger import LazyLogger
|
||||
from .utils import get_jellyfin_url, translate_string, get_art_url, get_default_filters, get_current_user_id
|
||||
from .utils import (
|
||||
get_filtered_items_count_text, get_jellyfin_url, translate_string, get_art_url,
|
||||
get_default_filters, get_current_user_id
|
||||
)
|
||||
from .item_functions import get_art
|
||||
|
||||
log = LazyLogger(__name__)
|
||||
@@ -75,7 +79,7 @@ def show_movie_tags(menu_params):
|
||||
if parent_id:
|
||||
menu_params["ParentId"] = parent_id
|
||||
|
||||
item_url = get_jellyfin_url("/Users/{}/Items".format(user_id), url_params)
|
||||
item_url = get_jellyfin_url("/Users/{userid}/Items", url_params)
|
||||
|
||||
art = {"thumb": "http://localhost:24276/{}".format(ensure_text(base64.b64encode(ensure_binary(item_url))))}
|
||||
|
||||
@@ -164,7 +168,7 @@ def show_movie_years(menu_params):
|
||||
if parent_id:
|
||||
params["ParentId"] = parent_id
|
||||
|
||||
item_url = get_jellyfin_url("/Users/{}/Items".format(user_id), params)
|
||||
item_url = get_jellyfin_url("/Users/{userid}/Items", params)
|
||||
|
||||
art = {"thumb": "http://localhost:24276/{}".format(ensure_text(base64.b64encode(ensure_binary(item_url))))}
|
||||
|
||||
@@ -237,7 +241,7 @@ def show_movie_pages(menu_params):
|
||||
if parent_id:
|
||||
params["ParentId"] = parent_id
|
||||
|
||||
item_url = get_jellyfin_url("/Users/{}/Items".format(user_id), params)
|
||||
item_url = get_jellyfin_url("/Users/{userid}/Items", params)
|
||||
|
||||
page_upper = start_index + page_limit
|
||||
if page_upper > total_results:
|
||||
@@ -280,6 +284,9 @@ def show_genre_list(menu_params):
|
||||
elif item_type == 'MusicAlbum':
|
||||
jellyfin_type = 'MusicAlbum'
|
||||
kodi_type = 'albums'
|
||||
elif item_type == 'mixed':
|
||||
jellyfin_type = 'Movie,Series'
|
||||
kodi_type = 'videos'
|
||||
|
||||
params = {
|
||||
"IncludeItemTypes": jellyfin_type,
|
||||
@@ -318,12 +325,14 @@ def show_genre_list(menu_params):
|
||||
for genre in result:
|
||||
title = genre.get('Name', translate_string(30250))
|
||||
|
||||
params["GenreIds"] = genre.get("Id")
|
||||
genre_id = genre.get("Id")
|
||||
params["GenreIds"] = genre_id
|
||||
li_properties = {"id": genre_id}
|
||||
|
||||
if parent_id is not None:
|
||||
params["ParentId"] = parent_id
|
||||
|
||||
path = get_jellyfin_url("/Users/{}/Items".format(user_id), params)
|
||||
path = get_jellyfin_url("/Users/{userid}/Items", params)
|
||||
|
||||
art = {"thumb": "http://localhost:24276/{}".format(ensure_text(base64.b64encode(ensure_binary(path))))}
|
||||
|
||||
@@ -331,7 +340,7 @@ def show_genre_list(menu_params):
|
||||
"&mode=GET_CONTENT" +
|
||||
"&media_type=" + kodi_type)
|
||||
log.debug("addMenuDirectoryItem: {0} - {1} - {2}".format(title, url, art))
|
||||
add_menu_directory_item(title, url, art=art)
|
||||
add_menu_directory_item(title, url, art=art, properties=li_properties)
|
||||
|
||||
xbmcplugin.endOfDirectory(int(sys.argv[1]))
|
||||
|
||||
@@ -389,7 +398,7 @@ def show_movie_alpha_list(menu_params):
|
||||
if 'NameLessThan' in params:
|
||||
params.pop('NameLessThan')
|
||||
|
||||
path = get_jellyfin_url("/Users/{}/Items".format(user_id), params)
|
||||
path = get_jellyfin_url("/Users/{userid}/Items", params)
|
||||
|
||||
art = {"thumb": "http://localhost:24276/{}".format(ensure_text(base64.b64encode(ensure_binary(path))))}
|
||||
|
||||
@@ -409,7 +418,6 @@ def show_tvshow_alpha_list(menu_params):
|
||||
return
|
||||
|
||||
parent_id = menu_params.get("parent_id")
|
||||
user_id = get_current_user_id()
|
||||
|
||||
prefixes = '#' + string.ascii_uppercase
|
||||
|
||||
@@ -439,7 +447,7 @@ def show_tvshow_alpha_list(menu_params):
|
||||
if 'NameLessThan' in params:
|
||||
params.pop('NameLessThan')
|
||||
|
||||
path = get_jellyfin_url("/Users/{}/Items".format(user_id), params)
|
||||
path = get_jellyfin_url("/Users/{userid}/Items", params)
|
||||
|
||||
art = {"thumb": "http://localhost:24276/{}".format(ensure_text(base64.b64encode(ensure_binary(path))))}
|
||||
|
||||
@@ -451,6 +459,55 @@ def show_tvshow_alpha_list(menu_params):
|
||||
xbmcplugin.endOfDirectory(int(sys.argv[1]))
|
||||
|
||||
|
||||
def show_mixed_alpha_list(menu_params):
|
||||
log.debug("== ENTER: showTvShowAlphaList() ==")
|
||||
|
||||
server = settings.getSetting('server_address')
|
||||
if server is None:
|
||||
return
|
||||
|
||||
parent_id = menu_params.get("parent_id")
|
||||
|
||||
prefixes = '#' + string.ascii_uppercase
|
||||
|
||||
params = {
|
||||
"Fields": get_default_filters(),
|
||||
"ImageTypeLimit": 1,
|
||||
"IncludeItemTypes": "Series,Movie",
|
||||
"SortBy": "Name",
|
||||
"SortOrder": "Ascending",
|
||||
"Recursive": True,
|
||||
"IsMissing": False
|
||||
}
|
||||
|
||||
for alpha_name in prefixes:
|
||||
|
||||
if parent_id is not None:
|
||||
params["ParentId"] = parent_id
|
||||
|
||||
if alpha_name == "#":
|
||||
params["NameLessThan"] = "A"
|
||||
# Ensure we don't try to search both at once
|
||||
if 'NameStartsWith' in params:
|
||||
params.pop('NameStartsWith')
|
||||
else:
|
||||
params["NameStartsWith"] = alpha_name
|
||||
# Ensure we don't try to search both at once
|
||||
if 'NameLessThan' in params:
|
||||
params.pop('NameLessThan')
|
||||
|
||||
path = get_jellyfin_url("/Users/{userid}/Items", params)
|
||||
|
||||
art = {"thumb": "http://localhost:24276/{}".format(ensure_text(base64.b64encode(ensure_binary(path))))}
|
||||
|
||||
url = (sys.argv[0] + "?url=" + quote(path) +
|
||||
"&mode=GET_CONTENT&media_type=mixed")
|
||||
log.debug("addMenuDirectoryItem: {0} ({1})".format(alpha_name, url))
|
||||
add_menu_directory_item(alpha_name, url, art=art)
|
||||
|
||||
xbmcplugin.endOfDirectory(int(sys.argv[1]))
|
||||
|
||||
|
||||
def show_artist_alpha_list(menu_params):
|
||||
log.debug("== ENTER: showArtistAlphaList() ==")
|
||||
|
||||
@@ -501,7 +558,7 @@ def show_artist_alpha_list(menu_params):
|
||||
if 'NameLessThan' in params:
|
||||
params.pop('NameLessThan')
|
||||
|
||||
path = get_jellyfin_url("/Users/{}/Items".format(user_id), params)
|
||||
path = get_jellyfin_url("/Users/{userid}/Items", params)
|
||||
|
||||
art = {"thumb": "http://localhost:24276/{}".format(ensure_text(base64.b64encode(ensure_binary(path))))}
|
||||
|
||||
@@ -517,6 +574,10 @@ def display_main_menu():
|
||||
handle = int(sys.argv[1])
|
||||
xbmcplugin.setContent(handle, 'files')
|
||||
|
||||
if settings.getSetting("interface_mode") == "1":
|
||||
display_library_views(None)
|
||||
return
|
||||
|
||||
add_menu_directory_item(translate_string(30406),
|
||||
"plugin://plugin.video.jellycon/?mode=SHOW_ADDON_MENU&type=library")
|
||||
add_menu_directory_item(translate_string(30407),
|
||||
@@ -554,6 +615,16 @@ def display_menu(params):
|
||||
def show_global_types(params):
|
||||
handle = int(sys.argv[1])
|
||||
|
||||
continue_watching_url_params = {
|
||||
"Fields": get_default_filters(),
|
||||
"ImageTypeLimit": 1,
|
||||
}
|
||||
continue_watching_url = get_jellyfin_url("/Users/{userid}/Items/Resume", continue_watching_url_params)
|
||||
add_menu_directory_item(translate_string(30445),
|
||||
"plugin://plugin.video.jellycon/?mode=GET_CONTENT&url=" + quote(continue_watching_url) +
|
||||
"&media_type=movies" +
|
||||
"&name_format="+quote("Episode|episode_name_format"))
|
||||
|
||||
add_menu_directory_item(translate_string(30256),
|
||||
"plugin://plugin.video.jellycon/?mode=SHOW_ADDON_MENU&type=global_list_movies")
|
||||
add_menu_directory_item(translate_string(30261),
|
||||
@@ -567,7 +638,6 @@ def display_homevideos_type(menu_params, view):
|
||||
view_name = view.get("Name")
|
||||
item_limit = settings.getSetting("show_x_filtered_items")
|
||||
hide_watched = settings.getSetting("hide_watched") == "true"
|
||||
user_id = get_current_user_id()
|
||||
|
||||
# All Home Movies
|
||||
base_params = {
|
||||
@@ -577,7 +647,7 @@ def display_homevideos_type(menu_params, view):
|
||||
"Fields": get_default_filters(),
|
||||
"ImageTypeLimit": 1
|
||||
}
|
||||
path = get_jellyfin_url("/Users/{}/Items".format(user_id), base_params)
|
||||
path = get_jellyfin_url("/Users/{userid}/Items", base_params)
|
||||
url = sys.argv[0] + "?url=" + quote(path) + "&mode=GET_CONTENT&media_type=homevideos"
|
||||
add_menu_directory_item(view_name + translate_string(30405), url)
|
||||
|
||||
@@ -587,9 +657,9 @@ def display_homevideos_type(menu_params, view):
|
||||
params["Filters"] = "IsResumable"
|
||||
params["Recursive"] = True
|
||||
params["Limit"] = item_limit
|
||||
path = get_jellyfin_url("/Users/{}/Items".format(user_id), params)
|
||||
path = get_jellyfin_url("/Users/{userid}/Items", params)
|
||||
url = sys.argv[0] + "?url=" + quote(path) + "&mode=GET_CONTENT&media_type=homevideos"
|
||||
add_menu_directory_item(view_name + translate_string(30267) + " (" + item_limit + ")", url)
|
||||
add_menu_directory_item(view_name + translate_string(30267) + get_filtered_items_count_text(), url)
|
||||
|
||||
# Recently added
|
||||
params = {}
|
||||
@@ -601,9 +671,9 @@ def display_homevideos_type(menu_params, view):
|
||||
if hide_watched:
|
||||
params["IsPlayed"] = False
|
||||
params["Limit"] = item_limit
|
||||
path = get_jellyfin_url("/Users/{}/Items".format(user_id), params)
|
||||
path = get_jellyfin_url("/Users/{userid}/Items", params)
|
||||
url = sys.argv[0] + "?url=" + quote(path) + "&mode=GET_CONTENT&media_type=homevideos"
|
||||
add_menu_directory_item(view_name + translate_string(30268) + " (" + item_limit + ")", url)
|
||||
add_menu_directory_item(view_name + translate_string(30268) + get_filtered_items_count_text(), url)
|
||||
|
||||
xbmcplugin.endOfDirectory(handle)
|
||||
|
||||
@@ -632,7 +702,6 @@ def display_tvshow_type(menu_params, view):
|
||||
view_name = view.get("Name")
|
||||
|
||||
item_limit = settings.getSetting("show_x_filtered_items")
|
||||
user_id = get_current_user_id()
|
||||
|
||||
# All TV Shows
|
||||
base_params = {
|
||||
@@ -644,7 +713,12 @@ def display_tvshow_type(menu_params, view):
|
||||
}
|
||||
if view is not None:
|
||||
base_params["ParentId"] = view.get("Id")
|
||||
path = get_jellyfin_url("/Users/{}/Items".format(user_id), base_params)
|
||||
path = get_jellyfin_url("/Users/{userid}/Items", base_params)
|
||||
|
||||
if settings.getSetting("interface_mode") == "1":
|
||||
get_content(path, { "media_type": "tvshows" })
|
||||
return
|
||||
|
||||
url = sys.argv[0] + "?url=" + quote(path) + "&mode=GET_CONTENT&media_type=tvshows"
|
||||
add_menu_directory_item(view_name + translate_string(30405), url)
|
||||
|
||||
@@ -652,7 +726,7 @@ def display_tvshow_type(menu_params, view):
|
||||
params = {}
|
||||
params.update(base_params)
|
||||
params["Filters"] = "IsFavorite"
|
||||
path = get_jellyfin_url("/Users/{}/Items".format(user_id), params)
|
||||
path = get_jellyfin_url("/Users/{userid}/Items", params)
|
||||
url = sys.argv[0] + "?url=" + quote(path) + "&mode=GET_CONTENT&media_type=tvshows"
|
||||
add_menu_directory_item(view_name + translate_string(30414), url)
|
||||
|
||||
@@ -660,10 +734,18 @@ def display_tvshow_type(menu_params, view):
|
||||
params = {}
|
||||
params.update(base_params)
|
||||
params["IsPlayed"] = False
|
||||
path = get_jellyfin_url("/Users/{}/Items".format(user_id), params)
|
||||
path = get_jellyfin_url("/Users/{userid}/Items", params)
|
||||
url = sys.argv[0] + "?url=" + quote(path) + "&mode=GET_CONTENT&media_type=tvshows"
|
||||
add_menu_directory_item(view_name + translate_string(30285), url)
|
||||
|
||||
# Totally unwatched tv shows
|
||||
params = {}
|
||||
params.update(base_params)
|
||||
params["IsPlayed"] = False
|
||||
path = get_jellyfin_url("/Users/{userid}/Items", params)
|
||||
url = sys.argv[0] + "?url=" + quote(path) + "&mode=GET_CONTENT&media_type=tvshows&OnlyTotallyUnwatchedTvShow=1"
|
||||
add_menu_directory_item(view_name + translate_string(30454), url)
|
||||
|
||||
# In progress episodes
|
||||
params = {}
|
||||
params.update(base_params)
|
||||
@@ -672,10 +754,10 @@ def display_tvshow_type(menu_params, view):
|
||||
params["SortOrder"] = "Descending"
|
||||
params["Filters"] = "IsResumable"
|
||||
params["IncludeItemTypes"] = "Episode"
|
||||
path = get_jellyfin_url("/Users/{}/Items".format(user_id), params)
|
||||
path = get_jellyfin_url("/Users/{userid}/Items", params)
|
||||
url = sys.argv[0] + "?url=" + quote(path) + "&mode=GET_CONTENT&media_type=Episodes&sort=none"
|
||||
url += "&name_format=" + quote('Episode|episode_name_format')
|
||||
add_menu_directory_item(view_name + translate_string(30267) + " (" + item_limit + ")", url)
|
||||
add_menu_directory_item(view_name + translate_string(30267) + get_filtered_items_count_text(), url)
|
||||
|
||||
# Latest Episodes
|
||||
params = {}
|
||||
@@ -684,9 +766,9 @@ def display_tvshow_type(menu_params, view):
|
||||
params["SortBy"] = "DateCreated"
|
||||
params["SortOrder"] = "Descending"
|
||||
params["IncludeItemTypes"] = "Episode"
|
||||
path = get_jellyfin_url("/Users/{}/Items/Latest".format(user_id), params)
|
||||
path = get_jellyfin_url("/Users/{userid}/Items/Latest", params)
|
||||
url = sys.argv[0] + "?url=" + quote(path) + "&mode=GET_CONTENT&media_type=tvshows&sort=none"
|
||||
add_menu_directory_item(view_name + translate_string(30288) + " (" + item_limit + ")", url)
|
||||
add_menu_directory_item(view_name + translate_string(30288) + get_filtered_items_count_text(), url)
|
||||
|
||||
# Recently Added
|
||||
params = {}
|
||||
@@ -696,16 +778,16 @@ def display_tvshow_type(menu_params, view):
|
||||
params["SortOrder"] = "Descending"
|
||||
params["Filters"] = "IsNotFolder"
|
||||
params["IncludeItemTypes"] = "Episode"
|
||||
path = get_jellyfin_url("/Users/{}/Items".format(user_id), params)
|
||||
path = get_jellyfin_url("/Users/{userid}/Items", params)
|
||||
url = sys.argv[0] + "?url=" + quote(path) + "&mode=GET_CONTENT&media_type=Episodes&sort=none"
|
||||
url += "&name_format=" + quote('Episode|episode_name_format')
|
||||
add_menu_directory_item(view_name + translate_string(30268) + " (" + item_limit + ")", url)
|
||||
add_menu_directory_item(view_name + translate_string(30268) + get_filtered_items_count_text(), url)
|
||||
|
||||
# Next Up Episodes
|
||||
params = {}
|
||||
params.update(base_params)
|
||||
params["Limit"] = item_limit
|
||||
params["Userid"] = user_id
|
||||
params["Userid"] = '{userid}'
|
||||
params["SortBy"] = "DateCreated"
|
||||
params["SortOrder"] = "Descending"
|
||||
params["Filters"] = "IsNotFolder"
|
||||
@@ -713,7 +795,7 @@ def display_tvshow_type(menu_params, view):
|
||||
path = get_jellyfin_url("/Shows/NextUp", params)
|
||||
url = sys.argv[0] + "?url=" + quote(path) + "&mode=GET_CONTENT&media_type=Episodes&sort=none"
|
||||
url += "&name_format=" + quote('Episode|episode_name_format')
|
||||
add_menu_directory_item(view_name + translate_string(30278) + " (" + item_limit + ")", url)
|
||||
add_menu_directory_item(view_name + translate_string(30278) + get_filtered_items_count_text(), url)
|
||||
|
||||
# TV Show Genres
|
||||
path = "plugin://plugin.video.jellycon/?mode=GENRES&item_type=tvshow"
|
||||
@@ -735,7 +817,6 @@ def display_music_type(menu_params, view):
|
||||
view_name = view.get("Name")
|
||||
|
||||
item_limit = settings.getSetting("show_x_filtered_items")
|
||||
user_id = get_current_user_id()
|
||||
|
||||
# all albums
|
||||
params = {
|
||||
@@ -744,7 +825,12 @@ def display_music_type(menu_params, view):
|
||||
"ImageTypeLimit": 1,
|
||||
"IncludeItemTypes": "MusicAlbum"
|
||||
}
|
||||
path = get_jellyfin_url("/Users/{}/Items".format(user_id), params)
|
||||
path = get_jellyfin_url("/Users/{userid}/Items", params)
|
||||
|
||||
if settings.getSetting("interface_mode") == "1":
|
||||
get_content(path, { "media_type": "MusicAlbums" })
|
||||
return
|
||||
|
||||
url = sys.argv[0] + "?url=" + quote(path) + "&mode=GET_CONTENT&media_type=MusicAlbums"
|
||||
add_menu_directory_item(view_name + translate_string(30320), url)
|
||||
|
||||
@@ -755,9 +841,9 @@ def display_music_type(menu_params, view):
|
||||
"IncludeItemTypes": "Audio",
|
||||
"Limit": item_limit
|
||||
}
|
||||
path = get_jellyfin_url("/Users/{}/Items/Latest".format(user_id), params)
|
||||
path = get_jellyfin_url("/Users/{userid}/Items/Latest", params)
|
||||
url = sys.argv[0] + "?url=" + quote(path) + "&mode=GET_CONTENT&media_type=MusicAlbums"
|
||||
add_menu_directory_item(view_name + translate_string(30268) + " (" + item_limit + ")", url)
|
||||
add_menu_directory_item(view_name + translate_string(30268) + get_filtered_items_count_text(), url)
|
||||
|
||||
# recently played
|
||||
params = {
|
||||
@@ -770,9 +856,9 @@ def display_music_type(menu_params, view):
|
||||
"SortBy": "DatePlayed",
|
||||
"SortOrder": "Descending"
|
||||
}
|
||||
path = get_jellyfin_url("/Users/{}/Items".format(user_id), params)
|
||||
path = get_jellyfin_url("/Users/{userid}/Items", params)
|
||||
url = sys.argv[0] + "?url=" + quote(path) + "&mode=GET_CONTENT&media_type=MusicAlbum"
|
||||
add_menu_directory_item(view_name + translate_string(30349) + " (" + item_limit + ")", url)
|
||||
add_menu_directory_item(view_name + translate_string(30349) + get_filtered_items_count_text(), url)
|
||||
|
||||
# most played
|
||||
params = {
|
||||
@@ -785,9 +871,9 @@ def display_music_type(menu_params, view):
|
||||
"SortBy": "PlayCount",
|
||||
"SortOrder": "Descending"
|
||||
}
|
||||
path = get_jellyfin_url("/Users/{}/Items".format(user_id), params)
|
||||
path = get_jellyfin_url("/Users/{userid}/Items", params)
|
||||
url = sys.argv[0] + "?url=" + quote(path) + "&mode=GET_CONTENT&media_type=MusicAlbum"
|
||||
add_menu_directory_item(view_name + translate_string(30353) + " (" + item_limit + ")", url)
|
||||
add_menu_directory_item(view_name + translate_string(30353) + get_filtered_items_count_text(), url)
|
||||
|
||||
# artists
|
||||
params = {
|
||||
@@ -812,6 +898,13 @@ def display_music_type(menu_params, view):
|
||||
add_menu_directory_item('{} - {}{}'.format(
|
||||
view_name, translate_string(30323), translate_string(30404)), path)
|
||||
|
||||
# Shuffle All
|
||||
path = "plugin://plugin.video.jellycon/?mode=PLAY&action=shuffle"
|
||||
if view is not None:
|
||||
path += "&item_id=" + view.get("Id")
|
||||
add_menu_directory_item('{} - {}'.format(
|
||||
view_name, translate_string(30448)), path, False)
|
||||
|
||||
xbmcplugin.endOfDirectory(handle)
|
||||
|
||||
|
||||
@@ -820,7 +913,6 @@ def display_musicvideos_type(params, view):
|
||||
xbmcplugin.setContent(handle, 'files')
|
||||
|
||||
view_name = view.get("Name")
|
||||
user_id = get_current_user_id()
|
||||
|
||||
# artists
|
||||
params = {
|
||||
@@ -830,7 +922,7 @@ def display_musicvideos_type(params, view):
|
||||
"IsMissing": False,
|
||||
"Fields": get_default_filters()
|
||||
}
|
||||
path = get_jellyfin_url("/Users/{}/Items".format(user_id), params)
|
||||
path = get_jellyfin_url("/Users/{userid}/Items", params)
|
||||
url = sys.argv[0] + "?url=" + quote(path) + "&mode=GET_CONTENT&media_type=musicvideos"
|
||||
add_menu_directory_item(view_name + translate_string(30405), url)
|
||||
|
||||
@@ -842,11 +934,10 @@ def display_livetv_type(menu_params, view):
|
||||
xbmcplugin.setContent(handle, 'files')
|
||||
|
||||
view_name = view.get("Name")
|
||||
user_id = get_current_user_id()
|
||||
|
||||
# channels
|
||||
params = {
|
||||
"UserId": user_id,
|
||||
"UserId": '{userid}',
|
||||
"Recursive": False,
|
||||
"ImageTypeLimit": 1,
|
||||
"Fields": get_default_filters()
|
||||
@@ -857,7 +948,7 @@ def display_livetv_type(menu_params, view):
|
||||
|
||||
# programs
|
||||
params = {
|
||||
"UserId": user_id,
|
||||
"UserId": '{userid}',
|
||||
"IsAiring": True,
|
||||
"ImageTypeLimit": 1,
|
||||
"Fields": get_default_filters() + ",ChannelInfo",
|
||||
@@ -869,7 +960,7 @@ def display_livetv_type(menu_params, view):
|
||||
|
||||
# recordings
|
||||
params = {
|
||||
"UserId": user_id,
|
||||
"UserId": '{userid}',
|
||||
"Recursive": False,
|
||||
"ImageTypeLimit": 1,
|
||||
"Fields": get_default_filters(),
|
||||
@@ -893,7 +984,6 @@ def display_movies_type(menu_params, view):
|
||||
item_limit = settings.getSetting("show_x_filtered_items")
|
||||
group_movies = settings.getSetting('group_movies') == "true"
|
||||
hide_watched = settings.getSetting("hide_watched") == "true"
|
||||
user_id = get_current_user_id()
|
||||
|
||||
base_params = {
|
||||
"IncludeItemTypes": "Movie",
|
||||
@@ -908,7 +998,12 @@ def display_movies_type(menu_params, view):
|
||||
base_params["ParentId"] = view.get("Id")
|
||||
|
||||
# All Movies
|
||||
path = get_jellyfin_url("/Users/{}/Items".format(user_id), base_params)
|
||||
path = get_jellyfin_url("/Users/{userid}/Items", base_params)
|
||||
|
||||
if settings.getSetting("interface_mode") == "1":
|
||||
get_content(path, { "media_type": "movies" })
|
||||
return
|
||||
|
||||
url = sys.argv[0] + "?url=" + quote(path) + "&mode=GET_CONTENT&media_type=movies"
|
||||
add_menu_directory_item('{}{}'.format(view_name, translate_string(30405)), url)
|
||||
|
||||
@@ -918,7 +1013,7 @@ def display_movies_type(menu_params, view):
|
||||
params["CollapseBoxSetItems"] = False
|
||||
params["GroupItemsIntoCollections"] = False
|
||||
params["Filters"] = "IsFavorite"
|
||||
path = get_jellyfin_url("/Users/{}/Items".format(user_id), params)
|
||||
path = get_jellyfin_url("/Users/{userid}/Items", params)
|
||||
url = sys.argv[0] + "?url=" + quote(path) + "&mode=GET_CONTENT&media_type=movies"
|
||||
add_menu_directory_item('{}{}'.format(view_name, translate_string(30414)), url)
|
||||
|
||||
@@ -928,7 +1023,7 @@ def display_movies_type(menu_params, view):
|
||||
params["CollapseBoxSetItems"] = False
|
||||
params["GroupItemsIntoCollections"] = False
|
||||
params["IsPlayed"] = False
|
||||
path = get_jellyfin_url("/Users/{}/Items".format(user_id), params)
|
||||
path = get_jellyfin_url("/Users/{userid}/Items", params)
|
||||
url = sys.argv[0] + "?url=" + quote(path) + "&mode=GET_CONTENT&media_type=movies"
|
||||
add_menu_directory_item('{}{}'.format(view_name, translate_string(30285)), url)
|
||||
|
||||
@@ -941,9 +1036,9 @@ def display_movies_type(menu_params, view):
|
||||
params["CollapseBoxSetItems"] = False
|
||||
params["GroupItemsIntoCollections"] = False
|
||||
params["Limit"] = item_limit
|
||||
path = get_jellyfin_url("/Users/{}/Items".format(user_id), params)
|
||||
path = get_jellyfin_url("/Users/{userid}/Items", params)
|
||||
url = sys.argv[0] + "?url=" + quote(path) + "&mode=GET_CONTENT&media_type=movies&sort=none"
|
||||
add_menu_directory_item('{}{} ({})'.format(view_name, translate_string(30349), item_limit), url)
|
||||
add_menu_directory_item(('{}{}{}').format(view_name, translate_string(30349), get_filtered_items_count_text()), url)
|
||||
|
||||
# Resumable Movies
|
||||
params = {}
|
||||
@@ -952,9 +1047,9 @@ def display_movies_type(menu_params, view):
|
||||
params["SortBy"] = "DatePlayed"
|
||||
params["SortOrder"] = "Descending"
|
||||
params["Limit"] = item_limit
|
||||
path = get_jellyfin_url("/Users/{}/Items".format(user_id), params)
|
||||
path = get_jellyfin_url("/Users/{userid}/Items", params)
|
||||
url = sys.argv[0] + "?url=" + quote(path) + "&mode=GET_CONTENT&media_type=movies&sort=none"
|
||||
add_menu_directory_item('{}{} ({})'.format(view_name, translate_string(30267), item_limit), url)
|
||||
add_menu_directory_item(('{}{}{}').format(view_name, translate_string(30267), get_filtered_items_count_text()), url)
|
||||
|
||||
# Recently Added Movies
|
||||
params = {}
|
||||
@@ -964,9 +1059,10 @@ def display_movies_type(menu_params, view):
|
||||
params["SortBy"] = "DateCreated"
|
||||
params["SortOrder"] = "Descending"
|
||||
params["Filters"] = "IsNotFolder"
|
||||
path = get_jellyfin_url("/Users/{}/Items".format(user_id), params)
|
||||
params["Limit"] = item_limit
|
||||
path = get_jellyfin_url("/Users/{userid}/Items", params)
|
||||
url = sys.argv[0] + "?url=" + quote(path) + "&mode=GET_CONTENT&media_type=movies&sort=none"
|
||||
add_menu_directory_item('{}{} ({})'.format(view_name, translate_string(30268), item_limit), url)
|
||||
add_menu_directory_item(('{}{}{}').format(view_name, translate_string(30268), get_filtered_items_count_text()), url)
|
||||
|
||||
# Collections
|
||||
params = {}
|
||||
@@ -976,13 +1072,13 @@ def display_movies_type(menu_params, view):
|
||||
params["ImageTypeLimit"] = 1
|
||||
params["IncludeItemTypes"] = "Boxset"
|
||||
params["Recursive"] = True
|
||||
path = get_jellyfin_url("/Users/{}/Items".format(user_id), params)
|
||||
path = get_jellyfin_url("/Users/{userid}/Items", params)
|
||||
url = sys.argv[0] + "?url=" + quote(path) + "&mode=GET_CONTENT&media_type=boxsets"
|
||||
add_menu_directory_item('{}{}'.format(view_name, translate_string(30410)), url)
|
||||
|
||||
# Favorite Collections
|
||||
params["Filters"] = "IsFavorite"
|
||||
path = get_jellyfin_url("/Users/{}/Items".format(user_id), params)
|
||||
path = get_jellyfin_url("/Users/{userid}/Items", params)
|
||||
url = sys.argv[0] + "?url=" + quote(path) + "&mode=GET_CONTENT&media_type=boxsets"
|
||||
add_menu_directory_item('{}{}'.format(view_name, translate_string(30415)), url)
|
||||
|
||||
@@ -1025,6 +1121,116 @@ def display_movies_type(menu_params, view):
|
||||
xbmcplugin.endOfDirectory(handle)
|
||||
|
||||
|
||||
def display_mixed_type(params, view):
|
||||
handle = int(sys.argv[1])
|
||||
|
||||
view_name = translate_string(30261)
|
||||
if view is not None:
|
||||
view_name = view.get("Name")
|
||||
|
||||
item_limit = settings.getSetting("show_x_filtered_items")
|
||||
|
||||
# All Mixed content
|
||||
base_params = {
|
||||
"Fields": get_default_filters(),
|
||||
"ImageTypeLimit": 1,
|
||||
"IsMissing": False,
|
||||
"IncludeItemTypes": "Series,Movie",
|
||||
"Recursive": True
|
||||
}
|
||||
if view is not None:
|
||||
base_params["ParentId"] = view.get("Id")
|
||||
path = get_jellyfin_url("/Users/{userid}/Items", base_params)
|
||||
|
||||
if settings.getSetting("interface_mode") == "1":
|
||||
get_content(path, { "media_type": "mixed" })
|
||||
return
|
||||
|
||||
url = sys.argv[0] + "?url=" + quote(path) + "&mode=GET_CONTENT&media_type=mixed"
|
||||
add_menu_directory_item(view_name + translate_string(30405), url)
|
||||
|
||||
# Favorite Mixed
|
||||
params = {}
|
||||
params.update(base_params)
|
||||
params["Filters"] = "IsFavorite"
|
||||
path = get_jellyfin_url("/Users/{userid}/Items", params)
|
||||
url = sys.argv[0] + "?url=" + quote(path) + "&mode=GET_CONTENT&media_type=mixed"
|
||||
add_menu_directory_item(view_name + translate_string(30414), url)
|
||||
|
||||
# Unplayed Mixed
|
||||
params = {}
|
||||
params.update(base_params)
|
||||
params["IsPlayed"] = False
|
||||
path = get_jellyfin_url("/Users/{userid}/Items", params)
|
||||
url = sys.argv[0] + "?url=" + quote(path) + "&mode=GET_CONTENT&media_type=mixed"
|
||||
add_menu_directory_item(view_name + translate_string(30285), url)
|
||||
|
||||
# In progress mixed
|
||||
params = {}
|
||||
params.update(base_params)
|
||||
params["Limit"] = item_limit
|
||||
params["SortBy"] = "DatePlayed"
|
||||
params["SortOrder"] = "Descending"
|
||||
params["Filters"] = "IsResumable"
|
||||
params["IncludeItemTypes"] = "Episode"
|
||||
path = get_jellyfin_url("/Users/{userid}/Items", params)
|
||||
url = sys.argv[0] + "?url=" + quote(path) + "&mode=GET_CONTENT&media_type=mixed&sort=none"
|
||||
url += "&name_format=" + quote('Episode|episode_name_format')
|
||||
add_menu_directory_item(view_name + translate_string(30267) + get_filtered_items_count_text(), url)
|
||||
|
||||
# Latest mixed
|
||||
params = {}
|
||||
params.update(base_params)
|
||||
params["Limit"] = item_limit
|
||||
params["SortBy"] = "DateCreated"
|
||||
params["SortOrder"] = "Descending"
|
||||
params["IncludeItemTypes"] = "Episode"
|
||||
path = get_jellyfin_url("/Users/{userid}/Items/Latest", params)
|
||||
url = sys.argv[0] + "?url=" + quote(path) + "&mode=GET_CONTENT&media_type=mixed&sort=none"
|
||||
add_menu_directory_item(view_name + translate_string(30288) + get_filtered_items_count_text(), url)
|
||||
|
||||
# Recently Added
|
||||
params = {}
|
||||
params.update(base_params)
|
||||
params["Limit"] = item_limit
|
||||
params["SortBy"] = "DateCreated"
|
||||
params["SortOrder"] = "Descending"
|
||||
params["Filters"] = "IsNotFolder"
|
||||
params["IncludeItemTypes"] = "Episode"
|
||||
path = get_jellyfin_url("/Users/{userid}/Items", params)
|
||||
url = sys.argv[0] + "?url=" + quote(path) + "&mode=GET_CONTENT&media_type=mixed&sort=none"
|
||||
url += "&name_format=" + quote('Episode|episode_name_format')
|
||||
add_menu_directory_item(view_name + translate_string(30268) + get_filtered_items_count_text(), url)
|
||||
|
||||
# Next Up Episodes
|
||||
params = {}
|
||||
params.update(base_params)
|
||||
params["Limit"] = item_limit
|
||||
params["Userid"] = '{userid}'
|
||||
params["SortBy"] = "DateCreated"
|
||||
params["SortOrder"] = "Descending"
|
||||
params["Filters"] = "IsNotFolder"
|
||||
params["IncludeItemTypes"] = "Episode"
|
||||
path = get_jellyfin_url("/Shows/NextUp", params)
|
||||
url = sys.argv[0] + "?url=" + quote(path) + "&mode=GET_CONTENT&media_type=Episodes&sort=none"
|
||||
url += "&name_format=" + quote('Episode|episode_name_format')
|
||||
add_menu_directory_item(view_name + translate_string(30278) + get_filtered_items_count_text(), url)
|
||||
|
||||
# Mixed Genres
|
||||
path = "plugin://plugin.video.jellycon/?mode=GENRES&item_type=mixed"
|
||||
if view is not None:
|
||||
path += "&parent_id=" + view.get("Id")
|
||||
add_menu_directory_item(view_name + translate_string(30325), path)
|
||||
|
||||
# Mixed Alpha picker
|
||||
path = "plugin://plugin.video.jellycon/?mode=TVSHOW_ALPHA"
|
||||
if view is not None:
|
||||
path += "&parent_id=" + view.get("Id")
|
||||
add_menu_directory_item(view_name + translate_string(30404), path)
|
||||
|
||||
xbmcplugin.endOfDirectory(handle)
|
||||
|
||||
|
||||
def display_library_views(params):
|
||||
handle = int(sys.argv[1])
|
||||
xbmcplugin.setContent(handle, 'files')
|
||||
@@ -1040,10 +1246,10 @@ def display_library_views(params):
|
||||
return []
|
||||
views = views.get("Items", [])
|
||||
|
||||
view_types = ["movies", "tvshows", "homevideos", "boxsets", "playlists", "music", "musicvideos", "livetv", "Channel"]
|
||||
view_types = ["movies", "tvshows", "homevideos", "boxsets", "playlists", "music", "musicvideos", "livetv", "Channel", "mixed"]
|
||||
|
||||
for view in views:
|
||||
collection_type = view.get('CollectionType', None)
|
||||
collection_type = view.get('CollectionType', 'mixed')
|
||||
item_type = view.get('Type', None)
|
||||
if collection_type in view_types or item_type == "Channel":
|
||||
view_name = view.get("Name")
|
||||
@@ -1070,9 +1276,8 @@ def get_playlist_path(view_info):
|
||||
"Fields": get_default_filters(),
|
||||
"ImageTypeLimit": 1
|
||||
}
|
||||
user_id = get_current_user_id()
|
||||
|
||||
path = get_jellyfin_url("/Users/{}/Items".format(user_id), params)
|
||||
path = get_jellyfin_url("/Users/{userid}/Items", params)
|
||||
url = sys.argv[0] + "?url=" + quote(path) + "&mode=GET_CONTENT&media_type=playlists"
|
||||
return url
|
||||
|
||||
@@ -1088,9 +1293,8 @@ def get_collection_path(view_info):
|
||||
"Recursive": True,
|
||||
"IsMissing": False
|
||||
}
|
||||
user_id = get_current_user_id()
|
||||
|
||||
path = get_jellyfin_url("/Users/{}/Items".format(user_id), params)
|
||||
path = get_jellyfin_url("/Users/{userid}/Items", params)
|
||||
url = sys.argv[0] + "?url=" + quote(path) + "&mode=GET_CONTENT&media_type=boxsets"
|
||||
return url
|
||||
|
||||
@@ -1102,9 +1306,8 @@ def get_channel_path(view):
|
||||
"ImageTypeLimit": 1,
|
||||
"Fields": get_default_filters()
|
||||
}
|
||||
user_id = get_current_user_id()
|
||||
|
||||
path = get_jellyfin_url("/Users/{}/Items".format(user_id), params)
|
||||
path = get_jellyfin_url("/Users/{userid}/Items", params)
|
||||
url = sys.argv[0] + "?url=" + quote(path) + "&mode=GET_CONTENT&media_type=files"
|
||||
return url
|
||||
|
||||
@@ -1118,7 +1321,7 @@ def display_library_view(params):
|
||||
|
||||
log.debug("VIEW_INFO : {0}".format(view_info))
|
||||
|
||||
collection_type = view_info.get("CollectionType", None)
|
||||
collection_type = view_info.get("CollectionType", "mixed")
|
||||
|
||||
if collection_type == "movies":
|
||||
display_movies_type(params, view_info)
|
||||
@@ -1132,31 +1335,41 @@ def display_library_view(params):
|
||||
display_musicvideos_type(params, view_info)
|
||||
elif collection_type == "livetv":
|
||||
display_livetv_type(params, view_info)
|
||||
elif collection_type == "mixed":
|
||||
display_mixed_type(params, view_info)
|
||||
|
||||
|
||||
def show_widgets():
|
||||
item_limit = settings.getSetting("show_x_filtered_items")
|
||||
|
||||
def show_widgets():
|
||||
add_menu_directory_item("All Movies",
|
||||
'plugin://plugin.video.jellycon/library/movies')
|
||||
|
||||
item_limit_text = get_filtered_items_count_text()
|
||||
|
||||
add_menu_directory_item(translate_string(30257) + " (" + item_limit + ")",
|
||||
add_menu_directory_item(translate_string(30257) + item_limit_text,
|
||||
'plugin://plugin.video.jellycon/?mode=WIDGET_CONTENT&type=recent_movies')
|
||||
add_menu_directory_item(translate_string(30258) + " (" + item_limit + ")",
|
||||
add_menu_directory_item(translate_string(30258) + item_limit_text,
|
||||
'plugin://plugin.video.jellycon/?mode=WIDGET_CONTENT&type=inprogress_movies')
|
||||
add_menu_directory_item(translate_string(30269) + " (" + item_limit + ")",
|
||||
add_menu_directory_item(translate_string(30269) + item_limit_text,
|
||||
'plugin://plugin.video.jellycon/?mode=WIDGET_CONTENT&type=random_movies')
|
||||
add_menu_directory_item(translate_string(30403) + " (" + item_limit + ")",
|
||||
add_menu_directory_item(translate_string(30403) + item_limit_text,
|
||||
'plugin://plugin.video.jellycon/?mode=WIDGET_CONTENT&type=movie_recommendations')
|
||||
|
||||
add_menu_directory_item(translate_string(30287) + " (" + item_limit + ")",
|
||||
add_menu_directory_item(translate_string(30287) + item_limit_text,
|
||||
'plugin://plugin.video.jellycon/?mode=WIDGET_CONTENT&type=recent_tvshows')
|
||||
add_menu_directory_item(translate_string(30263) + " (" + item_limit + ")",
|
||||
add_menu_directory_item(translate_string(30455) + item_limit_text,
|
||||
'plugin://plugin.video.jellycon/?mode=WIDGET_CONTENT&type=random_tvshows')
|
||||
add_menu_directory_item(translate_string(30263) + item_limit_text,
|
||||
'plugin://plugin.video.jellycon/?mode=WIDGET_CONTENT&type=recent_episodes')
|
||||
add_menu_directory_item(translate_string(30264) + " (" + item_limit + ")",
|
||||
add_menu_directory_item(translate_string(30264) + item_limit_text,
|
||||
'plugin://plugin.video.jellycon/?mode=WIDGET_CONTENT&type=inprogress_episodes')
|
||||
add_menu_directory_item(translate_string(30265) + " (" + item_limit + ")",
|
||||
add_menu_directory_item(translate_string(30265) + item_limit_text,
|
||||
'plugin://plugin.video.jellycon/?mode=WIDGET_CONTENT&type=nextup_episodes')
|
||||
add_menu_directory_item(translate_string(30457) + item_limit_text,
|
||||
'plugin://plugin.video.jellycon/?mode=WIDGET_CONTENT&type=recent_all')
|
||||
add_menu_directory_item(translate_string(30458),
|
||||
'plugin://plugin.video.jellycon/?mode=WIDGET_CONTENT&type=favorites_all')
|
||||
add_menu_directory_item(translate_string(30456) + item_limit_text,
|
||||
'plugin://plugin.video.jellycon/?mode=WIDGET_CONTENT&type=random_all')
|
||||
|
||||
xbmcplugin.endOfDirectory(int(sys.argv[1]))
|
||||
|
||||
@@ -1199,8 +1412,8 @@ def set_library_window_values(force=False):
|
||||
index = 0
|
||||
for item in result:
|
||||
|
||||
collection_type = item.get("CollectionType")
|
||||
if collection_type in ["movies", "boxsets", "music", "tvshows"]:
|
||||
collection_type = item.get("CollectionType", "mixed")
|
||||
if collection_type in ["movies", "boxsets", "music", "tvshows", "mixed"]:
|
||||
name = item.get("Name")
|
||||
item_id = item.get("Id")
|
||||
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
from __future__ import division, absolute_import, print_function, unicode_literals
|
||||
from __future__ import (
|
||||
division, absolute_import, print_function, unicode_literals
|
||||
)
|
||||
|
||||
import threading
|
||||
import time
|
||||
|
||||
import xbmc
|
||||
|
||||
from .functions import show_menu
|
||||
from .lazylogger import LazyLogger
|
||||
from .widgets import check_for_new_content
|
||||
@@ -23,7 +26,11 @@ class ContextMonitor(threading.Thread):
|
||||
|
||||
while not xbmc.Monitor().abortRequested() and not self.stop_thread:
|
||||
|
||||
if xbmc.getCondVisibility("Window.IsActive(fullscreenvideo) | Window.IsActive(visualisation)"):
|
||||
visibility_check = (
|
||||
"Window.IsActive(fullscreenvideo) | "
|
||||
"Window.IsActive(visualisation)"
|
||||
)
|
||||
if xbmc.getCondVisibility(visibility_check):
|
||||
xbmc.sleep(1000)
|
||||
else:
|
||||
if xbmc.getCondVisibility("Window.IsVisible(contextmenu)"):
|
||||
@@ -34,7 +41,9 @@ class ContextMonitor(threading.Thread):
|
||||
show_menu(params)
|
||||
|
||||
container_id = xbmc.getInfoLabel("System.CurrentControlID")
|
||||
item_id = xbmc.getInfoLabel("Container(" + str(container_id) + ").ListItem.Property(id)")
|
||||
item_id = xbmc.getInfoLabel(
|
||||
"Container({}).ListItem.Property(id)".format(container_id)
|
||||
)
|
||||
|
||||
xbmc.sleep(100)
|
||||
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
from __future__ import division, absolute_import, print_function, unicode_literals
|
||||
from __future__ import (
|
||||
division, absolute_import, print_function, unicode_literals
|
||||
)
|
||||
|
||||
import xbmcgui
|
||||
|
||||
|
||||
@@ -1,23 +1,25 @@
|
||||
# Gnu General Public License - see LICENSE.TXT
|
||||
from __future__ import division, absolute_import, print_function, unicode_literals
|
||||
from __future__ import (
|
||||
division, absolute_import, print_function, unicode_literals
|
||||
)
|
||||
|
||||
import json
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
import binascii
|
||||
import datetime
|
||||
|
||||
import xbmc
|
||||
import xbmcgui
|
||||
import xbmcaddon
|
||||
import xbmcvfs
|
||||
import xbmcplugin
|
||||
|
||||
from datetime import timedelta
|
||||
import json
|
||||
import os
|
||||
import re
|
||||
from six.moves.urllib.parse import urlencode
|
||||
import sys
|
||||
|
||||
from .jellyfin import api
|
||||
from .lazylogger import LazyLogger
|
||||
from .dialogs import ResumeDialog
|
||||
from .utils import send_event_notification, convert_size, get_device_id, translate_string, load_user_details, translate_path, get_jellyfin_url, download_external_sub
|
||||
from .utils import send_event_notification, convert_size, get_device_id, translate_string, load_user_details, translate_path, get_jellyfin_url, download_external_sub, get_bitrate
|
||||
from .kodi_utils import HomeWindow
|
||||
from .datamanager import clear_old_cache_data
|
||||
from .item_functions import extract_item_info, add_gui_item, get_art
|
||||
@@ -103,9 +105,12 @@ def play_all_files(items, play_items=True):
|
||||
list_item = set_list_item_props(item_id, list_item, item, server, listitem_props, item_title)
|
||||
|
||||
playlist.add(playurl, list_item)
|
||||
if play_items and playlist.size() == 1:
|
||||
# Play the first item immediately before processing the rest
|
||||
xbmc.Player().play(playlist)
|
||||
|
||||
if play_items:
|
||||
xbmc.Player().play(playlist)
|
||||
# Should already be playing, don't need to return anything
|
||||
return None
|
||||
else:
|
||||
return playlist
|
||||
@@ -237,8 +242,10 @@ def play_file(play_info):
|
||||
media_source_id = play_info.get("media_source_id", "")
|
||||
subtitle_stream_index = play_info.get("subtitle_stream_index", None)
|
||||
audio_stream_index = play_info.get("audio_stream_index", None)
|
||||
force_track_selection = play_info.get("force_track_selection", False)
|
||||
|
||||
log.debug("playFile id({0}) resume({1}) force_transcode({2})".format(item_id, auto_resume, force_transcode))
|
||||
log.debug("playFile id({0}) resume({1}) force_transcode({2}) force_track_selection({3})".format(
|
||||
item_id, auto_resume, force_transcode, force_track_selection))
|
||||
|
||||
addon_path = settings.getAddonInfo('path')
|
||||
force_auto_resume = settings.getSetting('forceAutoResume') == 'true'
|
||||
@@ -255,17 +262,52 @@ def play_file(play_info):
|
||||
log.debug("Playfile item was None, so can not play!")
|
||||
return
|
||||
|
||||
# if this is a season, playlist or album then play all items in that parent
|
||||
if result.get("Type") in ["Season", "MusicArtist", "MusicAlbum", "Playlist"]:
|
||||
# Generate an instant mix based on the item
|
||||
if action == 'instant_mix':
|
||||
max_queue = int(settings.getSetting('max_play_queue'))
|
||||
url_root = '/Items/{}/InstantMix'.format(item_id)
|
||||
url_params = {
|
||||
'UserId': api.user_id,
|
||||
'Fields': 'MediaSources',
|
||||
'IncludeItemTypes': 'Audio',
|
||||
'SortBy': 'SortName',
|
||||
'limit': max_queue
|
||||
}
|
||||
url = get_jellyfin_url(url_root, url_params)
|
||||
result = api.get(url)
|
||||
log.debug("PlayAllFiles items: {0}".format(result))
|
||||
|
||||
# process each item
|
||||
items = result["Items"]
|
||||
if items is None:
|
||||
items = []
|
||||
return play_all_files(items)
|
||||
|
||||
'''
|
||||
if this is a season, playlist, artist, album, or a full library then play
|
||||
*all* items in that parent.
|
||||
* Taking the max queue size setting into account
|
||||
'''
|
||||
if result.get("Type") in ["Season", "Series", "MusicArtist", "MusicAlbum",
|
||||
"Playlist", "CollectionFolder", "MusicGenre"]:
|
||||
max_queue = int(settings.getSetting('max_play_queue'))
|
||||
log.debug("PlayAllFiles for parent item id: {0}".format(item_id))
|
||||
url_root = '/Users/{}/Items'.format(api.user_id)
|
||||
# Look specifically for episodes or audio files
|
||||
url_params = {
|
||||
'ParentId': item_id,
|
||||
'Fields': 'MediaSources',
|
||||
'IncludeItemTypes': 'Episode,Audio',
|
||||
'Recursive': True
|
||||
'Recursive': True,
|
||||
'SortBy': 'SortName',
|
||||
'limit': max_queue
|
||||
}
|
||||
if result.get("Type") == "MusicGenre":
|
||||
url_params['genreIds'] = item_id
|
||||
else:
|
||||
url_params['ParentId'] = item_id
|
||||
|
||||
if action == 'shuffle':
|
||||
url_params['SortBy'] = 'Random'
|
||||
|
||||
url = get_jellyfin_url(url_root, url_params)
|
||||
result = api.get(url)
|
||||
@@ -365,8 +407,8 @@ def play_file(play_info):
|
||||
if user_data.get("PlaybackPositionTicks") != 0:
|
||||
|
||||
reasonable_ticks = int(user_data.get("PlaybackPositionTicks")) / 1000
|
||||
seek_time = reasonable_ticks / 10000
|
||||
display_time = str(timedelta(seconds=seek_time))
|
||||
seek_time = round(reasonable_ticks / 10000,0)
|
||||
display_time = (datetime.datetime(1,1,1) + datetime.timedelta(seconds=seek_time)).strftime('%H:%M:%S')
|
||||
|
||||
resume_dialog = ResumeDialog("ResumeDialog.xml", addon_path, "default", "720p")
|
||||
resume_dialog.setResumeTime("Resume from " + display_time)
|
||||
@@ -421,7 +463,7 @@ def play_file(play_info):
|
||||
|
||||
if playback_type == "2": # if transcoding then prompt for audio and subtitle
|
||||
playurl = audio_subs_pref(playurl, list_item, selected_media_source, item_id, audio_stream_index,
|
||||
subtitle_stream_index)
|
||||
subtitle_stream_index, force_track_selection)
|
||||
log.debug("New playurl for transcoding: {0}".format(playurl))
|
||||
|
||||
elif playback_type == "1": # for direct stream add any streamable subtitles
|
||||
@@ -441,6 +483,15 @@ def play_file(play_info):
|
||||
if result.get('Type') == 'Episode':
|
||||
next_episode = get_next_episode(result)
|
||||
data["next_episode"] = next_episode
|
||||
send_next_episode_details(result, next_episode)
|
||||
|
||||
# We need the livestream id to properly delete encodings
|
||||
if result.get("Type", "") in ["Program", "TvChannel"]:
|
||||
for media_source in media_sources:
|
||||
livestream_id = media_source.get("LiveStreamId")
|
||||
data["livestream_id"] = livestream_id
|
||||
if livestream_id:
|
||||
break
|
||||
|
||||
home_window.set_property('now_playing', json.dumps(data))
|
||||
|
||||
@@ -458,11 +509,14 @@ def play_file(play_info):
|
||||
playlist.add(playurl, list_item)
|
||||
player.play(playlist)
|
||||
else:
|
||||
if len(sys.argv) > 1:
|
||||
# Play from within addon
|
||||
if len(sys.argv) > 1 and int(sys.argv[1]) > 0:
|
||||
# Play from info menu
|
||||
xbmcplugin.setResolvedUrl(int(sys.argv[1]), True, list_item)
|
||||
else:
|
||||
# Play from remote control. Doesn't have a handle, so need to call player directly
|
||||
'''
|
||||
Play from remote control or addon menus. Doesn't have a handle,
|
||||
so need to call player directly
|
||||
'''
|
||||
playlist = xbmc.PlayList(xbmc.PLAYLIST_VIDEO)
|
||||
playlist.clear()
|
||||
playlist.add(playurl, list_item)
|
||||
@@ -678,8 +732,20 @@ def set_list_item_props(item_id, list_item, result, server, extra_props, title):
|
||||
|
||||
details = {
|
||||
'title': title,
|
||||
'mediatype': mediatype
|
||||
'mediatype': mediatype,
|
||||
'artist': "Unknown Artist",
|
||||
'album': "Unknown Album"
|
||||
}
|
||||
artist = result.get("Artists", [])
|
||||
if artist:
|
||||
details['artist'] = artist[0]
|
||||
track = result.get("IndexNumber")
|
||||
if track:
|
||||
details['tracknumber'] = track
|
||||
album = result.get("Album")
|
||||
if album:
|
||||
details['album'] = album
|
||||
|
||||
list_item.setInfo("Music", infoLabels=details)
|
||||
|
||||
else:
|
||||
@@ -714,12 +780,14 @@ def set_list_item_props(item_id, list_item, result, server, extra_props, title):
|
||||
# Present the list of audio and subtitles to select from
|
||||
# for external streamable subtitles add the URL to the Kodi item and let Kodi handle it
|
||||
# else ask for the subtitles to be burnt in when transcoding
|
||||
def audio_subs_pref(url, list_item, media_source, item_id, audio_stream_index, subtitle_stream_index):
|
||||
def audio_subs_pref(url, list_item, media_source, item_id, audio_stream_index, subtitle_stream_index, force_track_selection=False):
|
||||
dialog = xbmcgui.Dialog()
|
||||
audio_streams_list = {}
|
||||
audio_streams = []
|
||||
audio_streams_data = [] # Store full stream data for preference matching
|
||||
subtitle_streams_list = {}
|
||||
subtitle_streams = ['No subtitles']
|
||||
subtitle_streams_data = [] # Store full stream data for preference matching
|
||||
downloadable_streams = []
|
||||
select_audio_index = audio_stream_index
|
||||
select_subs_index = subtitle_stream_index
|
||||
@@ -728,6 +796,60 @@ def audio_subs_pref(url, list_item, media_source, item_id, audio_stream_index, s
|
||||
default_sub = media_source.get('DefaultSubtitleStreamIndex', "")
|
||||
source_id = media_source["Id"]
|
||||
|
||||
# Read user preferences
|
||||
# Map select index to language code
|
||||
lang_index_map = ['ger', 'eng', 'fra', 'spa', 'ita', 'jpn', 'rus', ''] # '' = other/custom
|
||||
sub_lang_index_map = ['', 'ger', 'eng', 'fra', 'spa', 'ita', 'jpn', 'rus', ''] # First is 'none'
|
||||
|
||||
audio_lang_index = int(settings.getSetting("preferred_audio_language") or "0")
|
||||
preferred_audio_lang = lang_index_map[audio_lang_index] if audio_lang_index < len(lang_index_map) else ''
|
||||
|
||||
auto_select_default_audio = settings.getSetting("auto_select_default_audio") == "true"
|
||||
|
||||
sub_lang_index = int(settings.getSetting("preferred_subtitle_language") or "1")
|
||||
preferred_sub_lang = sub_lang_index_map[sub_lang_index] if sub_lang_index < len(sub_lang_index_map) else ''
|
||||
|
||||
prefer_forced = settings.getSetting("prefer_forced_subtitles") == "true"
|
||||
only_forced = settings.getSetting("only_forced_subtitles") == "true"
|
||||
|
||||
# Subtitle codec preference: 0=PGS, 1=SRT, 2=No preference
|
||||
codec_pref_index = int(settings.getSetting("subtitle_codec_preference") or "0")
|
||||
prefer_pgs = codec_pref_index == 0
|
||||
prefer_srt = codec_pref_index == 1
|
||||
# codec_pref_index == 2 means no preference (both prefer_pgs and prefer_srt are False)
|
||||
|
||||
auto_no_subs = settings.getSetting("auto_no_subtitles_if_no_match") == "true"
|
||||
|
||||
# Language code mapping for better matching
|
||||
language_map = {
|
||||
'ger': ['ger', 'deu', 'de', 'german', 'deutsch'],
|
||||
'eng': ['eng', 'en', 'english'],
|
||||
'fra': ['fra', 'fr', 'fre', 'french', 'français'],
|
||||
'spa': ['spa', 'es', 'spanish', 'español'],
|
||||
'ita': ['ita', 'it', 'italian', 'italiano'],
|
||||
'jpn': ['jpn', 'ja', 'japanese', '日本語'],
|
||||
'rus': ['rus', 'ru', 'russian'],
|
||||
}
|
||||
|
||||
# Helper function to check if language matches
|
||||
def language_matches(stream_lang, preferred_lang):
|
||||
stream_lang = stream_lang.lower()
|
||||
preferred_lang = preferred_lang.lower()
|
||||
|
||||
# Direct match
|
||||
if preferred_lang in stream_lang or stream_lang in preferred_lang:
|
||||
return True
|
||||
|
||||
# Check against language map
|
||||
for key, variations in language_map.items():
|
||||
if preferred_lang in variations:
|
||||
# Check if stream language matches any variation
|
||||
for variant in variations:
|
||||
if variant in stream_lang or stream_lang.startswith(variant[:2]):
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
media_streams = media_source['MediaStreams']
|
||||
|
||||
for stream in media_streams:
|
||||
@@ -735,36 +857,176 @@ def audio_subs_pref(url, list_item, media_source, item_id, audio_stream_index, s
|
||||
index = stream['Index']
|
||||
|
||||
if 'Audio' in stream['Type']:
|
||||
codec = stream['Codec']
|
||||
codec = stream.get('Codec', None)
|
||||
channel_layout = stream.get('ChannelLayout', "")
|
||||
title = stream.get('Title', '')
|
||||
|
||||
try:
|
||||
track = "%s - %s - %s %s" % (index, stream['Language'], codec, channel_layout)
|
||||
except:
|
||||
track = "%s - %s %s" % (index, codec, channel_layout)
|
||||
if not codec:
|
||||
# Probably tvheadend and has no other info
|
||||
track = "%s - default" % (index)
|
||||
else:
|
||||
try:
|
||||
# Track includes language
|
||||
track = "%s - %s - %s %s" % (index, stream['Language'], codec, channel_layout)
|
||||
except KeyError:
|
||||
# Track doesn't include language
|
||||
track = "%s - %s %s" % (index, codec, channel_layout)
|
||||
|
||||
# Add title if available
|
||||
if title:
|
||||
track = "%s - %s" % (track, title)
|
||||
|
||||
audio_streams_list[track] = index
|
||||
audio_streams.append(track)
|
||||
audio_streams_data.append(stream)
|
||||
|
||||
elif 'Subtitle' in stream['Type']:
|
||||
try:
|
||||
track = "%s - %s" % (index, stream['Language'])
|
||||
except:
|
||||
track = "%s - %s" % (index, stream['Codec'])
|
||||
language = stream.get('Language', 'Unknown')
|
||||
codec = stream.get('Codec', 'Unknown')
|
||||
|
||||
codec_names = {
|
||||
'subrip': 'SRT',
|
||||
'hdmv_pgs_subtitle': 'PGS',
|
||||
'dvd_subtitle': 'VobSub',
|
||||
'ass': 'ASS'
|
||||
}
|
||||
codec_display = codec_names.get(codec.lower(), codec.upper())
|
||||
|
||||
track = "%s - %s (%s)" % (index, language, codec_display)
|
||||
|
||||
default = stream['IsDefault']
|
||||
forced = stream['IsForced']
|
||||
hearing_impaired = stream.get('IsHearingImpaired', False)
|
||||
downloadable = stream['IsTextSubtitleStream'] and stream['IsExternal'] and stream['SupportsExternalStream']
|
||||
|
||||
if default:
|
||||
track = "%s - Default" % track
|
||||
if forced:
|
||||
track = "%s - Forced" % track
|
||||
if hearing_impaired:
|
||||
track = "%s - SDH" % track
|
||||
if downloadable:
|
||||
downloadable_streams.append(index)
|
||||
|
||||
subtitle_streams_list[track] = index
|
||||
subtitle_streams.append(track)
|
||||
subtitle_streams_data.append(stream)
|
||||
|
||||
# Auto-select audio track based on preferences
|
||||
# Only auto-select if not already set by server/remote control AND not forcing manual selection
|
||||
if not force_track_selection and select_audio_index is None and len(audio_streams_data) > 0 and (preferred_audio_lang or auto_select_default_audio):
|
||||
auto_selected = None
|
||||
best_score = -1
|
||||
|
||||
# Try to match preferred language with scoring
|
||||
if preferred_audio_lang:
|
||||
for stream in audio_streams_data:
|
||||
score = 0
|
||||
stream_lang = stream.get('Language', '')
|
||||
|
||||
# Match against common variations using language map
|
||||
if language_matches(stream_lang, preferred_audio_lang):
|
||||
score += 100 # Language match
|
||||
|
||||
# Bonus for default track
|
||||
if stream.get('IsDefault', False):
|
||||
score += 50
|
||||
|
||||
# Bonus based on channel count (more channels = better quality)
|
||||
channels = stream.get('Channels', 2)
|
||||
score += min(channels * 5, 40) # Max +40 for 8 channels
|
||||
|
||||
# Bonus for high-quality codecs
|
||||
codec = stream.get('Codec', '').lower()
|
||||
if 'truehd' in codec or 'dts-hd' in codec or 'dts-ma' in codec:
|
||||
score += 30
|
||||
elif 'dts' in codec:
|
||||
score += 20
|
||||
elif 'ac3' in codec or 'eac3' in codec:
|
||||
score += 10
|
||||
|
||||
# Penalty for commentary tracks
|
||||
title = stream.get('Title', '').lower()
|
||||
display_title = stream.get('DisplayTitle', '').lower()
|
||||
if 'commentary' in title or 'kommentar' in title or 'commentary' in display_title:
|
||||
score -= 100 # Effectively exclude commentary
|
||||
|
||||
log.debug("Audio score for {0} ({1}): {2} (channels={3}, codec={4}, default={5})".format(
|
||||
stream_lang, stream['Index'], score, channels, codec, stream.get('IsDefault', False)))
|
||||
|
||||
if score > best_score:
|
||||
best_score = score
|
||||
auto_selected = stream['Index']
|
||||
|
||||
# Fall back to default audio if enabled and no language match
|
||||
if auto_selected is None and auto_select_default_audio:
|
||||
auto_selected = default_audio
|
||||
log.debug("Auto-selected default audio (index {0})".format(auto_selected))
|
||||
|
||||
if auto_selected is not None:
|
||||
select_audio_index = auto_selected
|
||||
if best_score > 0:
|
||||
log.debug("Auto-selected audio (index {0}, score {1})".format(auto_selected, best_score))
|
||||
|
||||
# Auto-select subtitle track based on preferences
|
||||
# Only auto-select if not already set by server/remote control AND not forcing manual selection
|
||||
if force_track_selection:
|
||||
log.debug("Forcing manual track selection (from context menu)")
|
||||
elif select_subs_index is not None:
|
||||
log.debug("Using subtitle index from server/remote: {0}".format(select_subs_index))
|
||||
elif len(subtitle_streams_data) == 0:
|
||||
log.debug("No subtitle streams available")
|
||||
elif len(subtitle_streams_data) > 0 and preferred_sub_lang: # Only if user configured a language preference
|
||||
auto_selected = None
|
||||
best_score = -1
|
||||
|
||||
log.debug("Auto-selecting subtitle: preferred_lang={0}, prefer_forced={1}, only_forced={2}, prefer_pgs={3}, prefer_srt={4}".format(
|
||||
preferred_sub_lang, prefer_forced, only_forced, prefer_pgs, prefer_srt))
|
||||
|
||||
for stream in subtitle_streams_data:
|
||||
score = 0
|
||||
stream_lang = stream.get('Language', '')
|
||||
codec = stream.get('Codec', '').lower()
|
||||
is_forced = stream.get('IsForced', False)
|
||||
is_default = stream.get('IsDefault', False)
|
||||
|
||||
# Skip non-forced subtitles if only_forced is enabled
|
||||
if only_forced and not is_forced:
|
||||
log.debug("Skipping non-forced subtitle {0} ({1}) - only_forced is enabled".format(
|
||||
stream_lang, stream['Index']))
|
||||
continue
|
||||
|
||||
# Score based on language match
|
||||
if preferred_sub_lang and language_matches(stream_lang, preferred_sub_lang):
|
||||
score += 100
|
||||
|
||||
# Bonus for forced if preferred
|
||||
if prefer_forced and is_forced:
|
||||
score += 50
|
||||
|
||||
# Bonus for codec preference
|
||||
if prefer_pgs and codec in ['hdmv_pgs_subtitle', 'pgs']:
|
||||
score += 30
|
||||
elif prefer_srt and codec in ['subrip', 'srt']:
|
||||
score += 30
|
||||
|
||||
# Small bonus for default
|
||||
if is_default:
|
||||
score += 10
|
||||
|
||||
log.debug("Subtitle score for {0} ({1}): {2} (forced={3}, codec={4})".format(
|
||||
stream_lang, stream['Index'], score, is_forced, codec))
|
||||
|
||||
if score > best_score:
|
||||
best_score = score
|
||||
auto_selected = stream['Index']
|
||||
|
||||
if auto_selected is not None and best_score >= 100: # Only auto-select if language matched
|
||||
select_subs_index = auto_selected
|
||||
log.debug("Auto-selected subtitle (index {0}, score {1})".format(auto_selected, best_score))
|
||||
elif auto_no_subs and preferred_sub_lang: # No match found but user wants auto "no subs"
|
||||
select_subs_index = -1 # Special value to indicate "no subtitles"
|
||||
log.debug("No matching subtitle found - auto-selected 'No subtitles'")
|
||||
|
||||
# set audio index
|
||||
if select_audio_index is not None:
|
||||
@@ -782,15 +1044,19 @@ def audio_subs_pref(url, list_item, media_source, item_id, audio_stream_index, s
|
||||
|
||||
# set subtitle index
|
||||
if select_subs_index is not None:
|
||||
# Handle special "no subtitles" value
|
||||
if select_subs_index == -1:
|
||||
# User wants no subtitles - do nothing
|
||||
pass
|
||||
# Load subtitles in the listitem if downloadable
|
||||
if select_subs_index in downloadable_streams:
|
||||
elif select_subs_index in downloadable_streams:
|
||||
subtitle_url = "%s/Videos/%s/%s/Subtitles/%s/Stream.srt"
|
||||
subtitle_url = subtitle_url % (settings.getSetting('server_address'), item_id, source_id, select_subs_index)
|
||||
log.debug("Streaming subtitles url: {0} {1}".format(select_subs_index, subtitle_url))
|
||||
list_item.setSubtitles([subtitle_url])
|
||||
else:
|
||||
# Burn subtitles
|
||||
playurlprefs += "&SubtitleStreamIndex=%s" % select_subs_index
|
||||
playurlprefs += "&SubtitleStreamIndex=%s&SubtitleMethod=Encode" % select_subs_index
|
||||
|
||||
elif len(subtitle_streams) > 1:
|
||||
resp = dialog.select(translate_string(30292), subtitle_streams)
|
||||
@@ -810,15 +1076,12 @@ def audio_subs_pref(url, list_item, media_source, item_id, audio_stream_index, s
|
||||
list_item.setSubtitles([subtitle_url])
|
||||
else:
|
||||
# Burn subtitles
|
||||
playurlprefs += "&SubtitleStreamIndex=%s" % select_subs_index
|
||||
playurlprefs += "&SubtitleStreamIndex=%s&SubtitleMethod=Encode" % select_subs_index
|
||||
|
||||
else: # User backed out of selection
|
||||
playurlprefs += "&SubtitleStreamIndex=%s" % default_sub
|
||||
playurlprefs += "&SubtitleStreamIndex=%s&SubtitleMethod=Encode" % default_sub
|
||||
|
||||
if url.find("|verifypeer=false") != -1:
|
||||
new_url = url.replace("|verifypeer=false", playurlprefs + "|verifypeer=false")
|
||||
else:
|
||||
new_url = url + playurlprefs
|
||||
new_url = url + playurlprefs
|
||||
|
||||
return new_url
|
||||
|
||||
@@ -834,38 +1097,33 @@ def external_subs(media_source, list_item, item_id):
|
||||
sub_names = []
|
||||
|
||||
server = settings.getSetting('server_address')
|
||||
user_details = load_user_details()
|
||||
token = user_details.get('token')
|
||||
|
||||
for stream in media_streams:
|
||||
|
||||
for idx, stream in enumerate(media_streams):
|
||||
if (stream['Type'] == "Subtitle"
|
||||
and stream['IsExternal']
|
||||
and stream['IsTextSubtitleStream']
|
||||
and stream['SupportsExternalStream']):
|
||||
|
||||
index = stream['Index']
|
||||
source_id = media_source['Id']
|
||||
|
||||
language = stream.get('Language', '')
|
||||
if language and stream['IsDefault']:
|
||||
language = '{}.default'.format(language)
|
||||
if language and stream['IsForced']:
|
||||
language = '{}.forced'.format(language)
|
||||
is_sdh = stream.get('Title') and stream['Title'] in ('sdh', 'cc')
|
||||
if language and is_sdh:
|
||||
language = '{}.{}'.format(language, stream['Title'])
|
||||
if language and stream['IsHearingImpaired']:
|
||||
language = '{}.SDH'.format(language)
|
||||
codec = stream.get('Codec', '')
|
||||
|
||||
url = '{}{}'.format(server, stream.get('DeliveryUrl'))
|
||||
if language:
|
||||
title = str(idx)
|
||||
if stream.get('Title'):
|
||||
title = stream['Title']
|
||||
'''
|
||||
Starting in 10.8, the server no longer provides language
|
||||
specific download points. We have to download the file
|
||||
and name it with the language code ourselves so Kodi
|
||||
will parse it correctly
|
||||
'''
|
||||
subtitle_file = download_external_sub(language, codec, url)
|
||||
subtitle_file = download_external_sub(language, codec, url, title)
|
||||
else:
|
||||
# If there is no language defined, we can go directly to the server
|
||||
subtitle_file = url
|
||||
@@ -979,23 +1237,22 @@ def prompt_for_stop_actions(item_id, data):
|
||||
prompt_delete_movie_percentage == 100):
|
||||
return
|
||||
|
||||
# if no runtime we cant calculate perceantge so just return
|
||||
# if no runtime we can't calculate percentage so just return
|
||||
if duration == 0:
|
||||
log.debug("No duration so returing")
|
||||
log.debug("No duration so returning")
|
||||
return
|
||||
|
||||
# item percentage complete
|
||||
percenatge_complete = int((current_position / duration) * 100)
|
||||
log.debug("Episode Percentage Complete: {0}".format(percenatge_complete))
|
||||
percentage_complete = int((current_position / duration) * 100)
|
||||
log.debug("Episode Percentage Complete: {0}".format(percentage_complete))
|
||||
|
||||
# prompt for next episode
|
||||
if (next_episode is not None and
|
||||
prompt_next_percentage < 100 and
|
||||
item_type == "Episode" and
|
||||
percenatge_complete > prompt_next_percentage):
|
||||
percentage_complete >= prompt_next_percentage):
|
||||
|
||||
if play_prompt:
|
||||
|
||||
plugin_path = settings.getAddonInfo('path')
|
||||
plugin_path_real = translate_path(os.path.join(plugin_path))
|
||||
|
||||
@@ -1006,6 +1263,14 @@ def prompt_for_stop_actions(item_id, data):
|
||||
if not play_next_dialog.get_play_called():
|
||||
xbmc.executebuiltin("Container.Refresh")
|
||||
|
||||
else:
|
||||
play_info = {
|
||||
"item_id": next_episode.get("Id"),
|
||||
"auto_resume": "-1",
|
||||
"force_transcode": False
|
||||
}
|
||||
send_event_notification("jellycon_play_action", play_info)
|
||||
|
||||
|
||||
def stop_all_playback():
|
||||
|
||||
@@ -1036,6 +1301,7 @@ def stop_all_playback():
|
||||
jellyfin_item_id = data.get("item_id")
|
||||
jellyfin_source_id = data.get("source_id")
|
||||
play_session_id = data.get("play_session_id")
|
||||
livestream_id = data.get('livestream_id')
|
||||
|
||||
if jellyfin_item_id is not None and current_position >= 0:
|
||||
log.debug("Playback Stopped at: {0}".format(current_position))
|
||||
@@ -1048,6 +1314,11 @@ def stop_all_playback():
|
||||
'RunTimeTicks': int(duration * 10000000),
|
||||
'PlaySessionId': play_session_id
|
||||
}
|
||||
|
||||
# If this is a livestream, include the id in the stopped call
|
||||
if livestream_id:
|
||||
postdata['LiveStreamId'] = livestream_id
|
||||
|
||||
api.post(url, postdata)
|
||||
data["currently_playing"] = False
|
||||
|
||||
@@ -1117,6 +1388,16 @@ def get_playing_data():
|
||||
|
||||
return {}
|
||||
|
||||
def get_jellyfin_playing_item():
|
||||
home_window = HomeWindow()
|
||||
play_data_string = home_window.get_property('now_playing')
|
||||
try:
|
||||
play_data = json.loads(play_data_string)
|
||||
except ValueError:
|
||||
# This isn't a JellyCon item
|
||||
return None
|
||||
|
||||
return play_data.get("item_id")
|
||||
|
||||
def get_play_url(media_source, play_session_id, channel_id=None):
|
||||
log.debug("get_play_url - media_source: {0}", media_source)
|
||||
@@ -1133,14 +1414,11 @@ def get_play_url(media_source, play_session_id, channel_id=None):
|
||||
|
||||
# get all the options
|
||||
server = settings.getSetting('server_address')
|
||||
use_https = settings.getSetting('protocol') == "1"
|
||||
verify_cert = settings.getSetting('verify_cert') == 'true'
|
||||
allow_direct_file_play = settings.getSetting('allow_direct_file_play') == 'true'
|
||||
|
||||
can_direct_play = media_source["SupportsDirectPlay"]
|
||||
can_direct_stream = media_source["SupportsDirectStream"]
|
||||
can_transcode = media_source["SupportsTranscoding"]
|
||||
container = media_source["Container"]
|
||||
|
||||
playurl = None
|
||||
playback_type = None
|
||||
@@ -1152,6 +1430,7 @@ def get_play_url(media_source, play_session_id, channel_id=None):
|
||||
direct_path = direct_path.strip()
|
||||
|
||||
# handle DVD structure
|
||||
container = media_source["Container"]
|
||||
if container == "dvd":
|
||||
direct_path = direct_path + "/VIDEO_TS/VIDEO_TS.IFO"
|
||||
elif container == "bluray":
|
||||
@@ -1169,17 +1448,9 @@ def get_play_url(media_source, play_session_id, channel_id=None):
|
||||
# check if file can be direct streamed/played
|
||||
if (can_direct_stream or can_direct_play) and playurl is None:
|
||||
item_id = media_source.get('Id')
|
||||
# We need to include the channel ID if this is a live stream
|
||||
if channel_id:
|
||||
url_root = '{}/Videos/{}/stream'.format(server, channel_id)
|
||||
play_params = {
|
||||
'static': True,
|
||||
'PlaySessionId': play_session_id,
|
||||
'MediaSourceId': item_id,
|
||||
'LiveStreamId': media_source.get('LiveStreamId')
|
||||
}
|
||||
play_param_string = urlencode(play_params)
|
||||
playurl = '{}?{}'.format(url_root, play_param_string)
|
||||
# live tv has to be transcoded by the server
|
||||
playurl = None
|
||||
else:
|
||||
url_root = '{}/Videos/{}/stream'.format(server, item_id)
|
||||
play_params = {
|
||||
@@ -1189,8 +1460,6 @@ def get_play_url(media_source, play_session_id, channel_id=None):
|
||||
}
|
||||
play_param_string = urlencode(play_params)
|
||||
playurl = '{}?{}'.format(url_root, play_param_string)
|
||||
if use_https and not verify_cert:
|
||||
playurl += "|verifypeer=false"
|
||||
playback_type = "1"
|
||||
|
||||
# check is file can be transcoded
|
||||
@@ -1200,8 +1469,7 @@ def get_play_url(media_source, play_session_id, channel_id=None):
|
||||
|
||||
user_details = load_user_details()
|
||||
user_token = user_details.get('token')
|
||||
playback_bitrate = settings.getSetting("force_max_stream_bitrate")
|
||||
bitrate = int(playback_bitrate) * 1000
|
||||
bitrate = get_bitrate(settings.getSetting("force_max_stream_bitrate"))
|
||||
playback_max_width = settings.getSetting("playback_max_width")
|
||||
audio_codec = settings.getSetting("audio_codec")
|
||||
audio_playback_bitrate = settings.getSetting("audio_playback_bitrate")
|
||||
@@ -1209,13 +1477,22 @@ def get_play_url(media_source, play_session_id, channel_id=None):
|
||||
audio_max_channels = settings.getSetting("audio_max_channels")
|
||||
playback_video_force_8 = settings.getSetting("playback_video_force_8") == "true"
|
||||
|
||||
# Determine target video codec for transcoding
|
||||
transcode_target_codec_setting = settings.getSetting("transcode_target_video_codec")
|
||||
if transcode_target_codec_setting == "1":
|
||||
transcode_video_codec = "hevc"
|
||||
elif transcode_target_codec_setting == "2":
|
||||
transcode_video_codec = "av1"
|
||||
else:
|
||||
transcode_video_codec = "h264"
|
||||
|
||||
transcode_params = {
|
||||
"MediaSourceId": item_id,
|
||||
"DeviceId": device_id,
|
||||
"PlaySessionId": play_session_id,
|
||||
"api_key": user_token,
|
||||
"SegmentContainer": "ts",
|
||||
"VideoCodec": "h264",
|
||||
"VideoCodec": transcode_video_codec,
|
||||
"VideoBitrate": bitrate,
|
||||
"MaxWidth": playback_max_width,
|
||||
"AudioCodec": audio_codec,
|
||||
@@ -1227,7 +1504,8 @@ def get_play_url(media_source, play_session_id, channel_id=None):
|
||||
|
||||
# We need to include the channel ID if this is a live stream
|
||||
if channel_id:
|
||||
transcode_params['LiveStreamId'] = media_source.get('LiveStreamId')
|
||||
if media_source.get('LiveStreamId'):
|
||||
transcode_params['LiveStreamId'] = media_source.get('LiveStreamId')
|
||||
transcode_path = urlencode(transcode_params)
|
||||
playurl = '{}/Videos/{}/master.m3u8?{}'.format(
|
||||
server, channel_id, transcode_path)
|
||||
@@ -1236,9 +1514,6 @@ def get_play_url(media_source, play_session_id, channel_id=None):
|
||||
playurl = '{}/Videos/{}/master.m3u8?{}'.format(
|
||||
server, item_id, transcode_path)
|
||||
|
||||
if use_https and not verify_cert:
|
||||
playurl += "|verifypeer=false"
|
||||
|
||||
playback_type = "2"
|
||||
|
||||
return playurl, playback_type, []
|
||||
@@ -1388,18 +1663,29 @@ class PlaybackService(xbmc.Monitor):
|
||||
home_window.set_property('exit', 'True')
|
||||
return
|
||||
|
||||
if sender != 'plugin.video.jellycon':
|
||||
if sender.lower() not in (
|
||||
'plugin.video.jellycon', 'xbmc', 'upnextprovider.signal'
|
||||
):
|
||||
return
|
||||
|
||||
|
||||
signal = method.split('.', 1)[-1]
|
||||
if signal not in ("jellycon_play_action", "jellycon_play_youtube_trailer_action", "set_view"):
|
||||
if signal not in (
|
||||
"jellycon_play_action", "jellycon_play_youtube_trailer_action",
|
||||
"set_view", "plugin.video.jellycon_play_action"):
|
||||
return
|
||||
|
||||
data_json = json.loads(data)
|
||||
play_info = data_json[0]
|
||||
if sender.lower() == "upnextprovider.signal":
|
||||
play_info = json.loads(binascii.unhexlify(data_json[0]))
|
||||
else:
|
||||
play_info = data_json[0]
|
||||
|
||||
log.debug("PlaybackService:onNotification:{0}".format(play_info))
|
||||
|
||||
if signal == "jellycon_play_action":
|
||||
if signal in (
|
||||
"jellycon_play_action", "plugin.video.jellycon_play_action"
|
||||
):
|
||||
play_file(play_info)
|
||||
elif signal == "jellycon_play_youtube_trailer_action":
|
||||
trailer_link = play_info["url"]
|
||||
@@ -1451,7 +1737,12 @@ class PlaybackService(xbmc.Monitor):
|
||||
|
||||
def get_item_playback_info(item_id, force_transcode):
|
||||
|
||||
# Filter codecs that should NEVER be played directly (always force transcoding)
|
||||
# These settings work independently from the target codec setting below
|
||||
# Example: force_transcode_h264=true + target=hevc means: H.264 files will be transcoded to H.265
|
||||
filtered_codecs = []
|
||||
if settings.getSetting("force_transcode_h264") == "true":
|
||||
filtered_codecs.append("h264")
|
||||
if settings.getSetting("force_transcode_h265") == "true":
|
||||
filtered_codecs.append("hevc")
|
||||
filtered_codecs.append("h265")
|
||||
@@ -1461,18 +1752,32 @@ def get_item_playback_info(item_id, force_transcode):
|
||||
filtered_codecs.append("msmpeg4v3")
|
||||
if settings.getSetting("force_transcode_mpeg4") == "true":
|
||||
filtered_codecs.append("mpeg4")
|
||||
if settings.getSetting("force_transcode_av1") == "true":
|
||||
filtered_codecs.append("av1")
|
||||
|
||||
playback_bitrate = settings.getSetting("max_stream_bitrate")
|
||||
force_playback_bitrate = settings.getSetting("force_max_stream_bitrate")
|
||||
if force_transcode:
|
||||
playback_bitrate = force_playback_bitrate
|
||||
if not force_transcode:
|
||||
bitrate = get_bitrate(settings.getSetting("max_stream_bitrate"))
|
||||
else:
|
||||
bitrate = get_bitrate(settings.getSetting("force_max_stream_bitrate"))
|
||||
|
||||
audio_codec = settings.getSetting("audio_codec")
|
||||
audio_playback_bitrate = settings.getSetting("audio_playback_bitrate")
|
||||
audio_max_channels = settings.getSetting("audio_max_channels")
|
||||
|
||||
audio_bitrate = int(audio_playback_bitrate) * 1000
|
||||
bitrate = int(playback_bitrate) * 1000
|
||||
|
||||
# Determine target video codec for transcoding
|
||||
# Note: force_transcode_* settings filter codecs for DirectPlay independently
|
||||
# This setting only affects what codec the server transcodes TO when transcoding is needed
|
||||
transcode_target_codec_setting = settings.getSetting("transcode_target_video_codec")
|
||||
log.debug("Transcode target codec setting value: '{0}'".format(transcode_target_codec_setting))
|
||||
if transcode_target_codec_setting == "1":
|
||||
transcode_video_codec = "hevc"
|
||||
elif transcode_target_codec_setting == "2":
|
||||
transcode_video_codec = "av1"
|
||||
else:
|
||||
transcode_video_codec = "h264"
|
||||
log.debug("Transcode target video codec: {0}".format(transcode_video_codec))
|
||||
|
||||
profile = {
|
||||
"Name": "Kodi",
|
||||
@@ -1489,7 +1794,7 @@ def get_item_playback_info(item_id, force_transcode):
|
||||
"Protocol": "hls",
|
||||
"Type": "Video",
|
||||
"AudioCodec": audio_codec,
|
||||
"VideoCodec": "h264",
|
||||
"VideoCodec": transcode_video_codec,
|
||||
"MaxAudioChannels": audio_max_channels
|
||||
},
|
||||
{
|
||||
@@ -1631,3 +1936,11 @@ def get_item_playback_info(item_id, force_transcode):
|
||||
log.debug("PlaybackInfo : {0}".format(play_info_result))
|
||||
|
||||
return play_info_result
|
||||
|
||||
def get_media_segments(item_id):
|
||||
url = "/MediaSegments/{}".format(item_id)
|
||||
result = api.get(url)
|
||||
if result is None or result["Items"] is None:
|
||||
log.debug("GetMediaSegments : Media segments cloud not be retrieved")
|
||||
return None
|
||||
return result["Items"]
|
||||
|
||||
1731
resources/lib/play_utils.py.orig
Normal file
1731
resources/lib/play_utils.py.orig
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,4 +1,6 @@
|
||||
from __future__ import division, absolute_import, print_function, unicode_literals
|
||||
from __future__ import (
|
||||
division, absolute_import, print_function, unicode_literals
|
||||
)
|
||||
|
||||
import os
|
||||
import threading
|
||||
@@ -92,6 +94,6 @@ class PlayNextService(threading.Thread):
|
||||
if xbmc.Monitor().waitForAbort(1):
|
||||
break
|
||||
|
||||
def stop_servcie(self):
|
||||
def stop_service(self):
|
||||
log.debug("PlayNextService Stop Called")
|
||||
self.stop_thread = True
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
# Gnu General Public License - see LICENSE.TXT
|
||||
from __future__ import division, absolute_import, print_function, unicode_literals
|
||||
from __future__ import (
|
||||
division, absolute_import, print_function, unicode_literals
|
||||
)
|
||||
|
||||
import socket
|
||||
import json
|
||||
import time
|
||||
from datetime import datetime
|
||||
|
||||
import xbmcaddon
|
||||
import xbmcgui
|
||||
@@ -13,8 +13,10 @@ import xbmc
|
||||
from .kodi_utils import HomeWindow
|
||||
from .jellyfin import API
|
||||
from .lazylogger import LazyLogger
|
||||
from .utils import datetime_from_string, translate_string, save_user_details, load_user_details, get_current_datetime
|
||||
from .dialogs import QuickConnectDialog
|
||||
from .utils import (
|
||||
datetime_from_string, translate_string, save_user_details,
|
||||
load_user_details, get_current_datetime, get_saved_users
|
||||
)
|
||||
|
||||
log = LazyLogger(__name__)
|
||||
|
||||
@@ -108,7 +110,7 @@ def get_server_details():
|
||||
xbmc.sleep(1000)
|
||||
data, addr = sock.recvfrom(1024)
|
||||
servers.append(json.loads(data))
|
||||
except:
|
||||
except: # noqa
|
||||
break
|
||||
except Exception as e:
|
||||
log.error("UPD Discovery Error: {0}".format(e))
|
||||
@@ -203,6 +205,8 @@ def check_server(force=False, change_user=False, notify=False):
|
||||
# do we need to change the user
|
||||
current_username = settings.getSetting('username')
|
||||
user_details = load_user_details()
|
||||
home_window = HomeWindow()
|
||||
home_window.set_property('user_name', current_username)
|
||||
|
||||
# if asked or we have no current user then show user selection screen
|
||||
if something_changed or change_user or len(current_username) == 0 or not user_details:
|
||||
@@ -210,60 +214,92 @@ def check_server(force=False, change_user=False, notify=False):
|
||||
# stop playback when switching users
|
||||
xbmc.Player().stop()
|
||||
|
||||
auth = quick_connect(api)
|
||||
# Initialize auth variable
|
||||
auth = {}
|
||||
|
||||
if auth:
|
||||
users = []
|
||||
user_selection = -1
|
||||
selected_user_name = auth.get('User', {}).get('Name')
|
||||
something_changed = True
|
||||
else:
|
||||
users, user_selection = user_select(api, current_username)
|
||||
|
||||
if not auth and user_selection > -1:
|
||||
# Check if quick connect is active on the server, initiate connection
|
||||
quick = api.get('/QuickConnect/Initiate')
|
||||
code = quick.get('Code')
|
||||
secret = quick.get('Secret')
|
||||
users, user_selection = user_select(api, current_username, code)
|
||||
|
||||
if user_selection > -1:
|
||||
# The user made a selection in the dialog
|
||||
something_changed = True
|
||||
selected_user = users[user_selection]
|
||||
selected_user_name = selected_user.getLabel()
|
||||
secured = selected_user.getProperty("secure") == "true"
|
||||
manual = selected_user.getProperty("manual") == "true"
|
||||
quick_connect = selected_user.getProperty("quickconnect") == "true"
|
||||
count = 0
|
||||
if quick_connect:
|
||||
# Try to authenticate to server with secret code 10 times
|
||||
while count < 10:
|
||||
log.debug('Checking for quick connect auth: attempt {}'.format(count))
|
||||
check = api.get('/QuickConnect/Connect?secret={}'.format(secret))
|
||||
if check.get('Authenticated'):
|
||||
break
|
||||
count += 1
|
||||
xbmc.sleep(1000)
|
||||
|
||||
home_window = HomeWindow()
|
||||
auth = api.post('/Users/AuthenticateWithQuickConnect',
|
||||
{'secret': secret})
|
||||
|
||||
# If using a manual login, ask for username
|
||||
if manual:
|
||||
kb = xbmc.Keyboard()
|
||||
kb.setHeading(translate_string(30005))
|
||||
if current_username:
|
||||
kb.setDefault(current_username)
|
||||
kb.doModal()
|
||||
if kb.isConfirmed():
|
||||
selected_user_name = kb.getText()
|
||||
log.debug("Manual entered username: {0}".format(selected_user_name))
|
||||
# If authentication was successful, save the username
|
||||
if auth:
|
||||
selected_user_name = auth['User'].get('Name')
|
||||
else:
|
||||
return
|
||||
# Login failed, we don't want to change anything
|
||||
something_changed = False
|
||||
log.info("There was an error logging in with quick connect")
|
||||
|
||||
home_window.set_property('user_name', selected_user_name)
|
||||
user_details = load_user_details()
|
||||
else:
|
||||
selected_user_name = selected_user.getLabel()
|
||||
secured = selected_user.getProperty("secure") == "true"
|
||||
manual = selected_user.getProperty("manual") == "true"
|
||||
|
||||
# Ask for password if user has one
|
||||
password = ''
|
||||
if secured and not user_details.get('token'):
|
||||
kb = xbmc.Keyboard()
|
||||
kb.setHeading(translate_string(30006))
|
||||
kb.setHiddenInput(True)
|
||||
kb.doModal()
|
||||
if kb.isConfirmed():
|
||||
password = kb.getText()
|
||||
# If using a manual login, ask for username
|
||||
if manual:
|
||||
kb = xbmc.Keyboard()
|
||||
kb.setHeading(translate_string(30005))
|
||||
if current_username:
|
||||
kb.setDefault(current_username)
|
||||
kb.doModal()
|
||||
if kb.isConfirmed():
|
||||
selected_user_name = kb.getText()
|
||||
log.debug("Manual entered username: {0}".format(selected_user_name))
|
||||
else:
|
||||
return
|
||||
|
||||
auth_payload = {'username': selected_user_name, 'pw': password}
|
||||
auth = api.authenticate(auth_payload)
|
||||
home_window.set_property('user_name', selected_user_name)
|
||||
settings.setSetting('username', selected_user_name)
|
||||
user_details = load_user_details()
|
||||
|
||||
if not user_details:
|
||||
# Ask for password if user has one
|
||||
password = ''
|
||||
if secured and not user_details.get('token'):
|
||||
kb = xbmc.Keyboard()
|
||||
kb.setHeading(translate_string(30006))
|
||||
kb.setHiddenInput(True)
|
||||
kb.doModal()
|
||||
if kb.isConfirmed():
|
||||
password = kb.getText()
|
||||
|
||||
auth_payload = {'username': selected_user_name, 'pw': password}
|
||||
auth = api.authenticate(auth_payload)
|
||||
if not auth:
|
||||
# Login failed, we don't want to change anything
|
||||
something_changed = False
|
||||
log.info('There was an error logging in with user {}'.format(selected_user_name))
|
||||
xbmcgui.Dialog().ok(__addon_name__, translate_string(30446))
|
||||
|
||||
if something_changed:
|
||||
home_window = HomeWindow()
|
||||
home_window.clear_property("jellycon_widget_reload")
|
||||
token = auth.get('AccessToken')
|
||||
user_id = auth.get('User').get('Id')
|
||||
if auth:
|
||||
token = auth.get('AccessToken')
|
||||
user_id = auth.get('User').get('Id')
|
||||
else:
|
||||
token = user_details.get('token')
|
||||
user_id = user_details.get('user_id')
|
||||
save_user_details(selected_user_name, user_id, token)
|
||||
xbmc.executebuiltin("ActivateWindow(Home)")
|
||||
if "estuary_jellycon" in xbmc.getSkinDir():
|
||||
@@ -271,65 +307,38 @@ def check_server(force=False, change_user=False, notify=False):
|
||||
xbmc.executebuiltin("ReloadSkin()")
|
||||
|
||||
|
||||
def quick_connect(api):
|
||||
'''
|
||||
Log in using quick connect funcion
|
||||
'''
|
||||
settings = xbmcaddon.Addon()
|
||||
addon_path = settings.getAddonInfo('path')
|
||||
|
||||
result = api.get('/QuickConnect/Initiate')
|
||||
|
||||
if not isinstance(result, dict) or not result:
|
||||
log.debug('Quick connect is disabled on the server')
|
||||
return {}
|
||||
|
||||
code = result.get('Code')
|
||||
secret = result.get('Secret')
|
||||
|
||||
# Open Quick Connect dialog, ask to proceed
|
||||
qc_dialog = QuickConnectDialog("QuickConnectDialog.xml", addon_path, "default", "720p")
|
||||
qc_dialog.code = code
|
||||
qc_dialog.doModal()
|
||||
connect_method = qc_dialog.getConnectMethod()
|
||||
del qc_dialog
|
||||
|
||||
if connect_method < 1:
|
||||
# User backed out or selected manual login
|
||||
return {}
|
||||
|
||||
count = 0
|
||||
while count < 15:
|
||||
# Check the server to see if the auth request has been completed
|
||||
log.debug('Checking for quick connect auth: attempt {}'.format(count))
|
||||
check = api.get('/QuickConnect/Connect?secret={}'.format(secret))
|
||||
if check.get('Authenticated'):
|
||||
break
|
||||
count += 1
|
||||
xbmc.sleep(1000)
|
||||
|
||||
if not check.get('Authenticated'):
|
||||
log.info('Quick connect not authorized in 15 seconds, defaulting to manual authentication')
|
||||
return {}
|
||||
|
||||
# Retrieve authentication information
|
||||
auth = api.post('/Users/AuthenticateWithQuickConnect',
|
||||
{'secret': secret})
|
||||
|
||||
return auth
|
||||
|
||||
|
||||
def user_select(api, current_username):
|
||||
def user_select(api, current_username, code):
|
||||
'''
|
||||
Display user selection screen
|
||||
'''
|
||||
# Retrieve list of public users from server
|
||||
result = api.get('/Users/Public')
|
||||
public = api.get('/Users/Public')
|
||||
|
||||
# Get list of saved users
|
||||
saved_users = get_saved_users()
|
||||
|
||||
# Combine public and saved users
|
||||
for user in saved_users:
|
||||
name = user.get('Name')
|
||||
# Check if saved user is in public list
|
||||
if name not in [x.get('Name', '') for x in public]:
|
||||
# If saved user is not already in list, add it
|
||||
public.append(user)
|
||||
|
||||
# Build user display
|
||||
selected_id = -1
|
||||
users = []
|
||||
for user in result:
|
||||
# If quick connect is active, make it the first entry
|
||||
if code:
|
||||
user_item = xbmcgui.ListItem(code)
|
||||
user_image = "DefaultUser.png"
|
||||
art = {"Thumb": user_image}
|
||||
user_item.setArt(art)
|
||||
user_item.setLabel2(translate_string(30443))
|
||||
user_item.setProperty('quickconnect', "true")
|
||||
users.append(user_item)
|
||||
|
||||
for user in public:
|
||||
user_item = create_user_listitem(api.server, user)
|
||||
if user_item:
|
||||
users.append(user_item)
|
||||
@@ -357,7 +366,7 @@ def user_select(api, current_username):
|
||||
selection_title,
|
||||
users,
|
||||
preselect=selected_id,
|
||||
autoclose=20000,
|
||||
autoclose=60000,
|
||||
useDetails=True)
|
||||
|
||||
return (users, user_selection)
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
from __future__ import division, absolute_import, print_function, unicode_literals
|
||||
from __future__ import (
|
||||
division, absolute_import, print_function, unicode_literals
|
||||
)
|
||||
|
||||
import sys
|
||||
|
||||
import xbmcgui
|
||||
import xbmcplugin
|
||||
import xbmcaddon
|
||||
@@ -47,10 +50,10 @@ def show_server_sessions():
|
||||
now_playing = session.get("NowPlayingItem", None)
|
||||
transcoding_info = session.get("TranscodingInfo", None)
|
||||
|
||||
session_info = user_name + " - " + client_name
|
||||
session_info = "{} - {}".format(user_name, client_name)
|
||||
user_session_details = ""
|
||||
|
||||
percenatge_played = 0
|
||||
percentage_played = 0
|
||||
position_ticks = 0
|
||||
runtime = 0
|
||||
play_method = "na"
|
||||
@@ -65,37 +68,50 @@ def show_server_sessions():
|
||||
|
||||
runtime = now_playing.get("RunTimeTicks", 0)
|
||||
if position_ticks > 0 and runtime > 0:
|
||||
percenatge_played = (position_ticks / float(runtime)) * 100.0
|
||||
percenatge_played = int(percenatge_played)
|
||||
percentage_played = (position_ticks / float(runtime)) * 100.0
|
||||
percentage_played = int(percentage_played)
|
||||
|
||||
session_info += " (" + now_playing.get("Name", "na") + " " + str(percenatge_played) + "%)"
|
||||
user_session_details += now_playing.get("Name", "na") + " " + str(percenatge_played) + "%" + "\n"
|
||||
session_info += " {} {}%".format(
|
||||
now_playing.get("Name", "na"), percentage_played
|
||||
)
|
||||
user_session_details += "{} {}%\n".format(
|
||||
now_playing.get("Name", "na"), percentage_played
|
||||
)
|
||||
|
||||
else:
|
||||
session_info += " (idle)"
|
||||
user_session_details += "Idle" + "\n"
|
||||
user_session_details += "Idle\n"
|
||||
|
||||
transcoding_details = ""
|
||||
if transcoding_info:
|
||||
if not transcoding_info.get("IsVideoDirect", None):
|
||||
transcoding_details += "Video:" + transcoding_info.get("VideoCodec", "") + ":" + str(transcoding_info.get("Width", 0)) + "x" + str(transcoding_info.get("Height", 0)) + "\n"
|
||||
transcoding_details += "Video:{}:{}x{}\n".format(
|
||||
transcoding_info.get("VideoCodec", ""),
|
||||
transcoding_info.get("Width", 0),
|
||||
transcoding_info.get("Height", 0)
|
||||
)
|
||||
else:
|
||||
transcoding_details += "Video:direct\n"
|
||||
|
||||
if not transcoding_info.get("IsAudioDirect", None):
|
||||
transcoding_details += "Audio:" + transcoding_info.get("AudioCodec", "") + ":" + str(transcoding_info.get("AudioChannels", 0)) + "\n"
|
||||
transcoding_details += "Audio:{}:{}\n".format(
|
||||
transcoding_info.get("AudioCodec", ""),
|
||||
transcoding_info.get("AudioChannels", 0)
|
||||
)
|
||||
else:
|
||||
transcoding_details += "Audio:direct\n"
|
||||
|
||||
transcoding_details += "Bitrate:" + str(transcoding_info.get("Bitrate", 0)) + "\n"
|
||||
transcoding_details += "Bitrate:{}\n".format(
|
||||
transcoding_info.get("Bitrate", 0)
|
||||
)
|
||||
|
||||
list_item = xbmcgui.ListItem(label=session_info)
|
||||
list_item.setArt(art)
|
||||
|
||||
user_session_details += device_name + "(" + client_version + ")\n"
|
||||
user_session_details += client_name + "\n"
|
||||
user_session_details += play_method + "\n"
|
||||
user_session_details += transcoding_details + "\n"
|
||||
user_session_details += "{}({})\n".format(device_name, client_version)
|
||||
user_session_details += "{}\n".format(client_name)
|
||||
user_session_details += "{}\n".format(play_method)
|
||||
user_session_details += "{}\n".format(transcoding_details)
|
||||
|
||||
info_labels = {}
|
||||
info_labels["duration"] = str(runtime / 10000000)
|
||||
@@ -105,7 +121,7 @@ def show_server_sessions():
|
||||
|
||||
list_item.setProperty('TotalTime', str(runtime / 10000000))
|
||||
list_item.setProperty('ResumeTime', str(position_ticks / 10000000))
|
||||
list_item.setProperty("complete_percentage", str(percenatge_played))
|
||||
list_item.setProperty("complete_percentage", str(percentage_played))
|
||||
|
||||
item_tuple = ("", list_item, False)
|
||||
list_items.append(item_tuple)
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
# Gnu General Public License - see LICENSE.TXT
|
||||
from __future__ import division, absolute_import, print_function, unicode_literals
|
||||
from __future__ import (
|
||||
division, absolute_import, print_function, unicode_literals
|
||||
)
|
||||
|
||||
import os
|
||||
import xml.etree.ElementTree as ET
|
||||
@@ -19,9 +20,11 @@ def clone_default_skin():
|
||||
xbmc.executebuiltin("Dialog.Close(all,true)")
|
||||
xbmc.executebuiltin("ActivateWindow(Home)")
|
||||
|
||||
response = xbmcgui.Dialog().yesno("JellyCon Skin Cloner",
|
||||
"This will clone the default Estuary Kodi skin and add JellyCon functionality to it.",
|
||||
"Do you want to continue?")
|
||||
response = xbmcgui.Dialog().yesno(
|
||||
"JellyCon Skin Cloner",
|
||||
("This will clone the default Estuary Kodi skin and"
|
||||
"add JellyCon functionality to it."),
|
||||
"Do you want to continue?")
|
||||
if not response:
|
||||
return
|
||||
|
||||
@@ -62,7 +65,9 @@ def clone_skin():
|
||||
log.debug("Found Path: {0}".format(found))
|
||||
|
||||
kodi_home_path = translate_path("special://home")
|
||||
kodi_skin_destination = os.path.join(kodi_home_path, "addons", "skin.estuary_jellycon")
|
||||
kodi_skin_destination = os.path.join(
|
||||
kodi_home_path, "addons", "skin.estuary_jellycon"
|
||||
)
|
||||
log.debug("Kodi Skin Destination: {0}".format(kodi_skin_destination))
|
||||
|
||||
# copy all skin files (clone)
|
||||
@@ -70,7 +75,7 @@ def clone_skin():
|
||||
total = len(all_files)
|
||||
for skin_file in all_files:
|
||||
percentage_done = int(float(count) / float(total) * 100.0)
|
||||
pdialog.update(percentage_done, "%s" % skin_file)
|
||||
pdialog.update(percentage_done, skin_file)
|
||||
|
||||
source = os.path.join(kodi_skin_source, skin_file)
|
||||
destination = os.path.join(kodi_skin_destination, skin_file)
|
||||
@@ -89,7 +94,9 @@ def clone_skin():
|
||||
addon_tree.write(addon_xml_path)
|
||||
|
||||
# get jellycon path
|
||||
jellycon_path = os.path.join(kodi_home_path, "addons", "plugin.video.jellycon")
|
||||
jellycon_path = os.path.join(
|
||||
kodi_home_path, "addons", "plugin.video.jellycon"
|
||||
)
|
||||
|
||||
log.debug("Major Version: {0}".format(kodi_version()))
|
||||
|
||||
@@ -101,7 +108,10 @@ def clone_skin():
|
||||
|
||||
# Copy customized skin files from our addon into cloned skin
|
||||
for file_name in file_list:
|
||||
source = os.path.join(jellycon_path, "resources", "skins", "skin.estuary", str(kodi_version), "xml", file_name)
|
||||
source = os.path.join(
|
||||
jellycon_path, "resources", "skins", "skin.estuary",
|
||||
str(kodi_version), "xml", file_name
|
||||
)
|
||||
destination = os.path.join(kodi_skin_destination, "xml", file_name)
|
||||
xbmcvfs.copy(source, destination)
|
||||
|
||||
@@ -110,7 +120,10 @@ def clone_skin():
|
||||
pdialog.close()
|
||||
del pdialog
|
||||
|
||||
response = xbmcgui.Dialog().yesno("JellyCon Skin Cloner", "Do you want to switch to the new cloned skin?")
|
||||
response = xbmcgui.Dialog().yesno(
|
||||
"JellyCon Skin Cloner",
|
||||
"Do you want to switch to the new cloned skin?"
|
||||
)
|
||||
if not response:
|
||||
return
|
||||
|
||||
@@ -121,10 +134,14 @@ def clone_skin():
|
||||
result = JsonRpc('Addons.SetAddonEnabled').execute(params)
|
||||
log.debug("Addons.SetAddonEnabled : {0}".format(result))
|
||||
|
||||
log.debug("SkinCloner : Current Skin : " + get_value("lookandfeel.skin"))
|
||||
log.debug("SkinCloner : Current Skin : {}".format(
|
||||
get_value("lookandfeel.skin"))
|
||||
)
|
||||
set_result = set_value("lookandfeel.skin", "skin.estuary_jellycon")
|
||||
log.debug("Save Setting : lookandfeel.skin : {0}".format(set_result))
|
||||
log.debug("SkinCloner : Current Skin : " + get_value("lookandfeel.skin"))
|
||||
log.debug("SkinCloner : Current Skin : {}".format(
|
||||
get_value("lookandfeel.skin"))
|
||||
)
|
||||
|
||||
|
||||
def update_kodi_settings():
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
# Gnu General Public License - see LICENSE.TXT
|
||||
from __future__ import division, absolute_import, print_function, unicode_literals
|
||||
from __future__ import (
|
||||
division, absolute_import, print_function, unicode_literals
|
||||
)
|
||||
|
||||
import sys
|
||||
import functools
|
||||
import time
|
||||
|
||||
from .lazylogger import LazyLogger
|
||||
|
||||
log = LazyLogger(__name__)
|
||||
@@ -28,6 +30,8 @@ def timer(func):
|
||||
data = args[1]
|
||||
elif func.__name__ == "main_entry_point" and len(sys.argv) > 2:
|
||||
data = sys.argv[2]
|
||||
log.info("timing_data|{0}|{1}|{2}|{3}".format(func.__name__, started, ended, data))
|
||||
log.info("timing_data|{0}|{1}|{2}|{3}".format(
|
||||
func.__name__, started, ended, data)
|
||||
)
|
||||
return value
|
||||
return wrapper
|
||||
|
||||
@@ -1,12 +1,8 @@
|
||||
# Gnu General Public License - see LICENSE.TXT
|
||||
from __future__ import division, absolute_import, print_function, unicode_literals
|
||||
from __future__ import (
|
||||
division, absolute_import, print_function, unicode_literals
|
||||
)
|
||||
|
||||
import xbmcaddon
|
||||
import xbmc
|
||||
import xbmcvfs
|
||||
from kodi_six.utils import py2_encode, py2_decode
|
||||
import sys
|
||||
|
||||
import binascii
|
||||
import string
|
||||
import random
|
||||
@@ -15,11 +11,16 @@ import time
|
||||
import math
|
||||
import os
|
||||
import hashlib
|
||||
import requests
|
||||
from datetime import datetime
|
||||
from dateutil import tz
|
||||
import re
|
||||
from datetime import datetime
|
||||
from uuid import uuid4
|
||||
|
||||
import requests
|
||||
from dateutil import tz
|
||||
import xbmcaddon
|
||||
import xbmc
|
||||
import xbmcvfs
|
||||
from kodi_six.utils import py2_encode, py2_decode
|
||||
from six import ensure_text, ensure_binary, text_type
|
||||
from six.moves.urllib.parse import urlencode
|
||||
|
||||
@@ -40,7 +41,8 @@ def kodi_version():
|
||||
else:
|
||||
default_versionstring = "19.1 (19.1.0) Git:20210509-85e05228b4"
|
||||
|
||||
version_string = xbmc.getInfoLabel('System.BuildVersion') or default_versionstring
|
||||
version_string = xbmc.getInfoLabel(
|
||||
'System.BuildVersion') or default_versionstring
|
||||
return int(version_string.split(' ', 1)[0].split('.', 1)[0])
|
||||
|
||||
|
||||
@@ -52,7 +54,7 @@ def get_jellyfin_url(path, params):
|
||||
|
||||
def get_checksum(item):
|
||||
userdata = item['UserData']
|
||||
checksum = "%s_%s_%s_%s_%s_%s_%s" % (
|
||||
checksum = "{}_{}_{}_{}_{}_{}_{}".format(
|
||||
item['Etag'],
|
||||
userdata['Played'],
|
||||
userdata['IsFavorite'],
|
||||
@@ -81,14 +83,18 @@ def send_event_notification(method, data=None, hexlify=False):
|
||||
Send events through Kodi's notification system
|
||||
'''
|
||||
data = data or {}
|
||||
data_str = json.dumps(data)
|
||||
|
||||
if hexlify:
|
||||
# Used exclusively for the upnext plugin
|
||||
data = ensure_text(binascii.hexlify(ensure_binary(json.dumps(data))))
|
||||
sender = 'plugin.video.jellycon'
|
||||
data = '"[%s]"' % json.dumps(data).replace('"', '\\"')
|
||||
data_str = ensure_text(binascii.hexlify(ensure_binary(data_str)))
|
||||
data = '["{}"]'.format(data_str)
|
||||
else:
|
||||
data = '"[{}]"'.format(data_str.replace('"', '\\"'))
|
||||
|
||||
xbmc.executebuiltin('NotifyAll(%s, %s, %s)' % (sender, method, data))
|
||||
sender = 'plugin.video.jellycon'
|
||||
|
||||
xbmc.executebuiltin('NotifyAll({}, {}, {})'.format(sender, method, data))
|
||||
|
||||
|
||||
def datetime_from_string(time_string):
|
||||
@@ -97,15 +103,22 @@ def datetime_from_string(time_string):
|
||||
if time_string[-1:] == "Z":
|
||||
time_string = re.sub("[0-9]{1}Z", " UTC", time_string)
|
||||
elif time_string[-6:] == "+00:00":
|
||||
time_string = re.sub("[0-9]{1}\+00:00", " UTC", time_string)
|
||||
time_string = re.sub(
|
||||
"[0-9]{1}\+00:00", " UTC", time_string # noqa: W605
|
||||
)
|
||||
|
||||
try:
|
||||
dt = datetime.strptime(time_string, "%Y-%m-%dT%H:%M:%S.%f %Z")
|
||||
except TypeError:
|
||||
# https://bugs.python.org/issue27400
|
||||
dt = datetime(*(time.strptime(time_string, "%Y-%m-%dT%H:%M:%S.%f %Z")[0:6]))
|
||||
dt = datetime(*(
|
||||
time.strptime(time_string, "%Y-%m-%dT%H:%M:%S.%f %Z")[0:6])
|
||||
)
|
||||
|
||||
# Dates received from the server are in UTC, but parsing them results in naive objects
|
||||
"""
|
||||
Dates received from the server are in UTC, but parsing them results
|
||||
in naive objects
|
||||
"""
|
||||
utc = tz.tzutc()
|
||||
utc_dt = dt.replace(tzinfo=utc)
|
||||
|
||||
@@ -128,7 +141,7 @@ def convert_size(size_bytes):
|
||||
i = int(math.floor(math.log(size_bytes, 1024)))
|
||||
p = math.pow(1024, i)
|
||||
s = round(size_bytes / p, 2)
|
||||
return "%s %s" % (s, size_name[i])
|
||||
return "{} {}".format(s, size_name[i])
|
||||
|
||||
|
||||
def translate_string(string_id):
|
||||
@@ -143,14 +156,20 @@ def translate_string(string_id):
|
||||
def get_device_id():
|
||||
|
||||
window = HomeWindow()
|
||||
username = window.get_property('username')
|
||||
username = window.get_property('user_name')
|
||||
client_id = window.get_property("client_id")
|
||||
hashed_name = hashlib.md5(username.encode()).hexdigest()
|
||||
|
||||
if client_id:
|
||||
if client_id and username:
|
||||
return '{}-{}'.format(client_id, hashed_name)
|
||||
elif client_id and not username:
|
||||
# Quick Connect, needs to be unique so sessions don't overwrite
|
||||
rand_id = uuid4().hex
|
||||
return '{}-{}'.format(client_id, rand_id)
|
||||
|
||||
jellyfin_guid_path = py2_decode(translate_path("special://temp/jellycon_guid"))
|
||||
jellyfin_guid_path = py2_decode(
|
||||
translate_path("special://temp/jellycon_guid")
|
||||
)
|
||||
log.debug("jellyfin_guid_path: {0}".format(jellyfin_guid_path))
|
||||
guid = xbmcvfs.File(jellyfin_guid_path)
|
||||
client_id = guid.read()
|
||||
@@ -178,7 +197,8 @@ def get_version():
|
||||
|
||||
def save_user_details(user_name, user_id, token):
|
||||
settings = xbmcaddon.Addon()
|
||||
save_user_to_settings = settings.getSetting('save_user_to_settings') == 'true'
|
||||
save_user_to_settings = settings.getSetting(
|
||||
'save_user_to_settings') == 'true'
|
||||
addon_data = translate_path(xbmcaddon.Addon().getAddonInfo('profile'))
|
||||
|
||||
# Save to a config file for reference later if desired
|
||||
@@ -186,7 +206,7 @@ def save_user_details(user_name, user_id, token):
|
||||
try:
|
||||
with open(os.path.join(addon_data, 'auth.json'), 'rb') as infile:
|
||||
auth_data = json.load(infile)
|
||||
except:
|
||||
except: # noqa
|
||||
# File doesn't exist or is empty
|
||||
auth_data = {}
|
||||
|
||||
@@ -196,7 +216,8 @@ def save_user_details(user_name, user_id, token):
|
||||
}
|
||||
|
||||
with open(os.path.join(addon_data, 'auth.json'), 'wb') as outfile:
|
||||
data = json.dumps(auth_data, sort_keys=True, indent=4, ensure_ascii=False)
|
||||
data = json.dumps(
|
||||
auth_data, sort_keys=True, indent=4, ensure_ascii=False)
|
||||
if isinstance(data, text_type):
|
||||
data = data.encode('utf-8')
|
||||
outfile.write(data)
|
||||
@@ -214,18 +235,22 @@ def load_user_details():
|
||||
user_name = window.get_property('user_name')
|
||||
if not user_name:
|
||||
user_name = settings.getSetting('username')
|
||||
save_user_to_settings = settings.getSetting('save_user_to_settings') == 'true'
|
||||
save_user = settings.getSetting('save_user_to_settings') == 'true'
|
||||
addon_data = translate_path(xbmcaddon.Addon().getAddonInfo('profile'))
|
||||
|
||||
if save_user_to_settings:
|
||||
if save_user:
|
||||
try:
|
||||
with open(os.path.join(addon_data, 'auth.json'), 'rb') as infile:
|
||||
auth_data = json.load(infile)
|
||||
except:
|
||||
except: # noqa
|
||||
# File doesn't exist yet
|
||||
return {}
|
||||
|
||||
user_data = auth_data.get(user_name, {})
|
||||
# User doesn't exist yet
|
||||
if not user_data:
|
||||
return {}
|
||||
|
||||
user_id = user_data.get('user_id')
|
||||
auth_token = user_data.get('token')
|
||||
|
||||
@@ -240,6 +265,34 @@ def load_user_details():
|
||||
return {}
|
||||
|
||||
|
||||
def get_saved_users():
|
||||
settings = xbmcaddon.Addon()
|
||||
save_user = settings.getSetting('save_user_to_settings') == 'true'
|
||||
addon_data = translate_path(xbmcaddon.Addon().getAddonInfo('profile'))
|
||||
if not save_user:
|
||||
return []
|
||||
|
||||
try:
|
||||
with open(os.path.join(addon_data, 'auth.json'), 'rb') as infile:
|
||||
auth_data = json.load(infile)
|
||||
except: # noqa
|
||||
# File doesn't exist yet
|
||||
return []
|
||||
|
||||
users = []
|
||||
for user, values in auth_data.items():
|
||||
users.append(
|
||||
{
|
||||
'Name': user,
|
||||
'Id': values.get('user_id'),
|
||||
# We need something here for the listitem function
|
||||
'Configuration': {'Dummy': True}
|
||||
}
|
||||
)
|
||||
|
||||
return users
|
||||
|
||||
|
||||
def get_current_user_id():
|
||||
user_details = load_user_details()
|
||||
user_id = user_details.get('user_id')
|
||||
@@ -279,12 +332,13 @@ def get_art_url(data, art_type, parent=False, index=0, server=None):
|
||||
if image_tag_type:
|
||||
image_tag = image_tag_type
|
||||
elif parent is True:
|
||||
if (item_type == "Episode" or item_type == "Season") and art_type == 'Primary':
|
||||
if ((item_type == "Episode" or item_type == "Season") and
|
||||
art_type == 'Primary'):
|
||||
tag_name = 'SeriesPrimaryImageTag'
|
||||
id_name = 'SeriesId'
|
||||
else:
|
||||
tag_name = 'Parent%sImageTag' % art_type
|
||||
id_name = 'Parent%sItemId' % art_type
|
||||
tag_name = 'Parent{}ImageTag'.format(art_type)
|
||||
id_name = 'Parent{}ItemId'.format(art_type)
|
||||
parent_image_id = data.get(id_name)
|
||||
parent_image_tag = data.get(tag_name)
|
||||
if parent_image_id is not None and parent_image_tag is not None:
|
||||
@@ -292,7 +346,9 @@ def get_art_url(data, art_type, parent=False, index=0, server=None):
|
||||
image_tag = parent_image_tag
|
||||
|
||||
# ParentTag not passed for Banner and Art
|
||||
if not image_tag and not ((art_type == 'Banner' or art_type == 'Art') and parent is True):
|
||||
if (not image_tag and
|
||||
not ((art_type == 'Banner' or art_type == 'Art') and
|
||||
parent is True)):
|
||||
return ""
|
||||
|
||||
artwork = "{}/Items/{}/Images/{}/{}?Format=original&Tag={}".format(
|
||||
@@ -303,7 +359,9 @@ def get_art_url(data, art_type, parent=False, index=0, server=None):
|
||||
def image_url(item_id, art_type, index, width, height, image_tag, server):
|
||||
|
||||
# test imageTag e3ab56fe27d389446754d0fb04910a34
|
||||
artwork = "{}/Items/{}/Images/{}/{}?Format=original&Tag={}".format(server, item_id, art_type, index, image_tag)
|
||||
artwork = "{}/Items/{}/Images/{}/{}?Format=original&Tag={}".format(
|
||||
server, item_id, art_type, index, image_tag
|
||||
)
|
||||
if int(width) > 0:
|
||||
artwork += '&MaxWidth={}'.format(width)
|
||||
if int(height) > 0:
|
||||
@@ -366,16 +424,43 @@ def translate_path(path):
|
||||
return xbmc.translatePath(path)
|
||||
|
||||
|
||||
def download_external_sub(language, codec, url):
|
||||
def download_external_sub(language, codec, url, title):
|
||||
addon_settings = xbmcaddon.Addon()
|
||||
verify_cert = addon_settings.getSetting('verify_cert') == 'true'
|
||||
|
||||
# Download the subtitle file
|
||||
r = requests.get(url)
|
||||
r = requests.get(url, verify=verify_cert)
|
||||
r.raise_for_status()
|
||||
|
||||
# Write the subtitle file to the local filesystem
|
||||
file_name = 'Stream.{}.{}'.format(language, codec)
|
||||
file_path = py2_decode(translate_path('special://temp/{}'.format(file_name)))
|
||||
file_name = 'Stream.{}.{}.{}'.format(title, language, codec)
|
||||
file_path = py2_decode(
|
||||
translate_path('special://temp/{}'.format(file_name))
|
||||
)
|
||||
with open(file_path, 'wb') as f:
|
||||
f.write(r.content)
|
||||
|
||||
return file_path
|
||||
|
||||
|
||||
def get_bitrate(enum_value):
|
||||
''' Get the video quality based on add-on settings.
|
||||
Max bit rate supported by server: 2147483 (max signed 32bit integer)
|
||||
'''
|
||||
bitrate = [500, 1000, 1500, 2000, 2500, 3000, 4000, 5000, 6000,
|
||||
7000, 8000, 9000, 10000, 12000, 14000, 16000, 18000,
|
||||
20000, 25000, 30000, 35000, 40000, 100000, 1000000, 2147483]
|
||||
return bitrate[int(enum_value) if enum_value else 24] * 1000
|
||||
|
||||
def get_filtered_items_count_text():
|
||||
settings = xbmcaddon.Addon()
|
||||
if settings.getSetting("hide_x_filtered_items_count") == 'true' :
|
||||
return ""
|
||||
else:
|
||||
return " (" + settings.getSetting("show_x_filtered_items") + ")"
|
||||
|
||||
def seconds_to_ticks(seconds:float):
|
||||
return seconds * 10000000
|
||||
|
||||
def ticks_to_seconds(ticks:int):
|
||||
return round(ticks / 10000000, 1)
|
||||
|
||||
@@ -1,16 +1,15 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import (
|
||||
division, absolute_import, print_function, unicode_literals
|
||||
)
|
||||
|
||||
#################################################################################################
|
||||
|
||||
from __future__ import division, absolute_import, print_function, unicode_literals
|
||||
import json
|
||||
import threading
|
||||
import websocket
|
||||
import time
|
||||
|
||||
import xbmc
|
||||
import xbmcaddon
|
||||
import xbmcgui
|
||||
import websocket
|
||||
|
||||
from .jellyfin import API
|
||||
from .functions import play_action
|
||||
@@ -34,11 +33,11 @@ class WebSocketClient(threading.Thread):
|
||||
|
||||
self.__dict__ = self._shared_state
|
||||
self.monitor = xbmc.Monitor()
|
||||
self.retry_count = 0
|
||||
|
||||
self.device_id = get_device_id()
|
||||
|
||||
self._library_monitor = library_change_monitor
|
||||
self.websocket_error = False
|
||||
|
||||
threading.Thread.__init__(self)
|
||||
|
||||
@@ -158,7 +157,9 @@ class WebSocketClient(threading.Thread):
|
||||
|
||||
elif command == 'SetVolume':
|
||||
volume = arguments['Volume']
|
||||
xbmc.executebuiltin('SetVolume(%s[,showvolumebar])' % volume)
|
||||
xbmc.executebuiltin(
|
||||
'SetVolume({}[,showvolumebar])'.format(volume)
|
||||
)
|
||||
|
||||
elif command == 'SetAudioStreamIndex':
|
||||
index = int(arguments['Index'])
|
||||
@@ -170,7 +171,7 @@ class WebSocketClient(threading.Thread):
|
||||
|
||||
elif command == 'SetRepeatMode':
|
||||
mode = arguments['RepeatMode']
|
||||
xbmc.executebuiltin('xbmc.PlayerControl(%s)' % mode)
|
||||
xbmc.executebuiltin('xbmc.PlayerControl({})'.format(mode))
|
||||
|
||||
elif command == 'DisplayMessage':
|
||||
|
||||
@@ -229,11 +230,16 @@ class WebSocketClient(threading.Thread):
|
||||
xbmc.executebuiltin(builtin[command])
|
||||
|
||||
def on_open(self, ws):
|
||||
# Wait to make sure previous keepalive cycle has ended
|
||||
if self.websocket_error:
|
||||
time.sleep(30)
|
||||
self.websocket_error = False
|
||||
log.debug("Connected")
|
||||
self.retry_count = 0
|
||||
self.post_capabilities()
|
||||
self.send_keepalive(ws)
|
||||
|
||||
def on_error(self, ws, error):
|
||||
self.websocket_error = True
|
||||
log.debug("Error: {0}".format(error))
|
||||
|
||||
def run(self):
|
||||
@@ -253,7 +259,9 @@ class WebSocketClient(threading.Thread):
|
||||
else:
|
||||
server = server.replace('http://', 'ws://')
|
||||
|
||||
websocket_url = "%s/socket?api_key=%s&deviceId=%s" % (server, token, self.device_id)
|
||||
websocket_url = "{}/socket?api_key={}&deviceId={}".format(
|
||||
server, token, self.device_id
|
||||
)
|
||||
log.debug("websocket url: {0}".format(websocket_url))
|
||||
|
||||
self._client = websocket.WebSocketApp(
|
||||
@@ -266,8 +274,7 @@ class WebSocketClient(threading.Thread):
|
||||
|
||||
while not self.monitor.abortRequested():
|
||||
|
||||
time.sleep(self.retry_count * 5)
|
||||
self._client.run_forever(ping_interval=10)
|
||||
self._client.run_forever(reconnect=30)
|
||||
|
||||
if self._stop_websocket:
|
||||
break
|
||||
@@ -276,8 +283,6 @@ class WebSocketClient(threading.Thread):
|
||||
# Abort was requested, exit
|
||||
break
|
||||
|
||||
if self.retry_count < 12:
|
||||
self.retry_count += 1
|
||||
log.debug("Reconnecting WebSocket")
|
||||
|
||||
log.debug("WebSocketClient Stopped")
|
||||
@@ -301,3 +306,22 @@ class WebSocketClient(threading.Thread):
|
||||
)
|
||||
|
||||
api.post_capabilities()
|
||||
|
||||
def send_keepalive(self, ws):
|
||||
# Stop the keepalive cycle if an error has been detected
|
||||
if self.websocket_error:
|
||||
return
|
||||
keepalive_payload = json.dumps({"MessageType": "KeepAlive", "Data": 30})
|
||||
# Send the keepalive, or register an error
|
||||
try:
|
||||
ws.send(keepalive_payload)
|
||||
except:
|
||||
self.websocket_error = True
|
||||
return
|
||||
# Schedule the next message
|
||||
self.schedule_keepalive(ws)
|
||||
|
||||
def schedule_keepalive(self, ws):
|
||||
# Schedule a keepalive message in 30 seconds
|
||||
timer = threading.Timer(30, self.send_keepalive, kwargs={'ws': ws})
|
||||
timer.start()
|
||||
|
||||
73
resources/lib/websocket_client.py.rej
Normal file
73
resources/lib/websocket_client.py.rej
Normal file
@@ -0,0 +1,73 @@
|
||||
@@ -46,7 +46,12 @@
|
||||
result = json.loads(message)
|
||||
message_type = result['MessageType']
|
||||
|
||||
- if message_type == 'Play':
|
||||
+ if message_type == 'ForceKeepAlive':
|
||||
+ timeout_seconds = result.get('Data', 60)
|
||||
+ log.debug("Received ForceKeepAlive with timeout: {0}s".format(timeout_seconds))
|
||||
+ self._send_keep_alive()
|
||||
+
|
||||
+ elif message_type == 'Play':
|
||||
data = result['Data']
|
||||
self._play(data)
|
||||
|
||||
@@ -237,6 +242,9 @@
|
||||
def on_error(self, ws, error):
|
||||
log.debug("Error: {0}".format(error))
|
||||
|
||||
+ def on_close(self, ws, close_status_code, close_msg):
|
||||
+ log.debug("WebSocket closed. Code: {0}, Message: {1}".format(close_status_code, close_msg))
|
||||
+
|
||||
def run(self):
|
||||
|
||||
token = None
|
||||
@@ -259,17 +267,23 @@
|
||||
)
|
||||
log.debug("websocket url: {0}".format(websocket_url))
|
||||
|
||||
- self._client = websocket.WebSocketApp(
|
||||
- websocket_url,
|
||||
- on_open=lambda ws: self.on_open(ws),
|
||||
- on_message=lambda ws, message: self.on_message(ws, message),
|
||||
- on_error=lambda ws, error: self.on_error(ws, error))
|
||||
-
|
||||
log.debug("Starting WebSocketClient")
|
||||
|
||||
while not self.monitor.abortRequested():
|
||||
|
||||
- self._client.run_forever(ping_interval=5, reconnect=13, ping_timeout=2)
|
||||
+ # Create a new WebSocketApp for each connection attempt to avoid
|
||||
+ # memory leaks from reusing a potentially dirty connection object
|
||||
+ self._client = websocket.WebSocketApp(
|
||||
+ websocket_url,
|
||||
+ on_open=lambda ws: self.on_open(ws),
|
||||
+ on_message=lambda ws, message: self.on_message(ws, message),
|
||||
+ on_error=lambda ws, error: self.on_error(ws, error),
|
||||
+ on_close=lambda ws, status, msg: self.on_close(ws, status, msg))
|
||||
+
|
||||
+ # Use ping_interval without ping_timeout to keep connection alive
|
||||
+ # without forcing disconnection. The server's ForceKeepAlive/KeepAlive
|
||||
+ # mechanism handles the actual keepalive logic.
|
||||
+ self._client.run_forever(ping_interval=10)
|
||||
|
||||
if self._stop_websocket:
|
||||
break
|
||||
@@ -291,6 +305,17 @@
|
||||
self._client.close()
|
||||
log.debug("Stopping WebSocket (stop_client called)")
|
||||
|
||||
+ def _send_keep_alive(self):
|
||||
+ """Send a KeepAlive message to the server to maintain the connection."""
|
||||
+ try:
|
||||
+ keep_alive_message = json.dumps({
|
||||
+ 'MessageType': 'KeepAlive'
|
||||
+ })
|
||||
+ self._client.send(keep_alive_message)
|
||||
+ log.debug("Sent KeepAlive message")
|
||||
+ except Exception as error:
|
||||
+ log.debug("Error sending KeepAlive: {0}".format(error))
|
||||
+
|
||||
def post_capabilities(self):
|
||||
|
||||
settings = xbmcaddon.Addon()
|
||||
@@ -1,14 +1,21 @@
|
||||
from __future__ import division, absolute_import, print_function, unicode_literals
|
||||
from __future__ import (
|
||||
division, absolute_import, print_function, unicode_literals
|
||||
)
|
||||
|
||||
import hashlib
|
||||
import random
|
||||
import time
|
||||
import datetime
|
||||
|
||||
import xbmcaddon
|
||||
import xbmcplugin
|
||||
import xbmcgui
|
||||
import hashlib
|
||||
import random
|
||||
import time
|
||||
|
||||
from .jellyfin import api
|
||||
from .utils import get_jellyfin_url, image_url, get_current_user_id, get_art_url, get_default_filters, kodi_version
|
||||
from .utils import (
|
||||
get_jellyfin_url, image_url, get_current_user_id,
|
||||
get_art_url, get_default_filters
|
||||
)
|
||||
from .lazylogger import LazyLogger
|
||||
from .kodi_utils import HomeWindow
|
||||
from .dir_functions import process_directory
|
||||
@@ -60,6 +67,85 @@ def set_random_movies():
|
||||
home_window.set_property("random-movies", movies_list_string)
|
||||
home_window.set_property("random-movies-changed", new_widget_hash)
|
||||
|
||||
@timer
|
||||
def set_random_tvshows():
|
||||
log.debug("set_random_tvshows Called")
|
||||
|
||||
settings = xbmcaddon.Addon()
|
||||
item_limit = settings.getSetting("show_x_filtered_items")
|
||||
hide_watched = settings.getSetting("hide_watched") == "true"
|
||||
user_id = get_current_user_id()
|
||||
|
||||
url_params = {}
|
||||
url_params["Recursive"] = True
|
||||
url_params["limit"] = item_limit
|
||||
if hide_watched:
|
||||
url_params["IsPlayed"] = False
|
||||
url_params["SortBy"] = "Random"
|
||||
url_params["IncludeItemTypes"] = "Series"
|
||||
url_params["ImageTypeLimit"] = 0
|
||||
|
||||
url = get_jellyfin_url("/Users/{}/Items".format(user_id), url_params)
|
||||
|
||||
results = api.get(url)
|
||||
|
||||
random_tvshows_list = []
|
||||
if results is not None:
|
||||
items = results.get("Items", [])
|
||||
for item in items:
|
||||
random_tvshows_list.append(item.get("Id"))
|
||||
|
||||
random.shuffle(random_tvshows_list)
|
||||
tvshow_list_string = ",".join(random_tvshows_list)
|
||||
home_window = HomeWindow()
|
||||
m = hashlib.md5()
|
||||
m.update(tvshow_list_string.encode())
|
||||
new_widget_hash = m.hexdigest()
|
||||
|
||||
log.debug("set_random_tvshows: {0}".format(tvshow_list_string))
|
||||
log.debug("set_random_tvshows: {0}".format(new_widget_hash))
|
||||
home_window.set_property("random-tvshows", tvshow_list_string)
|
||||
home_window.set_property("random-tvshows-changed", new_widget_hash)
|
||||
|
||||
@timer
|
||||
def set_random_all():
|
||||
log.debug("set_random_all Called")
|
||||
|
||||
settings = xbmcaddon.Addon()
|
||||
item_limit = settings.getSetting("show_x_filtered_items")
|
||||
hide_watched = settings.getSetting("hide_watched") == "true"
|
||||
user_id = get_current_user_id()
|
||||
|
||||
url_params = {}
|
||||
url_params["Recursive"] = True
|
||||
url_params["limit"] = item_limit
|
||||
if hide_watched:
|
||||
url_params["IsPlayed"] = False
|
||||
url_params["SortBy"] = "Random"
|
||||
url_params["IncludeItemTypes"] = "Movie,Series"
|
||||
url_params["ImageTypeLimit"] = 0
|
||||
|
||||
url = get_jellyfin_url("/Users/{}/Items".format(user_id), url_params)
|
||||
|
||||
results = api.get(url)
|
||||
|
||||
random_items = []
|
||||
if results is not None:
|
||||
items = results.get("Items", [])
|
||||
for item in items:
|
||||
random_items.append(item.get("Id"))
|
||||
|
||||
random.shuffle(random_items)
|
||||
item_list_string = ",".join(random_items)
|
||||
home_window = HomeWindow()
|
||||
m = hashlib.md5()
|
||||
m.update(item_list_string.encode())
|
||||
new_widget_hash = m.hexdigest()
|
||||
|
||||
log.debug("set_random_all: {0}".format(item_list_string))
|
||||
log.debug("set_random_all: {0}".format(new_widget_hash))
|
||||
home_window.set_property("random-all", item_list_string)
|
||||
home_window.set_property("random-all-changed", new_widget_hash)
|
||||
|
||||
def set_background_image(force=False):
|
||||
log.debug("set_background_image Called forced={0}".format(force))
|
||||
@@ -77,8 +163,9 @@ def set_background_image(force=False):
|
||||
background_items = []
|
||||
|
||||
if len(background_items) == 0:
|
||||
log.debug("set_background_image: Need to load more backgrounds {0} - {1}".format(
|
||||
len(background_items), background_current_item))
|
||||
log.debug("Need to load more backgrounds {0} - {1}".format(
|
||||
len(background_items), background_current_item)
|
||||
)
|
||||
|
||||
url_params = {}
|
||||
url_params["Recursive"] = True
|
||||
@@ -106,13 +193,17 @@ def set_background_image(force=False):
|
||||
background_items.append(item_background)
|
||||
|
||||
log.debug("set_background_image: Loaded {0} more backgrounds".format(
|
||||
len(background_items)))
|
||||
len(background_items))
|
||||
)
|
||||
|
||||
if len(background_items) > 0:
|
||||
bg_image = background_items[background_current_item].get("image")
|
||||
label = background_items[background_current_item].get("name")
|
||||
log.debug(
|
||||
"set_background_image: {0} - {1} - {2}".format(background_current_item, label, bg_image))
|
||||
"set_background_image: {0} - {1} - {2}".format(
|
||||
background_current_item, label, bg_image
|
||||
)
|
||||
)
|
||||
|
||||
background_current_item += 1
|
||||
if background_current_item >= len(background_items):
|
||||
@@ -171,7 +262,9 @@ def check_for_new_content():
|
||||
url_params["IncludeItemTypes"] = "Movie,Episode"
|
||||
url_params["ImageTypeLimit"] = 0
|
||||
|
||||
played_url = get_jellyfin_url('/Users/{}/Items'.format(user_id), url_params)
|
||||
played_url = get_jellyfin_url(
|
||||
'/Users/{}/Items'.format(user_id), url_params
|
||||
)
|
||||
|
||||
result = api.get(played_url)
|
||||
log.debug("LATEST_PLAYED_ITEM: {0}".format(result))
|
||||
@@ -215,7 +308,9 @@ def get_widget_content_cast(handle, params):
|
||||
if not result:
|
||||
return
|
||||
|
||||
if result.get("Type", "") in ["Episode", "Season"] and params.get("auto", "true") == "true":
|
||||
if (result.get("Type", "") in ["Episode", "Season"] and
|
||||
params.get("auto", "true") == "true"):
|
||||
|
||||
series_id = result.get("SeriesId")
|
||||
if series_id:
|
||||
params["id"] = series_id
|
||||
@@ -236,7 +331,9 @@ def get_widget_content_cast(handle, params):
|
||||
person_thumbnail = None
|
||||
if person_tag:
|
||||
person_thumbnail = image_url(
|
||||
person_id, "Primary", 0, 400, 400, person_tag, server=server)
|
||||
person_id, "Primary", 0, 400, 400,
|
||||
person_tag, server=server
|
||||
)
|
||||
|
||||
list_item = xbmcgui.ListItem(label=person_name, offscreen=True)
|
||||
|
||||
@@ -255,8 +352,8 @@ def get_widget_content_cast(handle, params):
|
||||
if person_role:
|
||||
list_item.setLabel2(person_role)
|
||||
|
||||
item_tupple = ("", list_item, False)
|
||||
list_items.append(item_tupple)
|
||||
item_tuple = ("", list_item, False)
|
||||
list_items.append(item_tuple)
|
||||
|
||||
xbmcplugin.setContent(handle, 'artists')
|
||||
xbmcplugin.addDirectoryItems(handle, list_items)
|
||||
@@ -315,6 +412,11 @@ def get_widget_content(handle, params):
|
||||
xbmcplugin.setContent(handle, 'movies')
|
||||
url_params["Ids"] = home_window.get_property("random-movies")
|
||||
|
||||
elif widget_type == "random_tvshows":
|
||||
home_window = HomeWindow()
|
||||
xbmcplugin.setContent(handle, 'tvshows')
|
||||
url_params["Ids"] = home_window.get_property("random-tvshows")
|
||||
|
||||
elif widget_type == "recent_tvshows":
|
||||
xbmcplugin.setContent(handle, 'episodes')
|
||||
url_verb = '/Users/{}/Items/Latest'.format(user_id)
|
||||
@@ -360,7 +462,14 @@ def get_widget_content(handle, params):
|
||||
url_params["Limit"] = item_limit
|
||||
url_params["userid"] = user_id
|
||||
url_params["Recursive"] = True
|
||||
url_params["enableResumable"] = False
|
||||
url_params["ImageTypeLimit"] = 1
|
||||
# check if rewatching is enabled and combine is disabled
|
||||
rewatch_days = int(settings.getSetting("rewatch_days"))
|
||||
if rewatch_days > 0 and settings.getSetting("rewatch_combine") != "true":
|
||||
rewatch_since = datetime.datetime.today() - datetime.timedelta(days=rewatch_days)
|
||||
url_params["nextUpDateCutoff"] = rewatch_since.strftime("%Y-%m-%d")
|
||||
url_params["enableRewatching"] = True
|
||||
# Collect InProgress items to be combined with NextUp
|
||||
inprogress_url_verb = "/Users/{}/Items".format(user_id)
|
||||
inprogress_url_params = url_params.copy()
|
||||
@@ -372,6 +481,8 @@ def get_widget_content(handle, params):
|
||||
inprogress_url_params["IncludeItemTypes"] = "Episode"
|
||||
inprogress_url_params["Limit"] = item_limit
|
||||
|
||||
|
||||
|
||||
elif widget_type == "movie_recommendations":
|
||||
suggested_items_url_params = {}
|
||||
suggested_items_url_params["userId"] = user_id
|
||||
@@ -387,12 +498,19 @@ def get_widget_content(handle, params):
|
||||
while len(ids) < item_limit and suggested_items:
|
||||
items = suggested_items[set_id]
|
||||
log.debug(
|
||||
"BaselineItemName : {0} - {1}".format(set_id, items.get("BaselineItemName")))
|
||||
"BaselineItemName : {0} - {1}".format(
|
||||
set_id, items.get("BaselineItemName")
|
||||
)
|
||||
)
|
||||
items = items["Items"]
|
||||
rand = random.randint(0, len(items) - 1)
|
||||
item = items[rand]
|
||||
if item["Type"] == "Movie" and item["Id"] not in ids and (not item["UserData"]["Played"] or not hide_watched):
|
||||
|
||||
if (item["Type"] == "Movie" and item["Id"] not in ids and
|
||||
(not item["UserData"]["Played"] or not hide_watched)):
|
||||
|
||||
ids.append(item["Id"])
|
||||
|
||||
del items[rand]
|
||||
if len(items) == 0:
|
||||
del suggested_items[set_id]
|
||||
@@ -404,24 +522,69 @@ def get_widget_content(handle, params):
|
||||
log.debug("Recommended Items : {0}".format(len(ids)))
|
||||
url_params["Ids"] = id_list
|
||||
|
||||
elif widget_type == "random_all":
|
||||
home_window = HomeWindow()
|
||||
xbmcplugin.setContent(handle, 'movies')
|
||||
url_params["Ids"] = home_window.get_property("random-all")
|
||||
|
||||
elif widget_type == "recent_all":
|
||||
xbmcplugin.setContent(handle, 'movies')
|
||||
url_verb = '/Users/{}/Items/Latest'.format(user_id)
|
||||
url_params["GroupItems"] = True
|
||||
url_params["Recursive"] = True
|
||||
url_params["SortBy"] = "DateCreated"
|
||||
url_params["SortOrder"] = "Descending"
|
||||
url_params["Limit"] = 45
|
||||
url_params["Filters"] = "IsNotFolder"
|
||||
url_params["Fields"] = get_default_filters()
|
||||
if hide_watched:
|
||||
url_params["IsPlayed"] = False
|
||||
url_params["IsVirtualUnaired"] = False
|
||||
url_params["IncludeItemTypes"] = "Episode, Movie"
|
||||
url_params["ImageTypeLimit"] = 1
|
||||
|
||||
elif widget_type == "favorites_all":
|
||||
home_window = HomeWindow()
|
||||
xbmcplugin.setContent(handle, 'movies')
|
||||
|
||||
url_params.update({
|
||||
"Filters": "IsFavorite",
|
||||
"IncludeItemTypes": "Movie,Series",
|
||||
"Recursive": True,
|
||||
"SortBy": "Name",
|
||||
"SortOrder": "Ascending",
|
||||
})
|
||||
|
||||
items_url = get_jellyfin_url(url_verb, url_params)
|
||||
|
||||
if url_params.get('IncludeItemTypes', '') == 'Episode' or params.get('type', '') == 'nextup_episodes':
|
||||
if (url_params.get('IncludeItemTypes', '') == 'Episode' or
|
||||
params.get('type', '') == 'nextup_episodes'):
|
||||
params["name_format"] = "Episode|episode_name_format"
|
||||
|
||||
list_items, detected_type, total_records = process_directory(
|
||||
items_url, None, params, use_cached_widget_data)
|
||||
|
||||
# Combine In Progress and Next Up Episodes, append next up after In Progress
|
||||
# Combine In Progress and Next Up Episodes, add next up after In Progress
|
||||
if widget_type == "nextup_episodes":
|
||||
inprogress_url = get_jellyfin_url(
|
||||
inprogress_url_verb, inprogress_url_params)
|
||||
|
||||
params["name_format"] = "Episode|episode_name_format"
|
||||
list_items_inprogress, detected_type, total_records = process_directory(
|
||||
inprogress, detected_type, total_records = process_directory(
|
||||
inprogress_url, None, params, use_cached_widget_data)
|
||||
|
||||
list_items = list_items_inprogress + list_items
|
||||
list_items = inprogress + list_items
|
||||
|
||||
# add rewatch combine is enabled
|
||||
if rewatch_days > 0 and settings.getSetting("rewatch_combine") == "true":
|
||||
rewatch_since = datetime.datetime.today() - datetime.timedelta(days=rewatch_days)
|
||||
url_params["nextUpDateCutoff"] = rewatch_since.strftime("%Y-%m-%d")
|
||||
url_params["enableRewatching"] = True
|
||||
rewatch_items_url = get_jellyfin_url(url_verb, url_params)
|
||||
rewatch_items, detected_type, total_records = process_directory(rewatch_items_url, None, params, use_cached_widget_data)
|
||||
for ri in rewatch_items:
|
||||
if not any(i[1].getProperty("id") == ri[1].getProperty("id") for i in list_items):
|
||||
list_items.append(ri)
|
||||
|
||||
if detected_type is not None:
|
||||
# if the media type is not set then try to use the detected type
|
||||
@@ -434,7 +597,7 @@ def get_widget_content(handle, params):
|
||||
content_type = 'episodes'
|
||||
elif detected_type == "Series":
|
||||
content_type = 'tvshows'
|
||||
elif detected_type == "Music" or detected_type == "Audio" or detected_type == "Musicalbum":
|
||||
elif detected_type in ["Music", "Audio", "Musicalbum"]:
|
||||
content_type = 'songs'
|
||||
|
||||
if content_type:
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<setting label="30388" type="lsep"/>
|
||||
<setting label="30011" type="action" action="RunScript(plugin.video.jellycon,0,?mode=DETECT_SERVER_USER)" option="close"/>
|
||||
<setting id="ipaddress" type="text" label="30000" default="" visible="false" enable="false" />
|
||||
<setting id="protocol" type="select" label="30390" lvalues="30391|30392" default="0" visible="false"/>
|
||||
<setting id="protocol" type="select" label="30390" lvalues="30391|30392" default="0" visible="false"/>
|
||||
<setting id="port" type="text" label="30001" default="8096" visible="false" enable="false" />
|
||||
<setting id="server_address" type="text" label="30000" default="" visible="true" enable="true" />
|
||||
<setting id="verify_cert" type="bool" label="30003" default="true" visible="true" enable="true" />
|
||||
@@ -28,23 +28,37 @@
|
||||
|
||||
<setting label="30238" type="lsep"/>
|
||||
<setting type="sep" />
|
||||
<setting id="max_stream_bitrate" type="slider" label="30208" default="75000" range="400,100,100000" option="int" visible="true"/>
|
||||
<setting id="max_stream_bitrate" type="enum" label="30208" values="0.5 Mbps|1 Mbps|1.5 Mbps|2.0 Mbps|2.5 Mbps|3.0 Mbps|4.0 Mbps|5.0 Mbps|6.0 Mbps|7.0 Mbps|8.0 Mbps|9.0 Mbps|10.0 Mbps|12.0 Mbps|14.0 Mbps|16.0 Mbps|18.0 Mbps|20.0 Mbps|25.0 Mbps|30.0 Mbps|35.0 Mbps|40.0 Mbps|100.0 Mbps|1000.0 Mbps [default]|Maximum" visible="true" default="23" />
|
||||
<setting id="allow_direct_file_play" type="bool" label="30433" default="false" visible="true" enable="true" />
|
||||
<setting id="transcode_target_video_codec" type="select" label="30679" lvalues="30680|30681|30683" default="0" visible="true" />
|
||||
<setting id="force_transcode_h264" type="bool" label="30682" default="false" visible="true" />
|
||||
<setting id="force_transcode_h265" type="bool" label="30236" default="false" visible="true" enable="true" />
|
||||
<setting id="force_transcode_mpeg2" type="bool" label="30239" default="false" visible="true" enable="true" />
|
||||
<setting id="force_transcode_msmpeg4v3" type="bool" label="30240" default="false" visible="true" enable="true" />
|
||||
<setting id="force_transcode_mpeg4" type="bool" label="30241" default="false" visible="true" enable="true" />
|
||||
<setting id="force_transcode_av1" type="bool" label="30242" default="false" visible="true" enable="true" />
|
||||
<setting id="direct_stream_sub_select" type="select" label="30379" lvalues="30380|30381|30382" default="0" visible="true"/>
|
||||
|
||||
<setting label="30211" type="lsep"/>
|
||||
<setting type="sep" />
|
||||
<setting id="force_max_stream_bitrate" type="slider" label="30434" default="7000" range="400,100,15000" option="int" visible="true"/>
|
||||
<setting id="force_max_stream_bitrate" type="enum" label="30434" values="0.5 Mbps|1 Mbps|1.5 Mbps|2.0 Mbps|2.5 Mbps|3.0 Mbps|4.0 Mbps|5.0 Mbps|6.0 Mbps|7.0 Mbps [default]|8.0 Mbps|9.0 Mbps|10.0 Mbps|12.0 Mbps|14.0 Mbps|16.0 Mbps|18.0 Mbps|20.0 Mbps|25.0 Mbps|30.0 Mbps|35.0 Mbps|40.0 Mbps|100.0 Mbps|1000.0 Mbps|Maximum" visible="true" default="9" />
|
||||
<setting id="playback_max_width" type="select" label="30212" values="640|720|1024|1280|1440|1600|1920|2600|4096" default="1920" visible="true"/>
|
||||
<setting id="playback_video_force_8" type="bool" label="30213" default="false" visible="true" enable="true"/>
|
||||
<setting id="audio_codec" type="select" label="30419" values="ac3|aac" default="ac3"/>
|
||||
<setting id="audio_playback_bitrate" type="select" label="30418" values="128|160|192|256|320|384|448|640" default="256" visible="true"/>
|
||||
<setting id="audio_max_channels" type="slider" label="30420" default="8" range="2,1,8" option="int" visible="true"/>
|
||||
|
||||
<setting label="30685" type="lsep"/>
|
||||
<setting type="sep" />
|
||||
<setting id="preferred_audio_language" type="select" label="30686" lvalues="30691|30692|30693|30694|30695|30696|30697|30698" default="0" visible="true"/>
|
||||
<setting id="auto_select_default_audio" type="bool" label="30687" default="true" visible="true"/>
|
||||
<setting id="preferred_subtitle_language" type="select" label="30688" lvalues="30699|30691|30692|30693|30694|30695|30696|30697|30698" default="1" visible="true"/>
|
||||
<setting id="prefer_forced_subtitles" type="bool" label="30689" default="true" visible="true"/>
|
||||
<setting id="only_forced_subtitles" type="bool" label="30702" default="true" visible="true"/>
|
||||
<setting id="subtitle_codec_preference" type="select" label="30703" lvalues="30704|30705|30706" default="0" visible="true"/>
|
||||
<setting id="auto_no_subtitles_if_no_match" type="bool" label="30700" default="true" visible="true"/>
|
||||
<setting id="max_play_queue" type="slider" label="30447" default="200" range="20, 10, 1000" option="int" visible="true"/>
|
||||
|
||||
</category>
|
||||
<category label="30214">
|
||||
|
||||
@@ -79,6 +93,7 @@
|
||||
<setting id="addCounts" type="bool" label="30116" default="false" visible="true" enable="true" />
|
||||
<setting id="addResumePercent" type="bool" label="30118" default="false" visible="true" enable="true" />
|
||||
<setting id="addSubtitleAvailable" type="bool" label="30163" default="false" visible="true" enable="true" />
|
||||
<setting id="hide_x_filtered_items_count" type="bool" label="30453" default="false" visible="true" enable="true" />
|
||||
<setting id="include_overview" type="bool" label="30181" default="true" visible="true" enable="true" />
|
||||
<setting id="include_media" type="bool" label="30182" default="true" visible="true" enable="true" />
|
||||
<setting id="add_user_ratings" type="bool" label="30348" default="true" visible="true" enable="true" />
|
||||
@@ -94,16 +109,48 @@
|
||||
<setting id="show_empty_folders" type="bool" label="30328" default="false" visible="true" enable="true" />
|
||||
<setting id="hide_watched" type="bool" label="30432" default="true" visible="true" enable="true" />
|
||||
|
||||
<setting label="30450" type="lsep"/>
|
||||
<setting type="sep" />
|
||||
<setting id="rewatch_days" type="slider" label="30451" default="0" range="0,1,365" option="int" visible="true"/>
|
||||
<setting id="rewatch_combine" type="bool" label="30452" default="false" visible="true" enable="true" />
|
||||
|
||||
<setting label="30223" type="lsep"/>
|
||||
<setting type="sep" />
|
||||
<setting id="moviePageSize" type="slider" label="30331" default="0" range="0,1,100" option="int" visible="true"/>
|
||||
<setting id="showPageSize" type="slider" label="30678" default="0" range="0,1,100" option="int" visible="true"/>
|
||||
<setting id="show_x_filtered_items" type="slider" label="30018" default="20" range="5,1,100" option="int" visible="true"/>
|
||||
|
||||
<setting label="30224" type="lsep"/>
|
||||
<setting type="sep" />
|
||||
<setting id="widget_select_action" type="select" label="30026" lvalues="30313|30314" default="0" visible="true"/>
|
||||
<setting id="interface_mode" type="select" label="30225" lvalues="30226|30227" default="0" visible="true"/>
|
||||
|
||||
</category>
|
||||
|
||||
<category label="30666">
|
||||
|
||||
<setting label="30670" type="lsep"/>
|
||||
<setting id="intro_skipper_action" type="select" label="30667" lvalues="30673|30672|30674" default="0" visible="true" enable="true" />
|
||||
<setting id="intro_skipper_start_offset" type="slider" label="30668" default="0" range="0,1,3" option="int" visible="true" enable="true"/>
|
||||
<setting id="intro_skipper_end_offset" type="slider" label="30669" default="1" range="0,1,3" option="int" visible="true" enable="true"/>
|
||||
<setting label="30671" type="lsep"/>
|
||||
<setting id="credit_skipper_action" type="select" label="30667" lvalues="30673|30672|30674" default="0" visible="true" enable="true" />
|
||||
<setting id="credit_skipper_start_offset" type="slider" label="30668" default="0" range="0,1,3" option="int" visible="true" enable="true" />
|
||||
<setting id="credit_skipper_end_offset" type="slider" label="30669" default="1" range="0,1,3" option="int" visible="true" enable="true" />
|
||||
<setting label="30675" type="lsep"/>
|
||||
<setting id="commercial_skipper_action" type="select" label="30667" lvalues="30673|30672|30674" default="0" visible="true" enable="true" />
|
||||
<setting id="commercial_skipper_start_offset" type="slider" label="30668" default="0" range="0,1,3" option="int" visible="true" enable="true"/>
|
||||
<setting id="commercial_skipper_end_offset" type="slider" label="30669" default="1" range="0,1,3" option="int" visible="true" enable="true"/>
|
||||
<setting label="30676" type="lsep"/>
|
||||
<setting id="preview_skipper_action" type="select" label="30667" lvalues="30673|30672|30674" default="0" visible="true" enable="true" />
|
||||
<setting id="preview_skipper_start_offset" type="slider" label="30668" default="0" range="0,1,3" option="int" visible="true" enable="true" />
|
||||
<setting id="preview_skipper_end_offset" type="slider" label="30669" default="1" range="0,1,3" option="int" visible="true" enable="true" />
|
||||
<setting label="30677" type="lsep"/>
|
||||
<setting id="recap_skipper_action" type="select" label="30667" lvalues="30673|30672|30674" default="0" visible="true" enable="true" />
|
||||
<setting id="recap_skipper_start_offset" type="slider" label="30668" default="0" range="0,1,3" option="int" visible="true" enable="true"/>
|
||||
<setting id="recap_skipper_end_offset" type="slider" label="30669" default="1" range="0,1,3" option="int" visible="true" enable="true"/>
|
||||
</category>
|
||||
|
||||
<category label="30111">
|
||||
|
||||
<setting label="30343" type="lsep"/>
|
||||
@@ -122,7 +169,8 @@
|
||||
<setting id="profile_count" type="slider" label="30010" default="0" range="0,1,20" option="int" visible="true" />
|
||||
<setting id="log_debug" type="bool" label="30027" default="false" visible="true" enable="true" />
|
||||
<setting id="log_timing" type="bool" label="30015" default="false" visible="true" enable="true" />
|
||||
<setting id="use_cache" type="bool" label="30345" default="true" visible="true" enable="true" />
|
||||
<setting id="disable_disk_cache" type="bool" label="30684" default="true" visible="true" enable="true" />
|
||||
<setting id="use_cache" type="bool" label="30345" default="false" visible="true" enable="true" />
|
||||
<setting id="use_cached_widget_data" type="bool" label="30441" default="false" visible="true" enable="true" />
|
||||
<setting id="showLoadProgress" type="bool" label="30120" default="false" visible="true" enable="true" />
|
||||
<setting id="suppressErrors" type="bool" label="30315" default="false" visible="true" enable="true" />
|
||||
|
||||
@@ -1,68 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<window id="3301" type="dialog">
|
||||
<defaultcontrol always="true">3010</defaultcontrol>
|
||||
<zorder>2</zorder>
|
||||
<coordinates>
|
||||
<system>1</system>
|
||||
<left>450</left>
|
||||
<top>200</top>
|
||||
</coordinates>
|
||||
<controls>
|
||||
|
||||
<control type="image">
|
||||
<left>0</left>
|
||||
<top>0</top>
|
||||
<width>400</width>
|
||||
<height>270</height>
|
||||
<texture border="40">bg.png</texture>
|
||||
</control>
|
||||
|
||||
<control type="label" id="4">
|
||||
<left>20</left>
|
||||
<top>5</top>
|
||||
<width>360</width>
|
||||
<height>50</height>
|
||||
<label>Heading</label>
|
||||
<font>font45_title</font>
|
||||
<align>center</align>
|
||||
</control>
|
||||
|
||||
<control type="textbox" id="3">
|
||||
<left>20</left>
|
||||
<top>65</top>
|
||||
<width>360</width>
|
||||
<height>50</height>
|
||||
<font>font45</font>
|
||||
<align>center</align>
|
||||
</control>
|
||||
|
||||
<control type="button" id="3010">
|
||||
<texturenofocus border="1" colordiffuse="ff161616">white.png</texturenofocus>
|
||||
<texturefocus border="1" colordiffuse="ff525252">white.png</texturefocus>
|
||||
<left>20</left>
|
||||
<top>135</top>
|
||||
<width>360</width>
|
||||
<height>40</height>
|
||||
<label></label>
|
||||
<onup></onup>
|
||||
<ondown>3011</ondown>
|
||||
<font>font14</font>
|
||||
<align>center</align>
|
||||
</control>
|
||||
|
||||
<control type="button" id="3011">
|
||||
<texturenofocus border="1" colordiffuse="ff161616">white.png</texturenofocus>
|
||||
<texturefocus border="1" colordiffuse="ff525252">white.png</texturefocus>
|
||||
<left>20</left>
|
||||
<top>195</top>
|
||||
<width>360</width>
|
||||
<height>40</height>
|
||||
<label></label>
|
||||
<onup>3010</onup>
|
||||
<ondown>3012</ondown>
|
||||
<font>font14</font>
|
||||
<align>center</align>
|
||||
</control>
|
||||
|
||||
</controls>
|
||||
</window>
|
||||
25
resources/skins/default/720p/SkipDialog.xml
Normal file
25
resources/skins/default/720p/SkipDialog.xml
Normal file
@@ -0,0 +1,25 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<window id="10000">
|
||||
<defaultcontrol always="true">9000</defaultcontrol>
|
||||
<zorder>2</zorder>
|
||||
<coordinates>
|
||||
<system>1</system>
|
||||
<left>0</left>
|
||||
<top>0</top>
|
||||
</coordinates>
|
||||
|
||||
<controls>
|
||||
<control type="button" id="9000">
|
||||
<left>1020</left>
|
||||
<top>550</top>
|
||||
<width>150</width>
|
||||
<height>65</height>
|
||||
<visible>true</visible>
|
||||
<label>Skip</label>
|
||||
<align>center</align>
|
||||
<texture border="1" colordiffuse="ff161616">white.png</texture>
|
||||
<font>font12</font>
|
||||
<onright>3014</onright>
|
||||
</control>
|
||||
</controls>
|
||||
</window>
|
||||
53
service.py
53
service.py
@@ -11,7 +11,7 @@ import xbmcgui
|
||||
from resources.lib.lazylogger import LazyLogger
|
||||
from resources.lib.play_utils import Service, PlaybackService, send_progress
|
||||
from resources.lib.kodi_utils import HomeWindow
|
||||
from resources.lib.widgets import set_background_image, set_random_movies
|
||||
from resources.lib.widgets import set_background_image, set_random_movies, set_random_tvshows, set_random_all
|
||||
from resources.lib.websocket_client import WebSocketClient
|
||||
from resources.lib.menu_functions import set_library_window_values
|
||||
from resources.lib.server_detect import check_server, check_connection_speed
|
||||
@@ -20,16 +20,20 @@ from resources.lib.datamanager import clear_old_cache_data
|
||||
from resources.lib.tracking import set_timing_enabled
|
||||
from resources.lib.image_server import HttpImageServerThread
|
||||
from resources.lib.playnext import PlayNextService
|
||||
from resources.lib.intro_skipper import IntroSkipperService
|
||||
|
||||
settings = xbmcaddon.Addon()
|
||||
|
||||
log_timing_data = settings.getSetting('log_timing') == "true"
|
||||
if log_timing_data:
|
||||
set_timing_enabled(True)
|
||||
try:
|
||||
settings = xbmcaddon.Addon()
|
||||
log_timing_data = settings.getSetting('log_timing') == "true"
|
||||
if log_timing_data:
|
||||
set_timing_enabled(True)
|
||||
except Exception:
|
||||
# During installation/update, addon might not be fully registered yet
|
||||
pass
|
||||
|
||||
# clear user and token when logging in
|
||||
home_window = HomeWindow()
|
||||
home_window.clear_property("userid")
|
||||
home_window.clear_property("user_name")
|
||||
home_window.clear_property("AccessToken")
|
||||
home_window.clear_property("Params")
|
||||
|
||||
@@ -63,6 +67,8 @@ last_progress_update = time.time()
|
||||
last_content_check = time.time()
|
||||
last_background_update = 0
|
||||
last_random_movie_update = 0
|
||||
last_random_tvshow_update = 0
|
||||
last_random_all_update = 0
|
||||
|
||||
# start the library update monitor
|
||||
library_change_monitor = LibraryChangeMonitor()
|
||||
@@ -87,6 +93,10 @@ if context_menu:
|
||||
context_monitor = ContextMonitor()
|
||||
context_monitor.start()
|
||||
|
||||
# Start the skip service monitor
|
||||
intro_skipper = IntroSkipperService(monitor)
|
||||
intro_skipper.start()
|
||||
|
||||
background_interval = int(settings.getSetting('background_interval'))
|
||||
newcontent_interval = int(settings.getSetting('new_content_check_interval'))
|
||||
random_movie_list_interval = int(settings.getSetting('random_movie_refresh_interval'))
|
||||
@@ -99,12 +109,11 @@ if enable_logging:
|
||||
time=8000,
|
||||
icon=xbmcgui.NOTIFICATION_WARNING)
|
||||
|
||||
prev_user_id = home_window.get_property("userid")
|
||||
prev_user = home_window.get_property("user_name")
|
||||
first_run = True
|
||||
home_window.set_property('exit', 'False')
|
||||
|
||||
while home_window.get_property('exit') == 'False':
|
||||
|
||||
try:
|
||||
if xbmc.Player().isPlaying():
|
||||
last_random_movie_update = time.time() - (random_movie_list_interval - 15)
|
||||
@@ -118,14 +127,13 @@ while home_window.get_property('exit') == 'False':
|
||||
|
||||
if not screen_saver_active:
|
||||
user_changed = False
|
||||
if prev_user_id != home_window.get_property("userid"):
|
||||
if prev_user != home_window.get_property("user_name"):
|
||||
log.debug("user_change_detected")
|
||||
prev_user_id = home_window.get_property("userid")
|
||||
prev_user = home_window.get_property("user_name")
|
||||
user_changed = True
|
||||
|
||||
if user_changed or first_run:
|
||||
settings = xbmcaddon.Addon()
|
||||
server_speed_check_data = settings.getSetting("server_speed_check_data")
|
||||
settings = xbmcaddon.Addon()
|
||||
server_speed_check_data = settings.getSetting("server_speed_check_data")
|
||||
server_host = settings.getSetting('server_address')
|
||||
if server_host is not None and server_host != "" and server_host != "<none>" and server_host not in server_speed_check_data:
|
||||
@@ -142,6 +150,14 @@ while home_window.get_property('exit') == 'False':
|
||||
last_random_movie_update = time.time()
|
||||
set_random_movies()
|
||||
|
||||
if user_changed or (random_movie_list_interval != 0 and (time.time() - last_random_tvshow_update) > random_movie_list_interval):
|
||||
last_random_tvshow_update = time.time()
|
||||
set_random_tvshows()
|
||||
|
||||
if user_changed or (random_movie_list_interval != 0 and (time.time() - last_random_all_update) > random_movie_list_interval):
|
||||
last_random_all_update = time.time()
|
||||
set_random_all()
|
||||
|
||||
if user_changed or (newcontent_interval != 0 and (time.time() - last_content_check) > newcontent_interval):
|
||||
last_content_check = time.time()
|
||||
library_change_monitor.check_for_updates()
|
||||
@@ -177,16 +193,19 @@ websocket_client.stop_client()
|
||||
# call stop on the library update monitor
|
||||
library_change_monitor.stop()
|
||||
|
||||
# stop the play next episdoe service
|
||||
# stop the play next episode service
|
||||
if play_next_service:
|
||||
play_next_service.stop_servcie()
|
||||
play_next_service.stop_service()
|
||||
|
||||
# call stop on the context menu monitor
|
||||
if context_monitor:
|
||||
context_monitor.stop_monitor()
|
||||
|
||||
# clear user and token when loggin off
|
||||
home_window.clear_property("userid")
|
||||
if intro_skipper:
|
||||
intro_skipper.stop_service()
|
||||
|
||||
# clear user and token when logging off
|
||||
home_window.clear_property("user_name")
|
||||
home_window.clear_property("AccessToken")
|
||||
home_window.clear_property("userimage")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user