Merge branch 'feature/auto_play_method' into develop

This commit is contained in:
faush01
2020-07-02 12:43:46 +10:00
17 changed files with 873 additions and 984 deletions

View File

@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<addon id="plugin.video.embycon"
name="EmbyCon"
version="1.9.90"
version="1.9.98"
provider-name="Team B">
<requires>
<import addon="xbmc.python" version="2.25.0"/>

View File

@@ -167,7 +167,7 @@ msgid "Show load progress"
msgstr ""
msgctxt "#30121"
msgid "On Resume"
msgid "On resume"
msgstr ""
msgctxt "#30125"
@@ -235,7 +235,7 @@ msgid "Playback"
msgstr ""
msgctxt "#30208"
msgid "Video Bitrate (Kbits)"
msgid "Max stream bitrate (Kbits)"
msgstr ""
msgctxt "#30209"
@@ -247,7 +247,7 @@ msgid "HTTP direct stream"
msgstr ""
msgctxt "#30211"
msgid "HTTP transcode"
msgid "Transcode options"
msgstr ""
msgctxt "#30212"
@@ -311,7 +311,7 @@ msgid "Episodes"
msgstr ""
msgctxt "#30236"
msgid "Force transcode h265(hevc)"
msgid "Force transcode h265 (hevc)"
msgstr ""
msgctxt "#30237"
@@ -319,7 +319,7 @@ msgid "Start from beginning"
msgstr ""
msgctxt "#30238"
msgid "Playback Options"
msgid "Playback stream options"
msgstr ""
msgctxt "#30239"
@@ -327,7 +327,7 @@ msgid "Force transcode mpeg2"
msgstr ""
msgctxt "#30240"
msgid "Force transcode msmpeg4v3(divx)"
msgid "Force transcode msmpeg4v3 (divx)"
msgstr ""
msgctxt "#30241"
@@ -1041,3 +1041,35 @@ msgstr ""
msgctxt "#30432"
msgid "Hide watched items in lists"
msgstr ""
msgctxt "#30433"
msgid "Allow direct file playback"
msgstr ""
msgctxt "#30434"
msgid "Force transcode stream bitrate (Kbits)"
msgstr ""
msgctxt "#30435"
msgid "Connection speed test"
msgstr ""
msgctxt "#30436"
msgid "Speed test data size (MB)"
msgstr ""
msgctxt "#30437"
msgid "Playback options"
msgstr ""
msgctxt "#30438"
msgid "Play cinema intros"
msgstr ""
msgctxt "#30439"
msgid "Show play next episode at time left"
msgstr ""
msgctxt "#30440"
msgid "Play next"
msgstr ""

View File

