150 Commits

Author SHA1 Message Date
mcarlton00
3c89de64cb Merge pull request #272 from jellyfin/prepare-0.7.0
Some checks failed
Build JellyCon / build (py2) (push) Has been cancelled
Build JellyCon / build (py3) (push) Has been cancelled
Prepare for release v0.7.0
2023-02-18 18:29:44 -05:00
jellyfin-bot
79551c52c8 bump version to 0.7.0 2023-02-18 23:24:45 +00:00
mcarlton00
4d3011e23b Merge pull request #271 from mcarlton00/v20-context
Fix context menu in kodi v20
2023-02-18 18:17:02 -05:00
Matt
2cd7c3bd7f Fix context menu in kodi v20 2023-02-18 16:27:14 -05:00
Ruben Kremer
6cc9583604 Translated using Weblate (Dutch)
Currently translated at 100.0% (276 of 276 strings)

Translation: Jellycon/Jellycon
Translate-URL: https://translate.jellyfin.org/projects/jellycon/jellycon/nl/
2023-02-16 16:39:13 -05:00
Imamuzzaki Abu Salam
352f6594e3 Translated using Weblate (Indonesian)
Currently translated at 100.0% (276 of 276 strings)

Translation: Jellycon/Jellycon
Translate-URL: https://translate.jellyfin.org/projects/jellycon/jellycon/id/
2023-02-15 05:39:12 -05:00
jolupa
2373ac2d19 Translated using Weblate (Catalan)
Currently translated at 21.0% (58 of 276 strings)

Translation: Jellycon/Jellycon
Translate-URL: https://translate.jellyfin.org/projects/jellycon/jellycon/ca/
2023-02-12 20:39:12 -05:00
Ilya Garkavenko
dfe7f6372a Translated using Weblate (Russian)
Currently translated at 99.2% (274 of 276 strings)

Translation: Jellycon/Jellycon
Translate-URL: https://translate.jellyfin.org/projects/jellycon/jellycon/ru/
2023-02-12 20:39:11 -05:00
jolupa
3e02b72dde Added translation using Weblate (Catalan) 2023-02-11 12:43:03 -05:00
mcarlton00
88b17be010 Merge pull request #268 from jellyfin/dependabot/pip/kodistubs-approx-eq-20.0
Update kodistubs requirement from ~=19.0 to ~=20.0
2023-02-05 09:30:16 -05:00
mcarlton00
8dd3d774c4 Merge pull request #267 from mcarlton00/genre-shuffle
Add ability to shuffle music genres
2023-02-05 08:46:11 -05:00
Bram
974f233431 Translated using Weblate (Dutch)
Currently translated at 94.9% (262 of 276 strings)

Translation: Jellycon/Jellycon
Translate-URL: https://translate.jellyfin.org/projects/jellycon/jellycon/nl/
2023-02-02 04:51:29 -05:00
KingArthvr_
4fd3ccefb0 Translated using Weblate (German)
Currently translated at 99.6% (275 of 276 strings)

Translation: Jellycon/Jellycon
Translate-URL: https://translate.jellyfin.org/projects/jellycon/jellycon/de/
2023-02-02 04:51:29 -05:00
kid1412621
2067f158fe Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (276 of 276 strings)

Translation: Jellycon/Jellycon
Translate-URL: https://translate.jellyfin.org/projects/jellycon/jellycon/zh_Hans/
2023-02-02 04:51:29 -05:00
myitinos
1ddf270847 Translated using Weblate (Indonesian)
Currently translated at 98.9% (273 of 276 strings)

Translation: Jellycon/Jellycon
Translate-URL: https://translate.jellyfin.org/projects/jellycon/jellycon/id/
2023-01-27 05:51:27 -05:00
Ecor
7073aeb307 Translated using Weblate (Spanish)
Currently translated at 100.0% (276 of 276 strings)

