Merge pull request #3 from cvium/rebrand

Rebrand to Jellyfin
This commit is contained in:
Vasily 2019-02-03 16:33:50 +03:00 committed by GitHub
commit 2d0d21aa2b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
87 changed files with 1190 additions and 1989 deletions

2
.gitignore vendored
View file

@ -4,3 +4,5 @@ machine_guid
/resources/media/Thumbs.db /resources/media/Thumbs.db
.idea/ .idea/
.DS_Store
.vscode/

View file

@ -1,6 +1,6 @@
# How to contribute # How to contribute
Thanks you for contributing to Emby for Kodi! Thanks you for contributing to Jellyfin for Kodi!
* Make pull requests towards the **master** branch; * Make pull requests towards the **master** branch;
* Keep the maximum line length shorter than 100 characters to keep things clean and readable; * Keep the maximum line length shorter than 100 characters to keep things clean and readable;

View file

@ -1,22 +1,24 @@
# Emby for Kodi # Jellyfin for Kodi
<!--
[![EmbyKodi_Banner](https://i.imgur.com/hx4cx41.png)](https://emby.media/community/index.php?/forum/99-kodi/) TODO
[![EmbyKodi_Banner](https://i.imgur.com/hx4cx41.png)](https://forum.jellyfin.org/)
[![Wiki](https://img.shields.io/badge/get%20started-wiki-brightgreen.svg)](https://github.com/MediaBrowser/plugin.video.emby/wiki) [![Wiki](https://img.shields.io/badge/get%20started-wiki-brightgreen.svg)](https://github.com/MediaBrowser/plugin.video.emby/wiki)
[![Forums](https://img.shields.io/badge/report%20issues-forums-3960C1.svg)](https://emby.media/community/index.php?/forum/99-kodi/) [![Forums](https://img.shields.io/badge/report%20issues-forums-3960C1.svg)](https://forum.jellyfin.org/)
[![Donate](https://img.shields.io/badge/donate-kofi-blue.svg)](https://ko-fi.com/A5354BI) [![Donate](https://img.shields.io/badge/donate-kofi-blue.svg)](https://ko-fi.com/A5354BI)
[![Emby](https://img.shields.io/badge/server-emby-52b54b.svg)](https://emby.media/) [![Emby](https://img.shields.io/badge/server-emby-52b54b.svg)](https://jellyfin.media/)
___ ___
-->
**A whole new way to manage and view your media library.** **A whole new way to manage and view your media library.**
The Emby for Kodi add-on combines the best of Kodi - ultra smooth navigation, beautiful UIs and playback of any file under the sun, and Emby - the most powerful open source multi-client media metadata indexer and server. You can now retire your MySQL setup in favor of a more flexible setup. The Jellyfin for Kodi add-on combines the best of Kodi - ultra smooth navigation, beautiful UIs and playback of any file under the sun, and Jellyfin - the most powerful open source multi-client media metadata indexer and server. You can now retire your MySQL setup in favor of a more flexible setup.
Synchronize your media on your Emby server to the native Kodi database, browsing your media at full speed, while retaining the ability to use other Kodi add-ons to enhance your experience. In addition, you can use any Kodi skin you'd like! Synchronize your media on your Jellyfin server to the native Kodi database, browsing your media at full speed, while retaining the ability to use other Kodi add-ons to enhance your experience. In addition, you can use any Kodi skin you'd like!
___ ___
### Supported ### Supported
The add-on supports a hybrid approach. You can decide which Emby libraries to sync to the Kodi database. Other libraries and features are accessible dynamically, as a plugin listing. The add-on supports a hybrid approach. You can decide which Jellyfin libraries to sync to the Kodi database. Other libraries and features are accessible dynamically, as a plugin listing.
- Library types available to sync: - Library types available to sync:
+ Movies and sets + Movies and sets
+ TV shows + TV shows
@ -29,19 +31,22 @@ The add-on supports a hybrid approach. You can decide which Emby libraries to sy
+ Theme media + Theme media
- Direct play and transcode - Direct play and transcode
- A 2-way watched and resume state between your server and Kodi. This is a near instant feature. - A 2-way watched and resume state between your server and Kodi. This is a near instant feature.
- Remote control your Kodi; send play commands from your Emby web client or Emby mobile apps. - Remote control your Kodi; send play commands from your Jellyfin web client or Jellyfin mobile apps.
- Extrafanart (rotating backgrounds) for skins that support it - Extrafanart (rotating backgrounds) for skins that support it
- Offer to delete content after playback - Offer to delete content after playback
- Backup your emby kodi profile. See the [Emby backup option](https://github.com/MediaBrowser/plugin.video.emby/wiki/Create-and-restore-from-backup) - Backup your Jellyfin Kodi profile ([Create and restore from backup
](https://web.archive.org/web/20190202213116/https://github.com/MediaBrowser/plugin.video.emby/wiki/create-and-restore-from-backup))
- and more... - and more...
### Install Emby for Kodi ### Install Jellyfin for Kodi
Get started with the [wiki guide](https://github.com/MediaBrowser/plugin.video.emby/wiki) 1. Install Jellyfin for Kodi from zip.
2. Within a few seconds you should be prompted for your server-details.
3. Once you're succesfully authenticated with your Jellyfin server, the initial sync will start.
4. The first sync of the Jellyfin server to the local Kodi database may take some time depending on your device and library size.
5. Once the full sync is done, you can browse your media in Kodi, and syncs will be done automatically in the background.
<!-- Get started with the [wiki guide](https://github.com/MediaBrowser/plugin.video.emby/wiki) -->
### Known limitations ### Known limitations
- Chapter images are missing unless native playback mode is used. - Chapter images are missing unless native playback mode is used.
- Certain add-ons that depend on seeing where your content is located will not work unless native playback mode is selected. - Certain add-ons that depend on seeing where your content is located will not work unless native playback mode is selected.
___
### Help translate
Check [Transifex](https://www.transifex.com/emby-for-kodi/emby-for-kodi/stringspo/) to help translate this project. Thank you!

View file

@ -1,13 +1,10 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<addon id="plugin.video.emby" <addon id="plugin.video.jellyfin"
name="Emby" name="Jellyfin"
version="4.0.3" version="10.1.0"
provider-name="angelblue05"> provider-name="angelblue05">
<requires> <requires>
<import addon="xbmc.python" version="2.25.0"/> <import addon="xbmc.python" version="2.25.0"/>
<import addon="plugin.video.emby.movies" version="0.14" />
<import addon="plugin.video.emby.tvshows" version="0.14" />
<import addon="plugin.video.emby.musicvideos" version="0.14" />
</requires> </requires>
<extension point="xbmc.python.pluginsource" <extension point="xbmc.python.pluginsource"
library="default.py"> library="default.py">
@ -19,11 +16,11 @@
<menu id="kodi.core.main"> <menu id="kodi.core.main">
<item library="context.py"> <item library="context.py">
<label>30401</label> <label>30401</label>
<visible>[!String.IsEmpty(ListItem.DBID) + !String.IsEqual(ListItem.DBID,-1) | !String.IsEmpty(ListItem.Property(embyid))] + !String.IsEmpty(Window(10000).Property(emby_context))</visible> <visible>[!String.IsEmpty(ListItem.DBID) + !String.IsEqual(ListItem.DBID,-1) | !String.IsEmpty(ListItem.Property(jellyfinid))] + !String.IsEmpty(Window(10000).Property(jellyfin_context))</visible>
</item> </item>
<item library="context_play.py"> <item library="context_play.py">
<label>30402</label> <label>30402</label>
<visible>[[!String.IsEmpty(ListItem.DBID) + !String.IsEqual(ListItem.DBID,-1) | !String.IsEmpty(ListItem.Property(embyid))] + [String.IsEqual(ListItem.DBTYPE,movie) | String.IsEqual(ListItem.DBTYPE,episode)]] + !String.IsEmpty(Window(10000).Property(emby_context_transcode))</visible> <visible>[[!String.IsEmpty(ListItem.DBID) + !String.IsEqual(ListItem.DBID,-1) | !String.IsEmpty(ListItem.Property(jellyfinid))] + [String.IsEqual(ListItem.DBTYPE,movie) | String.IsEqual(ListItem.DBTYPE,episode)]] + !String.IsEmpty(Window(10000).Property(jellyfin_context_transcode))</visible>
</item> </item>
</menu> </menu>
</extension> </extension>
@ -31,18 +28,17 @@
<platform>all</platform> <platform>all</platform>
<language>en</language> <language>en</language>
<license>GNU GENERAL PUBLIC LICENSE. Version 2, June 1991</license> <license>GNU GENERAL PUBLIC LICENSE. Version 2, June 1991</license>
<forum>http://emby.media/community/index.php?/forum/99-kodi/</forum> <forum>https://forum.jellyfin.org</forum>
<website>http://emby.media/</website> <website>https://jellyfin.media/</website>
<source>https://github.com/MediaBrowser/plugin.video.emby</source> <source>https://github.com/jellyfin/jellyfin-kodi</source>
<summary lang="en"></summary> <summary lang="en"></summary>
<description lang="en">Welcome to Emby for Kodi A whole new way to manage and view your media library. The Emby addon for Kodi combines the best of Kodi - ultra smooth navigation, beautiful UIs and playback of any file under the sun, and Emby - the most powerful fully open source multi-client media metadata indexer and server.&#10;&#10;Emby for Kodi is the absolute best way to enjoy the incredible Kodi playback engine combined with the power of Emby's centralized database. Features: Direct integration with the Kodi library for native Kodi speed Instant synchronization with the Emby server Full support for Movie, TV and Music collections Emby Server direct stream and transcoding support - use Kodi when you are away from home!</description> <description lang="en">Welcome to Jellyfin for Kodi!&#10;A whole new way to manage and view your media library. The Jellyfin addon for Kodi combines the best of Kodi - ultra smooth navigation, beautiful UIs and playback of any file under the sun, and Jellyfin - the most powerful fully open source multi-client media metadata indexer and server.&#10;&#10;Jellyfin for Kodi is the absolute best way to enjoy the incredible Kodi playback engine combined with the power of Jellyfin's centralized database. Features:&#10;* Direct integration with the Kodi library for native Kodi speed&#10;* Instant synchronization with the Jellyfin server&#10;* Full support for Movie, TV and Music collections&#10;* Jellyfin Server direct stream and transcoding support - use Kodi when you are away from home!</description>
<news> <news>
New stable release Rebrand in progress
The wiki has been updated, PLEASE READ: https://github.com/MediaBrowser/plugin.video.emby/wiki
Fix playback for Kodi Leia
Fix masterlock
Home videos and pictures now show under videos and picture add-ons
Dependencies were updated to 0.14!
</news> </news>
<assets>
<icon>icon.png</icon>
<fanart>fanart.jpg</fanart>
</assets>
</extension> </extension>
</addon> </addon>

View file

@ -11,11 +11,11 @@ import xbmcaddon
################################################################################################# #################################################################################################
__addon__ = xbmcaddon.Addon(id='plugin.video.emby') __addon__ = xbmcaddon.Addon(id='plugin.video.jellyfin')
__base__ = xbmc.translatePath(os.path.join(__addon__.getAddonInfo('path'), 'resources', 'lib')).decode('utf-8') __base__ = xbmc.translatePath(os.path.join(__addon__.getAddonInfo('path'), 'resources', 'lib')).decode('utf-8')
__libraries__ = xbmc.translatePath(os.path.join(__addon__.getAddonInfo('path'), 'libraries')).decode('utf-8') __libraries__ = xbmc.translatePath(os.path.join(__addon__.getAddonInfo('path'), 'libraries')).decode('utf-8')
__pcache__ = xbmc.translatePath(os.path.join(__addon__.getAddonInfo('profile'), 'emby')).decode('utf-8') __pcache__ = xbmc.translatePath(os.path.join(__addon__.getAddonInfo('profile'), 'jellyfin')).decode('utf-8')
__cache__ = xbmc.translatePath('special://temp/emby').decode('utf-8') __cache__ = xbmc.translatePath('special://temp/jellyfin').decode('utf-8')
sys.path.insert(0, __cache__) sys.path.insert(0, __cache__)
sys.path.insert(0, __pcache__) sys.path.insert(0, __pcache__)
@ -28,7 +28,7 @@ from entrypoint import Context
################################################################################################# #################################################################################################
LOG = logging.getLogger("EMBY.context") LOG = logging.getLogger("JELLYFIN.context")
################################################################################################# #################################################################################################

View file

@ -11,11 +11,11 @@ import xbmcaddon
################################################################################################# #################################################################################################
__addon__ = xbmcaddon.Addon(id='plugin.video.emby') __addon__ = xbmcaddon.Addon(id='plugin.video.jellyfin')
__base__ = xbmc.translatePath(os.path.join(__addon__.getAddonInfo('path'), 'resources', 'lib')).decode('utf-8') __base__ = xbmc.translatePath(os.path.join(__addon__.getAddonInfo('path'), 'resources', 'lib')).decode('utf-8')
__libraries__ = xbmc.translatePath(os.path.join(__addon__.getAddonInfo('path'), 'libraries')).decode('utf-8') __libraries__ = xbmc.translatePath(os.path.join(__addon__.getAddonInfo('path'), 'libraries')).decode('utf-8')
__pcache__ = xbmc.translatePath(os.path.join(__addon__.getAddonInfo('profile'), 'emby')).decode('utf-8') __pcache__ = xbmc.translatePath(os.path.join(__addon__.getAddonInfo('profile'), 'jellyfin')).decode('utf-8')
__cache__ = xbmc.translatePath('special://temp/emby').decode('utf-8') __cache__ = xbmc.translatePath('special://temp/jellyfin').decode('utf-8')
sys.path.insert(0, __cache__) sys.path.insert(0, __cache__)
sys.path.insert(0, __pcache__) sys.path.insert(0, __pcache__)
@ -28,7 +28,7 @@ from entrypoint import Context
################################################################################################# #################################################################################################
LOG = logging.getLogger("EMBY.context") LOG = logging.getLogger("JELLYFIN.context")
################################################################################################# #################################################################################################

View file

@ -11,11 +11,11 @@ import xbmcaddon
################################################################################################# #################################################################################################
__addon__ = xbmcaddon.Addon(id='plugin.video.emby') __addon__ = xbmcaddon.Addon(id='plugin.video.jellyfin')
__base__ = xbmc.translatePath(os.path.join(__addon__.getAddonInfo('path'), 'resources', 'lib')).decode('utf-8') __base__ = xbmc.translatePath(os.path.join(__addon__.getAddonInfo('path'), 'resources', 'lib')).decode('utf-8')
__libraries__ = xbmc.translatePath(os.path.join(__addon__.getAddonInfo('path'), 'libraries')).decode('utf-8') __libraries__ = xbmc.translatePath(os.path.join(__addon__.getAddonInfo('path'), 'libraries')).decode('utf-8')
__pcache__ = xbmc.translatePath(os.path.join(__addon__.getAddonInfo('profile'), 'emby')).decode('utf-8') __pcache__ = xbmc.translatePath(os.path.join(__addon__.getAddonInfo('profile'), 'jellyfin')).decode('utf-8')
__cache__ = xbmc.translatePath('special://temp/emby').decode('utf-8') __cache__ = xbmc.translatePath('special://temp/jellyfin').decode('utf-8')
sys.path.insert(0, __cache__) sys.path.insert(0, __cache__)
sys.path.insert(0, __pcache__) sys.path.insert(0, __pcache__)
@ -28,7 +28,7 @@ from entrypoint import Events
################################################################################################# #################################################################################################
LOG = logging.getLogger("EMBY.default") LOG = logging.getLogger("JELLYFIN.default")
################################################################################################# #################################################################################################

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.9 KiB

BIN
icon.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 40 KiB

Before After
Before After

View file

@ -1,6 +1,6 @@
# Emby for Kodi language file # Jellyfin for Kodi language file
# Addon Name: Emby for Kodi # Addon Name: Jellyfin for Kodi
# Addon id: plugin.video.emby # Addon id: plugin.video.jellyfin
# Addon Provider: angelblue05 # Addon Provider: angelblue05
# Translators: # Translators:
# Wolfgang Petri <horstepipe@googlemail.com>, 2018 # Wolfgang Petri <horstepipe@googlemail.com>, 2018
@ -9,7 +9,7 @@
# #
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: Emby for Kodi\n" "Project-Id-Version: Jellyfin for Kodi\n"
"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n"
"PO-Revision-Date: 2018-09-07 20:10+0000\n" "PO-Revision-Date: 2018-09-07 20:10+0000\n"
"Last-Translator: Benni <semool@secure-mail.biz>, 2019\n" "Last-Translator: Benni <semool@secure-mail.biz>, 2019\n"
@ -21,8 +21,8 @@ msgstr ""
"Plural-Forms: nplurals=2; plural=(n != 1);\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n"
msgctxt "#29999" msgctxt "#29999"
msgid "Emby for Kodi" msgid "Jellyfin for Kodi"
msgstr "Emby für Kodi" msgstr "Jellyfin für Kodi"
msgctxt "#30000" msgctxt "#30000"
msgid "Server address" msgid "Server address"
@ -193,12 +193,12 @@ msgid "TV Shows"
msgstr "Serien" msgstr "Serien"
msgctxt "#30401" msgctxt "#30401"
msgid "Emby options" msgid "Jellyfin options"
msgstr "Emby Optionen" msgstr "Jellyfin Optionen"
msgctxt "#30402" msgctxt "#30402"
msgid "Emby transcode" msgid "Jellyfin transcode"
msgstr "Emby transkodieren" msgstr "Jellyfin transkodieren"
msgctxt "#30405" msgctxt "#30405"
msgid "Add to favorites" msgid "Add to favorites"
@ -213,8 +213,8 @@ msgid "Settings"
msgstr "Einstellungen" msgstr "Einstellungen"
msgctxt "#30409" msgctxt "#30409"
msgid "Delete from Emby" msgid "Delete from Jellyfin"
msgstr "Vom Emby Server löschen" msgstr "Vom Jellyfin Server löschen"
msgctxt "#30410" msgctxt "#30410"
msgid "Refresh this item" msgid "Refresh this item"
@ -352,10 +352,6 @@ msgctxt "#30547"
msgid "Display message" msgid "Display message"
msgstr "Nachricht anzeigen" msgstr "Nachricht anzeigen"
msgctxt "#30600"
msgid "Sign in with Emby Connect"
msgstr "Mit Emby Connect anmelden"
msgctxt "#30602" msgctxt "#30602"
msgid "Password" msgid "Password"
msgstr "Passwort" msgstr "Passwort"
@ -393,8 +389,8 @@ msgid "Please sign in"
msgstr "Bitte melden Sie sich an" msgstr "Bitte melden Sie sich an"
msgctxt "#30613" msgctxt "#30613"
msgid "Change Emby Connect user" msgid "Change Jellyfin Connect user"
msgstr "Emby Connect Benutzer wechseln" msgstr "Jellyfin Connect Benutzer wechseln"
msgctxt "#30614" msgctxt "#30614"
msgid "Connect to server" msgid "Connect to server"
@ -412,10 +408,6 @@ msgctxt "#30617"
msgid "Server or port cannot be empty" msgid "Server or port cannot be empty"
msgstr "Server oder Port muss eingetragen werden" msgstr "Server oder Port muss eingetragen werden"
msgctxt "#30618"
msgid "Change Emby Connect user"
msgstr "Emby Connect Benutzer wechseln"
msgctxt "#33000" msgctxt "#33000"
msgid "Welcome" msgid "Welcome"
msgstr "Willkommen" msgstr "Willkommen"
@ -437,8 +429,8 @@ msgid "Choose the subtitles stream"
msgstr "Untertitel Spur wählen" msgstr "Untertitel Spur wählen"
msgctxt "#33015" msgctxt "#33015"
msgid "Delete file from Emby?" msgid "Delete file from Jellyfin?"
msgstr "Datei vom Emby Server löschen?" msgstr "Datei vom Jellyfin Server löschen?"
msgctxt "#33016" msgctxt "#33016"
msgid "Play trailers?" msgid "Play trailers?"
@ -454,16 +446,16 @@ msgstr "Rufe ab:"
msgctxt "#33022" msgctxt "#33022"
msgid "" msgid ""
"Detected the database needs to be recreated for this version of Emby for " "Detected the database needs to be recreated for this version of Jellyfin for "
"Kodi. Proceed?" "Kodi. Proceed?"
msgstr "" msgstr ""
"Die Datenbank muss neu erstellt werden für diese 'Emby for Kodi' Version. " "Die Datenbank muss neu erstellt werden für diese 'Jellyfin for Kodi' Version. "
"Fortfahren?" "Fortfahren?"
msgctxt "#33023" msgctxt "#33023"
msgid "Emby for Kodi will not work correctly until the database is reset." msgid "Jellyfin for Kodi will not work correctly until the database is reset."
msgstr "" msgstr ""
"'Emby for Kodi' wird nicht richtig funktionieren ohne einen Datenbank Reset." "'Jellyfin for Kodi' wird nicht richtig funktionieren ohne einen Datenbank Reset."
msgctxt "#33025" msgctxt "#33025"
msgid "Completed in:" msgid "Completed in:"
@ -475,12 +467,12 @@ msgstr "Es wurde eine neue Geräte-ID erstellt und Kodi wird nun neugestartet."
msgctxt "#33035" msgctxt "#33035"
msgid "" msgid ""
"Caution! If you choose Native mode, certain Emby features will be missing, " "Caution! If you choose Native mode, certain Jellyfin features will be missing, "
"such as: Emby cinema mode, direct stream/transcode options and parental " "such as: Jellyfin cinema mode, direct stream/transcode options and parental "
"access schedule." "access schedule."
msgstr "" msgstr ""
"Achtung: Wenn du den nativen Modus wählst, werden einige Emby Funktionen " "Achtung: Wenn du den nativen Modus wählst, werden einige Jellyfin Funktionen "
"fehlen, wie z.B.: Emby Kinomodus, Transkodierungsoptionen und der Zeitplan " "fehlen, wie z.B.: Jellyfin Kinomodus, Transkodierungsoptionen und der Zeitplan "
"für die Kindersicherung." "für die Kindersicherung."
msgctxt "#33036" msgctxt "#33036"
@ -502,11 +494,11 @@ msgstr "Kodi kann die Datei nicht finden:"
msgctxt "#33048" msgctxt "#33048"
msgid "" msgid ""
"You may need to verify your network credentials in the add-on settings or " "You may need to verify your network credentials in the add-on settings or "
"use the Emby path substitution to format your path correctly (Emby dashboard" "use the Jellyfin path substitution to format your path correctly (Jellyfin dashboard"
" > library). Stop syncing?" " > library). Stop syncing?"
msgstr "" msgstr ""
"Du solltest deine Netzwerkzugangsdaten in den Addon Einstellungen überprüfen" "Du solltest deine Netzwerkzugangsdaten in den Addon Einstellungen überprüfen"
" oder die Emby Funktion \"(Optionaler) Gemeinsamer Netzwerkordner\" (Emby " " oder die Jellyfin Funktion \"(Optionaler) Gemeinsamer Netzwerkordner\" (Jellyfin "
"Dashboard > Bibliothek > Verzeichnisse) benutzen. Synchronisierung " "Dashboard > Bibliothek > Verzeichnisse) benutzen. Synchronisierung "
"abbrechen?" "abbrechen?"
@ -551,8 +543,8 @@ msgid "Remove all cached artwork?"
msgstr "Alle zwischengespeicherten Bilder entfernen?" msgstr "Alle zwischengespeicherten Bilder entfernen?"
msgctxt "#33087" msgctxt "#33087"
msgid "Reset all Emby add-on settings?" msgid "Reset all Jellyfin add-on settings?"
msgstr "Alle Emby Addon Einstellungen zurücksetzen?" msgstr "Alle Jellyfin Addon Einstellungen zurücksetzen?"
msgctxt "#33088" msgctxt "#33088"
msgid "" msgid ""
@ -584,10 +576,10 @@ msgstr "Backup Ordner"
msgctxt "#33097" msgctxt "#33097"
msgid "" msgid ""
"Important, cleanonupdate was removed in your advanced settings to prevent " "Important, cleanonupdate was removed in your advanced settings to prevent "
"conflict with Emby for Kodi. Kodi will restart now." "conflict with Jellyfin for Kodi. Kodi will restart now."
msgstr "" msgstr ""
"Wichtig, cleanonupdate wurde aus deinen Advanced Settings enfernt um " "Wichtig, cleanonupdate wurde aus deinen Advanced Settings enfernt um "
"Probleme mit 'Emby for Kodi' zu vermeiden. Kodi wird nun neu gestartet." "Probleme mit 'Jellyfin for Kodi' zu vermeiden. Kodi wird nun neu gestartet."
msgctxt "#33098" msgctxt "#33098"
msgid "Refresh boxsets" msgid "Refresh boxsets"
@ -595,12 +587,12 @@ msgstr "Sammlungen aktualisieren"
msgctxt "#33099" msgctxt "#33099"
msgid "" msgid ""
"Install the server plugin Kodi companion to automatically apply emby library" "Install the server plugin Kodi companion to automatically apply jellyfin library"
" updates at startup. This setting can be found in the add-on settings > sync" " updates at startup. This setting can be found in the add-on settings > sync"
" options > Enable Kodi Companion." " options > Enable Kodi Companion."
msgstr "" msgstr ""
"Installiere auf dem Emby Server das 'Kodi Companion' Plugin um automatische " "Installiere auf dem Jellyfin Server das 'Kodi Companion' Plugin um automatische "
"Updates der Bibliothek zu erhalten. Diese Einstellung findest du unter 'Emby" "Updates der Bibliothek zu erhalten. Diese Einstellung findest du unter 'Jellyfin"
" Addon Einstellungen > Syncronisierung > Aktiviere Kodi Companion'." " Addon Einstellungen > Syncronisierung > Aktiviere Kodi Companion'."
msgctxt "#33100" msgctxt "#33100"
@ -706,12 +698,12 @@ msgstr ""
msgctxt "#33119" msgctxt "#33119"
msgid "" msgid ""
"Something went wrong during the sync. You'll be able to restore progress " "Something went wrong during the sync. You'll be able to restore progress "
"when restarting Kodi. If the problem persists, please report on the Emby for" "when restarting Kodi. If the problem persists, please report on the Jellyfin for"
" Kodi forums, with your Kodi log." " Kodi forums, with your Kodi log."
msgstr "" msgstr ""
"Es gab einen Fehler bei der Synchronisierung. Du kannst den Fortschritt " "Es gab einen Fehler bei der Synchronisierung. Du kannst den Fortschritt "
"wiederherstellen, wenn du Kodi neu startest. Sollte das Problem weiterhin " "wiederherstellen, wenn du Kodi neu startest. Sollte das Problem weiterhin "
"bestehen, melde es bitte mit deiner Kodi Logdatei im \"Emby for Kodi " "bestehen, melde es bitte mit deiner Kodi Logdatei im \"Jellyfin for Kodi "
"Forum\"." "Forum\"."
msgctxt "#33120" msgctxt "#33120"
@ -736,10 +728,10 @@ msgstr "Schließe Personen mit ein (langsam)"
msgctxt "#33125" msgctxt "#33125"
msgid "" msgid ""
"Choose the Emby views to sync to Kodi. You can optionally sync libraries at " "Choose the Jellyfin views to sync to Kodi. You can optionally sync libraries at "
"a later time." "a later time."
msgstr "" msgstr ""
"Wähle die Emby Datenbanken, welche synchronisiert werden sollen. Optional " "Wähle die Jellyfin Datenbanken, welche synchronisiert werden sollen. Optional "
"können diese auch nachträglich synchronisiert werden." "können diese auch nachträglich synchronisiert werden."
msgctxt "#33126" msgctxt "#33126"
@ -754,17 +746,17 @@ msgctxt "#33128"
msgid "" msgid ""
"Failed to retrieve latest content updates. No content updates will be " "Failed to retrieve latest content updates. No content updates will be "
"applied until Kodi is restarted. If this issue persists, please report on " "applied until Kodi is restarted. If this issue persists, please report on "
"the Emby for Kodi forums, with your Kodi log." "the Jellyfin for Kodi forums, with your Kodi log."
msgstr "" msgstr ""
"Fehler beim Empfang der letzten Inhaltsänderungen. Es werden keine " "Fehler beim Empfang der letzten Inhaltsänderungen. Es werden keine "
"Inhaltsänderungen angewendet ehe Kodi neu gestartet wird. Sollte das Problem" "Inhaltsänderungen angewendet ehe Kodi neu gestartet wird. Sollte das Problem"
" weiterhin bestehen, melde es bitte mit deiner Kodi Logdatei im \"Emby for " " weiterhin bestehen, melde es bitte mit deiner Kodi Logdatei im \"Jellyfin for "
"Kodi Forum\"." "Kodi Forum\"."
msgctxt "#33129" msgctxt "#33129"
msgid "You can sync libraries by launching the Emby add-on > Add libraries." msgid "You can sync libraries by launching the Jellyfin add-on > Add libraries."
msgstr "" msgstr ""
"Du kannst die Bibliothek syncronisieren über 'Emby Addon > Bibliothek " "Du kannst die Bibliothek syncronisieren über 'Jellyfin Addon > Bibliothek "
"hinzufügen." "hinzufügen."
msgctxt "#33130" msgctxt "#33130"
@ -838,22 +830,22 @@ msgstr "Datenbank entfernen"
msgctxt "#33145" msgctxt "#33145"
msgid "" msgid ""
"Please make sure your Samba (smb) share of your Emby server is accessible to" "Please make sure your Samba (smb) share of your Jellyfin server is accessible to"
" your Kodi installation and that you have path substitution configured on " " your Kodi installation and that you have path substitution configured on "
"your server. Otherwise, Kodi may fail to locate your files." "your server. Otherwise, Kodi may fail to locate your files."
msgstr "" msgstr ""
"Bitte stell sicher das deine Samba Freigabe (smb) auf deinem Emby Server für" "Bitte stell sicher das deine Samba Freigabe (smb) auf deinem Jellyfin Server für"
" Kodi zugänglich ist und das '(Optionaler) Gemeinsamer Netzwerkordner' auf " " Kodi zugänglich ist und das '(Optionaler) Gemeinsamer Netzwerkordner' auf "
"dem Emby Server korrekt eingestellt ist. Ansonsten kann Kodi die Dateien " "dem Jellyfin Server korrekt eingestellt ist. Ansonsten kann Kodi die Dateien "
"nicht finden." "nicht finden."
msgctxt "#33146" msgctxt "#33146"
msgid "Unable to connect to Emby." msgid "Unable to connect to Jellyfin."
msgstr "Verbindung zu Emby fehlgeschlagen." msgstr "Verbindung zu Jellyfin fehlgeschlagen."
msgctxt "#33147" msgctxt "#33147"
msgid "Your access to Emby is restricted." msgid "Your access to Jellyfin is restricted."
msgstr "Dein Zugang zu Emby ist eingeschränkt." msgstr "Dein Zugang zu Jellyfin ist eingeschränkt."
msgctxt "#33148" msgctxt "#33148"
msgid "Your access to this server is restricted." msgid "Your access to this server is restricted."
@ -882,8 +874,8 @@ msgid "Unable to locate TV Tunes in Kodi."
msgstr "TV Tunes Addon nicht gefunden" msgstr "TV Tunes Addon nicht gefunden"
msgctxt "#33153" msgctxt "#33153"
msgid "Your Emby theme media has been synced to Kodi" msgid "Your Jellyfin theme media has been synced to Kodi"
msgstr "Deine Emby Media Themes wurden synchronisiert" msgstr "Deine Jellyfin Media Themes wurden synchronisiert"
msgctxt "#33154" msgctxt "#33154"
msgid "Add libraries" msgid "Add libraries"
@ -891,11 +883,11 @@ msgstr "Bibliothek hinzufügen"
msgctxt "#33155" msgctxt "#33155"
msgid "" msgid ""
"The currently applied patch for Emby for Kodi is corrupted! Please post to " "The currently applied patch for Jellyfin for Kodi is corrupted! Please post to "
"the Emby for Kodi forums if this issue persists. This will need to be fixed " "the Jellyfin for Kodi forums if this issue persists. This will need to be fixed "
"as soon as possible." "as soon as possible."
msgstr "" msgstr ""
"Der aktuell angewendete Patch ist fehlerhaft! Bitte melde dich im 'Emby for " "Der aktuell angewendete Patch ist fehlerhaft! Bitte melde dich im 'Jellyfin for "
"Kodi' Forum wenn der Fehler wiederholt auftritt. Der Fehler sollte so " "Kodi' Forum wenn der Fehler wiederholt auftritt. Der Fehler sollte so "
"schnell wie möglich behoben werden." "schnell wie möglich behoben werden."
@ -916,21 +908,13 @@ msgid "Enable audio/subtitles selection"
msgstr "Audio/Untertitel Auswahl aktivieren" msgstr "Audio/Untertitel Auswahl aktivieren"
msgctxt "#33160" msgctxt "#33160"
msgid "To avoid errors, please update Emby for Kodi to version: " msgid "To avoid errors, please update Jellyfin for Kodi to version: "
msgstr "Um Fehler zu vermeiden update bitte 'Emby for Kodi' zur Version:" msgstr "Um Fehler zu vermeiden update bitte 'Jellyfin for Kodi' zur Version:"
msgctxt "#33161"
msgid "Check for updates"
msgstr "Nach Updates suchen"
msgctxt "#33162" msgctxt "#33162"
msgid "Reset the music library?" msgid "Reset the music library?"
msgstr "Musik Datenbank zurücksetzen?" msgstr "Musik Datenbank zurücksetzen?"
msgctxt "#33163"
msgid "Support this project"
msgstr "Unterstütze dieses Projekt"
msgctxt "#33164" msgctxt "#33164"
msgid "Mask sensitive information in log (does not apply to kodi logging)" msgid "Mask sensitive information in log (does not apply to kodi logging)"
msgstr "" msgstr ""
@ -969,10 +953,10 @@ msgctxt "#33172"
msgid "" msgid ""
"You have {number} updates pending. This may take a little while before " "You have {number} updates pending. This may take a little while before "
"seeing new content. It might be faster to update your libraries via " "seeing new content. It might be faster to update your libraries via "
"launching the Emby add-on > update libraries. Proceed anyway?" "launching the Jellyfin add-on > update libraries. Proceed anyway?"
msgstr "" msgstr ""
"Es stehen {number} Updates an. Es kann eine Weile dauern ehe neue Inhalte " "Es stehen {number} Updates an. Es kann eine Weile dauern ehe neue Inhalte "
"angezeigt werden. Es könnte schneller gehen die Datenbank über 'Emby Addon >" "angezeigt werden. Es könnte schneller gehen die Datenbank über 'Jellyfin Addon >"
" Datenbank aktualisieren' auf den neuesten Stand zu bringen. Trotzdem " " Datenbank aktualisieren' auf den neuesten Stand zu bringen. Trotzdem "
"fortfahren? " "fortfahren? "
@ -986,7 +970,7 @@ msgstr "Parallele Downloads (Standard: 3)"
msgctxt "#33175" msgctxt "#33175"
msgid "" msgid ""
"Paging tip: Each download thread requests your max items value from Emby at " "Paging tip: Each download thread requests your max items value from Jellyfin at "
"the same time." "the same time."
msgstr "" msgstr ""
"Tip: Jeder Download Vorgang nutzt jeweils die eingestellte 'Maximal parallel" "Tip: Jeder Download Vorgang nutzt jeweils die eingestellte 'Maximal parallel"
@ -1012,8 +996,8 @@ msgid "Force transcode"
msgstr "Transkodierung erzwingen" msgstr "Transkodierung erzwingen"
msgctxt "#33180" msgctxt "#33180"
msgid "Restart Emby for Kodi" msgid "Restart Jellyfin for Kodi"
msgstr "'Emby for Kodi' neustarten" msgstr "'Jellyfin for Kodi' neustarten"
msgctxt "#33181" msgctxt "#33181"
msgid "Restarting to apply the patch" msgid "Restarting to apply the patch"
@ -1066,12 +1050,12 @@ msgid "Enable Kodi database discovery"
msgstr "'Kodi Database discovery' aktivieren?" msgstr "'Kodi Database discovery' aktivieren?"
msgctxt "#33191" msgctxt "#33191"
msgid "Restart Emby for Kodi to apply this change?" msgid "Restart Jellyfin for Kodi to apply this change?"
msgstr "'Emby for Kodi' Neustarten zum anwenden der Änderung?" msgstr "'Jellyfin for Kodi' Neustarten zum anwenden der Änderung?"
msgctxt "#33192" msgctxt "#33192"
msgid "Restart Emby for Kodi" msgid "Restart Jellyfin for Kodi"
msgstr "'Emby for Kodi' neustarten" msgstr "'Jellyfin for Kodi' neustarten"
msgctxt "#33193" msgctxt "#33193"
msgid "Restarting..." msgid "Restarting..."

View file

@ -1,10 +1,10 @@
# Emby for Kodi language file # Jellyfin for Kodi language file
# Addon Name: Emby for Kodi # Addon Name: Jellyfin for Kodi
# Addon id: plugin.video.emby # Addon id: plugin.video.jellyfin
# Addon Provider: angelblue05 # Addon Provider: angelblue05
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: Emby for Kodi\n" "Project-Id-Version: Jellyfin for Kodi\n"
"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Language-Team: \n" "Language-Team: \n"
@ -15,7 +15,7 @@ msgstr ""
"Plural-Forms: nplurals=2; plural=(n != 1);\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n"
msgctxt "#29999" msgctxt "#29999"
msgid "Emby for Kodi" msgid "Jellyfin for Kodi"
msgstr "" msgstr ""
msgctxt "#30000" msgctxt "#30000"
@ -187,11 +187,11 @@ msgid "TV Shows"
msgstr "" msgstr ""
msgctxt "#30401" msgctxt "#30401"
msgid "Emby options" msgid "Jellyfin options"
msgstr "" msgstr ""
msgctxt "#30402" msgctxt "#30402"
msgid "Emby transcode" msgid "Jellyfin transcode"
msgstr "" msgstr ""
msgctxt "#30405" msgctxt "#30405"
@ -207,7 +207,7 @@ msgid "Settings"
msgstr "" msgstr ""
msgctxt "#30409" msgctxt "#30409"
msgid "Delete from Emby" msgid "Delete from Jellyfin"
msgstr "" msgstr ""
msgctxt "#30410" msgctxt "#30410"
@ -346,10 +346,6 @@ msgctxt "#30547"
msgid "Display message" msgid "Display message"
msgstr "" msgstr ""
msgctxt "#30600"
msgid "Sign in with Emby Connect"
msgstr ""
msgctxt "#30602" msgctxt "#30602"
msgid "Password" msgid "Password"
msgstr "" msgstr ""
@ -387,7 +383,7 @@ msgid "Please sign in"
msgstr "" msgstr ""
msgctxt "#30613" msgctxt "#30613"
msgid "Change Emby Connect user" msgid "Change Jellyfin Connect user"
msgstr "" msgstr ""
msgctxt "#30614" msgctxt "#30614"
@ -406,10 +402,6 @@ msgctxt "#30617"
msgid "Server or port cannot be empty" msgid "Server or port cannot be empty"
msgstr "" msgstr ""
msgctxt "#30618"
msgid "Change Emby Connect user"
msgstr ""
msgctxt "#33000" msgctxt "#33000"
msgid "Welcome" msgid "Welcome"
msgstr "" msgstr ""
@ -431,7 +423,7 @@ msgid "Choose the subtitles stream"
msgstr "" msgstr ""
msgctxt "#33015" msgctxt "#33015"
msgid "Delete file from Emby?" msgid "Delete file from Jellyfin?"
msgstr "" msgstr ""
msgctxt "#33016" msgctxt "#33016"
@ -447,11 +439,11 @@ msgid "Gathering:"
msgstr "" msgstr ""
msgctxt "#33022" msgctxt "#33022"
msgid "Detected the database needs to be recreated for this version of Emby for Kodi. Proceed?" msgid "Detected the database needs to be recreated for this version of Jellyfin for Kodi. Proceed?"
msgstr "" msgstr ""
msgctxt "#33023" msgctxt "#33023"
msgid "Emby for Kodi will not work correctly until the database is reset." msgid "Jellyfin for Kodi will not work correctly until the database is reset."
msgstr "" msgstr ""
msgctxt "#33025" msgctxt "#33025"
@ -463,7 +455,7 @@ msgid "A new device Id has been generated. Kodi will now restart."
msgstr "" msgstr ""
msgctxt "#33035" msgctxt "#33035"
msgid "Caution! If you choose Native mode, certain Emby features will be missing, such as: Emby cinema mode, direct stream/transcode options and parental access schedule." msgid "Caution! If you choose Native mode, certain Jellyfin features will be missing, such as: Jellyfin cinema mode, direct stream/transcode options and parental access schedule."
msgstr "" msgstr ""
msgctxt "#33036" msgctxt "#33036"
@ -483,7 +475,7 @@ msgid "Kodi can't locate file:"
msgstr "" msgstr ""
msgctxt "#33048" msgctxt "#33048"
msgid "You may need to verify your network credentials in the add-on settings or use the Emby path substitution to format your path correctly (Emby dashboard > library). Stop syncing?" msgid "You may need to verify your network credentials in the add-on settings or use the Jellyfin path substitution to format your path correctly (Jellyfin dashboard > library). Stop syncing?"
msgstr "" msgstr ""
msgctxt "#33049" msgctxt "#33049"
@ -527,7 +519,7 @@ msgid "Remove all cached artwork?"
msgstr "" msgstr ""
msgctxt "#33087" msgctxt "#33087"
msgid "Reset all Emby add-on settings?" msgid "Reset all Jellyfin add-on settings?"
msgstr "" msgstr ""
msgctxt "#33088" msgctxt "#33088"
@ -555,7 +547,7 @@ msgid "Backup folder"
msgstr "" msgstr ""
msgctxt "#33097" msgctxt "#33097"
msgid "Important, cleanonupdate was removed in your advanced settings to prevent conflict with Emby for Kodi. Kodi will restart now." msgid "Important, cleanonupdate was removed in your advanced settings to prevent conflict with Jellyfin for Kodi. Kodi will restart now."
msgstr "" msgstr ""
msgctxt "#33098" msgctxt "#33098"
@ -563,7 +555,7 @@ msgid "Refresh boxsets"
msgstr "" msgstr ""
msgctxt "#33099" msgctxt "#33099"
msgid "Install the server plugin Kodi companion to automatically apply emby library updates at startup. This setting can be found in the add-on settings > sync options > Enable Kodi Companion." msgid "Install the server plugin Kodi companion to automatically apply Jellyfin library updates at startup. This setting can be found in the add-on settings > sync options > Enable Kodi Companion."
msgstr "" msgstr ""
msgctxt "#33100" msgctxt "#33100"
@ -643,7 +635,7 @@ msgid "You've change the playback mode. Kodi needs to be reset to apply the chan
msgstr "" msgstr ""
msgctxt "#33119" msgctxt "#33119"
msgid "Something went wrong during the sync. You'll be able to restore progress when restarting Kodi. If the problem persists, please report on the Emby for Kodi forums, with your Kodi log." msgid "Something went wrong during the sync. You'll be able to restore progress when restarting Kodi. If the problem persists, please report on the Jellyfin for Kodi forums, with your Kodi log."
msgstr "" msgstr ""
msgctxt "#33120" msgctxt "#33120"
@ -667,7 +659,7 @@ msgid "Include people (slow)"
msgstr "" msgstr ""
msgctxt "#33125" msgctxt "#33125"
msgid "Choose the Emby views to sync to Kodi. You can optionally sync libraries at a later time." msgid "Choose the Jellyfin views to sync to Kodi. You can optionally sync libraries at a later time."
msgstr "" msgstr ""
msgctxt "#33126" msgctxt "#33126"
@ -679,11 +671,11 @@ msgid "Proceed"
msgstr "" msgstr ""
msgctxt "#33128" msgctxt "#33128"
msgid "Failed to retrieve latest content updates. No content updates will be applied until Kodi is restarted. If this issue persists, please report on the Emby for Kodi forums, with your Kodi log." msgid "Failed to retrieve latest content updates. No content updates will be applied until Kodi is restarted. If this issue persists, please report on the Jellyfin for Kodi forums, with your Kodi log."
msgstr "" msgstr ""
msgctxt "#33129" msgctxt "#33129"
msgid "You can sync libraries by launching the Emby add-on > Add libraries." msgid "You can sync libraries by launching the Jellyfin add-on > Add libraries."
msgstr "" msgstr ""
msgctxt "#33130" msgctxt "#33130"
@ -747,15 +739,15 @@ msgid "Removing library"
msgstr "" msgstr ""
msgctxt "#33145" msgctxt "#33145"
msgid "Please make sure your Samba (smb) share of your Emby server is accessible to your Kodi installation and that you have path substitution configured on your server. Otherwise, Kodi may fail to locate your files." msgid "Please make sure your Samba (smb) share of your Jellyfin server is accessible to your Kodi installation and that you have path substitution configured on your server. Otherwise, Kodi may fail to locate your files."
msgstr "" msgstr ""
msgctxt "#33146" msgctxt "#33146"
msgid "Unable to connect to Emby." msgid "Unable to connect to Jellyfin."
msgstr "" msgstr ""
msgctxt "#33147" msgctxt "#33147"
msgid "Your access to Emby is restricted." msgid "Your access to Jellyfin is restricted."
msgstr "" msgstr ""
msgctxt "#33148" msgctxt "#33148"
@ -779,7 +771,7 @@ msgid "Unable to locate TV Tunes in Kodi."
msgstr "" msgstr ""
msgctxt "#33153" msgctxt "#33153"
msgid "Your Emby theme media has been synced to Kodi" msgid "Your Jellyfin theme media has been synced to Kodi"
msgstr "" msgstr ""
msgctxt "#33154" msgctxt "#33154"
@ -787,7 +779,7 @@ msgid "Add libraries"
msgstr "" msgstr ""
msgctxt "#33155" msgctxt "#33155"
msgid "The currently applied patch for Emby for Kodi is corrupted! Please post to the Emby for Kodi forums if this issue persists. This will need to be fixed as soon as possible." msgid "The currently applied patch for Jellyfin for Kodi is corrupted! Please post to the Jellyfin for Kodi forums if this issue persists. This will need to be fixed as soon as possible."
msgstr "" msgstr ""
msgctxt "#33156" msgctxt "#33156"
@ -807,21 +799,13 @@ msgid "Enable audio/subtitles selection"
msgstr "" msgstr ""
msgctxt "#33160" msgctxt "#33160"
msgid "To avoid errors, please update Emby for Kodi to version: " msgid "To avoid errors, please update Jellyfin for Kodi to version: "
msgstr ""
msgctxt "#33161"
msgid "Check for updates"
msgstr "" msgstr ""
msgctxt "#33162" msgctxt "#33162"
msgid "Reset the music library?" msgid "Reset the music library?"
msgstr "" msgstr ""
msgctxt "#33163"
msgid "Support this project"
msgstr ""
msgctxt "#33164" msgctxt "#33164"
msgid "Mask sensitive information in log (does not apply to kodi logging)" msgid "Mask sensitive information in log (does not apply to kodi logging)"
msgstr "" msgstr ""
@ -855,7 +839,7 @@ msgid "By first letter"
msgstr "" msgstr ""
msgctxt "#33172" msgctxt "#33172"
msgid "You have {number} updates pending. This may take a little while before seeing new content. It might be faster to update your libraries via launching the Emby add-on > update libraries. Proceed anyway?" msgid "You have {number} updates pending. This may take a little while before seeing new content. It might be faster to update your libraries via launching the Jellyfin add-on > update libraries. Proceed anyway?"
msgstr "" msgstr ""
msgctxt "#33173" msgctxt "#33173"
@ -867,7 +851,7 @@ msgid "Paging - download threads (default: 3)"
msgstr "" msgstr ""
msgctxt "#33175" msgctxt "#33175"
msgid "Paging tip: Each download thread requests your max items value from Emby at the same time." msgid "Paging tip: Each download thread requests your max items value from Jellyfin at the same time."
msgstr "" msgstr ""
msgctxt "#33176" msgctxt "#33176"
@ -887,7 +871,7 @@ msgid "Force transcode"
msgstr "" msgstr ""
msgctxt "#33180" msgctxt "#33180"
msgid "Restart Emby for Kodi" msgid "Restart Jellyfin for Kodi"
msgstr "" msgstr ""
msgctxt "#33181" msgctxt "#33181"
@ -923,11 +907,11 @@ msgid "Would you like to sync Rotten Tomatoes ratings?"
msgstr "" msgstr ""
msgctxt "#33191" msgctxt "#33191"
msgid "Restart Emby for Kodi to apply this change?" msgid "Restart Jellyfin for Kodi to apply this change?"
msgstr "" msgstr ""
msgctxt "#33192" msgctxt "#33192"
msgid "Restart Emby for Kodi" msgid "Restart Jellyfin for Kodi"
msgstr "" msgstr ""
msgctxt "#33193" msgctxt "#33193"
@ -939,7 +923,7 @@ msgid "Manage libraries"
msgstr "" msgstr ""
msgctxt "#33195" msgctxt "#33195"
msgid "Enable Emby for Kodi" msgid "Enable Jellyfin for Kodi"
msgstr "" msgstr ""
msgctxt "#33196" msgctxt "#33196"

View file

@ -1,13 +1,13 @@
# Emby for Kodi language file # Jellyfin for Kodi language file
# Addon Name: Emby for Kodi # Addon Name: Jellyfin for Kodi
# Addon id: plugin.video.emby # Addon id: plugin.video.jellyfin
# Addon Provider: angelblue05 # Addon Provider: angelblue05
# Translators: # Translators:
# Jean Fontaine <balayop@yahoo.fr>, 2018 # Jean Fontaine <balayop@yahoo.fr>, 2018
# #
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: Emby for Kodi\n" "Project-Id-Version: Jellyfin for Kodi\n"
"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n"
"PO-Revision-Date: 2018-09-07 20:10+0000\n" "PO-Revision-Date: 2018-09-07 20:10+0000\n"
"Last-Translator: Jean Fontaine <balayop@yahoo.fr>, 2018\n" "Last-Translator: Jean Fontaine <balayop@yahoo.fr>, 2018\n"
@ -19,8 +19,8 @@ msgstr ""
"Plural-Forms: nplurals=2; plural=(n > 1);\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n"
msgctxt "#29999" msgctxt "#29999"
msgid "Emby for Kodi" msgid "Jellyfin for Kodi"
msgstr "Emby pour Kodi" msgstr "Jellyfin pour Kodi"
msgctxt "#30000" msgctxt "#30000"
msgid "Server address" msgid "Server address"
@ -191,12 +191,12 @@ msgid "TV Shows"
msgstr "Séries TV" msgstr "Séries TV"
msgctxt "#30401" msgctxt "#30401"
msgid "Emby options" msgid "Jellyfin options"
msgstr "Options Emby" msgstr "Options Jellyfin"
msgctxt "#30402" msgctxt "#30402"
msgid "Emby transcode" msgid "Jellyfin transcode"
msgstr "Emby transcodage" msgstr "Jellyfin transcodage"
msgctxt "#30405" msgctxt "#30405"
msgid "Add to favorites" msgid "Add to favorites"
@ -211,8 +211,8 @@ msgid "Settings"
msgstr "Paramètres" msgstr "Paramètres"
msgctxt "#30409" msgctxt "#30409"
msgid "Delete from Emby" msgid "Delete from Jellyfin"
msgstr "Supprimer d'Emby" msgstr "Supprimer d'Jellyfin"
msgctxt "#30410" msgctxt "#30410"
msgid "Refresh this item" msgid "Refresh this item"
@ -351,10 +351,6 @@ msgctxt "#30547"
msgid "Display message" msgid "Display message"
msgstr "Afficher le message" msgstr "Afficher le message"
msgctxt "#30600"
msgid "Sign in with Emby Connect"
msgstr "S'identifier avec Emby Connect"
msgctxt "#30602" msgctxt "#30602"
msgid "Password" msgid "Password"
msgstr "Mot de passe" msgstr "Mot de passe"
@ -392,8 +388,8 @@ msgid "Please sign in"
msgstr "Veuillez vous identifier" msgstr "Veuillez vous identifier"
msgctxt "#30613" msgctxt "#30613"
msgid "Change Emby Connect user" msgid "Change Jellyfin Connect user"
msgstr "Changer d'utilisateur Emby Connect" msgstr "Changer d'utilisateur Jellyfin Connect"
msgctxt "#30614" msgctxt "#30614"
msgid "Connect to server" msgid "Connect to server"
@ -411,10 +407,6 @@ msgctxt "#30617"
msgid "Server or port cannot be empty" msgid "Server or port cannot be empty"
msgstr "Le serveur ou le port ne peuvent pas être vides" msgstr "Le serveur ou le port ne peuvent pas être vides"
msgctxt "#30618"
msgid "Change Emby Connect user"
msgstr "Changer d'utilisateur Emby Connect"
msgctxt "#33000" msgctxt "#33000"
msgid "Welcome" msgid "Welcome"
msgstr "Bienvenue" msgstr "Bienvenue"
@ -436,8 +428,8 @@ msgid "Choose the subtitles stream"
msgstr "Choisissez le flux de sous-titres" msgstr "Choisissez le flux de sous-titres"
msgctxt "#33015" msgctxt "#33015"
msgid "Delete file from Emby?" msgid "Delete file from Jellyfin?"
msgstr "Supprimer le fichier depuis Emby ?" msgstr "Supprimer le fichier depuis Jellyfin ?"
msgctxt "#33016" msgctxt "#33016"
msgid "Play trailers?" msgid "Play trailers?"
@ -453,14 +445,14 @@ msgstr "Rassemblage:"
msgctxt "#33022" msgctxt "#33022"
msgid "" msgid ""
"Detected the database needs to be recreated for this version of Emby for " "Detected the database needs to be recreated for this version of Jellyfin for "
"Kodi. Proceed?" "Kodi. Proceed?"
msgstr "" msgstr ""
"La base de données doit être recréée pour cette version d'Emby pour Kodi. " "La base de données doit être recréée pour cette version d'Jellyfin pour Kodi. "
"Continuer ?" "Continuer ?"
msgctxt "#33023" msgctxt "#33023"
msgid "Emby for Kodi will not work correctly until the database is reset." msgid "Jellyfin for Kodi will not work correctly until the database is reset."
msgstr "" msgstr ""
msgctxt "#33025" msgctxt "#33025"
@ -474,12 +466,12 @@ msgstr ""
msgctxt "#33035" msgctxt "#33035"
msgid "" msgid ""
"Caution! If you choose Native mode, certain Emby features will be missing, " "Caution! If you choose Native mode, certain Jellyfin features will be missing, "
"such as: Emby cinema mode, direct stream/transcode options and parental " "such as: Jellyfin cinema mode, direct stream/transcode options and parental "
"access schedule." "access schedule."
msgstr "" msgstr ""
"Attention ! Si vous choisissez le mode natif, certaines fonctions Emby " "Attention ! Si vous choisissez le mode natif, certaines fonctions Jellyfin "
"seront manquantes, telles que : le mode cinéma d'Emby, les options de flux " "seront manquantes, telles que : le mode cinéma d'Jellyfin, les options de flux "
"direct/transcodage et la planification de l'accès parental." "direct/transcodage et la planification de l'accès parental."
msgctxt "#33036" msgctxt "#33036"
@ -501,12 +493,12 @@ msgstr "Kodi ne peut pas localiser le fichier :"
msgctxt "#33048" msgctxt "#33048"
msgid "" msgid ""
"You may need to verify your network credentials in the add-on settings or " "You may need to verify your network credentials in the add-on settings or "
"use the Emby path substitution to format your path correctly (Emby dashboard" "use the Jellyfin path substitution to format your path correctly (Jellyfin dashboard"
" > library). Stop syncing?" " > library). Stop syncing?"
msgstr "" msgstr ""
"Vous devez peut-être vérifier vos identifiants réseau dans les paramètres de" "Vous devez peut-être vérifier vos identifiants réseau dans les paramètres de"
" l'extension ou utiliser la substitution de chemin Emby pour formater " " l'extension ou utiliser la substitution de chemin Jellyfin pour formater "
"correctement votre chemin (tableau de bord Emby > bibliothèque). Arrêter de " "correctement votre chemin (tableau de bord Jellyfin > bibliothèque). Arrêter de "
"synchroniser ?" "synchroniser ?"
msgctxt "#33049" msgctxt "#33049"
@ -551,8 +543,8 @@ msgid "Remove all cached artwork?"
msgstr "Supprimer toutes les illustrations en cache ?" msgstr "Supprimer toutes les illustrations en cache ?"
msgctxt "#33087" msgctxt "#33087"
msgid "Reset all Emby add-on settings?" msgid "Reset all Jellyfin add-on settings?"
msgstr "Réinitialiser tous les paramètres de l'extension Emby ?" msgstr "Réinitialiser tous les paramètres de l'extension Jellyfin ?"
msgctxt "#33088" msgctxt "#33088"
msgid "" msgid ""
@ -584,10 +576,10 @@ msgstr "Dossier de sauvegarde"
msgctxt "#33097" msgctxt "#33097"
msgid "" msgid ""
"Important, cleanonupdate was removed in your advanced settings to prevent " "Important, cleanonupdate was removed in your advanced settings to prevent "
"conflict with Emby for Kodi. Kodi will restart now." "conflict with Jellyfin for Kodi. Kodi will restart now."
msgstr "" msgstr ""
"Important, cleanonupdate a été supprimé dans vos paramètres avancés pour " "Important, cleanonupdate a été supprimé dans vos paramètres avancés pour "
"éviter tout conflit avec Emby pour Kodi. Kodi va redémarrer maintenant." "éviter tout conflit avec Jellyfin pour Kodi. Kodi va redémarrer maintenant."
msgctxt "#33098" msgctxt "#33098"
msgid "Refresh boxsets" msgid "Refresh boxsets"
@ -595,12 +587,12 @@ msgstr "Rafraîchir les sagas"
msgctxt "#33099" msgctxt "#33099"
msgid "" msgid ""
"Install the server plugin Kodi companion to automatically apply emby library" "Install the server plugin Kodi companion to automatically apply Jellyfin library"
" updates at startup. This setting can be found in the add-on settings > sync" " updates at startup. This setting can be found in the add-on settings > sync"
" options > Enable Kodi Companion." " options > Enable Kodi Companion."
msgstr "" msgstr ""
"Installez le plugin serveur Kodi companion pour appliquer automatiquement " "Installez le plugin serveur Kodi companion pour appliquer automatiquement "
"les mises à jour de la bibliothèque emby au démarrage. Ce paramètre se " "les mises à jour de la bibliothèque Jellyfin au démarrage. Ce paramètre se "
"trouve dans les paramètres complémentaires > options de synchronisation > " "trouve dans les paramètres complémentaires > options de synchronisation > "
"Activer Kodi Companion." "Activer Kodi Companion."
@ -707,12 +699,12 @@ msgstr ""
msgctxt "#33119" msgctxt "#33119"
msgid "" msgid ""
"Something went wrong during the sync. You'll be able to restore progress " "Something went wrong during the sync. You'll be able to restore progress "
"when restarting Kodi. If the problem persists, please report on the Emby for" "when restarting Kodi. If the problem persists, please report on the Jellyfin for"
" Kodi forums, with your Kodi log." " Kodi forums, with your Kodi log."
msgstr "" msgstr ""
"Quelque chose s'est mal passé pendant la synchronisation. Vous pourrez " "Quelque chose s'est mal passé pendant la synchronisation. Vous pourrez "
"restaurer la progression au redémarrage de Kodi. Si le problème persiste, " "restaurer la progression au redémarrage de Kodi. Si le problème persiste, "
"merci de nous le signaler sur les forums Emby pour Kodi, avec votre journal " "merci de nous le signaler sur les forums Jellyfin pour Kodi, avec votre journal "
"Kodi." "Kodi."
msgctxt "#33120" msgctxt "#33120"
@ -737,10 +729,10 @@ msgstr "Inclure les individus (lent)"
msgctxt "#33125" msgctxt "#33125"
msgid "" msgid ""
"Choose the Emby views to sync to Kodi. You can optionally sync libraries at " "Choose the Jellyfin views to sync to Kodi. You can optionally sync libraries at "
"a later time." "a later time."
msgstr "" msgstr ""
"Choisir les vues Emby à synchroniser avec Kodi. Vous pouvez éventuellement " "Choisir les vues Jellyfin à synchroniser avec Kodi. Vous pouvez éventuellement "
"synchroniser les médiathèques ultérieurement." "synchroniser les médiathèques ultérieurement."
msgctxt "#33126" msgctxt "#33126"
@ -755,17 +747,17 @@ msgctxt "#33128"
msgid "" msgid ""
"Failed to retrieve latest content updates. No content updates will be " "Failed to retrieve latest content updates. No content updates will be "
"applied until Kodi is restarted. If this issue persists, please report on " "applied until Kodi is restarted. If this issue persists, please report on "
"the Emby for Kodi forums, with your Kodi log." "the Jellyfin for Kodi forums, with your Kodi log."
msgstr "" msgstr ""
"Impossible de récupérer les dernières mises à jour du contenu. Aucune mise à" "Impossible de récupérer les dernières mises à jour du contenu. Aucune mise à"
" jour du contenu ne sera appliquée tant que Kodi n'aura pas redémarré. Si ce" " jour du contenu ne sera appliquée tant que Kodi n'aura pas redémarré. Si ce"
" problème persiste, merci de le signaler sur les forums Emby pour Kodi, avec" " problème persiste, merci de le signaler sur les forums Jellyfin pour Kodi, avec"
" votre journal Kodi." " votre journal Kodi."
msgctxt "#33129" msgctxt "#33129"
msgid "You can sync libraries by launching the Emby add-on > Add libraries." msgid "You can sync libraries by launching the Jellyfin add-on > Add libraries."
msgstr "" msgstr ""
"Vous pouvez synchroniser les médiathèques en lançant l'add-on Emby > Ajouter" "Vous pouvez synchroniser les médiathèques en lançant l'add-on Jellyfin > Ajouter"
" des médiathèques." " des médiathèques."
msgctxt "#33130" msgctxt "#33130"
@ -839,22 +831,22 @@ msgstr "Suppression de la médiathèque"
msgctxt "#33145" msgctxt "#33145"
msgid "" msgid ""
"Please make sure your Samba (smb) share of your Emby server is accessible to" "Please make sure your Samba (smb) share of your Jellyfin server is accessible to"
" your Kodi installation and that you have path substitution configured on " " your Kodi installation and that you have path substitution configured on "
"your server. Otherwise, Kodi may fail to locate your files." "your server. Otherwise, Kodi may fail to locate your files."
msgstr "" msgstr ""
"Veuillez vous assurer que le partage Samba (smb) de votre serveur Emby est " "Veuillez vous assurer que le partage Samba (smb) de votre serveur Jellyfin est "
"accessible à votre installation Kodi et que vous avez configuré la " "accessible à votre installation Kodi et que vous avez configuré la "
"substitution de chemin sur votre serveur. Sinon, Kodi pourrait ne pas " "substitution de chemin sur votre serveur. Sinon, Kodi pourrait ne pas "
"localiser vos fichiers." "localiser vos fichiers."
msgctxt "#33146" msgctxt "#33146"
msgid "Unable to connect to Emby." msgid "Unable to connect to Jellyfin."
msgstr "Impossible de se connecter à Emby." msgstr "Impossible de se connecter à Jellyfin."
msgctxt "#33147" msgctxt "#33147"
msgid "Your access to Emby is restricted." msgid "Your access to Jellyfin is restricted."
msgstr "Votre accès à Emby est limité." msgstr "Votre accès à Jellyfin est limité."
msgctxt "#33148" msgctxt "#33148"
msgid "Your access to this server is restricted." msgid "Your access to this server is restricted."
@ -883,8 +875,8 @@ msgid "Unable to locate TV Tunes in Kodi."
msgstr "Impossible de trouver TV Tunes dans Kodi." msgstr "Impossible de trouver TV Tunes dans Kodi."
msgctxt "#33153" msgctxt "#33153"
msgid "Your Emby theme media has been synced to Kodi" msgid "Your Jellyfin theme media has been synced to Kodi"
msgstr "Votre média de thème Emby a été synchronisé avec Kodi" msgstr "Votre média de thème Jellyfin a été synchronisé avec Kodi"
msgctxt "#33154" msgctxt "#33154"
msgid "Add libraries" msgid "Add libraries"
@ -892,12 +884,12 @@ msgstr "Ajouter des médiathèques"
msgctxt "#33155" msgctxt "#33155"
msgid "" msgid ""
"The currently applied patch for Emby for Kodi is corrupted! Please post to " "The currently applied patch for Jellyfin for Kodi is corrupted! Please post to "
"the Emby for Kodi forums if this issue persists. This will need to be fixed " "the Jellyfin for Kodi forums if this issue persists. This will need to be fixed "
"as soon as possible." "as soon as possible."
msgstr "" msgstr ""
"Le patch actuellement appliqué pour Emby pour Kodi est corrompu ! Veuillez " "Le patch actuellement appliqué pour Jellyfin pour Kodi est corrompu ! Veuillez "
"poster sur les forums Emby pour Kodi si ce problème persiste. Cette " "poster sur les forums Jellyfin pour Kodi si ce problème persiste. Cette "
"situation devra être corrigée dès que possible." "situation devra être corrigée dès que possible."
msgctxt "#33156" msgctxt "#33156"
@ -917,23 +909,15 @@ msgid "Enable audio/subtitles selection"
msgstr "Activer la sélection audio/sous-titres" msgstr "Activer la sélection audio/sous-titres"
msgctxt "#33160" msgctxt "#33160"
msgid "To avoid errors, please update Emby for Kodi to version: " msgid "To avoid errors, please update Jellyfin for Kodi to version: "
msgstr "" msgstr ""
"Pour éviter les erreurs, veuillez mettre à jour la version d'Emby pour Kodi " "Pour éviter les erreurs, veuillez mettre à jour la version d'Jellyfin pour Kodi "
": " ": "
msgctxt "#33161"
msgid "Check for updates"
msgstr "Rechercher des mises à jour"
msgctxt "#33162" msgctxt "#33162"
msgid "Reset the music library?" msgid "Reset the music library?"
msgstr "Réinitialiser la médiathèque musicale ?" msgstr "Réinitialiser la médiathèque musicale ?"
msgctxt "#33163"
msgid "Support this project"
msgstr "Soutenir ce projet"
msgctxt "#33164" msgctxt "#33164"
msgid "Mask sensitive information in log (does not apply to kodi logging)" msgid "Mask sensitive information in log (does not apply to kodi logging)"
msgstr "" msgstr ""
@ -972,11 +956,11 @@ msgctxt "#33172"
msgid "" msgid ""
"You have {number} updates pending. This may take a little while before " "You have {number} updates pending. This may take a little while before "
"seeing new content. It might be faster to update your libraries via " "seeing new content. It might be faster to update your libraries via "
"launching the Emby add-on > update libraries. Proceed anyway?" "launching the Jellyfin add-on > update libraries. Proceed anyway?"
msgstr "" msgstr ""
"Vous avez {number} mises à jour en attente. Cela peut prendre un peu de " "Vous avez {number} mises à jour en attente. Cela peut prendre un peu de "
"temps avant de voir le nouveau contenu. Il peut être plus rapide de mettre à" "temps avant de voir le nouveau contenu. Il peut être plus rapide de mettre à"
" jour vos médiathèques en lançant l'add-on Emby > mettre à jour les " " jour vos médiathèques en lançant l'add-on Jellyfin > mettre à jour les "
"médiathèques. Procéder quand même ?" "médiathèques. Procéder quand même ?"
msgctxt "#33173" msgctxt "#33173"
@ -989,11 +973,11 @@ msgstr ""
msgctxt "#33175" msgctxt "#33175"
msgid "" msgid ""
"Paging tip: Each download thread requests your max items value from Emby at " "Paging tip: Each download thread requests your max items value from Jellyfin at "
"the same time." "the same time."
msgstr "" msgstr ""
"Conseil de pagination : Chaque téléchargement demande la valeur maximale des" "Conseil de pagination : Chaque téléchargement demande la valeur maximale des"
" éléments d'Emby en même temps." " éléments d'Jellyfin en même temps."
msgctxt "#33176" msgctxt "#33176"
msgid "Update or repair your libraries to apply the changes below." msgid "Update or repair your libraries to apply the changes below."
@ -1016,7 +1000,7 @@ msgid "Force transcode"
msgstr "Forcer le transcodage" msgstr "Forcer le transcodage"
msgctxt "#33180" msgctxt "#33180"
msgid "Restart Emby for Kodi" msgid "Restart Jellyfin for Kodi"
msgstr "" msgstr ""
msgctxt "#33181" msgctxt "#33181"
@ -1054,11 +1038,11 @@ msgid "Would you like to sync Rotten Tomatoes ratings?"
msgstr "" msgstr ""
msgctxt "#33191" msgctxt "#33191"
msgid "Restart Emby for Kodi to apply this change?" msgid "Restart Jellyfin for Kodi to apply this change?"
msgstr "" msgstr ""
msgctxt "#33192" msgctxt "#33192"
msgid "Restart Emby for Kodi" msgid "Restart Jellyfin for Kodi"
msgstr "" msgstr ""
msgctxt "#33193" msgctxt "#33193"

View file

@ -1,13 +1,13 @@
# Emby for Kodi language file # Jellyfin for Kodi language file
# Addon Name: Emby for Kodi # Addon Name: Jellyfin for Kodi
# Addon id: plugin.video.emby # Addon id: plugin.video.jellyfin
# Addon Provider: angelblue05 # Addon Provider: angelblue05
# Translators: # Translators:
# EffeF, 2019 # EffeF, 2019
# #
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: Emby for Kodi\n" "Project-Id-Version: Jellyfin for Kodi\n"
"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n"
"PO-Revision-Date: 2018-09-07 20:10+0000\n" "PO-Revision-Date: 2018-09-07 20:10+0000\n"
"Last-Translator: EffeF, 2019\n" "Last-Translator: EffeF, 2019\n"
@ -19,8 +19,8 @@ msgstr ""
"Plural-Forms: nplurals=2; plural=(n != 1);\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n"
msgctxt "#29999" msgctxt "#29999"
msgid "Emby for Kodi" msgid "Jellyfin for Kodi"
msgstr "Emby per Kodi" msgstr "Jellyfin per Kodi"
msgctxt "#30000" msgctxt "#30000"
msgid "Server address" msgid "Server address"
@ -191,12 +191,12 @@ msgid "TV Shows"
msgstr "Serie TV" msgstr "Serie TV"
msgctxt "#30401" msgctxt "#30401"
msgid "Emby options" msgid "Jellyfin options"
msgstr "Opzioni Emby" msgstr "Opzioni Jellyfin"
msgctxt "#30402" msgctxt "#30402"
msgid "Emby transcode" msgid "Jellyfin transcode"
msgstr "Transcodifica Emby" msgstr "Transcodifica Jellyfin"
msgctxt "#30405" msgctxt "#30405"
msgid "Add to favorites" msgid "Add to favorites"
@ -211,8 +211,8 @@ msgid "Settings"
msgstr "Impostazioni" msgstr "Impostazioni"
msgctxt "#30409" msgctxt "#30409"
msgid "Delete from Emby" msgid "Delete from Jellyfin"
msgstr "Elimina da Emby" msgstr "Elimina da Jellyfin"
msgctxt "#30410" msgctxt "#30410"
msgid "Refresh this item" msgid "Refresh this item"
@ -350,10 +350,6 @@ msgctxt "#30547"
msgid "Display message" msgid "Display message"
msgstr "Mostra messggio" msgstr "Mostra messggio"
msgctxt "#30600"
msgid "Sign in with Emby Connect"
msgstr "Accedi con Emby Connect"
msgctxt "#30602" msgctxt "#30602"
msgid "Password" msgid "Password"
msgstr "Password" msgstr "Password"
@ -391,8 +387,8 @@ msgid "Please sign in"
msgstr "Per favore accedi" msgstr "Per favore accedi"
msgctxt "#30613" msgctxt "#30613"
msgid "Change Emby Connect user" msgid "Change Jellyfin Connect user"
msgstr "Cambia utente Emby Connect" msgstr "Cambia utente Jellyfin Connect"
msgctxt "#30614" msgctxt "#30614"
msgid "Connect to server" msgid "Connect to server"
@ -410,10 +406,6 @@ msgctxt "#30617"
msgid "Server or port cannot be empty" msgid "Server or port cannot be empty"
msgstr "Server o porta non possono essere vuoti" msgstr "Server o porta non possono essere vuoti"
msgctxt "#30618"
msgid "Change Emby Connect user"
msgstr "Cambia utente Emby Connect"
msgctxt "#33000" msgctxt "#33000"
msgid "Welcome" msgid "Welcome"
msgstr "Benvenuto" msgstr "Benvenuto"
@ -435,8 +427,8 @@ msgid "Choose the subtitles stream"
msgstr "Scegli il flusso dei sottotitoli" msgstr "Scegli il flusso dei sottotitoli"
msgctxt "#33015" msgctxt "#33015"
msgid "Delete file from Emby?" msgid "Delete file from Jellyfin?"
msgstr "Eliminare file da Emby?" msgstr "Eliminare file da Jellyfin?"
msgctxt "#33016" msgctxt "#33016"
msgid "Play trailers?" msgid "Play trailers?"
@ -452,16 +444,16 @@ msgstr "Raggruppa:"
msgctxt "#33022" msgctxt "#33022"
msgid "" msgid ""
"Detected the database needs to be recreated for this version of Emby for " "Detected the database needs to be recreated for this version of Jellyfin for "
"Kodi. Proceed?" "Kodi. Proceed?"
msgstr "" msgstr ""
"Rilevato che il database deve essere ricreato per questa versione di Emby " "Rilevato che il database deve essere ricreato per questa versione di Jellyfin "
"per Kodi. Procedere?" "per Kodi. Procedere?"
msgctxt "#33023" msgctxt "#33023"
msgid "Emby for Kodi will not work correctly until the database is reset." msgid "Jellyfin for Kodi will not work correctly until the database is reset."
msgstr "" msgstr ""
"Emby per Kodi non funzionerà correttamente fino al ripristino del database." "Jellyfin per Kodi non funzionerà correttamente fino al ripristino del database."
msgctxt "#33025" msgctxt "#33025"
msgid "Completed in:" msgid "Completed in:"
@ -473,12 +465,12 @@ msgstr "È stato generato un nuovo ID dispositivo. Kodi verrà riavviato."
msgctxt "#33035" msgctxt "#33035"
msgid "" msgid ""
"Caution! If you choose Native mode, certain Emby features will be missing, " "Caution! If you choose Native mode, certain Jellyfin features will be missing, "
"such as: Emby cinema mode, direct stream/transcode options and parental " "such as: Jellyfin cinema mode, direct stream/transcode options and parental "
"access schedule." "access schedule."
msgstr "" msgstr ""
"Attenzione! Se si sceglie la modalità nativa, alcune funzionalità di Emby " "Attenzione! Se si sceglie la modalità nativa, alcune funzionalità di Jellyfin "
"saranno assenti, come ad esempio: modalità cinema Emby, opzioni streaming " "saranno assenti, come ad esempio: modalità cinema Jellyfin, opzioni streaming "
"diretto/transcodifica e il controllo parentale." "diretto/transcodifica e il controllo parentale."
msgctxt "#33036" msgctxt "#33036"
@ -500,12 +492,12 @@ msgstr "Kodi non riesce a localizzare il file:"
msgctxt "#33048" msgctxt "#33048"
msgid "" msgid ""
"You may need to verify your network credentials in the add-on settings or " "You may need to verify your network credentials in the add-on settings or "
"use the Emby path substitution to format your path correctly (Emby dashboard" "use the Jellyfin path substitution to format your path correctly (Jellyfin dashboard"
" > library). Stop syncing?" " > library). Stop syncing?"
msgstr "" msgstr ""
"Potrebbe essere necessario verificare le credenziali di rete nelle " "Potrebbe essere necessario verificare le credenziali di rete nelle "
"impostazioni dell'add-on o utilizzare la sostituzione del percorso Emby per " "impostazioni dell'add-on o utilizzare la sostituzione del percorso Jellyfin per "
"formattare correttamente il percorso (pannello controllo Emby > librerie). " "formattare correttamente il percorso (pannello controllo Jellyfin > librerie). "
"Interrompere la sincronizzazione?" "Interrompere la sincronizzazione?"
msgctxt "#33049" msgctxt "#33049"
@ -549,8 +541,8 @@ msgid "Remove all cached artwork?"
msgstr "Rimuove tutte le artwork dalla cache?" msgstr "Rimuove tutte le artwork dalla cache?"
msgctxt "#33087" msgctxt "#33087"
msgid "Reset all Emby add-on settings?" msgid "Reset all Jellyfin add-on settings?"
msgstr "Resetta tutte le impostazioni dell'add-on Emby?" msgstr "Resetta tutte le impostazioni dell'add-on Jellyfin?"
msgctxt "#33088" msgctxt "#33088"
msgid "" msgid ""
@ -582,10 +574,10 @@ msgstr "Cartella backup"
msgctxt "#33097" msgctxt "#33097"
msgid "" msgid ""
"Important, cleanonupdate was removed in your advanced settings to prevent " "Important, cleanonupdate was removed in your advanced settings to prevent "
"conflict with Emby for Kodi. Kodi will restart now." "conflict with Jellyfin for Kodi. Kodi will restart now."
msgstr "" msgstr ""
"Importante, cleanonupdate è stato rimosso nelle impostazioni avanzate per " "Importante, cleanonupdate è stato rimosso nelle impostazioni avanzate per "
"evitare conflitti con Emby per Kodi. Kodi verrà riavviato." "evitare conflitti con Jellyfin per Kodi. Kodi verrà riavviato."
msgctxt "#33098" msgctxt "#33098"
msgid "Refresh boxsets" msgid "Refresh boxsets"
@ -593,12 +585,12 @@ msgstr "Aggiorna collezioni"
msgctxt "#33099" msgctxt "#33099"
msgid "" msgid ""
"Install the server plugin Kodi companion to automatically apply emby library" "Install the server plugin Kodi companion to automatically apply Jellyfin library"
" updates at startup. This setting can be found in the add-on settings > sync" " updates at startup. This setting can be found in the add-on settings > sync"
" options > Enable Kodi Companion." " options > Enable Kodi Companion."
msgstr "" msgstr ""
"Installa il plugin Kodi companion sul server per applicare automaticamente " "Installa il plugin Kodi companion sul server per applicare automaticamente "
"gli aggiornamenti della libreria Emby all'avvio. Questa impostazione può " "gli aggiornamenti della libreria Jellyfin all'avvio. Questa impostazione può "
"essere trovata nelle impostazioni dell'add-on > opzioni di sincronizzazione>" "essere trovata nelle impostazioni dell'add-on > opzioni di sincronizzazione>"
" Abilita Kodi Companion." " Abilita Kodi Companion."
@ -703,12 +695,12 @@ msgstr ""
msgctxt "#33119" msgctxt "#33119"
msgid "" msgid ""
"Something went wrong during the sync. You'll be able to restore progress " "Something went wrong during the sync. You'll be able to restore progress "
"when restarting Kodi. If the problem persists, please report on the Emby for" "when restarting Kodi. If the problem persists, please report on the Jellyfin for"
" Kodi forums, with your Kodi log." " Kodi forums, with your Kodi log."
msgstr "" msgstr ""
"Qualcosa è andato storto durante la sincronizzazione. Sarai in grado di " "Qualcosa è andato storto durante la sincronizzazione. Sarai in grado di "
"ripristinare i progressi al riavvio di Kodi. Se il problema persiste, si " "ripristinare i progressi al riavvio di Kodi. Se il problema persiste, si "
"prega di riferire sul forum di Emby per Kodi, con il tuo log di Kodi." "prega di riferire sul forum di Jellyfin per Kodi, con il tuo log di Kodi."
msgctxt "#33120" msgctxt "#33120"
msgid "Select the libraries to add" msgid "Select the libraries to add"
@ -732,10 +724,10 @@ msgstr "Includi persone (lento)"
msgctxt "#33125" msgctxt "#33125"
msgid "" msgid ""
"Choose the Emby views to sync to Kodi. You can optionally sync libraries at " "Choose the Jellyfin views to sync to Kodi. You can optionally sync libraries at "
"a later time." "a later time."
msgstr "" msgstr ""
"Scegli le viste Emby da sincronizzare con Kodi. Puoi opzionalmente " "Scegli le viste Jellyfin da sincronizzare con Kodi. Puoi opzionalmente "
"sincronizzare le librerie in un secondo momento." "sincronizzare le librerie in un secondo momento."
msgctxt "#33126" msgctxt "#33126"
@ -750,17 +742,17 @@ msgctxt "#33128"
msgid "" msgid ""
"Failed to retrieve latest content updates. No content updates will be " "Failed to retrieve latest content updates. No content updates will be "
"applied until Kodi is restarted. If this issue persists, please report on " "applied until Kodi is restarted. If this issue persists, please report on "
"the Emby for Kodi forums, with your Kodi log." "the Jellyfin for Kodi forums, with your Kodi log."
msgstr "" msgstr ""
"Impossibile recuperare gli ultimi aggiornamenti dei contenuti. Nessun " "Impossibile recuperare gli ultimi aggiornamenti dei contenuti. Nessun "
"aggiornamento dei contenuti verrà applicato fino al riavvio di Kodi. Se il " "aggiornamento dei contenuti verrà applicato fino al riavvio di Kodi. Se il "
"problema persiste, segnalalo sul forum di Emby per Kodi, con il tuo log di " "problema persiste, segnalalo sul forum di Jellyfin per Kodi, con il tuo log di "
"Kodi." "Kodi."
msgctxt "#33129" msgctxt "#33129"
msgid "You can sync libraries by launching the Emby add-on > Add libraries." msgid "You can sync libraries by launching the Jellyfin add-on > Add libraries."
msgstr "" msgstr ""
"È possibile sincronizzare le librerie avviando l'add-on Emby > Aggiungi " "È possibile sincronizzare le librerie avviando l'add-on Jellyfin > Aggiungi "
"librerie." "librerie."
msgctxt "#33130" msgctxt "#33130"
@ -834,22 +826,22 @@ msgstr "Rimozione della libreria"
msgctxt "#33145" msgctxt "#33145"
msgid "" msgid ""
"Please make sure your Samba (smb) share of your Emby server is accessible to" "Please make sure your Samba (smb) share of your Jellyfin server is accessible to"
" your Kodi installation and that you have path substitution configured on " " your Kodi installation and that you have path substitution configured on "
"your server. Otherwise, Kodi may fail to locate your files." "your server. Otherwise, Kodi may fail to locate your files."
msgstr "" msgstr ""
"Assicurati che la tua condivisione di Samba (smb) del tuo server Emby sia " "Assicurati che la tua condivisione di Samba (smb) del tuo server Jellyfin sia "
"accessibile all'installazione di Kodi e che sia stata configurata la " "accessibile all'installazione di Kodi e che sia stata configurata la "
"sostituzione del percorso sul tuo server. In caso contrario, Kodi potrebbe " "sostituzione del percorso sul tuo server. In caso contrario, Kodi potrebbe "
"non riuscire a individuare i file." "non riuscire a individuare i file."
msgctxt "#33146" msgctxt "#33146"
msgid "Unable to connect to Emby." msgid "Unable to connect to Jellyfin."
msgstr "Impossibile connettersi a Emby." msgstr "Impossibile connettersi a Jellyfin."
msgctxt "#33147" msgctxt "#33147"
msgid "Your access to Emby is restricted." msgid "Your access to Jellyfin is restricted."
msgstr "Il tuo accesso a Emby è limitato." msgstr "Il tuo accesso a Jellyfin è limitato."
msgctxt "#33148" msgctxt "#33148"
msgid "Your access to this server is restricted." msgid "Your access to this server is restricted."
@ -878,8 +870,8 @@ msgid "Unable to locate TV Tunes in Kodi."
msgstr "Impossibile trovare TV Tunes in Kodi." msgstr "Impossibile trovare TV Tunes in Kodi."
msgctxt "#33153" msgctxt "#33153"
msgid "Your Emby theme media has been synced to Kodi" msgid "Your Jellyfin theme media has been synced to Kodi"
msgstr "I tuoi temi multimediali Emby sono stati sincronizzati con Kodi" msgstr "I tuoi temi multimediali Jellyfin sono stati sincronizzati con Kodi"
msgctxt "#33154" msgctxt "#33154"
msgid "Add libraries" msgid "Add libraries"
@ -887,12 +879,12 @@ msgstr "Aggiungi librerie"
msgctxt "#33155" msgctxt "#33155"
msgid "" msgid ""
"The currently applied patch for Emby for Kodi is corrupted! Please post to " "The currently applied patch for Jellyfin for Kodi is corrupted! Please post to "
"the Emby for Kodi forums if this issue persists. This will need to be fixed " "the Jellyfin for Kodi forums if this issue persists. This will need to be fixed "
"as soon as possible." "as soon as possible."
msgstr "" msgstr ""
"La patch attualmente applicata per Emby per Kodi è corrotta! Si prega di " "La patch attualmente applicata per Jellyfin per Kodi è corrotta! Si prega di "
"postare sul forum di Emby per Kodi se questo problema persiste. Questo dovrà" "postare sul forum di Jellyfin per Kodi se questo problema persiste. Questo dovrà"
" essere risolto il prima possibile." " essere risolto il prima possibile."
msgctxt "#33156" msgctxt "#33156"
@ -912,21 +904,13 @@ msgid "Enable audio/subtitles selection"
msgstr "Abilita selezione audio/sottotitoli" msgstr "Abilita selezione audio/sottotitoli"
msgctxt "#33160" msgctxt "#33160"
msgid "To avoid errors, please update Emby for Kodi to version: " msgid "To avoid errors, please update Jellyfin for Kodi to version: "
msgstr "Per evitare errori, aggiorna Emby per Kodi alla versione:" msgstr "Per evitare errori, aggiorna Jellyfin per Kodi alla versione:"
msgctxt "#33161"
msgid "Check for updates"
msgstr "Ricerca aggiornamenti"
msgctxt "#33162" msgctxt "#33162"
msgid "Reset the music library?" msgid "Reset the music library?"
msgstr "Ripristinare la libreria musicale?" msgstr "Ripristinare la libreria musicale?"
msgctxt "#33163"
msgid "Support this project"
msgstr "Supporta questo progetto"
msgctxt "#33164" msgctxt "#33164"
msgid "Mask sensitive information in log (does not apply to kodi logging)" msgid "Mask sensitive information in log (does not apply to kodi logging)"
msgstr "" msgstr ""
@ -964,11 +948,11 @@ msgctxt "#33172"
msgid "" msgid ""
"You have {number} updates pending. This may take a little while before " "You have {number} updates pending. This may take a little while before "
"seeing new content. It might be faster to update your libraries via " "seeing new content. It might be faster to update your libraries via "
"launching the Emby add-on > update libraries. Proceed anyway?" "launching the Jellyfin add-on > update libraries. Proceed anyway?"
msgstr "" msgstr ""
"Hai {number} aggiornamenti in sospeso. Questo potrebbe richiedere un po' di " "Hai {number} aggiornamenti in sospeso. Questo potrebbe richiedere un po' di "
"tempo prima di poter vedere i nuovi contenuti. Potrebbe essere più rapido " "tempo prima di poter vedere i nuovi contenuti. Potrebbe essere più rapido "
"aggiornare le tue librerie avviando l'add-on di Emby > Aggiorna librerie. " "aggiornare le tue librerie avviando l'add-on di Jellyfin > Aggiorna librerie. "
"Procedere comunque?" "Procedere comunque?"
msgctxt "#33173" msgctxt "#33173"
@ -981,11 +965,11 @@ msgstr "Chiamata - thread di download (default: 3)"
msgctxt "#33175" msgctxt "#33175"
msgid "" msgid ""
"Paging tip: Each download thread requests your max items value from Emby at " "Paging tip: Each download thread requests your max items value from Jellyfin at "
"the same time." "the same time."
msgstr "" msgstr ""
"Suggerimento: ogni thread di download richiede il tuoi elementi richiesti " "Suggerimento: ogni thread di download richiede il tuoi elementi richiesti "
"massimi da Emby contemporaneamente." "massimi da Jellyfin contemporaneamente."
msgctxt "#33176" msgctxt "#33176"
msgid "Update or repair your libraries to apply the changes below." msgid "Update or repair your libraries to apply the changes below."
@ -1005,8 +989,8 @@ msgid "Force transcode"
msgstr "Forza transcodifica" msgstr "Forza transcodifica"
msgctxt "#33180" msgctxt "#33180"
msgid "Restart Emby for Kodi" msgid "Restart Jellyfin for Kodi"
msgstr "Riavvia Emby per Kodi" msgstr "Riavvia Jellyfin per Kodi"
msgctxt "#33181" msgctxt "#33181"
msgid "Restarting to apply the patch" msgid "Restarting to apply the patch"
@ -1059,12 +1043,12 @@ msgid "Enable Kodi database discovery"
msgstr "Abilita il rilevamento del database Kodi" msgstr "Abilita il rilevamento del database Kodi"
msgctxt "#33191" msgctxt "#33191"
msgid "Restart Emby for Kodi to apply this change?" msgid "Restart Jellyfin for Kodi to apply this change?"
msgstr "Riavvia Emby per Kodi per applicare questo cambiamento?" msgstr "Riavvia Jellyfin per Kodi per applicare questo cambiamento?"
msgctxt "#33192" msgctxt "#33192"
msgid "Restart Emby for Kodi" msgid "Restart Jellyfin for Kodi"
msgstr "Riavvia Emby per Kodi" msgstr "Riavvia Jellyfin per Kodi"
msgctxt "#33193" msgctxt "#33193"
msgid "Restarting..." msgid "Restarting..."

View file

@ -1,13 +1,13 @@
# Emby for Kodi language file # Jellyfin for Kodi language file
# Addon Name: Emby for Kodi # Addon Name: Jellyfin for Kodi
# Addon id: plugin.video.emby # Addon id: plugin.video.jellyfin
# Addon Provider: angelblue05 # Addon Provider: angelblue05
# Translators: # Translators:
# 63ac71fcbd0581bb567b1f0d798c7970, 2019 # 63ac71fcbd0581bb567b1f0d798c7970, 2019
# #
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: Emby for Kodi\n" "Project-Id-Version: Jellyfin for Kodi\n"
"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n"
"PO-Revision-Date: 2018-09-07 20:10+0000\n" "PO-Revision-Date: 2018-09-07 20:10+0000\n"
"Last-Translator: 63ac71fcbd0581bb567b1f0d798c7970, 2019\n" "Last-Translator: 63ac71fcbd0581bb567b1f0d798c7970, 2019\n"
@ -19,8 +19,8 @@ msgstr ""
"Plural-Forms: nplurals=2; plural=(n != 1);\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n"
msgctxt "#29999" msgctxt "#29999"
msgid "Emby for Kodi" msgid "Jellyfin for Kodi"
msgstr "Emby voor Kodi" msgstr "Jellyfin voor Kodi"
msgctxt "#30000" msgctxt "#30000"
msgid "Server address" msgid "Server address"
@ -191,12 +191,12 @@ msgid "TV Shows"
msgstr "TV series" msgstr "TV series"
msgctxt "#30401" msgctxt "#30401"
msgid "Emby options" msgid "Jellyfin options"
msgstr "Emby opties" msgstr "Jellyfin opties"
msgctxt "#30402" msgctxt "#30402"
msgid "Emby transcode" msgid "Jellyfin transcode"
msgstr "Emby transcode" msgstr "Jellyfin transcode"
msgctxt "#30405" msgctxt "#30405"
msgid "Add to favorites" msgid "Add to favorites"
@ -211,8 +211,8 @@ msgid "Settings"
msgstr "Instellingen" msgstr "Instellingen"
msgctxt "#30409" msgctxt "#30409"
msgid "Delete from Emby" msgid "Delete from Jellyfin"
msgstr "Uit Emby verwijderen" msgstr "Uit Jellyfin verwijderen"
msgctxt "#30410" msgctxt "#30410"
msgid "Refresh this item" msgid "Refresh this item"
@ -350,10 +350,6 @@ msgctxt "#30547"
msgid "Display message" msgid "Display message"
msgstr "Melding tonen" msgstr "Melding tonen"
msgctxt "#30600"
msgid "Sign in with Emby Connect"
msgstr "Aanmelden met Emby Connect"
msgctxt "#30602" msgctxt "#30602"
msgid "Password" msgid "Password"
msgstr "Wachtwoord" msgstr "Wachtwoord"
@ -391,8 +387,8 @@ msgid "Please sign in"
msgstr "Aanmelden" msgstr "Aanmelden"
msgctxt "#30613" msgctxt "#30613"
msgid "Change Emby Connect user" msgid "Change Jellyfin Connect user"
msgstr "Emby Connect gebruiker wijzigen" msgstr "Jellyfin Connect gebruiker wijzigen"
msgctxt "#30614" msgctxt "#30614"
msgid "Connect to server" msgid "Connect to server"
@ -410,10 +406,6 @@ msgctxt "#30617"
msgid "Server or port cannot be empty" msgid "Server or port cannot be empty"
msgstr "Server of poort kan niet leeg zijn" msgstr "Server of poort kan niet leeg zijn"
msgctxt "#30618"
msgid "Change Emby Connect user"
msgstr "Emby Connect gebruiker wijzigen"
msgctxt "#33000" msgctxt "#33000"
msgid "Welcome" msgid "Welcome"
msgstr "Welkom" msgstr "Welkom"
@ -435,8 +427,8 @@ msgid "Choose the subtitles stream"
msgstr "Kies ondertitel stream" msgstr "Kies ondertitel stream"
msgctxt "#33015" msgctxt "#33015"
msgid "Delete file from Emby?" msgid "Delete file from Jellyfin?"
msgstr "Bestand uit Emby verwijderen?" msgstr "Bestand uit Jellyfin verwijderen?"
msgctxt "#33016" msgctxt "#33016"
msgid "Play trailers?" msgid "Play trailers?"
@ -452,15 +444,15 @@ msgstr "Verzamelen:"
msgctxt "#33022" msgctxt "#33022"
msgid "" msgid ""
"Detected the database needs to be recreated for this version of Emby for " "Detected the database needs to be recreated for this version of Jellyfin for "
"Kodi. Proceed?" "Kodi. Proceed?"
msgstr "" msgstr ""
"De databank moet opnieuw gemaakt worden voor deze versie van Emby for Kodi. " "De databank moet opnieuw gemaakt worden voor deze versie van Jellyfin for Kodi. "
"Verder gaan?" "Verder gaan?"
msgctxt "#33023" msgctxt "#33023"
msgid "Emby for Kodi will not work correctly until the database is reset." msgid "Jellyfin for Kodi will not work correctly until the database is reset."
msgstr "Emby for Kodi werkt niet correct voor dat de databank gereset is." msgstr "Jellyfin for Kodi werkt niet correct voor dat de databank gereset is."
msgctxt "#33025" msgctxt "#33025"
msgid "Completed in:" msgid "Completed in:"
@ -472,12 +464,12 @@ msgstr "Een nieuw apparaat id is aangemaakt. Kodi start nu opnieuw."
msgctxt "#33035" msgctxt "#33035"
msgid "" msgid ""
"Caution! If you choose Native mode, certain Emby features will be missing, " "Caution! If you choose Native mode, certain Jellyfin features will be missing, "
"such as: Emby cinema mode, direct stream/transcode options and parental " "such as: Jellyfin cinema mode, direct stream/transcode options and parental "
"access schedule." "access schedule."
msgstr "" msgstr ""
"Opgepast! Bij het kiezen van Native mode, zullen bepaalde Emby mogelijkheden" "Opgepast! Bij het kiezen van Native mode, zullen bepaalde Jellyfin mogelijkheden"
" ontbreken zoals: Emby Cinema modus, direct stream/transcode opties and " " ontbreken zoals: Jellyfin Cinema modus, direct stream/transcode opties and "
"ouderlijke toegang planning." "ouderlijke toegang planning."
msgctxt "#33036" msgctxt "#33036"
@ -499,12 +491,12 @@ msgstr "Kodi kan volgende bestand niet vinden:"
msgctxt "#33048" msgctxt "#33048"
msgid "" msgid ""
"You may need to verify your network credentials in the add-on settings or " "You may need to verify your network credentials in the add-on settings or "
"use the Emby path substitution to format your path correctly (Emby dashboard" "use the Jellyfin path substitution to format your path correctly (Jellyfin dashboard"
" > library). Stop syncing?" " > library). Stop syncing?"
msgstr "" msgstr ""
"Misschien is het nodig uw netwerk gegevens na te kijken in de add-on " "Misschien is het nodig uw netwerk gegevens na te kijken in de add-on "
"instellingen of gebruik de Emby path vervanging om uw folder correct te " "instellingen of gebruik de Jellyfin path vervanging om uw folder correct te "
"formateren (Emby dashboard > bibliotheek). Synchroniseren stoppen?" "formateren (Jellyfin dashboard > bibliotheek). Synchroniseren stoppen?"
msgctxt "#33049" msgctxt "#33049"
msgid "New" msgid "New"
@ -547,8 +539,8 @@ msgid "Remove all cached artwork?"
msgstr "Cached artwork verwijderen?" msgstr "Cached artwork verwijderen?"
msgctxt "#33087" msgctxt "#33087"
msgid "Reset all Emby add-on settings?" msgid "Reset all Jellyfin add-on settings?"
msgstr "Alle Emby add-on instellingen resetten?" msgstr "Alle Jellyfin add-on instellingen resetten?"
msgctxt "#33088" msgctxt "#33088"
msgid "" msgid ""
@ -580,10 +572,10 @@ msgstr "Backup folder"
msgctxt "#33097" msgctxt "#33097"
msgid "" msgid ""
"Important, cleanonupdate was removed in your advanced settings to prevent " "Important, cleanonupdate was removed in your advanced settings to prevent "
"conflict with Emby for Kodi. Kodi will restart now." "conflict with Jellyfin for Kodi. Kodi will restart now."
msgstr "" msgstr ""
"Belangrijd, cleanonupdate is verwijderen uit de geavanceerde instellingen om" "Belangrijd, cleanonupdate is verwijderen uit de geavanceerde instellingen om"
" een conflict met Emby for Kodi te voorkomen. Kodi start nu opnieuw op." " een conflict met Jellyfin for Kodi te voorkomen. Kodi start nu opnieuw op."
msgctxt "#33098" msgctxt "#33098"
msgid "Refresh boxsets" msgid "Refresh boxsets"
@ -591,11 +583,11 @@ msgstr "Boxsets vernieuwen"
msgctxt "#33099" msgctxt "#33099"
msgid "" msgid ""
"Install the server plugin Kodi companion to automatically apply emby library" "Install the server plugin Kodi companion to automatically apply Jellyfin library"
" updates at startup. This setting can be found in the add-on settings > sync" " updates at startup. This setting can be found in the add-on settings > sync"
" options > Enable Kodi Companion." " options > Enable Kodi Companion."
msgstr "" msgstr ""
"Installeer de server plugin Kodi companion om Emby bibliotheek updates " "Installeer de server plugin Kodi companion om Jellyfin bibliotheek updates "
"automatisch te laten lopen bij het opstarten. Deze instellingen kan gevonden" "automatisch te laten lopen bij het opstarten. Deze instellingen kan gevonden"
" worden in de add-on instellingen > synchroniseer opties > Kodi Companion " " worden in de add-on instellingen > synchroniseer opties > Kodi Companion "
"inschakelen." "inschakelen."
@ -700,12 +692,12 @@ msgstr ""
msgctxt "#33119" msgctxt "#33119"
msgid "" msgid ""
"Something went wrong during the sync. You'll be able to restore progress " "Something went wrong during the sync. You'll be able to restore progress "
"when restarting Kodi. If the problem persists, please report on the Emby for" "when restarting Kodi. If the problem persists, please report on the Jellyfin for"
" Kodi forums, with your Kodi log." " Kodi forums, with your Kodi log."
msgstr "" msgstr ""
"Er is iets mis gegaan tijdens de synchronisatie. U kunt de voortgang " "Er is iets mis gegaan tijdens de synchronisatie. U kunt de voortgang "
"herstellen als u Kodi opnieuw opstart. Als het probleem blijft, meld dit " "herstellen als u Kodi opnieuw opstart. Als het probleem blijft, meld dit "
"probleem dan op de Emby for Kodi forums, met uw Kodi log." "probleem dan op de Jellyfin for Kodi forums, met uw Kodi log."
msgctxt "#33120" msgctxt "#33120"
msgid "Select the libraries to add" msgid "Select the libraries to add"
@ -729,10 +721,10 @@ msgstr "Mensen meerekenen (langzaam)"
msgctxt "#33125" msgctxt "#33125"
msgid "" msgid ""
"Choose the Emby views to sync to Kodi. You can optionally sync libraries at " "Choose the Jellyfin views to sync to Kodi. You can optionally sync libraries at "
"a later time." "a later time."
msgstr "" msgstr ""
"Kies de Emby zichten om naar Kodi te synchroniseren. U kunt later de " "Kies de Jellyfin zichten om naar Kodi te synchroniseren. U kunt later de "
"bibliotheken optioneel synchroniseren." "bibliotheken optioneel synchroniseren."
msgctxt "#33126" msgctxt "#33126"
@ -747,16 +739,16 @@ msgctxt "#33128"
msgid "" msgid ""
"Failed to retrieve latest content updates. No content updates will be " "Failed to retrieve latest content updates. No content updates will be "
"applied until Kodi is restarted. If this issue persists, please report on " "applied until Kodi is restarted. If this issue persists, please report on "
"the Emby for Kodi forums, with your Kodi log." "the Jellyfin for Kodi forums, with your Kodi log."
msgstr "" msgstr ""
"Het is mislukt om de laatste inhoud updates te verkrijgen. Er worden geen " "Het is mislukt om de laatste inhoud updates te verkrijgen. Er worden geen "
"inhoud updates toe gepast totdat Kodi opnieuw is opgestart. Als deze fout " "inhoud updates toe gepast totdat Kodi opnieuw is opgestart. Als deze fout "
"blijft komen, meld u dan op de Emby for Kodi forums met uw Kodi log." "blijft komen, meld u dan op de Jellyfin for Kodi forums met uw Kodi log."
msgctxt "#33129" msgctxt "#33129"
msgid "You can sync libraries by launching the Emby add-on > Add libraries." msgid "You can sync libraries by launching the Jellyfin add-on > Add libraries."
msgstr "" msgstr ""
"U kunt bibliotheken synchroniseren door de Emby add-on > bibliotheken " "U kunt bibliotheken synchroniseren door de Jellyfin add-on > bibliotheken "
"toevoegen te starten." "toevoegen te starten."
msgctxt "#33130" msgctxt "#33130"
@ -829,21 +821,21 @@ msgstr "Bibliotheek wordt verwijderen"
msgctxt "#33145" msgctxt "#33145"
msgid "" msgid ""
"Please make sure your Samba (smb) share of your Emby server is accessible to" "Please make sure your Samba (smb) share of your Jellyfin server is accessible to"
" your Kodi installation and that you have path substitution configured on " " your Kodi installation and that you have path substitution configured on "
"your server. Otherwise, Kodi may fail to locate your files." "your server. Otherwise, Kodi may fail to locate your files."
msgstr "" msgstr ""
"Controleer of uw Samba (smb) gedeelde map van uw Emby server toegankelijk is" "Controleer of uw Samba (smb) gedeelde map van uw Jellyfin server toegankelijk is"
" voor uw Kodi installatie en dat path substitution op uw server is " " voor uw Kodi installatie en dat path substitution op uw server is "
"ingesteld. anders kan voorkomen dat het Kodi mislukt uw bestanden te vinden." "ingesteld. anders kan voorkomen dat het Kodi mislukt uw bestanden te vinden."
msgctxt "#33146" msgctxt "#33146"
msgid "Unable to connect to Emby." msgid "Unable to connect to Jellyfin."
msgstr "Niet in staat om met Emby te verbinden." msgstr "Niet in staat om met Jellyfin te verbinden."
msgctxt "#33147" msgctxt "#33147"
msgid "Your access to Emby is restricted." msgid "Your access to Jellyfin is restricted."
msgstr "Uw toegang tot Emby is beperkt." msgstr "Uw toegang tot Jellyfin is beperkt."
msgctxt "#33148" msgctxt "#33148"
msgid "Your access to this server is restricted." msgid "Your access to this server is restricted."
@ -872,8 +864,8 @@ msgid "Unable to locate TV Tunes in Kodi."
msgstr "Niet in staat om TV Tunes in Kodi te vinden." msgstr "Niet in staat om TV Tunes in Kodi te vinden."
msgctxt "#33153" msgctxt "#33153"
msgid "Your Emby theme media has been synced to Kodi" msgid "Your Jellyfin theme media has been synced to Kodi"
msgstr "Uw Emby thema media is gesynchroniseerd met Kodi" msgstr "Uw Jellyfin thema media is gesynchroniseerd met Kodi"
msgctxt "#33154" msgctxt "#33154"
msgid "Add libraries" msgid "Add libraries"
@ -881,12 +873,12 @@ msgstr "Bibliotheken toevoegen"
msgctxt "#33155" msgctxt "#33155"
msgid "" msgid ""
"The currently applied patch for Emby for Kodi is corrupted! Please post to " "The currently applied patch for Jellyfin for Kodi is corrupted! Please post to "
"the Emby for Kodi forums if this issue persists. This will need to be fixed " "the Jellyfin for Kodi forums if this issue persists. This will need to be fixed "
"as soon as possible." "as soon as possible."
msgstr "" msgstr ""
"De huidige toegepaste patch voor Emby is beschadigd! Maak alstublieft een " "De huidige toegepaste patch voor Jellyfin is beschadigd! Maak alstublieft een "
"melding op de Emby voor Kodi forums als het probleem blijft. Dit moet yo " "melding op de Jellyfin voor Kodi forums als het probleem blijft. Dit moet yo "
"snel als mogelijk verholpen worden." "snel als mogelijk verholpen worden."
msgctxt "#33156" msgctxt "#33156"
@ -906,21 +898,13 @@ msgid "Enable audio/subtitles selection"
msgstr "Schaken audio/ondertitel keuze in" msgstr "Schaken audio/ondertitel keuze in"
msgctxt "#33160" msgctxt "#33160"
msgid "To avoid errors, please update Emby for Kodi to version: " msgid "To avoid errors, please update Jellyfin for Kodi to version: "
msgstr "Om problemen voorkomen, update Emby for Kodi naar versie:" msgstr "Om problemen voorkomen, update Jellyfin for Kodi naar versie:"
msgctxt "#33161"
msgid "Check for updates"
msgstr "Naar updates zoeken"
msgctxt "#33162" msgctxt "#33162"
msgid "Reset the music library?" msgid "Reset the music library?"
msgstr "Muziek bibliotheek resetten?" msgstr "Muziek bibliotheek resetten?"
msgctxt "#33163"
msgid "Support this project"
msgstr "Dit project ondersteunen"
msgctxt "#33164" msgctxt "#33164"
msgid "Mask sensitive information in log (does not apply to kodi logging)" msgid "Mask sensitive information in log (does not apply to kodi logging)"
msgstr "" msgstr ""
@ -958,11 +942,11 @@ msgctxt "#33172"
msgid "" msgid ""
"You have {number} updates pending. This may take a little while before " "You have {number} updates pending. This may take a little while before "
"seeing new content. It might be faster to update your libraries via " "seeing new content. It might be faster to update your libraries via "
"launching the Emby add-on > update libraries. Proceed anyway?" "launching the Jellyfin add-on > update libraries. Proceed anyway?"
msgstr "" msgstr ""
"U heeft {number} wachtende updates. Het kan misschien even during voordat u " "U heeft {number} wachtende updates. Het kan misschien even during voordat u "
"nieuwe inhoud ziet. Misschien gaat het updaten van uw bibliotheken sneller " "nieuwe inhoud ziet. Misschien gaat het updaten van uw bibliotheken sneller "
"door de Emby add-on bibliotheken updaten te starten. Toch doorgaan?" "door de Jellyfin add-on bibliotheken updaten te starten. Toch doorgaan?"
msgctxt "#33173" msgctxt "#33173"
msgid "Forget about the previous sync? This is not recommended." msgid "Forget about the previous sync? This is not recommended."
@ -974,10 +958,10 @@ msgstr "Paging - download threads (standaard: 3)"
msgctxt "#33175" msgctxt "#33175"
msgid "" msgid ""
"Paging tip: Each download thread requests your max items value from Emby at " "Paging tip: Each download thread requests your max items value from Jellyfin at "
"the same time." "the same time."
msgstr "" msgstr ""
"Paging tip: Elke download thread vraagt naar uw maximum items waarde by Emby" "Paging tip: Elke download thread vraagt naar uw maximum items waarde by Jellyfin"
" op hetzelfde moment." " op hetzelfde moment."
msgctxt "#33176" msgctxt "#33176"
@ -999,8 +983,8 @@ msgid "Force transcode"
msgstr "Transkodering dwingen" msgstr "Transkodering dwingen"
msgctxt "#33180" msgctxt "#33180"
msgid "Restart Emby for Kodi" msgid "Restart Jellyfin for Kodi"
msgstr "Emby for Kodi opnieuw starten" msgstr "Jellyfin for Kodi opnieuw starten"
msgctxt "#33181" msgctxt "#33181"
msgid "Restarting to apply the patch" msgid "Restarting to apply the patch"
@ -1039,12 +1023,12 @@ msgid "Would you like to sync Rotten Tomatoes ratings?"
msgstr "Rotten Tomatoes ratings synchroniseren?" msgstr "Rotten Tomatoes ratings synchroniseren?"
msgctxt "#33191" msgctxt "#33191"
msgid "Restart Emby for Kodi to apply this change?" msgid "Restart Jellyfin for Kodi to apply this change?"
msgstr "Emby for Kodi opnieuw opstarten om de wijziging toe te passen?" msgstr "Jellyfin for Kodi opnieuw opstarten om de wijziging toe te passen?"
msgctxt "#33192" msgctxt "#33192"
msgid "Restart Emby for Kodi" msgid "Restart Jellyfin for Kodi"
msgstr "Emby for Kodi opnieuw starten" msgstr "Jellyfin for Kodi opnieuw starten"
msgctxt "#33193" msgctxt "#33193"
msgid "Restarting..." msgid "Restarting..."
@ -1055,8 +1039,8 @@ msgid "Manage libraries"
msgstr "Bibliotheken beheren" msgstr "Bibliotheken beheren"
msgctxt "#33195" msgctxt "#33195"
msgid "Enable Emby for Kodi" msgid "Enable Jellyfin for Kodi"
msgstr "Emby for Kodi inschakelen" msgstr "Jellyfin for Kodi inschakelen"
msgctxt "#33196" msgctxt "#33196"
msgid "Advanced options" msgid "Advanced options"

View file

@ -1,13 +1,13 @@
# Emby for Kodi language file # Jellyfin for Kodi language file
# Addon Name: Emby for Kodi # Addon Name: Jellyfin for Kodi
# Addon id: plugin.video.emby # Addon id: plugin.video.jellyfin
# Addon Provider: angelblue05 # Addon Provider: angelblue05
# Translators: # Translators:
# Michał Sawicz <michal@sawicz.net>, 2019 # Michał Sawicz <michal@sawicz.net>, 2019
# #
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: Emby for Kodi\n" "Project-Id-Version: Jellyfin for Kodi\n"
"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n"
"PO-Revision-Date: 2018-09-07 20:10+0000\n" "PO-Revision-Date: 2018-09-07 20:10+0000\n"
"Last-Translator: Michał Sawicz <michal@sawicz.net>, 2019\n" "Last-Translator: Michał Sawicz <michal@sawicz.net>, 2019\n"
@ -19,8 +19,8 @@ msgstr ""
"Plural-Forms: nplurals=4; plural=(n==1 ? 0 : (n%10>=2 && n%10<=4) && (n%100<12 || n%100>14) ? 1 : n!=1 && (n%10>=0 && n%10<=1) || (n%10>=5 && n%10<=9) || (n%100>=12 && n%100<=14) ? 2 : 3);\n" "Plural-Forms: nplurals=4; plural=(n==1 ? 0 : (n%10>=2 && n%10<=4) && (n%100<12 || n%100>14) ? 1 : n!=1 && (n%10>=0 && n%10<=1) || (n%10>=5 && n%10<=9) || (n%100>=12 && n%100<=14) ? 2 : 3);\n"
msgctxt "#29999" msgctxt "#29999"
msgid "Emby for Kodi" msgid "Jellyfin for Kodi"
msgstr "Emby dla Kodi" msgstr "Jellyfin dla Kodi"
msgctxt "#30000" msgctxt "#30000"
msgid "Server address" msgid "Server address"
@ -191,12 +191,12 @@ msgid "TV Shows"
msgstr "Seriale" msgstr "Seriale"
msgctxt "#30401" msgctxt "#30401"
msgid "Emby options" msgid "Jellyfin options"
msgstr "Opcje Emby" msgstr "Opcje Jellyfin"
msgctxt "#30402" msgctxt "#30402"
msgid "Emby transcode" msgid "Jellyfin transcode"
msgstr "Transkodowanie Emby" msgstr "Transkodowanie Jellyfin"
msgctxt "#30405" msgctxt "#30405"
msgid "Add to favorites" msgid "Add to favorites"
@ -211,8 +211,8 @@ msgid "Settings"
msgstr "Ustawienia" msgstr "Ustawienia"
msgctxt "#30409" msgctxt "#30409"
msgid "Delete from Emby" msgid "Delete from Jellyfin"
msgstr "Usuń z Emby" msgstr "Usuń z Jellyfin"
msgctxt "#30410" msgctxt "#30410"
msgid "Refresh this item" msgid "Refresh this item"
@ -350,10 +350,6 @@ msgctxt "#30547"
msgid "Display message" msgid "Display message"
msgstr "Wyświetl wiadomość" msgstr "Wyświetl wiadomość"
msgctxt "#30600"
msgid "Sign in with Emby Connect"
msgstr "Zaloguj z Emby Connect"
msgctxt "#30602" msgctxt "#30602"
msgid "Password" msgid "Password"
msgstr "Hasło" msgstr "Hasło"
@ -391,8 +387,8 @@ msgid "Please sign in"
msgstr "Proszę się zalogować" msgstr "Proszę się zalogować"
msgctxt "#30613" msgctxt "#30613"
msgid "Change Emby Connect user" msgid "Change Jellyfin Connect user"
msgstr "Zmień użytkownika Emby Connect" msgstr "Zmień użytkownika Jellyfin Connect"
msgctxt "#30614" msgctxt "#30614"
msgid "Connect to server" msgid "Connect to server"
@ -410,10 +406,6 @@ msgctxt "#30617"
msgid "Server or port cannot be empty" msgid "Server or port cannot be empty"
msgstr "Nazwa hosta i port nie mogą być puste" msgstr "Nazwa hosta i port nie mogą być puste"
msgctxt "#30618"
msgid "Change Emby Connect user"
msgstr "Zmień użytkownika Emby Connect"
msgctxt "#33000" msgctxt "#33000"
msgid "Welcome" msgid "Welcome"
msgstr "Witaj" msgstr "Witaj"
@ -435,8 +427,8 @@ msgid "Choose the subtitles stream"
msgstr "Wybierz napisy" msgstr "Wybierz napisy"
msgctxt "#33015" msgctxt "#33015"
msgid "Delete file from Emby?" msgid "Delete file from Jellyfin?"
msgstr "Usunąć plik z Emby?" msgstr "Usunąć plik z Jellyfin?"
msgctxt "#33016" msgctxt "#33016"
msgid "Play trailers?" msgid "Play trailers?"
@ -452,16 +444,16 @@ msgstr "Pobieranie:"
msgctxt "#33022" msgctxt "#33022"
msgid "" msgid ""
"Detected the database needs to be recreated for this version of Emby for " "Detected the database needs to be recreated for this version of Jellyfin for "
"Kodi. Proceed?" "Kodi. Proceed?"
msgstr "" msgstr ""
"Wykryto konieczność rekonstrukcji bazy dla tej wersji Emby dla Kodi. " "Wykryto konieczność rekonstrukcji bazy dla tej wersji Jellyfin dla Kodi. "
"Kontynuować?" "Kontynuować?"
msgctxt "#33023" msgctxt "#33023"
msgid "Emby for Kodi will not work correctly until the database is reset." msgid "Jellyfin for Kodi will not work correctly until the database is reset."
msgstr "" msgstr ""
"Emby dla Kodi nie będzie działało poprawnie dopóki baza nie zostanie " "Jellyfin dla Kodi nie będzie działało poprawnie dopóki baza nie zostanie "
"zresetowana." "zresetowana."
msgctxt "#33025" msgctxt "#33025"
@ -476,11 +468,11 @@ msgstr ""
msgctxt "#33035" msgctxt "#33035"
msgid "" msgid ""
"Caution! If you choose Native mode, certain Emby features will be missing, " "Caution! If you choose Native mode, certain Jellyfin features will be missing, "
"such as: Emby cinema mode, direct stream/transcode options and parental " "such as: Jellyfin cinema mode, direct stream/transcode options and parental "
"access schedule." "access schedule."
msgstr "" msgstr ""
"Uwaga! Jeśli wybierzesz tryb Natywny, niektóre funkcje Emby będą " "Uwaga! Jeśli wybierzesz tryb Natywny, niektóre funkcje Jellyfin będą "
"niedostępne, np.: tryb kinowy, opcje strumieniowania bezpośredniego i " "niedostępne, np.: tryb kinowy, opcje strumieniowania bezpośredniego i "
"transkodowania, harmonogram ograniczeń wiekowych." "transkodowania, harmonogram ograniczeń wiekowych."
@ -503,11 +495,11 @@ msgstr "Kodi nie odnalazł pliku:"
msgctxt "#33048" msgctxt "#33048"
msgid "" msgid ""
"You may need to verify your network credentials in the add-on settings or " "You may need to verify your network credentials in the add-on settings or "
"use the Emby path substitution to format your path correctly (Emby dashboard" "use the Jellyfin path substitution to format your path correctly (Jellyfin dashboard"
" > library). Stop syncing?" " > library). Stop syncing?"
msgstr "" msgstr ""
"Być może należy sprawdzić dane logowania w sieci w ustawieniach dodatku lub " "Być może należy sprawdzić dane logowania w sieci w ustawieniach dodatku lub "
"format podstawienia ścieżki w Emby (Kokpit Emby > Biblioteki). Zatrzymać " "format podstawienia ścieżki w Jellyfin (Kokpit Jellyfin > Biblioteki). Zatrzymać "
"synchronizację?" "synchronizację?"
msgctxt "#33049" msgctxt "#33049"
@ -551,8 +543,8 @@ msgid "Remove all cached artwork?"
msgstr "Usunąć pobrane grafiki?" msgstr "Usunąć pobrane grafiki?"
msgctxt "#33087" msgctxt "#33087"
msgid "Reset all Emby add-on settings?" msgid "Reset all Jellyfin add-on settings?"
msgstr "Zresetować wszystkie ustawienia dodatku Emby?" msgstr "Zresetować wszystkie ustawienia dodatku Jellyfin?"
msgctxt "#33088" msgctxt "#33088"
msgid "" msgid ""
@ -584,10 +576,10 @@ msgstr "Folder kopii zapasowej"
msgctxt "#33097" msgctxt "#33097"
msgid "" msgid ""
"Important, cleanonupdate was removed in your advanced settings to prevent " "Important, cleanonupdate was removed in your advanced settings to prevent "
"conflict with Emby for Kodi. Kodi will restart now." "conflict with Jellyfin for Kodi. Kodi will restart now."
msgstr "" msgstr ""
"Ważne: \"cleanonupdate\" zostało usunięte z ustawień zaawansowanych aby " "Ważne: \"cleanonupdate\" zostało usunięte z ustawień zaawansowanych aby "
"zapobiec konfliktowi z Emby dla Kodi. Kodi zostanie uruchomione ponownie." "zapobiec konfliktowi z Jellyfin dla Kodi. Kodi zostanie uruchomione ponownie."
msgctxt "#33098" msgctxt "#33098"
msgid "Refresh boxsets" msgid "Refresh boxsets"
@ -595,11 +587,11 @@ msgstr "Odśwież kolekcje"
msgctxt "#33099" msgctxt "#33099"
msgid "" msgid ""
"Install the server plugin Kodi companion to automatically apply emby library" "Install the server plugin Kodi companion to automatically apply Jellyfin library"
" updates at startup. This setting can be found in the add-on settings > sync" " updates at startup. This setting can be found in the add-on settings > sync"
" options > Enable Kodi Companion." " options > Enable Kodi Companion."
msgstr "" msgstr ""
"Zainstaluj wtyczkę serwera Emby \"Kodi Companion\" by automatycznie pobierać" "Zainstaluj wtyczkę serwera Jellyfin \"Kodi Companion\" by automatycznie pobierać"
" aktualizacje bazy danych. Właściwa opcja znajduje się w ustawieniach " " aktualizacje bazy danych. Właściwa opcja znajduje się w ustawieniach "
"dodatku > Synchronizacja > Włącz Kodi Companion." "dodatku > Synchronizacja > Włącz Kodi Companion."
@ -700,12 +692,12 @@ msgstr ""
msgctxt "#33119" msgctxt "#33119"
msgid "" msgid ""
"Something went wrong during the sync. You'll be able to restore progress " "Something went wrong during the sync. You'll be able to restore progress "
"when restarting Kodi. If the problem persists, please report on the Emby for" "when restarting Kodi. If the problem persists, please report on the Jellyfin for"
" Kodi forums, with your Kodi log." " Kodi forums, with your Kodi log."
msgstr "" msgstr ""
"Coś poszło nie tak podczas synchronizacji. Po uruchomieniu Kodi ponownie " "Coś poszło nie tak podczas synchronizacji. Po uruchomieniu Kodi ponownie "
"będzie możliwe jej wznowienie. Jeśli problem się powtórzy, proszę zgłoś go " "będzie możliwe jej wznowienie. Jeśli problem się powtórzy, proszę zgłoś go "
"na forum Emby for Kodi, dołączając dziennik zdarzeń Kodi." "na forum Jellyfin for Kodi, dołączając dziennik zdarzeń Kodi."
msgctxt "#33120" msgctxt "#33120"
msgid "Select the libraries to add" msgid "Select the libraries to add"
@ -729,10 +721,10 @@ msgstr "Pobieraj twórców (wolne)"
msgctxt "#33125" msgctxt "#33125"
msgid "" msgid ""
"Choose the Emby views to sync to Kodi. You can optionally sync libraries at " "Choose the Jellyfin views to sync to Kodi. You can optionally sync libraries at "
"a later time." "a later time."
msgstr "" msgstr ""
"Wybierz biblioteki Emby do synchronizacji z Kodi. Możesz to także zrobić " "Wybierz biblioteki Jellyfin do synchronizacji z Kodi. Możesz to także zrobić "
"później." "później."
msgctxt "#33126" msgctxt "#33126"
@ -747,16 +739,16 @@ msgctxt "#33128"
msgid "" msgid ""
"Failed to retrieve latest content updates. No content updates will be " "Failed to retrieve latest content updates. No content updates will be "
"applied until Kodi is restarted. If this issue persists, please report on " "applied until Kodi is restarted. If this issue persists, please report on "
"the Emby for Kodi forums, with your Kodi log." "the Jellyfin for Kodi forums, with your Kodi log."
msgstr "" msgstr ""
"Nie udało się pobrać ostatnich aktualizacji. Nie zostaną one zapisane dopóki" "Nie udało się pobrać ostatnich aktualizacji. Nie zostaną one zapisane dopóki"
" Kodi nie zostanie zrestartowane. Jeśli problem się powtórzy, proszę zgłoś " " Kodi nie zostanie zrestartowane. Jeśli problem się powtórzy, proszę zgłoś "
"go na forum Emby for Kodi, dołączając dziennik zdarzeń Kodi." "go na forum Jellyfin for Kodi, dołączając dziennik zdarzeń Kodi."
msgctxt "#33129" msgctxt "#33129"
msgid "You can sync libraries by launching the Emby add-on > Add libraries." msgid "You can sync libraries by launching the Jellyfin add-on > Add libraries."
msgstr "" msgstr ""
"Możesz zsynchronizować biblioteki wybierając dodatek Emby > Dodaj biblioteki" "Możesz zsynchronizować biblioteki wybierając dodatek Jellyfin > Dodaj biblioteki"
msgctxt "#33130" msgctxt "#33130"
msgid "Select the source" msgid "Select the source"
@ -797,7 +789,7 @@ msgid ""
"remove content, you'll need to repair the library." "remove content, you'll need to repair the library."
msgstr "" msgstr ""
"Możesz ręcznie aktualizować bibliotekę zamiast polegać na wtyczce serwera " "Możesz ręcznie aktualizować bibliotekę zamiast polegać na wtyczce serwera "
"Kodi Companion. Wybierz \"Zaktualizuj biblioteki\" w dodatku Emby. Aby " "Kodi Companion. Wybierz \"Zaktualizuj biblioteki\" w dodatku Jellyfin. Aby "
"usunąć zawartość, należy naprawić biblioteki." "usunąć zawartość, należy naprawić biblioteki."
msgctxt "#33139" msgctxt "#33139"
@ -826,21 +818,21 @@ msgstr "Usuwanie biblioteki"
msgctxt "#33145" msgctxt "#33145"
msgid "" msgid ""
"Please make sure your Samba (smb) share of your Emby server is accessible to" "Please make sure your Samba (smb) share of your Jellyfin server is accessible to"
" your Kodi installation and that you have path substitution configured on " " your Kodi installation and that you have path substitution configured on "
"your server. Otherwise, Kodi may fail to locate your files." "your server. Otherwise, Kodi may fail to locate your files."
msgstr "" msgstr ""
"Upewnij się, że udział Samba (smb) twojego serwera Emby jest dostępny dla " "Upewnij się, że udział Samba (smb) twojego serwera Jellyfin jest dostępny dla "
"tej instalacji Kodi i udostępniony folder sieciowy jest skonfigurowany na " "tej instalacji Kodi i udostępniony folder sieciowy jest skonfigurowany na "
"serwerze. W przeciwnym razie Kodi może nie odnaleźć twoich plików." "serwerze. W przeciwnym razie Kodi może nie odnaleźć twoich plików."
msgctxt "#33146" msgctxt "#33146"
msgid "Unable to connect to Emby." msgid "Unable to connect to Jellyfin."
msgstr "Błąd połączenia z Emby" msgstr "Błąd połączenia z Jellyfin"
msgctxt "#33147" msgctxt "#33147"
msgid "Your access to Emby is restricted." msgid "Your access to Jellyfin is restricted."
msgstr "Dostęp do Emby jest ograniczony." msgstr "Dostęp do Jellyfin jest ograniczony."
msgctxt "#33148" msgctxt "#33148"
msgid "Your access to this server is restricted." msgid "Your access to this server is restricted."
@ -868,7 +860,7 @@ msgid "Unable to locate TV Tunes in Kodi."
msgstr "Nie znaleziono TV Tunes w Kodi." msgstr "Nie znaleziono TV Tunes w Kodi."
msgctxt "#33153" msgctxt "#33153"
msgid "Your Emby theme media has been synced to Kodi" msgid "Your Jellyfin theme media has been synced to Kodi"
msgstr "Media przewodnie zostały zsynchronizowane z Kodi" msgstr "Media przewodnie zostały zsynchronizowane z Kodi"
msgctxt "#33154" msgctxt "#33154"
@ -877,12 +869,12 @@ msgstr "Dodaj biblioteki"
msgctxt "#33155" msgctxt "#33155"
msgid "" msgid ""
"The currently applied patch for Emby for Kodi is corrupted! Please post to " "The currently applied patch for Jellyfin for Kodi is corrupted! Please post to "
"the Emby for Kodi forums if this issue persists. This will need to be fixed " "the Jellyfin for Kodi forums if this issue persists. This will need to be fixed "
"as soon as possible." "as soon as possible."
msgstr "" msgstr ""
"Zainstalowana poprawka Emby dla Kodi jest uszkodzona! Proszę zgłoś ten błąd " "Zainstalowana poprawka Jellyfin dla Kodi jest uszkodzona! Proszę zgłoś ten błąd "
"na forum Emby for Kodi jeśli problem się powtórzy. Konieczna jest szybka " "na forum Jellyfin for Kodi jeśli problem się powtórzy. Konieczna jest szybka "
"aktualizacja." "aktualizacja."
msgctxt "#33156" msgctxt "#33156"
@ -902,21 +894,13 @@ msgid "Enable audio/subtitles selection"
msgstr "Włącz wybór ścieżki dźwiękowej/napisów" msgstr "Włącz wybór ścieżki dźwiękowej/napisów"
msgctxt "#33160" msgctxt "#33160"
msgid "To avoid errors, please update Emby for Kodi to version: " msgid "To avoid errors, please update Jellyfin for Kodi to version: "
msgstr "Aby uniknąć błędów, należy zaktualizować Emby dla Kodi do wersji:" msgstr "Aby uniknąć błędów, należy zaktualizować Jellyfin dla Kodi do wersji:"
msgctxt "#33161"
msgid "Check for updates"
msgstr "Sprawdź aktualizacje"
msgctxt "#33162" msgctxt "#33162"
msgid "Reset the music library?" msgid "Reset the music library?"
msgstr "Zresetować bibliotekę muzyki?" msgstr "Zresetować bibliotekę muzyki?"
msgctxt "#33163"
msgid "Support this project"
msgstr "Wesprzyj projekt"
msgctxt "#33164" msgctxt "#33164"
msgid "Mask sensitive information in log (does not apply to kodi logging)" msgid "Mask sensitive information in log (does not apply to kodi logging)"
msgstr "" msgstr ""
@ -954,10 +938,10 @@ msgctxt "#33172"
msgid "" msgid ""
"You have {number} updates pending. This may take a little while before " "You have {number} updates pending. This may take a little while before "
"seeing new content. It might be faster to update your libraries via " "seeing new content. It might be faster to update your libraries via "
"launching the Emby add-on > update libraries. Proceed anyway?" "launching the Jellyfin add-on > update libraries. Proceed anyway?"
msgstr "" msgstr ""
"Do pobrania jest {number} aktualizacji. To może trochę potrwać. Szybszą " "Do pobrania jest {number} aktualizacji. To może trochę potrwać. Szybszą "
"opcją może być pełna aktualizacja w dodatku Emby > Aktualizuj biblioteki. " "opcją może być pełna aktualizacja w dodatku Jellyfin > Aktualizuj biblioteki. "
"Kontynuować mimo to?" "Kontynuować mimo to?"
msgctxt "#33173" msgctxt "#33173"
@ -970,7 +954,7 @@ msgstr "Paginacja - wątki pobierania (domyślnie: 3)"
msgctxt "#33175" msgctxt "#33175"
msgid "" msgid ""
"Paging tip: Each download thread requests your max items value from Emby at " "Paging tip: Each download thread requests your max items value from Jellyfin at "
"the same time." "the same time."
msgstr "" msgstr ""
"Paginacja: każdy z wątków pobiera maksymalną ilość pozycji w tym samym " "Paginacja: każdy z wątków pobiera maksymalną ilość pozycji w tym samym "
@ -993,8 +977,8 @@ msgid "Force transcode"
msgstr "Wymuś transkodowanie" msgstr "Wymuś transkodowanie"
msgctxt "#33180" msgctxt "#33180"
msgid "Restart Emby for Kodi" msgid "Restart Jellyfin for Kodi"
msgstr "Zrestartuj Emby dla Kodi" msgstr "Zrestartuj Jellyfin dla Kodi"
msgctxt "#33181" msgctxt "#33181"
msgid "Restarting to apply the patch" msgid "Restarting to apply the patch"
@ -1034,12 +1018,12 @@ msgid "Would you like to sync Rotten Tomatoes ratings?"
msgstr "Czy synchronizować ocenę z Rotten Tomatoes?" msgstr "Czy synchronizować ocenę z Rotten Tomatoes?"
msgctxt "#33191" msgctxt "#33191"
msgid "Restart Emby for Kodi to apply this change?" msgid "Restart Jellyfin for Kodi to apply this change?"
msgstr "Zrestartować Emby dla Kodi by zaaplikować tę zmianę?" msgstr "Zrestartować Jellyfin dla Kodi by zaaplikować tę zmianę?"
msgctxt "#33192" msgctxt "#33192"
msgid "Restart Emby for Kodi" msgid "Restart Jellyfin for Kodi"
msgstr "Zrestartuj Emby dla Kodi" msgstr "Zrestartuj Jellyfin dla Kodi"
msgctxt "#33193" msgctxt "#33193"
msgid "Restarting..." msgid "Restarting..."
@ -1050,7 +1034,7 @@ msgid "Manage libraries"
msgstr "Zarządzaj bibliotekami" msgstr "Zarządzaj bibliotekami"
msgctxt "#33195" msgctxt "#33195"
msgid "Enable Emby for Kodi" msgid "Enable Jellyfin for Kodi"
msgstr "" msgstr ""
msgctxt "#33196" msgctxt "#33196"

View file

@ -15,7 +15,7 @@ from helper.utils import create_id
################################################################################################## ##################################################################################################
LOG = logging.getLogger("EMBY."+__name__) LOG = logging.getLogger("JELLYFIN."+__name__)
################################################################################################## ##################################################################################################
@ -71,45 +71,45 @@ def get_device_name():
def get_device_id(reset=False): def get_device_id(reset=False):
''' Return the device_id if already loaded. ''' Return the device_id if already loaded.
It will load from emby_guid file. If it's a fresh It will load from jellyfin_guid file. If it's a fresh
setup, it will generate a new GUID to uniquely setup, it will generate a new GUID to uniquely
identify the setup for all users. identify the setup for all users.
window prop: emby_deviceId window prop: jellyfin_deviceId
''' '''
client_id = window('emby_deviceId') client_id = window('jellyfin_deviceId')
if client_id: if client_id:
return client_id return client_id
directory = xbmc.translatePath('special://profile/addon_data/plugin.video.emby/').decode('utf-8') directory = xbmc.translatePath('special://profile/addon_data/plugin.video.jellyfin/').decode('utf-8')
if not xbmcvfs.exists(directory): if not xbmcvfs.exists(directory):
xbmcvfs.mkdir(directory) xbmcvfs.mkdir(directory)
emby_guid = os.path.join(directory, "emby_guid") jellyfin_guid = os.path.join(directory, "jellyfin_guid")
file_guid = xbmcvfs.File(emby_guid) file_guid = xbmcvfs.File(jellyfin_guid)
client_id = file_guid.read() client_id = file_guid.read()
if not client_id or reset: if not client_id or reset:
LOG.info("Generating a new GUID.") LOG.info("Generating a new GUID.")
client_id = str("%012X" % create_id()) client_id = str("%012X" % create_id())
file_guid = xbmcvfs.File(emby_guid, 'w') file_guid = xbmcvfs.File(jellyfin_guid, 'w')
file_guid.write(client_id) file_guid.write(client_id)
file_guid.close() file_guid.close()
LOG.info("DeviceId loaded: %s", client_id) LOG.info("DeviceId loaded: %s", client_id)
window('emby_deviceId', value=client_id) window('jellyfin_deviceId', value=client_id)
return client_id return client_id
def reset_device_id(): def reset_device_id():
window('emby_deviceId', clear=True) window('jellyfin_deviceId', clear=True)
get_device_id(True) get_device_id(True)
dialog("ok", heading="{emby}", line1=_(33033)) dialog("ok", heading="{jellyfin}", line1=_(33033))
xbmc.executebuiltin('RestartApp') xbmc.executebuiltin('RestartApp')
def get_info(): def get_info():

View file

@ -12,15 +12,15 @@ import xbmcvfs
import client import client
from database import get_credentials, save_credentials from database import get_credentials, save_credentials
from dialogs import ServerConnect, UsersConnect, LoginConnect, LoginManual, ServerManual from dialogs import ServerConnect, UsersConnect, LoginManual, ServerManual
from helper import _, settings, addon_id, event, api, dialog, window from helper import _, settings, addon_id, event, api, dialog, window
from emby import Emby from jellyfin import Jellyfin
from emby.core.connection_manager import get_server_address, CONNECTION_STATE from jellyfin.core.connection_manager import get_server_address, CONNECTION_STATE
from emby.core.exceptions import HTTPException from jellyfin.core.exceptions import HTTPException
################################################################################################## ##################################################################################################
LOG = logging.getLogger("EMBY."+__name__) LOG = logging.getLogger("JELLYFIN."+__name__)
XML_PATH = (xbmcaddon.Addon(addon_id()).getAddonInfo('path'), "default", "1080i") XML_PATH = (xbmcaddon.Addon(addon_id()).getAddonInfo('path'), "default", "1080i")
################################################################################################## ##################################################################################################
@ -65,7 +65,7 @@ class Connect(object):
save_credentials(credentials) save_credentials(credentials)
try: try:
Emby(server_id).start(True) Jellyfin(server_id).start(True)
except ValueError as error: except ValueError as error:
LOG.error(error) LOG.error(error)
@ -78,11 +78,11 @@ class Connect(object):
def get_client(self, server_id=None): def get_client(self, server_id=None):
''' Get Emby client. ''' Get Jellyfin client.
''' '''
client = Emby(server_id) client = Jellyfin(server_id)
client['config/app']("Kodi", self.info['Version'], self.info['DeviceName'], self.info['DeviceId']) client['config/app']("Kodi", self.info['Version'], self.info['DeviceName'], self.info['DeviceId'])
client['config']['http.user_agent'] = "Emby-Kodi/%s" % self.info['Version'] client['config']['http.user_agent'] = "Jellyfin-Kodi/%s" % self.info['Version']
client['config']['auth.ssl'] = self.get_ssl() client['config']['auth.ssl'] = self.get_ssl()
return client return client
@ -115,7 +115,7 @@ class Connect(object):
return state['Credentials'] return state['Credentials']
elif (server_selection or state['State'] in (CONNECTION_STATE['ConnectSignIn'], CONNECTION_STATE['ServerSelection']) or elif (server_selection or state['State'] == CONNECTION_STATE['ServerSelection'] or
state['State'] == CONNECTION_STATE['Unavailable'] and not settings('SyncInstallRunDone.bool')): state['State'] == CONNECTION_STATE['Unavailable'] and not settings('SyncInstallRunDone.bool')):
self.select_servers(state) self.select_servers(state)
@ -152,20 +152,19 @@ class Connect(object):
settings('username', self.user['Name']) settings('username', self.user['Name'])
if 'PrimaryImageTag' in self.user: if 'PrimaryImageTag' in self.user:
window('EmbyUserImage', api.API(self.user, client['auth/server-address']).get_user_artwork(self.user['Id'])) window('JellyfinUserImage', api.API(self.user, client['auth/server-address']).get_user_artwork(self.user['Id']))
def select_servers(self, state=None): def select_servers(self, state=None):
state = state or self.connect_manager.connect({'enableAutoLogin': False}) state = state or self.connect_manager.connect({'enableAutoLogin': False})
user = state.get('ConnectUser') or {} user = {}
dialog = ServerConnect("script-emby-connect-server.xml", *XML_PATH) dialog = ServerConnect("script-jellyfin-connect-server.xml", *XML_PATH)
dialog.set_args(**{ dialog.set_args(**{
'connect_manager': self.connect_manager, 'connect_manager': self.connect_manager,
'username': user.get('DisplayName', ""), 'username': user.get('DisplayName', ""),
'user_image': user.get('ImageUrl'), 'user_image': user.get('ImageUrl'),
'servers': state.get('Servers', []), 'servers': state.get('Servers', [])
'emby_connect': False if user else True
}) })
dialog.doModal() dialog.doModal()
@ -173,12 +172,6 @@ class Connect(object):
LOG.debug("Server selected: %s", dialog.get_server()) LOG.debug("Server selected: %s", dialog.get_server())
return return
elif dialog.is_connect_login():
LOG.debug("Login with emby connect")
try:
self.login_connect()
except RuntimeError: pass
elif dialog.is_manual_server(): elif dialog.is_manual_server():
LOG.debug("Adding manual server") LOG.debug("Adding manual server")
try: try:
@ -209,7 +202,7 @@ class Connect(object):
''' Return server or raise error. ''' Return server or raise error.
''' '''
dialog = ServerManual("script-emby-connect-server-manual.xml", *XML_PATH) dialog = ServerManual("script-jellyfin-connect-server-manual.xml", *XML_PATH)
dialog.set_args(**{'connect_manager': manager or self.connect_manager}) dialog.set_args(**{'connect_manager': manager or self.connect_manager})
dialog.doModal() dialog.doModal()
@ -218,35 +211,6 @@ class Connect(object):
else: else:
raise RuntimeError("Server is not connected") raise RuntimeError("Server is not connected")
def setup_login_connect(self):
''' Setup emby connect by itself.
'''
client = self.get_client()
client.set_credentials(get_credentials())
manager = client.auth
try:
self.login_connect(manager)
except RuntimeError:
return
credentials = client.get_credentials()
save_credentials(credentials)
def login_connect(self, manager=None):
''' Return connect user or raise error.
'''
dialog = LoginConnect("script-emby-connect-login.xml", *XML_PATH)
dialog.set_args(**{'connect_manager': manager or self.connect_manager})
dialog.doModal()
if dialog.is_logged_in():
return dialog.get_user()
else:
raise RuntimeError("Connect user is not logged in")
def login(self): def login(self):
users = self.connect_manager['public-users'] users = self.connect_manager['public-users']
@ -258,7 +222,7 @@ class Connect(object):
except RuntimeError: except RuntimeError:
raise RuntimeError("No user selected") raise RuntimeError("No user selected")
dialog = UsersConnect("script-emby-connect-users.xml", *XML_PATH) dialog = UsersConnect("script-jellyfin-connect-users.xml", *XML_PATH)
dialog.set_args(**{'server': server, 'users': users}) dialog.set_args(**{'server': server, 'users': users})
dialog.doModal() dialog.doModal()
@ -303,7 +267,7 @@ class Connect(object):
''' Return manual login user authenticated or raise error. ''' Return manual login user authenticated or raise error.
''' '''
dialog = LoginManual("script-emby-connect-login-manual.xml", *XML_PATH) dialog = LoginManual("script-jellyfin-connect-login-manual.xml", *XML_PATH)
dialog.set_args(**{'connect_manager': manager or self.connect_manager, 'username': user or {}}) dialog.set_args(**{'connect_manager': manager or self.connect_manager, 'username': user or {}})
dialog.doModal() dialog.doModal()
@ -316,7 +280,7 @@ class Connect(object):
''' Stop client and remove server. ''' Stop client and remove server.
''' '''
Emby(server_id).close() Jellyfin(server_id).close()
credentials = get_credentials() credentials = get_credentials()
for server in credentials['Servers']: for server in credentials['Servers']:

View file

@ -11,14 +11,14 @@ import sqlite3
import xbmc import xbmc
import xbmcvfs import xbmcvfs
import emby_db import jellyfin_db
from helper.utils import delete_folder from helper.utils import delete_folder
from helper import _, settings, window, dialog from helper import _, settings, window, dialog
from objects import obj from objects import obj
################################################################################################# #################################################################################################
LOG = logging.getLogger("EMBY."+__name__) LOG = logging.getLogger("JELLYFIN."+__name__)
################################################################################################# #################################################################################################
@ -26,7 +26,7 @@ LOG = logging.getLogger("EMBY."+__name__)
class Database(object): class Database(object):
''' This should be called like a context. ''' This should be called like a context.
i.e. with Database('emby') as db: i.e. with Database('jellyfin') as db:
db.cursor db.cursor
db.conn.commit() db.conn.commit()
''' '''
@ -36,7 +36,7 @@ class Database(object):
def __init__(self, file=None, commit_close=True): def __init__(self, file=None, commit_close=True):
''' file: emby, texture, music, video, :memory: or path to file ''' file: jellyfin, texture, music, video, :memory: or path to file
''' '''
self.db_file = file or "video" self.db_file = file or "video"
self.commit_close = commit_close self.commit_close = commit_close
@ -50,15 +50,15 @@ class Database(object):
self.conn = sqlite3.connect(self.path, timeout=self.timeout) self.conn = sqlite3.connect(self.path, timeout=self.timeout)
self.cursor = self.conn.cursor() self.cursor = self.conn.cursor()
if self.db_file in ('video', 'music', 'texture', 'emby'): if self.db_file in ('video', 'music', 'texture', 'jellyfin'):
self.conn.execute("PRAGMA journal_mode=WAL") # to avoid writing conflict with kodi self.conn.execute("PRAGMA journal_mode=WAL") # to avoid writing conflict with kodi
LOG.debug("--->[ database: %s ] %s", self.db_file, id(self.conn)) LOG.debug("--->[ database: %s ] %s", self.db_file, id(self.conn))
if not window('emby_db_check.bool') and self.db_file == 'emby': if not window('jellyfin_db_check.bool') and self.db_file == 'jellyfin':
window('emby_db_check.bool', True) window('jellyfin_db_check.bool', True)
emby_tables(self.cursor) jellyfin_tables(self.cursor)
self.conn.commit() self.conn.commit()
return self return self
@ -183,47 +183,47 @@ class Database(object):
self.cursor.close() self.cursor.close()
self.conn.close() self.conn.close()
def emby_tables(cursor): def jellyfin_tables(cursor):
''' Create the tables for the emby database. ''' Create the tables for the jellyfin database.
emby, view, version jellyfin, view, version
''' '''
cursor.execute( cursor.execute(
"""CREATE TABLE IF NOT EXISTS emby( """CREATE TABLE IF NOT EXISTS jellyfin(
emby_id TEXT UNIQUE, media_folder TEXT, emby_type TEXT, media_type TEXT, jellyfin_id TEXT UNIQUE, media_folder TEXT, jellyfin_type TEXT, media_type TEXT,
kodi_id INTEGER, kodi_fileid INTEGER, kodi_pathid INTEGER, parent_id INTEGER, kodi_id INTEGER, kodi_fileid INTEGER, kodi_pathid INTEGER, parent_id INTEGER,
checksum INTEGER, emby_parent_id TEXT)""") checksum INTEGER, jellyfin_parent_id TEXT)""")
cursor.execute( cursor.execute(
"""CREATE TABLE IF NOT EXISTS view( """CREATE TABLE IF NOT EXISTS view(
view_id TEXT UNIQUE, view_name TEXT, media_type TEXT)""") view_id TEXT UNIQUE, view_name TEXT, media_type TEXT)""")
cursor.execute("CREATE TABLE IF NOT EXISTS version(idVersion TEXT)") cursor.execute("CREATE TABLE IF NOT EXISTS version(idVersion TEXT)")
columns = cursor.execute("SELECT * FROM emby") columns = cursor.execute("SELECT * FROM jellyfin")
if 'emby_parent_id' not in [description[0] for description in columns.description]: if 'jellyfin_parent_id' not in [description[0] for description in columns.description]:
LOG.info("Add missing column emby_parent_id") LOG.info("Add missing column jellyfin_parent_id")
cursor.execute("ALTER TABLE emby ADD COLUMN emby_parent_id 'TEXT'") cursor.execute("ALTER TABLE jellyfin ADD COLUMN jellyfin_parent_id 'TEXT'")
def reset(): def reset():
''' Reset both the emby database and the kodi database. ''' Reset both the jellyfin database and the kodi database.
''' '''
from views import Views from views import Views
views = Views() views = Views()
if not dialog("yesno", heading="{emby}", line1=_(33074)): if not dialog("yesno", heading="{jellyfin}", line1=_(33074)):
return return
window('emby_should_stop.bool', True) window('jellyfin_should_stop.bool', True)
count = 10 count = 10
while window('emby_sync.bool'): while window('jellyfin_sync.bool'):
LOG.info("Sync is running...") LOG.info("Sync is running...")
count -= 1 count -= 1
if not count: if not count:
dialog("ok", heading="{emby}", line1=_(33085)) dialog("ok", heading="{jellyfin}", line1=_(33085))
return return
@ -231,16 +231,16 @@ def reset():
return return
reset_kodi() reset_kodi()
reset_emby() reset_jellyfin()
views.delete_playlists() views.delete_playlists()
views.delete_nodes() views.delete_nodes()
if dialog("yesno", heading="{emby}", line1=_(33086)): if dialog("yesno", heading="{jellyfin}", line1=_(33086)):
reset_artwork() reset_artwork()
addon_data = xbmc.translatePath("special://profile/addon_data/plugin.video.emby/").decode('utf-8') addon_data = xbmc.translatePath("special://profile/addon_data/plugin.video.jellyfin/").decode('utf-8')
if dialog("yesno", heading="{emby}", line1=_(33087)): if dialog("yesno", heading="{jellyfin}", line1=_(33087)):
xbmcvfs.delete(os.path.join(addon_data, "settings.xml")) xbmcvfs.delete(os.path.join(addon_data, "settings.xml"))
xbmcvfs.delete(os.path.join(addon_data, "data.json")) xbmcvfs.delete(os.path.join(addon_data, "data.json"))
@ -253,7 +253,7 @@ def reset():
settings('MinimumSetup', "") settings('MinimumSetup', "")
settings('MusicRescan.bool', False) settings('MusicRescan.bool', False)
settings('SyncInstallRunDone.bool', False) settings('SyncInstallRunDone.bool', False)
dialog("ok", heading="{emby}", line1=_(33088)) dialog("ok", heading="{jellyfin}", line1=_(33088))
xbmc.executebuiltin('RestartApp') xbmc.executebuiltin('RestartApp')
def reset_kodi(): def reset_kodi():
@ -267,7 +267,7 @@ def reset_kodi():
if name != 'version': if name != 'version':
videodb.cursor.execute("DELETE FROM " + name) videodb.cursor.execute("DELETE FROM " + name)
if settings('enableMusic.bool') or dialog("yesno", heading="{emby}", line1=_(33162)): if settings('enableMusic.bool') or dialog("yesno", heading="{jellyfin}", line1=_(33162)):
with Database('music') as musicdb: with Database('music') as musicdb:
musicdb.cursor.execute("SELECT tbl_name FROM sqlite_master WHERE type='table'") musicdb.cursor.execute("SELECT tbl_name FROM sqlite_master WHERE type='table'")
@ -280,22 +280,22 @@ def reset_kodi():
LOG.warn("[ reset kodi ]") LOG.warn("[ reset kodi ]")
def reset_emby(): def reset_jellyfin():
with Database('emby') as embydb: with Database('jellyfin') as jellyfindb:
embydb.cursor.execute("SELECT tbl_name FROM sqlite_master WHERE type='table'") jellyfindb.cursor.execute("SELECT tbl_name FROM sqlite_master WHERE type='table'")
for table in embydb.cursor.fetchall(): for table in jellyfindb.cursor.fetchall():
name = table[0] name = table[0]
if name not in ('version', 'view'): if name not in ('version', 'view'):
embydb.cursor.execute("DELETE FROM " + name) jellyfindb.cursor.execute("DELETE FROM " + name)
embydb.cursor.execute("DROP table IF EXISTS emby") jellyfindb.cursor.execute("DROP table IF EXISTS jellyfin")
embydb.cursor.execute("DROP table IF EXISTS view") jellyfindb.cursor.execute("DROP table IF EXISTS view")
embydb.cursor.execute("DROP table IF EXISTS version") jellyfindb.cursor.execute("DROP table IF EXISTS version")
LOG.warn("[ reset emby ]") LOG.warn("[ reset jellyfin ]")
def reset_artwork(): def reset_artwork():
@ -326,7 +326,7 @@ def reset_artwork():
def get_sync(): def get_sync():
path = xbmc.translatePath("special://profile/addon_data/plugin.video.emby/").decode('utf-8') path = xbmc.translatePath("special://profile/addon_data/plugin.video.jellyfin/").decode('utf-8')
if not xbmcvfs.exists(path): if not xbmcvfs.exists(path):
xbmcvfs.mkdirs(path) xbmcvfs.mkdirs(path)
@ -346,7 +346,7 @@ def get_sync():
def save_sync(sync): def save_sync(sync):
path = xbmc.translatePath("special://profile/addon_data/plugin.video.emby/").decode('utf-8') path = xbmc.translatePath("special://profile/addon_data/plugin.video.jellyfin/").decode('utf-8')
if not xbmcvfs.exists(path): if not xbmcvfs.exists(path):
xbmcvfs.mkdirs(path) xbmcvfs.mkdirs(path)
@ -358,7 +358,7 @@ def save_sync(sync):
def get_credentials(): def get_credentials():
path = xbmc.translatePath("special://profile/addon_data/plugin.video.emby/").decode('utf-8') path = xbmc.translatePath("special://profile/addon_data/plugin.video.jellyfin/").decode('utf-8')
if not xbmcvfs.exists(path): if not xbmcvfs.exists(path):
xbmcvfs.mkdirs(path) xbmcvfs.mkdirs(path)
@ -382,9 +382,8 @@ def get_credentials():
return credentials return credentials
def save_credentials(credentials): def save_credentials(credentials):
credentials = credentials or {} credentials = credentials or {}
path = xbmc.translatePath("special://profile/addon_data/plugin.video.emby/").decode('utf-8') path = xbmc.translatePath("special://profile/addon_data/plugin.video.jellyfin/").decode('utf-8')
if not xbmcvfs.exists(path): if not xbmcvfs.exists(path):
xbmcvfs.mkdirs(path) xbmcvfs.mkdirs(path)
@ -394,13 +393,13 @@ def save_credentials(credentials):
def get_item(kodi_id, media): def get_item(kodi_id, media):
''' Get emby item based on kodi id and media. ''' Get jellyfin item based on kodi id and media.
''' '''
with Database('emby') as embydb: with Database('jellyfin') as jellyfindb:
item = emby_db.EmbyDatabase(embydb.cursor).get_full_item_by_kodi_id(kodi_id, media) item = jellyfin_db.JellyfinDatabase(jellyfindb.cursor).get_full_item_by_kodi_id(kodi_id, media)
if not item: if not item:
LOG.debug("Not an emby item") LOG.debug("Not an jellyfin item")
return return

View file

@ -8,12 +8,12 @@ import queries as QU
################################################################################################## ##################################################################################################
LOG = logging.getLogger("EMBY."+__name__) LOG = logging.getLogger("JELLYFIN."+__name__)
################################################################################################## ##################################################################################################
class EmbyDatabase(): class JellyfinDatabase():
def __init__(self, cursor): def __init__(self, cursor):

View file

@ -1,8 +1,8 @@
get_item = """ SELECT kodi_id, kodi_fileid, kodi_pathid, parent_id, media_type, get_item = """ SELECT kodi_id, kodi_fileid, kodi_pathid, parent_id, media_type,
emby_type, media_folder, emby_parent_id jellyfin_type, media_folder, jellyfin_parent_id
FROM emby FROM jellyfin
WHERE emby_id = ? WHERE jellyfin_id = ?
""" """
get_item_obj = [ "{Id}" get_item_obj = [ "{Id}"
] ]
@ -10,20 +10,20 @@ get_item_series_obj = [ "{SeriesId}"
] ]
get_item_song_obj = [ "{SongAlbumId}" get_item_song_obj = [ "{SongAlbumId}"
] ]
get_item_id_by_parent = """ SELECT emby_id, kodi_id get_item_id_by_parent = """ SELECT jellyfin_id, kodi_id
FROM emby FROM jellyfin
WHERE parent_id = ? WHERE parent_id = ?
AND media_type = ? AND media_type = ?
""" """
get_item_id_by_parent_boxset_obj = [ "{SetId}","movie" get_item_id_by_parent_boxset_obj = [ "{SetId}","movie"
] ]
get_item_by_parent = """ SELECT emby_id, kodi_id, kodi_fileid get_item_by_parent = """ SELECT jellyfin_id, kodi_id, kodi_fileid
FROM emby FROM jellyfin
WHERE parent_id = ? WHERE parent_id = ?
AND media_type = ? AND media_type = ?
""" """
get_item_by_media_folder = """ SELECT emby_id, emby_type get_item_by_media_folder = """ SELECT jellyfin_id, jellyfin_type
FROM emby FROM jellyfin
WHERE media_folder = ? WHERE media_folder = ?
""" """
get_item_by_parent_movie_obj = [ "{KodiId}","movie" get_item_by_parent_movie_obj = [ "{KodiId}","movie"
@ -39,31 +39,31 @@ get_item_by_parent_album_obj = [ "{ParentId}","album"
get_item_by_parent_song_obj = [ "{ParentId}","song" get_item_by_parent_song_obj = [ "{ParentId}","song"
] ]
get_item_by_wild = """ SELECT kodi_id, media_type get_item_by_wild = """ SELECT kodi_id, media_type
FROM emby FROM jellyfin
WHERE emby_id LIKE ? WHERE jellyfin_id LIKE ?
""" """
get_item_by_wild_obj = [ "{Id}" get_item_by_wild_obj = [ "{Id}"
] ]
get_item_by_kodi = """ SELECT emby_id, parent_id, media_folder, emby_type, checksum get_item_by_kodi = """ SELECT jellyfin_id, parent_id, media_folder, jellyfin_type, checksum
FROM emby FROM jellyfin
WHERE kodi_id = ? WHERE kodi_id = ?
AND media_type = ? AND media_type = ?
""" """
get_checksum = """ SELECT emby_id, checksum get_checksum = """ SELECT jellyfin_id, checksum
FROM emby FROM jellyfin
WHERE emby_type = ? WHERE jellyfin_type = ?
""" """
get_view_name = """ SELECT view_name get_view_name = """ SELECT view_name
FROM view FROM view
WHERE view_id = ? WHERE view_id = ?
""" """
get_media_by_id = """ SELECT emby_type get_media_by_id = """ SELECT jellyfin_type
FROM emby FROM jellyfin
WHERE emby_id = ? WHERE jellyfin_id = ?
""" """
get_media_by_parent_id = """ SELECT emby_id, emby_type, kodi_id, kodi_fileid get_media_by_parent_id = """ SELECT jellyfin_id, jellyfin_type, kodi_id, kodi_fileid
FROM emby FROM jellyfin
WHERE emby_parent_id = ? WHERE jellyfin_parent_id = ?
""" """
get_view = """ SELECT view_name, media_type get_view = """ SELECT view_name, media_type
FROM view FROM view
@ -76,8 +76,8 @@ get_views_by_media = """ SELECT *
FROM view FROM view
WHERE media_type = ? WHERE media_type = ?
""" """
get_items_by_media = """ SELECT emby_id get_items_by_media = """ SELECT jellyfin_id
FROM emby FROM jellyfin
WHERE media_type = ? WHERE media_type = ?
""" """
get_version = """ SELECT idVersion get_version = """ SELECT idVersion
@ -86,35 +86,35 @@ get_version = """ SELECT idVersion
add_reference = """ INSERT OR REPLACE INTO emby(emby_id, kodi_id, kodi_fileid, kodi_pathid, emby_type, add_reference = """ INSERT OR REPLACE INTO jellyfin(jellyfin_id, kodi_id, kodi_fileid, kodi_pathid, jellyfin_type,
media_type, parent_id, checksum, media_folder, emby_parent_id) media_type, parent_id, checksum, media_folder, jellyfin_parent_id)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
""" """
add_reference_movie_obj = [ "{Id}","{MovieId}","{FileId}","{PathId}","Movie","movie", None,"{Checksum}","{LibraryId}", add_reference_movie_obj = [ "{Id}","{MovieId}","{FileId}","{PathId}","Movie","movie", None,"{Checksum}","{LibraryId}",
"{EmbyParentId}" "{JellyfinParentId}"
] ]
add_reference_boxset_obj = [ "{Id}","{SetId}",None,None,"BoxSet","set",None,"{Checksum}",None,None add_reference_boxset_obj = [ "{Id}","{SetId}",None,None,"BoxSet","set",None,"{Checksum}",None,None
] ]
add_reference_tvshow_obj = [ "{Id}","{ShowId}",None,"{PathId}","Series","tvshow",None,"{Checksum}","{LibraryId}", add_reference_tvshow_obj = [ "{Id}","{ShowId}",None,"{PathId}","Series","tvshow",None,"{Checksum}","{LibraryId}",
"{EmbyParentId}" "{JellyfinParentId}"
] ]
add_reference_season_obj = [ "{Id}","{SeasonId}",None,None,"Season","season","{ShowId}",None,None,None add_reference_season_obj = [ "{Id}","{SeasonId}",None,None,"Season","season","{ShowId}",None,None,None
] ]
add_reference_pool_obj = [ "{SeriesId}","{ShowId}",None,"{PathId}","Series","tvshow",None,"{Checksum}","{LibraryId}",None add_reference_pool_obj = [ "{SeriesId}","{ShowId}",None,"{PathId}","Series","tvshow",None,"{Checksum}","{LibraryId}",None
] ]
add_reference_episode_obj = [ "{Id}","{EpisodeId}","{FileId}","{PathId}","Episode","episode","{SeasonId}","{Checksum}", add_reference_episode_obj = [ "{Id}","{EpisodeId}","{FileId}","{PathId}","Episode","episode","{SeasonId}","{Checksum}",
None,"{EmbyParentId}" None,"{JellyfinParentId}"
] ]
add_reference_mvideo_obj = [ "{Id}","{MvideoId}","{FileId}","{PathId}","MusicVideo","musicvideo",None,"{Checksum}", add_reference_mvideo_obj = [ "{Id}","{MvideoId}","{FileId}","{PathId}","MusicVideo","musicvideo",None,"{Checksum}",
"{LibraryId}","{EmbyParentId}" "{LibraryId}","{JellyfinParentId}"
] ]
add_reference_artist_obj = [ "{Id}","{ArtistId}",None,None,"{ArtistType}","artist",None,"{Checksum}","{LibraryId}", add_reference_artist_obj = [ "{Id}","{ArtistId}",None,None,"{ArtistType}","artist",None,"{Checksum}","{LibraryId}",
"{EmbyParentId}" "{JellyfinParentId}"
] ]
add_reference_album_obj = [ "{Id}","{AlbumId}",None,None,"MusicAlbum","album",None,"{Checksum}",None,"{EmbyParentId}" add_reference_album_obj = [ "{Id}","{AlbumId}",None,None,"MusicAlbum","album",None,"{Checksum}",None,"{JellyfinParentId}"
] ]
add_reference_song_obj = [ "{Id}","{SongId}",None,"{PathId}","Audio","song","{AlbumId}","{Checksum}", add_reference_song_obj = [ "{Id}","{SongId}",None,"{PathId}","Audio","song","{AlbumId}","{Checksum}",
None,"{EmbyParentId}" None,"{JellyfinParentId}"
] ]
add_view = """ INSERT OR REPLACE INTO view(view_id, view_name, media_type) add_view = """ INSERT OR REPLACE INTO view(view_id, view_name, media_type)
VALUES (?, ?, ?) VALUES (?, ?, ?)
@ -124,15 +124,15 @@ add_version = """ INSERT OR REPLACE INTO version(idVersion)
""" """
update_reference = """ UPDATE emby update_reference = """ UPDATE jellyfin
SET checksum = ? SET checksum = ?
WHERE emby_id = ? WHERE jellyfin_id = ?
""" """
update_reference_obj = [ "{Checksum}", "{Id}" update_reference_obj = [ "{Checksum}", "{Id}"
] ]
update_parent = """ UPDATE emby update_parent = """ UPDATE jellyfin
SET parent_id = ? SET parent_id = ?
WHERE emby_id = ? WHERE jellyfin_id = ?
""" """
update_parent_movie_obj = [ "{SetId}","{Id}" update_parent_movie_obj = [ "{SetId}","{Id}"
] ]
@ -142,12 +142,12 @@ update_parent_album_obj = [ "{ArtistId}","{AlbumId}"]
delete_item = """ DELETE FROM emby delete_item = """ DELETE FROM jellyfin
WHERE emby_id = ? WHERE jellyfin_id = ?
""" """
delete_item_obj = [ "{Id}" delete_item_obj = [ "{Id}"
] ]
delete_item_by_parent = """ DELETE FROM emby delete_item_by_parent = """ DELETE FROM jellyfin
WHERE parent_id = ? WHERE parent_id = ?
AND media_type = ? AND media_type = ?
""" """
@ -163,20 +163,20 @@ delete_item_by_parent_artist_obj = [ "{ParentId}","artist"
] ]
delete_item_by_parent_album_obj = [ "{KodiId}","album" delete_item_by_parent_album_obj = [ "{KodiId}","album"
] ]
delete_item_by_kodi = """ DELETE FROM emby delete_item_by_kodi = """ DELETE FROM jellyfin
WHERE kodi_id = ? WHERE kodi_id = ?
AND media_type = ? AND media_type = ?
""" """
delete_item_by_wild = """ DELETE FROM emby delete_item_by_wild = """ DELETE FROM jellyfin
WHERE emby_id LIKE ? WHERE jellyfin_id LIKE ?
""" """
delete_view = """ DELETE FROM view delete_view = """ DELETE FROM view
WHERE view_id = ? WHERE view_id = ?
""" """
delete_parent_boxset_obj = [ None, "{Movie}" delete_parent_boxset_obj = [ None, "{Movie}"
] ]
delete_media_by_parent_id = """ DELETE FROM emby delete_media_by_parent_id = """ DELETE FROM jellyfin
WHERE emby_parent_id = ? WHERE jellyfin_parent_id = ?
""" """
delete_version = """ DELETE FROM version delete_version = """ DELETE FROM version
""" """

View file

@ -1,5 +1,4 @@
from serverconnect import ServerConnect from serverconnect import ServerConnect
from usersconnect import UsersConnect from usersconnect import UsersConnect
from loginconnect import LoginConnect
from loginmanual import LoginManual from loginmanual import LoginManual
from servermanual import ServerManual from servermanual import ServerManual

View file

@ -12,7 +12,7 @@ from helper import window, addon_id
################################################################################################## ##################################################################################################
LOG = logging.getLogger("EMBY."+__name__) LOG = logging.getLogger("JELLYFIN."+__name__)
ACTION_PARENT_DIR = 9 ACTION_PARENT_DIR = 9
ACTION_PREVIOUS_MENU = 10 ACTION_PREVIOUS_MENU = 10
ACTION_BACK = 92 ACTION_BACK = 92
@ -45,8 +45,8 @@ class ContextMenu(xbmcgui.WindowXMLDialog):
def onInit(self): def onInit(self):
if window('EmbyUserImage'): if window('JellyfinUserImage'):
self.getControl(USER_IMAGE).setImage(window('EmbyUserImage')) self.getControl(USER_IMAGE).setImage(window('JellyfinUserImage'))
height = 479 + (len(self._options) * 55) height = 479 + (len(self._options) * 55)
LOG.info("options: %s", self._options) LOG.info("options: %s", self._options)

View file

@ -1,147 +0,0 @@
# -*- coding: utf-8 -*-
##################################################################################################
import logging
import os
import xbmcgui
import xbmcaddon
from helper import _, addon_id, settings, dialog
##################################################################################################
LOG = logging.getLogger("EMBY."+__name__)
ACTION_PARENT_DIR = 9
ACTION_PREVIOUS_MENU = 10
ACTION_BACK = 92
SIGN_IN = 200
CANCEL = 201
ERROR_TOGGLE = 202
ERROR_MSG = 203
ERROR = {
'Invalid': 1,
'Empty': 2
}
##################################################################################################
class LoginConnect(xbmcgui.WindowXMLDialog):
_user = None
error = None
def __init__(self, *args, **kwargs):
xbmcgui.WindowXMLDialog.__init__(self, *args, **kwargs)
def set_args(self, **kwargs):
# connect_manager, user_image, servers, emby_connect
for key, value in kwargs.iteritems():
setattr(self, key, value)
def is_logged_in(self):
return True if self._user else False
def get_user(self):
return self._user
def onInit(self):
self.user_field = self._add_editcontrol(755, 338, 40, 415)
self.setFocus(self.user_field)
self.password_field = self._add_editcontrol(755, 448, 40, 415, password=1)
self.signin_button = self.getControl(SIGN_IN)
self.remind_button = self.getControl(CANCEL)
self.error_toggle = self.getControl(ERROR_TOGGLE)
self.error_msg = self.getControl(ERROR_MSG)
self.user_field.controlUp(self.remind_button)
self.user_field.controlDown(self.password_field)
self.password_field.controlUp(self.user_field)
self.password_field.controlDown(self.signin_button)
self.signin_button.controlUp(self.password_field)
self.remind_button.controlDown(self.user_field)
def onClick(self, control):
if control == SIGN_IN:
# Sign in to emby connect
self._disable_error()
user = self.user_field.getText()
password = self.password_field.getText()
if not user or not password:
# Display error
self._error(ERROR['Empty'], _('empty_user_pass'))
LOG.error("Username or password cannot be null")
elif self._login(user, password):
self.close()
elif control == CANCEL:
# Remind me later
self.close()
def onAction(self, action):
if (self.error == ERROR['Empty']
and self.user_field.getText() and self.password_field.getText()):
self._disable_error()
if action in (ACTION_BACK, ACTION_PARENT_DIR, ACTION_PREVIOUS_MENU):
self.close()
def _add_editcontrol(self, x, y, height, width, password=0):
media = os.path.join(xbmcaddon.Addon(addon_id()).getAddonInfo('path'), 'resources', 'skins', 'default', 'media')
control = xbmcgui.ControlEdit(0, 0, 0, 0,
label="User",
font="font13",
textColor="FF52b54b",
disabledColor="FF888888",
focusTexture="-",
noFocusTexture="-",
isPassword=password)
control.setPosition(x, y)
control.setHeight(height)
control.setWidth(width)
self.addControl(control)
return control
def _login(self, username, password):
result = self.connect_manager['login-connect'](username, password)
if result is False:
self._error(ERROR['Invalid'], _('invalid_auth'))
return False
self._user = result
username = result['User']['Name']
settings('connectUsername', value=username)
settings('idMethod', value="1")
dialog("notification", heading="{emby}", message="%s %s" % (_(33000), username.decode('utf-8')),
icon=result['User'].get('ImageUrl') or "{emby}",
time=2000,
sound=False)
return True
def _error(self, state, message):
self.error = state
self.error_msg.setLabel(message)
self.error_toggle.setVisibleCondition('true')
def _disable_error(self):
self.error = None
self.error_toggle.setVisibleCondition('false')

View file

@ -12,7 +12,7 @@ from helper import _, addon_id
################################################################################################## ##################################################################################################
LOG = logging.getLogger("EMBY."+__name__) LOG = logging.getLogger("JELLYFIN."+__name__)
ACTION_PARENT_DIR = 9 ACTION_PARENT_DIR = 9
ACTION_PREVIOUS_MENU = 10 ACTION_PREVIOUS_MENU = 10
ACTION_BACK = 92 ACTION_BACK = 92
@ -36,7 +36,7 @@ class LoginManual(xbmcgui.WindowXMLDialog):
xbmcgui.WindowXMLDialog.__init__(self, *args, **kwargs) xbmcgui.WindowXMLDialog.__init__(self, *args, **kwargs)
def set_args(self, **kwargs): def set_args(self, **kwargs):
# connect_manager, user_image, servers, emby_connect # connect_manager, user_image, servers
for key, value in kwargs.iteritems(): for key, value in kwargs.iteritems():
setattr(self, key, value) setattr(self, key, value)
@ -72,7 +72,6 @@ class LoginManual(xbmcgui.WindowXMLDialog):
def onClick(self, control): def onClick(self, control):
if control == SIGN_IN: if control == SIGN_IN:
# Sign in to emby connect
self._disable_error() self._disable_error()
user = self.user_field.getText() user = self.user_field.getText()

View file

@ -10,7 +10,7 @@ import xbmcaddon
################################################################################################## ##################################################################################################
LOG = logging.getLogger("EMBY."+__name__) LOG = logging.getLogger("JELLYFIN."+__name__)
ACTION_PARENT_DIR = 9 ACTION_PARENT_DIR = 9
ACTION_PREVIOUS_MENU = 10 ACTION_PREVIOUS_MENU = 10
ACTION_BACK = 92 ACTION_BACK = 92

View file

@ -8,11 +8,11 @@ import xbmc
import xbmcgui import xbmcgui
from helper import _ from helper import _
from emby.core.connection_manager import CONNECTION_STATE from jellyfin.core.connection_manager import CONNECTION_STATE
################################################################################################## ##################################################################################################
LOG = logging.getLogger("EMBY."+__name__) LOG = logging.getLogger("JELLYFIN."+__name__)
ACTION_PARENT_DIR = 9 ACTION_PARENT_DIR = 9
ACTION_PREVIOUS_MENU = 10 ACTION_PREVIOUS_MENU = 10
ACTION_BACK = 92 ACTION_BACK = 92
@ -24,7 +24,6 @@ CANCEL = 201
MESSAGE_BOX = 202 MESSAGE_BOX = 202
MESSAGE = 203 MESSAGE = 203
BUSY = 204 BUSY = 204
EMBY_CONNECT = 205
MANUAL_SERVER = 206 MANUAL_SERVER = 206
################################################################################################## ##################################################################################################
@ -45,7 +44,7 @@ class ServerConnect(xbmcgui.WindowXMLDialog):
xbmcgui.WindowXMLDialog.__init__(self, *args, **kwargs) xbmcgui.WindowXMLDialog.__init__(self, *args, **kwargs)
def set_args(self, **kwargs): def set_args(self, **kwargs):
# connect_manager, user_image, servers, emby_connect # connect_manager, user_image, servers
for key, value in kwargs.iteritems(): for key, value in kwargs.iteritems():
setattr(self, key, value) setattr(self, key, value)
@ -55,13 +54,9 @@ class ServerConnect(xbmcgui.WindowXMLDialog):
def get_server(self): def get_server(self):
return self._selected_server return self._selected_server
def is_connect_login(self):
return self._connect_login
def is_manual_server(self): def is_manual_server(self):
return self._manual_server return self._manual_server
def onInit(self): def onInit(self):
self.message = self.getControl(MESSAGE) self.message = self.getControl(MESSAGE)
@ -76,9 +71,6 @@ class ServerConnect(xbmcgui.WindowXMLDialog):
if self.user_image is not None: if self.user_image is not None:
self.getControl(USER_IMAGE).setImage(self.user_image) self.getControl(USER_IMAGE).setImage(self.user_image)
if not self.emby_connect: # Change connect user
self.getControl(EMBY_CONNECT).setLabel("[B]%s[/B]" % _(30618))
if self.servers: if self.servers:
self.setFocus(self.list_) self.setFocus(self.list_)
@ -109,12 +101,7 @@ class ServerConnect(xbmcgui.WindowXMLDialog):
def onClick(self, control): def onClick(self, control):
if control == EMBY_CONNECT: if control == MANUAL_SERVER:
self.connect_manager.clear_data()
self._connect_login = True
self.close()
elif control == MANUAL_SERVER:
self._manual_server = True self._manual_server = True
self.close() self.close()

View file

@ -9,11 +9,11 @@ import xbmcgui
import xbmcaddon import xbmcaddon
from helper import _, addon_id from helper import _, addon_id
from emby.core.connection_manager import CONNECTION_STATE from jellyfin.core.connection_manager import CONNECTION_STATE
################################################################################################## ##################################################################################################
LOG = logging.getLogger("EMBY."+__name__) LOG = logging.getLogger("JELLYFIN."+__name__)
ACTION_PARENT_DIR = 9 ACTION_PARENT_DIR = 9
ACTION_PREVIOUS_MENU = 10 ACTION_PREVIOUS_MENU = 10
ACTION_BACK = 92 ACTION_BACK = 92
@ -40,7 +40,7 @@ class ServerManual(xbmcgui.WindowXMLDialog):
xbmcgui.WindowXMLDialog.__init__(self, *args, **kwargs) xbmcgui.WindowXMLDialog.__init__(self, *args, **kwargs)
def set_args(self, **kwargs): def set_args(self, **kwargs):
# connect_manager, user_image, servers, emby_connect # connect_manager, user_image, servers, jellyfin_connect
for key, value in kwargs.iteritems(): for key, value in kwargs.iteritems():
setattr(self, key, value) setattr(self, key, value)
@ -72,7 +72,6 @@ class ServerManual(xbmcgui.WindowXMLDialog):
def onClick(self, control): def onClick(self, control):
if control == CONNECT: if control == CONNECT:
# Sign in to emby connect
self._disable_error() self._disable_error()
server = self.host_field.getText() server = self.host_field.getText()

View file

@ -9,7 +9,7 @@ import xbmcgui
################################################################################################## ##################################################################################################
LOG = logging.getLogger("EMBY."+__name__) LOG = logging.getLogger("JELLYFIN."+__name__)
ACTION_PARENT_DIR = 9 ACTION_PARENT_DIR = 9
ACTION_PREVIOUS_MENU = 10 ACTION_PREVIOUS_MENU = 10
ACTION_BACK = 92 ACTION_BACK = 92
@ -34,7 +34,7 @@ class UsersConnect(xbmcgui.WindowXMLDialog):
xbmcgui.WindowXMLDialog.__init__(self, *args, **kwargs) xbmcgui.WindowXMLDialog.__init__(self, *args, **kwargs)
def set_args(self, **kwargs): def set_args(self, **kwargs):
# connect_manager, user_image, servers, emby_connect # connect_manager, user_image, servers
for key, value in kwargs.iteritems(): for key, value in kwargs.iteritems():
setattr(self, key, value) setattr(self, key, value)
@ -47,7 +47,6 @@ class UsersConnect(xbmcgui.WindowXMLDialog):
def is_manual_login(self): def is_manual_login(self):
return self._manual_login return self._manual_login
def onInit(self): def onInit(self):
self.list_ = self.getControl(LIST) self.list_ = self.getControl(LIST)

View file

@ -16,19 +16,19 @@ import xbmcaddon
import requests import requests
from helper.utils import should_stop, delete_folder from helper.utils import should_stop, delete_folder
from helper import settings, stop, event, window, kodi_version, unzip, create_id from helper import settings, stop, event, window, kodi_version, unzip, create_id
from emby import Emby from jellyfin import Jellyfin
from emby.core import api from jellyfin.core import api
from emby.core.exceptions import HTTPException from jellyfin.core.exceptions import HTTPException
################################################################################################# #################################################################################################
LOG = logging.getLogger("EMBY."+__name__) LOG = logging.getLogger("JELLYFIN."+__name__)
LIMIT = min(int(settings('limitIndex') or 50), 50) LIMIT = min(int(settings('limitIndex') or 50), 50)
CACHE = xbmc.translatePath(os.path.join(xbmcaddon.Addon(id='plugin.video.emby').getAddonInfo('profile').decode('utf-8'), 'emby')).decode('utf-8') CACHE = xbmc.translatePath(os.path.join(xbmcaddon.Addon(id='plugin.video.jellyfin').getAddonInfo('profile').decode('utf-8'), 'jellyfin')).decode('utf-8')
################################################################################################# #################################################################################################
def get_embyserver_url(handler): def get_jellyfinserver_url(handler):
if handler.startswith('/'): if handler.startswith('/'):
@ -46,16 +46,16 @@ def browse_info():
def _http(action, url, request={}, server_id=None): def _http(action, url, request={}, server_id=None):
request.update({'url': url, 'type': action}) request.update({'url': url, 'type': action})
return Emby(server_id)['http/request'](request) return Jellyfin(server_id)['http/request'](request)
def _get(handler, params=None, server_id=None): def _get(handler, params=None, server_id=None):
return _http("GET", get_embyserver_url(handler), {'params': params}, server_id) return _http("GET", get_jellyfinserver_url(handler), {'params': params}, server_id)
def _post(handler, json=None, params=None, server_id=None): def _post(handler, json=None, params=None, server_id=None):
return _http("POST", get_embyserver_url(handler), {'params': params, 'json': json}, server_id) return _http("POST", get_jellyfinserver_url(handler), {'params': params, 'json': json}, server_id)
def _delete(handler, params=None, server_id=None): def _delete(handler, params=None, server_id=None):
return _http("DELETE", get_embyserver_url(handler), {'params': params}, server_id) return _http("DELETE", get_jellyfinserver_url(handler), {'params': params}, server_id)
def validate_view(library_id, item_id): def validate_view(library_id, item_id):
@ -317,7 +317,7 @@ class GetItemWorker(threading.Thread):
self.queue.task_done() self.queue.task_done()
if window('emby_should_stop.bool'): if window('jellyfin_should_stop.bool'):
break break
class TheVoid(object): class TheVoid(object):
@ -342,16 +342,16 @@ class TheVoid(object):
while True: while True:
response = window('emby_%s.json' % self.data['VoidName']) response = window('jellyfin_%s.json' % self.data['VoidName'])
if response != "": if response != "":
LOG.debug("--<[ nostromo/emby_%s.json ]", self.data['VoidName']) LOG.debug("--<[ nostromo/jellyfin_%s.json ]", self.data['VoidName'])
window('emby_%s' % self.data['VoidName'], clear=True) window('jellyfin_%s' % self.data['VoidName'], clear=True)
return response return response
if window('emby_should_stop.bool'): if window('jellyfin_should_stop.bool'):
LOG.info("Abandon mission! A black hole just swallowed [ %s/%s ]", self.method, self.data['VoidName']) LOG.info("Abandon mission! A black hole just swallowed [ %s/%s ]", self.method, self.data['VoidName'])
return return

View file

@ -8,14 +8,14 @@ import xbmc
import xbmcvfs import xbmcvfs
from helper import loghandler from helper import loghandler
from emby import Emby from jellyfin import Jellyfin
################################################################################################# #################################################################################################
Emby.set_loghandler(loghandler.LogHandler, logging.DEBUG) Jellyfin.set_loghandler(loghandler.LogHandler, logging.DEBUG)
loghandler.reset() loghandler.reset()
loghandler.config() loghandler.config()
LOG = logging.getLogger('EMBY.entrypoint') LOG = logging.getLogger('JELLYFIN.entrypoint')
################################################################################################# #################################################################################################

View file

@ -17,8 +17,8 @@ from objects import Actions
################################################################################################# #################################################################################################
LOG = logging.getLogger("EMBY."+__name__) LOG = logging.getLogger("JELLYFIN."+__name__)
XML_PATH = (xbmcaddon.Addon('plugin.video.emby').getAddonInfo('path'), "default", "1080i") XML_PATH = (xbmcaddon.Addon('plugin.video.jellyfin').getAddonInfo('path'), "default", "1080i")
OPTIONS = { OPTIONS = {
'Refresh': _(30410), 'Refresh': _(30410),
'Delete': _(30409), 'Delete': _(30409),
@ -40,13 +40,13 @@ class Context(object):
try: try:
self.kodi_id = sys.listitem.getVideoInfoTag().getDbId() or None self.kodi_id = sys.listitem.getVideoInfoTag().getDbId() or None
self.media = self.get_media_type() self.media = self.get_media_type()
self.server = sys.listitem.getProperty('embyserver') or None self.server = sys.listitem.getProperty('jellyfinserver') or None
item_id = sys.listitem.getProperty('embyid') item_id = sys.listitem.getProperty('jellyfinid')
except AttributeError: except AttributeError:
self.server = None self.server = None
if xbmc.getInfoLabel('ListItem.Property(embyid)'): if xbmc.getInfoLabel('ListItem.Property(jellyfinid)'):
item_id = xbmc.getInfoLabel('ListItem.Property(embyid)') item_id = xbmc.getInfoLabel('ListItem.Property(jellyfinid)')
else: else:
self.kodi_id = xbmc.getInfoLabel('ListItem.DBID') self.kodi_id = xbmc.getInfoLabel('ListItem.DBID')
self.media = xbmc.getInfoLabel('ListItem.DBTYPE') self.media = xbmc.getInfoLabel('ListItem.DBTYPE')
@ -96,7 +96,7 @@ class Context(object):
def get_item_id(self): def get_item_id(self):
''' Get synced item from embydb. ''' Get synced item from jellyfindb.
''' '''
item = database.get_item(self.kodi_id, self.media) item = database.get_item(self.kodi_id, self.media)
@ -130,7 +130,7 @@ class Context(object):
options.append(OPTIONS['Addon']) options.append(OPTIONS['Addon'])
context_menu = context.ContextMenu("script-emby-context.xml", *XML_PATH) context_menu = context.ContextMenu("script-jellyfin-context.xml", *XML_PATH)
context_menu.set_options(options) context_menu.set_options(options)
context_menu.doModal() context_menu.doModal()
@ -153,7 +153,7 @@ class Context(object):
TheVoid('FavoriteItem', {'ServerId': self.server, 'Id': self.item['Id'], 'Favorite': False}) TheVoid('FavoriteItem', {'ServerId': self.server, 'Id': self.item['Id'], 'Favorite': False})
elif selected == OPTIONS['Addon']: elif selected == OPTIONS['Addon']:
xbmc.executebuiltin('Addon.OpenSettings(plugin.video.emby)') xbmc.executebuiltin('Addon.OpenSettings(plugin.video.jellyfin)')
elif selected == OPTIONS['Delete']: elif selected == OPTIONS['Delete']:
self.delete_item() self.delete_item()
@ -164,7 +164,7 @@ class Context(object):
if not settings('skipContextMenu.bool'): if not settings('skipContextMenu.bool'):
if not dialog("yesno", heading="{emby}", line1=_(33015)): if not dialog("yesno", heading="{jellyfin}", line1=_(33015)):
delete = False delete = False
if delete: if delete:

View file

@ -17,14 +17,14 @@ import xbmcplugin
import xbmcaddon import xbmcaddon
import client import client
from database import reset, get_sync, Database, emby_db, get_credentials from database import reset, get_sync, Database, jellyfin_db, get_credentials
from objects import Objects, Actions from objects import Objects, Actions
from downloader import TheVoid from downloader import TheVoid
from helper import _, event, settings, window, dialog, api, JSONRPC from helper import _, event, settings, window, dialog, api, JSONRPC
################################################################################################# #################################################################################################
LOG = logging.getLogger("EMBY."+__name__) LOG = logging.getLogger("JELLYFIN."+__name__)
################################################################################################# #################################################################################################
@ -55,15 +55,15 @@ class Events(object):
if '/extrafanart' in base_url: if '/extrafanart' in base_url:
emby_path = path[1:] jellyfin_path = path[1:]
emby_id = params.get('id') jellyfin_id = params.get('id')
get_fanart(emby_id, emby_path, server) get_fanart(jellyfin_id, jellyfin_path, server)
elif '/Extras' in base_url or '/VideoFiles' in base_url: elif '/Extras' in base_url or '/VideoFiles' in base_url:
emby_path = path[1:] jellyfin_path = path[1:]
emby_id = params.get('id') jellyfin_id = params.get('id')
get_video_extras(emby_id, emby_path, server) get_video_extras(jellyfin_id, jellyfin_path, server)
elif mode =='play': elif mode =='play':
@ -100,8 +100,6 @@ class Events(object):
event('RemoveLibrarySelection') event('RemoveLibrarySelection')
elif mode == 'addlibs': elif mode == 'addlibs':
event('AddLibrarySelection') event('AddLibrarySelection')
elif mode == 'connect':
event('EmbyConnect')
elif mode == 'addserver': elif mode == 'addserver':
event('AddServer') event('AddServer')
elif mode == 'login': elif mode == 'login':
@ -109,11 +107,9 @@ class Events(object):
elif mode == 'removeserver': elif mode == 'removeserver':
event('RemoveServer', {'Id': server}) event('RemoveServer', {'Id': server})
elif mode == 'settings': elif mode == 'settings':
xbmc.executebuiltin('Addon.OpenSettings(plugin.video.emby)') xbmc.executebuiltin('Addon.OpenSettings(plugin.video.jellyfin)')
elif mode == 'adduser': elif mode == 'adduser':
add_user() add_user()
elif mode == 'checkupdate':
event('CheckUpdate')
elif mode == 'updateserver': elif mode == 'updateserver':
event('UpdateServer') event('UpdateServer')
elif mode == 'thememedia': elif mode == 'thememedia':
@ -123,23 +119,23 @@ class Events(object):
elif mode == 'backup': elif mode == 'backup':
backup() backup()
elif mode == 'restartservice': elif mode == 'restartservice':
window('emby.restart.bool', True) window('jellyfin.restart.bool', True)
else: else:
listing() listing()
def listing(): def listing():
''' Display all emby nodes and dynamic entries when appropriate. ''' Display all jellyfin nodes and dynamic entries when appropriate.
''' '''
total = int(window('Emby.nodes.total') or 0) total = int(window('Jellyfin.nodes.total') or 0)
sync = get_sync() sync = get_sync()
whitelist = [x.replace('Mixed:', "") for x in sync['Whitelist']] whitelist = [x.replace('Mixed:', "") for x in sync['Whitelist']]
servers = get_credentials()['Servers'][1:] servers = get_credentials()['Servers'][1:]
for i in range(total): for i in range(total):
window_prop = "Emby.nodes.%s" % i window_prop = "Jellyfin.nodes.%s" % i
path = window('%s.index' % window_prop) path = window('%s.index' % window_prop)
if not path: if not path:
@ -153,13 +149,13 @@ def listing():
if view_id and node in ('movies', 'tvshows', 'musicvideos', 'music', 'mixed') and view_id not in whitelist: if view_id and node in ('movies', 'tvshows', 'musicvideos', 'music', 'mixed') and view_id not in whitelist:
label = "%s %s" % (label.decode('utf-8'), _(33166)) label = "%s %s" % (label.decode('utf-8'), _(33166))
context.append((_(33123), "RunPlugin(plugin://plugin.video.emby/?mode=synclib&id=%s)" % view_id)) context.append((_(33123), "RunPlugin(plugin://plugin.video.jellyfin/?mode=synclib&id=%s)" % view_id))
if view_id and node in ('movies', 'tvshows', 'musicvideos', 'music') and view_id in whitelist: if view_id and node in ('movies', 'tvshows', 'musicvideos', 'music') and view_id in whitelist:
context.append((_(33136), "RunPlugin(plugin://plugin.video.emby/?mode=updatelib&id=%s)" % view_id)) context.append((_(33136), "RunPlugin(plugin://plugin.video.jellyfin/?mode=updatelib&id=%s)" % view_id))
context.append((_(33132), "RunPlugin(plugin://plugin.video.emby/?mode=repairlib&id=%s)" % view_id)) context.append((_(33132), "RunPlugin(plugin://plugin.video.jellyfin/?mode=repairlib&id=%s)" % view_id))
context.append((_(33133), "RunPlugin(plugin://plugin.video.emby/?mode=removelib&id=%s)" % view_id)) context.append((_(33133), "RunPlugin(plugin://plugin.video.jellyfin/?mode=removelib&id=%s)" % view_id))
LOG.debug("--[ listing/%s/%s ] %s", node, label, path) LOG.debug("--[ listing/%s/%s ] %s", node, label, path)
@ -177,25 +173,23 @@ def listing():
context = [] context = []
if server.get('ManualAddress'): if server.get('ManualAddress'):
context.append((_(33141), "RunPlugin(plugin://plugin.video.emby/?mode=removeserver&server=%s)" % server['Id'])) context.append((_(33141), "RunPlugin(plugin://plugin.video.jellyfin/?mode=removeserver&server=%s)" % server['Id']))
if 'AccessToken' not in server: if 'AccessToken' not in server:
directory("%s (%s)" % (server['Name'], _(30539)), "plugin://plugin.video.emby/?mode=login&server=%s" % server['Id'], False, context=context) directory("%s (%s)" % (server['Name'], _(30539)), "plugin://plugin.video.jellyfin/?mode=login&server=%s" % server['Id'], False, context=context)
else: else:
directory(server['Name'], "plugin://plugin.video.emby/?mode=browse&server=%s" % server['Id'], context=context) directory(server['Name'], "plugin://plugin.video.jellyfin/?mode=browse&server=%s" % server['Id'], context=context)
directory(_(33194), "plugin://plugin.video.emby/?mode=managelibs", True) directory(_(33194), "plugin://plugin.video.jellyfin/?mode=managelibs", True)
directory(_(33134), "plugin://plugin.video.emby/?mode=addserver", False) directory(_(33134), "plugin://plugin.video.jellyfin/?mode=addserver", False)
directory(_(33054), "plugin://plugin.video.emby/?mode=adduser", False) directory(_(33054), "plugin://plugin.video.jellyfin/?mode=adduser", False)
directory(_(5), "plugin://plugin.video.emby/?mode=settings", False) directory(_(5), "plugin://plugin.video.jellyfin/?mode=settings", False)
directory(_(33058), "plugin://plugin.video.emby/?mode=reset", False) directory(_(33058), "plugin://plugin.video.jellyfin/?mode=reset", False)
directory(_(33192), "plugin://plugin.video.emby/?mode=restartservice", False) directory(_(33192), "plugin://plugin.video.jellyfin/?mode=restartservice", False)
if settings('backupPath'): if settings('backupPath'):
directory(_(33092), "plugin://plugin.video.emby/?mode=backup", False) directory(_(33092), "plugin://plugin.video.jellyfin/?mode=backup", False)
directory(_(33163), None, False, artwork="special://home/addons/plugin.video.emby/donations.png")
xbmcplugin.setContent(int(sys.argv[1]), 'files') xbmcplugin.setContent(int(sys.argv[1]), 'files')
xbmcplugin.endOfDirectory(int(sys.argv[1])) xbmcplugin.endOfDirectory(int(sys.argv[1]))
@ -216,20 +210,20 @@ def directory(label, path, folder=True, artwork=None, fanart=None, context=None)
def dir_listitem(label, path, artwork=None, fanart=None): def dir_listitem(label, path, artwork=None, fanart=None):
li = xbmcgui.ListItem(label, path=path) li = xbmcgui.ListItem(label, path=path)
li.setThumbnailImage(artwork or "special://home/addons/plugin.video.emby/icon.png") li.setThumbnailImage(artwork or "special://home/addons/plugin.video.jellyfin/icon.png")
li.setArt({"fanart": fanart or "special://home/addons/plugin.video.emby/fanart.jpg"}) li.setArt({"fanart": fanart or "special://home/addons/plugin.video.jellyfin/fanart.jpg"})
li.setArt({"landscape": artwork or fanart or "special://home/addons/plugin.video.emby/fanart.jpg"}) li.setArt({"landscape": artwork or fanart or "special://home/addons/plugin.video.jellyfin/fanart.jpg"})
return li return li
def manage_libraries(): def manage_libraries():
directory(_(33098), "plugin://plugin.video.emby/?mode=refreshboxsets", False) directory(_(33098), "plugin://plugin.video.jellyfin/?mode=refreshboxsets", False)
directory(_(33154), "plugin://plugin.video.emby/?mode=addlibs", False) directory(_(33154), "plugin://plugin.video.jellyfin/?mode=addlibs", False)
directory(_(33139), "plugin://plugin.video.emby/?mode=updatelibs", False) directory(_(33139), "plugin://plugin.video.jellyfin/?mode=updatelibs", False)
directory(_(33140), "plugin://plugin.video.emby/?mode=repairlibs", False) directory(_(33140), "plugin://plugin.video.jellyfin/?mode=repairlibs", False)
directory(_(33184), "plugin://plugin.video.emby/?mode=removelibs", False) directory(_(33184), "plugin://plugin.video.jellyfin/?mode=removelibs", False)
directory(_(33060), "plugin://plugin.video.emby/?mode=thememedia", False) directory(_(33060), "plugin://plugin.video.jellyfin/?mode=thememedia", False)
xbmcplugin.setContent(int(sys.argv[1]), 'files') xbmcplugin.setContent(int(sys.argv[1]), 'files')
xbmcplugin.endOfDirectory(int(sys.argv[1])) xbmcplugin.endOfDirectory(int(sys.argv[1]))
@ -240,12 +234,12 @@ def browse(media, view_id=None, folder=None, server_id=None):
''' '''
LOG.info("--[ v:%s/%s ] %s", view_id, media, folder) LOG.info("--[ v:%s/%s ] %s", view_id, media, folder)
if not window('emby_online.bool') and server_id is None: if not window('jellyfin_online.bool') and server_id is None:
monitor = xbmc.Monitor() monitor = xbmc.Monitor()
for i in range(300): for i in range(300):
if window('emby_online.bool'): if window('jellyfin_online.bool'):
break break
elif monitor.waitForAbort(0.1): elif monitor.waitForAbort(0.1):
return return
@ -330,8 +324,8 @@ def browse(media, view_id=None, folder=None, server_id=None):
for item in listing: for item in listing:
li = xbmcgui.ListItem() li = xbmcgui.ListItem()
li.setProperty('embyid', item['Id']) li.setProperty('jellyfinid', item['Id'])
li.setProperty('embyserver', server_id) li.setProperty('jellyfinserver', server_id)
actions.set_listitem(item, li) actions.set_listitem(item, li)
if item.get('IsFolder'): if item.get('IsFolder'):
@ -343,16 +337,16 @@ def browse(media, view_id=None, folder=None, server_id=None):
'folder': item['Id'], 'folder': item['Id'],
'server': server_id 'server': server_id
} }
path = "%s?%s" % ("plugin://plugin.video.emby/", urllib.urlencode(params)) path = "%s?%s" % ("plugin://plugin.video.jellyfin/", urllib.urlencode(params))
context = [] context = []
if item['Type'] in ('Series', 'Season', 'Playlist'): if item['Type'] in ('Series', 'Season', 'Playlist'):
context.append(("Play", "RunPlugin(plugin://plugin.video.emby/?mode=playlist&id=%s&server=%s)" % (item['Id'], server_id))) context.append(("Play", "RunPlugin(plugin://plugin.video.jellyfin/?mode=playlist&id=%s&server=%s)" % (item['Id'], server_id)))
if item['UserData']['Played']: if item['UserData']['Played']:
context.append((_(16104), "RunPlugin(plugin://plugin.video.emby/?mode=unwatched&id=%s&server=%s)" % (item['Id'], server_id))) context.append((_(16104), "RunPlugin(plugin://plugin.video.jellyfin/?mode=unwatched&id=%s&server=%s)" % (item['Id'], server_id)))
else: else:
context.append((_(16103), "RunPlugin(plugin://plugin.video.emby/?mode=watched&id=%s&server=%s)" % (item['Id'], server_id))) context.append((_(16103), "RunPlugin(plugin://plugin.video.jellyfin/?mode=watched&id=%s&server=%s)" % (item['Id'], server_id)))
li.addContextMenuItems(context) li.addContextMenuItems(context)
list_li.append((path, li, True)) list_li.append((path, li, True))
@ -366,7 +360,7 @@ def browse(media, view_id=None, folder=None, server_id=None):
'folder': 'genres-%s' % item['Id'], 'folder': 'genres-%s' % item['Id'],
'server': server_id 'server': server_id
} }
path = "%s?%s" % ("plugin://plugin.video.emby/", urllib.urlencode(params)) path = "%s?%s" % ("plugin://plugin.video.jellyfin/", urllib.urlencode(params))
list_li.append((path, li, True)) list_li.append((path, li, True))
else: else:
@ -376,14 +370,14 @@ def browse(media, view_id=None, folder=None, server_id=None):
'mode': "play", 'mode': "play",
'server': server_id 'server': server_id
} }
path = "%s?%s" % ("plugin://plugin.video.emby/", urllib.urlencode(params)) path = "%s?%s" % ("plugin://plugin.video.jellyfin/", urllib.urlencode(params))
li.setProperty('path', path) li.setProperty('path', path)
context = [(_(13412), "RunPlugin(plugin://plugin.video.emby/?mode=playlist&id=%s&server=%s)" % (item['Id'], server_id))] context = [(_(13412), "RunPlugin(plugin://plugin.video.jellyfin/?mode=playlist&id=%s&server=%s)" % (item['Id'], server_id))]
if item['UserData']['Played']: if item['UserData']['Played']:
context.append((_(16104), "RunPlugin(plugin://plugin.video.emby/?mode=unwatched&id=%s&server=%s)" % (item['Id'], server_id))) context.append((_(16104), "RunPlugin(plugin://plugin.video.jellyfin/?mode=unwatched&id=%s&server=%s)" % (item['Id'], server_id)))
else: else:
context.append((_(16103), "RunPlugin(plugin://plugin.video.emby/?mode=watched&id=%s&server=%s)" % (item['Id'], server_id))) context.append((_(16103), "RunPlugin(plugin://plugin.video.jellyfin/?mode=watched&id=%s&server=%s)" % (item['Id'], server_id)))
li.addContextMenuItems(context) li.addContextMenuItems(context)
@ -402,7 +396,7 @@ def browse(media, view_id=None, folder=None, server_id=None):
def browse_subfolders(media, view_id, server_id=None): def browse_subfolders(media, view_id, server_id=None):
''' Display submenus for emby views. ''' Display submenus for jellyfin views.
''' '''
from views import DYNNODES from views import DYNNODES
@ -419,7 +413,7 @@ def browse_subfolders(media, view_id, server_id=None):
'folder': view_id if node[0] == 'all' else node[0], 'folder': view_id if node[0] == 'all' else node[0],
'server': server_id 'server': server_id
} }
path = "%s?%s" % ("plugin://plugin.video.emby/", urllib.urlencode(params)) path = "%s?%s" % ("plugin://plugin.video.jellyfin/", urllib.urlencode(params))
directory(node[1] or view['Name'], path) directory(node[1] or view['Name'], path)
xbmcplugin.setContent(int(sys.argv[1]), 'files') xbmcplugin.setContent(int(sys.argv[1]), 'files')
@ -443,7 +437,7 @@ def browse_letters(media, view_id, server_id=None):
'folder': 'firstletter-%s' % node, 'folder': 'firstletter-%s' % node,
'server': server_id 'server': server_id
} }
path = "%s?%s" % ("plugin://plugin.video.emby/", urllib.urlencode(params)) path = "%s?%s" % ("plugin://plugin.video.jellyfin/", urllib.urlencode(params))
directory(node, path) directory(node, path)
xbmcplugin.setContent(int(sys.argv[1]), 'files') xbmcplugin.setContent(int(sys.argv[1]), 'files')
@ -489,7 +483,7 @@ def get_fanart(item_id, path, server_id=None):
''' Get extra fanart for listitems. This is called by skinhelper. ''' Get extra fanart for listitems. This is called by skinhelper.
Images are stored locally, due to the Kodi caching system. Images are stored locally, due to the Kodi caching system.
''' '''
if not item_id and 'plugin.video.emby' in path: if not item_id and 'plugin.video.jellyfin' in path:
item_id = path.split('/')[-2] item_id = path.split('/')[-2]
if not item_id: if not item_id:
@ -498,7 +492,7 @@ def get_fanart(item_id, path, server_id=None):
LOG.info("[ extra fanart ] %s", item_id) LOG.info("[ extra fanart ] %s", item_id)
objects = Objects() objects = Objects()
list_li = [] list_li = []
directory = xbmc.translatePath("special://thumbnails/emby/%s/" % item_id).decode('utf-8') directory = xbmc.translatePath("special://thumbnails/jellyfin/%s/" % item_id).decode('utf-8')
server = TheVoid('GetServerAddress', {'ServerId': server_id}).get() server = TheVoid('GetServerAddress', {'ServerId': server_id}).get()
if not xbmcvfs.exists(directory): if not xbmcvfs.exists(directory):
@ -533,7 +527,7 @@ def get_video_extras(item_id, path, server_id=None):
''' Returns the video files for the item as plugin listing, can be used ''' Returns the video files for the item as plugin listing, can be used
to browse actual files or video extras, etc. to browse actual files or video extras, etc.
''' '''
if not item_id and 'plugin.video.emby' in path: if not item_id and 'plugin.video.jellyfin' in path:
item_id = path.split('/')[-2] item_id = path.split('/')[-2]
if not item_id: if not item_id:
@ -543,14 +537,14 @@ def get_video_extras(item_id, path, server_id=None):
# TODO # TODO
""" """
def getVideoFiles(embyId,embyPath): def getVideoFiles(jellyfinId,jellyfinPath):
#returns the video files for the item as plugin listing, can be used for browsing the actual files or videoextras etc. #returns the video files for the item as plugin listing, can be used for browsing the actual files or videoextras etc.
emby = embyserver.Read_EmbyServer() jellyfin = jellyfinserver.Read_JellyfinServer()
if not embyId: if not jellyfinId:
if "plugin.video.emby" in embyPath: if "plugin.video.jellyfin" in jellyfinPath:
embyId = embyPath.split("/")[-2] jellyfinId = jellyfinPath.split("/")[-2]
if embyId: if jellyfinId:
item = emby.getItem(embyId) item = jellyfin.getItem(jellyfinId)
putils = playutils.PlayUtils(item) putils = playutils.PlayUtils(item)
if putils.isDirectPlay(): if putils.isDirectPlay():
#only proceed if we can access the files directly. TODO: copy local on the fly if accessed outside #only proceed if we can access the files directly. TODO: copy local on the fly if accessed outside
@ -573,9 +567,9 @@ def get_next_episodes(item_id, limit):
''' Only for synced content. ''' Only for synced content.
''' '''
with Database('emby') as embydb: with Database('jellyfin') as jellyfindb:
db = emby_db.EmbyDatabase(embydb.cursor) db = jellyfin_db.JellyfinDatabase(jellyfindb.cursor)
library = db.get_view_name(item_id) library = db.get_view_name(item_id)
if not library: if not library:
@ -730,7 +724,7 @@ def add_user():
''' Add or remove users from the default server session. ''' Add or remove users from the default server session.
''' '''
if not window('emby_online.bool'): if not window('jellyfin_online.bool'):
return return
session = TheVoid('GetSession', {}).get() session = TheVoid('GetSession', {}).get()
@ -769,7 +763,7 @@ def get_themes():
from helper.playutils import PlayUtils from helper.playutils import PlayUtils
from helper.xmls import tvtunes_nfo from helper.xmls import tvtunes_nfo
library = xbmc.translatePath("special://profile/addon_data/plugin.video.emby/library").decode('utf-8') library = xbmc.translatePath("special://profile/addon_data/plugin.video.jellyfin/library").decode('utf-8')
play = settings('useDirectPaths') == "1" play = settings('useDirectPaths') == "1"
if not xbmcvfs.exists(library + '/'): if not xbmcvfs.exists(library + '/'):
@ -782,12 +776,12 @@ def get_themes():
tvtunes.setSetting('custom_path', library) tvtunes.setSetting('custom_path', library)
LOG.info("TV Tunes custom path is enabled and set.") LOG.info("TV Tunes custom path is enabled and set.")
else: else:
dialog("ok", heading="{emby}", line1=_(33152)) dialog("ok", heading="{jellyfin}", line1=_(33152))
return return
with Database('emby') as embydb: with Database('jellyfin') as jellyfindb:
all_views = emby_db.EmbyDatabase(embydb.cursor).get_views() all_views = jellyfin_db.JellyfinDatabase(jellyfindb.cursor).get_views()
views = [x[0] for x in all_views if x[2] in ('movies', 'tvshows', 'mixed')] views = [x[0] for x in all_views if x[2] in ('movies', 'tvshows', 'mixed')]
@ -831,7 +825,7 @@ def get_themes():
tvtunes_nfo(nfo_file, paths) tvtunes_nfo(nfo_file, paths)
dialog("notification", heading="{emby}", message=_(33153), icon="{emby}", time=1000, sound=False) dialog("notification", heading="{jellyfin}", message=_(33153), icon="{jellyfin}", time=1000, sound=False)
def delete_item(): def delete_item():
@ -843,7 +837,7 @@ def delete_item():
def backup(): def backup():
''' Emby backup. ''' Jellyfin backup.
''' '''
from helper.utils import delete_folder, copytree from helper.utils import delete_folder, copytree
@ -857,20 +851,20 @@ def backup():
backup = os.path.join(path, folder_name) backup = os.path.join(path, folder_name)
if xbmcvfs.exists(backup + '/'): if xbmcvfs.exists(backup + '/'):
if not dialog("yesno", heading="{emby}", line1=_(33090)): if not dialog("yesno", heading="{jellyfin}", line1=_(33090)):
return backup() return backup()
delete_folder(backup) delete_folder(backup)
addon_data = xbmc.translatePath("special://profile/addon_data/plugin.video.emby").decode('utf-8') addon_data = xbmc.translatePath("special://profile/addon_data/plugin.video.jellyfin").decode('utf-8')
destination_data = os.path.join(backup, "addon_data", "plugin.video.emby") destination_data = os.path.join(backup, "addon_data", "plugin.video.jellyfin")
destination_databases = os.path.join(backup, "Database") destination_databases = os.path.join(backup, "Database")
if not xbmcvfs.mkdirs(path) or not xbmcvfs.mkdirs(destination_databases): if not xbmcvfs.mkdirs(path) or not xbmcvfs.mkdirs(destination_databases):
LOG.info("Unable to create all directories") LOG.info("Unable to create all directories")
dialog("notification", heading="{emby}", icon="{emby}", message=_(33165), sound=False) dialog("notification", heading="{jellyfin}", icon="{jellyfin}", message=_(33165), sound=False)
return return
@ -878,9 +872,9 @@ def backup():
databases = Objects().objects databases = Objects().objects
db = xbmc.translatePath(databases['emby']).decode('utf-8') db = xbmc.translatePath(databases['jellyfin']).decode('utf-8')
xbmcvfs.copy(db, os.path.join(destination_databases, db.rsplit('\\', 1)[1])) xbmcvfs.copy(db, os.path.join(destination_databases, db.rsplit('\\', 1)[1]))
LOG.info("copied emby.db") LOG.info("copied jellyfin.db")
db = xbmc.translatePath(databases['video']).decode('utf-8') db = xbmc.translatePath(databases['video']).decode('utf-8')
filename = db.rsplit('\\', 1)[1] filename = db.rsplit('\\', 1)[1]
@ -895,4 +889,4 @@ def backup():
LOG.info("copied %s", filename) LOG.info("copied %s", filename)
LOG.info("backup completed") LOG.info("backup completed")
dialog("ok", heading="{emby}", line1="%s %s" % (_(33091), backup)) dialog("ok", heading="{jellyfin}", line1="%s %s" % (_(33091), backup))

View file

@ -21,12 +21,12 @@ import requests
from views import Views, verify_kodi_defaults from views import Views, verify_kodi_defaults
from helper import _, window, settings, event, dialog, find, compare_version from helper import _, window, settings, event, dialog, find, compare_version
from downloader import get_objects from downloader import get_objects
from emby import Emby from jellyfin import Jellyfin
from database import Database, emby_db, reset from database import Database, jellyfin_db, reset
################################################################################################# #################################################################################################
LOG = logging.getLogger("EMBY."+__name__) LOG = logging.getLogger("JELLYFIN."+__name__)
################################################################################################# #################################################################################################
@ -43,7 +43,7 @@ class Service(xbmc.Monitor):
def __init__(self): def __init__(self):
window('emby_should_stop', clear=True) window('jellyfin_should_stop', clear=True)
self.settings['addon_version'] = client.get_version() self.settings['addon_version'] = client.get_version()
self.settings['profile'] = xbmc.translatePath('special://profile') self.settings['profile'] = xbmc.translatePath('special://profile')
@ -53,14 +53,14 @@ class Service(xbmc.Monitor):
self.settings['enable_context'] = settings('enableContext.bool') self.settings['enable_context'] = settings('enableContext.bool')
self.settings['enable_context_transcode'] = settings('enableContextTranscode.bool') self.settings['enable_context_transcode'] = settings('enableContextTranscode.bool')
self.settings['kodi_companion'] = settings('kodiCompanion.bool') self.settings['kodi_companion'] = settings('kodiCompanion.bool')
window('emby_logLevel', value=str(self.settings['log_level'])) window('jellyfin_logLevel', value=str(self.settings['log_level']))
window('emby_kodiProfile', value=self.settings['profile']) window('jellyfin_kodiProfile', value=self.settings['profile'])
settings('platformDetected', client.get_platform()) settings('platformDetected', client.get_platform())
if self.settings['enable_context']: if self.settings['enable_context']:
window('emby_context.bool', True) window('jellyfin_context.bool', True)
if self.settings['enable_context_transcode']: if self.settings['enable_context_transcode']:
window('emby_context_transcode.bool', True) window('jellyfin_context_transcode.bool', True)
LOG.warn("--->>>[ %s ]", client.get_addon_name()) LOG.warn("--->>>[ %s ]", client.get_addon_name())
LOG.warn("Version: %s", client.get_version()) LOG.warn("Version: %s", client.get_version())
@ -78,8 +78,7 @@ class Service(xbmc.Monitor):
except Exception as error: except Exception as error:
LOG.error(error) LOG.error(error)
window('emby.connected.bool', True) window('jellyfin.connected.bool', True)
self.check_update()
settings('groupedSets.bool', objects.utils.get_grouped_set()) settings('groupedSets.bool', objects.utils.get_grouped_set())
xbmc.Monitor.__init__(self) xbmc.Monitor.__init__(self)
@ -99,9 +98,9 @@ class Service(xbmc.Monitor):
self.settings['mode'] = settings('useDirectPaths') self.settings['mode'] = settings('useDirectPaths')
while self.running: while self.running:
if window('emby_online.bool'): if window('jellyfin_online.bool'):
if self.settings['profile'] != window('emby_kodiProfile'): if self.settings['profile'] != window('jellyfin_kodiProfile'):
LOG.info("[ profile switch ] %s", self.settings['profile']) LOG.info("[ profile switch ] %s", self.settings['profile'])
break break
@ -118,10 +117,10 @@ class Service(xbmc.Monitor):
if update: if update:
self.settings['last_progress_report'] = datetime.today() self.settings['last_progress_report'] = datetime.today()
if window('emby.restart.bool'): if window('jellyfin.restart.bool'):
window('emby.restart', clear=True) window('jellyfin.restart', clear=True)
dialog("notification", heading="{emby}", message=_(33193), icon="{emby}", time=1000, sound=False) dialog("notification", heading="{jellyfin}", message=_(33193), icon="{jellyfin}", time=1000, sound=False)
raise Exception('RestartService') raise Exception('RestartService')
@ -142,8 +141,8 @@ class Service(xbmc.Monitor):
def stop_default(self): def stop_default(self):
window('emby_online', clear=True) window('jellyfin_online', clear=True)
Emby().close() Jellyfin().close()
if self.library_thread is not None: if self.library_thread is not None:
@ -154,9 +153,9 @@ class Service(xbmc.Monitor):
''' Check the database version to ensure we do not need to do a reset. ''' Check the database version to ensure we do not need to do a reset.
''' '''
with Database('emby') as embydb: with Database('jellyfin') as jellyfindb:
version = emby_db.EmbyDatabase(embydb.cursor).get_version() version = jellyfin_db.JellyfinDatabase(jellyfindb.cursor).get_version()
LOG.info("---[ db/%s ]", version) LOG.info("---[ db/%s ]", version)
if version and compare_version(version, "3.1.0") < 0: if version and compare_version(version, "3.1.0") < 0:
@ -173,64 +172,22 @@ class Service(xbmc.Monitor):
raise Exception("Completed database reset") raise Exception("Completed database reset")
def check_update(self, forced=False):
''' Check for objects build version and compare.
This pulls a dict that contains all the information for the build needed.
'''
LOG.info("--[ check updates/%s ]", objects.version)
kodi = "DEV" if settings('devMode.bool') else xbmc.getInfoLabel('System.BuildVersion')
try:
versions = requests.get('http://kodi.emby.media/Public%20testing/Dependencies/databases.json').json()
build = find(versions, kodi)
if not build:
raise Exception("build %s incompatible?!" % kodi)
label, zipfile = build.split('-', 1)
if label == 'DEV' and forced:
LOG.info("--[ force/objects/%s ]", label)
elif label == objects.version:
LOG.info("--[ objects/%s ]", objects.version)
return False
get_objects(zipfile, label + '.zip')
self.reload_objects()
dialog("notification", heading="{emby}", message=_(33156), icon="{emby}")
LOG.info("--[ new objects/%s ]", objects.version)
try:
if compare_version(self.settings['addon_version'], objects.embyversion) < 0:
dialog("ok", heading="{emby}", line1="%s %s" % (_(33160), objects.embyversion))
except Exception:
pass
except Exception as error:
LOG.exception(error)
return True
def onNotification(self, sender, method, data): def onNotification(self, sender, method, data):
''' All notifications are sent via NotifyAll built-in or Kodi. ''' All notifications are sent via NotifyAll built-in or Kodi.
Central hub. Central hub.
''' '''
if sender.lower() not in ('plugin.video.emby', 'xbmc'): if sender.lower() not in ('plugin.video.jellyfin', 'xbmc'):
return return
if sender == 'plugin.video.emby': if sender == 'plugin.video.jellyfin':
method = method.split('.')[1] method = method.split('.')[1]
if method not in ('ServerUnreachable', 'ServerShuttingDown', 'UserDataChanged', 'ServerConnect', if method not in ('ServerUnreachable', 'ServerShuttingDown', 'UserDataChanged', 'ServerConnect',
'LibraryChanged', 'ServerOnline', 'SyncLibrary', 'RepairLibrary', 'RemoveLibrary', 'LibraryChanged', 'ServerOnline', 'SyncLibrary', 'RepairLibrary', 'RemoveLibrary',
'EmbyConnect', 'SyncLibrarySelection', 'RepairLibrarySelection', 'AddServer', 'SyncLibrarySelection', 'RepairLibrarySelection', 'AddServer',
'Unauthorized', 'UpdateServer', 'UserConfigurationUpdated', 'ServerRestarting', 'Unauthorized', 'UpdateServer', 'UserConfigurationUpdated', 'ServerRestarting',
'RemoveServer', 'AddLibrarySelection', 'CheckUpdate', 'RemoveLibrarySelection'): 'RemoveServer', 'AddLibrarySelection', 'RemoveLibrarySelection'):
return return
data = json.loads(data)[0] data = json.loads(data)[0]
@ -245,7 +202,7 @@ class Service(xbmc.Monitor):
if method == 'ServerOnline': if method == 'ServerOnline':
if data.get('ServerId') is None: if data.get('ServerId') is None:
window('emby_online.bool', True) window('jellyfin_online.bool', True)
self.settings['auth_check'] = True self.settings['auth_check'] = True
self.warn = True self.warn = True
@ -253,8 +210,8 @@ class Service(xbmc.Monitor):
users = [user for user in (settings('additionalUsers') or "").decode('utf-8').split(',') if user] users = [user for user in (settings('additionalUsers') or "").decode('utf-8').split(',') if user]
users.insert(0, settings('username').decode('utf-8')) users.insert(0, settings('username').decode('utf-8'))
dialog("notification", heading="{emby}", message="%s %s" % (_(33000), ", ".join(users)), dialog("notification", heading="{jellyfin}", message="%s %s" % (_(33000), ", ".join(users)),
icon="{emby}", time=1500, sound=False) icon="{jellyfin}", time=1500, sound=False)
if self.library_thread is None: if self.library_thread is None:
@ -266,7 +223,7 @@ class Service(xbmc.Monitor):
if self.warn or data.get('ServerId'): if self.warn or data.get('ServerId'):
self.warn = data.get('ServerId') is not None self.warn = data.get('ServerId') is not None
dialog("notification", heading="{emby}", message=_(33146) if data.get('ServerId') is None else _(33149), icon=xbmcgui.NOTIFICATION_ERROR) dialog("notification", heading="{jellyfin}", message=_(33146) if data.get('ServerId') is None else _(33149), icon=xbmcgui.NOTIFICATION_ERROR)
if data.get('ServerId') is None: if data.get('ServerId') is None:
self.stop_default() self.stop_default()
@ -277,7 +234,7 @@ class Service(xbmc.Monitor):
self.start_default() self.start_default()
elif method == 'Unauthorized': elif method == 'Unauthorized':
dialog("notification", heading="{emby}", message=_(33147) if data['ServerId'] is None else _(33148), icon=xbmcgui.NOTIFICATION_ERROR) dialog("notification", heading="{jellyfin}", message=_(33147) if data['ServerId'] is None else _(33148), icon=xbmcgui.NOTIFICATION_ERROR)
if data.get('ServerId') is None and self.settings['auth_check']: if data.get('ServerId') is None and self.settings['auth_check']:
@ -294,7 +251,7 @@ class Service(xbmc.Monitor):
return return
if settings('restartMsg.bool'): if settings('restartMsg.bool'):
dialog("notification", heading="{emby}", message=_(33006), icon="{emby}") dialog("notification", heading="{jellyfin}", message=_(33006), icon="{jellyfin}")
self.stop_default() self.stop_default()
@ -307,9 +264,6 @@ class Service(xbmc.Monitor):
self.connect.register(data['Id']) self.connect.register(data['Id'])
xbmc.executebuiltin("Container.Refresh") xbmc.executebuiltin("Container.Refresh")
elif method == 'EmbyConnect':
self.connect.setup_login_connect()
elif method == 'AddServer': elif method == 'AddServer':
self.connect.setup_manual_server() self.connect.setup_manual_server()
@ -322,18 +276,18 @@ class Service(xbmc.Monitor):
elif method == 'UpdateServer': elif method == 'UpdateServer':
dialog("ok", heading="{emby}", line1=_(33151)) dialog("ok", heading="{jellyfin}", line1=_(33151))
self.connect.setup_manual_server() self.connect.setup_manual_server()
elif method == 'UserDataChanged' and self.library_thread: elif method == 'UserDataChanged' and self.library_thread:
if data.get('ServerId') or not window('emby_startup.bool'): if data.get('ServerId') or not window('jellyfin_startup.bool'):
return return
LOG.info("[ UserDataChanged ] %s", data) LOG.info("[ UserDataChanged ] %s", data)
self.library_thread.userdata(data['UserDataList']) self.library_thread.userdata(data['UserDataList'])
elif method == 'LibraryChanged' and self.library_thread: elif method == 'LibraryChanged' and self.library_thread:
if data.get('ServerId') or not window('emby_startup.bool'): if data.get('ServerId') or not window('jellyfin_startup.bool'):
return return
LOG.info("[ LibraryChanged ] %s", data) LOG.info("[ LibraryChanged ] %s", data)
@ -341,7 +295,7 @@ class Service(xbmc.Monitor):
self.library_thread.removed(data['ItemsRemoved']) self.library_thread.removed(data['ItemsRemoved'])
elif method == 'System.OnQuit': elif method == 'System.OnQuit':
window('emby_should_stop.bool', True) window('jellyfin_should_stop.bool', True)
self.running = False self.running = False
elif method in ('SyncLibrarySelection', 'RepairLibrarySelection', 'AddLibrarySelection', 'RemoveLibrarySelection'): elif method in ('SyncLibrarySelection', 'RepairLibrarySelection', 'AddLibrarySelection', 'RemoveLibrarySelection'):
@ -381,14 +335,14 @@ class Service(xbmc.Monitor):
elif method == 'System.OnSleep': elif method == 'System.OnSleep':
LOG.info("-->[ sleep ]") LOG.info("-->[ sleep ]")
window('emby_should_stop.bool', True) window('jellyfin_should_stop.bool', True)
if self.library_thread is not None: if self.library_thread is not None:
self.library_thread.stop_client() self.library_thread.stop_client()
self.library_thread = None self.library_thread = None
Emby.close_all() Jellyfin.close_all()
self.monitor.server = [] self.monitor.server = []
self.monitor.sleep = True self.monitor.sleep = True
@ -402,7 +356,7 @@ class Service(xbmc.Monitor):
LOG.info("--<[ sleep ]") LOG.info("--<[ sleep ]")
xbmc.sleep(10000)# Allow network to wake up xbmc.sleep(10000)# Allow network to wake up
self.monitor.sleep = False self.monitor.sleep = False
window('emby_should_stop', clear=True) window('jellyfin_should_stop', clear=True)
try: try:
self.connect.register() self.connect.register()
@ -422,37 +376,29 @@ class Service(xbmc.Monitor):
if data.get('ServerId') is None: if data.get('ServerId') is None:
Views().get_views() Views().get_views()
elif method == 'CheckUpdate':
if not self.check_update(True):
dialog("notification", heading="{emby}", message=_(21341), icon="{emby}", sound=False)
else:
dialog("notification", heading="{emby}", message=_(33181), icon="{emby}", sound=False)
window('emby.restart.bool', True)
def onSettingsChanged(self): def onSettingsChanged(self):
''' React to setting changes that impact window values. ''' React to setting changes that impact window values.
''' '''
if window('emby_should_stop.bool'): if window('jellyfin_should_stop.bool'):
return return
if settings('logLevel') != self.settings['log_level']: if settings('logLevel') != self.settings['log_level']:
log_level = settings('logLevel') log_level = settings('logLevel')
window('emby_logLevel', str(log_level)) window('jellyfin_logLevel', str(log_level))
self.settings['logLevel'] = log_level self.settings['logLevel'] = log_level
LOG.warn("New log level: %s", log_level) LOG.warn("New log level: %s", log_level)
if settings('enableContext.bool') != self.settings['enable_context']: if settings('enableContext.bool') != self.settings['enable_context']:
window('emby_context', settings('enableContext')) window('jellyfin_context', settings('enableContext'))
self.settings['enable_context'] = settings('enableContext.bool') self.settings['enable_context'] = settings('enableContext.bool')
LOG.warn("New context setting: %s", self.settings['enable_context']) LOG.warn("New context setting: %s", self.settings['enable_context'])
if settings('enableContextTranscode.bool') != self.settings['enable_context_transcode']: if settings('enableContextTranscode.bool') != self.settings['enable_context_transcode']:
window('emby_context_transcode', settings('enableContextTranscode')) window('jellyfin_context_transcode', settings('enableContextTranscode'))
self.settings['enable_context_transcode'] = settings('enableContextTranscode.bool') self.settings['enable_context_transcode'] = settings('enableContextTranscode.bool')
LOG.warn("New context transcode setting: %s", self.settings['enable_context_transcode']) LOG.warn("New context transcode setting: %s", self.settings['enable_context_transcode'])
@ -464,13 +410,13 @@ class Service(xbmc.Monitor):
if not self.settings.get('mode_warn'): if not self.settings.get('mode_warn'):
self.settings['mode_warn'] = True self.settings['mode_warn'] = True
dialog("yesno", heading="{emby}", line1=_(33118)) dialog("yesno", heading="{jellyfin}", line1=_(33118))
if settings('kodiCompanion.bool') != self.settings['kodi_companion']: if settings('kodiCompanion.bool') != self.settings['kodi_companion']:
self.settings['kodi_companion'] = settings('kodiCompanion.bool') self.settings['kodi_companion'] = settings('kodiCompanion.bool')
if not self.settings['kodi_companion']: if not self.settings['kodi_companion']:
dialog("ok", heading="{emby}", line1=_(33138)) dialog("ok", heading="{jellyfin}", line1=_(33138))
def reload_objects(self): def reload_objects(self):
@ -496,19 +442,19 @@ class Service(xbmc.Monitor):
def shutdown(self): def shutdown(self):
LOG.warn("---<[ EXITING ]") LOG.warn("---<[ EXITING ]")
window('emby_should_stop.bool', True) window('jellyfin_should_stop.bool', True)
properties = [ # TODO: review properties = [ # TODO: review
"emby_state", "emby_serverStatus", "emby_currUser", "jellyfin_state", "jellyfin_serverStatus", "jellyfin_currUser",
"emby_play", "emby_online", "emby.connected", "emby.resume", "emby_startup", "jellyfin_play", "jellyfin_online", "jellyfin.connected", "jellyfin.resume", "jellyfin_startup",
"emby.external", "emby.external_check", "emby_deviceId", "emby_db_check", "emby_pathverified", "jellyfin.external", "jellyfin.external_check", "jellyfin_deviceId", "jellyfin_db_check", "jellyfin_pathverified",
"emby_sync" "jellyfin_sync"
] ]
for prop in properties: for prop in properties:
window(prop, clear=True) window(prop, clear=True)
Emby.close_all() Jellyfin.close_all()
if self.library_thread is not None: if self.library_thread is not None:
self.library_thread.stop_client() self.library_thread.stop_client()

View file

@ -12,14 +12,14 @@ import xbmcvfs
import downloader as server import downloader as server
import helper.xmls as xmls import helper.xmls as xmls
from database import Database, get_sync, save_sync, emby_db from database import Database, get_sync, save_sync, jellyfin_db
from helper import _, settings, window, progress, dialog, LibraryException from helper import _, settings, window, progress, dialog, LibraryException
from helper.utils import get_screensaver, set_screensaver from helper.utils import get_screensaver, set_screensaver
from views import Views from views import Views
################################################################################################## ##################################################################################################
LOG = logging.getLogger("EMBY."+__name__) LOG = logging.getLogger("JELLYFIN."+__name__)
################################################################################################## ##################################################################################################
@ -27,7 +27,7 @@ LOG = logging.getLogger("EMBY."+__name__)
class FullSync(object): class FullSync(object):
''' This should be called like a context. ''' This should be called like a context.
i.e. with FullSync('emby') as sync: i.e. with FullSync('jellyfin') as sync:
sync.libraries() sync.libraries()
''' '''
# Borg - multiple instances, shared state # Borg - multiple instances, shared state
@ -45,7 +45,7 @@ class FullSync(object):
self.__dict__ = self._shared_state self.__dict__ = self._shared_state
if self.running: if self.running:
dialog("ok", heading="{emby}", line1=_(33197)) dialog("ok", heading="{jellyfin}", line1=_(33197))
raise Exception("Sync is already running.") raise Exception("Sync is already running.")
@ -65,7 +65,7 @@ class FullSync(object):
set_screensaver(value="") set_screensaver(value="")
self.running = True self.running = True
window('emby_sync.bool', True) window('jellyfin_sync.bool', True)
return self return self
@ -104,11 +104,11 @@ class FullSync(object):
def get_libraries(self, library_id=None): def get_libraries(self, library_id=None):
with Database('emby') as embydb: with Database('jellyfin') as jellyfindb:
if library_id is None: if library_id is None:
return emby_db.EmbyDatabase(embydb.cursor).get_views() return jellyfin_db.JellyfinDatabase(jellyfindb.cursor).get_views()
else: else:
return emby_db.EmbyDatabase(embydb.cursor).get_view(library_id) return jellyfin_db.JellyfinDatabase(jellyfindb.cursor).get_view(library_id)
def mapping(self): def mapping(self):
@ -117,10 +117,10 @@ class FullSync(object):
''' '''
if self.sync['Libraries']: if self.sync['Libraries']:
if not dialog("yesno", heading="{emby}", line1=_(33102)): if not dialog("yesno", heading="{jellyfin}", line1=_(33102)):
if not dialog("yesno", heading="{emby}", line1=_(33173)): if not dialog("yesno", heading="{jellyfin}", line1=_(33173)):
dialog("ok", heading="{emby}", line1=_(33122)) dialog("ok", heading="{jellyfin}", line1=_(33122))
raise LibraryException("ProgressStopped") raise LibraryException("ProgressStopped")
else: else:
@ -146,7 +146,7 @@ class FullSync(object):
''' Select all or certain libraries to be whitelisted. ''' Select all or certain libraries to be whitelisted.
''' '''
if dialog("yesno", heading="{emby}", line1=_(33125), nolabel=_(33127), yeslabel=_(33126)): if dialog("yesno", heading="{jellyfin}", line1=_(33125), nolabel=_(33127), yeslabel=_(33126)):
LOG.info("Selected sync later.") LOG.info("Selected sync later.")
raise LibraryException('SyncLibraryLater') raise LibraryException('SyncLibraryLater')
@ -204,8 +204,8 @@ class FullSync(object):
save_sync(self.sync) save_sync(self.sync)
xbmc.executebuiltin('UpdateLibrary(video)') xbmc.executebuiltin('UpdateLibrary(video)')
dialog("notification", heading="{emby}", message="%s %s" % (_(33025), str(elapsed).split('.')[0]), dialog("notification", heading="{jellyfin}", message="%s %s" % (_(33025), str(elapsed).split('.')[0]),
icon="{emby}", sound=False) icon="{jellyfin}", sound=False)
LOG.info("Full sync completed in: %s", str(elapsed).split('.')[0]) LOG.info("Full sync completed in: %s", str(elapsed).split('.')[0])
def process_library(self, library_id): def process_library(self, library_id):
@ -251,7 +251,7 @@ class FullSync(object):
if not 'Failed to validate path' in error: if not 'Failed to validate path' in error:
dialog("ok", heading="{emby}", line1=_(33119)) dialog("ok", heading="{jellyfin}", line1=_(33119))
LOG.error("full sync exited unexpectedly") LOG.error("full sync exited unexpectedly")
save_sync(self.sync) save_sync(self.sync)
@ -266,9 +266,9 @@ class FullSync(object):
with self.library.database_lock: with self.library.database_lock:
with Database() as videodb: with Database() as videodb:
with Database('emby') as embydb: with Database('jellyfin') as jellyfindb:
obj = Movies(self.server, embydb, videodb, self.direct_path) obj = Movies(self.server, jellyfindb, videodb, self.direct_path)
for items in server.get_items(library['Id'], "Movie", False, self.sync['RestorePoint'].get('params')): for items in server.get_items(library['Id'], "Movie", False, self.sync['RestorePoint'].get('params')):
@ -283,13 +283,13 @@ class FullSync(object):
obj.movie(movie, library=library) obj.movie(movie, library=library)
if self.update_library: if self.update_library:
self.movies_compare(library, obj, embydb) self.movies_compare(library, obj, jellyfindb)
def movies_compare(self, library, obj, embydb): def movies_compare(self, library, obj, jellyfinydb):
''' Compare entries from library to what's in the embydb. Remove surplus ''' Compare entries from library to what's in the jellyfindb. Remove surplus
''' '''
db = emby_db.EmbyDatabase(embydb.cursor) db = jellyfin_db.JellyfinDatabase(jellyfinydb.cursor)
items = db.get_item_by_media_folder(library['Id']) items = db.get_item_by_media_folder(library['Id'])
current = obj.item_ids current = obj.item_ids
@ -307,8 +307,8 @@ class FullSync(object):
with self.library.database_lock: with self.library.database_lock:
with Database() as videodb: with Database() as videodb:
with Database('emby') as embydb: with Database('jellyfin') as jellyfindb:
obj = TVShows(self.server, embydb, videodb, self.direct_path, True) obj = TVShows(self.server, jellyfindb, videodb, self.direct_path, True)
for items in server.get_items(library['Id'], "Series", False, self.sync['RestorePoint'].get('params')): for items in server.get_items(library['Id'], "Series", False, self.sync['RestorePoint'].get('params')):
@ -330,13 +330,13 @@ class FullSync(object):
obj.episode(episode) obj.episode(episode)
if self.update_library: if self.update_library:
self.tvshows_compare(library, obj, embydb) self.tvshows_compare(library, obj, jellyfindb)
def tvshows_compare(self, library, obj, embydb): def tvshows_compare(self, library, obj, jellyfindb):
''' Compare entries from library to what's in the embydb. Remove surplus ''' Compare entries from library to what's in the jellyfindb. Remove surplus
''' '''
db = emby_db.EmbyDatabase(embydb.cursor) db = jellyfin_db.JellyfinDatabase(jellyfindb.cursor)
items = db.get_item_by_media_folder(library['Id']) items = db.get_item_by_media_folder(library['Id'])
for x in list(items): for x in list(items):
@ -357,8 +357,8 @@ class FullSync(object):
with self.library.database_lock: with self.library.database_lock:
with Database() as videodb: with Database() as videodb:
with Database('emby') as embydb: with Database('jellyfin') as jellyfindb:
obj = MusicVideos(self.server, embydb, videodb, self.direct_path) obj = MusicVideos(self.server, jellyfindb, videodb, self.direct_path)
for items in server.get_items(library['Id'], "MusicVideo", False, self.sync['RestorePoint'].get('params')): for items in server.get_items(library['Id'], "MusicVideo", False, self.sync['RestorePoint'].get('params')):
@ -373,13 +373,13 @@ class FullSync(object):
obj.musicvideo(mvideo, library=library) obj.musicvideo(mvideo, library=library)
if self.update_library: if self.update_library:
self.musicvideos_compare(library, obj, embydb) self.musicvideos_compare(library, obj, jellyfindb)
def musicvideos_compare(self, library, obj, embydb): def musicvideos_compare(self, library, obj, jellyfindb):
''' Compare entries from library to what's in the embydb. Remove surplus ''' Compare entries from library to what's in the jellyfindb. Remove surplus
''' '''
db = emby_db.EmbyDatabase(embydb.cursor) db = jellyfin_db.JellyfinDatabase(jellyfindb.cursor)
items = db.get_item_by_media_folder(library['Id']) items = db.get_item_by_media_folder(library['Id'])
current = obj.item_ids current = obj.item_ids
@ -397,8 +397,8 @@ class FullSync(object):
with self.library.music_database_lock: with self.library.music_database_lock:
with Database('music') as musicdb: with Database('music') as musicdb:
with Database('emby') as embydb: with Database('jellyfin') as jellyfindb:
obj = Music(self.server, embydb, musicdb, self.direct_path) obj = Music(self.server, jellyfindb, musicdb, self.direct_path)
for items in server.get_artists(library['Id'], False, self.sync['RestorePoint'].get('params')): for items in server.get_artists(library['Id'], False, self.sync['RestorePoint'].get('params')):
@ -432,13 +432,13 @@ class FullSync(object):
if self.update_library: if self.update_library:
self.music_compare(library, obj, embydb) self.music_compare(library, obj, jellyfindb)
def music_compare(self, library, obj, embydb): def music_compare(self, library, obj, jellyfindb):
''' Compare entries from library to what's in the embydb. Remove surplus ''' Compare entries from library to what's in the jellyfindb. Remove surplus
''' '''
db = emby_db.EmbyDatabase(embydb.cursor) db = jellyfin_db.JellyfinDatabase(jellyfindb.cursor)
items = db.get_item_by_media_folder(library['Id']) items = db.get_item_by_media_folder(library['Id'])
for x in list(items): for x in list(items):
@ -459,8 +459,8 @@ class FullSync(object):
with self.library.database_lock: with self.library.database_lock:
with Database() as videodb: with Database() as videodb:
with Database('emby') as embydb: with Database('jellyfin') as jellyfindb:
obj = Movies(self.server, embydb, videodb, self.direct_path) obj = Movies(self.server, jellyfindb, videodb, self.direct_path)
for items in server.get_items(library_id, "BoxSet", False, self.sync['RestorePoint'].get('params')): for items in server.get_items(library_id, "BoxSet", False, self.sync['RestorePoint'].get('params')):
@ -482,9 +482,9 @@ class FullSync(object):
with self.library.database_lock: with self.library.database_lock:
with Database() as videodb: with Database() as videodb:
with Database('emby') as embydb: with Database('jellyfin') as jellyfindb:
obj = Movies(self.server, embydb, videodb, self.direct_path) obj = Movies(self.server, jellyfindb, videodb, self.direct_path)
obj.boxsets_reset() obj.boxsets_reset()
self.boxsets(None) self.boxsets(None)
@ -497,9 +497,9 @@ class FullSync(object):
MEDIA = self.library.MEDIA MEDIA = self.library.MEDIA
direct_path = self.library.direct_path direct_path = self.library.direct_path
with Database('emby') as embydb: with Database('jellyfin') as jellyfindb:
db = emby_db.EmbyDatabase(embydb.cursor) db = jellyfin_db.JellyfinDatabase(jellyfindb.cursor)
library = db.get_view(library_id.replace('Mixed:', "")) library = db.get_view(library_id.replace('Mixed:', ""))
items = db.get_item_by_media_folder(library_id.replace('Mixed:', "")) items = db.get_item_by_media_folder(library_id.replace('Mixed:', ""))
media = 'music' if library[1] == 'music' else 'video' media = 'music' if library[1] == 'music' else 'video'
@ -518,7 +518,7 @@ class FullSync(object):
movies = [x for x in items if x[1] == 'Movie'] movies = [x for x in items if x[1] == 'Movie']
tvshows = [x for x in items if x[1] == 'Series'] tvshows = [x for x in items if x[1] == 'Series']
obj = MEDIA['Movie'](self.server, embydb, kodidb, direct_path)['Remove'] obj = MEDIA['Movie'](self.server, jellyfindb, kodidb, direct_path)['Remove']
for item in movies: for item in movies:
@ -526,7 +526,7 @@ class FullSync(object):
dialog.update(int((float(count) / float(len(items))*100)), heading="%s: %s" % (_('addon_name'), library[0])) dialog.update(int((float(count) / float(len(items))*100)), heading="%s: %s" % (_('addon_name'), library[0]))
count += 1 count += 1
obj = MEDIA['Series'](self.server, embydb, kodidb, direct_path)['Remove'] obj = MEDIA['Series'](self.server, jellyfindb, kodidb, direct_path)['Remove']
for item in tvshows: for item in tvshows:
@ -534,7 +534,7 @@ class FullSync(object):
dialog.update(int((float(count) / float(len(items))*100)), heading="%s: %s" % (_('addon_name'), library[0])) dialog.update(int((float(count) / float(len(items))*100)), heading="%s: %s" % (_('addon_name'), library[0]))
count += 1 count += 1
else: else:
obj = MEDIA[items[0][1]](self.server, embydb, kodidb, direct_path)['Remove'] obj = MEDIA[items[0][1]](self.server, jellyfindb, kodidb, direct_path)['Remove']
for item in items: for item in items:
@ -558,7 +558,7 @@ class FullSync(object):
''' Exiting sync ''' Exiting sync
''' '''
self.running = False self.running = False
window('emby_sync', clear=True) window('jellyfin_sync', clear=True)
if not settings('dbSyncScreensaver.bool') and self.screensaver is not None: if not settings('dbSyncScreensaver.bool') and self.screensaver is not None:

View file

@ -22,5 +22,5 @@ from wrapper import progress
from wrapper import catch from wrapper import catch
from wrapper import silent_catch from wrapper import silent_catch
from wrapper import stop from wrapper import stop
from wrapper import emby_item from wrapper import jellyfin_item
from wrapper import library_check from wrapper import library_check

View file

@ -10,7 +10,7 @@ from . import settings
################################################################################################## ##################################################################################################
LOG = logging.getLogger("EMBY."+__name__) LOG = logging.getLogger("JELLYFIN."+__name__)
################################################################################################## ##################################################################################################
@ -28,7 +28,7 @@ class API(object):
def get_playcount(self, played, playcount): def get_playcount(self, played, playcount):
''' Convert Emby played/playcount into ''' Convert Jellyfin played/playcount into
the Kodi equivalent. The playcount is tied to the watch status. the Kodi equivalent. The playcount is tied to the watch status.
''' '''
return (playcount or 1) if played else None return (playcount or 1) if played else None
@ -231,7 +231,7 @@ class API(object):
def get_user_artwork(self, user_id): def get_user_artwork(self, user_id):
''' Get emby user profile picture. ''' Get jellyfin user profile picture.
''' '''
return "%s/emby/Users/%s/Images/Primary?Format=original" % (self.server, user_id) return "%s/emby/Users/%s/Images/Primary?Format=original" % (self.server, user_id)
@ -302,7 +302,7 @@ class API(object):
def get_backdrops(self, item_id, tags, query=None): def get_backdrops(self, item_id, tags, query=None):
''' Get backdrops based of "BackdropImageTags" in the emby object. ''' Get backdrops based of "BackdropImageTags" in the jellyfin object.
''' '''
backdrops = [] backdrops = []

View file

@ -3,7 +3,7 @@
################################################################################################# #################################################################################################
class LibraryException(Exception): class LibraryException(Exception):
# Emby library sync exception # Jellyfin library sync exception
def __init__(self, status): def __init__(self, status):
self.status = status self.status = status

View file

@ -14,14 +14,14 @@ from . import window, settings
def config(): def config():
logger = logging.getLogger('EMBY') logger = logging.getLogger('JELLYFIN')
logger.addHandler(LogHandler()) logger.addHandler(LogHandler())
logger.setLevel(logging.DEBUG) logger.setLevel(logging.DEBUG)
def reset(): def reset():
for handler in logging.getLogger('EMBY').handlers: for handler in logging.getLogger('JELLYFIN').handlers:
logging.getLogger('EMBY').removeHandler(handler) logging.getLogger('JELLYFIN').removeHandler(handler)
class LogHandler(logging.StreamHandler): class LogHandler(logging.StreamHandler):
@ -56,10 +56,10 @@ class LogHandler(logging.StreamHandler):
if self.mask_info: if self.mask_info:
for server in self.sensitive['Server']: for server in self.sensitive['Server']:
string = string.replace(server.encode('utf-8') or "{server}", "{emby-server}") string = string.replace(server.encode('utf-8') or "{server}", "{jellyfin-server}")
for token in self.sensitive['Token']: for token in self.sensitive['Token']:
string = string.replace(token.encode('utf-8') or "{token}", "{emby-token}") string = string.replace(token.encode('utf-8') or "{token}", "{jellyfin-token}")
try: try:
xbmc.log(string, level=xbmc.LOGNOTICE) xbmc.log(string, level=xbmc.LOGNOTICE)
@ -76,7 +76,7 @@ class LogHandler(logging.StreamHandler):
logging.DEBUG: 2 logging.DEBUG: 2
} }
try: try:
log_level = int(window('emby_logLevel')) log_level = int(window('jellyfin_logLevel'))
except ValueError: except ValueError:
log_level = 0 log_level = 0

View file

@ -17,11 +17,10 @@ import collections
import requests import requests
from . import _, settings, window, dialog from . import _, settings, window, dialog
from downloader import TheVoid from downloader import TheVoid
from emby import Emby
################################################################################################# #################################################################################################
LOG = logging.getLogger("EMBY."+__name__) LOG = logging.getLogger("JELLYFIN."+__name__)
################################################################################################# #################################################################################################
@ -32,7 +31,7 @@ def set_properties(item, method, server_id=None):
''' '''
info = item.get('PlaybackInfo') or {} info = item.get('PlaybackInfo') or {}
current = window('emby_play.json') or [] current = window('jellyfin_play.json') or []
current.append({ current.append({
'Type': item['Type'], 'Type': item['Type'],
'Id': item['Id'], 'Id': item['Id'],
@ -51,7 +50,7 @@ def set_properties(item, method, server_id=None):
'CurrentEpisode': info.get('CurrentEpisode') 'CurrentEpisode': info.get('CurrentEpisode')
}) })
window('emby_play.json', current) window('jellyfin_play.json', current)
class PlayUtils(object): class PlayUtils(object):
@ -178,7 +177,7 @@ class PlayUtils(object):
def get(self, source, audio=None, subtitle=None): def get(self, source, audio=None, subtitle=None):
''' The server returns sources based on the MaxStreamingBitrate value and other filters. ''' The server returns sources based on the MaxStreamingBitrate value and other filters.
prop: embyfilename for ?? I thought it was to pass the real path to subtitle add-ons but it's not working? prop: jellyfinfilename for ?? I thought it was to pass the real path to subtitle add-ons but it's not working?
''' '''
self.info['MediaSourceId'] = source['Id'] self.info['MediaSourceId'] = source['Id']
@ -214,7 +213,7 @@ class PlayUtils(object):
self.item['PlaybackInfo'].update(self.info) self.item['PlaybackInfo'].update(self.info)
API = api.API(self.item, self.info['ServerAddress']) API = api.API(self.item, self.info['ServerAddress'])
window('embyfilename', value=API.get_file_path(source.get('Path')).encode('utf-8')) window('jellyfinfilename', value=API.get_file_path(source.get('Path')).encode('utf-8'))
def live_stream(self, source): def live_stream(self, source):
@ -454,7 +453,7 @@ class PlayUtils(object):
def set_external_subs(self, source, listitem): def set_external_subs(self, source, listitem):
''' Try to download external subs locally so we can label them. ''' Try to download external subs locally so we can label them.
Since Emby returns all possible tracks together, sort them. Since Jellyfin returns all possible tracks together, sort them.
IsTextSubtitleStream if true, is available to download from server. IsTextSubtitleStream if true, is available to download from server.
''' '''
if not settings('enableExternalSubs.bool') or not source['MediaStreams']: if not settings('enableExternalSubs.bool') or not source['MediaStreams']:
@ -503,7 +502,7 @@ class PlayUtils(object):
''' Download external subtitles to temp folder ''' Download external subtitles to temp folder
to be able to have proper names to streams. to be able to have proper names to streams.
''' '''
temp = xbmc.translatePath("special://profile/addon_data/plugin.video.emby/temp/").decode('utf-8') temp = xbmc.translatePath("special://profile/addon_data/plugin.video.jellyfin/temp/").decode('utf-8')
if not xbmcvfs.exists(temp): if not xbmcvfs.exists(temp):
xbmcvfs.mkdir(temp) xbmcvfs.mkdir(temp)
@ -528,7 +527,7 @@ class PlayUtils(object):
''' For transcoding only ''' For transcoding only
Present the list of audio/subs to select from, before playback starts. Present the list of audio/subs to select from, before playback starts.
Since Emby returns all possible tracks together, sort them. Since Jellyfin returns all possible tracks together, sort them.
IsTextSubtitleStream if true, is available to download from server. IsTextSubtitleStream if true, is available to download from server.
''' '''
prefs = "" prefs = ""

View file

@ -11,7 +11,7 @@ import xbmcaddon
################################################################################################## ##################################################################################################
LOG = logging.getLogger('EMBY.'+__name__) LOG = logging.getLogger('JELLYFIN.'+__name__)
################################################################################################## ##################################################################################################
@ -22,7 +22,7 @@ def _(string):
if type(string) != int: if type(string) != int:
string = STRINGS[string] string = STRINGS[string]
result = xbmcaddon.Addon('plugin.video.emby').getLocalizedString(string) result = xbmcaddon.Addon('plugin.video.jellyfin').getLocalizedString(string)
if not result: if not result:
result = xbmc.getLocalizedString(string) result = xbmc.getLocalizedString(string)

View file

@ -21,12 +21,12 @@ from dateutil import tz, parser
################################################################################################# #################################################################################################
LOG = logging.getLogger("EMBY."+__name__) LOG = logging.getLogger("JELLYFIN."+__name__)
################################################################################################# #################################################################################################
def addon_id(): def addon_id():
return "plugin.video.emby" return "plugin.video.jellyfin"
def kodi_version(): def kodi_version():
return xbmc.getInfoLabel('System.BuildVersion')[:2] return xbmc.getInfoLabel('System.BuildVersion')[:2]
@ -134,7 +134,7 @@ def event(method, data=None, sender=None, hexlify=False):
''' Data is a dictionary. ''' Data is a dictionary.
''' '''
data = data or {} data = data or {}
sender = sender or "plugin.video.emby" sender = sender or "plugin.video.jellyfin"
if hexlify: if hexlify:
data = '\\"[\\"{0}\\"]\\"'.format(binascii.hexlify(json.dumps(data))) data = '\\"[\\"{0}\\"]\\"'.format(binascii.hexlify(json.dumps(data)))
@ -149,10 +149,10 @@ def dialog(dialog_type, *args, **kwargs):
d = xbmcgui.Dialog() d = xbmcgui.Dialog()
if "icon" in kwargs: if "icon" in kwargs:
kwargs['icon'] = kwargs['icon'].replace("{emby}", kwargs['icon'] = kwargs['icon'].replace("{jellyfin}",
"special://home/addons/plugin.video.emby/icon.png") "special://home/addons/plugin.video.jellyfin/icon.png")
if "heading" in kwargs: if "heading" in kwargs:
kwargs['heading'] = kwargs['heading'].replace("{emby}", _('addon_name')) kwargs['heading'] = kwargs['heading'].replace("{jellyfin}", _('addon_name'))
types = { types = {
'yesno': d.yesno, 'yesno': d.yesno,
@ -172,11 +172,11 @@ def should_stop():
if xbmc.Monitor().waitForAbort(0.00001): if xbmc.Monitor().waitForAbort(0.00001):
return True return True
if window('emby_should_stop.bool'): if window('jellyfin_should_stop.bool'):
LOG.info("exiiiiitttinggg") LOG.info("exiiiiitttinggg")
return True return True
if not window('emby_online.bool'): if not window('jellyfin_online.bool'):
return True return True
return False return False
@ -235,7 +235,7 @@ def validate(path):
''' Verify if path is accessible. ''' Verify if path is accessible.
''' '''
if window('emby_pathverified.bool'): if window('jellyfin_pathverified.bool'):
return True return True
path = path if os.path.supports_unicode_filenames else path.encode('utf-8') path = path if os.path.supports_unicode_filenames else path.encode('utf-8')
@ -243,11 +243,11 @@ def validate(path):
if not xbmcvfs.exists(path): if not xbmcvfs.exists(path):
LOG.info("Could not find %s", path) LOG.info("Could not find %s", path)
if dialog("yesno", heading="{emby}", line1="%s %s. %s" % (_(33047), path, _(33048))): if dialog("yesno", heading="{jellyfin}", line1="%s %s. %s" % (_(33047), path, _(33048))):
return False return False
window('emby_pathverified.bool', True) window('jellyfin_pathverified.bool', True)
return True return True
@ -292,7 +292,7 @@ def delete_folder(path=None):
''' '''
LOG.debug("--[ delete folder ]") LOG.debug("--[ delete folder ]")
delete_path = path is not None delete_path = path is not None
path = path or xbmc.translatePath('special://temp/emby').decode('utf-8') path = path or xbmc.translatePath('special://temp/jellyfin').decode('utf-8')
dirs, files = xbmcvfs.listdir(path) dirs, files = xbmcvfs.listdir(path)
delete_recursive(path, dirs) delete_recursive(path, dirs)

View file

@ -11,7 +11,7 @@ from utils import should_stop
################################################################################################# #################################################################################################
LOG = logging.getLogger("EMBY."+__name__) LOG = logging.getLogger("JELLYFIN."+__name__)
################################################################################################# #################################################################################################
@ -99,13 +99,13 @@ def stop(default=None):
return wrapper return wrapper
return decorator return decorator
def emby_item(): def jellyfin_item():
''' Wrapper to retrieve the emby_db item. ''' Wrapper to retrieve the jellyfin_db item.
''' '''
def decorator(func): def decorator(func):
def wrapper(self, item, *args, **kwargs): def wrapper(self, item, *args, **kwargs):
e_item = self.emby_db.get_item_by_id(item['Id'] if type(item) == dict else item) e_item = self.jellyfin_db.get_item_by_id(item['Id'] if type(item) == dict else item)
return func(self, item, e_item=e_item, *args, **kwargs) return func(self, item, e_item=e_item, *args, **kwargs)
@ -129,7 +129,7 @@ def library_check():
if 'e_item' in kwargs: if 'e_item' in kwargs:
try: try:
view_id = kwargs['e_item'][6] view_id = kwargs['e_item'][6]
view_name = self.emby_db.get_view_name(view_id) view_name = self.jellyfin_db.get_view_name(view_id)
view = {'Name': view_name, 'Id': view_id} view = {'Name': view_name, 'Id': view_id}
except Exception: except Exception:
view = None view = None
@ -141,7 +141,7 @@ def library_check():
if item['Type'] == 'MusicArtist': if item['Type'] == 'MusicArtist':
try: try:
views = self.emby_db.get_views_by_media('music')[0] views = self.jellyfin_db.get_views_by_media('music')[0]
except Exception: except Exception:
return return
@ -152,7 +152,7 @@ def library_check():
for ancestor in ancestors: for ancestor in ancestors:
if ancestor['Type'] == 'CollectionFolder': if ancestor['Type'] == 'CollectionFolder':
view = self.emby_db.get_view_name(ancestor['Id']) view = self.jellyfin_db.get_view_name(ancestor['Id'])
view = {'Id': None, 'Name': None} if view is None else {'Name': ancestor['Name'], 'Id': ancestor['Id']} view = {'Id': None, 'Name': None} if view is None else {'Name': ancestor['Name'], 'Id': ancestor['Id']}
break break

View file

@ -13,14 +13,14 @@ from . import _, indent, write_xml, dialog, settings
################################################################################################# #################################################################################################
LOG = logging.getLogger("EMBY."+__name__) LOG = logging.getLogger("JELLYFIN."+__name__)
################################################################################################# #################################################################################################
def sources(): def sources():
''' Create master lock compatible sources. ''' Create master lock compatible sources.
Also add the kodi.emby.media source. Also add the kodi.jellyfin.media source.
''' '''
path = xbmc.translatePath("special://profile/").decode('utf-8') path = xbmc.translatePath("special://profile/").decode('utf-8')
file = os.path.join(path, 'sources.xml') file = os.path.join(path, 'sources.xml')
@ -52,7 +52,7 @@ def sources():
if (protocol == 'smb://' and count_smb > 0) or (protocol == 'http://' and count_http > 0): if (protocol == 'smb://' and count_smb > 0) or (protocol == 'http://' and count_http > 0):
source = etree.SubElement(video, 'source') source = etree.SubElement(video, 'source')
etree.SubElement(source, 'name').text = "Emby" etree.SubElement(source, 'name').text = "Jellyfin"
etree.SubElement(source, 'path', attrib={'pathversion': "1"}).text = protocol etree.SubElement(source, 'path', attrib={'pathversion': "1"}).text = protocol
etree.SubElement(source, 'allowsharing').text = "true" etree.SubElement(source, 'allowsharing').text = "true"
@ -63,12 +63,13 @@ def sources():
files = etree.SubElement(xml, 'files') files = etree.SubElement(xml, 'files')
for source in xml.findall('.//path'): for source in xml.findall('.//path'):
if source.text == 'http://kodi.emby.media': # TODO get a repo url
if source.text == 'http://kodi.jellyfin.media':
break break
else: else:
source = etree.SubElement(files, 'source') source = etree.SubElement(files, 'source')
etree.SubElement(source, 'name').text = "kodi.emby.media" etree.SubElement(source, 'name').text = "kodi.jellyfin.media"
etree.SubElement(source, 'path', attrib={'pathversion': "1"}).text = "http://kodi.emby.media" etree.SubElement(source, 'path', attrib={'pathversion': "1"}).text = "http://kodi.jellyfin.media"
etree.SubElement(source, 'allowsharing').text = "true" etree.SubElement(source, 'allowsharing').text = "true"
except Exception as error: except Exception as error:
LOG.exception(error) LOG.exception(error)
@ -124,7 +125,7 @@ def advanced_settings():
indent(xml) indent(xml)
write_xml(etree.tostring(xml, 'UTF-8'), path) write_xml(etree.tostring(xml, 'UTF-8'), path)
dialog("ok", heading="{emby}", line1=_(33097)) dialog("ok", heading="{jellyfin}", line1=_(33097))
xbmc.executebuiltin('RestartApp') xbmc.executebuiltin('RestartApp')
return True return True

View file

@ -4,7 +4,7 @@
import logging import logging
from client import EmbyClient from client import JellyfinClient
from helpers import has_attribute from helpers import has_attribute
################################################################################################# #################################################################################################
@ -14,14 +14,14 @@ class NullHandler(logging.Handler):
print(self.format(record)) print(self.format(record))
loghandler = NullHandler loghandler = NullHandler
LOG = logging.getLogger('Emby') LOG = logging.getLogger('Jellyfin')
################################################################################################# #################################################################################################
def config(level=logging.INFO): def config(level=logging.INFO):
logger = logging.getLogger('Emby') logger = logging.getLogger('Jellyfin')
logger.addHandler(Emby.loghandler()) logger.addHandler(Jellyfin.loghandler())
logger.setLevel(level) logger.setLevel(level)
def ensure_client(): def ensure_client():
@ -38,17 +38,17 @@ def ensure_client():
return decorator return decorator
class Emby(object): class Jellyfin(object):
''' This is your Embyclient, you can create more than one. The server_id is only a temporary thing ''' This is your Jellyfinclient, you can create more than one. The server_id is only a temporary thing
to communicate with the EmbyClient(). to communicate with the JellyfinClient().
from emby import Emby from jellyfin import Jellyfin
Emby('123456')['config/app'] Jellyfin('123456')['config/app']
# Permanent client reference # Permanent client reference
client = Emby('123456').get_client() client = Jellyfin('123456').get_client()
client['config/app'] client['config/app']
''' '''
@ -68,9 +68,9 @@ class Emby(object):
@classmethod @classmethod
def set_loghandler(cls, func=loghandler, level=logging.INFO): def set_loghandler(cls, func=loghandler, level=logging.INFO):
for handler in logging.getLogger('Emby').handlers: for handler in logging.getLogger('Jellyfin').handlers:
if isinstance(handler, cls.loghandler): if isinstance(handler, cls.loghandler):
logging.getLogger('Emby').removeHandler(handler) logging.getLogger('Jellyfin').removeHandler(handler)
cls.loghandler = func cls.loghandler = func
config(level) config(level)
@ -83,7 +83,7 @@ class Emby(object):
self.client[self.server_id].stop() self.client[self.server_id].stop()
self.client.pop(self.server_id, None) self.client.pop(self.server_id, None)
LOG.info("---[ STOPPED EMBYCLIENT: %s ]---", self.server_id) LOG.info("---[ STOPPED JELLYFINCLIENT: %s ]---", self.server_id)
@classmethod @classmethod
def close_all(cls): def close_all(cls):
@ -92,7 +92,7 @@ class Emby(object):
cls.client[client].stop() cls.client[client].stop()
cls.client = {} cls.client = {}
LOG.info("---[ STOPPED ALL EMBYCLIENTS ]---") LOG.info("---[ STOPPED ALL JELLYFINCLIENTS ]---")
@classmethod @classmethod
def get_active_clients(cls): def get_active_clients(cls):
@ -102,7 +102,7 @@ class Emby(object):
def __setattr__(self, name, value): def __setattr__(self, name, value):
if has_attribute(self, name): if has_attribute(self, name):
return super(Emby, self).__setattr__(name, value) return super(Jellyfin, self).__setattr__(name, value)
setattr(self.client[self.server_id], name, value) setattr(self.client[self.server_id], name, value)
@ -116,11 +116,11 @@ class Emby(object):
def construct(self): def construct(self):
self.client[self.server_id] = EmbyClient() self.client[self.server_id] = JellyfinClient()
if self.server_id == 'default': if self.server_id == 'default':
LOG.info("---[ START EMBYCLIENT ]---") LOG.info("---[ START JELLYFINCLIENT ]---")
else: else:
LOG.info("---[ START EMBYCLIENT: %s ]---", self.server_id) LOG.info("---[ START JELLYFINCLIENT: %s ]---", self.server_id)
config() config()

View file

@ -12,7 +12,7 @@ from core.connection_manager import ConnectionManager, CONNECTION_STATE
################################################################################################# #################################################################################################
LOG = logging.getLogger('Emby.'+__name__) LOG = logging.getLogger('JELLYFIN.'+__name__)
################################################################################################# #################################################################################################
@ -25,18 +25,18 @@ def callback(message, data):
pass pass
class EmbyClient(object): class JellyfinClient(object):
logged_in = False logged_in = False
def __init__(self): def __init__(self):
LOG.debug("EmbyClient initializing...") LOG.debug("JellyfinClient initializing...")
self.config = Config() self.config = Config()
self.http = HTTP(self) self.http = HTTP(self)
self.wsc = WSClient(self) self.wsc = WSClient(self)
self.auth = ConnectionManager(self) self.auth = ConnectionManager(self)
self.emby = api.API(self.http) self.jellyfin = api.API(self.http)
self.callback_ws = callback self.callback_ws = callback
self.callback = callback self.callback = callback
@ -100,7 +100,7 @@ class EmbyClient(object):
return self.auth.__shortcuts__(key.replace('auth/', "", 1)) return self.auth.__shortcuts__(key.replace('auth/', "", 1))
elif key.startswith('api'): elif key.startswith('api'):
return self.emby return self.jellyfin
elif key == 'connected': elif key == 'connected':
return self.logged_in return self.logged_in

View file

@ -2,7 +2,7 @@
################################################################################################# #################################################################################################
def emby_url(client, handler): def jellyfin_url(client, handler):
return "%s/emby/%s" % (client.config['auth.server'], handler) return "%s/emby/%s" % (client.config['auth.server'], handler)
def basic_info(): def basic_info():
@ -50,7 +50,7 @@ class API(object):
################################################################################################# #################################################################################################
# Bigger section of the Emby api # Bigger section of the Jellyfin api
################################################################################################# #################################################################################################
@ -96,9 +96,9 @@ class API(object):
def artwork(self, item_id, art, max_width, ext="jpg", index=None): def artwork(self, item_id, art, max_width, ext="jpg", index=None):
if index is None: if index is None:
return emby_url(self.client, "Items/%s/Images/%s?MaxWidth=%s&format=%s" % (item_id, art, max_width, ext)) return jellyfin_url(self.client, "Items/%s/Images/%s?MaxWidth=%s&format=%s" % (item_id, art, max_width, ext))
return emby_url(self.client, "Items/%s/Images/%s/%s?MaxWidth=%s&format=%s" % (item_id, art, index, max_width, ext)) return jellyfin_url(self.client, "Items/%s/Images/%s/%s?MaxWidth=%s&format=%s" % (item_id, art, index, max_width, ext))
################################################################################################# #################################################################################################
@ -306,13 +306,13 @@ class API(object):
return self.users("/PlayedItems/%s" % item_id, "POST" if watched else "DELETE") return self.users("/PlayedItems/%s" % item_id, "POST" if watched else "DELETE")
def get_sync_queue(self, date, filters=None): def get_sync_queue(self, date, filters=None):
return self._get("Emby.Kodi.SyncQueue/{UserId}/GetItems", params={ return self._get("Jellyfin.Plugin.KodiSyncQueue/{UserId}/GetItems", params={
'LastUpdateDT': date, 'LastUpdateDT': date,
'filter': filters or None 'filter': filters or None
}) })
def get_server_time(self): def get_server_time(self):
return self._get("Emby.Kodi.SyncQueue/GetServerDateTime") return self._get("Jellyfin.Plugin.KodiSyncQueue/GetServerDateTime")
def get_play_info(self, item_id, profile): def get_play_info(self, item_id, profile):
return self.items("/%s/PlaybackInfo" % item_id, "POST", json={ return self.items("/%s/PlaybackInfo" % item_id, "POST", json={

View file

@ -12,7 +12,7 @@ import logging
DEFAULT_HTTP_MAX_RETRIES = 3 DEFAULT_HTTP_MAX_RETRIES = 3
DEFAULT_HTTP_TIMEOUT = 30 DEFAULT_HTTP_TIMEOUT = 30
LOG = logging.getLogger('Emby.'+__name__) LOG = logging.getLogger('JELLYFIN.'+__name__)
################################################################################################# #################################################################################################

View file

@ -14,13 +14,12 @@ from http import HTTP
################################################################################################# #################################################################################################
LOG = logging.getLogger('Emby.'+__name__) LOG = logging.getLogger('JELLYFIN.'+__name__)
CONNECTION_STATE = { CONNECTION_STATE = {
'Unavailable': 0, 'Unavailable': 0,
'ServerSelection': 1, 'ServerSelection': 1,
'ServerSignIn': 2, 'ServerSignIn': 2,
'SignedIn': 3, 'SignedIn': 3,
'ConnectSignIn': 4,
'ServerUpdateNeeded': 5 'ServerUpdateNeeded': 5
} }
CONNECTION_MODE = { CONNECTION_MODE = {
@ -43,7 +42,7 @@ def get_server_address(server, mode):
class ConnectionManager(object): class ConnectionManager(object):
min_server_version = "3.0.5930" min_server_version = "10.1.0"
server_version = min_server_version server_version = min_server_version
user = {} user = {}
server_id = None server_id = None
@ -69,14 +68,6 @@ class ConnectionManager(object):
return self.connect return self.connect
elif key == "login": elif key == "login":
return self.login return self.login
elif key == "login-connect":
return self.login_to_connect
elif key == "connect-user":
return self.connect_user()
elif key == "connect-token":
return self.connect_token()
elif key == "connect-user-id":
return self.connect_user_id()
elif key == "server": elif key == "server":
return self.get_server_info(self.server_id) return self.get_server_info(self.server_id)
elif key == "server-id": elif key == "server-id":
@ -84,11 +75,11 @@ class ConnectionManager(object):
elif key == "server-version": elif key == "server-version":
return self.server_version return self.server_version
elif key == "user-id": elif key == "user-id":
return self.emby_user_id() return self.jellyfin_user_id()
elif key == "public-users": elif key == "public-users":
return self.get_public_users() return self.get_public_users()
elif key == "token": elif key == "token":
return self.emby_token() return self.jellyfin_token()
elif key == "manual-server": elif key == "manual-server":
return self.connect_to_address return self.connect_to_address
elif key == "connect-to-server": elif key == "connect-to-server":
@ -113,8 +104,6 @@ class ConnectionManager(object):
self.user = None self.user = None
credentials = self.credentials.get_credentials() credentials = self.credentials.get_credentials()
credentials['ConnectAccessToken'] = None
credentials['ConnectUserId'] = None
credentials['Servers'] = list() credentials['Servers'] = list()
self.credentials.get_credentials(credentials) self.credentials.get_credentials(credentials)
@ -135,19 +124,14 @@ class ConnectionManager(object):
# Clone the credentials # Clone the credentials
credentials = self.credentials.get_credentials() credentials = self.credentials.get_credentials()
connect_servers = self._get_connect_servers(credentials)
found_servers = self._find_servers(self._server_discovery()) found_servers = self._find_servers(self._server_discovery())
if not connect_servers and not found_servers and not credentials['Servers']: # back out right away, no point in continuing if not found_servers and not credentials['Servers']: # back out right away, no point in continuing
LOG.info("Found no servers") LOG.info("Found no servers")
return list() return list()
servers = list(credentials['Servers']) servers = list(credentials['Servers'])
self._merge_servers(servers, found_servers) self._merge_servers(servers, found_servers)
self._merge_servers(servers, connect_servers)
servers = self._filter_servers(servers, connect_servers)
try: try:
servers.sort(key=lambda x: datetime.strptime(x['DateLastAccessed'], "%Y-%m-%dT%H:%M:%SZ"), reverse=True) servers.sort(key=lambda x: datetime.strptime(x['DateLastAccessed'], "%Y-%m-%dT%H:%M:%SZ"), reverse=True)
@ -159,38 +143,6 @@ class ConnectionManager(object):
return servers return servers
def login_to_connect(self, username, password):
if not username:
raise AttributeError("username cannot be empty")
if not password:
raise AttributeError("password cannot be empty")
try:
result = self._request_url({
'type': "POST",
'url': self.get_connect_url("user/authenticate"),
'data': {
'nameOrEmail': username,
'password': self._get_connect_password_hash(password)
},
'dataType': "json"
})
except Exception as error: # Failed to login
LOG.error(error)
return False
else:
credentials = self.credentials.get_credentials()
credentials['ConnectAccessToken'] = result['AccessToken']
credentials['ConnectUserId'] = result['User']['Id']
credentials['ConnectUser'] = result['User']['DisplayName']
self.credentials.get_credentials(credentials)
# Signed in
self._on_connect_user_signin(result['User'])
return result
def login(self, server, username, password=None, clear=True, options={}): def login(self, server, username, password=None, clear=True, options={}):
if not username: if not username:
@ -202,7 +154,7 @@ class ConnectionManager(object):
try: try:
request = { request = {
'type': "POST", 'type': "POST",
'url': self.get_emby_url(server, "Users/AuthenticateByName"), 'url': self.get_jellyfin_url(server, "Users/AuthenticateByName"),
'json': { 'json': {
'username': username, 'username': username,
'password': hashlib.sha1(password or "").hexdigest(), 'password': hashlib.sha1(password or "").hexdigest(),
@ -274,19 +226,10 @@ class ConnectionManager(object):
LOG.info("Begin connect") LOG.info("Begin connect")
return self._connect_to_servers(self.get_available_servers(), options) return self._connect_to_servers(self.get_available_servers(), options)
def connect_user(self): def jellyfin_user_id(self):
return self.user
def connect_user_id(self):
return self.credentials.get_credentials().get('ConnectUserId')
def connect_token(self):
return self.credentials.get_credentials().get('ConnectAccessToken')
def emby_user_id(self):
return self.get_server_info(self.server_id)['UserId'] return self.get_server_info(self.server_id)['UserId']
def emby_token(self): def jellyfin_token(self):
return self.get_server_info(self.server_id)['AccessToken'] return self.get_server_info(self.server_id)['AccessToken']
def get_server_info(self, server_id): def get_server_info(self, server_id):
@ -302,12 +245,9 @@ class ConnectionManager(object):
return server return server
def get_public_users(self): def get_public_users(self):
return self.client.emby.get_public_users() return self.client.jellyfin.get_public_users()
def get_connect_url(self, handler): def get_jellyfin_url(self, base, handler):
return "https://connect.emby.media/service/%s" % handler
def get_emby_url(self, base, handler):
return "%s/emby/%s" % (base, handler) return "%s/emby/%s" % (base, handler)
def _request_url(self, request, headers=True): def _request_url(self, request, headers=True):
@ -344,12 +284,6 @@ class ConnectionManager(object):
if len(servers) == 1: if len(servers) == 1:
result = self.connect_to_server(servers[0], options) result = self.connect_to_server(servers[0], options)
"""
if result['State'] == CONNECTION_STATE['Unavailable']:
result['State'] = CONNECTION_STATE['ConnectSignIn'] if result['ConnectUser'] is None else CONNECTION_STATE['ServerSelection']
"""
LOG.debug("resolving connectToServers with result['State']: %s", result) LOG.debug("resolving connectToServers with result['State']: %s", result)
return result return result
@ -364,17 +298,15 @@ class ConnectionManager(object):
# Return loaded credentials if exists # Return loaded credentials if exists
credentials = self.credentials.get_credentials() credentials = self.credentials.get_credentials()
self._ensure_connect_user(credentials)
return { return {
'Servers': servers, 'Servers': servers,
'State': CONNECTION_STATE['ConnectSignIn'] if (not len(servers) and not self.connect_user()) else (result.get('State') or CONNECTION_STATE['ServerSelection']), 'State': result.get('State') or CONNECTION_STATE['ServerSelection'],
'ConnectUser': self.connect_user()
} }
def _try_connect(self, url, timeout=None, options={}): def _try_connect(self, url, timeout=None, options={}):
url = self.get_emby_url(url, "system/info/public") url = self.get_jellyfin_url(url, "system/info/public")
LOG.info("tryConnect url: %s", url) LOG.info("tryConnect url: %s", url)
return self._request_url({ return self._request_url({
@ -442,20 +374,11 @@ class ConnectionManager(object):
def _on_successful_connection(self, server, system_info, connection_mode, options): def _on_successful_connection(self, server, system_info, connection_mode, options):
credentials = self.credentials.get_credentials() credentials = self.credentials.get_credentials()
if credentials.get('ConnectAccessToken') and options.get('enableAutoLogin') is not False:
if self._ensure_connect_user(credentials) is not False:
if server.get('ExchangeToken'):
self._add_authentication_info_from_connect(server, connection_mode, credentials, options)
return self._after_connect_validated(server, credentials, system_info, connection_mode, True, options) return self._after_connect_validated(server, credentials, system_info, connection_mode, True, options)
def _resolve_failure(self): def _resolve_failure(self):
return { return {
'State': CONNECTION_STATE['Unavailable'], 'State': CONNECTION_STATE['Unavailable']
'ConnectUser': self.connect_user()
} }
def _get_min_server_version(self, val=None): def _get_min_server_version(self, val=None):
@ -496,27 +419,10 @@ class ConnectionManager(object):
def _string_equals_ignore_case(self, str1, str2): def _string_equals_ignore_case(self, str1, str2):
return (str1 or "").lower() == (str2 or "").lower() return (str1 or "").lower() == (str2 or "").lower()
def _get_connect_user(self, user_id, access_token):
if not user_id:
raise AttributeError("null userId")
if not access_token:
raise AttributeError("null accessToken")
return self._request_url({
'type': "GET",
'url': self.get_connect_url('user?id=%s' % user_id),
'dataType': "json",
'headers': {
'X-Connect-UserToken': access_token
}
})
def _server_discovery(self): def _server_discovery(self):
MULTI_GROUP = ("<broadcast>", 7359) MULTI_GROUP = ("<broadcast>", 7359)
MESSAGE = "who is EmbyServer?" MESSAGE = "who is JellyfinServer?"
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.settimeout(1.0) # This controls the socket.timeout exception sock.settimeout(1.0) # This controls the socket.timeout exception
@ -550,37 +456,6 @@ class ConnectionManager(object):
LOG.error("Error trying to find servers: %s", e) LOG.error("Error trying to find servers: %s", e)
return servers return servers
def _get_connect_servers(self, credentials):
LOG.info("Begin getConnectServers")
servers = list()
if not credentials.get('ConnectAccessToken') or not credentials.get('ConnectUserId'):
return servers
url = self.get_connect_url("servers?userId=%s" % credentials['ConnectUserId'])
request = {
'type': "GET",
'url': url,
'dataType': "json",
'headers': {
'X-Connect-UserToken': credentials['ConnectAccessToken']
}
}
for server in self._request_url(request):
servers.append({
'ExchangeToken': server['AccessKey'],
'ConnectServerId': server['Id'],
'Id': server['SystemId'],
'Name': server['Name'],
'RemoteAddress': server['Url'],
'LocalAddress': server['LocalAddress'],
'UserLinkType': "Guest" if server['UserType'].lower() == "guest" else "LinkedUser",
})
return servers
def _get_last_used_server(self): def _get_last_used_server(self):
servers = self.credentials.get_credentials()['Servers'] servers = self.credentials.get_credentials()['Servers']
@ -624,22 +499,6 @@ class ConnectionManager(object):
else: else:
return servers return servers
def _filter_servers(self, servers, connect_servers):
filtered = list()
for server in servers:
if server.get('ExchangeToken') is None:
# It's not a connect server, so assume it's still valid
filtered.append(server)
continue
for connect_server in connect_servers:
if server['Id'] == connect_server['Id']:
filtered.append(server)
break
return filtered
def _convert_endpoint_address_to_manual_address(self, info): def _convert_endpoint_address_to_manual_address(self, info):
if info.get('Address') and info.get('EndpointAddress'): if info.get('Address') and info.get('EndpointAddress'):
@ -668,45 +527,6 @@ class ConnectionManager(object):
return address return address
def _get_connect_password_hash(self, password):
password = self._clean_connect_password(password)
return hashlib.md5(password).hexdigest()
def _clean_connect_password(self, password):
password = password or ""
password = password.replace("&", '&amp;')
password = password.replace("/", '&#092;')
password = password.replace("!", '&#33;')
password = password.replace("$", '&#036;')
password = password.replace("\"", '&quot;')
password = password.replace("<", '&lt;')
password = password.replace(">", '&gt;')
password = password.replace("'", '&#39;')
return password
def _ensure_connect_user(self, credentials):
if self.user and self.user['Id'] == credentials['ConnectUserId']:
return
elif credentials.get('ConnectUserId') and credentials.get('ConnectAccessToken'):
self.user = None
try:
result = self._get_connect_user(credentials['ConnectUserId'], credentials['ConnectAccessToken'])
self._on_connect_user_signin(result)
except Exception:
return False
def _on_connect_user_signin(self, user):
self.user = user
LOG.info("connectusersignedin %s", user)
def _save_user_info_into_credentials(self, server, user): def _save_user_info_into_credentials(self, server, user):
info = { info = {
@ -715,43 +535,6 @@ class ConnectionManager(object):
} }
self.credentials.add_update_user(server, info) self.credentials.add_update_user(server, info)
def _add_authentication_info_from_connect(self, server, connection_mode, credentials, options={}):
if not server.get('ExchangeToken'):
raise KeyError("server['ExchangeToken'] cannot be null")
if not credentials.get('ConnectUserId'):
raise KeyError("credentials['ConnectUserId'] cannot be null")
auth = "MediaBrowser "
auth += "Client=%s, " % self.config['app.name']
auth += "Device=%s, " % self.config['app.device_name']
auth += "DeviceId=%s, " % self.config['app.device_id']
auth += "Version=%s " % self.config['app.version']
try:
auth = self._request_url({
'url': self.get_emby_url(get_server_address(server, connection_mode), "Connect/Exchange"),
'type': "GET",
'dataType': "json",
'verify': options.get('ssl'),
'params': {
'ConnectUserId': credentials['ConnectUserId']
},
'headers': {
'X-MediaBrowser-Token': server['ExchangeToken'],
'X-Emby-Authorization': auth
}
})
except Exception:
server['UserId'] = None
server['AccessToken'] = None
return False
else:
server['UserId'] = auth['LocalUserId']
server['AccessToken'] = auth['AccessToken']
return auth
def _after_connect_validated(self, server, credentials, system_info, connection_mode, verify_authentication, options): def _after_connect_validated(self, server, credentials, system_info, connection_mode, verify_authentication, options):
if options.get('enableAutoLogin') == False: if options.get('enableAutoLogin') == False:
@ -787,8 +570,7 @@ class ConnectionManager(object):
self.config['auth.ssl'] = options.get('ssl', self.config['auth.ssl']) self.config['auth.ssl'] = options.get('ssl', self.config['auth.ssl'])
result = { result = {
'Servers': [server], 'Servers': [server]
'ConnectUser': self.connect_user()
} }
result['State'] = CONNECTION_STATE['SignedIn'] if server.get('AccessToken') else CONNECTION_STATE['ServerSignIn'] result['State'] = CONNECTION_STATE['SignedIn'] if server.get('AccessToken') else CONNECTION_STATE['ServerSignIn']
@ -800,7 +582,7 @@ class ConnectionManager(object):
try: try:
system_info = self._request_url({ system_info = self._request_url({
'type': "GET", 'type': "GET",
'url': self.get_emby_url(get_server_address(server, connection_mode), "System/Info"), 'url': self.get_jellyfin_url(get_server_address(server, connection_mode), "System/Info"),
'verify': options.get('ssl'), 'verify': options.get('ssl'),
'dataType': "json", 'dataType': "json",
'headers': { 'headers': {

View file

@ -10,7 +10,7 @@ from datetime import datetime
################################################################################################# #################################################################################################
LOG = logging.getLogger('Emby.'+__name__) LOG = logging.getLogger('JELLYFIN.'+__name__)
################################################################################################# #################################################################################################

View file

@ -3,7 +3,7 @@
################################################################################################# #################################################################################################
class HTTPException(Exception): class HTTPException(Exception):
# Emby HTTP exception # Jellyfin HTTP exception
def __init__(self, status, message): def __init__(self, status, message):
self.status = status self.status = status
self.message = message self.message = message

View file

@ -11,7 +11,7 @@ from exceptions import HTTPException
################################################################################################# #################################################################################################
LOG = logging.getLogger('Emby.'+__name__) LOG = logging.getLogger('Jellyfin.'+__name__)
################################################################################################# #################################################################################################
@ -69,7 +69,7 @@ class HTTP(object):
def request(self, data, session=None): def request(self, data, session=None):
''' Give a chance to retry the connection. Emby sometimes can be slow to answer back ''' Give a chance to retry the connection. Jellyfin sometimes can be slow to answer back
data dictionary can contain: data dictionary can contain:
type: GET, POST, etc. type: GET, POST, etc.
url: (optional) url: (optional)

View file

@ -13,7 +13,7 @@ from ..resources import websocket
################################################################################################## ##################################################################################################
LOG = logging.getLogger('Emby.'+__name__) LOG = logging.getLogger('JELLYFIN.'+__name__)
################################################################################################## ##################################################################################################
@ -82,7 +82,7 @@ class WSClient(threading.Thread):
message = json.loads(message) message = json.loads(message)
data = message.get('Data', {}) data = message.get('Data', {})
if message['MessageType'] in ('RefreshProgress'): if message['MessageType'] in ('RefreshProgress',):
LOG.debug("Ignoring %s", message) LOG.debug("Ignoring %s", message)
return return

View file

@ -7,7 +7,7 @@ from uuid import uuid4
################################################################################################# #################################################################################################
LOG = logging.getLogger('Emby.'+__name__) LOG = logging.getLogger('JELLYFIN.'+__name__)
################################################################################################# #################################################################################################

View file

@ -12,17 +12,17 @@ import xbmc
import xbmcgui import xbmcgui
from objects import Movies, TVShows, MusicVideos, Music from objects import Movies, TVShows, MusicVideos, Music
from database import Database, emby_db, get_sync, save_sync from database import Database, jellyfin_db, get_sync, save_sync
from full_sync import FullSync from full_sync import FullSync
from views import Views from views import Views
from downloader import GetItemWorker from downloader import GetItemWorker
from helper import _, api, stop, settings, window, dialog, event, progress, LibraryException from helper import _, api, stop, settings, window, dialog, event, progress, LibraryException
from helper.utils import split_list, set_screensaver, get_screensaver from helper.utils import split_list, set_screensaver, get_screensaver
from emby import Emby from jellyfin import Jellyfin
################################################################################################## ##################################################################################################
LOG = logging.getLogger("EMBY."+__name__) LOG = logging.getLogger("JELLYFIN."+__name__)
LIMIT = min(int(settings('limitIndex') or 50), 50) LIMIT = min(int(settings('limitIndex') or 50), 50)
DTHREADS = int(settings('limitThreads') or 3) DTHREADS = int(settings('limitThreads') or 3)
MEDIA = { MEDIA = {
@ -62,7 +62,7 @@ class Library(threading.Thread):
self.progress_display = int(settings('syncProgress') or 50) self.progress_display = int(settings('syncProgress') or 50)
self.monitor = monitor self.monitor = monitor
self.player = monitor.monitor.player self.player = monitor.monitor.player
self.server = Emby().get_client() self.server = Jellyfin().get_client()
self.updated_queue = Queue.Queue() self.updated_queue = Queue.Queue()
self.userdata_queue = Queue.Queue() self.userdata_queue = Queue.Queue()
self.removed_queue = Queue.Queue() self.removed_queue = Queue.Queue()
@ -71,7 +71,7 @@ class Library(threading.Thread):
self.removed_output = self.__new_queues__() self.removed_output = self.__new_queues__()
self.notify_output = Queue.Queue() self.notify_output = Queue.Queue()
self.emby_threads = [] self.jellyfin_threads = []
self.download_threads = [] self.download_threads = []
self.notify_threads = [] self.notify_threads = []
self.writer_threads = {'updated': [], 'userdata': [], 'removed': []} self.writer_threads = {'updated': [], 'userdata': [], 'removed': []}
@ -101,7 +101,7 @@ class Library(threading.Thread):
if not self.startup(): if not self.startup():
self.stop_client() self.stop_client()
window('emby_startup.bool', True) window('jellyfin_startup.bool', True)
while not self.stop_thread: while not self.stop_thread:
@ -151,7 +151,7 @@ class Library(threading.Thread):
self.worker_notify() self.worker_notify()
if self.pending_refresh: if self.pending_refresh:
window('emby_sync.bool', True) window('jellyfin_sync.bool', True)
if self.total_updates > self.progress_display: if self.total_updates > self.progress_display:
queue_size = self.worker_queue_size() queue_size = self.worker_queue_size()
@ -177,7 +177,7 @@ class Library(threading.Thread):
self.pending_refresh = False self.pending_refresh = False
self.save_last_sync() self.save_last_sync()
self.total_updates = 0 self.total_updates = 0
window('emby_sync', clear=True) window('jellyfin_sync', clear=True)
if self.progress_updates: if self.progress_updates:
@ -206,7 +206,7 @@ class Library(threading.Thread):
''' When there's an active thread. Let the main thread know. ''' When there's an active thread. Let the main thread know.
''' '''
self.pending_refresh = True self.pending_refresh = True
window('emby_sync.bool', True) window('jellyfin_sync.bool', True)
def worker_queue_size(self): def worker_queue_size(self):
@ -227,7 +227,7 @@ class Library(threading.Thread):
def worker_downloads(self): def worker_downloads(self):
''' Get items from emby and place them in the appropriate queues. ''' Get items from jellyfin and place them in the appropriate queues.
''' '''
for queue in ((self.updated_queue, self.updated_output), (self.userdata_queue, self.userdata_output)): for queue in ((self.updated_queue, self.updated_output), (self.userdata_queue, self.userdata_output)):
if queue[0].qsize() and len(self.download_threads) < DTHREADS: if queue[0].qsize() and len(self.download_threads) < DTHREADS:
@ -238,9 +238,9 @@ class Library(threading.Thread):
def worker_sort(self): def worker_sort(self):
''' Get items based on the local emby database and place item in appropriate queues. ''' Get items based on the local jellyfin database and place item in appropriate queues.
''' '''
if self.removed_queue.qsize() and len(self.emby_threads) < 2: if self.removed_queue.qsize() and len(self.jellyfin_threads) < 2:
new_thread = SortWorker(self.removed_queue, self.removed_output) new_thread = SortWorker(self.removed_queue, self.removed_output)
new_thread.start() new_thread.start()
@ -350,10 +350,10 @@ class Library(threading.Thread):
if settings('kodiCompanion.bool'): if settings('kodiCompanion.bool'):
for plugin in self.server['api'].get_plugins(): for plugin in self.server['api'].get_plugins():
if plugin['Name'] in ("Emby.Kodi Sync Queue", "Kodi companion"): if plugin['Name'] in ("Jellyfin.Kodi Sync Queue", "Kodi companion"):
if not self.fast_sync(): if not self.fast_sync():
dialog("ok", heading="{emby}", line1=_(33128)) dialog("ok", heading="{jellyfin}", line1=_(33128))
raise Exception("Failed to retrieve latest updates") raise Exception("Failed to retrieve latest updates")
@ -369,7 +369,7 @@ class Library(threading.Thread):
if error.status in 'SyncLibraryLater': if error.status in 'SyncLibraryLater':
dialog("ok", heading="{emby}", line1=_(33129)) dialog("ok", heading="{jellyfin}", line1=_(33129))
settings('SyncInstallRunDone.bool', True) settings('SyncInstallRunDone.bool', True)
sync = get_sync() sync = get_sync()
sync['Libraries'] = [] sync['Libraries'] = []
@ -379,7 +379,7 @@ class Library(threading.Thread):
elif error.status == 'CompanionMissing': elif error.status == 'CompanionMissing':
dialog("ok", heading="{emby}", line1=_(33099)) dialog("ok", heading="{jellyfin}", line1=_(33099))
settings('kodiCompanion.bool', False) settings('kodiCompanion.bool', False)
return True return True
@ -422,7 +422,7 @@ class Library(threading.Thread):
''' Inverse yes no, in case the dialog is forced closed by Kodi. ''' Inverse yes no, in case the dialog is forced closed by Kodi.
''' '''
if dialog("yesno", heading="{emby}", line1=_(33172).replace('{number}', str(total)), nolabel=_(107), yeslabel=_(106)): if dialog("yesno", heading="{jellyfin}", line1=_(33172).replace('{number}', str(total)), nolabel=_(107), yeslabel=_(106)):
LOG.warn("Large updates skipped.") LOG.warn("Large updates skipped.")
return True return True
@ -482,8 +482,8 @@ class Library(threading.Thread):
whitelist = [x.replace('Mixed:', "") for x in sync['Whitelist']] whitelist = [x.replace('Mixed:', "") for x in sync['Whitelist']]
libraries = [] libraries = []
with Database('emby') as embydb: with Database('jellyfin') as jellyfindb:
db = emby_db.EmbyDatabase(embydb.cursor) db = jellyfin_db.JellyfinDatabase(jellyfindb.cursor)
if mode in ('SyncLibrarySelection', 'RepairLibrarySelection', 'RemoveLibrarySelection'): if mode in ('SyncLibrarySelection', 'RepairLibrarySelection', 'RemoveLibrarySelection'):
for library in sync['Whitelist']: for library in sync['Whitelist']:
@ -614,7 +614,7 @@ class UpdatedWorker(threading.Thread):
with self.lock: with self.lock:
with self.database as kodidb: with self.database as kodidb:
with Database('emby') as embydb: with Database('jellyfin') as jellyfindb:
while True: while True:
@ -623,7 +623,7 @@ class UpdatedWorker(threading.Thread):
except Queue.Empty: except Queue.Empty:
break break
obj = MEDIA[item['Type']](self.args[0], embydb, kodidb, self.args[1])[item['Type']] obj = MEDIA[item['Type']](self.args[0], jellyfindb, kodidb, self.args[1])[item['Type']]
try: try:
if obj(item) and self.notify: if obj(item) and self.notify:
@ -636,7 +636,7 @@ class UpdatedWorker(threading.Thread):
self.queue.task_done() self.queue.task_done()
if window('emby_should_stop.bool'): if window('jellyfin_should_stop.bool'):
break break
LOG.info("--<[ q:updated/%s ]", id(self)) LOG.info("--<[ q:updated/%s ]", id(self))
@ -658,7 +658,7 @@ class UserDataWorker(threading.Thread):
with self.lock: with self.lock:
with self.database as kodidb: with self.database as kodidb:
with Database('emby') as embydb: with Database('jellyfin') as jellyfindb:
while True: while True:
@ -667,7 +667,7 @@ class UserDataWorker(threading.Thread):
except Queue.Empty: except Queue.Empty:
break break
obj = MEDIA[item['Type']](self.args[0], embydb, kodidb, self.args[1])['UserData'] obj = MEDIA[item['Type']](self.args[0], jellyfindb, kodidb, self.args[1])['UserData']
try: try:
obj(item) obj(item)
@ -679,7 +679,7 @@ class UserDataWorker(threading.Thread):
self.queue.task_done() self.queue.task_done()
if window('emby_should_stop.bool'): if window('jellyfin_should_stop.bool'):
break break
LOG.info("--<[ q:userdata/%s ]", id(self)) LOG.info("--<[ q:userdata/%s ]", id(self))
@ -698,8 +698,8 @@ class SortWorker(threading.Thread):
def run(self): def run(self):
with Database('emby') as embydb: with Database('jellyfin') as jellyfindb:
database = emby_db.EmbyDatabase(embydb.cursor) database = jellyfin_db.JellyfinDatabase(jellyfindb.cursor)
while True: while True:
@ -715,14 +715,14 @@ class SortWorker(threading.Thread):
items = database.get_media_by_parent_id(item_id) items = database.get_media_by_parent_id(item_id)
if not items: if not items:
LOG.info("Could not find media %s in the emby database.", item_id) LOG.info("Could not find media %s in the jellyfin database.", item_id)
else: else:
for item in items: for item in items:
self.output[item[1]].put({'Id': item[0], 'Type': item[1]}) self.output[item[1]].put({'Id': item[0], 'Type': item[1]})
self.queue.task_done() self.queue.task_done()
if window('emby_should_stop.bool'): if window('jellyfin_should_stop.bool'):
break break
LOG.info("--<[ q:sort/%s ]", id(self)) LOG.info("--<[ q:sort/%s ]", id(self))
@ -744,7 +744,7 @@ class RemovedWorker(threading.Thread):
with self.lock: with self.lock:
with self.database as kodidb: with self.database as kodidb:
with Database('emby') as embydb: with Database('jellyfin') as jellyfindb:
while True: while True:
@ -753,7 +753,7 @@ class RemovedWorker(threading.Thread):
except Queue.Empty: except Queue.Empty:
break break
obj = MEDIA[item['Type']](self.args[0], embydb, kodidb, self.args[1])['Remove'] obj = MEDIA[item['Type']](self.args[0], jellyfindb, kodidb, self.args[1])['Remove']
try: try:
obj(item['Id']) obj(item['Id'])
@ -765,7 +765,7 @@ class RemovedWorker(threading.Thread):
self.queue.task_done() self.queue.task_done()
if window('emby_should_stop.bool'): if window('jellyfin_should_stop.bool'):
break break
LOG.info("--<[ q:removed/%s ]", id(self)) LOG.info("--<[ q:removed/%s ]", id(self))
@ -796,11 +796,11 @@ class NotifyWorker(threading.Thread):
if time and (not self.player.isPlayingVideo() or xbmc.getCondVisibility('VideoPlayer.Content(livetv)')): if time and (not self.player.isPlayingVideo() or xbmc.getCondVisibility('VideoPlayer.Content(livetv)')):
dialog("notification", heading="%s %s" % (_(33049), item[0]), message=item[1], dialog("notification", heading="%s %s" % (_(33049), item[0]), message=item[1],
icon="{emby}", time=time, sound=False) icon="{jellyfin}", time=time, sound=False)
self.queue.task_done() self.queue.task_done()
if window('emby_should_stop.bool'): if window('jellyfin_should_stop.bool'):
break break
LOG.info("--<[ q:notify/%s ]", id(self)) LOG.info("--<[ q:notify/%s ]", id(self))

View file

@ -17,12 +17,12 @@ import player
from client import get_device_id from client import get_device_id
from objects import Actions, PlaylistWorker, on_play, on_update, special_listener from objects import Actions, PlaylistWorker, on_play, on_update, special_listener
from helper import _, settings, window, dialog, event, api, JSONRPC from helper import _, settings, window, dialog, event, api, JSONRPC
from emby import Emby from jellyfin import Jellyfin
from webservice import WebService from webservice import WebService
################################################################################################# #################################################################################################
LOG = logging.getLogger("EMBY."+__name__) LOG = logging.getLogger("JELLYFIN."+__name__)
################################################################################################# #################################################################################################
@ -50,10 +50,10 @@ class Monitor(xbmc.Monitor):
def onNotification(self, sender, method, data): def onNotification(self, sender, method, data):
if sender.lower() not in ('plugin.video.emby', 'xbmc', 'upnextprovider.signal'): if sender.lower() not in ('plugin.video.jellyfin', 'xbmc', 'upnextprovider.signal'):
return return
if sender == 'plugin.video.emby': if sender == 'plugin.video.jellyfin':
method = method.split('.')[1] method = method.split('.')[1]
if method not in ('GetItem', 'ReportProgressRequested', 'LoadServer', 'RandomItems', 'Recommended', if method not in ('GetItem', 'ReportProgressRequested', 'LoadServer', 'RandomItems', 'Recommended',
@ -69,7 +69,7 @@ class Monitor(xbmc.Monitor):
elif sender.startswith('upnextprovider'): elif sender.startswith('upnextprovider'):
method = method.split('.')[1] method = method.split('.')[1]
if method not in ('plugin.video.emby_play_action'): if method not in ('plugin.video.jellyfin_play_action',):
return return
data = json.loads(data) data = json.loads(data)
@ -114,13 +114,13 @@ class Monitor(xbmc.Monitor):
except Exception as error: except Exception as error:
LOG.error(error) LOG.error(error)
dialog("ok", heading="{emby}", line1=_(33142)) dialog("ok", heading="{jellyfin}", line1=_(33142))
return return
server = Emby(data['ServerId']) server = Jellyfin(data['ServerId'])
except Exception: except Exception:
server = Emby() server = Jellyfin()
if method == 'GetItem': if method == 'GetItem':
@ -169,7 +169,7 @@ class Monitor(xbmc.Monitor):
elif method == 'GetUsers': elif method == 'GetUsers':
users = server['api'].get_users(data.get('IsDisabled', True), data.get('IsHidden', True)) users = server['api'].get_users()
self.void_responder(data, users) self.void_responder(data, users)
elif method == 'GetTranscodeOptions': elif method == 'GetTranscodeOptions':
@ -272,12 +272,12 @@ class Monitor(xbmc.Monitor):
def void_responder(self, data, result): def void_responder(self, data, result):
window('emby_%s.json' % data['VoidName'], result) window('jellyfin_%s.json' % data['VoidName'], result)
LOG.debug("--->[ nostromo/emby_%s.json ] sent", data['VoidName']) LOG.debug("--->[ nostromo/jellyfin_%s.json ] sent", data['VoidName'])
def server_instance(self, server_id=None): def server_instance(self, server_id=None):
server = Emby(server_id) server = Jellyfin(server_id)
self.post_capabilities(server) self.post_capabilities(server)
if server_id is not None: if server_id is not None:
@ -312,7 +312,7 @@ class Monitor(xbmc.Monitor):
"Mute,Unmute,SetVolume," "Mute,Unmute,SetVolume,"
"Play,Playstate,PlayNext,PlayMediaSource" "Play,Playstate,PlayNext,PlayMediaSource"
), ),
'IconUrl': "https://raw.githubusercontent.com/MediaBrowser/plugin.video.emby/develop/kodi_icon.png", 'IconUrl': "https://raw.githubusercontent.com/jellyfin/jellyfin-kodi/master/kodi_icon.png",
}) })
session = server['api'].get_device(self.device_id) session = server['api'].get_device(self.device_id)
@ -323,7 +323,7 @@ class Monitor(xbmc.Monitor):
''' Setup additional users images. ''' Setup additional users images.
''' '''
for i in range(10): for i in range(10):
window('EmbyAdditionalUserImage.%s' % i, clear=True) window('JellyfinAdditionalUserImage.%s' % i, clear=True)
try: try:
session = server['api'].get_device(self.device_id) session = server['api'].get_device(self.device_id)
@ -336,12 +336,12 @@ class Monitor(xbmc.Monitor):
info = server['api'].get_user(user['UserId']) info = server['api'].get_user(user['UserId'])
image = api.API(info, server['config/auth.server']).get_user_artwork(user['UserId']) image = api.API(info, server['config/auth.server']).get_user_artwork(user['UserId'])
window('EmbyAdditionalUserImage.%s' % index, image) window('JellyfinAdditionalUserImage.%s' % index, image)
window('EmbyAdditionalUserPosition.%s' % user['UserId'], str(index)) window('JellyfinAdditionalUserPosition.%s' % user['UserId'], str(index))
def playstate(self, data): def playstate(self, data):
''' Emby playstate updates. ''' Jellyfin playstate updates.
''' '''
command = data['Command'] command = data['Command']
actions = { actions = {
@ -367,7 +367,7 @@ class Monitor(xbmc.Monitor):
def general_commands(self, data): def general_commands(self, data):
''' General commands from Emby to control the Kodi interface. ''' General commands from Jellyfin to control the Kodi interface.
''' '''
command = data['Name'] command = data['Name']
args = data['Arguments'] args = data['Arguments']
@ -392,7 +392,7 @@ class Monitor(xbmc.Monitor):
elif command == 'DisplayMessage': elif command == 'DisplayMessage':
dialog("notification", heading=args['Header'], message=args['Text'], dialog("notification", heading=args['Header'], message=args['Text'],
icon="{emby}", time=int(settings('displayMessage'))*1000) icon="{jellyfin}", time=int(settings('displayMessage'))*1000)
elif command == 'SendString': elif command == 'SendString':
JSONRPC('Input.SendText').execute({'text': args['String'], 'done': False}) JSONRPC('Input.SendText').execute({'text': args['String'], 'done': False})

View file

@ -18,12 +18,11 @@ from downloader import TheVoid
from obj import Objects from obj import Objects
from helper import _, playutils, api, window, settings, dialog, JSONRPC from helper import _, playutils, api, window, settings, dialog, JSONRPC
from dialogs import resume from dialogs import resume
from emby import Emby
from utils import get_play_action from utils import get_play_action
################################################################################################# #################################################################################################
LOG = logging.getLogger("EMBY."+__name__) LOG = logging.getLogger("JELLYFIN."+__name__)
################################################################################################# #################################################################################################
@ -89,8 +88,8 @@ class Actions(object):
Detect the seektime for video type content. Detect the seektime for video type content.
Verify the default video action set in Kodi for accurate resume behavior. Verify the default video action set in Kodi for accurate resume behavior.
''' '''
seektime = window('emby.resume.bool') seektime = window('jellyfin.resume.bool')
window('emby.resume', clear=True) window('jellyfin.resume', clear=True)
if item['MediaType'] in ('Video', 'Audio'): if item['MediaType'] in ('Video', 'Audio'):
resume = item['UserData'].get('PlaybackPositionTicks') resume = item['UserData'].get('PlaybackPositionTicks')
@ -128,7 +127,7 @@ class Actions(object):
if settings('askCinema') == "true": if settings('askCinema') == "true":
resp = dialog("yesno", heading="{emby}", line1=_(33016)) resp = dialog("yesno", heading="{jellyfin}", line1=_(33016))
if not resp: if not resp:
enabled = False enabled = False
@ -148,7 +147,7 @@ class Actions(object):
self.stack.append([intro['PlaybackInfo']['Path'], listitem]) self.stack.append([intro['PlaybackInfo']['Path'], listitem])
window('emby.skip.%s' % intro['Id'], value="true") window('jellyfin.skip.%s' % intro['Id'], value="true")
def _set_additional_parts(self, item_id): def _set_additional_parts(self, item_id):
@ -215,7 +214,7 @@ class Actions(object):
LOG.info("[ playlist/%s ] %s", item['Id'], item['Name']) LOG.info("[ playlist/%s ] %s", item['Id'], item['Name'])
self.set_listitem(item, listitem, None, False) self.set_listitem(item, listitem, None, False)
path = "plugin://plugin.video.emby/?mode=play&id=%s&playlist=true" % item['Id'] path = "plugin://plugin.video.jellyfin/?mode=play&id=%s&playlist=true" % item['Id']
listitem.setPath(path) listitem.setPath(path)
playlist.add(path, listitem, index) playlist.add(path, listitem, index)
@ -239,7 +238,7 @@ class Actions(object):
obj['Artwork'] = API.get_all_artwork(objects.map(item, 'Artwork')) obj['Artwork'] = API.get_all_artwork(objects.map(item, 'Artwork'))
self.listitem_photo(obj, listitem, item) self.listitem_photo(obj, listitem, item)
elif item['Type'] in ('TvChannel'): elif item['Type'] in ('TvChannel',):
obj = objects.map(item, 'BrowseChannel') obj = objects.map(item, 'BrowseChannel')
obj['Artwork'] = API.get_all_artwork(objects.map(item, 'Artwork')) obj['Artwork'] = API.get_all_artwork(objects.map(item, 'Artwork'))
@ -312,9 +311,9 @@ class Actions(object):
obj['Artwork']['Thumb'] = obj['Artwork']['Thumb'] or "" obj['Artwork']['Thumb'] = obj['Artwork']['Thumb'] or ""
if not intro and not obj['Type'] == 'Trailer': if not intro and not obj['Type'] == 'Trailer':
obj['Artwork']['Primary'] = obj['Artwork']['Primary'] or "special://home/addons/plugin.video.emby/icon.png" obj['Artwork']['Primary'] = obj['Artwork']['Primary'] or "special://home/addons/plugin.video.jellyfin/icon.png"
else: else:
obj['Artwork']['Primary'] = obj['Artwork']['Primary'] or obj['Artwork']['Thumb'] or (obj['Artwork']['Backdrop'][0] if len(obj['Artwork']['Backdrop']) else "special://home/addons/plugin.video.emby/fanart.jpg") obj['Artwork']['Primary'] = obj['Artwork']['Primary'] or obj['Artwork']['Thumb'] or (obj['Artwork']['Backdrop'][0] if len(obj['Artwork']['Backdrop']) else "special://home/addons/plugin.video.jellyfin/fanart.jpg")
obj['Artwork']['Primary'] += "&KodiTrailer=true" if obj['Type'] == 'Trailer' else "&KodiCinemaMode=true" obj['Artwork']['Primary'] += "&KodiTrailer=true" if obj['Type'] == 'Trailer' else "&KodiCinemaMode=true"
obj['Artwork']['Backdrop'] = [obj['Artwork']['Primary']] obj['Artwork']['Backdrop'] = [obj['Artwork']['Primary']]
@ -472,9 +471,9 @@ class Actions(object):
obj['Runtime'] = round(float((obj['Runtime'] or 0) / 10000000.0), 6) obj['Runtime'] = round(float((obj['Runtime'] or 0) / 10000000.0), 6)
obj['PlayCount'] = API.get_playcount(obj['Played'], obj['PlayCount']) or 0 obj['PlayCount'] = API.get_playcount(obj['Played'], obj['PlayCount']) or 0
obj['Overlay'] = 7 if obj['Played'] else 6 obj['Overlay'] = 7 if obj['Played'] else 6
obj['Artwork']['Primary'] = obj['Artwork']['Primary'] or "special://home/addons/plugin.video.emby/icon.png" obj['Artwork']['Primary'] = obj['Artwork']['Primary'] or "special://home/addons/plugin.video.jellyfin/icon.png"
obj['Artwork']['Thumb'] = obj['Artwork']['Thumb'] or "special://home/addons/plugin.video.emby/fanart.jpg" obj['Artwork']['Thumb'] = obj['Artwork']['Thumb'] or "special://home/addons/plugin.video.jellyfin/fanart.jpg"
obj['Artwork']['Backdrop'] = obj['Artwork']['Backdrop'] or ["special://home/addons/plugin.video.emby/fanart.jpg"] obj['Artwork']['Backdrop'] = obj['Artwork']['Backdrop'] or ["special://home/addons/plugin.video.jellyfin/fanart.jpg"]
metadata = { metadata = {
@ -657,9 +656,9 @@ class Actions(object):
''' Base resume dialog based on Kodi settings. ''' Base resume dialog based on Kodi settings.
''' '''
LOG.info("Resume dialog called.") LOG.info("Resume dialog called.")
XML_PATH = (xbmcaddon.Addon('plugin.video.emby').getAddonInfo('path'), "default", "1080i") XML_PATH = (xbmcaddon.Addon('plugin.video.jellyfin').getAddonInfo('path'), "default", "1080i")
dialog = resume.ResumeDialog("script-emby-resume.xml", *XML_PATH) dialog = resume.ResumeDialog("script-jellyfin-resume.xml", *XML_PATH)
dialog.set_resume_point("Resume from %s" % str(timedelta(seconds=seektime)).split(".")[0]) dialog.set_resume_point("Resume from %s" % str(timedelta(seconds=seektime)).split(".")[0])
dialog.doModal() dialog.doModal()
@ -721,14 +720,14 @@ def on_update(data, server):
if item: if item:
if not window('emby.skip.%s.bool' % item[0]): if not window('jellyfin.skip.%s.bool' % item[0]):
server['api'].item_played(item[0], playcount) server['api'].item_played(item[0], playcount)
window('emby.skip.%s' % item[0], clear=True) window('jellyfin.skip.%s' % item[0], clear=True)
def on_play(data, server): def on_play(data, server):
''' Setup progress for emby playback. ''' Setup progress for jellyfin playback.
''' '''
player = xbmc.Player() player = xbmc.Player()
@ -781,7 +780,7 @@ def special_listener():
''' '''
player = xbmc.Player() player = xbmc.Player()
isPlaying = player.isPlaying() isPlaying = player.isPlaying()
count = int(window('emby.external_count') or 0) count = int(window('jellyfin.external_count') or 0)
if (not isPlaying and xbmc.getCondVisibility('Window.IsVisible(DialogContextMenu.xml)') and if (not isPlaying and xbmc.getCondVisibility('Window.IsVisible(DialogContextMenu.xml)') and
xbmc.getInfoLabel('Control.GetLabel(1002)') == xbmc.getLocalizedString(12021)): xbmc.getInfoLabel('Control.GetLabel(1002)') == xbmc.getLocalizedString(12021)):
@ -791,24 +790,24 @@ def special_listener():
if control == 1002: # Start from beginning if control == 1002: # Start from beginning
LOG.info("Resume dialog: Start from beginning selected.") LOG.info("Resume dialog: Start from beginning selected.")
window('emby.resume.bool', False) window('jellyfin.resume.bool', False)
else: else:
LOG.info("Resume dialog: Resume selected.") LOG.info("Resume dialog: Resume selected.")
window('emby.resume.bool', True) window('jellyfin.resume.bool', True)
elif isPlaying and not window('emby.external_check'): elif isPlaying and not window('jellyfin.external_check'):
time = player.getTime() time = player.getTime()
if time > 1: # Not external player. if time > 1: # Not external player.
window('emby.external_check', value="true") window('jellyfin.external_check', value="true")
window('emby.external_count', value="0") window('jellyfin.external_count', value="0")
elif count == 120: elif count == 120:
LOG.info("External player detected.") LOG.info("External player detected.")
window('emby.external.bool', True) window('jellyfin.external.bool', True)
window('emby.external_check.bool', True) window('jellyfin.external_check.bool', True)
window('emby.external_count', value="0") window('jellyfin.external_count', value="0")
elif time == 0: elif time == 0:
window('emby.external_count', value=str(count + 1)) window('jellyfin.external_count', value=str(count + 1))

View file

@ -17,7 +17,7 @@ import requests
################################################################################################## ##################################################################################################
LOG = logging.getLogger("EMBY."+__name__) LOG = logging.getLogger("JELLYFIN."+__name__)
################################################################################################## ##################################################################################################
@ -247,7 +247,7 @@ from __objs__ import QU
################################################################################################## ##################################################################################################
log = logging.getLogger("EMBY."+__name__) log = logging.getLogger("JELLYFIN."+__name__)
################################################################################################## ##################################################################################################
@ -278,7 +278,7 @@ class Artwork(object):
# This method will sync all Kodi artwork to textures13.db # This method will sync all Kodi artwork to textures13.db
# and cache them locally. This takes diskspace! # and cache them locally. This takes diskspace!
if not dialog(type_="yesno", if not dialog(type_="yesno",
heading="{emby}", heading="{jellyfin}",
line1=_(33042)): line1=_(33042)):
return return
@ -288,7 +288,7 @@ class Artwork(object):
pdialog.create(_(29999), _(33043)) pdialog.create(_(29999), _(33043))
# ask to rest all existing or not # ask to rest all existing or not
if dialog(type_="yesno", heading="{emby}", line1=_(33044)): if dialog(type_="yesno", heading="{jellyfin}", line1=_(33044)):
log.info("Resetting all cache data first") log.info("Resetting all cache data first")
self.delete_cache() self.delete_cache()

View file

@ -12,7 +12,7 @@ from helper import values
################################################################################################## ##################################################################################################
LOG = logging.getLogger("EMBY."+__name__) LOG = logging.getLogger("JELLYFIN."+__name__)
################################################################################################## ##################################################################################################

View file

@ -9,7 +9,7 @@ import queries as QU
################################################################################################## ##################################################################################################
LOG = logging.getLogger("EMBY."+__name__) LOG = logging.getLogger("JELLYFIN."+__name__)
################################################################################################## ##################################################################################################

View file

@ -9,7 +9,7 @@ from kodi import Kodi
################################################################################################## ##################################################################################################
LOG = logging.getLogger("EMBY."+__name__) LOG = logging.getLogger("JELLYFIN."+__name__)
################################################################################################## ##################################################################################################

View file

@ -9,7 +9,7 @@ from kodi import Kodi
################################################################################################## ##################################################################################################
log = logging.getLogger("EMBY."+__name__) log = logging.getLogger("JELLYFIN."+__name__)
################################################################################################## ##################################################################################################

View file

@ -1,5 +1,5 @@
''' Queries for the Kodi database. obj reflect key/value to retrieve from emby items. ''' Queries for the Kodi database. obj reflect key/value to retrieve from jellyfin items.
Some functions require additional information, therefore obj do not always reflect Some functions require additional information, therefore obj do not always reflect
the Kodi database query values. the Kodi database query values.
''' '''

View file

@ -9,7 +9,7 @@ from kodi import Kodi
################################################################################################## ##################################################################################################
LOG = logging.getLogger("EMBY."+__name__) LOG = logging.getLogger("JELLYFIN."+__name__)
################################################################################################## ##################################################################################################

View file

@ -9,26 +9,26 @@ import urllib
import downloader as server import downloader as server
from obj import Objects from obj import Objects
from kodi import Movies as KodiDb, queries as QU from kodi import Movies as KodiDb, queries as QU
from database import emby_db, queries as QUEM from database import jellyfin_db, queries as QUEM
from helper import api, catch, stop, validate, emby_item, library_check, values, settings, Local from helper import api, catch, stop, validate, jellyfin_item, library_check, values, settings, Local
################################################################################################## ##################################################################################################
LOG = logging.getLogger("EMBY."+__name__) LOG = logging.getLogger("JELLYFIN."+__name__)
################################################################################################## ##################################################################################################
class Movies(KodiDb): class Movies(KodiDb):
def __init__(self, server, embydb, videodb, direct_path): def __init__(self, server, jellyfindb, videodb, direct_path):
self.server = server self.server = server
self.emby = embydb self.jellyfin = jellyfindb
self.video = videodb self.video = videodb
self.direct_path = direct_path self.direct_path = direct_path
self.emby_db = emby_db.EmbyDatabase(embydb.cursor) self.jellyfin_db = jellyfin_db.JellyfinDatabase(jellyfindb.cursor)
self.objects = Objects() self.objects = Objects()
self.item_ids = [] self.item_ids = []
@ -46,7 +46,7 @@ class Movies(KodiDb):
return self.remove return self.remove
@stop() @stop()
@emby_item() @jellyfin_item()
@library_check() @library_check()
def movie(self, item, e_item, library): def movie(self, item, e_item, library):
@ -146,7 +146,7 @@ class Movies(KodiDb):
obj['FileId'] = self.add_file(*values(obj, QU.add_file_obj)) obj['FileId'] = self.add_file(*values(obj, QU.add_file_obj))
self.add(*values(obj, QU.add_movie_obj)) self.add(*values(obj, QU.add_movie_obj))
self.emby_db.add_reference(*values(obj, QUEM.add_reference_movie_obj)) self.jellyfin_db.add_reference(*values(obj, QUEM.add_reference_movie_obj))
LOG.info("ADD movie [%s/%s/%s] %s: %s", obj['PathId'], obj['FileId'], obj['MovieId'], obj['Id'], obj['Title']) LOG.info("ADD movie [%s/%s/%s] %s: %s", obj['PathId'], obj['FileId'], obj['MovieId'], obj['Id'], obj['Title'])
def movie_update(self, obj): def movie_update(self, obj):
@ -160,7 +160,7 @@ class Movies(KodiDb):
self.update_unique_id(*values(obj, QU.update_unique_id_movie_obj)) self.update_unique_id(*values(obj, QU.update_unique_id_movie_obj))
self.update(*values(obj, QU.update_movie_obj)) self.update(*values(obj, QU.update_movie_obj))
self.emby_db.update_reference(*values(obj, QUEM.update_reference_obj)) self.jellyfin_db.update_reference(*values(obj, QUEM.update_reference_obj))
LOG.info("UPDATE movie [%s/%s/%s] %s: %s", obj['PathId'], obj['FileId'], obj['MovieId'], obj['Id'], obj['Title']) LOG.info("UPDATE movie [%s/%s/%s] %s: %s", obj['PathId'], obj['FileId'], obj['MovieId'], obj['Id'], obj['Title'])
def trailer(self, obj): def trailer(self, obj):
@ -169,7 +169,7 @@ class Movies(KodiDb):
if obj['LocalTrailer']: if obj['LocalTrailer']:
trailer = self.server['api'].get_local_trailers(obj['Id']) trailer = self.server['api'].get_local_trailers(obj['Id'])
obj['Trailer'] = "plugin://plugin.video.emby/trailer?id=%s&mode=play" % trailer[0]['Id'] obj['Trailer'] = "plugin://plugin.video.jellyfin/trailer?id=%s&mode=play" % trailer[0]['Id']
elif obj['Trailer']: elif obj['Trailer']:
obj['Trailer'] = "plugin://plugin.video.youtube/play/?video_id=%s" % obj['Trailer'].rsplit('=', 1)[1] obj['Trailer'] = "plugin://plugin.video.youtube/play/?video_id=%s" % obj['Trailer'].rsplit('=', 1)[1]
@ -192,7 +192,7 @@ class Movies(KodiDb):
obj['Path'] = obj['Path'].replace(obj['Filename'], "") obj['Path'] = obj['Path'].replace(obj['Filename'], "")
else: else:
obj['Path'] = "plugin://plugin.video.emby.movies/" obj['Path'] = "plugin://plugin.video.jellyfin/"
params = { params = {
'filename': obj['Filename'].encode('utf-8'), 'filename': obj['Filename'].encode('utf-8'),
'id': obj['Id'], 'id': obj['Id'],
@ -203,7 +203,7 @@ class Movies(KodiDb):
@stop() @stop()
@emby_item() @jellyfin_item()
def boxset(self, item, e_item): def boxset(self, item, e_item):
''' If item does not exist, entry will be added. ''' If item does not exist, entry will be added.
@ -234,11 +234,11 @@ class Movies(KodiDb):
temp_obj['Movie'] = movie temp_obj['Movie'] = movie
temp_obj['MovieId'] = obj['Current'][temp_obj['Movie']] temp_obj['MovieId'] = obj['Current'][temp_obj['Movie']]
self.remove_from_boxset(*values(temp_obj, QU.delete_movie_set_obj)) self.remove_from_boxset(*values(temp_obj, QU.delete_movie_set_obj))
self.emby_db.update_parent_id(*values(temp_obj, QUEM.delete_parent_boxset_obj)) self.jellyfin_db.update_parent_id(*values(temp_obj, QUEM.delete_parent_boxset_obj))
LOG.info("DELETE from boxset [%s] %s: %s", temp_obj['SetId'], temp_obj['Title'], temp_obj['MovieId']) LOG.info("DELETE from boxset [%s] %s: %s", temp_obj['SetId'], temp_obj['Title'], temp_obj['MovieId'])
self.artwork.add(obj['Artwork'], obj['SetId'], "set") self.artwork.add(obj['Artwork'], obj['SetId'], "set")
self.emby_db.add_reference(*values(obj, QUEM.add_reference_boxset_obj)) self.jellyfin_db.add_reference(*values(obj, QUEM.add_reference_boxset_obj))
LOG.info("UPDATE boxset [%s] %s", obj['SetId'], obj['Title']) LOG.info("UPDATE boxset [%s] %s", obj['SetId'], obj['Title'])
def boxset_current(self, obj): def boxset_current(self, obj):
@ -246,7 +246,7 @@ class Movies(KodiDb):
''' Add or removes movies based on the current movies found in the boxset. ''' Add or removes movies based on the current movies found in the boxset.
''' '''
try: try:
current = self.emby_db.get_item_id_by_parent_id(*values(obj, QUEM.get_item_id_by_parent_boxset_obj)) current = self.jellyfin_db.get_item_id_by_parent_id(*values(obj, QUEM.get_item_id_by_parent_boxset_obj))
movies = dict(current) movies = dict(current)
except ValueError: except ValueError:
movies = {} movies = {}
@ -261,7 +261,7 @@ class Movies(KodiDb):
temp_obj['Id'] = movie['Id'] temp_obj['Id'] = movie['Id']
try: try:
temp_obj['MovieId'] = self.emby_db.get_item_by_id(*values(temp_obj, QUEM.get_item_obj))[0] temp_obj['MovieId'] = self.jellyfin_db.get_item_by_id(*values(temp_obj, QUEM.get_item_obj))[0]
except TypeError: except TypeError:
LOG.info("Failed to process %s to boxset.", temp_obj['Title']) LOG.info("Failed to process %s to boxset.", temp_obj['Title'])
@ -270,7 +270,7 @@ class Movies(KodiDb):
if temp_obj['Id'] not in obj['Current']: if temp_obj['Id'] not in obj['Current']:
self.set_boxset(*values(temp_obj, QU.update_movie_set_obj)) self.set_boxset(*values(temp_obj, QU.update_movie_set_obj))
self.emby_db.update_parent_id(*values(temp_obj, QUEM.update_parent_movie_obj)) self.jellyfin_db.update_parent_id(*values(temp_obj, QUEM.update_parent_movie_obj))
LOG.info("ADD to boxset [%s/%s] %s: %s to boxset", temp_obj['SetId'], temp_obj['MovieId'], temp_obj['Title'], temp_obj['Id']) LOG.info("ADD to boxset [%s/%s] %s: %s to boxset", temp_obj['SetId'], temp_obj['MovieId'], temp_obj['Title'], temp_obj['Id'])
else: else:
obj['Current'].pop(temp_obj['Id']) obj['Current'].pop(temp_obj['Id'])
@ -279,12 +279,12 @@ class Movies(KodiDb):
''' Special function to remove all existing boxsets. ''' Special function to remove all existing boxsets.
''' '''
boxsets = self.emby_db.get_items_by_media('set') boxsets = self.jellyfin_db.get_items_by_media('set')
for boxset in boxsets: for boxset in boxsets:
self.remove(boxset[0]) self.remove(boxset[0])
@stop() @stop()
@emby_item() @jellyfin_item()
def userdata(self, item, e_item): def userdata(self, item, e_item):
''' This updates: Favorite, LastPlayedDate, Playcount, PlaybackPositionTicks ''' This updates: Favorite, LastPlayedDate, Playcount, PlaybackPositionTicks
@ -313,14 +313,14 @@ class Movies(KodiDb):
LOG.debug("New resume point %s: %s", obj['Id'], obj['Resume']) LOG.debug("New resume point %s: %s", obj['Id'], obj['Resume'])
self.add_playstate(*values(obj, QU.add_bookmark_obj)) self.add_playstate(*values(obj, QU.add_bookmark_obj))
self.emby_db.update_reference(*values(obj, QUEM.update_reference_obj)) self.jellyfin_db.update_reference(*values(obj, QUEM.update_reference_obj))
LOG.info("USERDATA movie [%s/%s] %s: %s", obj['FileId'], obj['MovieId'], obj['Id'], obj['Title']) LOG.info("USERDATA movie [%s/%s] %s: %s", obj['FileId'], obj['MovieId'], obj['Id'], obj['Title'])
@stop() @stop()
@emby_item() @jellyfin_item()
def remove(self, item_id, e_item): def remove(self, item_id, e_item):
''' Remove movieid, fileid, emby reference. ''' Remove movieid, fileid, jellyfin reference.
Remove artwork, boxset Remove artwork, boxset
''' '''
obj = {'Id': item_id} obj = {'Id': item_id}
@ -338,15 +338,15 @@ class Movies(KodiDb):
self.delete(*values(obj, QU.delete_movie_obj)) self.delete(*values(obj, QU.delete_movie_obj))
elif obj['Media'] == 'set': elif obj['Media'] == 'set':
for movie in self.emby_db.get_item_by_parent_id(*values(obj, QUEM.get_item_by_parent_movie_obj)): for movie in self.jellyfin_db.get_item_by_parent_id(*values(obj, QUEM.get_item_by_parent_movie_obj)):
temp_obj = dict(obj) temp_obj = dict(obj)
temp_obj['MovieId'] = movie[1] temp_obj['MovieId'] = movie[1]
temp_obj['Movie'] = movie[0] temp_obj['Movie'] = movie[0]
self.remove_from_boxset(*values(temp_obj, QU.delete_movie_set_obj)) self.remove_from_boxset(*values(temp_obj, QU.delete_movie_set_obj))
self.emby_db.update_parent_id(*values(temp_obj, QUEM.delete_parent_boxset_obj)) self.jellyfin_db.update_parent_id(*values(temp_obj, QUEM.delete_parent_boxset_obj))
self.delete_boxset(*values(obj, QU.delete_set_obj)) self.delete_boxset(*values(obj, QU.delete_set_obj))
self.emby_db.remove_item(*values(obj, QUEM.delete_item_obj)) self.jellyfin_db.remove_item(*values(obj, QUEM.delete_item_obj))
LOG.info("DELETE %s [%s/%s] %s", obj['Media'], obj['FileId'], obj['KodiId'], obj['Id']) LOG.info("DELETE %s [%s/%s] %s", obj['Media'], obj['FileId'], obj['KodiId'], obj['Id'])

View file

@ -9,26 +9,26 @@ import urllib
from obj import Objects from obj import Objects
from kodi import Music as KodiDb, queries_music as QU from kodi import Music as KodiDb, queries_music as QU
from database import emby_db, queries as QUEM from database import jellyfin_db, queries as QUEM
from helper import api, catch, stop, validate, emby_item, values, library_check, settings, Local from helper import api, catch, stop, validate, jellyfin_item, values, library_check, settings, Local
################################################################################################## ##################################################################################################
LOG = logging.getLogger("EMBY."+__name__) LOG = logging.getLogger("JELLYFIN."+__name__)
################################################################################################## ##################################################################################################
class Music(KodiDb): class Music(KodiDb):
def __init__(self, server, embydb, musicdb, direct_path): def __init__(self, server, jellyfindb, musicdb, direct_path):
self.server = server self.server = server
self.emby = embydb self.jellyfin = jellyfindb
self.music = musicdb self.music = musicdb
self.direct_path = direct_path self.direct_path = direct_path
self.emby_db = emby_db.EmbyDatabase(embydb.cursor) self.jellyfin_db = jellyfin_db.JellyfinDatabase(jellyfindb.cursor)
self.objects = Objects() self.objects = Objects()
self.item_ids = [] self.item_ids = []
@ -48,7 +48,7 @@ class Music(KodiDb):
return self.remove return self.remove
@stop() @stop()
@emby_item() @jellyfin_item()
@library_check() @library_check()
def artist(self, item, e_item, library): def artist(self, item, e_item, library):
@ -103,23 +103,23 @@ class Music(KodiDb):
''' Add object to kodi. ''' Add object to kodi.
safety checks: It looks like Emby supports the same artist multiple times. safety checks: It looks like Jellyfin supports the same artist multiple times.
Kodi doesn't allow that. In case that happens we just merge the artist entries. Kodi doesn't allow that. In case that happens we just merge the artist entries.
''' '''
obj['ArtistId'] = self.get(*values(obj, QU.get_artist_obj)) obj['ArtistId'] = self.get(*values(obj, QU.get_artist_obj))
self.emby_db.add_reference(*values(obj, QUEM.add_reference_artist_obj)) self.jellyfin_db.add_reference(*values(obj, QUEM.add_reference_artist_obj))
LOG.info("ADD artist [%s] %s: %s", obj['ArtistId'], obj['Name'], obj['Id']) LOG.info("ADD artist [%s] %s: %s", obj['ArtistId'], obj['Name'], obj['Id'])
def artist_update(self, obj): def artist_update(self, obj):
''' Update object to kodi. ''' Update object to kodi.
''' '''
self.emby_db.update_reference(*values(obj, QUEM.update_reference_obj)) self.jellyfin_db.update_reference(*values(obj, QUEM.update_reference_obj))
LOG.info("UPDATE artist [%s] %s: %s", obj['ArtistId'], obj['Name'], obj['Id']) LOG.info("UPDATE artist [%s] %s: %s", obj['ArtistId'], obj['Name'], obj['Id'])
@stop() @stop()
@emby_item() @jellyfin_item()
def album(self, item, e_item): def album(self, item, e_item):
''' Update object to kodi. ''' Update object to kodi.
@ -172,14 +172,14 @@ class Music(KodiDb):
''' Add object to kodi. ''' Add object to kodi.
''' '''
obj['AlbumId'] = self.get_album(*values(obj, QU.get_album_obj)) obj['AlbumId'] = self.get_album(*values(obj, QU.get_album_obj))
self.emby_db.add_reference(*values(obj, QUEM.add_reference_album_obj)) self.jellyfin_db.add_reference(*values(obj, QUEM.add_reference_album_obj))
LOG.info("ADD album [%s] %s: %s", obj['AlbumId'], obj['Title'], obj['Id']) LOG.info("ADD album [%s] %s: %s", obj['AlbumId'], obj['Title'], obj['Id'])
def album_update(self, obj): def album_update(self, obj):
''' Update object to kodi. ''' Update object to kodi.
''' '''
self.emby_db.update_reference(*values(obj, QUEM.update_reference_obj)) self.jellyfin_db.update_reference(*values(obj, QUEM.update_reference_obj))
LOG.info("UPDATE album [%s] %s: %s", obj['AlbumId'], obj['Title'], obj['Id']) LOG.info("UPDATE album [%s] %s: %s", obj['AlbumId'], obj['Title'], obj['Id'])
def artist_discography(self, obj): def artist_discography(self, obj):
@ -193,17 +193,17 @@ class Music(KodiDb):
temp_obj['AlbumId'] = obj['Id'] temp_obj['AlbumId'] = obj['Id']
try: try:
temp_obj['ArtistId'] = self.emby_db.get_item_by_id(*values(temp_obj, QUEM.get_item_obj))[0] temp_obj['ArtistId'] = self.jellyfin_db.get_item_by_id(*values(temp_obj, QUEM.get_item_obj))[0]
except TypeError: except TypeError:
continue continue
self.add_discography(*values(temp_obj, QU.update_discography_obj)) self.add_discography(*values(temp_obj, QU.update_discography_obj))
self.emby_db.update_parent_id(*values(temp_obj, QUEM.update_parent_album_obj)) self.jellyfin_db.update_parent_id(*values(temp_obj, QUEM.update_parent_album_obj))
def artist_link(self, obj): def artist_link(self, obj):
''' Assign main artists to album. ''' Assign main artists to album.
Artist does not exist in emby database, create the reference. Artist does not exist in jellyfin database, create the reference.
''' '''
for artist in (obj['AlbumArtists'] or []): for artist in (obj['AlbumArtists'] or []):
@ -212,12 +212,12 @@ class Music(KodiDb):
temp_obj['Id'] = artist['Id'] temp_obj['Id'] = artist['Id']
try: try:
temp_obj['ArtistId'] = self.emby_db.get_item_by_id(*values(temp_obj, QUEM.get_item_obj))[0] temp_obj['ArtistId'] = self.jellyfin_db.get_item_by_id(*values(temp_obj, QUEM.get_item_obj))[0]
except TypeError: except TypeError:
try: try:
self.artist(self.server['api'].get_item(temp_obj['Id']), library=None) self.artist(self.server['api'].get_item(temp_obj['Id']), library=None)
temp_obj['ArtistId'] = self.emby_db.get_item_by_id(*values(temp_obj, QUEM.get_item_obj))[0] temp_obj['ArtistId'] = self.jellyfin_db.get_item_by_id(*values(temp_obj, QUEM.get_item_obj))[0]
except Exception as error: except Exception as error:
LOG.error(error) LOG.error(error)
continue continue
@ -228,7 +228,7 @@ class Music(KodiDb):
@stop() @stop()
@emby_item() @jellyfin_item()
def song(self, item, e_item): def song(self, item, e_item):
''' Update object to kodi. ''' Update object to kodi.
@ -310,7 +310,7 @@ class Music(KodiDb):
obj['PathId'] = self.add_path(obj['Path']) obj['PathId'] = self.add_path(obj['Path'])
try: try:
obj['AlbumId'] = self.emby_db.get_item_by_id(*values(obj, QUEM.get_item_song_obj))[0] obj['AlbumId'] = self.jellyfin_db.get_item_by_id(*values(obj, QUEM.get_item_song_obj))[0]
except TypeError: except TypeError:
try: try:
@ -318,12 +318,12 @@ class Music(KodiDb):
raise TypeError("No album id found associated?") raise TypeError("No album id found associated?")
self.album(self.server['api'].get_item(obj['SongAlbumId'])) self.album(self.server['api'].get_item(obj['SongAlbumId']))
obj['AlbumId'] = self.emby_db.get_item_by_id(*values(obj, QUEM.get_item_song_obj))[0] obj['AlbumId'] = self.jellyfin_db.get_item_by_id(*values(obj, QUEM.get_item_song_obj))[0]
except TypeError: except TypeError:
self.single(obj) self.single(obj)
self.add_song(*values(obj, QU.add_song_obj)) self.add_song(*values(obj, QU.add_song_obj))
self.emby_db.add_reference(*values(obj, QUEM.add_reference_song_obj)) self.jellyfin_db.add_reference(*values(obj, QUEM.add_reference_song_obj))
LOG.debug("ADD song [%s/%s/%s] %s: %s", obj['PathId'], obj['AlbumId'], obj['SongId'], obj['Id'], obj['Title']) LOG.debug("ADD song [%s/%s/%s] %s: %s", obj['PathId'], obj['AlbumId'], obj['SongId'], obj['Id'], obj['Title'])
def song_update(self, obj): def song_update(self, obj):
@ -333,7 +333,7 @@ class Music(KodiDb):
self.update_path(*values(obj, QU.update_path_obj)) self.update_path(*values(obj, QU.update_path_obj))
self.update_song(*values(obj, QU.update_song_obj)) self.update_song(*values(obj, QU.update_song_obj))
self.emby_db.update_reference(*values(obj, QUEM.update_reference_obj)) self.jellyfin_db.update_reference(*values(obj, QUEM.update_reference_obj))
LOG.info("UPDATE song [%s/%s/%s] %s: %s", obj['PathId'], obj['AlbumId'], obj['SongId'], obj['Id'], obj['Title']) LOG.info("UPDATE song [%s/%s/%s] %s: %s", obj['PathId'], obj['AlbumId'], obj['SongId'], obj['Id'], obj['Title'])
def get_song_path_filename(self, obj, api): def get_song_path_filename(self, obj, api):
@ -368,12 +368,12 @@ class Music(KodiDb):
artists.append(temp_obj['Name']) artists.append(temp_obj['Name'])
try: try:
temp_obj['ArtistId'] = self.emby_db.get_item_by_id(*values(temp_obj, QUEM.get_item_obj))[0] temp_obj['ArtistId'] = self.jellyfin_db.get_item_by_id(*values(temp_obj, QUEM.get_item_obj))[0]
except TypeError: except TypeError:
try: try:
self.artist(self.server['api'].get_item(temp_obj['Id']), library=None) self.artist(self.server['api'].get_item(temp_obj['Id']), library=None)
temp_obj['ArtistId'] = self.emby_db.get_item_by_id(*values(temp_obj, QUEM.get_item_obj))[0] temp_obj['ArtistId'] = self.jellyfin_db.get_item_by_id(*values(temp_obj, QUEM.get_item_obj))[0]
except Exception as error: except Exception as error:
LOG.error(error) LOG.error(error)
continue continue
@ -392,7 +392,7 @@ class Music(KodiDb):
def song_artist_link(self, obj): def song_artist_link(self, obj):
''' Assign main artists to song. ''' Assign main artists to song.
Artist does not exist in emby database, create the reference. Artist does not exist in jellyfin database, create the reference.
''' '''
for index, artist in enumerate(obj['ArtistItems'] or []): for index, artist in enumerate(obj['ArtistItems'] or []):
@ -402,12 +402,12 @@ class Music(KodiDb):
temp_obj['Index'] = index temp_obj['Index'] = index
try: try:
temp_obj['ArtistId'] = self.emby_db.get_item_by_id(*values(temp_obj, QUEM.get_item_obj))[0] temp_obj['ArtistId'] = self.jellyfin_db.get_item_by_id(*values(temp_obj, QUEM.get_item_obj))[0]
except TypeError: except TypeError:
try: try:
self.artist(self.server['api'].get_item(temp_obj['Id']), library=None) self.artist(self.server['api'].get_item(temp_obj['Id']), library=None)
temp_obj['ArtistId'] = self.emby_db.get_item_by_id(*values(temp_obj, QUEM.get_item_obj))[0] temp_obj['ArtistId'] = self.jellyfin_db.get_item_by_id(*values(temp_obj, QUEM.get_item_obj))[0]
except Exception as error: except Exception as error:
LOG.error(error) LOG.error(error)
continue continue
@ -422,7 +422,7 @@ class Music(KodiDb):
@stop() @stop()
@emby_item() @jellyfin_item()
def userdata(self, item, e_item): def userdata(self, item, e_item):
''' This updates: Favorite, LastPlayedDate, Playcount, PlaybackPositionTicks ''' This updates: Favorite, LastPlayedDate, Playcount, PlaybackPositionTicks
@ -446,11 +446,11 @@ class Music(KodiDb):
self.rate_song(*values(obj, QU.update_song_rating_obj)) self.rate_song(*values(obj, QU.update_song_rating_obj))
self.emby_db.update_reference(*values(obj, QUEM.update_reference_obj)) self.jellyfin_db.update_reference(*values(obj, QUEM.update_reference_obj))
LOG.info("USERDATA %s [%s] %s: %s", obj['Media'], obj['KodiId'], obj['Id'], obj['Title']) LOG.info("USERDATA %s [%s] %s: %s", obj['Media'], obj['KodiId'], obj['Id'], obj['Title'])
@stop() @stop()
@emby_item() @jellyfin_item()
def remove(self, item_id, e_item): def remove(self, item_id, e_item):
''' This updates: Favorite, LastPlayedDate, Playcount, PlaybackPositionTicks ''' This updates: Favorite, LastPlayedDate, Playcount, PlaybackPositionTicks
@ -470,47 +470,47 @@ class Music(KodiDb):
if obj['Media'] == 'song': if obj['Media'] == 'song':
self.remove_song(obj['KodiId'], obj['Id']) self.remove_song(obj['KodiId'], obj['Id'])
self.emby_db.remove_wild_item(obj['id']) self.jellyfin_db.remove_wild_item(obj['id'])
for item in self.emby_get_item_by_wild_id(*values(obj, QUEM.get_item_by_wild_obj)): for item in self.jellyfin_db.get_item_by_wild_id(*values(obj, QUEM.get_item_by_wild_obj)):
if item[1] == 'album': if item[1] == 'album':
temp_obj = dict(obj) temp_obj = dict(obj)
temp_obj['ParentId'] = item[0] temp_obj['ParentId'] = item[0]
if not self.emby_db.get_item_by_parent_id(*values(temp_obj, QUEM.get_item_by_parent_song_obj)): if not self.jellyfin_db.get_item_by_parent_id(*values(temp_obj, QUEM.get_item_by_parent_song_obj)):
self.remove_album(temp_obj['ParentId'], obj['Id']) self.remove_album(temp_obj['ParentId'], obj['Id'])
elif obj['Media'] == 'album': elif obj['Media'] == 'album':
obj['ParentId'] = obj['KodiId'] obj['ParentId'] = obj['KodiId']
for song in self.emby_db.get_item_by_parent_id(*values(obj, QUEM.get_item_by_parent_song_obj)): for song in self.jellyfin_db.get_item_by_parent_id(*values(obj, QUEM.get_item_by_parent_song_obj)):
self.remove_song(song[1], obj['Id']) self.remove_song(song[1], obj['Id'])
else: else:
self.emby_db.remove_items_by_parent_id(*values(obj, QUEM.delete_item_by_parent_song_obj)) self.jellyfin_db.remove_items_by_parent_id(*values(obj, QUEM.delete_item_by_parent_song_obj))
self.remove_album(obj['KodiId'], obj['Id']) self.remove_album(obj['KodiId'], obj['Id'])
elif obj['Media'] == 'artist': elif obj['Media'] == 'artist':
obj['ParentId'] = obj['KodiId'] obj['ParentId'] = obj['KodiId']
for album in self.emby_db.get_item_by_parent_id(*values(obj, QUEM.get_item_by_parent_album_obj)): for album in self.jellyfin_db.get_item_by_parent_id(*values(obj, QUEM.get_item_by_parent_album_obj)):
temp_obj = dict(obj) temp_obj = dict(obj)
temp_obj['ParentId'] = album[1] temp_obj['ParentId'] = album[1]
for song in self.emby_db.get_item_by_parent_id(*values(temp_obj, QUEM.get_item_by_parent_song_obj)): for song in self.jellyfin_db.get_item_by_parent_id(*values(temp_obj, QUEM.get_item_by_parent_song_obj)):
self.remove_song(song[1], obj['Id']) self.remove_song(song[1], obj['Id'])
else: else:
self.emby_db.remove_items_by_parent_id(*values(temp_obj, QUEM.delete_item_by_parent_song_obj)) self.jellyfin_db.remove_items_by_parent_id(*values(temp_obj, QUEM.delete_item_by_parent_song_obj))
self.emby_db.remove_items_by_parent_id(*values(temp_obj, QUEM.delete_item_by_parent_artist_obj)) self.jellyfin_db.remove_items_by_parent_id(*values(temp_obj, QUEM.delete_item_by_parent_artist_obj))
self.remove_album(temp_obj['ParentId'], obj['Id']) self.remove_album(temp_obj['ParentId'], obj['Id'])
else: else:
self.emby_db.remove_items_by_parent_id(*values(obj, QUEM.delete_item_by_parent_album_obj)) self.jellyfin_db.remove_items_by_parent_id(*values(obj, QUEM.delete_item_by_parent_album_obj))
self.remove_artist(obj['KodiId'], obj['Id']) self.remove_artist(obj['KodiId'], obj['Id'])
self.emby_db.remove_item(*values(obj, QUEM.delete_item_obj)) self.jellyfin_db.remove_item(*values(obj, QUEM.delete_item_obj))
def remove_artist(self, kodi_id, item_id): def remove_artist(self, kodi_id, item_id):
@ -530,10 +530,10 @@ class Music(KodiDb):
self.delete_song(kodi_id) self.delete_song(kodi_id)
LOG.info("DELETE song [%s] %s", kodi_id, item_id) LOG.info("DELETE song [%s] %s", kodi_id, item_id)
@emby_item() @jellyfin_item()
def get_child(self, item_id, e_item): def get_child(self, item_id, e_item):
''' Get all child elements from tv show emby id. ''' Get all child elements from tv show jellyfin id.
''' '''
obj = {'Id': item_id} obj = {'Id': item_id}
child = [] child = []
@ -548,13 +548,13 @@ class Music(KodiDb):
obj['ParentId'] = obj['KodiId'] obj['ParentId'] = obj['KodiId']
for album in self.emby_db.get_item_by_parent_id(*values(obj, QUEM.get_item_by_parent_album_obj)): for album in self.jellyfin_db.get_item_by_parent_id(*values(obj, QUEM.get_item_by_parent_album_obj)):
temp_obj = dict(obj) temp_obj = dict(obj)
temp_obj['ParentId'] = album[1] temp_obj['ParentId'] = album[1]
child.append((album[0],)) child.append((album[0],))
for song in self.emby_db.get_item_by_parent_id(*values(temp_obj, QUEM.get_item_by_parent_song_obj)): for song in self.jellyfin_db.get_item_by_parent_id(*values(temp_obj, QUEM.get_item_by_parent_song_obj)):
child.append((song[0],)) child.append((song[0],))
return child return child

View file

@ -9,26 +9,26 @@ import urllib
from obj import Objects from obj import Objects
from kodi import MusicVideos as KodiDb, queries as QU from kodi import MusicVideos as KodiDb, queries as QU
from database import emby_db, queries as QUEM from database import jellyfin_db, queries as QUEM
from helper import api, catch, stop, validate, library_check, emby_item, values, Local from helper import api, catch, stop, validate, library_check, jellyfin_item, values, Local
################################################################################################## ##################################################################################################
LOG = logging.getLogger("EMBY."+__name__) LOG = logging.getLogger("JELLYFIN."+__name__)
################################################################################################## ##################################################################################################
class MusicVideos(KodiDb): class MusicVideos(KodiDb):
def __init__(self, server, embydb, videodb, direct_path): def __init__(self, server, jellyfindb, videodb, direct_path):
self.server = server self.server = server
self.emby = embydb self.jellyfin = jellyfindb
self.video = videodb self.video = videodb
self.direct_path = direct_path self.direct_path = direct_path
self.emby_db = emby_db.EmbyDatabase(embydb.cursor) self.jellyfin_db = jellyfin_db.JellyfinDatabase(jellyfindb.cursor)
self.objects = Objects() self.objects = Objects()
self.item_ids = [] self.item_ids = []
@ -44,14 +44,14 @@ class MusicVideos(KodiDb):
return self.remove return self.remove
@stop() @stop()
@emby_item() @jellyfin_item()
@library_check() @library_check()
def musicvideo(self, item, e_item, library): def musicvideo(self, item, e_item, library):
''' If item does not exist, entry will be added. ''' If item does not exist, entry will be added.
If item exists, entry will be updated. If item exists, entry will be updated.
If we don't get the track number from Emby, see if we can infer it If we don't get the track number from Jellyfin, see if we can infer it
from the sortname attribute. from the sortname attribute.
''' '''
API = api.API(item, self.server['auth/server-address']) API = api.API(item, self.server['auth/server-address'])
@ -149,7 +149,7 @@ class MusicVideos(KodiDb):
obj['FileId'] = self.add_file(*values(obj, QU.add_file_obj)) obj['FileId'] = self.add_file(*values(obj, QU.add_file_obj))
self.add(*values(obj, QU.add_musicvideo_obj)) self.add(*values(obj, QU.add_musicvideo_obj))
self.emby_db.add_reference(*values(obj, QUEM.add_reference_mvideo_obj)) self.jellyfin_db.add_reference(*values(obj, QUEM.add_reference_mvideo_obj))
LOG.info("ADD mvideo [%s/%s/%s] %s: %s", obj['PathId'], obj['FileId'], obj['MvideoId'], obj['Id'], obj['Title']) LOG.info("ADD mvideo [%s/%s/%s] %s: %s", obj['PathId'], obj['FileId'], obj['MvideoId'], obj['Id'], obj['Title'])
def musicvideo_update(self, obj): def musicvideo_update(self, obj):
@ -157,7 +157,7 @@ class MusicVideos(KodiDb):
''' Update object to kodi. ''' Update object to kodi.
''' '''
self.update(*values(obj, QU.update_musicvideo_obj)) self.update(*values(obj, QU.update_musicvideo_obj))
self.emby_db.update_reference(*values(obj, QUEM.update_reference_obj)) self.jellyfin_db.update_reference(*values(obj, QUEM.update_reference_obj))
LOG.info("UPDATE mvideo [%s/%s/%s] %s: %s", obj['PathId'], obj['FileId'], obj['MvideoId'], obj['Id'], obj['Title']) LOG.info("UPDATE mvideo [%s/%s/%s] %s: %s", obj['PathId'], obj['FileId'], obj['MvideoId'], obj['Id'], obj['Title'])
def get_path_filename(self, obj): def get_path_filename(self, obj):
@ -174,7 +174,7 @@ class MusicVideos(KodiDb):
obj['Path'] = obj['Path'].replace(obj['Filename'], "") obj['Path'] = obj['Path'].replace(obj['Filename'], "")
else: else:
obj['Path'] = "plugin://plugin.video.emby.musicvideos/" obj['Path'] = "plugin://plugin.video.jellyfin/"
params = { params = {
'filename': obj['Filename'].encode('utf-8'), 'filename': obj['Filename'].encode('utf-8'),
'id': obj['Id'], 'id': obj['Id'],
@ -185,7 +185,7 @@ class MusicVideos(KodiDb):
@stop() @stop()
@emby_item() @jellyfin_item()
def userdata(self, item, e_item): def userdata(self, item, e_item):
''' This updates: Favorite, LastPlayedDate, Playcount, PlaybackPositionTicks ''' This updates: Favorite, LastPlayedDate, Playcount, PlaybackPositionTicks
@ -213,14 +213,14 @@ class MusicVideos(KodiDb):
self.remove_tag(*values(obj, QU.delete_tag_mvideo_obj)) self.remove_tag(*values(obj, QU.delete_tag_mvideo_obj))
self.add_playstate(*values(obj, QU.add_bookmark_obj)) self.add_playstate(*values(obj, QU.add_bookmark_obj))
self.emby_db.update_reference(*values(obj, QUEM.update_reference_obj)) self.jellyfin_db.update_reference(*values(obj, QUEM.update_reference_obj))
LOG.info("USERDATA mvideo [%s/%s] %s: %s", obj['FileId'], obj['MvideoId'], obj['Id'], obj['Title']) LOG.info("USERDATA mvideo [%s/%s] %s: %s", obj['FileId'], obj['MvideoId'], obj['Id'], obj['Title'])
@stop() @stop()
@emby_item() @jellyfin_item()
def remove(self, item_id, e_item): def remove(self, item_id, e_item):
''' Remove mvideoid, fileid, pathid, emby reference. ''' Remove mvideoid, fileid, pathid, jellyfin reference.
''' '''
obj = {'Id': item_id} obj = {'Id': item_id}
@ -237,5 +237,5 @@ class MusicVideos(KodiDb):
if self.direct_path: if self.direct_path:
self.remove_path(*values(obj, QU.delete_path_obj)) self.remove_path(*values(obj, QU.delete_path_obj))
self.emby_db.remove_item(*values(obj, QUEM.delete_item_obj)) self.jellyfin_db.remove_item(*values(obj, QUEM.delete_item_obj))
LOG.info("DELETE musicvideo %s [%s/%s] %s", obj['MvideoId'], obj['PathId'], obj['FileId'], obj['Id']) LOG.info("DELETE musicvideo %s [%s/%s] %s", obj['MvideoId'], obj['PathId'], obj['FileId'], obj['Id'])

View file

@ -8,7 +8,7 @@ import os
################################################################################################## ##################################################################################################
LOG = logging.getLogger("EMBY."+__name__) LOG = logging.getLogger("JELLYFIN."+__name__)
################################################################################################## ##################################################################################################
@ -37,7 +37,7 @@ class Objects(object):
''' Syntax to traverse the item dictionary. ''' Syntax to traverse the item dictionary.
This of the query almost as a url. This of the query almost as a url.
Item is the Emby item json object structure Item is the Jellyfin item json object structure
",": each element will be used as a fallback until a value is found. ",": each element will be used as a fallback until a value is found.
"?": split filters and key name from the query part, i.e. MediaSources/0?$Name "?": split filters and key name from the query part, i.e. MediaSources/0?$Name

View file

@ -2,7 +2,7 @@
"video": "special://database/MyVideos107.db", "video": "special://database/MyVideos107.db",
"music": "special://database/MyMusic60.db", "music": "special://database/MyMusic60.db",
"texture": "special://database/Textures13.db", "texture": "special://database/Textures13.db",
"emby": "special://database/emby.db", "jellyfin": "special://database/jellyfin.db",
"MovieProviderName": "imdb", "MovieProviderName": "imdb",
"Movie": { "Movie": {
"Id": "Id", "Id": "Id",
@ -40,7 +40,7 @@
"Audio": "MediaSources/0/MediaStreams:?Type=Audio", "Audio": "MediaSources/0/MediaStreams:?Type=Audio",
"Video": "MediaSources/0/MediaStreams:?Type=Video", "Video": "MediaSources/0/MediaStreams:?Type=Video",
"Container": "MediaSources/0/Container", "Container": "MediaSources/0/Container",
"EmbyParentId": "ParentId", "JellyfinParentId": "ParentId",
"CriticRating": "CriticRating" "CriticRating": "CriticRating"
}, },
"MovieUserData": { "MovieUserData": {
@ -77,7 +77,7 @@
"Tags": "Tags", "Tags": "Tags",
"Favorite": "UserData/IsFavorite", "Favorite": "UserData/IsFavorite",
"RecursiveCount": "RecursiveItemCount", "RecursiveCount": "RecursiveItemCount",
"EmbyParentId": "ParentId", "JellyfinParentId": "ParentId",
"Status": "Status" "Status": "Status"
}, },
"Season": { "Season": {
@ -119,7 +119,7 @@
"Video": "MediaSources/0/MediaStreams:?Type=Video", "Video": "MediaSources/0/MediaStreams:?Type=Video",
"Container": "MediaSources/0/Container", "Container": "MediaSources/0/Container",
"Location": "LocationType", "Location": "LocationType",
"EmbyParentId": "SeriesId,ParentId" "JellyfinParentId": "SeriesId,ParentId"
}, },
"EpisodeUserData": { "EpisodeUserData": {
"Id": "Id", "Id": "Id",
@ -160,7 +160,7 @@
"Played": "UserData/Played", "Played": "UserData/Played",
"Favorite": "UserData/IsFavorite", "Favorite": "UserData/IsFavorite",
"Directors": "People:?Type=Director$Name", "Directors": "People:?Type=Director$Name",
"EmbyParentId": "ParentId" "JellyfinParentId": "ParentId"
}, },
"MusicVideoUserData": { "MusicVideoUserData": {
"Id": "Id", "Id": "Id",
@ -178,7 +178,7 @@
"UniqueId": "ProviderIds/MusicBrainzArtist", "UniqueId": "ProviderIds/MusicBrainzArtist",
"Genres": "Genres", "Genres": "Genres",
"Bio": "Overview", "Bio": "Overview",
"EmbyParentId": "ParentId" "JellyfinParentId": "ParentId"
}, },
"Album": { "Album": {
"Id": "Id", "Id": "Id",
@ -190,7 +190,7 @@
"AlbumArtists": "AlbumArtists", "AlbumArtists": "AlbumArtists",
"Artists": "AlbumArtists:?$Name", "Artists": "AlbumArtists:?$Name",
"ArtistItems": "ArtistItems", "ArtistItems": "ArtistItems",
"EmbyParentId": "ParentId" "JellyfinParentId": "ParentId"
}, },
"Song": { "Song": {
"Id": "Id", "Id": "Id",
@ -213,7 +213,7 @@
"Album": "Album", "Album": "Album",
"SongAlbumId": "AlbumId", "SongAlbumId": "AlbumId",
"Container": "MediaSources/0/Container", "Container": "MediaSources/0/Container",
"EmbyParentId": "ParentId" "JellyfinParentId": "ParentId"
}, },
"SongUserData": { "SongUserData": {
"Id": "Id", "Id": "Id",

View file

@ -11,27 +11,27 @@ from ntpath import dirname
from obj import Objects from obj import Objects
from kodi import TVShows as KodiDb, queries as QU from kodi import TVShows as KodiDb, queries as QU
import downloader as server import downloader as server
from database import emby_db, queries as QUEM from database import jellyfin_db, queries as QUEM
from helper import api, catch, stop, validate, emby_item, library_check, settings, values, Local from helper import api, catch, stop, validate, jellyfin_item, library_check, settings, values, Local
################################################################################################## ##################################################################################################
LOG = logging.getLogger("EMBY."+__name__) LOG = logging.getLogger("JELLYFIN."+__name__)
################################################################################################## ##################################################################################################
class TVShows(KodiDb): class TVShows(KodiDb):
def __init__(self, server, embydb, videodb, direct_path, update_library=False): def __init__(self, server, jellyfindb, videodb, direct_path, update_library=False):
self.server = server self.server = server
self.emby = embydb self.jellyfin = jellyfindb
self.video = videodb self.video = videodb
self.direct_path = direct_path self.direct_path = direct_path
self.update_library = update_library self.update_library = update_library
self.emby_db = emby_db.EmbyDatabase(embydb.cursor) self.jellyfin_db = jellyfin_db.JellyfinDatabase(jellyfindb.cursor)
self.objects = Objects() self.objects = Objects()
self.item_ids = [] self.item_ids = []
@ -51,7 +51,7 @@ class TVShows(KodiDb):
return self.remove return self.remove
@stop() @stop()
@emby_item() @jellyfin_item()
@library_check() @library_check()
def tvshow(self, item, e_item, library): def tvshow(self, item, e_item, library):
@ -143,18 +143,18 @@ class TVShows(KodiDb):
self.item_ids.append(season['SeriesId']) self.item_ids.append(season['SeriesId'])
try: try:
self.emby_db.get_item_by_id(*values(obj, QUEM.get_item_series_obj))[0] self.jellyfin_db.get_item_by_id(*values(obj, QUEM.get_item_series_obj))[0]
if self.update_library: if self.update_library:
season_episodes[season['Id']] = season['SeriesId'] season_episodes[season['Id']] = season['SeriesId']
except TypeError: except TypeError:
self.emby_db.add_reference(*values(obj, QUEM.add_reference_pool_obj)) self.jellyfin_db.add_reference(*values(obj, QUEM.add_reference_pool_obj))
LOG.info("POOL %s [%s/%s]", obj['Title'], obj['Id'], obj['SeriesId']) LOG.info("POOL %s [%s/%s]", obj['Title'], obj['Id'], obj['SeriesId'])
season_episodes[season['Id']] = season['SeriesId'] season_episodes[season['Id']] = season['SeriesId']
try: try:
self.emby_db.get_item_by_id(season['Id'])[0] self.jellyfin_db.get_item_by_id(season['Id'])[0]
self.item_ids.append(season['Id']) self.item_ids.append(season['Id'])
except TypeError: except TypeError:
self.season(season, obj['ShowId']) self.season(season, obj['ShowId'])
@ -184,7 +184,7 @@ class TVShows(KodiDb):
obj['PathId'] = self.add_path(*values(obj, QU.get_path_obj)) obj['PathId'] = self.add_path(*values(obj, QU.get_path_obj))
self.add(*values(obj, QU.add_tvshow_obj)) self.add(*values(obj, QU.add_tvshow_obj))
self.emby_db.add_reference(*values(obj, QUEM.add_reference_tvshow_obj)) self.jellyfin_db.add_reference(*values(obj, QUEM.add_reference_tvshow_obj))
LOG.info("ADD tvshow [%s/%s/%s] %s: %s", obj['TopPathId'], obj['PathId'], obj['ShowId'], obj['Title'], obj['Id']) LOG.info("ADD tvshow [%s/%s/%s] %s: %s", obj['TopPathId'], obj['PathId'], obj['ShowId'], obj['Title'], obj['Id'])
def tvshow_update(self, obj): def tvshow_update(self, obj):
@ -198,7 +198,7 @@ class TVShows(KodiDb):
self.update_unique_id(*values(obj, QU.update_unique_id_tvshow_obj)) self.update_unique_id(*values(obj, QU.update_unique_id_tvshow_obj))
self.update(*values(obj, QU.update_tvshow_obj)) self.update(*values(obj, QU.update_tvshow_obj))
self.emby_db.update_reference(*values(obj, QUEM.update_reference_obj)) self.jellyfin_db.update_reference(*values(obj, QUEM.update_reference_obj))
LOG.info("UPDATE tvshow [%s/%s] %s: %s", obj['PathId'], obj['ShowId'], obj['Title'], obj['Id']) LOG.info("UPDATE tvshow [%s/%s] %s: %s", obj['PathId'], obj['ShowId'], obj['Title'], obj['Id'])
def get_path_filename(self, obj): def get_path_filename(self, obj):
@ -217,7 +217,7 @@ class TVShows(KodiDb):
if not validate(obj['Path']): if not validate(obj['Path']):
raise Exception("Failed to validate path. User stopped.") raise Exception("Failed to validate path. User stopped.")
else: else:
obj['TopLevel'] = "plugin://plugin.video.emby.tvshows/" obj['TopLevel'] = "plugin://plugin.video.jellyfin/"
obj['Path'] = "%s%s/" % (obj['TopLevel'], obj['Id']) obj['Path'] = "%s%s/" % (obj['TopLevel'], obj['Id'])
@ -237,7 +237,7 @@ class TVShows(KodiDb):
if obj['ShowId'] is None: if obj['ShowId'] is None:
try: try:
obj['ShowId'] = self.emby_db.get_item_by_id(*values(obj, QUEM.get_item_series_obj))[0] obj['ShowId'] = self.jellyfin_db.get_item_by_id(*values(obj, QUEM.get_item_series_obj))[0]
except (KeyError, TypeError): except (KeyError, TypeError):
LOG.error("Unable to add series %s", obj['SeriesId']) LOG.error("Unable to add series %s", obj['SeriesId'])
@ -247,7 +247,7 @@ class TVShows(KodiDb):
obj['Artwork'] = API.get_all_artwork(self.objects.map(item, 'Artwork')) obj['Artwork'] = API.get_all_artwork(self.objects.map(item, 'Artwork'))
if obj['Location'] != "Virtual": if obj['Location'] != "Virtual":
self.emby_db.add_reference(*values(obj, QUEM.add_reference_season_obj)) self.jellyfin_db.add_reference(*values(obj, QUEM.add_reference_season_obj))
self.item_ids.append(obj['Id']) self.item_ids.append(obj['Id'])
self.artwork.add(obj['Artwork'], obj['SeasonId'], "season") self.artwork.add(obj['Artwork'], obj['SeasonId'], "season")
@ -255,7 +255,7 @@ class TVShows(KodiDb):
@stop() @stop()
@emby_item() @jellyfin_item()
def episode(self, item, e_item): def episode(self, item, e_item):
''' If item does not exist, entry will be added. ''' If item does not exist, entry will be added.
@ -354,7 +354,7 @@ class TVShows(KodiDb):
if not self.direct_path and obj['Resume']: if not self.direct_path and obj['Resume']:
temp_obj = dict(obj) temp_obj = dict(obj)
temp_obj['Path'] = "plugin://plugin.video.emby.tvshows/" temp_obj['Path'] = "plugin://plugin.video.jellyfin/"
temp_obj['PathId'] = self.get_path(*values(temp_obj, QU.get_path_obj)) temp_obj['PathId'] = self.get_path(*values(temp_obj, QU.get_path_obj))
temp_obj['FileId'] = self.add_file(*values(temp_obj, QU.add_file_obj)) temp_obj['FileId'] = self.add_file(*values(temp_obj, QU.add_file_obj))
self.update_file(*values(temp_obj, QU.update_file_obj)) self.update_file(*values(temp_obj, QU.update_file_obj))
@ -384,7 +384,7 @@ class TVShows(KodiDb):
return self.episode_add(obj) return self.episode_add(obj)
self.emby_db.add_reference(*values(obj, QUEM.add_reference_episode_obj)) self.jellyfin_db.add_reference(*values(obj, QUEM.add_reference_episode_obj))
LOG.debug("ADD episode [%s/%s] %s: %s", obj['PathId'], obj['FileId'], obj['Id'], obj['Title']) LOG.debug("ADD episode [%s/%s] %s: %s", obj['PathId'], obj['FileId'], obj['Id'], obj['Title'])
def episode_update(self, obj): def episode_update(self, obj):
@ -399,8 +399,8 @@ class TVShows(KodiDb):
self.update_episode(*values(obj, QU.update_episode_obj)) self.update_episode(*values(obj, QU.update_episode_obj))
self.emby_db.update_reference(*values(obj, QUEM.update_reference_obj)) self.jellyfin_db.update_reference(*values(obj, QUEM.update_reference_obj))
self.emby_db.update_parent_id(*values(obj, QUEM.update_parent_episode_obj)) self.jellyfin_db.update_parent_id(*values(obj, QUEM.update_parent_episode_obj))
LOG.debug("UPDATE episode [%s/%s] %s: %s", obj['PathId'], obj['FileId'], obj['Id'], obj['Title']) LOG.debug("UPDATE episode [%s/%s] %s: %s", obj['PathId'], obj['FileId'], obj['Id'], obj['Title'])
def get_episode_path_filename(self, obj): def get_episode_path_filename(self, obj):
@ -419,7 +419,7 @@ class TVShows(KodiDb):
obj['Path'] = obj['Path'].replace(obj['Filename'], "") obj['Path'] = obj['Path'].replace(obj['Filename'], "")
else: else:
obj['Path'] = "plugin://plugin.video.emby.tvshows/%s/" % obj['SeriesId'] obj['Path'] = "plugin://plugin.video.jellyfin/%s/" % obj['SeriesId']
params = { params = {
'filename': obj['Filename'].encode('utf-8'), 'filename': obj['Filename'].encode('utf-8'),
'id': obj['Id'], 'id': obj['Id'],
@ -429,13 +429,13 @@ class TVShows(KodiDb):
obj['Filename'] = "%s?%s" % (obj['Path'], urllib.urlencode(params)) obj['Filename'] = "%s?%s" % (obj['Path'], urllib.urlencode(params))
def get_show_id(self, obj): def get_show_id(self, obj):
obj['ShowId'] = self.emby_db.get_item_by_id(*values(obj, QUEM.get_item_series_obj)) obj['ShowId'] = self.jellyfin_db.get_item_by_id(*values(obj, QUEM.get_item_series_obj))
if obj['ShowId'] is None: if obj['ShowId'] is None:
try: try:
self.tvshow(self.server['api'].get_item(obj['SeriesId']), library=None) self.tvshow(self.server['api'].get_item(obj['SeriesId']), library=None)
obj['ShowId'] = self.emby_db.get_item_by_id(*values(obj, QUEM.get_item_series_obj))[0] obj['ShowId'] = self.jellyfin_db.get_item_by_id(*values(obj, QUEM.get_item_series_obj))[0]
except (TypeError, KeyError): except (TypeError, KeyError):
LOG.error("Unable to add series %s", obj['SeriesId']) LOG.error("Unable to add series %s", obj['SeriesId'])
@ -449,7 +449,7 @@ class TVShows(KodiDb):
@stop() @stop()
@emby_item() @jellyfin_item()
def userdata(self, item, e_item): def userdata(self, item, e_item):
''' This updates: Favorite, LastPlayedDate, Playcount, PlaybackPositionTicks ''' This updates: Favorite, LastPlayedDate, Playcount, PlaybackPositionTicks
@ -493,26 +493,26 @@ class TVShows(KodiDb):
temp_obj = dict(obj) temp_obj = dict(obj)
temp_obj['Filename'] = self.get_filename(*values(temp_obj, QU.get_file_obj)) temp_obj['Filename'] = self.get_filename(*values(temp_obj, QU.get_file_obj))
temp_obj['Path'] = "plugin://plugin.video.emby.tvshows/" temp_obj['Path'] = "plugin://plugin.video.jellyfin/"
self.remove_file(*values(temp_obj, QU.delete_file_obj)) self.remove_file(*values(temp_obj, QU.delete_file_obj))
elif not self.direct_path and obj['Resume']: elif not self.direct_path and obj['Resume']:
temp_obj = dict(obj) temp_obj = dict(obj)
temp_obj['Filename'] = self.get_filename(*values(temp_obj, QU.get_file_obj)) temp_obj['Filename'] = self.get_filename(*values(temp_obj, QU.get_file_obj))
temp_obj['PathId'] = self.get_path("plugin://plugin.video.emby.tvshows/") temp_obj['PathId'] = self.get_path("plugin://plugin.video.jellyfin/")
temp_obj['FileId'] = self.add_file(*values(temp_obj, QU.add_file_obj)) temp_obj['FileId'] = self.add_file(*values(temp_obj, QU.add_file_obj))
self.update_file(*values(temp_obj, QU.update_file_obj)) self.update_file(*values(temp_obj, QU.update_file_obj))
self.add_playstate(*values(temp_obj, QU.add_bookmark_obj)) self.add_playstate(*values(temp_obj, QU.add_bookmark_obj))
self.emby_db.update_reference(*values(obj, QUEM.update_reference_obj)) self.jellyfin_db.update_reference(*values(obj, QUEM.update_reference_obj))
LOG.info("USERDATA %s [%s/%s] %s: %s", obj['Media'], obj['FileId'], obj['KodiId'], obj['Id'], obj['Title']) LOG.info("USERDATA %s [%s/%s] %s: %s", obj['Media'], obj['FileId'], obj['KodiId'], obj['Id'], obj['Title'])
@stop() @stop()
@emby_item() @jellyfin_item()
def remove(self, item_id, e_item): def remove(self, item_id, e_item):
''' Remove showid, fileid, pathid, emby reference. ''' Remove showid, fileid, pathid, jellyfin reference.
There's no episodes left, delete show and any possible remaining seasons There's no episodes left, delete show and any possible remaining seasons
''' '''
obj = {'Id': item_id} obj = {'Id': item_id}
@ -529,7 +529,7 @@ class TVShows(KodiDb):
temp_obj = dict(obj) temp_obj = dict(obj)
self.remove_episode(obj['KodiId'], obj['FileId'], obj['Id']) self.remove_episode(obj['KodiId'], obj['FileId'], obj['Id'])
season = self.emby_db.get_full_item_by_kodi_id(*values(obj, QUEM.delete_item_by_parent_season_obj)) season = self.jellyfin_db.get_full_item_by_kodi_id(*values(obj, QUEM.delete_item_by_parent_season_obj))
try: try:
temp_obj['Id'] = season[0] temp_obj['Id'] = season[0]
@ -537,61 +537,61 @@ class TVShows(KodiDb):
except TypeError: except TypeError:
return return
if not self.emby_db.get_item_by_parent_id(*values(obj, QUEM.get_item_by_parent_episode_obj)): if not self.jellyfin_db.get_item_by_parent_id(*values(obj, QUEM.get_item_by_parent_episode_obj)):
self.remove_season(obj['ParentId'], obj['Id']) self.remove_season(obj['ParentId'], obj['Id'])
self.emby_db.remove_item(*values(temp_obj, QUEM.delete_item_obj)) self.jellyfin_db.remove_item(*values(temp_obj, QUEM.delete_item_obj))
temp_obj['Id'] = self.emby_db.get_item_by_kodi_id(*values(temp_obj, QUEM.get_item_by_parent_tvshow_obj)) temp_obj['Id'] = self.jellyfin_db.get_item_by_kodi_id(*values(temp_obj, QUEM.get_item_by_parent_tvshow_obj))
if not self.get_total_episodes(*values(temp_obj, QU.get_total_episodes_obj)): if not self.get_total_episodes(*values(temp_obj, QU.get_total_episodes_obj)):
for season in self.emby_db.get_item_by_parent_id(*values(temp_obj, QUEM.get_item_by_parent_season_obj)): for season in self.jellyfin_db.get_item_by_parent_id(*values(temp_obj, QUEM.get_item_by_parent_season_obj)):
self.remove_season(season[1], obj['Id']) self.remove_season(season[1], obj['Id'])
else: else:
self.emby_db.remove_items_by_parent_id(*values(temp_obj, QUEM.delete_item_by_parent_season_obj)) self.jellyfin_db.remove_items_by_parent_id(*values(temp_obj, QUEM.delete_item_by_parent_season_obj))
self.remove_tvshow(temp_obj['ParentId'], obj['Id']) self.remove_tvshow(temp_obj['ParentId'], obj['Id'])
self.emby_db.remove_item(*values(temp_obj, QUEM.delete_item_obj)) self.jellyfin_db.remove_item(*values(temp_obj, QUEM.delete_item_obj))
elif obj['Media'] == 'tvshow': elif obj['Media'] == 'tvshow':
obj['ParentId'] = obj['KodiId'] obj['ParentId'] = obj['KodiId']
for season in self.emby_db.get_item_by_parent_id(*values(obj, QUEM.get_item_by_parent_season_obj)): for season in self.jellyfin_db.get_item_by_parent_id(*values(obj, QUEM.get_item_by_parent_season_obj)):
temp_obj = dict(obj) temp_obj = dict(obj)
temp_obj['ParentId'] = season[1] temp_obj['ParentId'] = season[1]
for episode in self.emby_db.get_item_by_parent_id(*values(temp_obj, QUEM.get_item_by_parent_episode_obj)): for episode in self.jellyfin_db.get_item_by_parent_id(*values(temp_obj, QUEM.get_item_by_parent_episode_obj)):
self.remove_episode(episode[1], episode[2], obj['Id']) self.remove_episode(episode[1], episode[2], obj['Id'])
else: else:
self.emby_db.remove_items_by_parent_id(*values(temp_obj, QUEM.delete_item_by_parent_episode_obj)) self.jellyfin_db.remove_items_by_parent_id(*values(temp_obj, QUEM.delete_item_by_parent_episode_obj))
else: else:
self.emby_db.remove_items_by_parent_id(*values(obj, QUEM.delete_item_by_parent_season_obj)) self.jellyfin_db.remove_items_by_parent_id(*values(obj, QUEM.delete_item_by_parent_season_obj))
self.remove_tvshow(obj['KodiId'], obj['Id']) self.remove_tvshow(obj['KodiId'], obj['Id'])
elif obj['Media'] == 'season': elif obj['Media'] == 'season':
for episode in self.emby_db.get_item_by_parent_id(*values(obj, QUEM.get_item_by_parent_episode_obj)): for episode in self.jellyfin_db.get_item_by_parent_id(*values(obj, QUEM.get_item_by_parent_episode_obj)):
self.remove_episode(episode[1], episode[2], obj['Id']) self.remove_episode(episode[1], episode[2], obj['Id'])
else: else:
self.emby_db.remove_items_by_parent_id(*values(obj, QUEM.delete_item_by_parent_episode_obj)) self.jellyfin_db.remove_items_by_parent_id(*values(obj, QUEM.delete_item_by_parent_episode_obj))
self.remove_season(obj['KodiId'], obj['Id']) self.remove_season(obj['KodiId'], obj['Id'])
if not self.emby_db.get_item_by_parent_id(*values(obj, QUEM.delete_item_by_parent_season_obj)): if not self.jellyfin_db.get_item_by_parent_id(*values(obj, QUEM.delete_item_by_parent_season_obj)):
self.remove_tvshow(obj['ParentId'], obj['Id']) self.remove_tvshow(obj['ParentId'], obj['Id'])
self.emby_db.remove_item_by_kodi_id(*values(obj, QUEM.delete_item_by_parent_tvshow_obj)) self.jellyfin_db.remove_item_by_kodi_id(*values(obj, QUEM.delete_item_by_parent_tvshow_obj))
# Remove any series pooling episodes # Remove any series pooling episodes
for episode in self.emby_db.get_media_by_parent_id(obj['Id']): for episode in self.jellyfin_db.get_media_by_parent_id(obj['Id']):
self.remove_episode(episode[2], episode[3], obj['Id']) self.remove_episode(episode[2], episode[3], obj['Id'])
else: else:
self.emby_db.remove_media_by_parent_id(obj['Id']) self.jellyfin_db.remove_media_by_parent_id(obj['Id'])
self.emby_db.remove_item(*values(obj, QUEM.delete_item_obj)) self.jellyfin_db.remove_item(*values(obj, QUEM.delete_item_obj))
def remove_tvshow(self, kodi_id, item_id): def remove_tvshow(self, kodi_id, item_id):
@ -611,10 +611,10 @@ class TVShows(KodiDb):
self.delete_episode(kodi_id, file_id) self.delete_episode(kodi_id, file_id)
LOG.info("DELETE episode [%s/%s] %s", file_id, kodi_id, item_id) LOG.info("DELETE episode [%s/%s] %s", file_id, kodi_id, item_id)
@emby_item() @jellyfin_item()
def get_child(self, item_id, e_item): def get_child(self, item_id, e_item):
''' Get all child elements from tv show emby id. ''' Get all child elements from tv show jellyfin id.
''' '''
obj = {'Id': item_id} obj = {'Id': item_id}
child = [] child = []
@ -629,16 +629,16 @@ class TVShows(KodiDb):
obj['ParentId'] = obj['KodiId'] obj['ParentId'] = obj['KodiId']
for season in self.emby_db.get_item_by_parent_id(*values(obj, QUEM.get_item_by_parent_season_obj)): for season in self.jellyfin_db.get_item_by_parent_id(*values(obj, QUEM.get_item_by_parent_season_obj)):
temp_obj = dict(obj) temp_obj = dict(obj)
temp_obj['ParentId'] = season[1] temp_obj['ParentId'] = season[1]
child.append(season[0]) child.append(season[0])
for episode in self.emby_db.get_item_by_parent_id(*values(temp_obj, QUEM.get_item_by_parent_episode_obj)): for episode in self.jellyfin_db.get_item_by_parent_id(*values(temp_obj, QUEM.get_item_by_parent_episode_obj)):
child.append(episode[0]) child.append(episode[0])
for episode in self.emby_db.get_media_by_parent_id(obj['Id']): for episode in self.jellyfin_db.get_media_by_parent_id(obj['Id']):
child.append(episode[0]) child.append(episode[0])
return child return child

View file

@ -8,7 +8,7 @@ from helper import JSONRPC
################################################################################################# #################################################################################################
LOG = logging.getLogger("EMBY."+__name__) LOG = logging.getLogger("JELLYFIN."+__name__)
################################################################################################# #################################################################################################

View file

@ -11,11 +11,11 @@ import xbmcvfs
from objects.obj import Objects from objects.obj import Objects
from helper import _, api, window, settings, dialog, event, silent_catch, JSONRPC from helper import _, api, window, settings, dialog, event, silent_catch, JSONRPC
from emby import Emby from jellyfin import Jellyfin
################################################################################################# #################################################################################################
LOG = logging.getLogger("EMBY."+__name__) LOG = logging.getLogger("JELLYFIN."+__name__)
################################################################################################# #################################################################################################
@ -43,7 +43,7 @@ class Player(xbmc.Player):
''' We may need to wait for info to be set in kodi monitor. ''' We may need to wait for info to be set in kodi monitor.
Accounts for scenario where Kodi starts playback and exits immediately. Accounts for scenario where Kodi starts playback and exits immediately.
First, ensure previous playback terminated correctly in Emby. First, ensure previous playback terminated correctly in Jellyfin.
''' '''
self.stop_playback() self.stop_playback()
self.up_next = False self.up_next = False
@ -69,7 +69,7 @@ class Player(xbmc.Player):
return return
items = window('emby_play.json') items = window('jellyfin_play.json')
item = None item = None
while not items: while not items:
@ -77,11 +77,11 @@ class Player(xbmc.Player):
if monitor.waitForAbort(2): if monitor.waitForAbort(2):
return return
items = window('emby_play.json') items = window('jellyfin_play.json')
count += 1 count += 1
if count == 20: if count == 20:
LOG.info("Could not find emby prop...") LOG.info("Could not find jellyfin prop...")
return return
@ -93,7 +93,7 @@ class Player(xbmc.Player):
else: else:
item = items.pop(0) item = items.pop(0)
window('emby_play.json', items) window('jellyfin_play.json', items)
self.set_item(current_file, item) self.set_item(current_file, item)
data = { data = {
@ -111,7 +111,7 @@ class Player(xbmc.Player):
'SubtitleStreamIndex': item['SubtitleStreamIndex'] 'SubtitleStreamIndex': item['SubtitleStreamIndex']
} }
item['Server']['api'].session_playing(data) item['Server']['api'].session_playing(data)
window('emby.skip.%s.bool' % item['Id'], True) window('jellyfin.skip.%s.bool' % item['Id'], True)
if monitor.waitForAbort(2): if monitor.waitForAbort(2):
return return
@ -148,7 +148,7 @@ class Player(xbmc.Player):
'CurrentPosition': item.get('CurrentPosition') or int(seektime), 'CurrentPosition': item.get('CurrentPosition') or int(seektime),
'Muted': muted, 'Muted': muted,
'Volume': volume, 'Volume': volume,
'Server': Emby(item['ServerId']).get_client(), 'Server': Jellyfin(item['ServerId']).get_client(),
'Paused': False 'Paused': False
}) })
@ -302,7 +302,7 @@ class Player(xbmc.Player):
def report_playback(self, report=True): def report_playback(self, report=True):
''' Report playback progress to emby server. ''' Report playback progress to jellyfin server.
Check if the user seek. Check if the user seek.
''' '''
current_file = self.get_playing_file() current_file = self.get_playing_file()
@ -312,7 +312,7 @@ class Player(xbmc.Player):
item = self.get_file_info(current_file) item = self.get_file_info(current_file)
if window('emby.external.bool'): if window('jellyfin.external.bool'):
return return
if not report: if not report:
@ -365,7 +365,7 @@ class Player(xbmc.Player):
''' Will be called when user stops playing a file. ''' Will be called when user stops playing a file.
''' '''
window('emby_play', clear=True) window('jellyfin_play', clear=True)
self.stop_playback() self.stop_playback()
LOG.info("--<[ playback ]") LOG.info("--<[ playback ]")
@ -388,10 +388,10 @@ class Player(xbmc.Player):
for file in self.played: for file in self.played:
item = self.get_file_info(file) item = self.get_file_info(file)
window('emby.skip.%s.bool' % item['Id'], True) window('jellyfin.skip.%s.bool' % item['Id'], True)
if window('emby.external.bool'): if window('jellyfin.external.bool'):
window('emby.external', clear=True) window('jellyfin.external', clear=True)
if int(item['CurrentPosition']) == 1: if int(item['CurrentPosition']) == 1:
item['CurrentPosition'] = int(item['Runtime']) item['CurrentPosition'] = int(item['Runtime'])
@ -415,7 +415,7 @@ class Player(xbmc.Player):
item['Server']['api'].close_transcode(item['DeviceId']) item['Server']['api'].close_transcode(item['DeviceId'])
path = xbmc.translatePath("special://profile/addon_data/plugin.video.emby/temp/").decode('utf-8') path = xbmc.translatePath("special://profile/addon_data/plugin.video.jellyfin/temp/").decode('utf-8')
if xbmcvfs.exists(path): if xbmcvfs.exists(path):
dirs, files = xbmcvfs.listdir(path) dirs, files = xbmcvfs.listdir(path)
@ -442,6 +442,6 @@ class Player(xbmc.Player):
if dialog("yesno", heading=_(30091), line1=_(33015), autoclose=120000): if dialog("yesno", heading=_(30091), line1=_(33015), autoclose=120000):
item['Server']['api'].delete_item(item['Id']) item['Server']['api'].delete_item(item['Id'])
window('emby.external_check', clear=True) window('jellyfin.external_check', clear=True)
self.played.clear() self.played.clear()

View file

@ -10,7 +10,7 @@ from helper import _, settings, dialog, JSONRPC, compare_version
################################################################################################# #################################################################################################
LOG = logging.getLogger("EMBY."+__name__) LOG = logging.getLogger("JELLYFIN."+__name__)
################################################################################################# #################################################################################################
@ -42,7 +42,7 @@ class Setup(object):
if not self.get_web_server(): if not self.get_web_server():
settings('enableTextureCache.bool', False) settings('enableTextureCache.bool', False)
dialog("ok", heading="{emby}", line1=_(33103)) dialog("ok", heading="{jellyfin}", line1=_(33103))
return return
@ -105,24 +105,24 @@ class Setup(object):
settings('useDirectPaths', value="1" if value else "0") settings('useDirectPaths', value="1" if value else "0")
if value: if value:
dialog("ok", heading="{emby}", line1=_(33145)) dialog("ok", heading="{jellyfin}", line1=_(33145))
def _is_artwork_caching(self): def _is_artwork_caching(self):
value = dialog("yesno", heading="{emby}", line1=_(33117)) value = dialog("yesno", heading="{jellyfin}", line1=_(33117))
settings('enableTextureCache.bool', value) settings('enableTextureCache.bool', value)
def _is_empty_shows(self): def _is_empty_shows(self):
value = dialog("yesno", heading="{emby}", line1=_(33100)) value = dialog("yesno", heading="{jellyfin}", line1=_(33100))
settings('syncEmptyShows.bool', value) settings('syncEmptyShows.bool', value)
def _is_rotten_tomatoes(self): def _is_rotten_tomatoes(self):
value = dialog("yesno", heading="{emby}", line1=_(33188)) value = dialog("yesno", heading="{jellyfin}", line1=_(33188))
settings('syncRottenTomatoes.bool', value) settings('syncRottenTomatoes.bool', value)
def _is_music(self): def _is_music(self):
value = dialog("yesno", heading="{emby}", line1=_(33039)) value = dialog("yesno", heading="{jellyfin}", line1=_(33039))
settings('enableMusic.bool', value=value) settings('enableMusic.bool', value=value)

View file

@ -12,14 +12,14 @@ import xbmc
import xbmcvfs import xbmcvfs
import downloader as server import downloader as server
from database import Database, emby_db, get_sync, save_sync from database import Database, jellyfin_db, get_sync, save_sync
from objects.kodi import kodi from objects.kodi import kodi
from helper import _, api, indent, write_xml, window, event from helper import _, api, indent, write_xml, window, event
from emby import Emby from jellyfin import Jellyfin
################################################################################################# #################################################################################################
LOG = logging.getLogger("EMBY."+__name__) LOG = logging.getLogger("JELLYFIN."+__name__)
NODES = { NODES = {
'tvshows': [ 'tvshows': [
('all', None), ('all', None),
@ -144,21 +144,21 @@ class Views(object):
def __init__(self): def __init__(self):
self.sync = get_sync() self.sync = get_sync()
self.server = Emby() self.server = Jellyfin()
def add_library(self, view): def add_library(self, view):
''' Add entry to view table in emby database. ''' Add entry to view table in jellyfin database.
''' '''
with Database('emby') as embydb: with Database('jellyfin') as jellyfindb:
emby_db.EmbyDatabase(embydb.cursor).add_view(view['Id'], view['Name'], view['Media']) jellyfin_db.JellyfinDatabase(jellyfindb.cursor).add_view(view['Id'], view['Name'], view['Media'])
def remove_library(self, view_id): def remove_library(self, view_id):
''' Remove entry from view table in emby database. ''' Remove entry from view table in jellyfin database.
''' '''
with Database('emby') as embydb: with Database('jellyfin') as jellyfindb:
emby_db.EmbyDatabase(embydb.cursor).remove_view(view_id) jellyfin_db.JellyfinDatabase(jellyfindb.cursor).remove_view(view_id)
self.delete_playlist_by_id(view_id) self.delete_playlist_by_id(view_id)
self.delete_node_by_id(view_id) self.delete_node_by_id(view_id)
@ -203,9 +203,9 @@ class Views(object):
self.add_library(library) self.add_library(library)
with Database('emby') as embydb: with Database('jellyfin') as jellyfindb:
views = emby_db.EmbyDatabase(embydb.cursor).get_views() views = jellyfin_db.JellyfinDatabase(jellyfindb.cursor).get_views()
removed = [] removed = []
for view in views: for view in views:
@ -226,8 +226,8 @@ class Views(object):
playlist_path = xbmc.translatePath("special://profile/playlists/video").decode('utf-8') playlist_path = xbmc.translatePath("special://profile/playlists/video").decode('utf-8')
index = 0 index = 0
with Database('emby') as embydb: with Database('jellyfin') as jellyfindb:
db = emby_db.EmbyDatabase(embydb.cursor) db = jellyfin_db.JellyfinDatabase(jellyfindb.cursor)
for library in self.sync['Whitelist']: for library in self.sync['Whitelist']:
@ -250,7 +250,7 @@ class Views(object):
if view['Media'] in ('movies', 'tvshows', 'musicvideos'): if view['Media'] in ('movies', 'tvshows', 'musicvideos'):
self.add_playlist(playlist_path, view) self.add_playlist(playlist_path, view)
if view['Media'] not in ('music'): if view['Media'] not in ('music',):
self.add_nodes(node_path, view) self.add_nodes(node_path, view)
index += 1 index += 1
@ -268,7 +268,7 @@ class Views(object):
''' Create or update the xps file. ''' Create or update the xps file.
''' '''
file = os.path.join(path, "emby%s%s.xsp" % (view['Media'], view['Id'])) file = os.path.join(path, "jellyfin%s%s.xsp" % (view['Media'], view['Id']))
try: try:
xml = etree.parse(file).getroot() xml = etree.parse(file).getroot()
@ -297,7 +297,7 @@ class Views(object):
''' Create or update the video node file. ''' Create or update the video node file.
''' '''
folder = os.path.join(path, "emby%s%s" % (view['Media'], view['Id'])) folder = os.path.join(path, "jellyfin%s%s" % (view['Media'], view['Id']))
if not xbmcvfs.exists(folder): if not xbmcvfs.exists(folder):
xbmcvfs.mkdir(folder) xbmcvfs.mkdir(folder)
@ -311,7 +311,7 @@ class Views(object):
def add_single_node(self, path, index, item_type, view): def add_single_node(self, path, index, item_type, view):
file = os.path.join(path, "emby_%s.xml" % view['Tag'].replace(" ", "")) file = os.path.join(path, "jellyfin_%s.xml" % view['Tag'].replace(" ", ""))
try: try:
xml = etree.parse(file).getroot() xml = etree.parse(file).getroot()
@ -359,7 +359,7 @@ class Views(object):
else: else:
element = etree.Element('node', {'order': str(index), 'type': "folder"}) element = etree.Element('node', {'order': str(index), 'type': "folder"})
etree.SubElement(element, 'icon').text = "special://home/addons/plugin.video.emby/icon.png" etree.SubElement(element, 'icon').text = "special://home/addons/plugin.video.jellyfin/icon.png"
return element return element
@ -657,7 +657,7 @@ class Views(object):
def order_media_folders(self, folders): def order_media_folders(self, folders):
''' Returns a list of sorted media folders based on the Emby views. ''' Returns a list of sorted media folders based on the Jellyfin views.
Insert them in SortedViews and remove Views that are not in media folders. Insert them in SortedViews and remove Views that are not in media folders.
''' '''
if not folders: if not folders:
@ -677,13 +677,13 @@ class Views(object):
def window_nodes(self): def window_nodes(self):
''' Just read from the database and populate based on SortedViews ''' Just read from the database and populate based on SortedViews
Setup the window properties that reflect the emby server views and more. Setup the window properties that reflect the jellyfin server views and more.
''' '''
self.window_clear() self.window_clear()
self.window_clear('Emby.wnodes') self.window_clear('Jellyfin.wnodes')
with Database('emby') as embydb: with Database('jellyfin') as jellyfindb:
libraries = emby_db.EmbyDatabase(embydb.cursor).get_views() libraries = jellyfin_db.JellyfinDatabase(jellyfindb.cursor).get_views()
libraries = self.order_media_folders(libraries or []) libraries = self.order_media_folders(libraries or [])
index = 0 index = 0
@ -743,8 +743,8 @@ class Views(object):
self.window_single_node(index, "favorites", single) self.window_single_node(index, "favorites", single)
index += 1 index += 1
window('Emby.nodes.total', str(index)) window('Jellyfin.nodes.total', str(index))
window('Emby.wnodes.total', str(windex)) window('Jellyfin.wnodes.total', str(windex))
def window_node(self, index, view, node=None, node_label=None): def window_node(self, index, view, node=None, node_label=None):
@ -773,17 +773,17 @@ class Views(object):
if node in ('all', 'music'): if node in ('all', 'music'):
window_prop = "Emby.nodes.%s" % index window_prop = "Jellyfin.nodes.%s" % index
window('%s.index' % window_prop, path.replace('all.xml', "")) # dir window('%s.index' % window_prop, path.replace('all.xml', "")) # dir
window('%s.title' % window_prop, view['Name'].encode('utf-8')) window('%s.title' % window_prop, view['Name'].encode('utf-8'))
window('%s.content' % window_prop, path) window('%s.content' % window_prop, path)
elif node == 'browse': elif node == 'browse':
window_prop = "Emby.nodes.%s" % index window_prop = "Jellyfin.nodes.%s" % index
window('%s.title' % window_prop, view['Name'].encode('utf-8')) window('%s.title' % window_prop, view['Name'].encode('utf-8'))
else: else:
window_prop = "Emby.nodes.%s.%s" % (index, node) window_prop = "Jellyfin.nodes.%s.%s" % (index, node)
window('%s.title' % window_prop, node_label.encode('utf-8')) window('%s.title' % window_prop, node_label.encode('utf-8'))
window('%s.content' % window_prop, path) window('%s.content' % window_prop, path)
@ -796,10 +796,10 @@ class Views(object):
''' Single destination node. ''' Single destination node.
''' '''
path = "library://video/emby_%s.xml" % view['Tag'].replace(" ", "") path = "library://video/jellyfin_%s.xml" % view['Tag'].replace(" ", "")
window_path = "ActivateWindow(Videos,%s,return)" % path window_path = "ActivateWindow(Videos,%s,return)" % path
window_prop = "Emby.nodes.%s" % index window_prop = "Jellyfin.nodes.%s" % index
window('%s.title' % window_prop, view['Name']) window('%s.title' % window_prop, view['Name'])
window('%s.path' % window_prop, window_path) window('%s.path' % window_prop, window_path)
window('%s.content' % window_prop, path) window('%s.content' % window_prop, path)
@ -825,18 +825,18 @@ class Views(object):
if node == 'all': if node == 'all':
window_prop = "Emby.wnodes.%s" % index window_prop = "Jellyfin.wnodes.%s" % index
window('%s.index' % window_prop, path.replace('all.xml', "")) # dir window('%s.index' % window_prop, path.replace('all.xml', "")) # dir
window('%s.title' % window_prop, view['Name'].encode('utf-8')) window('%s.title' % window_prop, view['Name'].encode('utf-8'))
window('%s.content' % window_prop, path) window('%s.content' % window_prop, path)
elif node == 'browse': elif node == 'browse':
window_prop = "Emby.wnodes.%s" % index window_prop = "Jellyfin.wnodes.%s" % index
window('%s.title' % window_prop, view['Name'].encode('utf-8')) window('%s.title' % window_prop, view['Name'].encode('utf-8'))
window('%s.content' % window_prop, path) window('%s.content' % window_prop, path)
else: else:
window_prop = "Emby.wnodes.%s.%s" % (index, node) window_prop = "Jellyfin.wnodes.%s.%s" % (index, node)
window('%s.title' % window_prop, node_label.encode('utf-8')) window('%s.title' % window_prop, node_label.encode('utf-8'))
window('%s.content' % window_prop, path) window('%s.content' % window_prop, path)
@ -865,7 +865,7 @@ class Views(object):
window('%s.artwork' % prop, clear=True) window('%s.artwork' % prop, clear=True)
def window_path(self, view, node): def window_path(self, view, node):
return "library://video/emby%s%s/%s.xml" % (view['Media'], view['Id'], node) return "library://video/jellyfin%s%s/%s.xml" % (view['Media'], view['Id'], node)
def window_music(self, view): def window_music(self, view):
return "library://music/" return "library://music/"
@ -877,7 +877,7 @@ class Views(object):
'mode': "nextepisodes", 'mode': "nextepisodes",
'limit': self.limit 'limit': self.limit
} }
return "%s?%s" % ("plugin://plugin.video.emby/", urllib.urlencode(params)) return "%s?%s" % ("plugin://plugin.video.jellyfin/", urllib.urlencode(params))
def window_browse(self, view, node=None): def window_browse(self, view, node=None):
@ -892,13 +892,13 @@ class Views(object):
if node: if node:
params['folder'] = node params['folder'] = node
return "%s?%s" % ("plugin://plugin.video.emby/", urllib.urlencode(params)) return "%s?%s" % ("plugin://plugin.video.jellyfin/", urllib.urlencode(params))
def window_clear(self, name=None): def window_clear(self, name=None):
''' Clearing window prop setup for Views. ''' Clearing window prop setup for Views.
''' '''
total = int(window((name or 'Emby.nodes') + '.total') or 0) total = int(window((name or 'Jellyfin.nodes') + '.total') or 0)
props = [ props = [
"index","id","path","artwork","title","content","type" "index","id","path","artwork","title","content","type"
@ -914,10 +914,10 @@ class Views(object):
] ]
for i in range(total): for i in range(total):
for prop in props: for prop in props:
window('Emby.nodes.%s.%s' % (str(i), prop), clear=True) window('Jellyfin.nodes.%s.%s' % (str(i), prop), clear=True)
for prop in props: for prop in props:
window('Emby.nodes.%s' % prop, clear=True) window('Jellyfin.nodes.%s' % prop, clear=True)
def delete_playlist(self, path): def delete_playlist(self, path):
@ -926,12 +926,12 @@ class Views(object):
def delete_playlists(self): def delete_playlists(self):
''' Remove all emby playlists. ''' Remove all jellyfin playlists.
''' '''
path = xbmc.translatePath("special://profile/playlists/video/").decode('utf-8') path = xbmc.translatePath("special://profile/playlists/video/").decode('utf-8')
_, files = xbmcvfs.listdir(path) _, files = xbmcvfs.listdir(path)
for file in files: for file in files:
if file.decode('utf-8').startswith('emby'): if file.decode('utf-8').startswith('jellyfin'):
self.delete_playlist(os.path.join(path, file.decode('utf-8'))) self.delete_playlist(os.path.join(path, file.decode('utf-8')))
def delete_playlist_by_id(self, view_id): def delete_playlist_by_id(self, view_id):
@ -943,7 +943,7 @@ class Views(object):
for file in files: for file in files:
file = file.decode('utf-8') file = file.decode('utf-8')
if file.startswith('emby') and file.endswith('%s.xsp' % view_id): if file.startswith('jellyfin') and file.endswith('%s.xsp' % view_id):
self.delete_playlist(os.path.join(path, file.decode('utf-8'))) self.delete_playlist(os.path.join(path, file.decode('utf-8')))
def delete_node(self, path): def delete_node(self, path):
@ -960,12 +960,12 @@ class Views(object):
for file in files: for file in files:
if file.startswith('emby'): if file.startswith('jellyfin'):
self.delete_node(os.path.join(path, file.decode('utf-8'))) self.delete_node(os.path.join(path, file.decode('utf-8')))
for directory in dirs: for directory in dirs:
if directory.startswith('emby'): if directory.startswith('jellyfin'):
_, files = xbmcvfs.listdir(os.path.join(path, directory.decode('utf-8'))) _, files = xbmcvfs.listdir(os.path.join(path, directory.decode('utf-8')))
for file in files: for file in files:
@ -982,7 +982,7 @@ class Views(object):
for directory in dirs: for directory in dirs:
if directory.startswith('emby') and directory.endswith(view_id): if directory.startswith('jellyfin') and directory.endswith(view_id):
_, files = xbmcvfs.listdir(os.path.join(path, directory.decode('utf-8'))) _, files = xbmcvfs.listdir(os.path.join(path, directory.decode('utf-8')))
for file in files: for file in files:

View file

@ -13,7 +13,7 @@ import xbmc
################################################################################################# #################################################################################################
PORT = 57578 PORT = 57578
LOG = logging.getLogger("EMBY."+__name__) LOG = logging.getLogger("JELLYFIN."+__name__)
################################################################################################# #################################################################################################
@ -126,7 +126,7 @@ class requestHandler(BaseHTTPServer.BaseHTTPRequestHandler):
xbmc.log("[ webservice ] path: %s params: %s" % (str(self.path), str(params)), xbmc.LOGWARNING) xbmc.log("[ webservice ] path: %s params: %s" % (str(self.path), str(params)), xbmc.LOGWARNING)
path = ("plugin://plugin.video.emby?mode=play&id=%s&dbid=%s&filename=%s&transcode=%s" path = ("plugin://plugin.video.jellyfin?mode=play&id=%s&dbid=%s&filename=%s&transcode=%s"
% (params.get('Id'), params.get('KodiId'), params.get('Name'), params.get('transcode') or False)) % (params.get('Id'), params.get('KodiId'), params.get('Name'), params.get('transcode') or False))
self.send_response(200) self.send_response(200)

View file

@ -1,15 +1,12 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?> <?xml version="1.0" encoding="utf-8" standalone="yes"?>
<settings> <settings>
<category label="29999"><!-- Emby --> <category label="29999"><!-- Jellyfin -->
<setting label="30003" id="idMethod" type="enum" values="Manual|Emby Connect" default="0" /> <setting label="30003" id="idMethod" type="enum" values="Manual" default="0" />
<setting label="30024" id="username" type="text" default="" visible="eq(-1,0)" /> <setting label="30024" id="username" type="text" default="" visible="true" />
<setting label="30543" id="connectUsername" type="text" default="" visible="!eq(0,) + eq(-2,1)" />
<setting label="30600" type="action" action="RunPlugin(plugin://plugin.video.emby?mode=connect)" visible="eq(-3,1) + eq(-1,)" option="close" />
<setting label="30618" type="action" action="RunPlugin(plugin://plugin.video.emby?mode=connect)" visible="eq(-4,1) + !eq(-2,)" option="close" />
<setting label="30001" id="serverName" type="text" default="" /> <setting label="30001" id="serverName" type="text" default="" />
<setting label="30000" id="server" type="text" default="" visible="true" /> <setting label="30000" id="server" type="text" default="" visible="true" />
<setting label="33150" type="action" action="RunPlugin(plugin://plugin.video.emby?mode=updateserver)" visible="!eq(-1,)" option="close" /> <setting label="33150" type="action" action="RunPlugin(plugin://plugin.video.jellyfin?mode=updateserver)" visible="!eq(-1,)" option="close" />
<setting label="30500" id="sslverify" type="bool" default="true" visible="true" /> <setting label="30500" id="sslverify" type="bool" default="true" visible="true" />
<setting type="sep" /> <setting type="sep" />
@ -92,19 +89,18 @@
<category label="30022"><!-- Advanced --> <category label="30022"><!-- Advanced -->
<setting label="30004" id="logLevel" type="enum" values="Disabled|Info|Debug" default="1" /> <setting label="30004" id="logLevel" type="enum" values="Disabled|Info|Debug" default="1" />
<setting label="33164" id="maskInfo" type="bool" default="true" /> <setting label="33164" id="maskInfo" type="bool" default="true" />
<setting label="30239" type="action" action="RunPlugin(plugin://plugin.video.emby?mode=reset)" option="close" /> <setting label="30239" type="action" action="RunPlugin(plugin://plugin.video.jellyfin?mode=reset)" option="close" />
<setting label="30535" type="action" action="RunPlugin(plugin://plugin.video.emby?mode=deviceid)" option="close" /> <setting label="30535" type="action" action="RunPlugin(plugin://plugin.video.jellyfin?mode=deviceid)" option="close" />
<setting label="33196" type="lsep" /> <setting label="33196" type="lsep" />
<setting label="33195" id="enableAddon" type="bool" default="true" /> <setting label="33195" id="enableAddon" type="bool" default="true" />
<setting label="33180" type="action" action="RunPlugin(plugin://plugin.video.emby?mode=restartservice)" option="close" /> <setting label="33180" type="action" action="RunPlugin(plugin://plugin.video.jellyfin?mode=restartservice)" option="close" />
<setting label="30529" id="startupDelay" type="number" default="0" option="int" /> <setting label="30529" id="startupDelay" type="number" default="0" option="int" />
<setting label="33161" type="action" action="RunPlugin(plugin://plugin.video.emby?mode=checkupdate)" option="close" />
<setting label="Developer mode" id="devMode" type="bool" default="false" /> <setting label="Developer mode" id="devMode" type="bool" default="false" />
<setting type="sep" /> <setting type="sep" />
<setting label="33104" type="lsep"/> <setting label="33104" type="lsep"/>
<setting label="33093" type="folder" id="backupPath" option="writeable" /> <setting label="33093" type="folder" id="backupPath" option="writeable" />
<setting label="33092" type="action" action="RunPlugin(plugin://plugin.video.emby?mode=backup)" visible="!eq(-1,)" option="close" /> <setting label="33092" type="action" action="RunPlugin(plugin://plugin.video.jellyfin?mode=backup)" visible="!eq(-1,)" option="close" />
</category> </category>
</settings> </settings>

View file

@ -1,203 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<window>
<animation type="WindowOpen" reversible="false">
<effect type="zoom" start="80" end="100" center="960,540" delay="160" tween="circle" easin="out" time="240" />
<effect type="fade" delay="160" end="100" time="240" />
</animation>
<animation type="WindowClose" reversible="false">
<effect type="zoom" start="100" end="80" center="960,540" easing="in" tween="circle" easin="out" time="240" />
<effect type="fade" start="100" end="0" time="240" />
</animation>
<controls>
<control type="group">
<control type="image">
<top>-200</top>
<bottom>-200</bottom>
<left>-200</left>
<right>-200</right>
<texture colordiffuse="CC000000">white.png</texture>
<aspectratio>stretch</aspectratio>
<animation effect="fade" end="100" time="200">WindowOpen</animation>
<animation effect="fade" start="100" end="0" time="200">WindowClose</animation>
</control>
<control type="group">
<centerleft>50%</centerleft>
<centertop>50%</centertop>
<width>470</width>
<height>660</height>
<control type="group">
<top>-30</top>
<control type="image">
<left>20</left>
<width>100%</width>
<height>25</height>
<texture>logo-white.png</texture>
<aspectratio align="left">keep</aspectratio>
</control>
</control>
<control type="image">
<width>100%</width>
<height>660</height>
<texture colordiffuse="ff222326" border="10">dialogs/dialog_back.png</texture>
</control>
<control type="group">
<centerleft>50%</centerleft>
<top>10</top>
<width>460</width>
<height>660</height>
<control type="grouplist" id="100">
<orientation>vertical</orientation>
<itemgap>0</itemgap>
<control type="label">
<width>100%</width>
<height>75</height>
<aligny>center</aligny>
<textoffsetx>20</textoffsetx>
<font>font13</font>
<textcolor>white</textcolor>
<textshadow>66000000</textshadow>
<label>[B]$ADDON[plugin.video.emby 30612][/B]</label>
</control>
<control type="group" id="101">
<height>110</height>
<control type="label">
<label>$ADDON[plugin.video.emby 30024]</label>
<textcolor>ffe1e1e1</textcolor>
<shadowcolor>66000000</shadowcolor>
<font>font12</font>
<aligny>top</aligny>
<textoffsetx>20</textoffsetx>
</control>
<control type="label">
<height>50</height>
</control>
<control type="image">
<left>20</left>
<right>20</right>
<height>1</height>
<top>90</top>
<texture colordiffuse="ff525252">white.png</texture>
</control>
</control>
<control type="group" id="102">
<height>110</height>
<control type="label">
<label>$ADDON[plugin.video.emby 30602]</label>
<textcolor>ffe1e1e1</textcolor>
<textshadow>66000000</textshadow>
<font>font12</font>
<aligny>top</aligny>
<textoffsetx>20</textoffsetx>
</control>
<control type="label">
<height>50</height>
</control>
<control type="image">
<description>separator</description>
<left>20</left>
<right>20</right>
<height>1</height>
<top>90</top>
<texture colordiffuse="ff525252">white.png</texture>
</control>
</control>
<control type="button" id="200">
<label>[B]$ADDON[plugin.video.emby 30605][/B]</label>
<width>426</width>
<height>65</height>
<font>font13</font>
<textcolor>ffe1e1e1</textcolor>
<focusedcolor>white</focusedcolor>
<selectedcolor>ffe1e1e1</selectedcolor>
<shadowcolor>66000000</shadowcolor>
<textoffsetx>20</textoffsetx>
<aligny>center</aligny>
<align>center</align>
<texturefocus border="10" colordiffuse="ff52b54b">buttons/shadow_smallbutton.png</texturefocus>
<texturenofocus border="10" colordiffuse="ff464646">buttons/shadow_smallbutton.png</texturenofocus>
<pulseonselect>no</pulseonselect>
<animation effect="slide" time="0" end="17,0" condition="true">Conditional</animation>
</control>
<control type="button" id="201">
<label>[B]$ADDON[plugin.video.emby 30606][/B]</label>
<width>426</width>
<height>65</height>
<font>font13</font>
<textcolor>ffe1e1e1</textcolor>
<focusedcolor>white</focusedcolor>
<selectedcolor>ffe1e1e1</selectedcolor>
<shadowcolor>66000000</shadowcolor>
<textoffsetx>20</textoffsetx>
<aligny>center</aligny>
<align>center</align>
<texturefocus border="10" colordiffuse="ff52b54b">buttons/shadow_smallbutton.png</texturefocus>
<texturenofocus border="10" colordiffuse="ff464646">buttons/shadow_smallbutton.png</texturenofocus>
<pulseonselect>no</pulseonselect>
<animation effect="slide" time="0" end="17,0" condition="true">Conditional</animation>
</control>
<control type="label">
<description>spacer</description>
<height>20</height>
</control>
<control type="group">
<control type="label">
<label>$ADDON[plugin.video.emby 30603]</label>
<font>font_flag</font>
<textcolor>ff464646</textcolor>
<shadowcolor>66000000</shadowcolor>
<wrapmultiline>true</wrapmultiline>
<scroll>true</scroll>
<aligny>top</aligny>
<height>160</height>
<left>20</left>
<right>160</right>
</control>
<control type="group">
<top>10</top>
<right>20</right>
<width>130</width>
<control type="image">
<width>130</width>
<height>130</height>
<description>qrcode</description>
<texture>qrcode_disclaimer.png</texture>
</control>
<control type="label">
<top>135</top>
<align>center</align>
<label>[UPPERCASE]$ADDON[plugin.video.emby 30604][/UPPERCASE]</label>
<font>font_flag</font>
<scroll>true</scroll>
<textcolor>FF52b54b</textcolor>
<shadowcolor>66000000</shadowcolor>
<aligny>top</aligny>
</control>
</control>
</control>
</control>
</control>
<control type="group" id="202">
<top>660</top>
<visible>false</visible>
<control type="image">
<description>Error box</description>
<width>100%</width>
<height>70</height>
<texture colordiffuse="ff222326" border="10">dialogs/dialog_back.png</texture>
</control>
<control type="label" id="203">
<top>10</top>
<height>50</height>
<textcolor>ffe1e1e1</textcolor>
<scroll>true</scroll>
<shadowcolor>66000000</shadowcolor>
<font>font12</font>
<textoffsetx>20</textoffsetx>
<aligny>center</aligny>
<align>center</align>
</control>
</control>
</control>
</control>
</controls>
</window>

View file

@ -57,12 +57,12 @@
<font>font13</font> <font>font13</font>
<textcolor>white</textcolor> <textcolor>white</textcolor>
<textshadow>66000000</textshadow> <textshadow>66000000</textshadow>
<label>[B]$ADDON[plugin.video.emby 30612][/B]</label> <label>[B]$ADDON[plugin.video.jellyfin 30612][/B]</label>
</control> </control>
<control type="group" id="101"> <control type="group" id="101">
<height>110</height> <height>110</height>
<control type="label"> <control type="label">
<label>$ADDON[plugin.video.emby 30024]</label> <label>$ADDON[plugin.video.jellyfin 30024]</label>
<textcolor>ffe1e1e1</textcolor> <textcolor>ffe1e1e1</textcolor>
<shadowcolor>66000000</shadowcolor> <shadowcolor>66000000</shadowcolor>
<font>font12</font> <font>font12</font>
@ -83,7 +83,7 @@
<control type="group" id="102"> <control type="group" id="102">
<height>110</height> <height>110</height>
<control type="label"> <control type="label">
<label>$ADDON[plugin.video.emby 30602]</label> <label>$ADDON[plugin.video.jellyfin 30602]</label>
<textcolor>ffe1e1e1</textcolor> <textcolor>ffe1e1e1</textcolor>
<textshadow>66000000</textshadow> <textshadow>66000000</textshadow>
<font>font12</font> <font>font12</font>
@ -103,7 +103,7 @@
</control> </control>
</control> </control>
<control type="button" id="200"> <control type="button" id="200">
<label>[B]$ADDON[plugin.video.emby 30605][/B]</label> <label>[B]$ADDON[plugin.video.jellyfin 30605][/B]</label>
<width>426</width> <width>426</width>
<height>65</height> <height>65</height>
<font>font13</font> <font>font13</font>
@ -121,7 +121,7 @@
<animation effect="slide" time="0" end="17,0" condition="true">Conditional</animation> <animation effect="slide" time="0" end="17,0" condition="true">Conditional</animation>
</control> </control>
<control type="button" id="201"> <control type="button" id="201">
<label>[B]$ADDON[plugin.video.emby 30606][/B]</label> <label>[B]$ADDON[plugin.video.jellyfin 30606][/B]</label>
<width>426</width> <width>426</width>
<height>65</height> <height>65</height>
<font>font13</font> <font>font13</font>

View file

@ -57,12 +57,12 @@
<font>font13</font> <font>font13</font>
<textcolor>white</textcolor> <textcolor>white</textcolor>
<textshadow>66000000</textshadow> <textshadow>66000000</textshadow>
<label>[B]$ADDON[plugin.video.emby 30614][/B]</label> <label>[B]$ADDON[plugin.video.jellyfin 30614][/B]</label>
</control> </control>
<control type="group" id="101"> <control type="group" id="101">
<height>110</height> <height>110</height>
<control type="label"> <control type="label">
<label>$ADDON[plugin.video.emby 30615]</label> <label>$ADDON[plugin.video.jellyfin 30615]</label>
<textcolor>ffe1e1e1</textcolor> <textcolor>ffe1e1e1</textcolor>
<shadowcolor>66000000</shadowcolor> <shadowcolor>66000000</shadowcolor>
<font>font12</font> <font>font12</font>
@ -83,7 +83,7 @@
<control type="group" id="102"> <control type="group" id="102">
<height>110</height> <height>110</height>
<control type="label"> <control type="label">
<label>$ADDON[plugin.video.emby 30030]</label> <label>$ADDON[plugin.video.jellyfin 30030]</label>
<textcolor>ffe1e1e1</textcolor> <textcolor>ffe1e1e1</textcolor>
<textshadow>66000000</textshadow> <textshadow>66000000</textshadow>
<font>font12</font> <font>font12</font>
@ -103,7 +103,7 @@
</control> </control>
</control> </control>
<control type="button" id="200"> <control type="button" id="200">
<label>[B]$ADDON[plugin.video.emby 30616][/B]</label> <label>[B]$ADDON[plugin.video.jellyfin 30616][/B]</label>
<width>426</width> <width>426</width>
<height>65</height> <height>65</height>
<font>font13</font> <font>font13</font>
@ -120,7 +120,7 @@
<animation effect="slide" time="0" end="17,0" condition="true">Conditional</animation> <animation effect="slide" time="0" end="17,0" condition="true">Conditional</animation>
</control> </control>
<control type="button" id="201"> <control type="button" id="201">
<label>[B]$ADDON[plugin.video.emby 30606][/B]</label> <label>[B]$ADDON[plugin.video.jellyfin 30606][/B]</label>
<width>426</width> <width>426</width>
<height>65</height> <height>65</height>
<font>font13</font> <font>font13</font>

View file

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<window> <window>
<defaultcontrol always="true">205</defaultcontrol> <defaultcontrol always="true">206</defaultcontrol>
<animation type="WindowOpen" reversible="false"> <animation type="WindowOpen" reversible="false">
<effect type="zoom" start="80" end="100" center="960,540" delay="160" tween="circle" easin="out" time="240" /> <effect type="zoom" start="80" end="100" center="960,540" delay="160" tween="circle" easin="out" time="240" />
<effect type="fade" delay="160" end="100" time="240" /> <effect type="fade" delay="160" end="100" time="240" />
@ -64,7 +64,7 @@
<font>font13</font> <font>font13</font>
<textcolor>white</textcolor> <textcolor>white</textcolor>
<textshadow>66000000</textshadow> <textshadow>66000000</textshadow>
<label>[B]$ADDON[plugin.video.emby 30607][/B]</label> <label>[B]$ADDON[plugin.video.jellyfin 30607][/B]</label>
</control> </control>
<control type="group" id="101"> <control type="group" id="101">
<height>200</height> <height>200</height>
@ -160,26 +160,8 @@
<description>spacer</description> <description>spacer</description>
<height>20</height> <height>20</height>
</control> </control>
<control type="button" id="205">
<label>[B]$ADDON[plugin.video.emby 30600][/B]</label>
<width>476</width>
<height>65</height>
<font>font13</font>
<textcolor>ffe1e1e1</textcolor>
<focusedcolor>white</focusedcolor>
<selectedcolor>ffe1e1e1</selectedcolor>
<shadowcolor>66000000</shadowcolor>
<textoffsetx>20</textoffsetx>
<aligny>center</aligny>
<align>center</align>
<texturefocus border="10" colordiffuse="ff52b54b">buttons/shadow_smallbutton.png</texturefocus>
<texturenofocus border="10" colordiffuse="ff464646">buttons/shadow_smallbutton.png</texturenofocus>
<pulseonselect>no</pulseonselect>
<onup>155</onup>
<animation effect="slide" time="0" end="17,0" condition="true">Conditional</animation>
</control>
<control type="button" id="206"> <control type="button" id="206">
<label>[B]$ADDON[plugin.video.emby 30611][/B]</label> <label>[B]$ADDON[plugin.video.jellyfin 30611][/B]</label>
<width>476</width> <width>476</width>
<height>65</height> <height>65</height>
<font>font13</font> <font>font13</font>
@ -197,7 +179,7 @@
<animation effect="slide" time="0" end="17,0" condition="true">Conditional</animation> <animation effect="slide" time="0" end="17,0" condition="true">Conditional</animation>
</control> </control>
<control type="button" id="201"> <control type="button" id="201">
<label>[B]$ADDON[plugin.video.emby 30606][/B]</label> <label>[B]$ADDON[plugin.video.jellyfin 30606][/B]</label>
<width>476</width> <width>476</width>
<height>65</height> <height>65</height>
<font>font13</font> <font>font13</font>

View file

@ -57,7 +57,7 @@
<font>font13</font> <font>font13</font>
<textcolor>white</textcolor> <textcolor>white</textcolor>
<textshadow>66000000</textshadow> <textshadow>66000000</textshadow>
<label>[B]$ADDON[plugin.video.emby 30612][/B]</label> <label>[B]$ADDON[plugin.video.jellyfin 30612][/B]</label>
</control> </control>
<control type="list" id="155"> <control type="list" id="155">
<animation effect="slide" time="0" start="0,0" end="148,0" condition="Integer.IsEqual(Container(155).NumItems,2)">Conditional</animation> <animation effect="slide" time="0" start="0,0" end="148,0" condition="Integer.IsEqual(Container(155).NumItems,2)">Conditional</animation>
@ -175,7 +175,7 @@
</focusedlayout> </focusedlayout>
</control> </control>
<control type="button" id="200"> <control type="button" id="200">
<label>[B]$ADDON[plugin.video.emby 30540][/B]</label> <label>[B]$ADDON[plugin.video.jellyfin 30540][/B]</label>
<width>874</width> <width>874</width>
<height>65</height> <height>65</height>
<font>font13</font> <font>font13</font>
@ -193,7 +193,7 @@
<animation effect="slide" time="0" end="17,0" condition="true">Conditional</animation> <animation effect="slide" time="0" end="17,0" condition="true">Conditional</animation>
</control> </control>
<control type="button" id="201"> <control type="button" id="201">
<label>[B]$ADDON[plugin.video.emby 30606][/B]</label> <label>[B]$ADDON[plugin.video.jellyfin 30606][/B]</label>
<width>874</width> <width>874</width>
<height>65</height> <height>65</height>
<font>font13</font> <font>font13</font>

View file

@ -51,8 +51,8 @@
<width>100%</width> <width>100%</width>
<height>25</height> <height>25</height>
<aspectratio align="right">keep</aspectratio> <aspectratio align="right">keep</aspectratio>
<texture diffuse="user_image.png">$INFO[Window(Home).Property(EmbyUserImage)]</texture> <texture diffuse="user_image.png">$INFO[Window(Home).Property(JellyfinUserImage)]</texture>
<visible>!String.IsEmpty(Window(Home).Property(EmbyUserImage))</visible> <visible>!String.IsEmpty(Window(Home).Property(JellyfinUserImage))</visible>
</control> </control>
<control type="image"> <control type="image">
<right>20</right> <right>20</right>
@ -60,7 +60,7 @@
<height>25</height> <height>25</height>
<aspectratio align="right">keep</aspectratio> <aspectratio align="right">keep</aspectratio>
<texture diffuse="user_image.png">userflyoutdefault.png</texture> <texture diffuse="user_image.png">userflyoutdefault.png</texture>
<visible>String.IsEmpty(Window(Home).Property(EmbyUserImage))</visible> <visible>String.IsEmpty(Window(Home).Property(JellyfinUserImage))</visible>
</control> </control>
</control> </control>
<control type="image"> <control type="image">

View file

@ -13,11 +13,11 @@ import xbmcaddon
################################################################################################# #################################################################################################
__addon__ = xbmcaddon.Addon(id='plugin.video.emby') __addon__ = xbmcaddon.Addon(id='plugin.video.jellyfin')
__base__ = xbmc.translatePath(os.path.join(__addon__.getAddonInfo('path'), 'resources', 'lib')).decode('utf-8') __base__ = xbmc.translatePath(os.path.join(__addon__.getAddonInfo('path'), 'resources', 'lib')).decode('utf-8')
__libraries__ = xbmc.translatePath(os.path.join(__addon__.getAddonInfo('path'), 'libraries')).decode('utf-8') __libraries__ = xbmc.translatePath(os.path.join(__addon__.getAddonInfo('path'), 'libraries')).decode('utf-8')
__pcache__ = xbmc.translatePath(os.path.join(__addon__.getAddonInfo('profile'), 'emby')).decode('utf-8') __pcache__ = xbmc.translatePath(os.path.join(__addon__.getAddonInfo('profile'), 'jellyfin')).decode('utf-8')
__cache__ = xbmc.translatePath('special://temp/emby').decode('utf-8') __cache__ = xbmc.translatePath('special://temp/jellyfin').decode('utf-8')
sys.path.insert(0, __libraries__) sys.path.insert(0, __libraries__)
@ -34,11 +34,10 @@ sys.path.append(__base__)
from entrypoint import Service from entrypoint import Service
from helper import settings from helper import settings
from emby import Emby
################################################################################################# #################################################################################################
LOG = logging.getLogger("EMBY.service") LOG = logging.getLogger("JELLYFIN.service")
DELAY = int(settings('startupDelay') if settings('SyncInstallRunDone.bool') else 4 or 0) DELAY = int(settings('startupDelay') if settings('SyncInstallRunDone.bool') else 4 or 0)
################################################################################################# #################################################################################################
@ -85,7 +84,7 @@ if __name__ == "__main__":
while True: while True:
if not settings('enableAddon.bool'): if not settings('enableAddon.bool'):
LOG.warn("Emby for Kodi is not enabled.") LOG.warn("Jellyfin for Kodi is not enabled.")
break break