@@ -1,929 +0,0 @@
msgid ""
msgstr ""
"Project-Id-Version: EmbyCon\n"
"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n"
"PO-Revision-Date: 2019-10-29 19:09+0100\n"
"Last-Translator: EffeF\n"
"Language-Team: \n"
"Language: it\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: Poedit 2.2.3\n"
msgctxt "#30000"
msgid "Host"
msgstr "Host"
msgctxt "#30001"
msgid "Port"
msgstr "Porta"
msgctxt "#30003"
msgid "Verify HTTPS certificate"
msgstr "Verifica del certificato HTTPS"
msgctxt "#30005"
msgid "Username"
msgstr "Username"
msgctxt "#30006"
msgid "Password"
msgstr "Password"
msgctxt "#30007"
msgid "Samba username"
msgstr "Username Samba"
msgctxt "#30008"
msgid "Samba password"
msgstr "Password Samba"
msgctxt "#30010"
msgid "Number of performance profiles to capture"
msgstr "Numero di profili prestazionali da acquisire"
msgctxt "#30011"
msgid "[Detect local server]"
msgstr "[Rileva server locale]"
msgctxt "#30012"
msgid "[Change user]"
msgstr "[Cambia utente]"
msgctxt "#30014"
msgid "Emby"
msgstr "Emby"
msgctxt "#30015"
msgid "Log timing data"
msgstr "Registra i dati di temporizzazione"
msgctxt "#30016"
msgid "Device display name"
msgstr "Nome del dispositivo visualizzato"
msgctxt "#30017"
msgid "Show connected clients"
msgstr "Mostra i client connessi"
msgctxt "#30018"
msgid "Number of items to show in filtered lists"
msgstr "Numero di elementi da mostrare negli elenchi filtrati"
msgctxt "#30019"
msgid "Filtered episode name format"
msgstr "Formato del nome dell'episodio filtrato"
msgctxt "#30020"
msgid "Flatten single season"
msgstr "Spiana stagione singola"
msgctxt "#30021"
msgid "Show all episodes item"
msgstr "Mostra tutti gli episodi"
msgctxt "#30022"
msgid "Advanced"
msgstr "Avanzate"
msgctxt "#30023"
msgid "Hide unwatched episode details"
msgstr "Nascondi dettagli episodio non visto"
msgctxt "#30024"
msgid "Username:"
msgstr "Username:"
msgctxt "#30025"
msgid "Password:"
msgstr "Password:"
msgctxt "#30026"
msgid "Widget item select action"
msgstr "Azione selezione elemento widget"
msgctxt "#30044"
msgid "Incorrect Username/Password"
msgstr "Username/Password Errata"
msgctxt "#30045"
msgid "Username not found"
msgstr "Username non trovato"
msgctxt "#30052"
msgid "Deleting"
msgstr "Eliminazione"
msgctxt "#30053"
msgid "Waiting for server to delete"
msgstr "Attese del server per l'eliminazione"
msgctxt "#30063"
msgid "N/A"
msgstr "N/D"
msgctxt "#30091"
msgid "Confirm delete?"
msgstr "Conferma eliminazione?"
msgctxt "#30092"
msgid "Warning: This action will delete the media files from the server."
msgstr "Avviso: questa azione eliminerà i file multimediali dal server."
msgctxt "#30110"
msgid "Interface"
msgstr "Interfaccia"
msgctxt "#30111"
msgid "Services"
msgstr "Servizi"
msgctxt "#30112"
msgid "Loading Content"
msgstr "Caricamento Contenuto"
msgctxt "#30113"
msgid "Retrieving Data"
msgstr "Recupero Dati"
msgctxt "#30114"
msgid "Jump back seconds"
msgstr "Torna indietro di secondi"
msgctxt "#30116"
msgid "Add unwatched counts to names"
msgstr "Aggiungi conteggio non visti ai nomi"
msgctxt "#30118"
msgid "Add resume percent to names"
msgstr "Aggiungi percentuale riprendi ai nomi"
msgctxt "#30120"
msgid "Show load progress"
msgstr "Mostra avanzamento del caricamento"
msgctxt "#30121"
msgid "On Resume"
msgstr "Alla Ripresa"
msgctxt "#30125"
msgid "Done"
msgstr "Fatto"
msgctxt "#30126"
msgid "Processing Item : "
msgstr "Elaborazione Elemento : "
msgctxt "#30135"
msgid "Error"
msgstr "Errore"
msgctxt "#30139"
msgid "No Media Type Set"
msgstr "Nessun Tipo Supporto Impostato"
msgctxt "#30163"
msgid "Add (cc) if subtitle is available"
msgstr "Aggiungi (cc) se sono disponibili i sottotitoli"
msgctxt "#30166"
msgid "Select Server"
msgstr "Seleziona Server"
msgctxt "#30167"
msgid "Selected Server Address"
msgstr "Indirizzo Server Selezionato"
msgctxt "#30169"
msgid "Address: "
msgstr "Indirizzo: "
msgctxt "#30180"
msgid "Select User"
msgstr "Seleziona Utente"
msgctxt "#30181"
msgid "Include plot"
msgstr "Includi trama"
msgctxt "#30182"
msgid "Include media stream info"
msgstr "Includi informazioni sul flusso multimediale"
msgctxt "#30183"
msgid "Include people"
msgstr "Includi persone"
msgctxt "#30200"
msgid "URL error: %s"
msgstr "Errore URL: %s"
msgctxt "#30201"
msgid "Unable to connect to server"
msgstr "Impossibile stabilire una connessione al server"
msgctxt "#30206"
msgid "Playback type"
msgstr "Tipo di riproduzione"
msgctxt "#30207"
msgid "Playback"
msgstr "Riproduzione"
msgctxt "#30208"
msgid "Transcode Bitrate (Kbits)"
msgstr "Transcode Bitrate (Kbits)"
msgctxt "#30209"
msgid "File direct path"
msgstr "Percorso diretto del file"
msgctxt "#30210"
msgid "HTTP direct stream"
msgstr "Flusso diretto HTTP"
msgctxt "#30211"
msgid "HTTP transcode"
msgstr "Transcodifica HTTP"
msgctxt "#30212"
msgid "Transcode max width"
msgstr "Transcodifica larghezza massima"
msgctxt "#30213"
msgid "Transcode force 8 bit"
msgstr "Forza transcodifica 8 bit"
msgctxt "#30214"
msgid "Events"
msgstr "Eventi"
msgctxt "#30215"
msgid "On playback stop (100% = disabled)"
msgstr "All'arresto della riproduzione (100% = disabilitato)"
msgctxt "#30216"
msgid "Item Details"
msgstr "Dettagli Elemento"
msgctxt "#30217"
msgid "Prompt to delete episode after %"
msgstr "Richiedi l'eliminazione dell'episodio dopo %"
msgctxt "#30218"
msgid "Play next episode after %"
msgstr "Riproduci il prossimo episodio dopo %"
msgctxt "#30219"
msgid " - Prompt before play"
msgstr " - Chiedi prima di riprodurre"
msgctxt "#30220"
msgid "Prompt to delete movie after %"
msgstr "Richiedi l'eliminazione del film dopo %"
msgctxt "#30222"
msgid "Item Layout"
msgstr "Layout Elemento"
msgctxt "#30223"
msgid "Page Size and Filtering"
msgstr "Dimensioni Pagina e Filtro"
msgctxt "#30224"
msgid "Interaction"
msgstr "Interazione"
msgctxt "#30229"
msgid "TV Shows"
msgstr "Programmi TV"
msgctxt "#30231"
msgid "Movies"
msgstr "Film"
msgctxt "#30235"
msgid "Episodes"
msgstr "Episodi"
msgctxt "#30236"
msgid "Force transcode h265(hevc)"
msgstr "Forza transcodifica h265(hevc)"
msgctxt "#30237"
msgid "Start from beginning"
msgstr "Riprendi dall'inizio"
msgctxt "#30238"
msgid "Playback Options"
msgstr "Opzioni Riproduzione"
msgctxt "#30239"
msgid "Force transcode mpeg2"
msgstr "Forza transcodifica mpeg2"
msgctxt "#30240"
msgid "Force transcode msmpeg4v3(divx)"
msgstr "Forza transcodifica msmpeg4v3(divx)"
msgctxt "#30241"
msgid "Force transcode mpeg4"
msgstr "Forza transcodifica mpeg4"
msgctxt "#30246"
msgid "Search"
msgstr "Cerca"
msgctxt "#30247"
msgid "Custom Widget Content"
msgstr "Contenuto Widget Personalizzato"
msgctxt "#30250"
msgid "Unknown"
msgstr "Sconosciuto"
msgctxt "#30251"
msgid "Movies (Genres)"
msgstr "Film (Generi)"
msgctxt "#30252"
msgid "Movies (A-Z)"
msgstr "Film (A-Z)"
msgctxt "#30254"
msgid "Show add-on settings"
msgstr "Mostra impostazioni add-on"
msgctxt "#30255"
msgid "TV Show (A-Z)"
msgstr "Programmi TV (A-Z)"
msgctxt "#30256"
msgid "Movies"
msgstr "Film"
msgctxt "#30257"
msgid "Movies - Recently Added"
msgstr "Film - Aggiunti Recentemente"
msgctxt "#30258"
msgid "Movies - In Progress"
msgstr "Film - In Corso"
msgctxt "#30259"
msgid "Movies - Favorites"
msgstr "Film - Preferiti"
msgctxt "#30260"
msgid "BoxSets"
msgstr "BoxSets"
msgctxt "#30261"
msgid "TV Shows"
msgstr "Programmi TV"
msgctxt "#30262"
msgid "TV Shows - Favorites"
msgstr "Programmi TV - Preferiti"
msgctxt "#30263"
msgid "Episodes - Recently Added"
msgstr "Episodi - Aggiunti Recentemente"
msgctxt "#30264"
msgid "Episodes - In Progress"
msgstr "Episodi - In Corso"
msgctxt "#30265"
msgid "Episodes - Next Up"
msgstr "Episodi - Successivi"
msgctxt "#30266"
msgid "Movie (Pages)"
msgstr "Film (Pagine)"
msgctxt "#30267"
msgid " - In Progress"
msgstr " - In Corso"
msgctxt "#30268"
msgid " - Recently Added"
msgstr " - Aggiunti Recentemente"
msgctxt "#30269"
msgid "Movies - Random"
msgstr "Film - Casuali"
msgctxt "#30270"
msgid "Mark Watched"
msgstr "Segna come Visto"
msgctxt "#30271"
msgid "Mark Unwatched"
msgstr "Segna come Non Visto"
msgctxt "#30272"
msgid "Set Favourite"
msgstr "Imposta Preferito"
msgctxt "#30273"
msgid "Unset Favourite"
msgstr "Elimina Preferito"
msgctxt "#30274"
msgid "Delete"
msgstr "Elimina"
msgctxt "#30275"
msgid "Force Transcode"
msgstr "Forza Transcodifica"
msgctxt "#30276"
msgid "Extra Resume Prompt Detected"
msgstr "Rilevata Richiesta Ripresa Extra"
msgctxt "#30277"
msgid "EmbyCon needs to prompt for resume on partily played items, Kodi can also prompt, this can cause a double prompt. Do you want to remove the double prompt?"
msgstr "EmbyCon deve richiedere di riprendere su elementi parzialmente riprodotti, Kodi anche, ciò può causare una doppia richiesta. Vuoi rimuovere la doppia richiesta?"
msgctxt "#30278"
msgid " - Next Up"
msgstr " - Successivi"
msgctxt "#30279"
msgid "TV Shows - Unwatched"
msgstr "Programmi TV - Non Visti"
msgctxt "#30280"
msgid "Missing Title"
msgstr "Titolo Mancante"
msgctxt "#30281"
msgid "Refresh Cached Images"
msgstr "Aggiorna Immagini nella Cache"
msgctxt "#30282"
msgid "No Emby servers detected on your local network."
msgstr "Nessun server Emby rilevato sulla rete locale."
msgctxt "#30283"
msgid "Play Next Episode"
msgstr "Avvia Episodio Successivo"
msgctxt "#30284"
msgid "Do you want to play the next episode?"
msgstr "Vuoi riprodurre il prossimo episodio?"
msgctxt "#30285"
msgid " - Unwatched"
msgstr " - Non Visti"
msgctxt "#30286"
msgid "Movies - Unwatched"
msgstr "Fim - Non Visti"
msgctxt "#30287"
msgid "TV Shows - Latest"
msgstr "Programmi TV - Ultimi"
msgctxt "#30288"
msgid " - Latest"
msgstr " - Ultimi"
msgctxt "#30289"
msgid "TV Show (Genres)"
msgstr "Programmi TV (Generi)"
msgctxt "#30290"
msgid "All"
msgstr "Tutti"
msgctxt "#30291"
msgid "Select Audio Stream"
msgstr "Seleziona Flusso Audio"
msgctxt "#30292"
msgid "Select Subtitle Stream"
msgstr "Seleziona Flusso Sottotitoli"
msgctxt "#30293"
msgid "Cache images"
msgstr "Immagini nella cache"
msgctxt "#30294"
msgid "Notice"
msgstr "Avviso"
msgctxt "#30295"
msgid "To use this feature you need HTTP control enabled"
msgstr "Per utilizzare questa funzione è necessario il controllo HTTP abilitato"
msgctxt "#30296"
msgid "Delete"
msgstr "Elimina"
msgctxt "#30297"
msgid "Delete unused images?"
msgstr "Elimina immagini inutilizzate?"
msgctxt "#30298"
msgid "Deleting Kodi Images"
msgstr "Eliminazione Immagini Kodi"
msgctxt "#30299"
msgid "Cache Images"
msgstr "Cache delle Immagini"
msgctxt "#30300"
msgid "Cache all Emby images as local Kodi images?"
msgstr "Inserire nella cache tutte le immagini Emby come immagini Kodi locali?"
msgctxt "#30301"
msgid "Caching Images"
msgstr "Inserimento immagini nella cache"
msgctxt "#30302"
msgid "Existing images : "
msgstr "Immagini esistenti : "
msgctxt "#30303"
msgid "Missing Emby images : "
msgstr "Immagini Emby mancanti : "
msgctxt "#30304"
msgid "Cached Emby images : "
msgstr "Immagini cache Emby : "
msgctxt "#30305"
msgid "Not Found: %s"
msgstr "Non Trovato: %s"
msgctxt "#30306"
msgid "Playback starting: %s"
msgstr "Inizio riproduzione: %s"
msgctxt "#30307"
msgid "Play Trailer"
msgstr "Riproduci Trailer"
msgctxt "#30308"
msgid "Select Trailer"
msgstr "Seleziona Trailer"
msgctxt "#30309"
msgid "Select Media Source"
msgstr "Seleziona Sorgente Multimediale"
msgctxt "#30310"
msgid "Enable Emby remote control"
msgstr "Abilita controllo remoto Emby"
msgctxt "#30311"
msgid "Library - "
msgstr "Libreria - "
msgctxt "#30312"
msgid "All - "
msgstr "Tutti - "
msgctxt "#30313"
msgid "Menu"
msgstr "Menu"
msgctxt "#30314"
msgid "Play"
msgstr "Riproduci"
msgctxt "#30315"
msgid "Suppress notifications for connection errors"
msgstr "Elimina notifiche per errori connessione"
msgctxt "#30316"
msgid "Connection Error"
msgstr "Errore Connessione"
msgctxt "#30317"
msgid "Play All"
msgstr "Riproduci Tutto"
msgctxt "#30318"
msgid "Music - Albums"
msgstr "Musica - Album"
msgctxt "#30320"
msgid " - Albums"
msgstr " - Album"
msgctxt "#30322"
msgid "Auto resume"
msgstr "Ripresa automatica"
msgctxt "#30324"
msgid "Movies - Recommendations"
msgstr "Film - Raccomandazioni"
msgctxt "#30325"
msgid " - Genres"
msgstr " - Generi"
msgctxt "#30327"
msgid "Go To Season"
msgstr "Vai Alla Stagione"
msgctxt "#30328"
msgid "Show empty folders (shows, seasons, collections)"
msgstr "Mostra cartelle vuote (programmi, stagioni, collezioni)"
msgctxt "#30329"
msgid "Screensaver"
msgstr "Salvaschermo"
msgctxt "#30330"
msgid "Show change user dialog"
msgstr "Mostra la finestra di dialogo cambia utente"
msgctxt "#30331"
msgid "Movies per page"
msgstr "Film per pagina"
msgctxt "#30332"
msgid "Stop media playback on screensaver activation"
msgstr "Arresta riproduzione all'attivazione dello screensaver"
msgctxt "#30333"
msgid "Cache artwork in the background"
msgstr "Salva immagini nella cache in background"
msgctxt "#30334"
msgid "Use EmbyCon context menu"
msgstr "Usa il menu contestuale di EmbyCon"
msgctxt "#30337"
msgid "Song"
msgstr "Canzone"
msgctxt "#30338"
msgid "Album"
msgstr "Album"
msgctxt "#30339"
msgid "Person"
msgstr "Persona"
msgctxt "#30340"
msgid "Group movies into collections"
msgstr "Raggruppa i film in collezioni"
msgctxt "#30341"
msgid "Background image update interval (0 = disabled)"
msgstr "Intervallo di aggiornamento dell'immagine di sfondo (0 = disabilitato)"
msgctxt "#30342"
msgid "New content check interval (0 = disabled)"
msgstr "Intervallo di controllo nuovo contenuto (0 = disabilitato)"
msgctxt "#30343"
msgid "Changes Require Kodi Restart"
msgstr "Modifiche Richiedono Riavvio Kodi"
msgctxt "#30344"
msgid "Number of images removed from cache : %s"
msgstr "Numero di immagini rimosse dalla cache : %s"
msgctxt "#30345"
msgid "Cache server requests"
msgstr "Richieste server cache"
msgctxt "#30346"
msgid "Deleteing Cached Images"
msgstr "Eliminazione Immagini dalla Cache"
msgctxt "#30347"
msgid "Getting Existing Images"
msgstr "Ottengo Immagini Esistenti"
msgctxt "#30348"
msgid "Add user ratings"
msgstr "Aggiungi valutazioni utente"
msgctxt "#30349"
msgid " - Recently Played"
msgstr " - Recentemente Riprodotto"
msgctxt "#30350"
msgid "Music - Recently Added"
msgstr "Musica - Recentemente Aggiunta"
msgctxt "#30351"
msgid "Music - Recently Played"
msgstr "Musica - Recentemente Riprodotta"
msgctxt "#30352"
msgid "Music - Frequently Played"
msgstr "Musica - Riprodotta Spesso"
msgctxt "#30319"
msgid "Music - All Album Artists"
msgstr "Musica - Tutti gli Artisti Album"
msgctxt "#30321"
msgid " - Album Artists"
msgstr " - Artisti Album"
msgctxt "#30353"
msgid " - Frequently Played"
msgstr " - Riprodotta Spesso"
msgctxt "#30354"
msgid "Go To Series"
msgstr "Vai Alla Serie"
msgctxt "#30355"
msgid "Kodi Settings->Services->Allow remote control via HTTP"
msgstr "Impostazioni Kodi->Servizi->Consenti controllo remoto via HTTP"
msgctxt "#30356"
msgid "Loading existing image list"
msgstr "Caricamento elenco immagini esistenti"
msgctxt "#30357"
msgid "Processing existing image list"
msgstr "Elaborazione elenco immagini esistenti"
msgctxt "#30358"
msgid "Retreiving remote image list"
msgstr "Recupero elenco immagini remote"
msgctxt "#30359"
msgid "Building full image list"
msgstr "Creazione elenco completo immagini"
msgctxt "#30360"
msgid " - Channels"
msgstr " - Canali"
msgctxt "#30361"
msgid " - Programs"
msgstr " - Programmi"
msgctxt "#30362"
msgid " - Recordings"
msgstr " - Registrazioni"
msgctxt "#30363"
msgid "Save Password?"
msgstr "Salvare Password?"
msgctxt "#30364"
msgid "Do you want to save the password?"
msgstr "Vuoi salvare la password?"
msgctxt "#30365"
msgid "Manual Login"
msgstr "Login Manuale"
msgctxt "#30366"
msgid "Manually enter user details"
msgstr "Inserisci manualmente dettagli utente"
msgctxt "#30367"
msgid "Allow fast user switching password saving"
msgstr "Consenti salvataggio password per un cambio utente rapido"
msgctxt "#30368"
msgid "Clear Password?"
msgstr "Cancellare Password?"
msgctxt "#30369"
msgid "Do you want to clear your saved password?"
msgstr "Vuoi cancellare la password salvata?"
msgctxt "#30370"
msgid "Do you want to manually enter a server url?"
msgstr "Vuoi inserire manualmente un URL del server?"
msgctxt "#30371"
msgid "Could not connect to the URL you entered, do you want to try again?"
msgstr "Impossibile connettersi all'URL inserito, vuoi riprovare?"
msgctxt "#30372"
msgid "Server URL"
msgstr "URL del server"
msgctxt "#30373"
msgid "Scanning for local servers"
msgstr "Scansione server locali"
msgctxt "#30374"
msgid "Sending request"
msgstr "Invio richiesta"
msgctxt "#30375"
msgid "Receiving data packet: %s"
msgstr "Ricezione pacchetto dati: %s"
msgctxt "#30376"
msgid "Checking server url"
msgstr "Verifica URL del server"
msgctxt "#30377"
msgid "Sending request"
msgstr "Invio richiesta"
msgctxt "#30378"
msgid "Persist user details"
msgstr "Persistenza dettagli utente"
msgctxt "#30379"
msgid "External subtitle prompt"
msgstr "Richiesta sottotitoli esterni"
msgctxt "#30380"
msgid "Never"
msgstr "Mai"
msgctxt "#30381"
msgid "More than one"
msgstr "Più di una"
msgctxt "#30382"
msgid "Always"
msgstr "Sempre"
msgctxt "#30383"
msgid "System - "
msgstr "Sistema - "
msgctxt "#30384"
msgid "Random movies interval minutes (0 = disabled)"
msgstr "Intervallo minuti film casuali (0 = disabilitato)"
msgctxt "#30385"
msgid "Existing images before delete : "
msgstr "Immagini esistenti prima dell'eliminazione : "
msgctxt "#30386"
msgid "Unused Emby images : "
msgstr "Immagini Emby inutilizzate : "
msgctxt "#30387"
msgid "Unused images removed : "
msgstr "Immagini inutilizzate rimosse : "
msgctxt "#30388"
msgid "Server details"
msgstr "Dettagli server"
msgctxt "#30389"
msgid "User details"
msgstr "Dettagli utente"
msgctxt "#30390"
msgid "Protocol"
msgstr "Protocollo"
msgctxt "#30391"
msgid "HTTP"
msgstr "HTTP"
msgctxt "#30392"
msgid "HTTPS"
msgstr "HTTPS"
msgctxt "#30393"
msgid "Clear Cache Result"
msgstr "Cancella Cache Risultati"
msgctxt "#30394"
msgid "%s cache files deleted"
msgstr "%s file eliminati dalla cache"
msgctxt "#30395"
msgid "Clear cached server data"
msgstr "Cancella dati del server dalla cache"
msgctxt "#30397"
msgid " - Pages"
msgstr " - Pagine"
msgctxt "#30398"
msgid "Refresh Emby Metadata"
msgstr "Aggiorna Metadati Emby"
msgctxt "#30399"
msgid "Hide"
msgstr "Nascondi"
msgctxt "#30400"
msgid "Cache images interval minutes (0 = disabled)"
msgstr "Intervallo minuti immagini cache (0 = disabilitato)"
msgctxt "#30401"
msgid "Info"
msgstr "Info"
msgctxt "#30402"
msgid "Add to Kodi Playlist"
msgstr "Aggiungi alla playlist Kodi"

