Fix watched feedback and added General command

Everything in the remote control is supported except for audiostream and
subtitleindex. Turns out the watched playcount bug was indeed a
feedback, so to prevent this I'm skipping the first message that has the
itemId right after marking watched.
This commit is contained in:
angelblue05 2015-05-16 01:31:08 -05:00
parent 6aeabc2e3f
commit 79e4bd8a6a
6 changed files with 152 additions and 58 deletions

View file

@ -71,8 +71,18 @@ class DownloadUtils():
url = "{server}/mediabrowser/Sessions/Capabilities/Full" url = "{server}/mediabrowser/Sessions/Capabilities/Full"
data = { data = {
'PlayableMediaTypes': "Audio,Video", 'PlayableMediaTypes': "Audio,Video",
'SupportedCommands': "Play,Playstate,SendString,DisplayMessage,PlayNext", 'SupportsMediaControl': True,
'SupportsMediaControl': True 'SupportedCommands': (
"MoveUp,MoveDown,MoveLeft,MoveRight,Select,"
"Back,ToggleContextMenu,ToggleFullscreen,ToggleOsdMenu,"
"GoHome,PageUp,NextLetter,GoToSearch,"
"GoToSettings,PageDown,PreviousLetter,TakeScreenshot,"
"VolumeUp,VolumeDown,ToggleMute,SendString,DisplayMessage,"
"Mute,Unmute,SetVolume,"
"Play,Playstate,PlayNext"
)
} }
self.logMsg("Capabilities URL: %s" % url, 2) self.logMsg("Capabilities URL: %s" % url, 2)

View file

@ -42,8 +42,9 @@ class Kodi_Monitor(xbmc.Monitor):
item = jsondata.get("item").get("id") item = jsondata.get("item").get("id")
type = jsondata.get("item").get("type") type = jsondata.get("item").get("type")
prop = WINDOW.getProperty('Played%s%s' % (type,item)) prop = WINDOW.getProperty('Played%s%s' % (type,item))
processWatched = WINDOW.getProperty('played_skipWatched')
if (playcount != None) and (prop != "true"): if (playcount != None) and (prop != "true") and (processWatched != "true"):
WINDOW.setProperty("Played%s%s" % (type,item), "true") WINDOW.setProperty("Played%s%s" % (type,item), "true")
utils.logMsg("MB# Sync","Kodi_Monitor--> VideoLibrary.OnUpdate : " + str(data),2) utils.logMsg("MB# Sync","Kodi_Monitor--> VideoLibrary.OnUpdate : " + str(data),2)
WriteKodiVideoDB().updatePlayCountFromKodi(item, type, playcount) WriteKodiVideoDB().updatePlayCountFromKodi(item, type, playcount)
@ -87,6 +88,7 @@ class Kodi_Monitor(xbmc.Monitor):
# triggers 3 times in a row. # triggers 3 times in a row.
xbmc.sleep(100) xbmc.sleep(100)
self.WINDOW.clearProperty("Played%s%s" % (type,id)) self.WINDOW.clearProperty("Played%s%s" % (type,id))
self.WINDOW.clearProperty('played_skipWatched')

View file

@ -108,10 +108,17 @@ class PlaybackUtils():
resume_result = resumeScreen.select(self.language(30105), display_list) resume_result = resumeScreen.select(self.language(30105), display_list)
if resume_result == 0: if resume_result == 0:
WINDOW.setProperty(playurl+"seektime", str(seekTime)) WINDOW.setProperty(playurl+"seektime", str(seekTime))
elif resume_result < 0:
# User cancelled dialog
xbmc.log("Emby player -> User cancelled resume dialog.")
return
else: else:
WINDOW.clearProperty(playurl+"seektime") WINDOW.clearProperty(playurl+"seektime")
else: else:
WINDOW.clearProperty(playurl+"seektime") WINDOW.clearProperty(playurl+"seektime")
else:
# Playback started from library
WINDOW.setProperty(playurl+"seektime", str(seekTime))
if result.get("Type")=="Episode": if result.get("Type")=="Episode":
WINDOW.setProperty(playurl+"refresh_id", result.get("SeriesId")) WINDOW.setProperty(playurl+"refresh_id", result.get("SeriesId"))

View file