Translation: Jellycon/Jellycon
Translate-URL: https://translate.jellyfin.org/projects/jellycon/jellycon/es/
2023-01-24 02:51:27 -05:00
dependabot[bot]
9af3415ac6 Update kodistubs requirement from ~=19.0 to ~=20.0
Updates the requirements on [kodistubs](https://github.com/romanvm/Kodistubs) to permit the latest version.
- [Release notes](https://github.com/romanvm/Kodistubs/releases)
- [Commits](https://github.com/romanvm/Kodistubs/compare/19.0.0...20.0.0)

---
updated-dependencies:
- dependency-name: kodistubs
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-23 16:03:30 +00:00
Matt
61720a5f90 Increase default max play queue size 2023-01-21 11:28:45 -05:00
Matt
e15a87ef7f Add ability to shuffle music genres 2023-01-21 11:28:23 -05:00
mcarlton00
997f6985ba Merge pull request #266 from mcarlton00/stop-livetv-encoding
Include LiveStreamId in session stopped api call
2023-01-21 11:26:07 -05:00
Matt
b132f63871 Include LiveStreamId in session stopped api call 2023-01-21 10:23:58 -05:00
mcarlton00
6c4dad03b5 Merge pull request #265 from kianmeng/fix-typos
Fix typos
2023-01-21 09:57:54 -05:00
Kian-Meng Ang
7efcb96921 Fix typos
Found via:
- `codespell -S *.po,*.xml`
- `typos --format brief`
2023-01-21 10:43:11 +08:00
mcarlton00
22dcbe1c13 Merge pull request #263 from mcarlton00/pep8-refactor
pep8 refactor - part 1
2023-01-19 21:44:21 -05:00
mcarlton00
8ae8b5639f Merge pull request #262 from mcarlton00/upnext-addon
Fix support for the upnext addon
2023-01-19 21:32:25 -05:00
Marcin Woliński
8b8d32e20b Translated using Weblate (Polish)
Currently translated at 100.0% (276 of 276 strings)

Translation: Jellycon/Jellycon
Translate-URL: https://translate.jellyfin.org/projects/jellycon/jellycon/pl/
2023-01-17 14:51:25 -05:00
Thomas Schwery
d004716c4b Translated using Weblate (French)
Currently translated at 100.0% (276 of 276 strings)

Translation: Jellycon/Jellycon
Translate-URL: https://translate.jellyfin.org/projects/jellycon/jellycon/fr/
2023-01-17 14:51:25 -05:00
ilyigna
2b154a4cff Translated using Weblate (Spanish)
Currently translated at 99.6% (275 of 276 strings)

Translation: Jellycon/Jellycon
Translate-URL: https://translate.jellyfin.org/projects/jellycon/jellycon/es/
2023-01-17 14:51:25 -05:00
pvphome
df411a0e00 Translated using Weblate (Russian)
Currently translated at 99.2% (274 of 276 strings)

Translation: Jellycon/Jellycon
Translate-URL: https://translate.jellyfin.org/projects/jellycon/jellycon/ru/
2023-01-17 14:51:25 -05:00
Matt
381ecb95a9 Fix variable name for upnext 2023-01-16 16:24:28 -05:00
Matt
886160ca0f Fix support for the upnext addon 2023-01-16 15:04:42 -05:00
Matt
b178f785de pep8 - utils.py 2023-01-16 13:25:00 -05:00
Matt
9266b05fad pep8 - server_sessions.py 2023-01-15 11:04:56 -05:00
Matt
973fc68893 pep8 - skin_cloner.py 2023-01-15 10:53:36 -05:00
Matt
a0b8af9aa0 pep8 - widgets.py 2023-01-15 10:49:21 -05:00
Matt
4a97979027 pep8 - loghandler.py 2023-01-15 10:25:55 -05:00
Matt
c5f5834b64 pep8 - monitors.py 2023-01-15 10:22:57 -05:00
Matt
8e10ff79b1 pep8 - tracking.py 2023-01-15 10:07:49 -05:00
Matt
7950610b4d pep8 - websocket_client.py 2023-01-15 09:56:53 -05:00
Matt
93277c7d4f pep8 - functions.py 2023-01-14 16:47:48 -05:00
mcarlton00
9523d8252d Merge pull request #261 from mcarlton00/flake8-imports
Refactor imports for pep8 standards
2023-01-14 10:02:06 -05:00
Weevild
f16f2748a6 Translated using Weblate (Swedish)
Currently translated at 100.0% (276 of 276 strings)

Translation: Jellycon/Jellycon
Translate-URL: https://translate.jellyfin.org/projects/jellycon/jellycon/sv/
2023-01-13 10:51:23 -05:00
0TTA
f04c4d70b9 Translated using Weblate (Arabic)
Currently translated at 86.5% (239 of 276 strings)

Translation: Jellycon/Jellycon
Translate-URL: https://translate.jellyfin.org/projects/jellycon/jellycon/ar/
2023-01-13 10:51:23 -05:00
mcarlton00
f8e337ea92 Remove unnecessary headers 2023-01-12 21:05:29 -05:00
mcarlton00
347ab47672 Refactor imports to be under line length limit 2023-01-12 21:02:32 -05:00
mcarlton00
d25de226d0 Reorder imports for flake8 guidelines 2023-01-12 20:50:41 -05:00
mcarlton00
aa5b813929 Merge pull request #260 from mcarlton00/please-mr-linter
Fix flake8 linting complaints
2023-01-11 21:11:51 -05:00
mcarlton00
bf513dee43 Fix flake8 linting complaints 2023-01-11 19:51:26 -05:00
Moritz
cb68387437 Translated using Weblate (German)
Currently translated at 99.2% (274 of 276 strings)

Translation: Jellycon/Jellycon
Translate-URL: https://translate.jellyfin.org/projects/jellycon/jellycon/de/
2023-01-11 07:51:22 -05:00
0TTA
f8da1f5337 Translated using Weblate (Arabic)
Currently translated at 64.8% (179 of 276 strings)

Translation: Jellycon/Jellycon
Translate-URL: https://translate.jellyfin.org/projects/jellycon/jellycon/ar/
2023-01-11 07:51:22 -05:00
mcarlton00
952eb31cc2 Merge pull request #259 from jellyfin/dependabot/github_actions/appleboy/ssh-action-0.1.7
Bump appleboy/ssh-action from 0.1.6 to 0.1.7
2023-01-10 22:19:25 -05:00
mcarlton00
1d9b401405 Merge pull request #256 from jellyfin/dependabot/github_actions/release-drafter/release-drafter-5.22.0
Bump release-drafter/release-drafter from 5.21.1 to 5.22.0
2023-01-10 22:18:58 -05:00
mcarlton00
70ec2d8773 Merge pull request #255 from mcarlton00/music-shuffle-all
Add ability to shuffle entire music library
2023-01-10 22:18:28 -05:00
mcarlton00
383e1fd67b Merge pull request #258 from mrkev-gh/master
Increase maximum stream bitrate
2023-01-10 19:10:01 -05:00
Oskari Lavinto
a013c8efb0 Translated using Weblate (Finnish)
Currently translated at 100.0% (276 of 276 strings)

Translation: Jellycon/Jellycon
Translate-URL: https://translate.jellyfin.org/projects/jellycon/jellycon/fi/
2023-01-10 00:51:21 -05:00
Csaba
1b255f211e Translated using Weblate (Hungarian)
Currently translated at 100.0% (276 of 276 strings)

Translation: Jellycon/Jellycon
Translate-URL: https://translate.jellyfin.org/projects/jellycon/jellycon/hu/
2023-01-10 00:51:21 -05:00
mrkev
7b64a7cdd3 Increase maximum stream bitrate
Use enum for setting max bitrate, same as in jellyfin-kodi. New default is 1000000.
Fixes #257
2023-01-09 22:33:13 +01:00
dependabot[bot]
e3b34b81fd Bump appleboy/ssh-action from 0.1.6 to 0.1.7
Bumps [appleboy/ssh-action](https://github.com/appleboy/ssh-action) from 0.1.6 to 0.1.7.
- [Release notes](https://github.com/appleboy/ssh-action/releases)
- [Commits](https://github.com/appleboy/ssh-action/compare/v0.1.6...v0.1.7)

---
updated-dependencies:
- dependency-name: appleboy/ssh-action
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-09 16:03:06 +00:00
Retrial
d70d2c3374 Translated using Weblate (Greek)
Currently translated at 12.8% (35 of 273 strings)

Translation: Jellycon/Jellycon
Translate-URL: https://translate.jellyfin.org/projects/jellycon/jellycon/el/
2023-01-08 14:51:21 -05:00
dependabot[bot]
af06f09269 Bump release-drafter/release-drafter from 5.21.1 to 5.22.0
Bumps [release-drafter/release-drafter](https://github.com/release-drafter/release-drafter) from 5.21.1 to 5.22.0.
- [Release notes](https://github.com/release-drafter/release-drafter/releases)
- [Commits](https://github.com/release-drafter/release-drafter/compare/v5.21.1...v5.22.0)

---
updated-dependencies:
- dependency-name: release-drafter/release-drafter
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-02 16:05:09 +00:00
mcarlton00
b32043cfd9 Add ability to shuffle entire music library 2023-01-01 18:21:13 -05:00
mcarlton00
00b611d6f6 Merge pull request #254 from mcarlton00/faster-play-queue
Start playing multiple items faster
2022-12-31 12:39:48 -05:00
Matt
afea58c53a Start playing multiple items faster 2022-12-31 10:10:17 -05:00
mcarlton00
0db36ea1b8 Merge pull request #253 from mcarlton00/more-music-features
Add instant mix and shuffle features for music
2022-12-31 09:44:54 -05:00
Matt
5aa3b543ce Add new setting and translations 2022-12-30 16:11:18 -05:00
Matt
3dfde5eb04 Add instant mix and shuffle all features for music 2022-12-30 15:30:03 -05:00
mcarlton00
351c872c46 Merge pull request #249 from jellyfin/dependabot/github_actions/appleboy/ssh-action-0.1.6
Bump appleboy/ssh-action from 0.1.5 to 0.1.6
2022-12-30 11:42:07 -05:00
Niels van Velzen
802f93c30c Translated using Weblate (Dutch)
Currently translated at 95.6% (261 of 273 strings)

Translation: Jellycon/Jellycon
Translate-URL: https://translate.jellyfin.org/projects/jellycon/jellycon/nl/
2022-12-26 10:51:15 -05:00
wolfiiy
94b0dce77e Translated using Weblate (French)
Currently translated at 100.0% (273 of 273 strings)

Translation: Jellycon/Jellycon
Translate-URL: https://translate.jellyfin.org/projects/jellycon/jellycon/fr/
2022-12-26 10:51:15 -05:00
Ricardo Verduguez
2d2d378dca Translated using Weblate (Spanish)
Currently translated at 100.0% (273 of 273 strings)

Translation: Jellycon/Jellycon
Translate-URL: https://translate.jellyfin.org/projects/jellycon/jellycon/es/
2022-12-22 07:51:14 -05:00
dependabot[bot]
f84afcd7ab Bump appleboy/ssh-action from 0.1.5 to 0.1.6
Bumps [appleboy/ssh-action](https://github.com/appleboy/ssh-action) from 0.1.5 to 0.1.6.
- [Release notes](https://github.com/appleboy/ssh-action/releases)
- [Commits](https://github.com/appleboy/ssh-action/compare/v0.1.5...v0.1.6)

---
updated-dependencies:
- dependency-name: appleboy/ssh-action
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-12-12 16:03:56 +00:00
Kirill Tyurin
b7f507271e Translated using Weblate (Russian)
Currently translated at 100.0% (273 of 273 strings)

Translation: Jellycon/Jellycon
Translate-URL: https://translate.jellyfin.org/projects/jellycon/jellycon/ru/
2022-12-05 10:51:08 -05:00
Marco
399e5b1683 Translated using Weblate (French)
Currently translated at 99.6% (272 of 273 strings)

Translation: Jellycon/Jellycon
Translate-URL: https://translate.jellyfin.org/projects/jellycon/jellycon/fr/
2022-12-01 02:33:54 -05:00
wolfwork
0140dc6ff4 Translated using Weblate (Korean)
Currently translated at 35.1% (96 of 273 strings)

Translation: Jellycon/Jellycon
Translate-URL: https://translate.jellyfin.org/projects/jellycon/jellycon/ko/
2022-11-23 01:51:03 -05:00
wolfwork
d1d403815e Added translation using Weblate (Korean) 2022-11-22 01:17:14 -05:00
Marcin Woliński
af2dabaa9d Translated using Weblate (Polish)
Currently translated at 100.0% (273 of 273 strings)

Translation: Jellycon/Jellycon
Translate-URL: https://translate.jellyfin.org/projects/jellycon/jellycon/pl/
2022-11-16 06:37:49 -05:00
Thomas Schwery
c9a8cec161 Translated using Weblate (French)
Currently translated at 99.2% (271 of 273 strings)

Translation: Jellycon/Jellycon
Translate-URL: https://translate.jellyfin.org/projects/jellycon/jellycon/fr/
2022-11-14 06:51:00 -05:00
siriuskoan
190d439d36 Translated using Weblate (Chinese (Traditional))
Currently translated at 9.5% (26 of 273 strings)

Translation: Jellycon/Jellycon
Translate-URL: https://translate.jellyfin.org/projects/jellycon/jellycon/zh_Hant/
2022-11-12 20:51:00 -05:00
mcarlton00
0a53312dee Merge pull request #244 from IncredibleLaser/limit-bugfix
Add item limit to the list of parameters for recently added movies
2022-11-12 08:54:27 -05:00
Super Laser
1759115a80 Add item limit to the list of parameters for recently added movies 2022-11-09 20:52:31 +01:00
mcarlton00
be477f2433 Merge pull request #241 from jellyfin/prepare-0.6.1
Some checks failed
Build JellyCon / build (py2) (push) Has been cancelled
Build JellyCon / build (py3) (push) Has been cancelled
Prepare for release v0.6.1
2022-11-01 21:10:59 -04:00
jellyfin-bot
d3a3e27649 bump version to 0.6.1 2022-11-02 01:02:26 +00:00
mcarlton00
c832f74a26 Merge pull request #239 from EwertonBello/refact/use-fstring
refact: use f-string instead of format
2022-10-31 21:51:30 -04:00
Ewerton Belo
721aa664a8 fix: restore changes of fstring in service.py 2022-10-31 20:14:55 -03:00
Ewerton Belo
96982d52f1 refact: use f-string instead of format 2022-10-31 19:29:48 -03:00
mcarlton00
a59d711c1e Merge pull request #234 from jellyfin/dependabot/github_actions/release-drafter/release-drafter-5.21.1
Bump release-drafter/release-drafter from 5.21.0 to 5.21.1
2022-10-30 09:09:05 -04:00
mcarlton00
0559903fd6 Merge pull request #238 from mcarlton00/cancel-user-select
Initialize variable before it's used
2022-10-30 09:08:36 -04:00
Matt
a904c6a62e Initialize variable before it's used 2022-10-30 09:02:53 -04:00
mcarlton00
d73e144511 Merge pull request #235 from mcarlton00/quick-connect-fail
Don't crash if quickconnect is disabled on the server
2022-10-30 09:00:49 -04:00
Kilian
4730138dc1 Translated using Weblate (French)
Currently translated at 98.9% (270 of 273 strings)

Translation: Jellycon/Jellycon
Translate-URL: https://translate.jellyfin.org/projects/jellycon/jellycon/fr/
2022-10-26 09:50:53 -04:00
Matt
6dd37bd8d2 Don't crash if quickconnect is disabled on the server 2022-10-22 13:12:25 -04:00
Angus Fraser
05452e6f46 Translated using Weblate (Italian)
Currently translated at 49.8% (136 of 273 strings)

Translation: Jellycon/Jellycon
Translate-URL: https://translate.jellyfin.org/projects/jellycon/jellycon/it/
2022-10-20 22:50:51 -04:00
wolong gl
b7593b4042 Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (273 of 273 strings)

Translation: Jellycon/Jellycon
Translate-URL: https://translate.jellyfin.org/projects/jellycon/jellycon/zh_Hans/
2022-10-20 22:50:51 -04:00
dependabot[bot]
000a48cc57 Bump release-drafter/release-drafter from 5.21.0 to 5.21.1
Bumps [release-drafter/release-drafter](https://github.com/release-drafter/release-drafter) from 5.21.0 to 5.21.1.
- [Release notes](https://github.com/release-drafter/release-drafter/releases)
- [Commits](https://github.com/release-drafter/release-drafter/compare/v5.21.0...v5.21.1)

---
updated-dependencies:
- dependency-name: release-drafter/release-drafter
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-10-17 16:15:51 +00:00
daniel knutzen
a89d0a6dc2 Translated using Weblate (Swedish)
Currently translated at 100.0% (273 of 273 strings)

Translation: Jellycon/Jellycon
Translate-URL: https://translate.jellyfin.org/projects/jellycon/jellycon/sv/
2022-10-17 01:50:50 -04:00
mcarlton00
caa014a0ac Merge pull request #232 from jellyfin/prepare-0.5.8
Some checks failed
Build JellyCon / build (py2) (push) Has been cancelled
Build JellyCon / build (py3) (push) Has been cancelled
Prepare for release v0.5.8
2022-10-11 15:01:08 -04:00
Matt
8199642f35 0.6.0 2022-10-11 14:59:12 -04:00
jellyfin-bot
da6525120d bump version to 0.5.8 2022-10-11 18:57:57 +00:00
mcarlton00
362760d3ab Merge pull request #231 from mcarlton00/musicvideo-resume
Add play option to music video context menu
2022-10-11 14:47:13 -04:00
Hans Christian Madsen
1cce67702d Translated using Weblate (Swedish)
Currently translated at 88.2% (241 of 273 strings)

Translation: Jellycon/Jellycon
Translate-URL: https://translate.jellyfin.org/projects/jellycon/jellycon/sv/
2022-10-10 11:54:40 -04:00
mcarlton00
ff761dd088 Merge branch 'master' into musicvideo-resume 2022-10-08 16:46:00 -04:00
Matt
beda70b1f9 Add play option to music video context menu 2022-10-08 16:43:57 -04:00
Paulo
eb9eb2009f Translated using Weblate (French)
Currently translated at 87.1% (238 of 273 strings)

Translation: Jellycon/Jellycon
Translate-URL: https://translate.jellyfin.org/projects/jellycon/jellycon/fr/
2022-10-05 13:54:38 -04:00
Oskari Lavinto
73bcfef007 Translated using Weblate (Finnish)
Currently translated at 100.0% (273 of 273 strings)

Translation: Jellycon/Jellycon
Translate-URL: https://translate.jellyfin.org/projects/jellycon/jellycon/fi/
2022-10-04 01:54:39 -04:00
Benjamin
3104d5aec9 Translated using Weblate (Swedish)
Currently translated at 82.4% (225 of 273 strings)

Translation: Jellycon/Jellycon
Translate-URL: https://translate.jellyfin.org/projects/jellycon/jellycon/sv/
2022-10-04 01:54:39 -04:00
Adammantium
0d3c39cc0a Translated using Weblate (German)
Currently translated at 100.0% (273 of 273 strings)

Translation: Jellycon/Jellycon
Translate-URL: https://translate.jellyfin.org/projects/jellycon/jellycon/de/
2022-10-04 01:54:39 -04:00
Csaba
e57059cf3c Translated using Weblate (Hungarian)
Currently translated at 100.0% (273 of 273 strings)

Translation: Jellycon/Jellycon
Translate-URL: https://translate.jellyfin.org/projects/jellycon/jellycon/hu/
2022-10-04 01:54:39 -04:00
mcarlton00
18e9a99d17 Merge pull request #228 from mcarlton00/remove-old-verify
Cleanup old https verify method
2022-10-03 10:15:52 -04:00
mcarlton00
7b7549fef0 Merge pull request #227 from mcarlton00/mixed-content
Add support for mixed content libraries
2022-10-03 09:11:46 -04:00
Matt
251f43fb77 Remove unused variable 2022-10-02 08:12:02 -04:00
Matt
6c4077b143 Cleanup old https verify method 2022-10-02 08:10:44 -04:00
Matt
00a7e92ef7 Remove unused variable 2022-10-02 08:07:40 -04:00
Matt
61c1a3db8e Add support for mixed content libraries 2022-10-01 22:15:44 -04:00
mcarlton00
bdcd65d6c9 Merge pull request #226 from mcarlton00/redesign-quickconnect
Move quickconnect code into user selection list
2022-10-01 21:06:38 -04:00
Matt
f7a427b809 Remove unneeded dialog template 2022-10-01 18:17:53 -04:00
Matt
e96e727c7c Move quickconnect code into user selection list 2022-10-01 17:40:26 -04:00
mcarlton00
f2ea26b529 Merge pull request #225 from mcarlton00/display-saved-users
Show saved users in the user selection list
2022-10-01 13:32:27 -04:00
Matt
7b10c48e8f Show saved users in the user selection list 2022-10-01 10:59:10 -04:00
Weevild
0c71e82675 Translated using Weblate (Swedish)
Currently translated at 75.3% (205 of 272 strings)

Translation: Jellycon/Jellycon
Translate-URL: https://translate.jellyfin.org/projects/jellycon/jellycon/sv/
2022-10-01 09:54:38 -04:00
Thanos
7fa7c8f9f8 Translated using Weblate (Dutch)
Currently translated at 95.5% (260 of 272 strings)

Translation: Jellycon/Jellycon
Translate-URL: https://translate.jellyfin.org/projects/jellycon/jellycon/nl/
2022-10-01 09:54:38 -04:00
Thanos
102eb934af Translated using Weblate (Turkish)
Currently translated at 23.5% (64 of 272 strings)

Translation: Jellycon/Jellycon
Translate-URL: https://translate.jellyfin.org/projects/jellycon/jellycon/tr/
2022-10-01 09:54:38 -04:00
mcarlton00
099e0193e9 Merge pull request #223 from jellyfin/dependabot/github_actions/release-drafter/release-drafter-5.21.0
Bump release-drafter/release-drafter from 5.20.1 to 5.21.0
2022-09-29 21:38:44 -04:00
mcarlton00
c68b4bf392 Merge pull request #222 from mcarlton00/stale-menus
Fix stale menu links when user switching
2022-09-29 21:38:11 -04:00
mcarlton00
14b2a10fdf Merge pull request #221 from mcarlton00/unique-client-id
Force unique client IDs when using quick connect
2022-09-29 21:37:52 -04:00
mcarlton00
a9ba96e08b Merge pull request #220 from mcarlton00/auth-error-message
Add an error message when authentication fails
2022-09-29 21:37:36 -04:00
Ariel Martín Estévez
d4c3ebab24 Translated using Weblate (Spanish)
Currently translated at 100.0% (272 of 272 strings)

Translation: Jellycon/Jellycon
Translate-URL: https://translate.jellyfin.org/projects/jellycon/jellycon/es/
2022-09-24 16:54:34 -04:00
Fabien LARTIGUE
4f5396f945 Translated using Weblate (French)
Currently translated at 87.5% (238 of 272 strings)

Translation: Jellycon/Jellycon
Translate-URL: https://translate.jellyfin.org/projects/jellycon/jellycon/fr/
2022-09-22 05:54:34 -04:00
mcarlton00
59a5f72f7c Merge pull request #224 from aiosk/subtitle_not_working_on_self_sign_certificate_server
subtitle not working on self sign certificate
2022-09-21 10:07:41 -04:00
Oskari Lavinto
47fbf495f1 Translated using Weblate (Finnish)
Currently translated at 100.0% (272 of 272 strings)

Translation: Jellycon/Jellycon
Translate-URL: https://translate.jellyfin.org/projects/jellycon/jellycon/fi/
2022-09-21 04:54:33 -04:00
Ad-Blokker
55529f49e3 Translated using Weblate (Dutch)
Currently translated at 61.3% (167 of 272 strings)

Translation: Jellycon/Jellycon
Translate-URL: https://translate.jellyfin.org/projects/jellycon/jellycon/nl/
2022-09-21 04:54:33 -04:00
Csaba
dd0f410161 Translated using Weblate (Hungarian)
Currently translated at 100.0% (272 of 272 strings)

Translation: Jellycon/Jellycon
Translate-URL: https://translate.jellyfin.org/projects/jellycon/jellycon/hu/
2022-09-21 04:54:33 -04:00
andry.yosua
6ee2f9c962 subtitle not working on self sign certificate
`requests.get` when download subtitle file do not respect "Verify HTTPS
certificate" setting.

STEPS TO REPRODUCE:
- i have installed self sign certificate on jellyfin server
- i have set "Verify HTTPS certificate" to false on addon setting

EXPECTED RESULTS:
i can play movies

ACTUAL RESULTS:
i can not play movies.

this happened because `requests.get` when download subtitle file do not
respect "Verify HTTPS certificate" setting.

this PR add "Verify HTTPS certificate" setting when downloading subtitle
file
2022-09-20 05:51:43 +07:00
dependabot[bot]
f24e20a902 Bump release-drafter/release-drafter from 5.20.1 to 5.21.0
Bumps [release-drafter/release-drafter](https://github.com/release-drafter/release-drafter) from 5.20.1 to 5.21.0.
- [Release notes](https://github.com/release-drafter/release-drafter/releases)
- [Commits](https://github.com/release-drafter/release-drafter/compare/v5.20.1...v5.21.0)

---
updated-dependencies:
- dependency-name: release-drafter/release-drafter
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-09-19 16:16:26 +00:00
lollolgag
1cf0155622 Translated using Weblate (German)
Currently translated at 100.0% (272 of 272 strings)

Translation: Jellycon/Jellycon
Translate-URL: https://translate.jellyfin.org/projects/jellycon/jellycon/de/
2022-09-19 06:54:33 -04:00
Matt
aa208d2ae5 Fix stale menu links when user switching 2022-09-18 18:34:30 -04:00
Matt
1d8b9824ad Force unique client IDs when using quick connect 2022-09-18 09:36:00 -04:00
Matt
bd1917a8a7 Add an error message when authentication fails 2022-09-18 08:49:06 -04:00
mcarlton00
50a43e8e01 Merge pull request #217 from mcarlton00/playnext-dialog
Make it clear that the play next episode setting is in seconds
2022-09-18 08:32:46 -04:00
Matt
bee8be9698 Make it clear that the play next episode setting is in seconds 2022-09-17 12:42:09 -04:00
mcarlton00
774c9ba12d Merge pull request #208 from jellyfin/dependabot/github_actions/release-drafter/release-drafter-5.20.1
Bump release-drafter/release-drafter from 5.20.0 to 5.20.1
2022-09-17 11:48:48 -04:00
mcarlton00
8be5c1b9eb Merge pull request #213 from mcarlton00/tvheadend-fix
Fix playing livetv from tvheadend
2022-09-17 11:48:21 -04:00
wolong gl
9ada09e809 Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (272 of 272 strings)

Translation: Jellycon/Jellycon
Translate-URL: https://translate.jellyfin.org/projects/jellycon/jellycon/zh_Hans/
2022-09-14 21:11:37 -04:00
Matt
007a997f8f Fix playing livetv from tvheadend 2022-09-11 12:01:02 -04:00
mcarlton00
d70f9290f5 Merge pull request #211 from jellyfin/prepare-0.5.7
Some checks failed
Build JellyCon / build (py2) (push) Has been cancelled
Build JellyCon / build (py3) (push) Has been cancelled
Prepare for release v0.5.7
2022-08-26 14:28:52 -04:00
jellyfin-bot
d32be4aba7 bump version to 0.5.7 2022-08-26 18:28:17 +00:00
mcarlton00
359dd05972 Merge pull request #210 from mcarlton00/user-switching-watch-status
Apply watched status to the correct user
2022-08-26 14:14:21 -04:00
Matt
c005d331ee Apply watched status to the correct user 2022-08-26 13:38:15 -04:00
DJSweder
e51f136c4e Translated using Weblate (Czech)
Currently translated at 8.0% (22 of 272 strings)

Translation: Jellycon/Jellycon
Translate-URL: https://translate.jellyfin.org/projects/jellycon/jellycon/cs/
2022-08-25 16:11:29 -04:00
dependabot[bot]
95ee6e4e24 Bump release-drafter/release-drafter from 5.20.0 to 5.20.1
Bumps [release-drafter/release-drafter](https://github.com/release-drafter/release-drafter) from 5.20.0 to 5.20.1.
- [Release notes](https://github.com/release-drafter/release-drafter/releases)
- [Commits](https://github.com/release-drafter/release-drafter/compare/v5.20.0...v5.20.1)

---
updated-dependencies:
- dependency-name: release-drafter/release-drafter
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-08-22 16:14:52 +00:00
lyaschuchenko
677d3a4a76 Translated using Weblate (Ukrainian)
Currently translated at 100.0% (272 of 272 strings)

Translation: Jellycon/Jellycon
Translate-URL: https://translate.jellyfin.org/projects/jellycon/jellycon/uk/
2022-08-20 22:11:27 -04:00
55 changed files with 3859 additions and 856 deletions

View File

@@ -10,7 +10,7 @@ jobs:
steps:
- name: Update Draft
uses: release-drafter/release-drafter@v5.20.0
uses: release-drafter/release-drafter@v5.22.0
id: draft
env:
GITHUB_TOKEN: ${{ secrets.JF_BOT_TOKEN }}
@@ -23,7 +23,7 @@ jobs:
- name: Checkout repository
uses: actions/checkout@v3
- name: Parse Changlog
- name: Parse Changelog
run: |
pip install emoji
cat << EOF >> cl.md

View File

@@ -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@v5.22.0
if: ${{ matrix.py_version == 'py3' }}
with:
publish: true
@@ -53,7 +53,7 @@ jobs:
remote_key: ${{ secrets.DEPLOY_KEY }}
- name: Add to Kodi repo and clean up
uses: appleboy/ssh-action@v0.1.5
uses: appleboy/ssh-action@v0.1.7
with:
host: ${{ secrets.DEPLOY_HOST }}
username: ${{ secrets.DEPLOY_USER }}

View File

@@ -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@v5.22.0
env:
GITHUB_TOKEN: ${{ secrets.JF_BOT_TOKEN }}

View File

@@ -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)

View File

@@ -1,18 +1,36 @@
version: '0.5.6'
version: '0.7.0'
changelog: |-
:tada: New features and improvements
------------------------------------
+ Add Continue Watching Widget (#199) @aiosk
+ Add ability to shuffle music genres (#267) @mcarlton00
+ Add ability to shuffle entire music library (#255) @mcarlton00
+ Increase maximum stream bitrate (#258) @mrkev-gh
+ Start playing multiple items faster (#254) @mcarlton00
+ Add instant mix and shuffle features for music (#253) @mcarlton00
Bug Fixes
---------
+ Fix user switching (#204) @mcarlton00
+ Don't request empty folders from api if setting is disabled (#198) @mcarlton00
+ Don't error when switching to a cached user (#200) @mcarlton00
+ Fix context menu in kodi v20 (#271) @mcarlton00
+ Include LiveStreamId in session stopped api call (#266) @mcarlton00
+ Fix support for the upnext addon (#262) @mcarlton00
+ Add item limit to the list of parameters for recently added movies (#244) @IncredibleLaser
Code or Repo Maintenance
------------------------
+ Fix typos (#265) @kianmeng
+ pep8 refactor - part 1 (#263) @mcarlton00
+ Refactor imports for pep8 standards (#261) @mcarlton00
+ Fix flake8 linting complaints (#260) @mcarlton00
:arrow_up: Dependency updates
-----------------------------
+ Update kodistubs requirement from ~=19.0 to ~=20.0 (#268) @dependabot
CI & build changes
------------------
+ Bump appleboy/ssh-action from 0.1.4 to 0.1.5 (#202) @dependabot
+ Bump appleboy/ssh-action from 0.1.6 to 0.1.7 (#259) @dependabot
+ Bump release-drafter/release-drafter from 5.21.1 to 5.22.0 (#256) @dependabot
+ Bump appleboy/ssh-action from 0.1.5 to 0.1.6 (#249) @dependabot
dependencies:
py2:
- addon: 'xbmc.python'

View File

@@ -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 ~= 20.0; python_version >= '3.6'
git+https://github.com/romanvm/kodi.six
git+https://github.com/ruuk/script.module.addon.signals

View File

@@ -1,7 +1,7 @@
msgid ""
msgstr ""
"PO-Revision-Date: 2022-06-05 14:22+0000\n"
"Last-Translator: egymoh <egymoh2@hotmail.com>\n"
"PO-Revision-Date: 2023-01-13 15:51+0000\n"
"Last-Translator: 0TTA <OTTTA@protonmail.com>\n"
"Language-Team: Arabic <https://translate.jellyfin.org/projects/jellycon/"
"jellycon/ar/>\n"
"Language: ar\n"
@@ -10,7 +10,7 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 "
"&& n%100<=10 ? 3 : n%100>=11 ? 4 : 5;\n"
"X-Generator: Weblate 4.10.1\n"
"X-Generator: Weblate 4.14.1\n"
msgctxt "#30361"
msgid " - Programs"
@@ -52,19 +52,17 @@ msgctxt "#30319"
msgid "Music - All Album Artists"
msgstr "كل فناني الألبوم"
#, fuzzy
msgctxt "#30351"
msgid "Music - Recently Played"
msgstr "لعبت مؤخرا"
msgstr "موسيقى - شُغلت مؤخرا"
msgctxt "#30350"
msgid "Music - Recently Added"
msgstr "أضيف مؤخرا"
#, fuzzy
msgctxt "#30349"
msgid " - Recently Played"
msgstr "لعبت مؤخرا"
msgstr "- شُغلت مؤخرا"
msgctxt "#30348"
msgid "Add user ratings"
@@ -359,7 +357,7 @@ msgstr "أضيف مؤخرا"
msgctxt "#30267"
msgid " - In Progress"
msgstr "في تقدم"
msgstr "قيد المشاهدة"
msgctxt "#30266"
msgid "Movies - Pages"
@@ -371,7 +369,7 @@ msgstr "الحلقات - التالي"
msgctxt "#30264"
msgid "Episodes - In Progress"
msgstr "الحلقات - قيد التقدم"
msgstr "حلقات - قيد المشاهدة"
msgctxt "#30263"
msgid "Episodes - Recently Added"
@@ -391,7 +389,7 @@ msgstr "أفلام - المفضلة"
msgctxt "#30258"
msgid "Movies - In Progress"
msgstr "أفلام - قيد التحميل"
msgstr "أفلام - قيد المشاهدة"
msgctxt "#30257"
msgid "Movies - Recently Added"
@@ -664,7 +662,7 @@ msgstr "اسم المستخدم:"
msgctxt "#30023"
msgid "Hide unwatched episode details"
msgstr "إخفاء تفاصيل الحلقة التي لم تتم مشاهدتها"
msgstr "إخفاء تفاصيل الحلقة غير المشاهدة"
msgctxt "#30022"
msgid "Advanced"
@@ -745,3 +743,235 @@ msgstr "أستضافة"
msgctxt "#30208"
msgid "Max stream bitrate (Kbits)"
msgstr "الحد الأقصى لمعدل نقل البيانات (Kbps)"
msgctxt "#30210"
msgid "HTTP direct stream"
msgstr "(بروتوكول نقل النص الفائق) مشاهدة مباشرة"
msgctxt "#30364"
msgid "Do you want to save the password?"
msgstr "أتود حفظ كلمة السر؟"
msgctxt "#30366"
msgid "Manually enter user details"
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 "أتود إدخال رابط الخادم يدويا؟"
msgctxt "#30373"
msgid "Scanning for local servers"
msgstr "يبحث عن خوادم داخل شبكة المنزل"
msgctxt "#30393"
msgid "Clear Cache Result"
msgstr "حذف نتائج الذاكرة المؤقتة"
msgctxt "#30394"
msgid "Cache files deleted"
msgstr "حُذفت ملفات الذاكرة المؤقتة"
msgctxt "#30398"
msgid "Refresh Jellyfin Metadata"
msgstr "حدث البيانات الوصفية"
msgctxt "#30401"
msgid "Info"
msgstr "المعلومات"
msgctxt "#30412"
msgid " - Decades"
msgstr "- عقود"
msgctxt "#30416"
msgid "HTTP timeout seconds"
msgstr "مدة الانتظار قبل قطع الاتصال لـ (بروتوكول نقل النص الفائق)"
msgctxt "#30420"
msgid "Audio max channels"
msgstr "الحد الأقصى لقنوات الصوت"
msgctxt "#30446"
msgid "There was an error logging in"
msgstr "حدث خطأ خلال تسجيل الدخول"
msgctxt "#30363"
msgid "Save Password?"
msgstr "أتود حفظ كلمة السر؟"
msgctxt "#30371"
msgid "Could not connect to the URL you entered, do you want to try again?"
msgstr "فشل الاتصال بالرابط المُدخل، أتود المحاولة مرة أخرى؟"
msgctxt "#30372"
msgid "Server URL"
msgstr "رابط الخادم"
msgctxt "#30381"
msgid "More than one"
msgstr "أكثر من واحدا"
msgctxt "#30392"
msgid "HTTPS"
msgstr "بروتوكول نقل النص الفائق الآمن"
msgctxt "#30399"
msgid "Hide"
msgstr "إخفاء"
msgctxt "#30403"
msgid "Movies - Recommendations"
msgstr "الأفلام - التوصيات"
msgctxt "#30418"
msgid "Audio bitrate (Kbits)"
msgstr "معدل نقل البت (بالكيلو بتّ بالثانية)"
msgctxt "#30445"
msgid "Continue Watching"
msgstr "استئناف المشاهدة"
msgctxt "#30402"
msgid "Add to Kodi Playlist"
msgstr "أضفها إلى قائمة كودي"
msgctxt "#30323"
msgid "Artists"
msgstr "الفنانين"
msgctxt "#30352"
msgid "Music - Frequently Played"
msgstr "موسيقى - شُغلت مرارا"
msgctxt "#30365"
msgid "Manual Login"
msgstr "تسجيل الدخول يدويا"
msgctxt "#30414"
msgid " - Favorites"
msgstr "- المفضلة"
msgctxt "#30382"
msgid "Always"
msgstr "دائما"
msgctxt "#30388"
msgid "Server details"
msgstr "تفاصيل الخادم"
msgctxt "#30389"
msgid "User details"
msgstr "تفاصيل المستخدم"
msgctxt "#30391"
msgid "HTTP"
msgstr "بروتوكول نقل النص الفائق"
msgctxt "#30405"
msgid " - Show All"
msgstr "- أظهر الكل"
msgctxt "#30406"
msgid "Jellyfin Libraries"
msgstr "مكتبات Jellyfin"
msgctxt "#30411"
msgid " - Years"
msgstr "- السنوات"
msgctxt "#30417"
msgid "You do not have permision to delete this item"
msgstr "لست مُخول لحذف هذا"
msgctxt "#30423"
msgid "NotSet"
msgstr "لم تُضبط الإعدادات"
msgctxt "#30419"
msgid "Audio codec"
msgstr "ترميز الصوت"
msgctxt "#30424"
msgid "Default"
msgstr "افتراضي"
msgctxt "#30425"
msgid "Year"
msgstr "سنة"
msgctxt "#30426"
msgid "Title"
msgstr "العنوان"
msgctxt "#30427"
msgid "Added"
msgstr "اُضيف"
msgctxt "#30428"
msgid "Rating"
msgstr "التقييم"
msgctxt "#30429"
msgid "Genre"
msgstr "التصنيف الأدبي"
msgctxt "#30431"
msgid "Seasons"
msgstr "المواسم"
msgctxt "#30432"
msgid "Hide watched items in lists"
msgstr "اخفي العناصر المُشاهدة من القائمة"
msgctxt "#30433"
msgid "Allow direct file playback"
msgstr "اسمح بالمشاهدة المباشرة"
msgctxt "#30435"
msgid "Connection speed test"
msgstr "اختبار سرعة الاتصال"
msgctxt "#30437"
msgid "Playback options"
msgstr "إعدادات التشغيل"
msgctxt "#30440"
msgid "Play next"
msgstr "شغل التالي"
msgctxt "#30448"
msgid "Shuffle"
msgstr "عشوائي"
msgctxt "#30353"
msgid " - Frequently Played"
msgstr "- شُغلت مرارا"
msgctxt "#30362"
msgid " - Recordings"
msgstr "- المُسجلات"
msgctxt "#30383"
msgid "System - "
msgstr "النظام -"
msgctxt "#30397"
msgid " - Pages"
msgstr "- الصفحات"
msgctxt "#30404"
msgid " - A-Z"
msgstr "- من أ إلى ي"
msgctxt "#30434"
msgid "Force transcode stream bitrate (Kbits)"
msgstr "إجبار الترميز على معدل نقل البت (بالكيلو بتّ بالثانية)"

View File

@@ -0,0 +1,244 @@
msgid ""
msgstr ""
"PO-Revision-Date: 2023-02-13 01:39+0000\n"
"Last-Translator: jolupa <jolupameister@gmail.com>\n"
"Language-Team: Catalan <https://translate.jellyfin.org/projects/jellycon/"
"jellycon/ca/>\n"
"Language: ca\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 4.14.1\n"
msgctxt "#30003"
msgid "Verify HTTPS certificate"
msgstr "Verifica el certificat HTTPS"
msgctxt "#30006"
msgid "Password"
msgstr "Contrasenya"
msgctxt "#30012"
msgid "[Change user]"
msgstr "[Canvia usuari]"
msgctxt "#30014"
msgid "Jellyfin"
msgstr "Jellyfin"
msgctxt "#30018"
msgid "Number of items to show in filtered lists"
msgstr "Nombre d'elements a mostrar a la llista filtrada"
msgctxt "#30020"
msgid "Flatten single season"
msgstr "Aplana sessions úniques"
msgctxt "#30024"
msgid "Username:"
msgstr "Nom d'usuari:"
msgctxt "#30052"
msgid "Deleting"
msgstr "Esborran"
msgctxt "#30063"
msgid "N/A"
msgstr "No Permès"
msgctxt "#30111"
msgid "Services"
msgstr "Serveis"
msgctxt "#30113"
msgid "Retrieving Data"
msgstr "Recuperant Dades"
msgctxt "#30116"
msgid "Add unwatched counts to names"
msgstr "Afegir nombre de no vistes als noms"
msgctxt "#30120"
msgid "Show load progress"
msgstr "Mostrar la progressió de la carrega"
msgctxt "#30125"
msgid "Done"
msgstr "Fet"
msgctxt "#30135"
msgid "Error"
msgstr "Error"
msgctxt "#30163"
msgid "Add (cc) if subtitle is available"
msgstr "Afegeix (cc) si hi han subtítols disponibles"
msgctxt "#30167"
msgid "Selected Server Address"
msgstr "Adreça del servidor seleccionat"
msgctxt "#30169"
msgid "Address: "
msgstr "Adreça:"
msgctxt "#30181"
msgid "Include plot"
msgstr "Inclou sipnosi"
msgctxt "#30200"
msgid "URL error"
msgstr "Error en la URL"
msgctxt "#30207"
msgid "Playback"
msgstr "Reproducció"
msgctxt "#30209"
msgid "File direct path"
msgstr "Ruta directa el fitxer"
msgctxt "#30000"
msgid "Host"
msgstr "Servidor"
msgctxt "#30001"
msgid "Port"
msgstr "Port"
msgctxt "#30005"
msgid "Username"
msgstr "Nom d'usuari"
msgctxt "#30007"
msgid "Samba username"
msgstr "Nom d'usuari de Samba"
msgctxt "#30008"
msgid "Samba password"
msgstr "Contrasenya de Samba"
msgctxt "#30010"
msgid "Number of performance profiles to capture"
msgstr "Nombre de perfils de rendiment a capturar"
msgctxt "#30011"
msgid "[Detect local server]"
msgstr "[Detecta el servidor local]"
msgctxt "#30015"
msgid "Log timing data"
msgstr "Temporitzador de dates del registre"
msgctxt "#30016"
msgid "Device display name"
msgstr "Nom del dispositiu emissor"
msgctxt "#30017"
msgid "Show connected clients"
msgstr "Mostrar clients conectats"
msgctxt "#30019"
msgid "Filtered episode name format"
msgstr "Format del nom d'episodis filtrats"
msgctxt "#30021"
msgid "Show all episodes item"
msgstr "Mostra tots els episodis"
msgctxt "#30022"
msgid "Advanced"
msgstr "Avançat"
msgctxt "#30023"
msgid "Hide unwatched episode details"
msgstr "Amaga els detalls dels episodis no vistos"
msgctxt "#30025"
msgid "Password:"
msgstr "Contrasenya:"
msgctxt "#30026"
msgid "Widget item select action"
msgstr "Acció al selecionar article d'un giny"
msgctxt "#30027"
msgid "Enable debug logging"
msgstr "Activar el registre de depuració"
msgctxt "#30044"
msgid "Incorrect Username/Password"
msgstr "Nom d'Usuari/Contrasenya incorrectes"
msgctxt "#30045"
msgid "Username not found"
msgstr "No s'ha trobat l'usuari"
msgctxt "#30053"
msgid "Waiting for server to delete"
msgstr "Esperant que sigui esborrat per el servidor"
msgctxt "#30091"
msgid "Confirm delete?"
msgstr "Confirmes que el vols esborrar?"
msgctxt "#30092"
msgid "Warning: This action will delete the media files from the server."
msgstr "Atenció: Això esborrarà els fitxers dels servidors."
msgctxt "#30110"
msgid "Interface"
msgstr "Interfície"
msgctxt "#30112"
msgid "Loading Content"
msgstr "Carregant Contingut"
msgctxt "#30114"
msgid "Jump back seconds"
msgstr "Saltar enrera segons"
msgctxt "#30118"
msgid "Add resume percent to names"
msgstr "Afegir percentatge de resum als noms"
msgctxt "#30121"
msgid "On resume"
msgstr "Retoman"
msgctxt "#30126"
msgid "Processing Item : "
msgstr "Processant l'article:"
msgctxt "#30139"
msgid "No Media Type Set"
msgstr "No s'ha fixat cap tipus de media"
msgctxt "#30166"
msgid "Select Server"
msgstr "Selecciona un servidor"
msgctxt "#30180"
msgid "Select User"
msgstr "Selecciona Usuari"
msgctxt "#30182"
msgid "Include media stream info"
msgstr "Inclou informació del contingut multimèdia"
msgctxt "#30183"
msgid "Include people"
msgstr "Inclou persones"
msgctxt "#30201"
msgid "Unable to connect to server"
msgstr "Imposible conectar al servidor"
msgctxt "#30206"
msgid "Playback type"
msgstr "Tipus de reproducció"
msgctxt "#30208"
msgid "Max stream bitrate (Kbits)"
msgstr "Màxim bitrate del contingut (Kbps)"

View File

@@ -1,6 +1,6 @@
msgid ""
msgstr ""
"PO-Revision-Date: 2022-06-09 21:22+0000\n"
"PO-Revision-Date: 2022-08-25 20:11+0000\n"
"Last-Translator: DJSweder <djsweder@gmail.com>\n"
"Language-Team: Czech <https://translate.jellyfin.org/projects/jellycon/"
"jellycon/cs/>\n"
@@ -9,7 +9,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n"
"X-Generator: Weblate 4.10.1\n"
"X-Generator: Weblate 4.13.1\n"
msgctxt "#30016"
msgid "Device display name"
@@ -58,3 +58,43 @@ msgstr "Port"
msgctxt "#30000"
msgid "Host"
msgstr "Hostitel"
msgctxt "#30027"
msgid "Enable debug logging"
msgstr "Povolit protokolování ladění"
msgctxt "#30026"
msgid "Widget item select action"
msgstr "Akce pro výběr položky widgetu"
msgctxt "#30025"
msgid "Password:"
msgstr "Heslo:"
msgctxt "#30024"
msgid "Username:"
msgstr "Uživatelské jméno:"
msgctxt "#30023"
msgid "Hide unwatched episode details"
msgstr "Schovat podrobnosti nezhlédnutých epizod"
msgctxt "#30022"
msgid "Advanced"
msgstr "Pokročilé"
msgctxt "#30021"
msgid "Show all episodes item"
msgstr "Zobrazit všechny epizody"
msgctxt "#30019"
msgid "Filtered episode name format"
msgstr "Formát názvu filtrované epizody"
msgctxt "#30018"
msgid "Number of items to show in filtered lists"
msgstr "Počet položek k zobrazení ve filtrovaném seznamu"
msgctxt "#30017"
msgid "Show connected clients"
msgstr "Zobrazit připojené klienty"

View File

@@ -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: 2023-02-02 09:51+0000\n"
"Last-Translator: KingArthvr_ <arthurruckdeschel@gmail.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 4.14.1\n"
msgctxt "#30120"
msgid "Show load progress"
@@ -1105,3 +1105,23 @@ 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 "Zufallswiedergabe"

View File

@@ -1,2 +1,154 @@
msgid ""
msgstr "X-Generator: Weblate\nMIME-Version: 1.0\nContent-Type: text/plain; charset=UTF-8\nContent-Transfer-Encoding: 8bit"
msgstr ""
"PO-Revision-Date: 2023-01-08 19:51+0000\n"
"Last-Translator: Retrial <giwrgosmant@gmail.com>\n"
"Language-Team: Greek <https://translate.jellyfin.org/projects/jellycon/"
"jellycon/el/>\n"
"Language: el\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 4.14.1\n"
msgctxt "#30000"
msgid "Host"
msgstr "Host"
msgctxt "#30001"
msgid "Port"
msgstr "Port"
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 "#30008"
msgid "Samba password"
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 "#30021"
msgid "Show all episodes item"
msgstr "Εμφάνιση όλων των επεισοδίων"
msgctxt "#30024"
msgid "Username:"
msgstr "Όνομα χρήστη:"
msgctxt "#30025"
msgid "Password:"
msgstr "Κωδικός πρόσβασης:"
msgctxt "#30045"
msgid "Username not found"
msgstr "Το όνομα χρήστη δεν βρέθηκε"
msgctxt "#30052"
msgid "Deleting"
msgstr "Διαγραφή"
msgctxt "#30053"
msgid "Waiting for server to delete"
msgstr "Αναμονή για διαγραφή διακομιστή"
msgctxt "#30063"
msgid "N/A"
msgstr "N/A"
msgctxt "#30110"
msgid "Interface"
msgstr "Διεπαφή"
msgctxt "#30111"
msgid "Services"
msgstr "Υπηρεσίες"
msgctxt "#30113"
msgid "Retrieving Data"
msgstr "Ανάκτηση Δεδομένων"
msgctxt "#30114"
msgid "Jump back seconds"
msgstr "Πήδηξε πίσω δευτερόλεπτα"
msgctxt "#30120"
msgid "Show load progress"
msgstr "Εμφάνιση της προόδου φόρτωσης"
msgctxt "#30016"
msgid "Device display name"
msgstr "Εμφανιζόμενο όνομα συσκευής"
msgctxt "#30023"
msgid "Hide unwatched episode details"
msgstr "Απόκρυψη λεπτομερειών επεισοδίου που δεν έχετε παρακολουθήσει"
msgctxt "#30026"
msgid "Widget item select action"
msgstr "Επιλογή ενέργειας στοιχείου widget"
msgctxt "#30027"
msgid "Enable debug logging"
msgstr "Ενεργοποίηση καταγραφής εντοπισμού σφαλμάτων"
msgctxt "#30044"
msgid "Incorrect Username/Password"
msgstr "Λανθασμένο Όνομα χρήστη/Κωδικός πρόσβασης"
msgctxt "#30091"
msgid "Confirm delete?"
msgstr "Επιβεβαίωση διαγραφής;"
msgctxt "#30092"
msgid "Warning: This action will delete the media files from the server."
msgstr ""
"Προειδοποίηση: Αυτή η ενέργεια θα διαγράψει τα αρχεία πολυμέσων από τον "
"διακομιστή."
msgctxt "#30112"
msgid "Loading Content"
msgstr "Φόρτωση Περιεχομένου"

View File

@@ -1077,8 +1077,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"
@@ -1103,4 +1103,20 @@ msgstr "Login using Quick Connect"
msgctxt "#30445"
msgid "Continue Watching"
msgstr "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"

View File

@@ -1,7 +1,7 @@
msgid ""
msgstr ""
"PO-Revision-Date: 2022-08-15 12:40+0000\n"
"Last-Translator: Francisco Álamo García <fran.minecraft.mta@gmail.com>\n"
"PO-Revision-Date: 2023-01-24 07:51+0000\n"
"Last-Translator: Ecor <elias.coronado@uabc.edu.mx>\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.13.1\n"
"X-Generator: Weblate 4.14.1\n"
msgctxt "#30442"
msgid "Simple new content check"
@@ -1105,3 +1105,23 @@ 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"

View File

@@ -1,6 +1,6 @@
msgid ""
msgstr ""
"PO-Revision-Date: 2022-08-09 05:22+0000\n"
"PO-Revision-Date: 2023-01-10 05:51+0000\n"
"Last-Translator: Oskari Lavinto <olavinto@protonmail.com>\n"
"Language-Team: Finnish <https://translate.jellyfin.org/projects/jellycon/"
"jellycon/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 4.14.1\n"
msgctxt "#30442"
msgid "Simple new content check"
@@ -1103,3 +1103,25 @@ 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 "Pikamiksaus"

View File

@@ -1,6 +1,6 @@
msgid ""
msgstr ""
"PO-Revision-Date: 2022-08-10 20:22+0000\n"
"PO-Revision-Date: 2023-01-17 19:51+0000\n"
"Last-Translator: Thomas Schwery <thomas@inf3.ch>\n"
"Language-Team: French <https://translate.jellyfin.org/projects/jellycon/"
"jellycon/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 4.14.1\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"
@@ -935,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"
@@ -953,10 +950,9 @@ msgctxt "#30394"
msgid "Cache files deleted"
msgstr "Fichiers du cache supprimés"
#, fuzzy
msgctxt "#30393"
msgid "Clear Cache Result"
msgstr "Vider le cache des résultats"
msgstr "Effacer le cache des résultats"
msgctxt "#30388"
msgid "Server details"
@@ -976,11 +972,155 @@ msgctxt "#30370"
msgid "Do you want to manually enter a server url?"
msgstr "Voulez-vous saisir manuellement une adresse de serveur ?"
#, fuzzy
msgctxt "#30369"
msgid "Do you want to clear your saved password?"
msgstr "Voulez-vous effacer votre mot de passe sauvé ?"
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é"

View File

@@ -1,6 +1,6 @@
msgid ""
msgstr ""
"PO-Revision-Date: 2022-08-09 05:22+0000\n"
"PO-Revision-Date: 2023-01-10 05:51+0000\n"
"Last-Translator: Csaba <csab0825@gmail.com>\n"
"Language-Team: Hungarian <https://translate.jellyfin.org/projects/jellycon/"
"jellycon/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 4.14.1\n"
msgctxt "#30441"
msgid "Use cached widget data"
@@ -1103,3 +1103,23 @@ 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"

View File

@@ -1,7 +1,7 @@
msgid ""
msgstr ""
"PO-Revision-Date: 2022-08-15 12:40+0000\n"
"Last-Translator: Arief Hidayat <kekesed97@gmail.com>\n"
"PO-Revision-Date: 2023-02-15 10:39+0000\n"
"Last-Translator: Imamuzzaki Abu Salam <imamuzzaki@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.13.1\n"
"X-Generator: Weblate 4.14.1\n"
msgctxt "#30414"
msgid " - Favorites"
@@ -1101,3 +1101,24 @@ 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"

View File

@@ -1,7 +1,7 @@
msgid ""
msgstr ""
"PO-Revision-Date: 2022-08-17 22:11+0000\n"
"Last-Translator: momphucker <weblate@mailbox.enricomarogna.com>\n"
"PO-Revision-Date: 2022-10-21 02:50+0000\n"
"Last-Translator: Angus Fraser <angusmglfraser@yahoo.co.uk>\n"
"Language-Team: Italian <https://translate.jellyfin.org/projects/jellycon/"
"jellycon/it/>\n"
"Language: it\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.13.1\n"
"X-Generator: Weblate 4.14.1\n"
msgctxt "#30120"
msgid "Show load progress"
@@ -466,6 +466,7 @@ msgctxt "#30323"
msgid "Artists"
msgstr "Artisti"
#, fuzzy
msgctxt "#30311"
msgid "Library - "
msgstr "Libreria -"
@@ -481,3 +482,88 @@ 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"
#, fuzzy
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)"

View 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 "즐겨찾기 설정"

View File

@@ -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: 2023-02-16 21:39+0000\n"
"Last-Translator: Ruben Kremer <rubenkremer@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 4.14.1\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 %"
@@ -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"
@@ -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,7 +305,7 @@ 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"
@@ -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,590 @@ 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"

View File

@@ -1,6 +1,6 @@
msgid ""
msgstr ""
"PO-Revision-Date: 2022-06-28 13:22+0000\n"
"PO-Revision-Date: 2023-01-17 19:51+0000\n"
"Last-Translator: Marcin Woliński <cierdek@gmail.com>\n"
"Language-Team: Polish <https://translate.jellyfin.org/projects/jellycon/"
"jellycon/pl/>\n"
@@ -10,7 +10,7 @@ msgstr ""
"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"
"X-Generator: Weblate 4.14.1\n"
msgctxt "#30313"
msgid "Menu"
@@ -1101,3 +1101,27 @@ msgstr "Szybkie połączenie"
msgctxt "#30323"
msgid "Artists"
msgstr "Artyści"
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"

View File

@@ -1,7 +1,7 @@
msgid ""
msgstr ""
"PO-Revision-Date: 2022-08-10 20:22+0000\n"
"Last-Translator: WWWesten <wwwesten@gmail.com>\n"
"PO-Revision-Date: 2023-02-13 01:39+0000\n"
"Last-Translator: Ilya Garkavenko <fewdji@gmail.com>\n"
"Language-Team: Russian <https://translate.jellyfin.org/projects/jellycon/"
"jellycon/ru/>\n"
"Language: ru\n"
@@ -10,7 +10,7 @@ msgstr ""
"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"
"X-Generator: Weblate 4.14.1\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"
@@ -353,7 +353,7 @@ 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"
@@ -1083,9 +1083,10 @@ msgctxt "#30001"
msgid "Port"
msgstr "Порт"
#, fuzzy
msgctxt "#30000"
msgid "Host"
msgstr "Узел"
msgstr "Хост"
msgctxt "#30444"
msgid "Login using Quick Connect"
@@ -1102,3 +1103,20 @@ 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 "Максимальный размер очереди"

View File

@@ -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: 2023-01-13 15:51+0000\n"
"Last-Translator: Weevild <Filip.westman@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 4.14.1\n"
msgctxt "#30283"
msgid "Play Next Episode?"
@@ -489,7 +489,7 @@ msgstr "Hoppa tillbaka sekunder"
msgctxt "#30125"
msgid "Done"
msgstr "Färdig"
msgstr "Klar"
msgctxt "#30139"
msgid "No Media Type Set"
@@ -549,7 +549,7 @@ msgstr "[Upptäck lokal server]"
msgctxt "#30003"
msgid "Verify HTTPS certificate"
msgstr "Verifiera HTTPS certifikat"
msgstr "Verifiera HTTPS-certifikat"
msgctxt "#30001"
msgid "Port"
@@ -649,7 +649,7 @@ msgstr "Adress:"
msgctxt "#30110"
msgid "Interface"
msgstr "Användargränssnitt"
msgstr "Gränssnitt"
msgctxt "#30135"
msgid "Error"
@@ -657,7 +657,7 @@ msgstr "Error"
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"
@@ -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 \"inte än sedd\" 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 - Osädda"
msgctxt "#30285"
msgid " - Unwatched"
@@ -796,23 +791,20 @@ 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 uppspelada halvsedda 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 upspelning upptäckt"
msgctxt "#30247"
msgid "Custom Widget Content"
@@ -826,7 +818,6 @@ msgctxt "#30220"
msgid "Prompt to delete movie after %"
msgstr "Uppmaning att radera film efter %"
#, fuzzy
msgctxt "#30219"
msgid " - Prompt before play"
msgstr "- Fråga före uppspelning"
@@ -835,15 +826,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 +844,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 +890,231 @@ 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 prestanda profiler 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"

View File

@@ -1,2 +1,328 @@
msgid ""
msgstr "X-Generator: Weblate\nMIME-Version: 1.0\nContent-Type: text/plain; charset=UTF-8\nContent-Transfer-Encoding: 8bit"
msgstr ""
"PO-Revision-Date: 2022-10-01 13:54+0000\n"
"Last-Translator: Thanos <ahmetspam.42@hotmail.com>\n"
"Language-Team: Turkish <https://translate.jellyfin.org/projects/jellycon/"
"jellycon/tr/>\n"
"Language: tr\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 4.14.1\n"
msgctxt "#30237"
msgid "Start from beginning"
msgstr "Baştan başla"
msgctxt "#30236"
msgid "Force transcode h265 (hevc)"
msgstr "H265 (hevc) kodunu dönüştürmeye zorla"
msgctxt "#30235"
msgid "Episodes"
msgstr "Bölümler"
msgctxt "#30231"
msgid "Movies"
msgstr "Filmler"
msgctxt "#30229"
msgid "TV Shows"
msgstr "TV Şovları"
msgctxt "#30224"
msgid "Interaction"
msgstr "Etkileşim"
msgctxt "#30223"
msgid "Page Size and Filtering"
msgstr "Sayfa Boyutu ve Filtreleme"
msgctxt "#30222"
msgid "Item Layout"
msgstr "Öğe Düzeni"
msgctxt "#30220"
msgid "Prompt to delete movie after %"
msgstr "%'den sonra filmi silme istemi"
msgctxt "#30219"
msgid " - Prompt before play"
msgstr "- Oynamadan önce sor"
msgctxt "#30218"
msgid "Play next episode after %"
msgstr "% sonra sonraki bölümü oynat"
msgctxt "#30217"
msgid "Prompt to delete episode after %"
msgstr "%'den sonra bölümü silme istemi"
msgctxt "#30216"
msgid "Item Details"
msgstr "Ürün Detayları"
msgctxt "#30215"
msgid "On playback stop (100% = disabled)"
msgstr "Oynatma durduğunda (%100 = devre dışı)"
msgctxt "#30214"
msgid "Events"
msgstr "Olaylar"
msgctxt "#30213"
msgid "Video force 8 bit"
msgstr "Video 8 bit kullanimini zorla"
msgctxt "#30212"
msgid "Video max width"
msgstr "Video maksimum genişliği"
msgctxt "#30211"
msgid "Transcode options"
msgstr "Kod dönüştürme seçenekleri"
#, fuzzy
msgctxt "#30210"
msgid "HTTP direct stream"
msgstr "HTTP doğrudan akışı"
#, fuzzy
msgctxt "#30209"
msgid "File direct path"
msgstr "Dosyanin doğrudan yolu"
msgctxt "#30208"
msgid "Max stream bitrate (Kbits)"
msgstr "Maksimum akış bit hızı (Kbps)"
#, fuzzy
msgctxt "#30207"
msgid "Playback"
msgstr "Geri çalma"
msgctxt "#30206"
msgid "Playback type"
msgstr "Oynatma türü"
msgctxt "#30201"
msgid "Unable to connect to server"
msgstr "Sunucuya bağlanılamıyor"
msgctxt "#30200"
msgid "URL error"
msgstr "URL hatası"
msgctxt "#30183"
msgid "Include people"
msgstr "Kişileri dahil et"
msgctxt "#30182"
msgid "Include media stream info"
msgstr "Medya akışı bilgilerini dahil et"
msgctxt "#30181"
msgid "Include plot"
msgstr "Konuyu dahil et"
msgctxt "#30180"
msgid "Select User"
msgstr "Kullanıcı seç"
msgctxt "#30169"
msgid "Address: "
msgstr "Adres:"
#, fuzzy
msgctxt "#30167"
msgid "Selected Server Address"
msgstr "Seçilen Sunucunun Adresi"
msgctxt "#30166"
msgid "Select Server"
msgstr "Sunucu seç"
msgctxt "#30163"
msgid "Add (cc) if subtitle is available"
msgstr "Altyazı varsa (cc) ekleyin"
msgctxt "#30139"
msgid "No Media Type Set"
msgstr "Medya Türü Ayarı Yok"
msgctxt "#30135"
msgid "Error"
msgstr "Hata"
msgctxt "#30126"
msgid "Processing Item : "
msgstr "Öğenin İşlenmesi:"
msgctxt "#30125"
msgid "Done"
msgstr "Tamamlandı"
#, fuzzy
msgctxt "#30121"
msgid "On resume"
msgstr "Sürdürunce"
msgctxt "#30120"
msgid "Show load progress"
msgstr "Yükleme ilerlemesini göster"
msgctxt "#30118"
msgid "Add resume percent to names"
msgstr "İsimlere özgeçmiş yüzdesi ekle"
#, fuzzy
msgctxt "#30116"
msgid "Add unwatched counts to names"
msgstr "Adlara izlenmeyen sayıları ekleyin"
#, fuzzy
msgctxt "#30114"
msgid "Jump back seconds"
msgstr "Saniyeler geri atla"
msgctxt "#30113"
msgid "Retrieving Data"
msgstr "Veri Aliniyor"
msgctxt "#30112"
msgid "Loading Content"
msgstr "İçerik Yükleniyor"
msgctxt "#30111"
msgid "Services"
msgstr "Hizmetler"
msgctxt "#30110"
msgid "Interface"
msgstr "Arayüz"
msgctxt "#30092"
msgid "Warning: This action will delete the media files from the server."
msgstr "Uyarı: Bu eylem, medya dosyalarını sunucudan siler."
msgctxt "#30091"
msgid "Confirm delete?"
msgstr "Silmeyi onayla?"
msgctxt "#30063"
msgid "N/A"
msgstr "Yok"
#, fuzzy
msgctxt "#30053"
msgid "Waiting for server to delete"
msgstr "Sunucunun silmesi bekleniyor"
msgctxt "#30052"
msgid "Deleting"
msgstr "Siliniyor"
msgctxt "#30045"
msgid "Username not found"
msgstr "Kullanıcı bulunamadı"
msgctxt "#30044"
msgid "Incorrect Username/Password"
msgstr "Yanlış kullanıcı/şifre"
#, fuzzy
msgctxt "#30027"
msgid "Enable debug logging"
msgstr "Hata ayıklama günlüğünü etkinleştir"
#, fuzzy
msgctxt "#30026"
msgid "Widget item select action"
msgstr "Widget öğesi seçme eylemi"
msgctxt "#30025"
msgid "Password:"
msgstr "Şifre:"
msgctxt "#30024"
msgid "Username:"
msgstr "Kullanıcı:"
msgctxt "#30023"
msgid "Hide unwatched episode details"
msgstr "İzlenmeyen bölüm ayrıntılarını gizle"
msgctxt "#30022"
msgid "Advanced"
msgstr "Gelişmiş"
msgctxt "#30021"
msgid "Show all episodes item"
msgstr "Tüm bölümleri göster"
msgctxt "#30020"
msgid "Flatten single season"
msgstr "Tek sezon düzleştirin"
msgctxt "#30019"
msgid "Filtered episode name format"
msgstr "Filtrelenmiş bölüm adı biçimi"
msgctxt "#30018"
msgid "Number of items to show in filtered lists"
msgstr "Filtrelenmiş listelerde gösterilecek öğe sayısı"
msgctxt "#30017"
msgid "Show connected clients"
msgstr "Bağlı istemcileri göster"
msgctxt "#30016"
msgid "Device display name"
msgstr "Cihazın görünen adı"
msgctxt "#30015"
msgid "Log timing data"
msgstr "Zamanlama verilerini günlüğe kaydet"
msgctxt "#30014"
msgid "Jellyfin"
msgstr "Jellyfin"
msgctxt "#30012"
msgid "[Change user]"
msgstr "[Kullanıcıyı değiştir]"
#, fuzzy
msgctxt "#30011"
msgid "[Detect local server]"
msgstr "[Yerel sunucuyu algıla]"
#, fuzzy
msgctxt "#30010"
msgid "Number of performance profiles to capture"
msgstr "Yakalanacak performans profili sayısı"
msgctxt "#30008"
msgid "Samba password"
msgstr "Samba Şifre"
msgctxt "#30007"
msgid "Samba username"
msgstr "Samba Kullanıcı"
msgctxt "#30006"
msgid "Password"
msgstr "Şifre"
msgctxt "#30005"
msgid "Username"
msgstr "Kullanıcı"
msgctxt "#30003"
msgid "Verify HTTPS certificate"
msgstr "HTTPS sertifikasını doğrulayın"
msgctxt "#30000"
msgid "Host"
msgstr "Sunucu"

View File

@@ -1,7 +1,7 @@
msgid ""
msgstr ""
"PO-Revision-Date: 2022-07-07 17:22+0000\n"
"Last-Translator: Fedir Smilianets <fedor.smile@gmail.com>\n"
"PO-Revision-Date: 2022-08-21 02:11+0000\n"
"Last-Translator: lyaschuchenko <lyaschuchenko@gmail.com>\n"
"Language-Team: Ukrainian <https://translate.jellyfin.org/projects/jellycon/"
"jellycon/uk/>\n"
"Language: uk\n"
@@ -10,7 +10,7 @@ msgstr ""
"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"
"X-Generator: Weblate 4.13.1\n"
msgctxt "#30434"
msgid "Force transcode stream bitrate (Kbits)"
@@ -1100,3 +1100,7 @@ msgstr "Порт"
msgctxt "#30000"
msgid "Host"
msgstr "Хост"
msgctxt "#30445"
msgid "Continue Watching"
msgstr "Продовжити перегляд"

View File

@@ -1,7 +1,7 @@
msgid ""
msgstr ""
"PO-Revision-Date: 2022-06-20 16:22+0000\n"
"Last-Translator: wolong gl <wolong98@gmail.com>\n"
"PO-Revision-Date: 2023-02-02 09:51+0000\n"
"Last-Translator: kid1412621 <kid1412621@gmail.com>\n"
"Language-Team: Chinese (Simplified) <https://translate.jellyfin.org/projects/"
"jellycon/jellycon/zh_Hans/>\n"
"Language: zh_Hans\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 4.14.1\n"
msgctxt "#30442"
msgid "Simple new content check"
@@ -1094,3 +1094,27 @@ 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 "最大播放队列数"

View File

@@ -1,7 +1,7 @@
msgid ""
msgstr ""
"PO-Revision-Date: 2022-04-14 06:13+0000\n"
"Last-Translator: rayanamukami <rayanamukami@gmail.com>\n"
"PO-Revision-Date: 2022-11-13 01:50+0000\n"
"Last-Translator: siriuskoan <me@siriuskoan.one>\n"
"Language-Team: Chinese (Traditional) <https://translate.jellyfin.org/"
"projects/jellycon/jellycon/zh_Hant/>\n"
"Language: zh_Hant\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 4.14.1\n"
msgctxt "#30207"
msgid "Playback"
@@ -102,3 +102,15 @@ msgstr "埠"
msgctxt "#30000"
msgid "Host"
msgstr "主機"
msgctxt "#30016"
msgid "Device display name"
msgstr "裝置顯示名稱"
msgctxt "#30017"
msgid "Show connected clients"
msgstr "顯示已連線的用戶"
msgctxt "#30011"
msgid "[Detect local server]"
msgstr "[偵測本機使用者]"

View File

@@ -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

View File

@@ -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
@@ -208,7 +208,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")

View File

@@ -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__)
@@ -259,7 +260,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

View File

@@ -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
@@ -204,43 +206,3 @@ class PlayNextDialog(xbmcgui.WindowXMLDialog):
def get_play_called(self):
return self.play_called
class QuickConnectDialog(xbmcgui.WindowXMLDialog):
connect_method = -1
def __init__(self, *args, **kwargs):
xbmcgui.WindowXMLDialog.__init__(self, *args, **kwargs)
log.debug("QuickConnectDialog INITIALISED")
self.code = ''
def onInit(self):
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):
pass
def doAction(self, actionID):
pass
def onClick(self, controlID):
if controlID == 3010:
self.connect_method = 1
self.close()
if controlID == 3011:
self.connect_method = 0
self.close()
def getConnectMethod(self):
return self.connect_method

View File

@@ -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 .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__)
@@ -68,6 +72,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))
@@ -244,14 +253,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 +271,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' +
@@ -324,7 +336,7 @@ 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:
@@ -333,7 +345,7 @@ def process_directory(url, progress, params, use_cache_data=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' +
@@ -341,7 +353,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' +
@@ -358,7 +370,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' +
@@ -382,7 +394,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) +

View File

@@ -1,30 +1,40 @@
# 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
@@ -35,6 +45,7 @@ __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')
log = LazyLogger(__name__)
@@ -56,7 +67,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 +81,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"
@@ -107,7 +122,9 @@ def main_entry_point():
__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 +146,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 +162,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 +178,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,61 +199,61 @@ 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.delete("/Users/{}/Items/{}".format(api.user_id, item_id))
item_id = item.get("Id")
item_name = item.get("Name", "")
@@ -278,18 +263,24 @@ def delete(item_id):
final_name = ""
if series_name:
final_name += series_name + " - "
final_name += "{} -".format(series_name)
if ep_number != -1:
final_name += "Episode %02d - " % (ep_number,)
final_name += "Episode {:02d} - ".format(ep_number)
final_name += item_name
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 +292,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 +313,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 +336,39 @@ 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"]:
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 +441,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')
@@ -461,22 +474,30 @@ def show_menu(params):
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 +506,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 +575,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 +627,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 +672,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 +697,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 +727,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 +760,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 +776,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 +810,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 +842,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 +856,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)
@@ -851,7 +946,9 @@ def play_action(params):
def play_item_trailer(item_id):
log.debug("== ENTER: playTrailer ==")
url = "/Users/{}/Items/{}/LocalTrailers?format=json".format(user_details.get('user_id'), item_id)
url = "/Users/{}/Items/{}/LocalTrailers?format=json".format(
user_details.get('user_id'), item_id
)
result = api.get(url)
@@ -868,7 +965,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 +973,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 +992,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 +1002,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 +1020,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 = "RunPlugin(plugin://{}{})".format(url_root, youtube_id)
log.debug("youtube_plugin: {0}".format(play_url))
xbmc.executebuiltin(youtube_plugin)
xbmc.executebuiltin(play_url)

View File

@@ -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

View File

@@ -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)

View File

@@ -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,13 +68,13 @@ 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)

View File

@@ -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

View File

@@ -1,11 +1,13 @@
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__)
@@ -35,11 +37,13 @@ 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 = {}
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)

View File

@@ -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):

View File

@@ -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,13 +12,9 @@ from kodi_six import xbmc, xbmcaddon
from .utils import translate_path
##################################################################################################
__addon__ = xbmcaddon.Addon(id='plugin.video.jellycon')
__pluginpath__ = translate_path(__addon__.getAddonInfo('path'))
##################################################################################################
def getLogger(name=None):
if name is None:
@@ -47,7 +42,9 @@ class LogHandler(logging.StreamHandler):
string = self.format(record)
# Hide server URL in logs
string = string.replace(self.server or "{server}", "{jellyfin-server}")
string = string.replace(
self.server or "{server}", "{jellyfin-server}"
)
py_version = sys.version_info.major
# Log level notation changed in Kodi v19
@@ -75,12 +72,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)
@@ -97,7 +99,10 @@ class MyFormatter(logging.Formatter):
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 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):

View File

@@ -1,20 +1,23 @@
# 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 .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_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 +78,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 +167,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 +240,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 +283,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 +324,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 +339,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 +397,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 +417,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 +446,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 +458,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 +557,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))))}
@@ -554,13 +610,11 @@ def display_menu(params):
def show_global_types(params):
handle = int(sys.argv[1])
user_id = get_current_user_id()
continue_watching_url_params = {
"Fields": get_default_filters(),
"ImageTypeLimit": 1,
}
continue_watching_url = get_jellyfin_url("/Users/{}/Items/Resume".format(user_id), continue_watching_url_params)
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" +
@@ -579,7 +633,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 = {
@@ -589,7 +642,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)
@@ -599,7 +652,7 @@ 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)
@@ -613,7 +666,7 @@ 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)
@@ -644,7 +697,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 = {
@@ -656,7 +708,7 @@ 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)
url = sys.argv[0] + "?url=" + quote(path) + "&mode=GET_CONTENT&media_type=tvshows"
add_menu_directory_item(view_name + translate_string(30405), url)
@@ -664,7 +716,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)
@@ -672,7 +724,7 @@ 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)
@@ -684,7 +736,7 @@ 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)
@@ -696,7 +748,7 @@ 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)
@@ -708,7 +760,7 @@ 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)
@@ -717,7 +769,7 @@ def display_tvshow_type(menu_params, view):
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"
@@ -747,7 +799,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 = {
@@ -756,7 +807,7 @@ 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)
url = sys.argv[0] + "?url=" + quote(path) + "&mode=GET_CONTENT&media_type=MusicAlbums"
add_menu_directory_item(view_name + translate_string(30320), url)
@@ -767,7 +818,7 @@ 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)
@@ -782,7 +833,7 @@ 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)
@@ -797,7 +848,7 @@ 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)
@@ -824,6 +875,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)
@@ -832,7 +890,6 @@ def display_musicvideos_type(params, view):
xbmcplugin.setContent(handle, 'files')
view_name = view.get("Name")
user_id = get_current_user_id()
# artists
params = {
@@ -842,7 +899,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)
@@ -854,11 +911,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()
@@ -869,7 +925,7 @@ def display_livetv_type(menu_params, view):
# programs
params = {
"UserId": user_id,
"UserId": '{userid}',
"IsAiring": True,
"ImageTypeLimit": 1,
"Fields": get_default_filters() + ",ChannelInfo",
@@ -881,7 +937,7 @@ def display_livetv_type(menu_params, view):
# recordings
params = {
"UserId": user_id,
"UserId": '{userid}',
"Recursive": False,
"ImageTypeLimit": 1,
"Fields": get_default_filters(),
@@ -905,7 +961,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",
@@ -920,7 +975,7 @@ 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)
url = sys.argv[0] + "?url=" + quote(path) + "&mode=GET_CONTENT&media_type=movies"
add_menu_directory_item('{}{}'.format(view_name, translate_string(30405)), url)
@@ -930,7 +985,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)
@@ -940,7 +995,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)
@@ -953,7 +1008,7 @@ 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)
@@ -964,7 +1019,7 @@ 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)
@@ -976,7 +1031,8 @@ 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)
@@ -988,13 +1044,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)
@@ -1037,6 +1093,111 @@ 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)
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) + " (" + item_limit + ")", 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) + " (" + item_limit + ")", 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) + " (" + item_limit + ")", 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) + " (" + item_limit + ")", 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')
@@ -1052,10 +1213,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")
@@ -1082,9 +1243,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
@@ -1100,9 +1260,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
@@ -1114,9 +1273,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
@@ -1130,7 +1288,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)
@@ -1144,6 +1302,8 @@ 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():
@@ -1211,8 +1371,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")

View File

@@ -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)

View File

@@ -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

View File

@@ -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
from datetime import timedelta
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
@@ -255,17 +260,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", "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)
@@ -441,6 +481,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))
@@ -738,21 +787,29 @@ 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', "")
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)
audio_streams_list[track] = index
audio_streams.append(track)
elif 'Subtitle' in stream['Type']:
try:
# Track includes language
track = "%s - %s" % (index, stream['Language'])
except:
except KeyError:
# Track doesn't include language
track = "%s - %s" % (index, stream['Codec'])
default = stream['IsDefault']
@@ -818,10 +875,7 @@ def audio_subs_pref(url, list_item, media_source, item_id, audio_stream_index, s
else: # User backed out of selection
playurlprefs += "&SubtitleStreamIndex=%s" % 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
@@ -837,8 +891,6 @@ 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:
@@ -847,9 +899,6 @@ def external_subs(media_source, list_item, item_id):
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)
@@ -982,20 +1031,20 @@ 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 perceantge 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:
@@ -1039,6 +1088,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))
@@ -1051,6 +1101,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
@@ -1136,14 +1191,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
@@ -1155,6 +1207,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":
@@ -1172,17 +1225,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 = {
@@ -1192,8 +1237,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
@@ -1203,8 +1246,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")
@@ -1230,7 +1272,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)
@@ -1239,9 +1282,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, []
@@ -1391,18 +1431,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"]
@@ -1465,17 +1516,16 @@ def get_item_playback_info(item_id, force_transcode):
if settings.getSetting("force_transcode_mpeg4") == "true":
filtered_codecs.append("mpeg4")
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
profile = {
"Name": "Kodi",

View File

@@ -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

View File

@@ -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))
@@ -212,54 +214,82 @@ 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)
# 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))
auth = api.post('/Users/AuthenticateWithQuickConnect',
{'secret': secret})
# 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)
settings.setSetting('username', 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"
if not user_details:
# Ask for password if user has one
password = ''
if secured and not user_details.get('token'):
# If using a manual login, ask for username
if manual:
kb = xbmc.Keyboard()
kb.setHeading(translate_string(30006))
kb.setHiddenInput(True)
kb.setHeading(translate_string(30005))
if current_username:
kb.setDefault(current_username)
kb.doModal()
if kb.isConfirmed():
password = kb.getText()
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()
@@ -277,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)
@@ -363,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)