View File

@@ -0,0 +1,58 @@
import xbmc
import xbmcgui
from .simple_logging import SimpleLogging
log = SimpleLogging(__name__)
class BitrateDialog(xbmcgui.WindowXMLDialog):
slider_control = None
bitrate_label = None
initial_bitrate_value = 0
selected_transcode_value = 0
def __init__(self, *args, **kwargs):
log.debug("BitrateDialog: __init__")
xbmcgui.WindowXML.__init__(self, *args, **kwargs)
def onInit(self):
log.debug("ActionMenu: onInit")
self.action_exitkeys_id = [10, 13]
self.slider_control = self.getControl(3000)
self.slider_control.setInt(self.initial_bitrate_value, 400, 100, 15000)
self.bitrate_label = self.getControl(3030)
bitrate_label_string = str(self.slider_control.getInt()) + " Kbs"
self.bitrate_label.setLabel(bitrate_label_string)
def onFocus(self, control_id):
pass
def doAction(self, action_id):
pass
def onMessage(self, message):
log.debug("ActionMenu: onMessage: {0}", message)
def onAction(self, action):
# log.debug("onAction: onAction: {0} {1}", action.getId(), self.slider_control.getInt())
bitrate_label_string = str(self.slider_control.getInt()) + " Kbs"
self.bitrate_label.setLabel(bitrate_label_string)
if action.getId() == 10: # ACTION_PREVIOUS_MENU
self.close()
elif action.getId() == 92: # ACTION_NAV_BACK
self.close()
elif action.getId() == 7: # ENTER
self.selected_transcode_value = self.slider_control.getInt()
self.close()
def onClick(self, control_id):
if control_id == 3000:
log.debug("ActionMenu: Selected Item: {0}", control_id)
#self.close()

