2015-07-22 23:16:08 +10:00
# -*- coding: utf-8 -*-
2015-06-05 16:05:40 +10:00
import os
import sys
import time
from datetime import datetime
2015-03-14 08:24:59 +11:00
import xbmcaddon
import xbmc
import xbmcgui
2015-07-22 23:16:08 +10:00
import xbmcvfs
2015-03-14 08:24:59 +11:00
2015-08-14 19:03:12 +10:00
_addon = xbmcaddon . Addon ( id = ' plugin.video.emby ' )
addon_path = _addon . getAddonInfo ( ' path ' ) . decode ( ' utf-8 ' )
2015-06-05 16:05:40 +10:00
base_resource_path = xbmc . translatePath ( os . path . join ( addon_path , ' resources ' , ' lib ' ) ) . decode ( ' utf-8 ' )
sys . path . append ( base_resource_path )
2015-03-14 08:24:59 +11:00
import KodiMonitor
import Utils as utils
2015-04-03 21:13:01 +11:00
from ClientInformation import ClientInformation
2015-06-05 16:05:40 +10:00
from ConnectionManager import ConnectionManager
2015-04-03 21:13:01 +11:00
from UserClient import UserClient
2015-06-05 16:05:40 +10:00
from Player import Player
from WebSocketClient import WebSocketThread
from LibrarySync import LibrarySync
2015-09-16 03:03:52 +10:00
from LibraryMonitor import LibraryMonitor
2015-04-07 03:17:32 +10:00
2015-03-14 08:24:59 +11:00
class Service ( ) :
2015-04-03 21:13:01 +11:00
2015-05-17 22:11:50 +10:00
KodiMonitor = KodiMonitor . Kodi_Monitor ( )
2015-06-05 16:05:40 +10:00
clientInfo = ClientInformation ( )
2015-04-07 03:17:32 +10:00
addonName = clientInfo . getAddonName ( )
2015-06-05 20:12:09 +10:00
logLevel = UserClient ( ) . getLogLevel ( )
2015-05-03 15:27:43 +10:00
WINDOW = xbmcgui . Window ( 10000 )
2015-06-05 16:05:40 +10:00
newWebSocketThread = None
newUserClient = None
2015-06-16 15:53:01 +10:00
newLibraryThread = None
2015-05-03 15:27:43 +10:00
warn_auth = True
2015-06-04 20:10:49 +10:00
welcome_msg = True
2015-05-03 15:27:43 +10:00
server_online = True
2015-06-05 16:05:40 +10:00
def __init__ ( self , * args ) :
2015-04-27 06:41:39 +10:00
addonName = self . addonName
2015-09-24 21:48:43 +10:00
WINDOW = self . WINDOW
WINDOW . setProperty ( ' getLogLevel ' , str ( self . logLevel ) )
2015-03-14 08:24:59 +11:00
2015-06-05 16:05:40 +10:00
# Initial logging
2015-04-07 03:17:32 +10:00
self . logMsg ( " Starting Monitor " , 0 )
self . logMsg ( " ======== START %s ======== " % addonName , 0 )
2015-09-24 21:48:43 +10:00
self . logMsg ( " Platform: %s " % ( self . clientInfo . getPlatform ( ) ) , 0 )
2015-06-05 16:05:40 +10:00
self . logMsg ( " KODI Version: %s " % xbmc . getInfoLabel ( ' System.BuildVersion ' ) , 0 )
2015-09-24 21:48:43 +10:00
self . logMsg ( " %s Version: %s " % ( addonName , self . clientInfo . getVersion ( ) ) , 0 )
self . logMsg ( " Log Level: %s " % self . logLevel , 1 )
2015-06-05 16:05:40 +10:00
# Reset window props for profile switch
2015-09-24 21:48:43 +10:00
WINDOW . clearProperty ( ' Server_online ' )
WINDOW . clearProperty ( ' Server_status ' )
WINDOW . clearProperty ( ' startup ' )
WINDOW . clearProperty ( ' OnWakeSync ' )
WINDOW . clearProperty ( ' minDBVersionCheck ' )
2015-09-07 03:28:00 +10:00
2015-09-07 19:12:28 +10:00
# Set min DB version
2015-09-24 21:48:43 +10:00
WINDOW . setProperty ( ' minDBVersion ' , ' 1.1.40 ' )
2015-06-05 16:05:40 +10:00
2015-09-24 21:48:43 +10:00
embyProperty = WINDOW . getProperty ( ' Emby.nodes.total ' )
2015-06-05 16:05:40 +10:00
propNames = [
2015-05-07 18:32:30 +10:00
2015-06-05 16:05:40 +10:00
" index " , " path " , " title " , " content " ,
" inprogress.content " , " inprogress.title " ,
" inprogress.content " , " inprogress.path " ,
" nextepisodes.title " , " nextepisodes.content " ,
" nextepisodes.path " , " unwatched.title " ,
" unwatched.content " , " unwatched.path " ,
" recent.title " , " recent.content " , " recent.path " ,
" recentepisodes.title " , " recentepisodes.content " ,
" recentepisodes.path " , " inprogressepisodes.title " ,
" inprogressepisodes.content " , " inprogressepisodes.path "
]
2015-05-07 18:32:30 +10:00
if embyProperty :
totalNodes = int ( embyProperty )
for i in range ( totalNodes ) :
for prop in propNames :
2015-09-24 21:48:43 +10:00
WINDOW . clearProperty ( ' Emby.nodes. %s . %s ' % ( str ( i ) , prop ) )
2015-04-07 03:17:32 +10:00
def logMsg ( self , msg , lvl = 1 ) :
2015-06-05 16:05:40 +10:00
2015-05-03 15:27:43 +10:00
className = self . __class__ . __name__
2015-06-05 16:05:40 +10:00
utils . logMsg ( " %s %s " % ( self . addonName , className ) , msg , int ( lvl ) )
2015-03-14 08:24:59 +11:00
def ServiceEntryPoint ( self ) :
2015-09-24 21:48:43 +10:00
WINDOW = self . WINDOW
2015-06-05 16:05:40 +10:00
# Server auto-detect
2015-03-14 13:37:03 +11:00
ConnectionManager ( ) . checkServer ( )
2015-06-05 16:05:40 +10:00
# Initialize important threads
2015-04-03 21:13:01 +11:00
user = UserClient ( )
player = Player ( )
2015-04-02 06:07:29 +11:00
ws = WebSocketThread ( )
2015-06-16 15:53:01 +10:00
library = LibrarySync ( )
2015-09-16 03:03:52 +10:00
librarymonitor = LibraryMonitor ( )
xbmc . log ( " START LIBRARY MONITOR " )
librarymonitor . start ( )
2015-06-05 16:05:40 +10:00
# Sync and progress report
lastProgressUpdate = datetime . today ( )
2015-04-02 06:07:29 +11:00
while not self . KodiMonitor . abortRequested ( ) :
2015-05-03 15:27:43 +10:00
2015-06-05 16:05:40 +10:00
# Before proceeding, need to make sure:
# 1. Server is online
# 2. User is set
# 3. User has access to the server
2015-09-24 21:48:43 +10:00
if WINDOW . getProperty ( ' Server_online ' ) == " true " :
2015-06-05 16:05:40 +10:00
# Emby server is online
# Verify if user is set and has access to the server
2015-07-22 23:16:08 +10:00
if ( user . currUser is not None ) and user . HasAccess :
2015-06-16 15:53:01 +10:00
2015-06-05 16:05:40 +10:00
# If an item is playing
2015-05-12 17:34:03 +10:00
if xbmc . Player ( ) . isPlaying ( ) :
try :
2015-06-05 16:05:40 +10:00
# Update and report progress
2015-05-12 17:34:03 +10:00
playTime = xbmc . Player ( ) . getTime ( )
totalTime = xbmc . Player ( ) . getTotalTime ( )
currentFile = xbmc . Player ( ) . getPlayingFile ( )
2015-06-05 16:05:40 +10:00
# Update positionticks
2015-07-22 23:16:08 +10:00
if player . played_information . get ( currentFile ) is not None :
2015-09-24 21:48:43 +10:00
player . played_information [ currentFile ] [ " currentPosition " ] = playTime
2015-05-12 17:34:03 +10:00
td = datetime . today ( ) - lastProgressUpdate
secDiff = td . seconds
2015-06-05 16:05:40 +10:00
# Report progress to Emby server
if ( secDiff > 3 ) :
2015-07-22 23:16:08 +10:00
player . reportPlayback ( )
2015-05-12 17:34:03 +10:00
lastProgressUpdate = datetime . today ( )
2015-06-05 16:05:40 +10:00
2015-09-24 21:48:43 +10:00
elif WINDOW . getProperty ( ' commandUpdate ' ) == " true " :
2015-06-05 16:05:40 +10:00
# Received a remote control command that
# requires updating immediately
2015-09-24 21:48:43 +10:00
WINDOW . clearProperty ( ' commandUpdate ' )
2015-07-22 23:16:08 +10:00
player . reportPlayback ( )
2015-09-24 21:48:43 +10:00
lastProgressUpdate = datetime . today ( )
2015-05-12 17:34:03 +10:00
2015-06-05 16:05:40 +10:00
except Exception as e :
2015-07-22 23:16:08 +10:00
self . logMsg ( " Exception in Playback Monitor Service: %s " % e , 1 )
2015-05-12 17:34:03 +10:00
pass
2015-06-16 17:11:38 +10:00
else :
# Start up events
self . warn_auth = True
2015-08-14 19:03:12 +10:00
if utils . settings ( ' supressConnectMsg ' ) == " false " :
2015-06-16 17:11:38 +10:00
if self . welcome_msg :
# Reset authentication warnings
self . welcome_msg = False
2015-08-15 15:20:06 +10:00
# Get additional users
additionalUsers = user . AdditionalUser
if additionalUsers :
add = " , %s " % " , " . join ( additionalUsers )
else :
add = " "
xbmcgui . Dialog ( ) . notification ( " Emby server " , " Welcome %s %s ! " % ( user . currUser , add ) , icon = " special://home/addons/plugin.video.emby/icon.png " , time = 2000 , sound = False )
2015-06-16 17:11:38 +10:00
# Start the Websocket Client
2015-07-22 23:16:08 +10:00
if ( self . newWebSocketThread is None ) :
2015-06-16 17:11:38 +10:00
self . newWebSocketThread = " Started "
ws . start ( )
2015-06-16 18:25:12 +10:00
# Start the Library Sync Thread
2015-07-22 23:16:08 +10:00
if ( self . newLibraryThread is None ) :
2015-06-16 17:11:38 +10:00
self . newLibraryThread = " Started "
library . start ( )
2015-06-16 15:53:01 +10:00
2015-05-12 17:34:03 +10:00
else :
2015-05-12 18:16:34 +10:00
2015-07-22 23:16:08 +10:00
if ( user . currUser is None ) and self . warn_auth :
2015-06-05 16:05:40 +10:00
# Alert user is not authenticated and suppress future warning
2015-05-12 17:34:03 +10:00
self . warn_auth = False
2015-06-05 16:05:40 +10:00
self . logMsg ( " Not authenticated yet. " , 1 )
2015-05-12 17:34:03 +10:00
2015-06-05 16:05:40 +10:00
# User access is restricted.
# Keep verifying until access is granted
# unless server goes offline or Kodi is shut down.
2015-05-12 18:16:34 +10:00
while user . HasAccess == False :
2015-06-05 16:05:40 +10:00
# Verify access with an API call
2015-05-12 18:16:34 +10:00
user . hasAccess ( )
2015-05-13 08:08:39 +10:00
2015-09-24 21:48:43 +10:00
if WINDOW . getProperty ( ' Server_online ' ) != " true " :
2015-05-14 14:48:35 +10:00
# Server went offline
break
2015-05-12 18:16:34 +10:00
if self . KodiMonitor . waitForAbort ( 5 ) :
# Abort was requested while waiting. We should exit
break
2015-04-02 06:07:29 +11:00
else :
2015-06-05 16:05:40 +10:00
# Wait until Emby server is online
# or Kodi is shut down.
2015-05-03 15:27:43 +10:00
while not self . KodiMonitor . abortRequested ( ) :
2015-04-27 09:15:40 +10:00
2015-05-03 15:27:43 +10:00
if user . getServer ( ) == " " :
2015-06-05 16:05:40 +10:00
# No server info set in add-on settings
2015-05-03 15:27:43 +10:00
pass
2015-06-05 16:05:40 +10:00
2015-05-07 08:58:31 +10:00
elif user . getPublicUsers ( ) == False :
2015-06-05 16:05:40 +10:00
# Server is offline.
# Alert the user and suppress future warning
2015-05-03 15:27:43 +10:00
if self . server_online :
self . logMsg ( " Server is offline. " , 1 )
2015-09-24 21:48:43 +10:00
WINDOW . setProperty ( ' Server_online ' , " false " )
2015-07-22 23:16:08 +10:00
xbmcgui . Dialog ( ) . notification ( " Error connecting " , " %s Server is unreachable. " % self . addonName , icon = " special://home/addons/plugin.video.emby/icon.png " , sound = False )
2015-05-03 15:27:43 +10:00
self . server_online = False
2015-06-05 16:05:40 +10:00
2015-03-14 08:24:59 +11:00
else :
2015-05-03 15:27:43 +10:00
# Server is online
if not self . server_online :
2015-06-05 16:05:40 +10:00
# Server was offline when Kodi started.
2015-05-03 15:27:43 +10:00
# Wait for server to be fully established.
if self . KodiMonitor . waitForAbort ( 5 ) :
# Abort was requested while waiting.
break
2015-06-05 16:05:40 +10:00
# Alert the user that server is online.
2015-07-22 23:16:08 +10:00
xbmcgui . Dialog ( ) . notification ( " Emby server " , " Welcome %s ! " % user . currUser , icon = " special://home/addons/plugin.video.emby/icon.png " , time = 2000 , sound = False )
2015-06-05 16:05:40 +10:00
2015-05-03 15:27:43 +10:00
self . server_online = True
self . logMsg ( " Server is online and ready. " , 1 )
2015-09-24 21:48:43 +10:00
WINDOW . setProperty ( ' Server_online ' , " true " )
2015-05-03 15:27:43 +10:00
2015-06-05 16:05:40 +10:00
# Start the User client
2015-07-22 23:16:08 +10:00
if self . newUserClient is None :
2015-05-03 15:27:43 +10:00
self . newUserClient = " Started "
user . start ( )
break
if self . KodiMonitor . waitForAbort ( 1 ) :
# Abort was requested while waiting.
break
2015-04-12 19:49:02 +10:00
2015-06-05 16:05:40 +10:00
if self . KodiMonitor . waitForAbort ( 1 ) :
# Abort was requested while waiting. We should exit
break
2015-08-23 02:17:54 +10:00
2015-09-24 21:48:43 +10:00
# If music is enable and direct stream for music is enabled
2015-08-23 02:17:54 +10:00
# We use Kodi pathsubstitution to allow for music to play outside network
# The setting needs to be set before Kodi starts.
if utils . settings ( ' enableMusicSync ' ) == " true " and utils . settings ( ' directstreammusic ' ) == " true " :
# We need to keep track of the settings
alternate = utils . settings ( ' altip ' ) == " true "
pathsub = utils . settings ( ' pathsub ' ) == " true "
if pathsub and not alternate :
# Path sub in place, but primary address in use, remove it
utils . pathsubstitution ( False )
elif not pathsub and alternate :
# Path sub not in place, but secondary address in use, add it
utils . pathsubstitution ( )
2015-04-02 06:07:29 +11:00
2015-07-22 23:16:08 +10:00
if ( self . newWebSocketThread is not None ) :
2015-04-03 21:13:01 +11:00
ws . stopClient ( )
2015-07-22 23:16:08 +10:00
if ( self . newUserClient is not None ) :
2015-05-03 15:27:43 +10:00
user . stopClient ( )
2015-09-16 03:03:52 +10:00
xbmc . log ( " STOP LIBRARY MONITOR " )
librarymonitor . stop ( )
2015-05-03 15:27:43 +10:00
self . logMsg ( " ======== STOP %s ======== " % self . addonName , 0 )
2015-05-17 22:11:50 +10:00
2015-04-27 09:15:40 +10:00
#start the service
2015-06-05 16:05:40 +10:00
Service ( ) . ServiceEntryPoint ( )