@ -69,7 +69,6 @@ class Player( xbmc.Player ):
for item_url in self.played_information: for item_url in self.played_information:
data = self.played_information.get(item_url) data = self.played_information.get(item_url)
if (data is not None): if (data is not None):
self.logMsg("emby Service -> item_url : " + item_url) self.logMsg("emby Service -> item_url : " + item_url)
self.logMsg("emby Service -> item_data : " + str(data)) self.logMsg("emby Service -> item_data : " + str(data))
@ -81,6 +80,9 @@ class Player( xbmc.Player ):
currentFile = data.get("currentfile") currentFile = data.get("currentfile")
type = data.get("Type") type = data.get("Type")
# Prevent websocket feedback
self.WINDOW.setProperty("played_itemId", item_id)
if(currentPosition != None and self.hasData(runtime)): if(currentPosition != None and self.hasData(runtime)):
runtimeTicks = int(runtime) runtimeTicks = int(runtime)
self.logMsg("emby Service -> runtimeticks:" + str(runtimeTicks)) self.logMsg("emby Service -> runtimeticks:" + str(runtimeTicks))
@ -88,6 +90,10 @@ class Player( xbmc.Player ):
markPlayedAt = float(90) / 100 markPlayedAt = float(90) / 100
self.logMsg("emby Service -> Percent Complete:" + str(percentComplete) + " Mark Played At:" + str(markPlayedAt)) self.logMsg("emby Service -> Percent Complete:" + str(percentComplete) + " Mark Played At:" + str(markPlayedAt))
if percentComplete < markPlayedAt:
# Do not mark as watched
self.WINDOW.setProperty('played_skipWatched', 'true')
self.stopPlayback(data) self.stopPlayback(data)
if percentComplete > .80 and data.get("Type") == "Episode" and addonSettings.getSetting("offerDelete")=="true": if percentComplete > .80 and data.get("Type") == "Episode" and addonSettings.getSetting("offerDelete")=="true":
@ -116,29 +122,17 @@ class Player( xbmc.Player ):
self.logMsg("stopPlayback called", 2) self.logMsg("stopPlayback called", 2)
item_id = data.get("item_id") item_id = data.get("item_id")
audioindex = data.get("AudioStreamIndex")
subtitleindex = data.get("SubtitleStreamIndex")
playMethod = data.get("playmethod")
currentPosition = data.get("currentPosition") currentPosition = data.get("currentPosition")
positionTicks = int(currentPosition * 10000000) positionTicks = int(currentPosition * 10000000)
url = "{server}/mediabrowser/Sessions/Playing/Stopped" url = "{server}/mediabrowser/Sessions/Playing/Stopped"
postdata = { postdata = {
'QueueableMediaTypes': "Video",
'CanSeek': True,
'ItemId': item_id, 'ItemId': item_id,
'MediaSourceId': item_id, 'MediaSourceId': item_id,
'PlayMethod': playMethod,
'PositionTicks': positionTicks 'PositionTicks': positionTicks
} }
if audioindex:
postdata['AudioStreamIndex'] = audioindex
if subtitleindex:
postdata['SubtitleStreamIndex'] = subtitleindex
self.doUtils.downloadUrl(url, postBody=postdata, type="POST") self.doUtils.downloadUrl(url, postBody=postdata, type="POST")
def reportPlayback(self): def reportPlayback(self):
@ -154,7 +148,7 @@ class Player( xbmc.Player ):
data = self.played_information.get(currentFile) data = self.played_information.get(currentFile)
# only report playback if emby has initiated the playback (item_id has value) # only report playback if emby has initiated the playback (item_id has value)
if (data is not None) and (data.get("item_id") is not None): if data is not None and data.get("item_id") is not None:
# Get playback information # Get playback information
item_id = data.get("item_id") item_id = data.get("item_id")
@ -167,14 +161,22 @@ class Player( xbmc.Player ):
if paused is None: if paused is None:
paused = False paused = False
#url = "{server}/mediabrowser/Sessions/Playing/Progress" # Get playback volume
volume_query = '{"jsonrpc": "2.0", "method": "Application.GetProperties", "params": {"properties": ["volume","muted"]}, "id": 1}'
result = xbmc.executeJSONRPC(volume_query)
result = json.loads(result)
volume = result.get(u'result').get(u'volume')
muted = result.get(u'result').get(u'muted')
postdata = { postdata = {
'QueueableMediaTypes': "Video", 'QueueableMediaTypes': "Video",
'CanSeek': True, 'CanSeek': True,
'ItemId': item_id, 'ItemId': item_id,
'MediaSourceId': item_id, 'MediaSourceId': item_id,
'PlayMethod': playMethod,
'IsPaused': paused, 'IsPaused': paused,
'PlayMethod': playMethod 'VolumeLevel': volume,
'IsMuted': muted
} }
if playTime: if playTime:
@ -243,15 +245,17 @@ class Player( xbmc.Player ):
itemType = WINDOW.getProperty(currentFile + "type") itemType = WINDOW.getProperty(currentFile + "type")
seekTime = WINDOW.getProperty(currentFile + "seektime") seekTime = WINDOW.getProperty(currentFile + "seektime")
username = WINDOW.getProperty('currUser') # Get playback volume
sessionId = WINDOW.getProperty('sessionId%s' % username) volume_query = '{"jsonrpc": "2.0", "method": "Application.GetProperties", "params": {"properties": ["volume","muted"]}, "id": 1}'
result = xbmc.executeJSONRPC(volume_query)
result = json.loads(result)
volume = result.get(u'result').get(u'volume')
muted = result.get(u'result').get(u'muted')
if seekTime != "": if seekTime:
PlaybackUtils().seekToPosition(int(seekTime)) PlaybackUtils().seekToPosition(int(seekTime))
else:
if (not item_id) or (len(item_id) == 0): seekTime = 0
self.logMsg("onPlayBackStarted: No info for current playing file", 0)
return
url = "{server}/mediabrowser/Sessions/Playing" url = "{server}/mediabrowser/Sessions/Playing"
postdata = { postdata = {
@ -259,7 +263,10 @@ class Player( xbmc.Player ):
'CanSeek': True, 'CanSeek': True,
'ItemId': item_id, 'ItemId': item_id,
'MediaSourceId': item_id, 'MediaSourceId': item_id,
'PlayMethod': playMethod 'PlayMethod': playMethod,
'VolumeLevel': volume,
'PositionTicks': int(seekTime),
'IsMuted': muted
} }
if audioindex: if audioindex:
@ -268,24 +275,24 @@ class Player( xbmc.Player ):
if subtitleindex: if subtitleindex:
postdata['SubtitleStreamIndex'] = subtitleindex postdata['SubtitleStreamIndex'] = subtitleindex
# Post playback to server
self.logMsg("Sending POST play started.", 1) self.logMsg("Sending POST play started.", 1)
#self.logMsg("emby Service -> Sending Post Play Started : " + url, 0)
self.doUtils.downloadUrl(url, postBody=postdata, type="POST") self.doUtils.downloadUrl(url, postBody=postdata, type="POST")
# save data map for updates and position calls # save data map for updates and position calls
data = {} data = {
data["runtime"] = runtime 'runtime': runtime,
data["item_id"] = item_id 'item_id': item_id,
data["refresh_id"] = refresh_id 'refresh_id': refresh_id,
data["currentfile"] = currentFile 'currentfile': currentFile,
data["AudioStreamIndex"] = audioindex 'AudioStreamIndex': audioindex,
data["SubtitleStreamIndex"] = subtitleindex 'SubtitleStreamIndex': subtitleindex,
data["playmethod"] = playMethod 'playmethod': playMethod,
data["Type"] = itemType 'type': itemType,
'PositionTicks': int(seekTime)
}
self.played_information[currentFile] = data self.played_information[currentFile] = data
self.logMsg("ADDING_FILE: %s" % self.played_information, 1)
self.logMsg("emby Service -> ADDING_FILE : " + currentFile, 0)
self.logMsg("emby Service -> ADDING_FILE : " + str(self.played_information), 0)
# log some playback stats # log some playback stats
if(itemType != None): if(itemType != None):
@ -303,7 +310,7 @@ class Player( xbmc.Player ):
self.playStats[playMethod] = 1 self.playStats[playMethod] = 1
# reset in progress position # reset in progress position
self.reportPlayback() #self.reportPlayback()
def GetPlayStats(self): def GetPlayStats(self):
return self.playStats return self.playStats