View File

@@ -78,7 +78,8 @@ def get_details_string():
"PremiereDate",
"ProductionYear",
"AirTime",
"Status"
"Status",
"Tags"
]
if include_media:
@@ -152,7 +153,194 @@ class DownloadUtils:
self.download_url(url, post_body=data, method="POST")
log.debug("Posted Capabilities: {0}", data)
def get_item_playback_info(self, item_id):
def get_item_playback_info(self, item_id, force_transcode):
addon_settings = xbmcaddon.Addon()
# ["hevc", "h265", "h264", "mpeg4", "msmpeg4v3", "mpeg2video", "vc1"]
filtered_codecs = []
if addon_settings.getSetting("force_transcode_h265") == "true":
filtered_codecs.append("hevc")
filtered_codecs.append("h265")
if addon_settings.getSetting("force_transcode_mpeg2") == "true":
filtered_codecs.append("mpeg2video")
if addon_settings.getSetting("force_transcode_msmpeg4v3") == "true":
filtered_codecs.append("msmpeg4v3")
if addon_settings.getSetting("force_transcode_mpeg4") == "true":
filtered_codecs.append("mpeg4")
playback_bitrate = addon_settings.getSetting("max_stream_bitrate")
force_playback_bitrate = addon_settings.getSetting("force_max_stream_bitrate")
if force_transcode:
playback_bitrate = force_playback_bitrate
audio_codec = addon_settings.getSetting("audio_codec")
audio_playback_bitrate = addon_settings.getSetting("audio_playback_bitrate")
audio_max_channels = addon_settings.getSetting("audio_max_channels")
audio_bitrate = int(audio_playback_bitrate) * 1000
bitrate = int(playback_bitrate) * 1000
profile = {
"Name": "Kodi",
"MaxStaticBitrate": bitrate,
"MaxStreamingBitrate": bitrate,
"MusicStreamingTranscodingBitrate": audio_bitrate,
"TimelineOffsetSeconds": 5,
"TranscodingProfiles": [
{
"Type": "Audio"
},
{
"Container": "ts",
"Protocol": "hls",
"Type": "Video",
"AudioCodec": audio_codec,
"VideoCodec": "h264",
"MaxAudioChannels": audio_max_channels
},
{
"Container": "jpeg",
"Type": "Photo"
}
],
"DirectPlayProfiles": [
{
"Type": "Video"
},
{
"Type": "Audio"
},
{
"Type": "Photo"
}
],
"ResponseProfiles": [],
"ContainerProfiles": [],
"CodecProfiles": [],
"SubtitleProfiles": [
{
"Format": "srt",
"Method": "External"
},
{
"Format": "srt",
"Method": "Embed"
},
{
"Format": "ass",
"Method": "External"
},
{
"Format": "ass",
"Method": "Embed"
},
{
"Format": "sub",
"Method": "Embed"
},
{
"Format": "sub",
"Method": "External"
},
{
"Format": "ssa",
"Method": "Embed"
},
{
"Format": "ssa",
"Method": "External"
},
{
"Format": "smi",
"Method": "Embed"
},
{
"Format": "smi",
"Method": "External"
},
{
"Format": "pgssub",
"Method": "Embed"
},
{
"Format": "pgssub",
"Method": "External"
},
{
"Format": "dvdsub",
"Method": "Embed"
},
{
"Format": "dvdsub",
"Method": "External"
},
{
"Format": "pgs",
"Method": "Embed"
},
{
"Format": "pgs",
"Method": "External"
}
]
}
if len(filtered_codecs) > 0:
profile['DirectPlayProfiles'][0]['VideoCodec'] = "-%s" % ",".join(filtered_codecs)
if force_transcode:
profile['DirectPlayProfiles'] = []
if addon_settings.getSetting("playback_video_force_8") == "true":
profile['CodecProfiles'].append(
{
"Type": "Video",
"Codec": "h264",
"Conditions": [
{
"Condition": "LessThanEqual",
"Property": "VideoBitDepth",
"Value": "8",
"IsRequired": False
}
]
}
)
profile['CodecProfiles'].append(
{
"Type": "Video",
"Codec": "h265,hevc",
"Conditions": [
{
"Condition": "EqualsAny",
"Property": "VideoProfile",
"Value": "main"
}
]
}
)
playback_info = {
'UserId': self.get_user_id(),
'DeviceProfile': profile,
'AutoOpenLiveStream': True
}
if force_transcode:
url = "{server}/emby/Items/%s/PlaybackInfo?MaxStreamingBitrate=%s&EnableDirectPlay=false&EnableDirectStream=false" % (item_id, bitrate)
else:
url = "{server}/emby/Items/%s/PlaybackInfo?MaxStreamingBitrate=%s" % (item_id, bitrate)
log.debug("PlaybackInfo : {0}", url)
log.debug("PlaybackInfo : {0}", profile)
play_info_result = self.download_url(url, post_body=playback_info, method="POST")
play_info_result = json.loads(play_info_result)
log.debug("PlaybackInfo : {0}", play_info_result)
return play_info_result
def get_item_playback_info_old(self, item_id):
profile = {
"Name": "Kodi",

View File

@@ -19,12 +19,13 @@ from .utils import get_art, send_event_notification, convert_size
from .kodi_utils import HomeWindow
from .clientinfo import ClientInformation
from .datamanager import DataManager, clear_cached_server_data
from .server_detect import check_server
from .server_detect import check_server, check_connection_speed
from .simple_logging import SimpleLogging
from .menu_functions import display_main_menu, display_menu, show_movie_alpha_list, show_tvshow_alpha_list, show_genre_list, show_search, show_movie_pages
from .translation import string_load
from .server_sessions import show_server_sessions
from .action_menu import ActionMenu
from .bitrate_dialog import BitrateDialog
from .safe_delete_dialog import SafeDeleteDialog
from .widgets import get_widget_content, get_widget_content_cast, check_for_new_content
from . import trakttokodi
@@ -90,6 +91,8 @@ def main_entry_point():
check_server(force=True, notify=True)
elif mode == "DETECT_SERVER_USER":
check_server(force=True, change_user=True, notify=False)
elif mode == "DETECT_CONNECTION_SPEED":
check_connection_speed()
elif mode == "playTrailer":
item_id = params["id"]
play_item_trailer(item_id)
@@ -538,7 +541,20 @@ def show_menu(params):
elif selected_action == "transcode":
params['force_transcode'] = 'true'
play_action(params)
force_max_stream_bitrate = settings.getSetting("force_max_stream_bitrate")
initial_bitrate_value = int(force_max_stream_bitrate)
bitrate_dialog = BitrateDialog("BitrateDialog.xml", PLUGINPATH, "default", "720p")
bitrate_dialog.initial_bitrate_value = initial_bitrate_value
bitrate_dialog.doModal()
selected_transcode_value = bitrate_dialog.selected_transcode_value
del bitrate_dialog
log.debug("selected_transcode_value: {0}", selected_transcode_value)
if selected_transcode_value > 0:
settings.setSetting("force_max_stream_bitrate", str(selected_transcode_value))
play_action(params)
elif selected_action == "add_to_playlist":
params["action"] = "add_to_playlist"

View File

@@ -63,6 +63,7 @@ class ItemDetails:
tagline = ""
status = None
media_streams = None
tags = None
resume_time = 0
duration = 0
@@ -155,6 +156,11 @@ def extract_item_info(item, gui_options):
if item["Taglines"] is not None and len(item["Taglines"]) > 0:
item_details.tagline = item["Taglines"][0]
item_details.tags = []
if item["TagItems"] is not None and len(item["TagItems"]) > 0:
for tag_info in item["TagItems"]:
item_details.tags.append(tag_info["Name"])
# set the item name
# override with name format string from request
name_format = gui_options["name_format"]
@@ -554,6 +560,7 @@ def add_gui_item(url, item_details, display_options, folder=True, default_sort=F
info_labels["dateadded"] = item_details.date_added
info_labels["country"] = item_details.production_location
info_labels["mpaa"] = item_details.mpaa
info_labels["tag"] = item_details.tags
if display_options["addUserRatings"]:
info_labels["userrating"] = item_details.critic_rating

View File

@@ -583,6 +583,7 @@ def display_addon_menu(params):
add_menu_directory_item(string_load(30017), "plugin://plugin.video.embycon/?mode=SHOW_SERVER_SESSIONS")
add_menu_directory_item(string_load(30012), "plugin://plugin.video.embycon/?mode=CHANGE_USER")
add_menu_directory_item(string_load(30011), "plugin://plugin.video.embycon/?mode=DETECT_SERVER_USER")
add_menu_directory_item(string_load(30435), "plugin://plugin.video.embycon/?mode=DETECT_CONNECTION_SPEED")
add_menu_directory_item(string_load(30254), "plugin://plugin.video.embycon/?mode=SHOW_SETTINGS")
add_menu_directory_item(string_load(30395), "plugin://plugin.video.embycon/?mode=CLEAR_CACHE")
add_menu_directory_item(string_load(30293), "plugin://plugin.video.embycon/?mode=CACHE_ARTWORK")

View File

@@ -27,7 +27,7 @@ log = SimpleLogging(__name__)
download_utils = DownloadUtils()
def play_all_files(items, monitor):
def play_all_files(items, monitor, play_items=True):
log.debug("playAllFiles called with items: {0}", items)
server = download_utils.get_server()
@@ -39,7 +39,7 @@ def play_all_files(items, monitor):
item_id = item.get("Id")
# get playback info
playback_info = download_utils.get_item_playback_info(item_id)
playback_info = download_utils.get_item_playback_info(item_id, False)
if playback_info is None:
log.debug("playback_info was None, could not get MediaSources so can not play!")
return
@@ -58,14 +58,10 @@ def play_all_files(items, monitor):
selected_media_source = sources[0]
source_id = selected_media_source.get("Id")
playurl, playback_type, listitem_props = PlayUtils().get_play_url(item_id,
selected_media_source,
False,
play_session_id)
playurl, playback_type, listitem_props = PlayUtils().get_play_url(selected_media_source)
log.info("Play URL: {0} PlaybackType: {1} ListItem Properties: {2}", playurl, playback_type, listitem_props)
log.debug("Play URL: {0} PlaybackType: {1} ListItem Properties: {2}", playurl, playback_type, listitem_props)
if playurl in None:
if playurl is None:
return
playback_type_string = "DirectPlay"
@@ -99,7 +95,11 @@ def play_all_files(items, monitor):
playlist.add(playurl, list_item)
xbmc.Player().play(playlist)
if play_items:
xbmc.Player().play(playlist)
return None
else:
return playlist
def play_list_of_items(id_list, monitor):
@@ -136,7 +136,7 @@ def add_to_playlist(play_info, monitor):
return
# get playback info
playback_info = download_utils.get_item_playback_info(item_id)
playback_info = download_utils.get_item_playback_info(item_id, False)
if playback_info is None:
log.debug("playback_info was None, could not get MediaSources so can not play!")
return
@@ -157,12 +157,11 @@ def add_to_playlist(play_info, monitor):
selected_media_source = sources[0]
source_id = selected_media_source.get("Id")
playurl, playback_type, listitem_props = PlayUtils().get_play_url(item_id,
selected_media_source,
False,
play_session_id)
playurl, playback_type, listitem_props = PlayUtils().get_play_url(selected_media_source)
log.info("Play URL: {0} PlaybackType: {1} ListItem Properties: {2}", playurl, playback_type, listitem_props)
log.debug("Play URL: {0} PlaybackType: {1} ListItem Properties: {2}", playurl, playback_type, listitem_props)
if playurl is None:
return
playback_type_string = "DirectPlay"
if playback_type == "2":
@@ -196,6 +195,24 @@ def add_to_playlist(play_info, monitor):
playlist.add(playurl, list_item)
def get_playback_intros(item_id):
log.debug("get_playback_intros")
data_manager = DataManager()
url = "{server}/emby/Users/{userid}/Items/%s/Intros" % item_id
intro_items = data_manager.get_content(url)
if intro_items is None:
log.debug("get_playback_intros failed!")
return
into_list = []
intro_items = intro_items["Items"]
for into in intro_items:
into_list.append(into)
return into_list
@timer
def play_file(play_info, monitor):
item_id = play_info.get("item_id")
@@ -226,6 +243,7 @@ def play_file(play_info, monitor):
addon_path = settings.getAddonInfo('path')
force_auto_resume = settings.getSetting('forceAutoResume') == 'true'
jump_back_amount = int(settings.getSetting("jump_back_amount"))
play_cinema_intros = settings.getSetting('play_cinema_intros') == 'true'
server = download_utils.get_server()
@@ -273,7 +291,7 @@ def play_file(play_info, monitor):
return
# get playback info from the server using the device profile
playback_info = download_utils.get_item_playback_info(item_id)
playback_info = download_utils.get_item_playback_info(item_id, force_transcode)
if playback_info is None:
log.debug("playback_info was None, could not get MediaSources so can not play!")
return
@@ -371,12 +389,8 @@ def play_file(play_info, monitor):
return
log.debug("play_session_id: {0}", play_session_id)
playurl, playback_type, listitem_props = PlayUtils().get_play_url(item_id,
selected_media_source,
force_transcode,
play_session_id)
log.debug("Play URL: {0} Playback Type: {1} ListItem Properties: {2}", playurl, playback_type, listitem_props)
playurl, playback_type, listitem_props = PlayUtils().get_play_url(selected_media_source)
log.info("Play URL: {0} Playback Type: {1} ListItem Properties: {2}", playurl, playback_type, listitem_props)
if playurl is None:
return
@@ -437,9 +451,19 @@ def play_file(play_info, monitor):
list_item = set_list_item_props(item_id, list_item, result, server, listitem_props, item_title)
player = xbmc.Player()
playlist = xbmc.PlayList(xbmc.PLAYLIST_VIDEO)
playlist.clear()
playlist.add(playurl, list_item)
intro_items = []
if play_cinema_intros and seek_time == 0:
intro_items = get_playback_intros(item_id)
if len(intro_items) > 0:
playlist = play_all_files(intro_items, monitor, play_items=False)
playlist.add(playurl, list_item)
else:
playlist = xbmc.PlayList(xbmc.PLAYLIST_VIDEO)
playlist.clear()
playlist.add(playurl, list_item)
player.play(playlist)
if seek_time != 0:

143
resources/lib/playnext.py Normal file
View File

@@ -0,0 +1,143 @@
import os
import threading
import xbmc
import xbmcgui
import xbmcaddon
from .simple_logging import SimpleLogging
from .play_utils import get_playing_data, send_event_notification
log = SimpleLogging(__name__)
class PlayNextService(threading.Thread):
stop_thread = False
monitor = None
def __init__(self, play_monitor):
super(PlayNextService, self).__init__()
self.monitor = play_monitor
def run(self):
settings = xbmcaddon.Addon()
play_next_trigger_time = int(settings.getSetting('play_next_trigger_time'))
play_next_dialog = None
play_next_triggered = False
is_playing = False
while not xbmc.Monitor().abortRequested() and not self.stop_thread:
player = xbmc.Player()
if player.isPlaying():
if not is_playing:
settings = xbmcaddon.Addon()
play_next_trigger_time = int(settings.getSetting('play_next_trigger_time'))
log.debug("New play_next_trigger_time value: {0}", play_next_trigger_time)
duration = player.getTotalTime()
position = player.getTime()
trigger_time = play_next_trigger_time # 300
time_to_end = (duration - position)
if not play_next_triggered and (trigger_time > time_to_end) and play_next_dialog is None:
play_next_triggered = True
log.debug("play_next_triggered hit at {0} seconds from end", time_to_end)
play_data = get_playing_data(self.monitor.played_information)
log.debug("play_next_triggered play_data : {0}", play_data)
next_episode = play_data.get("next_episode")
item_type = play_data.get("item_type")
if next_episode is not None and item_type == "Episode":
settings = xbmcaddon.Addon()
plugin_path = settings.getAddonInfo('path')
plugin_path_real = xbmc.translatePath(os.path.join(plugin_path))
play_next_dialog = PlayNextDialog("PlayNextDialog.xml", plugin_path_real, "default", "720p")
play_next_dialog.set_episode_info(next_episode)
if play_next_dialog is not None:
play_next_dialog.show()
is_playing = True
else:
play_next_triggered = False
if play_next_dialog is not None:
play_next_dialog.close()
del play_next_dialog
play_next_dialog = None
is_playing = False
if xbmc.Monitor().waitForAbort(1):
break
def stop_servcie(self):
log.debug("PlayNextService Stop Called")
self.stop_thread = True
class PlayNextDialog(xbmcgui.WindowXMLDialog):
action_exitkeys_id = None
episode_info = None
def __init__(self, *args, **kwargs):
log.debug("PlayNextDialog: __init__")
xbmcgui.WindowXML.__init__(self, *args, **kwargs)
def onInit(self):
log.debug("PlayNextDialog: onInit")
self.action_exitkeys_id = [10, 13]
index = self.episode_info.get("IndexNumber", -1)
series_name = self.episode_info.get("SeriesName")
next_epp_name = "Episode %02d - (%s)" % (index, self.episode_info.get("Name", "n/a"))
series_label = self.getControl(3011)
series_label.setLabel(series_name)
series_label = self.getControl(3012)
series_label.setLabel(next_epp_name)
def onFocus(self, control_id):
pass
def doAction(self, action_id):
pass
def onMessage(self, message):
log.debug("PlayNextDialog: onMessage: {0}", message)
def onAction(self, action):
if action.getId() == 10: # ACTION_PREVIOUS_MENU
self.close()
elif action.getId() == 92: # ACTION_NAV_BACK
self.close()
else:
log.debug("PlayNextDialog: onAction: {0}", action.getId())
def onClick(self, control_id):
if control_id == 3013:
log.debug("PlayNextDialog: Play Next Episode")
self.close()
next_item_id = self.episode_info.get("Id")
log.debug("Playing Next Episode: {0}", next_item_id)
play_info = {}
play_info["item_id"] = next_item_id
play_info["auto_resume"] = "-1"
play_info["force_transcode"] = False
send_event_notification("embycon_play_action", play_info)
elif control_id == 3014:
self.close()
def set_episode_info(self, info):
self.episode_info = info

View File

@@ -3,6 +3,8 @@
import socket
import json
from urlparse import urlparse
import httplib
import ssl
import time
import hashlib
from datetime import datetime
@@ -16,6 +18,7 @@ from .downloadutils import DownloadUtils, save_user_details, load_user_details
from .simple_logging import SimpleLogging
from .translation import string_load
from .utils import datetime_from_string
from .clientinfo import ClientInformation
log = SimpleLogging(__name__)
@@ -23,6 +26,95 @@ __addon__ = xbmcaddon.Addon()
__addon_name__ = __addon__.getAddonInfo('name')
def check_connection_speed():
log.debug("check_connection_speed")
settings = xbmcaddon.Addon()
verify_cert = settings.getSetting('verify_cert') == 'true'
http_timeout = int(settings.getSetting("http_timeout"))
speed_test_data_size = int(settings.getSetting("speed_test_data_size"))
test_data_size = speed_test_data_size * 1000000
du = DownloadUtils()
server = du.get_server()
url = server + "/emby/playback/bitratetest?size=%s" % test_data_size
url_bits = urlparse(url.strip())
protocol = url_bits.scheme
host_name = url_bits.hostname
port = url_bits.port
# user_name = url_bits.username
# user_password = url_bits.password
url_path = url_bits.path
url_puery = url_bits.query
server = "%s:%s" % (host_name, port)
url_path = url_path + "?" + url_puery
local_use_https = False
if protocol.lower() == "https":
local_use_https = True
if local_use_https and verify_cert:
log.debug("Connection: HTTPS, Cert checked")
conn = httplib.HTTPSConnection(server, timeout=http_timeout)
elif local_use_https and not verify_cert:
log.debug("Connection: HTTPS, Cert NOT checked")
conn = httplib.HTTPSConnection(server, timeout=http_timeout, context=ssl._create_unverified_context())
else:
log.debug("Connection: HTTP")
conn = httplib.HTTPConnection(server, timeout=http_timeout)
head = du.get_auth_header(True)
head["User-Agent"] = "EmbyCon-" + ClientInformation().get_version()
conn.request(method="GET", url=url_path, headers=head)
progress_dialog = xbmcgui.DialogProgress()
message = 'Testing with {0} MB of data'.format(speed_test_data_size)
progress_dialog.create("EmbyCon connection speed test", message)
total_data_read = 0
total_time = time.time()
log.debug("Starting Connection Speed Test")
response = conn.getresponse()
last_percentage_done = 0
if int(response.status) == 200:
data = response.read(10240)
while len(data) > 0:
total_data_read += len(data)
percentage_done = int(float(total_data_read) / float(test_data_size) * 100.0)
if last_percentage_done != percentage_done:
progress_dialog.update(percentage_done)
last_percentage_done = percentage_done
data = response.read(10240)
else:
log.error("HTTP response error: {0} {1}", response.status, response.reason)
error_message = "HTTP response error: %s\n%s" % (response.status, response.reason)
xbmcgui.Dialog().ok("Speed Test Error", error_message)
return -1
total_data_read_kbits = (total_data_read * 8) / 1000
total_time = time.time() - total_time
speed = int(total_data_read_kbits / total_time)
log.debug("Finished Connection Speed Test, speed: {0} total_data: {1}, total_time: {2}", speed, total_data_read, total_time)
progress_dialog.close()
del progress_dialog
heading = "Speed Test Result : {0:,} Kbs".format(speed)
message = "Do you want to set this speed as your max stream bitrate for playback?\n"
message += "{0:,} MB over {1} sec".format(int((total_data_read / 1000000)), total_time)
response = xbmcgui.Dialog().yesno(heading, message)
if response:
settings.setSetting("max_stream_bitrate", str(speed))
return speed
def check_safe_delete_available():
log.debug("check_safe_delete_available")

View File

@@ -23,9 +23,9 @@ def timer(func):
ended = time.time()
if enabled:
data = ""
if func.__name__ == "downloadUrl" and len(args) > 1:
if func.__name__ == "download_url" and len(args) > 1:
data = args[1]
elif func.__name__ == "mainEntryPoint" and len(sys.argv) > 2:
elif func.__name__ == "main_entry_point" and len(sys.argv) > 2:
data = sys.argv[2]
log.info("timing_data|{0}|{1}|{2}|{3}", func.__name__, started, ended, data)
return value

View File

@@ -1,6 +1,7 @@
# Gnu General Public License - see LICENSE.TXT
import xbmcaddon
import xbmc
import xbmcvfs
import string
import random
@@ -44,7 +45,106 @@ def get_emby_url(base_url, params):
class PlayUtils:
@staticmethod
def get_play_url(item_id, media_source, force_transcode, play_session_id):
def get_play_url(media_source):
log.debug("get_play_url - media_source: {0}", media_source)
# check if strm file Container
if media_source.get('Container') == 'strm':
log.debug("Detected STRM Container")
playurl, listitem_props = PlayUtils().get_strm_details(media_source)
if playurl is None:
log.debug("Error, no strm content")
return None, None, None
else:
return playurl, "0", listitem_props
# get all the options
addon_settings = xbmcaddon.Addon()
server = downloadUtils.get_server()
use_https = addon_settings.getSetting('protocol') == "1"
verify_cert = addon_settings.getSetting('verify_cert') == 'true'
allow_direct_file_play = addon_settings.getSetting('allow_direct_file_play') == 'true'
can_direct_play = media_source["SupportsDirectPlay"]
can_direct_stream = media_source["SupportsDirectStream"]
can_transcode = media_source["SupportsTranscoding"]
container = media_source["Container"]
playurl = None
playback_type = None
# check if file can be directly played
if allow_direct_file_play and can_direct_play:
direct_path = media_source["Path"]
direct_path = direct_path.replace("\\", "/")
direct_path = direct_path.strip()
# handle DVD structure
if container == "dvd":
direct_path = direct_path + "/VIDEO_TS/VIDEO_TS.IFO"
elif container == "bluray":
direct_path = direct_path + "/BDMV/index.bdmv"
if direct_path.startswith("//"):
direct_path = "smb://" + direct_path[2:]
log.debug("playback_direct_path: {0}", direct_path)
if xbmcvfs.exists(direct_path):
playurl = direct_path
playback_type = "0"
# check if file can be direct streamed
if can_direct_stream and playurl is None:
direct_stream_path = media_source["DirectStreamUrl"]
direct_stream_path = server + "/emby" + direct_stream_path
if use_https and not verify_cert:
direct_stream_path += "|verifypeer=false"
playurl = direct_stream_path
playback_type = "1"
# check is file can be transcoded
if can_transcode and playurl is None:
transcode_stream_path = media_source["TranscodingUrl"]
url_path, url_params = transcode_stream_path.split('?')
params = url_params.split('&')
log.debug("Streaming Params Before : {0}", params)
# remove the audio and subtitle indexes
# this will be replaced by user selection dialogs in Kodi
params_to_remove = ["AudioStreamIndex", "SubtitleStreamIndex", "AudioBitrate"]
reduced_params = []
for param in params:
param_bits = param.split("=")
if param_bits[0] not in params_to_remove:
reduced_params.append(param)
audio_playback_bitrate = addon_settings.getSetting("audio_playback_bitrate")
audio_bitrate = int(audio_playback_bitrate) * 1000
reduced_params.append("AudioBitrate=%s" % audio_bitrate)
playback_max_width = addon_settings.getSetting("playback_max_width")
reduced_params.append("MaxWidth=%s" % playback_max_width)
log.debug("Streaming Params After : {0}", reduced_params)
new_url_params = "&".join(reduced_params)
transcode_stream_path = server + "/emby" + url_path + "?" + new_url_params
if use_https and not verify_cert:
transcode_stream_path += "|verifypeer=false"
playurl = transcode_stream_path
playback_type = "2"
return playurl, playback_type, []
@staticmethod
def get_play_url_old(item_id, media_source, force_transcode, play_session_id):
log.debug("get_play_url")
# check if strm file, path will contain contain strm contents
if media_source.get('Container') == 'strm':
@@ -56,8 +156,6 @@ class PlayUtils:
else:
return playurl, "0", listitem_props
log.debug("get_play_url")
addon_settings = xbmcaddon.Addon()
playback_type = addon_settings.getSetting("playback_type")
server = downloadUtils.get_server()
@@ -107,7 +205,7 @@ class PlayUtils:
# transcode
if playback_type == "2":
playback_bitrate = addon_settings.getSetting("playback_bitrate")
playback_bitrate = addon_settings.getSetting("max_stream_bitrate")
log.debug("playback_bitrate: {0}", playback_bitrate)
playback_max_width = addon_settings.getSetting("playback_max_width")

View File

@@ -20,31 +20,45 @@
</category>
<category label="30207">
<setting id="playback_type" type="select" label="30206" lvalues="30209|30210|30211" default="1" />
<setting label="30209" type="lsep"/>
<setting label="30437" type="lsep"/>
<setting type="sep" />
<setting id="smbusername" type="text" label="30007" default="" enable="true" visible="true"/>
<setting id="smbpassword" type="text" label="30008" default="" option="hidden" enable="true" visible="true"/>
<setting id="play_cinema_intros" type="bool" label="30438" default="false" visible="true" enable="true" />
<!--<setting id="playback_type" type="select" label="30206" lvalues="30209|30210|30211" default="1" />-->
<setting label="30238" type="lsep"/>
<setting type="sep" />
<setting id="max_stream_bitrate" type="slider" label="30208" default="75000" range="400,100,100000" option="int" visible="true"/>
<setting id="allow_direct_file_play" type="bool" label="30433" default="false" visible="true" enable="true" />
<setting id="force_transcode_h265" type="bool" label="30236" default="false" visible="true" enable="true" />
<setting id="force_transcode_mpeg2" type="bool" label="30239" default="false" visible="true" enable="true" />
<setting id="force_transcode_msmpeg4v3" type="bool" label="30240" default="false" visible="true" enable="true" />
<setting id="force_transcode_mpeg4" type="bool" label="30241" default="false" visible="true" enable="true" />
<setting id="direct_stream_sub_select" type="select" label="30379" lvalues="30380|30381|30382" default="0" visible="true"/>
<setting label="30211" type="lsep"/>
<setting type="sep" />
<setting id="playback_bitrate" type="slider" label="30208" default="6400" range="400,100,20000" option="int" visible="true"/>
<setting id="force_max_stream_bitrate" type="slider" label="30434" default="7000" range="400,100,15000" option="int" visible="true"/>
<setting id="playback_max_width" type="select" label="30212" values="640|720|1024|1280|1440|1600|1920|2600|4096" default="1920" visible="true"/>
<setting id="playback_video_force_8" type="bool" label="30213" default="false" visible="true" enable="true"/>
<setting id="audio_codec" type="select" label="30419" values="ac3|aac" default="ac3"/>
<setting id="audio_playback_bitrate" type="select" label="30418" values="128|160|192|256|320|384|448|640" default="256" visible="true"/>
<setting id="audio_max_channels" type="slider" label="30420" default="8" range="2,1,8" option="int" visible="true"/>
<setting label="30238" type="lsep"/>
<!--
<setting label="30209" type="lsep"/>
<setting type="sep" />
<setting id="force_transcode_h265" type="bool" label="30236" default="false" visible="true" enable="true" />
<setting id="force_transcode_mpeg2" type="bool" label="30239" default="false" visible="true" enable="true" />
<setting id="force_transcode_msmpeg4v3" type="bool" label="30240" default="false" visible="true" enable="true" />
<setting id="force_transcode_mpeg4" type="bool" label="30241" default="false" visible="true" enable="true" />
<setting id="direct_stream_sub_select" type="select" label="30379" lvalues="30380|30381|30382" default="0" visible="true"/>
<setting id="smbusername" type="text" label="30007" default="" enable="true" visible="true"/>
<setting id="smbpassword" type="text" label="30008" default="" option="hidden" enable="true" visible="true"/>
-->
</category>
<category label="30214">
<setting label="30440" type="lsep"/>
<setting type="sep" />
<setting id="play_next_trigger_time" type="slider" label="30439" default="0" range="0,1,180" option="int" visible="true"/>
<setting label="30215" type="lsep"/>
<setting type="sep" />
<setting id="promptPlayNextEpisodePercentage" type="slider" label="30218" default="90" range="5,1,100" option="int" visible="true"/>
@@ -117,6 +131,7 @@
<setting id="use_cache" type="bool" label="30345" default="true" visible="true" enable="true" />
<setting id="showLoadProgress" type="bool" label="30120" default="false" visible="true" enable="true" />
<setting id="suppressErrors" type="bool" label="30315" default="false" visible="true" enable="true" />
<setting id="speed_test_data_size" type="slider" label="30436" default="15" range="5,1,100" option="int" visible="true"/>
</category>
<category label="30421">

View File

@@ -0,0 +1,51 @@
<?xml version="1.0" encoding="UTF-8"?>
<window id="3301" type="dialog">
<defaultcontrol always="true">3000</defaultcontrol>
<zorder>2</zorder>
<coordinates>
<system>1</system>
<left>450</left>
<top>280</top>
</coordinates>
<controls>
<control type="image" id="3010">
<left>0</left>
<top>0</top>
<width>380</width>
<height>100</height>
<texture border="40">bg.png</texture>
</control>
<control type="label" id="3020">
<width>120</width>
<left>20</left>
<top>5</top>
<height>45</height>
<label>Bitrate : </label>
<textcolor>99FFFFFF</textcolor>
<font>font14</font>
<align>left</align>
</control>
<control type="label" id="3030">
<width>150</width>
<left>120</left>
<top>5</top>
<height>45</height>
<label>100 Mbs</label>
<textcolor>99FFFFFF</textcolor>
<font>font14</font>
<align>left</align>
</control>
<control type="slider" id="3000">
<left>20</left>
<top>55</top>
<width>340</width>
<height>30</height>
<visible>true</visible>
</control>
</controls>
</window>

View File

@@ -0,0 +1,67 @@
<?xml version="1.0" encoding="UTF-8"?>
<window id="3301" type="dialog">
<defaultcontrol always="true">3013</defaultcontrol>
<zorder>2</zorder>
<coordinates>
<system>1</system>
<left>0</left>
<top>0</top>
</coordinates>
<controls>
<control type="image" id="3010">
<left>0</left>
<top>0</top>
<width>1280</width>
<height>52</height>
<texture border="0" colordiffuse="90FFFFFF">bg.png</texture>
</control>
<control type="label" id="3011">
<left>20</left>
<top>0</top>
<width>390</width>
<height>45</height>
<label></label>
<font>font45_title</font>
<align>left</align>
</control>
<control type="label" id="3012">
<left>390</left>
<top>5</top>
<width>500</width>
<height>35</height>
<label></label>
<font>font14</font>
<align>center</align>
</control>
<control type="button" id="3013">
<left>1020</left>
<top>-8</top>
<width>150</width>
<height>65</height>
<visible>true</visible>
<label>Play Next</label>
<align>center</align>
<texture border="1" colordiffuse="ff161616">white.png</texture>
<font>font12</font>
<onright>3014</onright>
</control>
<control type="button" id="3014">
<left>1140</left>
<top>-8</top>
<width>150</width>
<height>65</height>
<visible>true</visible>
<label>Close</label>
<align>center</align>
<texture border="1" colordiffuse="ff161616">white.png</texture>
<font>font12</font>
<onleft>3013</onleft>
</control>
</controls>
</window>

View File

@@ -16,11 +16,12 @@ from resources.lib.widgets import set_background_image, set_random_movies
from resources.lib.websocket_client import WebSocketClient
from resources.lib.menu_functions import set_library_window_values
from resources.lib.context_monitor import ContextMonitor
from resources.lib.server_detect import check_server, check_safe_delete_available
from resources.lib.server_detect import check_server, check_safe_delete_available, check_connection_speed
from resources.lib.library_change_monitor import LibraryChangeMonitor
from resources.lib.datamanager import clear_old_cache_data
from resources.lib.tracking import set_timing_enabled
from resources.lib.image_server import HttpImageServerThread
from resources.lib.playnext import PlayNextService
settings = xbmcaddon.Addon()
@@ -86,6 +87,12 @@ websocket_client = WebSocketClient(library_change_monitor)
if remote_control:
websocket_client.start()
play_next_service = None
play_next_trigger_time = int(settings.getSetting('play_next_trigger_time'))
if play_next_trigger_time > 0:
play_next_service = PlayNextService(monitor)
play_next_service.start()
# Start the context menu monitor
context_monitor = None
context_menu = settings.getSetting('override_contextmenu') == "true"
@@ -109,6 +116,7 @@ if enable_logging:
# the service to exit when a user cancels an addon load action. This is a bug in Kodi.
# I am switching back to xbmc.abortRequested approach until kodi is fixed or I find a work arround
prev_user_id = home_window.get_property("userid")
first_run = True
while not xbmc.abortRequested:
@@ -130,6 +138,19 @@ while not xbmc.abortRequested:
prev_user_id = home_window.get_property("userid")
user_changed = True
if user_changed or first_run:
server_speed_check_data = settings.getSetting("server_speed_check_data")
server_host = download_utils.get_server()
if server_host is not None and server_host != "" and server_host != "<none>" and server_host not in server_speed_check_data:
message = "This is the first time you have connected to this server.\nDo you want to run a connection speed test?"
response = xbmcgui.Dialog().yesno("First Connection", message)
if response:
speed = check_connection_speed()
if speed > 0:
settings.setSetting("server_speed_check_data", server_host + "-" + str(speed))
else:
settings.setSetting("server_speed_check_data", server_host + "-skipped")
if user_changed or (random_movie_list_interval != 0 and (time.time() - last_random_movie_update) > random_movie_list_interval):
last_random_movie_update = time.time()
set_random_movies()
@@ -162,6 +183,7 @@ while not xbmc.abortRequested:
log.error("Exception in Playback Monitor: {0}", error)
log.error("{0}", traceback.format_exc())
first_run = False
xbmc.sleep(1000)
image_server.stop()
@@ -169,6 +191,10 @@ image_server.stop()
# call stop on the library update monitor
library_change_monitor.stop()
# stop the play next episdoe service
if play_next_service:
play_next_service.stop_servcie()
# call stop on the context menu monitor
if context_monitor:
context_monitor.stop_monitor()