View File

@@ -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)

View File

@@ -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():

View File

@@ -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

View File

@@ -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,15 @@ 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))))
data_str = ensure_text(binascii.hexlify(ensure_binary(data_str)))
sender = 'plugin.video.jellycon'
data = '"[%s]"' % json.dumps(data).replace('"', '\\"')
data = '"[{}]"'.format(data_str.replace('"', '\\"'))
xbmc.executebuiltin('NotifyAll(%s, %s, %s)' % (sender, method, data))
xbmc.executebuiltin('NotifyAll({}, {}, {})'.format(sender, method, data))
def datetime_from_string(time_string):
@@ -97,15 +100,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 +138,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):
@@ -144,16 +154,19 @@ def get_device_id():
window = HomeWindow()
username = window.get_property('user_name')
if not username:
settings = xbmcaddon.Addon()
username = settings.getSetting('username')
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()
@@ -181,7 +194,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
@@ -189,7 +203,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 = {}
@@ -199,7 +213,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)
@@ -217,14 +232,14 @@ 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 {}
@@ -247,6 +262,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')
@@ -286,12 +329,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:
@@ -299,7 +343,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(
@@ -310,7 +356,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:
@@ -374,15 +422,29 @@ def translate_path(path):
def download_external_sub(language, codec, url):
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_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

View File

@@ -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
@@ -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':
@@ -253,7 +254,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(

View File

@@ -1,14 +1,20 @@
from __future__ import division, absolute_import, print_function, unicode_literals
from __future__ import (
division, absolute_import, print_function, unicode_literals
)
import xbmcaddon
import xbmcplugin
import xbmcgui
import hashlib
import random
import time
import xbmcaddon
import xbmcplugin
import xbmcgui
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
@@ -77,8 +83,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 +113,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 +182,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 +228,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 +251,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 +272,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)
@@ -387,12 +404,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]
@@ -406,22 +430,23 @@ def get_widget_content(handle, params):
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
if detected_type is not None:
# if the media type is not set then try to use the detected type
@@ -434,7 +459,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:

View File

@@ -28,7 +28,7 @@
<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="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" />
@@ -38,12 +38,13 @@
<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 id="max_play_queue" type="slider" label="30447" default="200" range="20, 10, 1000" option="int" visible="true"/>
</category>
<category label="30214">

View File

@@ -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>

View File

@@ -29,7 +29,7 @@ if log_timing_data:
# 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")
@@ -99,7 +99,7 @@ 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')
@@ -118,9 +118,9 @@ 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:
@@ -177,16 +177,16 @@ 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")
# clear user and token when logging off
home_window.clear_property("user_name")
home_window.clear_property("AccessToken")
home_window.clear_property("userimage")