View file

@ -99,8 +99,14 @@ class WebSocketThread(threading.Thread):
messageType = result.get("MessageType") messageType = result.get("MessageType")
data = result.get("Data") data = result.get("Data")
WINDOW = xbmcgui.Window( 10000 )
playedItemId = WINDOW.getProperty('played_itemId')
if(messageType != None and messageType == "Play" and data != None): if (playedItemId != '') and (playedItemId in message):
# Prevent feedback for watched
WINDOW.clearProperty('played_itemId')
elif(messageType != None and messageType == "Play" and data != None):
itemIds = data.get("ItemIds") itemIds = data.get("ItemIds")
playCommand = data.get("PlayCommand") playCommand = data.get("PlayCommand")
@ -144,7 +150,6 @@ class WebSocketThread(threading.Thread):
elif(messageType != None and messageType == "UserDataChanged"): elif(messageType != None and messageType == "UserDataChanged"):
# for now just do a full playcount sync # for now just do a full playcount sync
WINDOW = xbmcgui.Window( 10000 )
self.logMsg("Message : Doing UserDataChanged", 0) self.logMsg("Message : Doing UserDataChanged", 0)
userDataList = data.get("UserDataList") userDataList = data.get("UserDataList")
self.logMsg("Message : Doing UserDataChanged : UserDataList : " + str(userDataList), 0) self.logMsg("Message : Doing UserDataChanged : UserDataList : " + str(userDataList), 0)
@ -169,16 +174,77 @@ class WebSocketThread(threading.Thread):
elif messageType == "GeneralCommand": elif messageType == "GeneralCommand":
if data.get("Name") == "DisplayMessage": command = data.get("Name")
message = data.get("Arguments") arguments = data.get("Arguments")
header = message[u'Header']
text = message[u'Text']
xbmcgui.Dialog().notification(header, text)
elif data.get("Name") == "SendString": commandsPlayback = [
message = data.get("Arguments") 'Mute','Unmute','SetVolume',
string = message[u'String'] 'SetAudioStreamIndex'
xbmcgui.Dialog().notification("Emby server", string) ]
if command in commandsPlayback:
# These commands need to be reported back
if command == "Mute":
xbmc.executebuiltin('Mute')
elif command == "Unmute":
xbmc.executebuiltin('Mute')
elif command == "SetVolume":
volume = arguments[u'Volume']
xbmc.executebuiltin('SetVolume(%s[,showvolumebar])' % volume)
# Report playback
WINDOW.setProperty('commandUpdate', 'true')
else:
# GUI commands
if command == "ToggleFullscreen":
xbmc.executebuiltin('Action(FullScreen)')
elif command == "ToggleOsdMenu":
xbmc.executebuiltin('Action(OSD)')
elif command == "MoveUp":
xbmc.executebuiltin('Action(Up)')
elif command == "MoveDown":
xbmc.executebuiltin('Action(Down)')
elif command == "MoveLeft":
xbmc.executebuiltin('Action(Left)')
elif command == "MoveRight":
xbmc.executebuiltin('Action(Right)')
elif command == "Select":
xbmc.executebuiltin('Action(Select)')
elif command == "Back":
xbmc.executebuiltin('Action(back)')
elif command == "ToggleContextMenu":
xbmc.executebuiltin('Action(ContextMenu)')
elif command == "GoHome":
xbmc.executebuiltin('ActivateWindow(Home)')
elif command == "PageUp":
xbmc.executebuiltin('Action(PageUp)')
elif command == "NextLetter":
xbmc.executebuiltin('Action(NextLetter)')
elif command == "GoToSearch":
xbmc.executebuiltin('VideoLibrary.Search')
elif command == "GoToSettings":
xbmc.executebuiltin('ActivateWindow(Settings)')
elif command == "PageDown":
xbmc.executebuiltin('Action(PageDown)')
elif command == "PreviousLetter":
xbmc.executebuiltin('Action(PrevLetter)')
elif command == "TakeScreenshot":
xbmc.executebuiltin('TakeScreenshot')
elif command == "ToggleMute":
xbmc.executebuiltin('Mute')
elif command == "VolumeUp":
xbmc.executebuiltin('Action(VolumeUp)')
elif command == "VolumeDown":
xbmc.executebuiltin('Action(VolumeDown)')
elif command == "DisplayMessage":
header = arguments[u'Header']
text = arguments[u'Text']
xbmcgui.Dialog().notification(header, text)
elif command == "SendString":
string = arguments[u'String']
xbmcgui.Dialog().notification("Emby server", string)
else:
self.logMsg("Unknown command.", 1)
def remove_items(self, itemsRemoved): def remove_items(self, itemsRemoved):

View file

@ -98,6 +98,7 @@ class Service():
ws.start() ws.start()
if xbmc.Player().isPlaying(): if xbmc.Player().isPlaying():
WINDOW.setProperty("Emby_Service_Timestamp", str(int(time.time())))
try: try:
playTime = xbmc.Player().getTime() playTime = xbmc.Player().getTime()
totalTime = xbmc.Player().getTotalTime() totalTime = xbmc.Player().getTotalTime()
@ -131,6 +132,7 @@ class Service():
pass pass
else: else:
WINDOW.setProperty("Emby_Service_Timestamp", str(int(time.time())))
#full sync #full sync
if (startupComplete == False): if (startupComplete == False):
self.logMsg("Doing_Db_Sync: syncDatabase (Started)") self.logMsg("Doing_Db_Sync: syncDatabase (Started)")