def externalSubs(self, id, playurl, mediaSources): username = utils.window('currUser') server = utils.window('server%s' % username) externalsubs = [] mapping = {} mediaStream = mediaSources[0].get('MediaStreams') kodiindex = 0 for stream in mediaStream: index = stream['Index'] # Since Emby returns all possible tracks together, have to pull only external subtitles. # IsTextSubtitleStream if true, is available to download from emby. if "Subtitle" in stream['Type'] and stream['IsExternal'] and stream['IsTextSubtitleStream']: playmethod = utils.window("%splaymethod" % playurl) if "DirectPlay" in playmethod: # Direct play, get direct path url = PlayUtils().directPlay(stream) elif "DirectStream" in playmethod: # Direct stream url = "%s/Videos/%s/%s/Subtitles/%s/Stream.srt" % (server, id, id, index) # map external subtitles for mapping mapping[kodiindex] = index externalsubs.append(url) kodiindex += 1 mapping = json.dumps(mapping) utils.window('%sIndexMapping' % playurl, value=mapping) return externalsubs
def addPlaylistItem(self, playlist, item): id = item['Id'] username = utils.window('currUser') server = utils.window('server%s' % username) playurl = PlayUtils().getPlayUrl(server, id, item) if utils.window('playurlFalse') == "true": # Playurl failed - set in PlayUtils.py utils.window('playurlFalse', clear=True) self.logMsg( "Failed to retrieve the playback path/url or dialog was cancelled.", 1) return self.logMsg("Playurl: %s" % playurl) thumb = API().getArtwork(item, "Primary") listItem = xbmcgui.ListItem(path=playurl, iconImage=thumb, thumbnailImage=thumb) self.setListItemProps(server, id, listItem, item) self.setProperties(playurl, item, listItem) playlist.add(playurl, listItem)
def addPlaylistItem(self, playlist, item, server, userid): id = item.get("Id") playurl = PlayUtils().getPlayUrl(server, id, item) utils.logMsg("PlayBackUtils", "Play URL: " + playurl) thumbPath = API().getArtwork(item, "Primary") listItem = xbmcgui.ListItem(path=playurl, iconImage=thumbPath, thumbnailImage=thumbPath) self.setListItemProps(server, id, listItem, item) WINDOW = xbmcgui.Window(10000) username = WINDOW.getProperty('currUser') userid = WINDOW.getProperty('userId%s' % username) server = WINDOW.getProperty('server%s' % username) # Can not play virtual items if (item.get("LocationType") == "Virtual") or (item.get("IsPlaceHolder") == True): xbmcgui.Dialog().ok(self.language(30128), self.language(30129)) return False else: watchedurl = "%s/mediabrowser/Users/%s/PlayedItems/%s" % (server, userid, id) positionurl = "%s/mediabrowser/Users/%s/PlayingItems/%s" % (server, userid, id) deleteurl = "%s/mediabrowser/Items/%s" % (server, id) # set the current playing info WINDOW = xbmcgui.Window( 10000 ) WINDOW.setProperty(playurl + "watchedurl", watchedurl) WINDOW.setProperty(playurl + "positionurl", positionurl) WINDOW.setProperty(playurl + "deleteurl", "") if item.get("Type") == "Episode" and addon.getSetting("offerDelete")=="true": WINDOW.setProperty(playurl + "deleteurl", deleteurl) WINDOW.setProperty(playurl + "runtimeticks", str(item.get("RunTimeTicks"))) WINDOW.setProperty(playurl+"type", item.get("Type")) WINDOW.setProperty(playurl + "item_id", id) if (item.get("Type") == "Episode"): WINDOW.setProperty(playurl + "refresh_id", item.get("SeriesId")) else: WINDOW.setProperty(playurl + "refresh_id", id) utils.logMsg("PlayBackUtils", "PlayList Item Url : " + str(playurl)) playlist.add(playurl, listItem) return True
def PLAY(self, result, setup="service"): xbmc.log("PLAY Called") WINDOW = xbmcgui.Window(10000) username = WINDOW.getProperty('currUser') userid = WINDOW.getProperty('userId%s' % username) server = WINDOW.getProperty('server%s' % username) try: id = result["Id"] except: return userData = result['UserData'] # BOOKMARK - RESUME POINT timeInfo = API().getTimeInfo(result) jumpBackSec = int(utils.settings("resumeJumpBack")) seekTime = round(float(timeInfo.get('ResumeTime')), 6) if seekTime > jumpBackSec: # To avoid negative bookmark seekTime = seekTime - jumpBackSec itemsToPlay = [] # Check for intros if seekTime == 0: # if we have any play them when the movie/show is not being resumed # We can add the option right here url = "{server}/mediabrowser/Users/{UserId}/Items/%s/Intros?format=json&ImageTypeLimit=1&Fields=Etag" % id intros = self.downloadUtils.downloadUrl(url) if intros[u'TotalRecordCount'] == 0: pass else: for intro in intros[u'Items']: introId = intro[u'Id'] itemsToPlay.append(introId) # Add original item itemsToPlay.append(id) # For split movies if u'PartCount' in result: partcount = result[u'PartCount'] # Get additional parts/playurl url = "{server}/mediabrowser/Videos/%s/AdditionalParts" % id parts = self.downloadUtils.downloadUrl(url) for part in parts[u'Items']: partId = part[u'Id'] itemsToPlay.append(partId) if len(itemsToPlay) > 1: # Let's play the playlist return self.AddToPlaylist(itemsToPlay) playurl = PlayUtils().getPlayUrl(server, id, result) if playurl == False or WINDOW.getProperty('playurlFalse') == "true": WINDOW.clearProperty('playurlFalse') xbmc.log("Failed to retrieve the playback path/url.") return if WINDOW.getProperty("%splaymethod" % playurl) == "Transcode": # Transcoding, we pull every track to set before playback starts playurlprefs = self.audioSubsPref(playurl, result.get("MediaSources")) if playurlprefs: playurl = playurlprefs else: # User cancelled dialog return thumbPath = API().getArtwork(result, "Primary") #if the file is a virtual strm file, we need to override the path by reading it's contents if playurl.endswith(".strm"): xbmc.log("virtual strm file file detected, starting playback with 3th party addon...") StrmTemp = "special://temp/temp.strm" xbmcvfs.copy(playurl, StrmTemp) playurl = open(xbmc.translatePath(StrmTemp), 'r').readline() listItem = xbmcgui.ListItem(path=playurl, iconImage=thumbPath, thumbnailImage=thumbPath) if WINDOW.getProperty("%splaymethod" % playurl) != "Transcode": # Only for direct play and direct stream # Append external subtitles to stream subtitleList = self.externalSubs(id, playurl, server, result.get('MediaSources')) listItem.setSubtitles(subtitleList) #pass # Can not play virtual items if (result.get("LocationType") == "Virtual"): xbmcgui.Dialog().ok(self.language(30128), self.language(30129)) watchedurl = "%s/mediabrowser/Users/%s/PlayedItems/%s" % (server, userid, id) positionurl = "%s/mediabrowser/Users/%s/PlayingItems/%s" % (server, userid, id) deleteurl = "%s/mediabrowser/Items/%s" % (server, id) # set the current playing info WINDOW.setProperty(playurl+"watchedurl", watchedurl) WINDOW.setProperty(playurl+"positionurl", positionurl) WINDOW.setProperty(playurl+"deleteurl", "") WINDOW.setProperty(playurl+"deleteurl", deleteurl) #show the additional resume dialog if launched from a widget if xbmc.getCondVisibility("Window.IsActive(home)"): if seekTime != 0: displayTime = str(datetime.timedelta(seconds=(int(seekTime)))) display_list = [ self.language(30106) + ' ' + displayTime, self.language(30107)] resumeScreen = xbmcgui.Dialog() resume_result = resumeScreen.select(self.language(30105), display_list) if resume_result == 0: listItem.setProperty('StartOffset', str(seekTime)) elif resume_result < 0: # User cancelled dialog xbmc.log("Emby player -> User cancelled resume dialog.") xbmcplugin.setResolvedUrl(int(sys.argv[1]), False, listItem) return if result.get("Type")=="Episode": WINDOW.setProperty(playurl+"refresh_id", result.get("SeriesId")) else: WINDOW.setProperty(playurl+"refresh_id", id) WINDOW.setProperty(playurl+"runtimeticks", str(result.get("RunTimeTicks"))) WINDOW.setProperty(playurl+"type", result.get("Type")) WINDOW.setProperty(playurl+"item_id", id) #launch the playback - only set the listitem props if we're not using the setresolvedurl approach if setup == "service": self.setListItemProps(server, id, listItem, result) xbmc.Player().play(playurl,listItem) elif setup == "default": if xbmc.getCondVisibility("Window.IsActive(home)"): self.setListItemProps(server, id, listItem, result) xbmc.Player().play(playurl,listItem) else: xbmcplugin.setResolvedUrl(int(sys.argv[1]), True, listItem)
def PLAY(self, id): xbmc.log("PLAY Called") port = addon.getSetting('port') host = addon.getSetting('ipaddress') server = host + ":" + port userid = self.downloadUtils.getUserId() jsonData = self.downloadUtils.downloadUrl("http://" + server + "/mediabrowser/Users/" + userid + "/Items/" + id + "?format=json&ImageTypeLimit=1", suppress=False, popup=1 ) result = json.loads(jsonData) userData = result.get("UserData") resume_result = 0 seekTime = 0 #get the resume point from Kodi DB for a Movie kodiItem = ReadKodiDB().getKodiMovie(id) if kodiItem != None: seekTime = int(round(kodiItem['resume'].get("position"))) else: #get the resume point from Kodi DB for an episode episodeItem = ReadEmbyDB().getItem(id) if episodeItem != None and str(episodeItem["Type"]) == "Episode": kodiItem = ReadKodiDB().getKodiEpisodeByMbItem(id,episodeItem["SeriesId"]) if kodiItem != None: seekTime = int(round(kodiItem['resume'].get("position"))) playurl = PlayUtils().getPlayUrl(server, id, result) isStrmFile = False thumbPath = API().getArtwork(result, "Primary") #workaround for when the file to play is a strm file itself if playurl.endswith(".strm"): isStrmFile = True tempPath = os.path.join(addondir,"library","temp.strm") xbmcvfs.copy(playurl, tempPath) sfile = open(tempPath, 'r') playurl = sfile.readline() sfile.close() xbmcvfs.delete(tempPath) WINDOW.setProperty("virtualstrm", id) WINDOW.setProperty("virtualstrmtype", result.get("Type")) listItem = xbmcgui.ListItem(path=playurl, iconImage=thumbPath, thumbnailImage=thumbPath) self.setListItemProps(server, id, listItem, result) # Can not play virtual items if (result.get("LocationType") == "Virtual"): xbmcgui.Dialog().ok(self.language(30128), self.language(30129)) watchedurl = 'http://' + server + '/mediabrowser/Users/'+ userid + '/PlayedItems/' + id positionurl = 'http://' + server + '/mediabrowser/Users/'+ userid + '/PlayingItems/' + id deleteurl = 'http://' + server + '/mediabrowser/Items/' + id # set the current playing info WINDOW.setProperty(playurl+"watchedurl", watchedurl) WINDOW.setProperty(playurl+"positionurl", positionurl) WINDOW.setProperty(playurl+"deleteurl", "") WINDOW.setProperty(playurl+"deleteurl", deleteurl) if seekTime != 0: displayTime = str(datetime.timedelta(seconds=seekTime)) display_list = [ self.language(30106) + ' ' + displayTime, self.language(30107)] resumeScreen = xbmcgui.Dialog() resume_result = resumeScreen.select(self.language(30105), display_list) if resume_result == 0: WINDOW.setProperty(playurl+"seektime", str(seekTime)) else: WINDOW.clearProperty(playurl+"seektime") else: WINDOW.clearProperty(playurl+"seektime") if result.get("Type")=="Episode": WINDOW.setProperty(playurl+"refresh_id", result.get("SeriesId")) else: WINDOW.setProperty(playurl+"refresh_id", id) WINDOW.setProperty(playurl+"runtimeticks", str(result.get("RunTimeTicks"))) WINDOW.setProperty(playurl+"type", result.get("Type")) WINDOW.setProperty(playurl+"item_id", id) if PlayUtils().isDirectPlay(result) == True: playMethod = "DirectPlay" else: playMethod = "Transcode" WINDOW.setProperty(playurl+"playmethod", playMethod) mediaSources = result.get("MediaSources") if(mediaSources != None): if mediaSources[0].get('DefaultAudioStreamIndex') != None: WINDOW.setProperty(playurl+"AudioStreamIndex", str(mediaSources[0].get('DefaultAudioStreamIndex'))) if mediaSources[0].get('DefaultSubtitleStreamIndex') != None: WINDOW.setProperty(playurl+"SubtitleStreamIndex", str(mediaSources[0].get('DefaultSubtitleStreamIndex'))) #this launches the playback #artwork only works with both resolvedurl and player command if isStrmFile: xbmcplugin.setResolvedUrl(int(sys.argv[1]), True, listItem) else: xbmcplugin.setResolvedUrl(int(sys.argv[1]), True, listItem) if(addon.getSetting("addExtraPlaybackArt") == "true"): utils.logMsg("PLAY", "Doing second xbmc.Player().play to add extra art") xbmc.Player().play(playurl,listItem)
def PLAY(self, result, setup="service"): self.logMsg("PLAY Called", 1) api = self.api doUtils = self.doUtils username = utils.window('currUser') server = utils.window('server%s' % username) id = result['Id'] userdata = result['UserData'] # Get the playurl - direct play, direct stream or transcoding playurl = PlayUtils().getPlayUrl(server, id, result) listItem = xbmcgui.ListItem() if utils.window('playurlFalse') == "true": # Playurl failed - set in PlayUtils.py utils.window('playurlFalse', clear=True) self.logMsg( "Failed to retrieve the playback path/url or dialog was cancelled.", 1) return xbmcplugin.setResolvedUrl(int(sys.argv[1]), False, listItem) ############### -- SETUP MAIN ITEM ################ # Set listitem and properties for main item self.logMsg("Returned playurl: %s" % playurl, 1) listItem.setPath(playurl) self.setProperties(playurl, result, listItem) mainArt = API().getArtwork(result, "Primary") listItem.setThumbnailImage(mainArt) listItem.setIconImage(mainArt) ############### ORGANIZE CURRENT PLAYLIST ################ homeScreen = xbmc.getCondVisibility('Window.IsActive(home)') playlist = xbmc.PlayList(xbmc.PLAYLIST_VIDEO) startPos = max(playlist.getposition(), 0) # Can return -1 sizePlaylist = playlist.size() propertiesPlayback = utils.window('propertiesPlayback') == "true" introsPlaylist = False dummyPlaylist = False currentPosition = startPos self.logMsg("Playlist start position: %s" % startPos, 2) self.logMsg("Playlist plugin position: %s" % currentPosition, 2) self.logMsg("Playlist size: %s" % sizePlaylist, 2) ############### RESUME POINT ################ # Resume point for widget only timeInfo = api.getTimeInfo(result) jumpBackSec = int(utils.settings('resumeJumpBack')) seekTime = round(float(timeInfo.get('ResumeTime')), 6) if seekTime > jumpBackSec: # To avoid negative bookmark seekTime = seekTime - jumpBackSec # Show the additional resume dialog if launched from a widget if homeScreen and seekTime: # Dialog presentation displayTime = str(datetime.timedelta(seconds=(int(seekTime)))) display_list = [ "%s %s" % (self.language(30106), displayTime), self.language(30107) ] resume_result = xbmcgui.Dialog().select(self.language(30105), display_list) if resume_result == 0: # User selected to resume, append resume point to listitem listItem.setProperty('StartOffset', str(seekTime)) elif resume_result > 0: # User selected to start from beginning seekTime = 0 else: # User cancelled the dialog self.logMsg("User cancelled resume dialog.", 1) return xbmcplugin.setResolvedUrl(int(sys.argv[1]), False, listItem) # We need to ensure we add the intro and additional parts only once. # Otherwise we get a loop. if not propertiesPlayback: utils.window('propertiesPlayback', value="true") self.logMsg("Setting up properties in playlist.") ############### -- CHECK FOR INTROS ################ if utils.settings('disableCinema') == "false" and not seekTime: # if we have any play them when the movie/show is not being resumed url = "{server}/mediabrowser/Users/{UserId}/Items/%s/Intros?format=json&ImageTypeLimit=1&Fields=Etag" % id intros = doUtils.downloadUrl(url) if intros['TotalRecordCount'] != 0: getTrailers = True if utils.settings('askCinema') == "true": resp = xbmcgui.Dialog().yesno("Emby Cinema Mode", "Play trailers?") if not resp: # User selected to not play trailers getTrailers = False self.logMsg("Skip trailers.", 1) if getTrailers: for intro in intros['Items']: # The server randomly returns intros, process them. introId = intro['Id'] introPlayurl = PlayUtils().getPlayUrl( server, introId, intro) introListItem = xbmcgui.ListItem() self.logMsg("Adding Intro: %s" % introPlayurl, 1) # Set listitem and properties for intros self.setProperties(introPlayurl, intro, introListItem) self.setListItemProps(server, introId, introListItem, intro) playlist.add(introPlayurl, introListItem, index=currentPosition) introsPlaylist = True currentPosition += 1 ############### -- ADD MAIN ITEM ONLY FOR HOMESCREEN ############### if homeScreen and not sizePlaylist: # Extend our current playlist with the actual item to play only if there's no playlist first self.logMsg("Adding main item to playlist.", 1) self.setListItemProps(server, id, listItem, result) playlist.add(playurl, listItem, index=currentPosition) # Ensure that additional parts are played after the main item currentPosition += 1 ############### -- CHECK FOR ADDITIONAL PARTS ################ if result.get('PartCount'): # Only add to the playlist after intros have played partcount = result['PartCount'] url = "{server}/mediabrowser/Videos/%s/AdditionalParts" % id parts = doUtils.downloadUrl(url) for part in parts['Items']: partId = part['Id'] additionalPlayurl = PlayUtils().getPlayUrl( server, partId, part) additionalListItem = xbmcgui.ListItem() self.logMsg("Adding additional part: %s" % partcount, 1) # Set listitem and properties for each additional parts self.setProperties(additionalPlayurl, part, additionalListItem) self.setListItemProps(server, partId, additionalListItem, part) playlist.add(additionalPlayurl, additionalListItem, index=currentPosition) currentPosition += 1 ############### ADD DUMMY TO PLAYLIST ################# if (not homeScreen and introsPlaylist) or (homeScreen and sizePlaylist > 0): # Playlist will fail on the current position. Adding dummy url dummyPlaylist = True self.logMsg( "Adding dummy url to counter the setResolvedUrl error.", 2) playlist.add(playurl, index=startPos) currentPosition += 1 # We just skipped adding properties. Reset flag for next time. elif propertiesPlayback: self.logMsg("Resetting properties playback flag.", 2) utils.window('propertiesPlayback', clear=True) self.verifyPlaylist() ############### PLAYBACK ################ if not homeScreen and not introsPlaylist: self.logMsg("Processed as a single item.", 1) xbmcplugin.setResolvedUrl(int(sys.argv[1]), True, listItem) elif dummyPlaylist: # Added a dummy file to the playlist because the first item is going to fail automatically. self.logMsg("Processed as a playlist. First item is skipped.", 1) xbmcplugin.setResolvedUrl(int(sys.argv[1]), False, listItem) else: self.logMsg("Play as a regular item.", 1) xbmc.Player().play(playlist, startpos=startPos)
def addOrUpdateSongToKodiLibrary(self, MBitem, connection, cursor): kodiVersion = self.kodiversion embyId = MBitem["Id"] # If the item already exist in the local Kodi DB we'll perform a full item update # If the item doesn't exist, we'll add it to the database cursor.execute("SELECT kodi_id FROM emby WHERE emby_id = ?", (embyId,)) try: songid = cursor.fetchone()[0] except: songid = None timeInfo = API().getTimeInfo(MBitem) userData = API().getUserData(MBitem) genres = MBitem.get('Genres') ##### The song details ##### playcount = userData.get('PlayCount') lastplayed = userData.get('LastPlayedDate') dateadded = API().getDateCreated(MBitem) checksum = API().getChecksum(MBitem) name = MBitem['Name'] musicBrainzId = API().getProvider(MBitem, "musicBrainzTrackId") genre = " / ".join(genres) artists = " / ".join(MBitem.get('Artists')) tracknumber = MBitem.get('IndexNumber', 0) disc = MBitem.get('ParentIndexNumber', 1) track = disc*2**16 + tracknumber year = MBitem.get('ProductionYear') bio = API().getOverview(MBitem) duration = timeInfo.get('TotalTime') if utils.settings('directstreammusic') == "true": WINDOW = xbmcgui.Window(10000) username = WINDOW.getProperty('currUser') server = WINDOW.getProperty('server%s' % username) playurl = PlayUtils().directStream(MBitem, server, embyId, "Audio") filename = "stream.mp3" path = playurl.replace(filename, "") else: # Get the path and filename playurl = PlayUtils().directPlay(MBitem) path, filename = ntsplit(playurl) if "/" in playurl: path = "%s/" % path elif "\\" in playurl: path = "%s\\" % path # Validate the path in database cursor.execute("SELECT idPath as pathid FROM path WHERE strPath = ?", (path,)) try: pathid = cursor.fetchone()[0] except: cursor.execute("select coalesce(max(idPath),0) as pathid from path") pathid = cursor.fetchone()[0] + 1 query = "INSERT INTO path(idPath, strPath) values(?, ?)" cursor.execute(query, (pathid, path)) # Get the album cursor.execute("SELECT kodi_id FROM emby WHERE emby_id = ?", (MBitem.get("AlbumId"),)) try: albumid = cursor.fetchone()[0] except: # No album found, create a single's album cursor.execute("select coalesce(max(idAlbum),0) as albumid from album") albumid = cursor.fetchone()[0] + 1 if kodiVersion == 15: # Kodi Isengard query = "INSERT INTO album(idAlbum, strGenres, iYear, dateAdded, strReleaseType) values(?, ?, ?, ?, ?)" cursor.execute(query, (albumid, genre, year, dateadded, "single")) elif kodiVersion == 16: query = "INSERT INTO album(idAlbum, strGenres, iYear, strReleaseType) values(?, ?, ?, ?)" cursor.execute(query, (albumid, genre, year, "single")) else: # Kodi Gotham and Helix query = "INSERT INTO album(idAlbum, strGenres, iYear, dateAdded) values(?, ?, ?, ?)" cursor.execute(query, (albumid, genre, year, dateadded)) finally: cursor.execute("SELECT strArtists FROM album WHERE idAlbum = ?", (albumid,)) result = cursor.fetchone() if result and result[0] == "": # Link album to artists if MBitem['AlbumArtists']: album_artists = MBitem['AlbumArtists'] else: album_artists = MBitem['ArtistItems'] MBartists = [] for artist in album_artists: MBartists.append(artist['Name']) cursor.execute("SELECT kodi_id FROM emby WHERE emby_id = ?", (artist['Id'],)) try: artistid = cursor.fetchone()[0] except: pass else: query = "INSERT OR REPLACE INTO album_artist(idArtist, idAlbum, strArtist) values(?, ?, ?)" cursor.execute(query, (artistid, albumid, artist['Name'])) artists_onalbum = " / ".join(MBartists) if kodiVersion == 15: # Kodi Isengard query = "UPDATE album SET strArtists = ? WHERE idAlbum = ?" cursor.execute(query, (artists_onalbum, albumid)) elif kodiVersion == 16: query = "UPDATE album SET strArtists = ? WHERE idAlbum = ?" cursor.execute(query, (artists_onalbum, albumid)) else: # Kodi Gotham and Helix query = "UPDATE album SET strArtists = ? WHERE idAlbum = ?" cursor.execute(query, (artists_onalbum, albumid)) ##### UPDATE THE SONG ##### if songid: self.logMsg("UPDATE song to Kodi library, Id: %s - Title: %s" % (embyId, name), 1) query = "UPDATE song SET idAlbum = ?, strArtists = ?, strGenres = ?, strTitle = ?, iTrack = ?, iDuration = ?, iYear = ?, strFilename = ?, strMusicBrainzTrackID = ?, iTimesPlayed = ?, lastplayed = ? WHERE idSong = ?" cursor.execute(query, (albumid, artists, genre, name, track, duration, year, filename, musicBrainzId, playcount, lastplayed, songid)) # Update the checksum in emby table query = "UPDATE emby SET checksum = ? WHERE emby_id = ?" cursor.execute(query, (checksum, embyId)) ##### OR ADD THE SONG ##### else: self.logMsg("ADD song to Kodi library, Id: %s - Title: %s" % (embyId, name), 1) # Create the song cursor.execute("select coalesce(max(idSong),0) as songid from song") songid = cursor.fetchone()[0] + 1 query = "INSERT INTO song(idSong, idAlbum, idPath, strArtists, strGenres, strTitle, iTrack, iDuration, iYear, strFileName, strMusicBrainzTrackID, iTimesPlayed, lastplayed) values(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)" cursor.execute(query, (songid, albumid, pathid, artists, genre, name, track, duration, year, filename, musicBrainzId, playcount, lastplayed)) # Create the reference in emby table query = "INSERT INTO emby(emby_id, kodi_id, media_type, checksum) values(?, ?, ?, ?)" cursor.execute(query, (embyId, songid, "song", checksum)) # Add genres self.AddGenresToMedia(songid, genres, "song", cursor) # Link song to album if albumid: query = "INSERT OR REPLACE INTO albuminfosong(idAlbumInfoSong, idAlbumInfo, iTrack, strTitle, iDuration) values(?, ?, ?, ?, ?)" cursor.execute(query, (songid, albumid, track, name, duration)) # Link song to artist for artist in MBitem.get('ArtistItems'): cursor.execute("SELECT kodi_id FROM emby WHERE emby_id = ?", (artist['Id'],)) try: artistid = cursor.fetchone()[0] except: pass else: query = "INSERT OR REPLACE INTO song_artist(idArtist, idSong, strArtist) values(?, ?, ?)" cursor.execute(query, (artistid, songid, artist['Name'])) # Update artwork self.textureCache.addArtwork(API().getAllArtwork(MBitem, parentInfo=True), songid, "song", cursor)
def onNotification(self, sender, method, data): addon = xbmcaddon.Addon(id='plugin.video.emby') downloadUtils = DownloadUtils() print "onNotification:" + method + ":" + sender + ":" + str(data) #player started playing an item - if method == "Player.OnPlay": print "playlist onadd is called" jsondata = json.loads(data) if jsondata != None: if jsondata.has_key("item"): if jsondata.get("item").has_key("id") and jsondata.get( "item").has_key("type"): id = jsondata.get("item").get("id") type = jsondata.get("item").get("type") embyid = ReadKodiDB().getEmbyIdByKodiId(id, type) if embyid != None: WINDOW = xbmcgui.Window(10000) username = WINDOW.getProperty('currUser') userid = WINDOW.getProperty('userId%s' % username) server = WINDOW.getProperty('server%s' % username) url = "{server}/mediabrowser/Users/{UserId}/Items/%s?format=json&ImageTypeLimit=1" % embyid result = downloadUtils.downloadUrl(url) userData = result[u'UserData'] playurl = PlayUtils().getPlayUrl( server, embyid, result) watchedurl = "%s/mediabrowser/Users/%s/PlayedItems/%s" % ( server, userid, embyid) positionurl = "%s/mediabrowser/Users/%s/PlayingItems/%s" % ( server, userid, embyid) deleteurl = "%s/mediabrowser/Items/%s" % (server, embyid) # set the current playing info WINDOW.setProperty(playurl + "watchedurl", watchedurl) WINDOW.setProperty(playurl + "positionurl", positionurl) WINDOW.setProperty(playurl + "deleteurl", "") WINDOW.setProperty(playurl + "deleteurl", deleteurl) if result[u'Type'] == "Episode": WINDOW.setProperty(playurl + "refresh_id", result[u'SeriesId']) else: WINDOW.setProperty(playurl + "refresh_id", embyid) WINDOW.setProperty(playurl + "runtimeticks", str(result[u'RunTimeTicks'])) WINDOW.setProperty(playurl + "type", result[u'Type']) WINDOW.setProperty(playurl + "item_id", embyid) if PlayUtils().isDirectPlay(result) == True: playMethod = "DirectPlay" else: playMethod = "Transcode" WINDOW.setProperty(playurl + "playmethod", playMethod) mediaSources = result[u'MediaSources'] if (mediaSources != None): if mediaSources[0].get( 'DefaultAudioStreamIndex') != None: WINDOW.setProperty( playurl + "AudioStreamIndex", str(mediaSources[0] [u'DefaultAudioStreamIndex'])) if mediaSources[0].get( 'DefaultSubtitleStreamIndex') != None: WINDOW.setProperty( playurl + "SubtitleStreamIndex", str(mediaSources[0] [u'DefaultSubtitleStreamIndex'])) if method == "VideoLibrary.OnUpdate": jsondata = json.loads(data) if jsondata != None: playcount = None playcount = jsondata.get("playcount") item = jsondata.get("item").get("id") type = jsondata.get("item").get("type") if playcount != None: utils.logMsg( "MB# Sync", "Kodi_Monitor--> VideoLibrary.OnUpdate : " + str(data), 2) WriteKodiDB().updatePlayCountFromKodi( item, type, playcount)
def PLAY(self, result, setup = "service"): self.logMsg("PLAY Called", 1) api = self.api doUtils = self.doUtils username = utils.window('currUser') server = utils.window('server%s' % username) id = result['Id'] userdata = result['UserData'] # Get the playurl - direct play, direct stream or transcoding playurl = PlayUtils().getPlayUrl(server, id, result) listItem = xbmcgui.ListItem() if utils.window('playurlFalse') == "true": # Playurl failed - set in PlayUtils.py utils.window('playurlFalse', clear=True) self.logMsg("Failed to retrieve the playback path/url or dialog was cancelled.", 1) return xbmcplugin.setResolvedUrl(int(sys.argv[1]), False, listItem) ############### RESUME POINT ################ # Resume point for widget only timeInfo = api.getTimeInfo(result) jumpBackSec = int(utils.settings('resumeJumpBack')) seekTime = round(float(timeInfo.get('ResumeTime')), 6) if seekTime > jumpBackSec: # To avoid negative bookmark seekTime = seekTime - jumpBackSec # Show the additional resume dialog if launched from a widget if xbmc.getCondVisibility('Window.IsActive(home)') and seekTime: # Dialog presentation displayTime = str(datetime.timedelta(seconds=(int(seekTime)))) display_list = ["%s %s" % (self.language(30106), displayTime), self.language(30107)] resume_result = xbmcgui.Dialog().select(self.language(30105), display_list) if resume_result == 0: # User selected to resume, append resume point to listitem listItem.setProperty('StartOffset', str(seekTime)) elif resume_result > 0: # User selected to start from beginning seekTime = 0 else: # User cancelled the dialog self.logMsg("User cancelled resume dialog.", 1) return xbmcplugin.setResolvedUrl(int(sys.argv[1]), False, listItem) ############### ORGANIZE CURRENT PLAYLIST ################ # In order, intros, original item requested and any additional part playlist = xbmc.PlayList(xbmc.PLAYLIST_VIDEO) startPos = max(playlist.getposition(), 0) # Can return -1 sizePlaylist = playlist.size() currentPosition = startPos self.logMsg("Playlist start position: %s" % startPos, 2) self.logMsg("Playlist current position: %s" % currentPosition, 2) self.logMsg("Playlist size: %s" % sizePlaylist, 2) # Properties to ensure we have have proper playlists with additional items. introsPlaylist = False introProperty = utils.window('PlaylistIntroSet') == "true" dummyProperty = utils.window('PlaylistsetDummy') == "true" additionalProperty = utils.window('PlaylistAdditional') == "true" ############### -- CHECK FOR INTROS ################ if utils.settings('disableCinema') == "false" and not introProperty and not seekTime: # if we have any play them when the movie/show is not being resumed url = "{server}/mediabrowser/Users/{UserId}/Items/%s/Intros?format=json&ImageTypeLimit=1&Fields=Etag" % id intros = doUtils.downloadUrl(url) if intros['TotalRecordCount'] != 0: # The server randomly returns one custom intro intro = intros['Items'][0] introId = intro['Id'] introListItem = xbmcgui.ListItem() introPlayurl = PlayUtils().getPlayUrl(server, introId, intro) self.logMsg("Intro play: %s" % introPlayurl, 1) self.setProperties(introPlayurl, intro, introListItem) self.setListItemProps(server, introId, introListItem, intro) introsPlaylist = True utils.window('PlaylistIntroSet', value="true") playlist.add(introPlayurl, introListItem, index=currentPosition) currentPosition += 1 elif introProperty: # Play main item, do not play the intro since we already played it. Reset property for next time. utils.window('PlaylistIntroSet', clear=True) self.logMsg("Clear intro property.", 2) ############### -- SETUP MAIN ITEM ################ ##### Set listitem and properties for main item self.logMsg("Returned playurl: %s" % playurl, 1) listItem.setPath(playurl) self.setProperties(playurl, result, listItem) mainArt = API().getArtwork(result, "Primary") listItem.setThumbnailImage(mainArt) listItem.setIconImage(mainArt) if introsPlaylist and not sizePlaylist: # Extend our current playlist with the actual item to play only if there's no playlist first self.logMsg("No playlist detected at the start. Creating playlist with intro and play item.", 1) self.logMsg("Playlist current position: %s" % (currentPosition), 1) playlist.add(playurl, listItem, index=currentPosition) currentPosition += 1 ############### -- CHECK FOR ADDITIONAL PARTS ################ if result.get('PartCount') and not additionalProperty: # Only add to the playlist after intros have played url = "{server}/mediabrowser/Videos/%s/AdditionalParts" % id parts = doUtils.downloadUrl(url) for part in parts['Items']: partId = part['Id'] additionalPlayurl = PlayUtils().getPlayUrl(server, partId, part) additionalListItem = xbmcgui.ListItem() # Set listitem and properties for each additional parts self.logMsg("Adding to playlist: %s position: %s" % (additionalPlayurl, currentPosition), 1) self.setProperties(additionalPlayurl, part, additionalListItem) self.setListItemProps(server, partId, additionalListItem, part) # Add item to playlist, after the main item utils.window('PlaylistAdditional', value="true") playlist.add(additionalPlayurl, additionalListItem, index=currentPosition+1) currentPosition += 1 elif additionalProperty: # Additional parts are already set, reset property for next time utils.window('PlaylistAdditional', clear=True) self.logMsg("Clear additional property", 2) ############### PLAYBACK ################ if setup == "service" or xbmc.getCondVisibility('Window.IsActive(home)'): # Sent via websocketclient.py or default.py but via widgets self.logMsg("Detecting playback happening via service.py or home menu.", 1) self.setListItemProps(server, id, listItem, result) playlistPlayer = False if introsPlaylist and not sizePlaylist: # Extend our current playlist with the actual item to play only if there's no playlist first playlistPlayer = True elif sizePlaylist > 0 and not dummyProperty: # Playlist will fail on the current position. Adding dummy url playlist.add(playurl, index=startPos) self.logMsg("Adding dummy path as replacement for position: %s" % startPos, 2) utils.window('PlaylistsetDummy', value="true") playlistPlayer = True elif dummyProperty: # Already failed, play the item as a single item utils.window('PlaylistsetDummy', clear=True) self.logMsg("Clear dummy property.", 2) if playlistPlayer: self.logMsg("Processed as a playlist.", 1) return xbmc.Player().play(playlist) else: self.logMsg("Processed as a single item.", 1) return xbmc.Player().play(playurl, listItem) elif setup == "default": self.logMsg("Detecting playback happening via default.py.", 1) playlistPlayer = False if sizePlaylist > 0 and not dummyProperty: # Playlist will fail on the current position. Adding dummy url playlist.add(playurl, index=startPos) self.logMsg("Adding dummy path as replacement for position: %s" % startPos, 2) utils.window('PlaylistsetDummy', value="true") playlistPlayer = True elif dummyProperty: # Already failed, play the item as a single item utils.window('PlaylistsetDummy', clear=True) self.logMsg("Clear dummy property.", 2) if playlistPlayer: self.logMsg("Processed as a playlist.", 1) return xbmc.Player().play(playlist, startpos=startPos) else: # Sent via default.py self.logMsg("Processed as a single item.", 1) return xbmcplugin.setResolvedUrl(int(sys.argv[1]), True, listItem)
def PLAY(self, id): xbmc.log("PLAY Called") WINDOW = xbmcgui.Window(10000) username = WINDOW.getProperty('currUser') userid = WINDOW.getProperty('userId%s' % username) server = WINDOW.getProperty('server%s' % username) url = "{server}/mediabrowser/Users/{UserId}/Items/%s?format=json&ImageTypeLimit=1" % id result = self.downloadUtils.downloadUrl(url) userData = result[u'UserData'] resume_result = 0 seekTime = 0 #get the resume point from Kodi DB for a Movie kodiItem = ReadKodiDB().getKodiMovie(id) if kodiItem != None: seekTime = int(round(kodiItem['resume'].get("position"))) else: #get the resume point from Kodi DB for an episode episodeItem = ReadEmbyDB().getItem(id) if episodeItem != None and str(episodeItem["Type"]) == "Episode": kodiItem = ReadKodiDB().getKodiEpisodeByMbItem(id,episodeItem["SeriesId"]) if kodiItem != None: seekTime = int(round(kodiItem['resume'].get("position"))) playurl = PlayUtils().getPlayUrl(server, id, result) isStrmFile = False thumbPath = API().getArtwork(result, "Primary") #workaround for when the file to play is a strm file itself if playurl.endswith(".strm"): isStrmFile = True tempPath = os.path.join(addondir,"library","temp.strm") xbmcvfs.copy(playurl, tempPath) sfile = open(tempPath, 'r') playurl = sfile.readline() sfile.close() xbmcvfs.delete(tempPath) WINDOW.setProperty("virtualstrm", id) WINDOW.setProperty("virtualstrmtype", result.get("Type")) listItem = xbmcgui.ListItem(path=playurl, iconImage=thumbPath, thumbnailImage=thumbPath) self.setListItemProps(server, id, listItem, result) # Can not play virtual items if (result.get("LocationType") == "Virtual"): xbmcgui.Dialog().ok(self.language(30128), self.language(30129)) watchedurl = "%s/mediabrowser/Users/%s/PlayedItems/%s" % (server, userid, id) positionurl = "%s/mediabrowser/Users/%s/PlayingItems/%s" % (server, userid, id) deleteurl = "%s/mediabrowser/Items/%s" % (server, id) # set the current playing info WINDOW.setProperty(playurl+"watchedurl", watchedurl) WINDOW.setProperty(playurl+"positionurl", positionurl) WINDOW.setProperty(playurl+"deleteurl", "") WINDOW.setProperty(playurl+"deleteurl", deleteurl) if seekTime != 0: displayTime = str(datetime.timedelta(seconds=seekTime)) display_list = [ self.language(30106) + ' ' + displayTime, self.language(30107)] resumeScreen = xbmcgui.Dialog() resume_result = resumeScreen.select(self.language(30105), display_list) if resume_result == 0: WINDOW.setProperty(playurl+"seektime", str(seekTime)) else: WINDOW.clearProperty(playurl+"seektime") else: WINDOW.clearProperty(playurl+"seektime") if result.get("Type")=="Episode": WINDOW.setProperty(playurl+"refresh_id", result.get("SeriesId")) else: WINDOW.setProperty(playurl+"refresh_id", id) WINDOW.setProperty(playurl+"runtimeticks", str(result.get("RunTimeTicks"))) WINDOW.setProperty(playurl+"type", result.get("Type")) WINDOW.setProperty(playurl+"item_id", id) if PlayUtils().isDirectPlay(result) == True: playMethod = "DirectPlay" else: playMethod = "Transcode" WINDOW.setProperty(playurl+"playmethod", playMethod) mediaSources = result.get("MediaSources") if(mediaSources != None): if mediaSources[0].get('DefaultAudioStreamIndex') != None: WINDOW.setProperty(playurl+"AudioStreamIndex", str(mediaSources[0].get('DefaultAudioStreamIndex'))) if mediaSources[0].get('DefaultSubtitleStreamIndex') != None: WINDOW.setProperty(playurl+"SubtitleStreamIndex", str(mediaSources[0].get('DefaultSubtitleStreamIndex'))) #this launches the playback #artwork only works with both resolvedurl and player command if isStrmFile: xbmcplugin.setResolvedUrl(int(sys.argv[1]), True, listItem) else: xbmcplugin.setResolvedUrl(int(sys.argv[1]), True, listItem) if(addon.getSetting("addExtraPlaybackArt") == "true"): utils.logMsg("PLAY", "Doing second xbmc.Player().play to add extra art") xbmc.Player().play(playurl,listItem)
def setListItemProps(self, server, id, listItem, result): # set up item and item info thumbID = id eppNum = -1 seasonNum = -1 tvshowTitle = "" if(result.get("Type") == "Episode"): thumbID = result.get("SeriesId") seasonNum = result.get("ParentIndexNumber") eppNum = result.get("IndexNumber") tvshowTitle = result.get("SeriesName") self.setArt(listItem,'poster', API().getArtwork(result, "Primary")) self.setArt(listItem,'tvshow.poster', API().getArtwork(result, "SeriesPrimary")) self.setArt(listItem,'clearart', API().getArtwork(result, "Art")) self.setArt(listItem,'tvshow.clearart', API().getArtwork(result, "Art")) self.setArt(listItem,'clearlogo', API().getArtwork(result, "Logo")) self.setArt(listItem,'tvshow.clearlogo', API().getArtwork(result, "Logo")) self.setArt(listItem,'discart', API().getArtwork(result, "Disc")) self.setArt(listItem,'fanart_image', API().getArtwork(result, "Backdrop")) self.setArt(listItem,'landscape', API().getArtwork(result, "Thumb")) listItem.setProperty('IsPlayable', 'true') listItem.setProperty('IsFolder', 'false') # Process Studios studios = API().getStudios(result) if studios == []: studio = "" else: studio = studios[0] listItem.setInfo('video', {'studio' : studio}) # play info playinformation = '' if PlayUtils().isDirectPlay(result) == True: playinformation = self.language(30165) else: playinformation = self.language(30166) details = { 'title' : result.get("Name", "Missing Name") + ' - ' + playinformation, 'plot' : result.get("Overview") } if(eppNum > -1): details["episode"] = str(eppNum) if(seasonNum > -1): details["season"] = str(seasonNum) if tvshowTitle != None: details["TVShowTitle"] = tvshowTitle listItem.setInfo( "Video", infoLabels=details ) people = API().getPeople(result) # Process Genres genre = API().getGenre(result) listItem.setInfo('video', {'director' : people.get('Director')}) listItem.setInfo('video', {'writer' : people.get('Writer')}) listItem.setInfo('video', {'mpaa': result.get("OfficialRating")}) listItem.setInfo('video', {'genre': genre})
def getThemeMedia(): doUtils = DownloadUtils() playUtils = PlayUtils() currUser = WINDOW.getProperty('currUser') server = WINDOW.getProperty('server%s' % currUser) playback = None library = xbmc.translatePath( "special://profile/addon_data/plugin.video.emby/library/").decode( 'utf-8') # Choose playback method resp = xbmcgui.Dialog().select("Choose playback method for your themes", ["Direct Play", "Direct Stream"]) if resp == 0: # Direct Play playback = "DirectPlay" elif resp == 1: # Direct Stream playback = "DirectStream" else: return # Set custom path for user tvtunes_path = xbmc.translatePath( "special://profile/addon_data/script.tvtunes/").decode('utf-8') if xbmcvfs.exists(tvtunes_path): tvtunes = xbmcaddon.Addon(id="script.tvtunes") tvtunes.setSetting('custom_path_enable', "true") tvtunes.setSetting('custom_path', library) xbmc.log("TV Tunes custom path is enabled and set.") else: # if it does not exist this will not work so warn user, often they need to edit the settings first for it to be created. dialog = xbmcgui.Dialog() dialog.ok( 'Warning', 'The settings file does not exist in tvtunes. Go to the tvtunes addon and change a setting, then come back and re-run' ) return # Create library directory if not xbmcvfs.exists(library): xbmcvfs.mkdir(library) # Get every user view Id userViews = [] url = "{server}/mediabrowser/Users/{UserId}/Items?format=json" result = doUtils.downloadUrl(url) for view in result[u'Items']: userviewId = view[u'Id'] userViews.append(userviewId) # Get Ids with Theme Videos itemIds = {} for view in userViews: url = "{server}/mediabrowser/Users/{UserId}/Items?HasThemeVideo=True&ParentId=%s&format=json" % view result = doUtils.downloadUrl(url) if result[u'TotalRecordCount'] != 0: for item in result[u'Items']: itemId = item[u'Id'] folderName = item[u'Name'] folderName = utils.normalize_string(folderName.encode('utf-8')) itemIds[itemId] = folderName # Get paths for theme videos for itemId in itemIds: nfo_path = xbmc.translatePath( "special://profile/addon_data/plugin.video.emby/library/%s/" % itemIds[itemId]) # Create folders for each content if not xbmcvfs.exists(nfo_path): xbmcvfs.mkdir(nfo_path) # Where to put the nfos nfo_path = "%s%s" % (nfo_path, "tvtunes.nfo") url = "{server}/mediabrowser/Items/%s/ThemeVideos?format=json" % itemId result = doUtils.downloadUrl(url) # Create nfo and write themes to it nfo_file = open(nfo_path, 'w') pathstowrite = "" # May be more than one theme for theme in result[u'Items']: if playback == "DirectPlay": playurl = playUtils.directPlay(theme) else: playurl = playUtils.directStream(result, server, theme[u'Id'], "ThemeVideo") pathstowrite += ('<file>%s</file>' % playurl.encode('utf-8')) # Check if the item has theme songs and add them url = "{server}/mediabrowser/Items/%s/ThemeSongs?format=json" % itemId result = doUtils.downloadUrl(url) # May be more than one theme for theme in result[u'Items']: if playback == "DirectPlay": playurl = playUtils.directPlay(theme) else: playurl = playUtils.directStream(result, server, theme[u'Id'], "Audio") pathstowrite += ('<file>%s</file>' % playurl.encode('utf-8')) nfo_file.write('<tvtunes>%s</tvtunes>' % pathstowrite) # Close nfo file nfo_file.close() # Get Ids with Theme songs musicitemIds = {} for view in userViews: url = "{server}/mediabrowser/Users/{UserId}/Items?HasThemeSong=True&ParentId=%s&format=json" % view result = doUtils.downloadUrl(url) if result[u'TotalRecordCount'] != 0: for item in result[u'Items']: itemId = item[u'Id'] folderName = item[u'Name'] folderName = utils.normalize_string(folderName.encode('utf-8')) musicitemIds[itemId] = folderName # Get paths for itemId in musicitemIds: # if the item was already processed with video themes back out if itemId in itemIds: continue nfo_path = xbmc.translatePath( "special://profile/addon_data/plugin.video.emby/library/%s/" % musicitemIds[itemId]) # Create folders for each content if not xbmcvfs.exists(nfo_path): xbmcvfs.mkdir(nfo_path) # Where to put the nfos nfo_path = "%s%s" % (nfo_path, "tvtunes.nfo") url = "{server}/mediabrowser/Items/%s/ThemeSongs?format=json" % itemId result = doUtils.downloadUrl(url) # Create nfo and write themes to it nfo_file = open(nfo_path, 'w') pathstowrite = "" # May be more than one theme for theme in result[u'Items']: if playback == "DirectPlay": playurl = playUtils.directPlay(theme) else: playurl = playUtils.directStream(result, server, theme[u'Id'], "Audio") pathstowrite += ('<file>%s</file>' % playurl.encode('utf-8')) nfo_file.write('<tvtunes>%s</tvtunes>' % pathstowrite) # Close nfo file nfo_file.close()
def addOrUpdateSongToKodiLibrary( self, embyId ,connection, cursor): addon = xbmcaddon.Addon(id='plugin.video.emby') WINDOW = xbmcgui.Window(10000) username = WINDOW.getProperty('currUser') userid = WINDOW.getProperty('userId%s' % username) server = WINDOW.getProperty('server%s' % username) downloadUtils = DownloadUtils() MBitem = ReadEmbyDB().getFullItem(embyId) timeInfo = API().getTimeInfo(MBitem) userData=API().getUserData(MBitem) kodiVersion = 14 if xbmc.getInfoLabel("System.BuildVersion").startswith("15"): kodiVersion = 15 # If the item already exist in the local Kodi DB we'll perform a full item update # If the item doesn't exist, we'll add it to the database cursor.execute("SELECT kodi_id FROM emby WHERE emby_id = ?",(MBitem["Id"],)) result = cursor.fetchone() if result != None: songid = result[0] else: songid = None #### The song details ######### name = utils.convertEncoding(MBitem["Name"]) musicBrainzId = None if MBitem.get("ProviderIds"): if MBitem.get("ProviderIds").get("MusicBrainzTrackId"): musicBrainzId = MBitem.get("ProviderIds").get("MusicBrainzTrackId") genres = " / ".join(MBitem.get("Genres")) artists = " / ".join(MBitem.get("Artists")) track = MBitem.get("IndexNumber") duration = MBitem.get("RunTimeTicks", 0) / 10000000 year = MBitem.get("ProductionYear") bio = utils.convertEncoding(API().getOverview(MBitem)) dateadded = None if MBitem.get("DateCreated"): dateadded = MBitem["DateCreated"].split('.')[0].replace('T', " ") if userData.get("LastPlayedDate") != None: lastplayed = userData.get("LastPlayedDate") else: lastplayed = None playcount = None if userData.get("PlayCount"): playcount = int(userData.get("PlayCount")) #get the album albumid = None if MBitem.get("AlbumId"): cursor.execute("SELECT kodi_id FROM emby WHERE emby_id = ?",(MBitem.get("AlbumId"),)) result = cursor.fetchone() if result: albumid = result[0] if albumid == None: #no album = single in kodi, we need to create a single album for that cursor.execute("select coalesce(max(idAlbum),0) as albumid from album") albumid = cursor.fetchone()[0] albumid = albumid + 1 if kodiVersion == 15: pathsql="insert into album(idAlbum, strArtists, strGenres, iYear, dateAdded, strReleaseType) values(?, ?, ?, ?, ?, ?)" cursor.execute(pathsql, (albumid, artists, genres, year, dateadded, "single")) else: pathsql="insert into album(idAlbum, strArtists, strGenres, iYear, dateAdded) values(?, ?, ?, ?, ?)" cursor.execute(pathsql, (albumid, artists, genres, year, dateadded)) #some stuff here to get the album linked to artists for artist in MBitem.get("ArtistItems"): cursor.execute("SELECT kodi_id FROM emby WHERE emby_id = ?",(artist["Id"],)) result = cursor.fetchone() if result: artistid = result[0] sql="INSERT OR REPLACE into album_artist(idArtist, idAlbum, strArtist) values(?, ?, ?)" cursor.execute(sql, (artistid, albumid, artist["Name"])) if PlayUtils().isDirectPlay(MBitem): playurl = PlayUtils().directPlay(MBitem) #use the direct file path if "\\" in playurl: filename = playurl.rsplit("\\",1)[-1] path = playurl.replace(filename,"") elif "/" in playurl: filename = playurl.rsplit("/",1)[-1] path = playurl.replace(filename,"") else: #for transcoding we just use the server's streaming path because I couldn't figure out how to set the plugin path in the music DB path = server + "/Audio/%s/" %MBitem["Id"] filename = "stream.mp3" #get the path cursor.execute("SELECT idPath as pathid FROM path WHERE strPath = ?",(path,)) result = cursor.fetchone() if result != None: pathid = result[0] else: cursor.execute("select coalesce(max(idPath),0) as pathid from path") pathid = cursor.fetchone()[0] pathid = pathid + 1 pathsql = "insert into path(idPath, strPath) values(?, ?)" cursor.execute(pathsql, (pathid,path)) ##### ADD THE SONG ############ if songid == None: utils.logMsg("ADD song to Kodi library","Id: %s - Title: %s" % (embyId, name)) try: #create the song cursor.execute("select coalesce(max(idSong),0) as songid from song") songid = cursor.fetchone()[0] songid = songid + 1 pathsql="insert into song(idSong, idAlbum, idPath, strArtists, strGenres, strTitle, iTrack, iDuration, iYear, strFileName, strMusicBrainzTrackID, iTimesPlayed, lastplayed) values(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)" cursor.execute(pathsql, (songid, albumid, pathid, artists, genres, name, track, duration, year, filename, musicBrainzId, playcount, lastplayed)) #create the reference in emby table pathsql = "INSERT into emby(emby_id, kodi_id, media_type, checksum) values(?, ?, ?, ?)" cursor.execute(pathsql, (MBitem["Id"], songid, "song", API().getChecksum(MBitem))) except Exception, e: utils.logMsg("Error while adding song to Kodi library: ", e) return
def addOrUpdateSongToKodiLibrary(self, MBitem, connection, cursor): kodiVersion = self.kodiversion embyId = MBitem["Id"] # If the item already exist in the local Kodi DB we'll perform a full item update # If the item doesn't exist, we'll add it to the database cursor.execute("SELECT kodi_id FROM emby WHERE emby_id = ?", (embyId,)) try: songid = cursor.fetchone()[0] except: songid = None timeInfo = API().getTimeInfo(MBitem) userData = API().getUserData(MBitem) genres = MBitem.get('Genres') ##### The song details ##### playcount = userData.get('PlayCount') lastplayed = userData.get('LastPlayedDate') dateadded = API().getDateCreated(MBitem) checksum = API().getChecksum(MBitem) name = MBitem['Name'] musicBrainzId = API().getProvider(MBitem, "musicBrainzTrackId") genre = " / ".join(genres) artists = " / ".join(MBitem.get('Artists')) track = MBitem.get('IndexNumber') year = MBitem.get('ProductionYear') bio = API().getOverview(MBitem) duration = timeInfo.get('TotalTime') # Get the path and filename playurl = PlayUtils().directPlay(MBitem) try: path, filename = ntsplit(playurl) if "/" in playurl: path = "%s/" % path elif "\\" in playurl: path = "%s\\" % path except: # playurl returned false - using server streaming path, because could not figure out plugin paths for music DB playurl = PlayUtils().directstream(MBitem, self.server, embyId, "Audio") filename = "stream.mp3" path = playurl.replace(filename, "") # Validate the path in database cursor.execute("SELECT idPath as pathid FROM path WHERE strPath = ?", (path,)) try: pathid = cursor.fetchone()[0] except: cursor.execute("select coalesce(max(idPath),0) as pathid from path") pathid = cursor.fetchone()[0] + 1 query = "INSERT INTO path(idPath, strPath) values(?, ?)" cursor.execute(query, (pathid, path)) # Get the album cursor.execute("SELECT kodi_id FROM emby WHERE emby_id = ?", (MBitem.get("AlbumId"),)) try: albumid = cursor.fetchone()[0] except: # No album found, create a single's album cursor.execute("select coalesce(max(idAlbum),0) as albumid from album") albumid = cursor.fetchone()[0] + 1 if kodiVersion == 15 or kodiVersion == 16: # Kodi Isengard query = "INSERT INTO album(idAlbum, strArtists, strGenres, iYear, dateAdded, strReleaseType) values(?, ?, ?, ?, ?, ?)" cursor.execute(query, (albumid, artists, genre, year, dateadded, "single")) else: # Kodi Gotham and Helix query = "INSERT INTO album(idAlbum, strArtists, strGenres, iYear, dateAdded) values(?, ?, ?, ?, ?)" cursor.execute(query, (albumid, artists, genre, year, dateadded)) # Link album to artists for artist in MBitem['ArtistItems']: cursor.execute("SELECT kodi_id FROM emby WHERE emby_id = ?", (artist['Id'],)) try: artistid = cursor.fetchone()[0] except: pass else: query = "INSERT OR REPLACE INTO album_artist(idArtist, idAlbum, strArtist) values(?, ?, ?)" cursor.execute(query, (artistid, albumid, artist['Name'])) ##### UPDATE THE SONG ##### if songid: self.logMsg("UPDATE song to Kodi library, Id: %s - Title: %s" % (embyId, name), 1) query = "UPDATE song SET idAlbum = ?, strArtists = ?, strGenres = ?, strTitle = ?, iTrack = ?, iDuration = ?, iYear = ?, strFilename = ?, strMusicBrainzTrackID = ?, iTimesPlayed = ?, lastplayed = ? WHERE idSong = ?" cursor.execute(query, (albumid, artists, genre, name, track, duration, year, filename, musicBrainzId, playcount, lastplayed, songid)) # Update the checksum in emby table query = "UPDATE emby SET checksum = ? WHERE emby_id = ?" cursor.execute(query, (checksum, embyId)) ##### OR ADD THE SONG ##### else: self.logMsg("ADD song to Kodi library, Id: %s - Title: %s" % (embyId, name), 1) # Create the song cursor.execute("select coalesce(max(idSong),0) as songid from song") songid = cursor.fetchone()[0] + 1 query = "INSERT INTO song(idSong, idAlbum, idPath, strArtists, strGenres, strTitle, iTrack, iDuration, iYear, strFileName, strMusicBrainzTrackID, iTimesPlayed, lastplayed) values(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)" cursor.execute(query, (songid, albumid, pathid, artists, genre, name, track, duration, year, filename, musicBrainzId, playcount, lastplayed)) # Create the reference in emby table query = "INSERT INTO emby(emby_id, kodi_id, media_type, checksum) values(?, ?, ?, ?)" cursor.execute(query, (embyId, songid, "song", checksum)) # Add genres self.AddGenresToMedia(songid, genres, "song", cursor) # Link song to album if albumid: query = "INSERT OR REPLACE INTO albuminfosong(idAlbumInfoSong, idAlbumInfo, iTrack, strTitle, iDuration) values(?, ?, ?, ?, ?)" cursor.execute(query, (songid, albumid, track, name, duration)) # Link song to artist for artist in MBitem.get('ArtistItems'): cursor.execute("SELECT kodi_id FROM emby WHERE emby_id = ?", (artist['Id'],)) try: artistid = cursor.fetchone()[0] except: pass else: query = "INSERT OR REPLACE INTO song_artist(idArtist, idSong, strArtist) values(?, ?, ?)" cursor.execute(query, (artistid, songid, artist['Name'])) # Update artwork self.addOrUpdateArt(API().getArtwork(MBitem, "Primary"), songid, "song", "thumb", cursor) self.addOrUpdateArt(API().getArtwork(MBitem, "Primary"), songid, "song", "poster", cursor) self.addOrUpdateArt(API().getArtwork(MBitem, "Banner"), songid, "song", "banner", cursor) self.addOrUpdateArt(API().getArtwork(MBitem, "Logo"), songid, "song", "clearlogo", cursor) self.addOrUpdateArt(API().getArtwork(MBitem, "Art"), songid, "song", "clearart", cursor) self.addOrUpdateArt(API().getArtwork(MBitem, "Thumb"), songid, "song", "landscape", cursor) self.addOrUpdateArt(API().getArtwork(MBitem, "Disc"), songid, "song", "discart", cursor) self.addOrUpdateArt(API().getArtwork(MBitem, "Backdrop"), songid, "song", "fanart", cursor)
def PLAY(self, result, setup="service"): xbmc.log("PLAY Called") WINDOW = xbmcgui.Window(10000) username = WINDOW.getProperty('currUser') userid = WINDOW.getProperty('userId%s' % username) server = WINDOW.getProperty('server%s' % username) try: id = result["Id"] except: return # For split movies if u'PartCount' in result: partcount = result[u'PartCount'] # Get additional parts/playurl url = "{server}/mediabrowser/Videos/%s/AdditionalParts" % id parts = self.downloadUtils.downloadUrl(url) partsId = [id] for part in parts[u'Items']: partId = part[u'Id'] partsId.append(partId) self.PLAYAllItems(partsId, startPositionTicks=None) userData = result['UserData'] resume_result = 0 seekTime = 0 if userData.get("PlaybackPositionTicks") != 0: reasonableTicks = int(userData.get("PlaybackPositionTicks")) / 1000 seekTime = reasonableTicks / 10000 playurl = PlayUtils().getPlayUrl(server, id, result) if playurl == False: #xbmcgui.Dialog().ok('Warning', 'Failed to launch playback.') xbmc.log("Failed to retrieve the playback path/url.") return thumbPath = API().getArtwork(result, "Primary") #if the file is a virtual strm file, we need to override the path by reading it's contents if playurl.endswith(".strm"): xbmc.log("virtual strm file file detected, starting playback with 3th party addon...") StrmTemp = "special://temp/temp.strm" xbmcvfs.copy(playurl, StrmTemp) playurl = open(xbmc.translatePath(StrmTemp), 'r').readline() listItem = xbmcgui.ListItem(path=playurl, iconImage=thumbPath, thumbnailImage=thumbPath) # Can not play virtual items if (result.get("LocationType") == "Virtual"): xbmcgui.Dialog().ok(self.language(30128), self.language(30129)) watchedurl = "%s/mediabrowser/Users/%s/PlayedItems/%s" % (server, userid, id) positionurl = "%s/mediabrowser/Users/%s/PlayingItems/%s" % (server, userid, id) deleteurl = "%s/mediabrowser/Items/%s" % (server, id) # set the current playing info WINDOW.setProperty(playurl+"watchedurl", watchedurl) WINDOW.setProperty(playurl+"positionurl", positionurl) WINDOW.setProperty(playurl+"deleteurl", "") WINDOW.setProperty(playurl+"deleteurl", deleteurl) #show the additional resume dialog if launched from a widget if xbmc.getCondVisibility("Window.IsActive(home)"): if userData.get("PlaybackPositionTicks") != 0: reasonableTicks = int(userData.get("PlaybackPositionTicks")) / 1000 seekTime = reasonableTicks / 10000 if seekTime != 0: displayTime = str(datetime.timedelta(seconds=seekTime)) display_list = [ self.language(30106) + ' ' + displayTime, self.language(30107)] resumeScreen = xbmcgui.Dialog() resume_result = resumeScreen.select(self.language(30105), display_list) if resume_result == 0: WINDOW.setProperty(playurl+"seektime", str(seekTime)) elif resume_result < 0: # User cancelled dialog xbmc.log("Emby player -> User cancelled resume dialog.") return else: WINDOW.clearProperty(playurl+"seektime") else: WINDOW.clearProperty(playurl+"seektime") else: # Playback started from library WINDOW.setProperty(playurl+"seektime", str(seekTime)) if result.get("Type")=="Episode": WINDOW.setProperty(playurl+"refresh_id", result.get("SeriesId")) else: WINDOW.setProperty(playurl+"refresh_id", id) WINDOW.setProperty(playurl+"runtimeticks", str(result.get("RunTimeTicks"))) WINDOW.setProperty(playurl+"type", result.get("Type")) WINDOW.setProperty(playurl+"item_id", id) mediaSources = result.get("MediaSources") if(mediaSources != None): if mediaSources[0].get('DefaultAudioStreamIndex') != None: WINDOW.setProperty(playurl+"AudioStreamIndex", str(mediaSources[0].get('DefaultAudioStreamIndex'))) if mediaSources[0].get('DefaultSubtitleStreamIndex') != None: WINDOW.setProperty(playurl+"SubtitleStreamIndex", str(mediaSources[0].get('DefaultSubtitleStreamIndex'))) #launch the playback - only set the listitem props if we're not using the setresolvedurl approach if setup == "service": self.setListItemProps(server, id, listItem, result) xbmc.Player().play(playurl,listItem) elif setup == "default": #artwork only works from widgets (home screen) with player command as there is no listitem selected if xbmc.getCondVisibility("Window.IsActive(home)"): self.setListItemProps(server, id, listItem, result) xbmc.Player().play(playurl,listItem) else: xbmcplugin.setResolvedUrl(int(sys.argv[1]), True, listItem)
def onNotification(self, sender, method, data): WINDOW = self.WINDOW downloadUtils = DownloadUtils() #player started playing an item - if ("Playlist.OnAdd" in method or "Player.OnPlay" in method) and utils.settings('useDirectPaths') == 'true': jsondata = json.loads(data) if jsondata != None: if jsondata.has_key("item"): if jsondata.get("item").has_key("id") and jsondata.get( "item").has_key("type"): id = jsondata.get("item").get("id") type = jsondata.get("item").get("type") embyid = ReadKodiDB().getEmbyIdByKodiId(id, type) if embyid != None: playurl = xbmc.Player().getPlayingFile() WINDOW = xbmcgui.Window(10000) username = WINDOW.getProperty('currUser') userid = WINDOW.getProperty('userId%s' % username) server = WINDOW.getProperty('server%s' % username) url = "{server}/mediabrowser/Users/{UserId}/Items/" + embyid + "?format=json&ImageTypeLimit=1" result = downloadUtils.downloadUrl(url) print "Here: %s" % result userData = result['UserData'] playurl = PlayUtils().getPlayUrl( server, embyid, result) watchedurl = 'http://' + server + '/mediabrowser/Users/' + userid + '/PlayedItems/' + embyid positionurl = 'http://' + server + '/mediabrowser/Users/' + userid + '/PlayingItems/' + embyid deleteurl = 'http://' + server + '/mediabrowser/Items/' + embyid # set the current playing info WINDOW.setProperty(playurl + "watchedurl", watchedurl) WINDOW.setProperty(playurl + "positionurl", positionurl) WINDOW.setProperty(playurl + "deleteurl", "") WINDOW.setProperty(playurl + "deleteurl", deleteurl) if result.get("Type") == "Episode": WINDOW.setProperty(playurl + "refresh_id", result.get("SeriesId")) else: WINDOW.setProperty(playurl + "refresh_id", embyid) WINDOW.setProperty(playurl + "runtimeticks", str(result.get("RunTimeTicks"))) WINDOW.setProperty(playurl + "type", result.get("Type")) WINDOW.setProperty(playurl + "item_id", embyid) if PlayUtils().isDirectPlay(result) == True: playMethod = "DirectPlay" else: playMethod = "Transcode" WINDOW.setProperty(playurl + "playmethod", playMethod) mediaSources = result.get("MediaSources") if (mediaSources != None): mediaStream = mediaSources[0].get( 'MediaStreams') defaultsubs = "" for stream in mediaStream: if u'Subtitle' in stream[ u'Type'] and stream[u'IsDefault']: if u'Language' in stream: defaultsubs = stream[u'Language'] else: defaultsubs = stream[u'Codec'] WINDOW.setProperty("%ssubs" % playurl, defaultsubs.encode('utf-8')) if mediaSources[0].get( 'DefaultAudioStreamIndex') != None: WINDOW.setProperty( playurl + "AudioStreamIndex", str(mediaSources[0].get( 'DefaultAudioStreamIndex'))) if mediaSources[0].get( 'DefaultSubtitleStreamIndex') != None: WINDOW.setProperty( playurl + "SubtitleStreamIndex", str(mediaSources[0].get( 'DefaultSubtitleStreamIndex'))) if method == "VideoLibrary.OnUpdate": # Triggers 4 times, the following is only for manually marking as watched/unwatched jsondata = json.loads(data) try: playcount = jsondata.get('playcount') item = jsondata['item']['id'] type = jsondata['item']['type'] prop = utils.window('Played%s%s' % (type, item)) except: self.logMsg("Could not process VideoLibrary.OnUpdate data.", 1) else: self.logMsg("VideoLibrary.OnUpdate: %s" % data, 2) if prop != "true": # Set property to prevent the multi triggering utils.window('Played%s%s' % (type, item), "true") WriteKodiVideoDB().updatePlayCountFromKodi( item, type, playcount) self.clearProperty(type, item) if method == "System.OnWake": xbmc.sleep(10000) #Allow network to wake up WINDOW.setProperty("OnWakeSync", "true") if method == "VideoLibrary.OnRemove": xbmc.log('Intercepted remove from sender: ' + sender + ' method: ' + method + ' data: ' + data) jsondata = json.loads(data) id = ReadKodiDB().getEmbyIdByKodiId(jsondata.get("id"), jsondata.get("type")) if id == None: return xbmc.log("Deleting Emby ID: " + id + " from database") connection = utils.KodiSQL() cursor = connection.cursor() cursor.execute("DELETE FROM emby WHERE emby_id = ?", (id, )) connection.commit() cursor.close if jsondata: if jsondata.get("type") == "episode" or "movie": url = '{server}/mediabrowser/Items?Ids=' + id + '&format=json' #This is a check to see if the item exists on the server, if it doesn't it may have already been deleted by another client result = DownloadUtils().downloadUrl(url) item = result.get("Items")[0] if data: return_value = xbmcgui.Dialog().yesno( "Confirm Delete", "Delete file on Emby Server?") if return_value: url = '{server}/mediabrowser/Items/' + id xbmc.log('Deleting via URL: ' + url) DownloadUtils().downloadUrl(url, type="DELETE") elif method == "Playlist.OnClear": self.logMsg("Clear playback properties.", 2) utils.window('PlaylistIntroSet', clear=True) utils.window('PlaylistsetDummy', clear=True) utils.window('PlaylistAdditional', clear=True)
def addOrUpdateSongToKodiLibrary(self, MBitem, connection, cursor): kodiVersion = self.kodiversion embyId = MBitem["Id"] # If the item already exist in the local Kodi DB we'll perform a full item update # If the item doesn't exist, we'll add it to the database cursor.execute("SELECT kodi_id FROM emby WHERE emby_id = ?", (embyId,)) try: songid = cursor.fetchone()[0] except: songid = None timeInfo = API().getTimeInfo(MBitem) userData = API().getUserData(MBitem) genres = MBitem.get('Genres') ##### The song details ##### playcount = userData.get('PlayCount') lastplayed = userData.get('LastPlayedDate') dateadded = API().getDateCreated(MBitem) checksum = API().getChecksum(MBitem) name = MBitem['Name'] musicBrainzId = API().getProvider(MBitem, "musicBrainzTrackId") genre = " / ".join(genres) artists = " / ".join(MBitem.get('Artists')) track = MBitem.get('IndexNumber') year = MBitem.get('ProductionYear') bio = API().getOverview(MBitem) duration = timeInfo.get('TotalTime') if utils.settings('directstreammusic') == "true": WINDOW = xbmcgui.Window(10000) username = WINDOW.getProperty('currUser') server = WINDOW.getProperty('server%s' % username) playurl = PlayUtils().directStream(MBitem, server, embyId, "Audio") filename = "stream.mp3" path = playurl.replace(filename, "") else: # Get the path and filename playurl = PlayUtils().directPlay(MBitem) path, filename = ntsplit(playurl) if "/" in playurl: path = "%s/" % path elif "\\" in playurl: path = "%s\\" % path # Validate the path in database cursor.execute("SELECT idPath as pathid FROM path WHERE strPath = ?", (path,)) try: pathid = cursor.fetchone()[0] except: cursor.execute("select coalesce(max(idPath),0) as pathid from path") pathid = cursor.fetchone()[0] + 1 query = "INSERT INTO path(idPath, strPath) values(?, ?)" cursor.execute(query, (pathid, path)) # Get the album cursor.execute("SELECT kodi_id FROM emby WHERE emby_id = ?", (MBitem.get("AlbumId"),)) try: albumid = cursor.fetchone()[0] except: # No album found, create a single's album cursor.execute("select coalesce(max(idAlbum),0) as albumid from album") albumid = cursor.fetchone()[0] + 1 if kodiVersion == 15: # Kodi Isengard query = "INSERT INTO album(idAlbum, strArtists, strGenres, iYear, dateAdded, strReleaseType) values(?, ?, ?, ?, ?, ?)" cursor.execute(query, (albumid, artists, genre, year, dateadded, "single")) elif kodiVersion == 16: query = "INSERT INTO album(idAlbum, strArtists, strGenres, iYear, strReleaseType) values(?, ?, ?, ?, ?)" cursor.execute(query, (albumid, artists, genre, year, "single")) else: # Kodi Gotham and Helix query = "INSERT INTO album(idAlbum, strArtists, strGenres, iYear, dateAdded) values(?, ?, ?, ?, ?)" cursor.execute(query, (albumid, artists, genre, year, dateadded)) # Link album to artists for artist in MBitem['ArtistItems']: cursor.execute("SELECT kodi_id FROM emby WHERE emby_id = ?", (artist['Id'],)) try: artistid = cursor.fetchone()[0] except: pass else: query = "INSERT OR REPLACE INTO album_artist(idArtist, idAlbum, strArtist) values(?, ?, ?)" cursor.execute(query, (artistid, albumid, artist['Name'])) ##### UPDATE THE SONG ##### if songid: self.logMsg("UPDATE song to Kodi library, Id: %s - Title: %s" % (embyId, name), 1) query = "UPDATE song SET idAlbum = ?, strArtists = ?, strGenres = ?, strTitle = ?, iTrack = ?, iDuration = ?, iYear = ?, strFilename = ?, strMusicBrainzTrackID = ?, iTimesPlayed = ?, lastplayed = ? WHERE idSong = ?" cursor.execute(query, (albumid, artists, genre, name, track, duration, year, filename, musicBrainzId, playcount, lastplayed, songid)) # Update the checksum in emby table query = "UPDATE emby SET checksum = ? WHERE emby_id = ?" cursor.execute(query, (checksum, embyId)) ##### OR ADD THE SONG ##### else: self.logMsg("ADD song to Kodi library, Id: %s - Title: %s" % (embyId, name), 1) # Create the song cursor.execute("select coalesce(max(idSong),0) as songid from song") songid = cursor.fetchone()[0] + 1 query = "INSERT INTO song(idSong, idAlbum, idPath, strArtists, strGenres, strTitle, iTrack, iDuration, iYear, strFileName, strMusicBrainzTrackID, iTimesPlayed, lastplayed) values(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)" cursor.execute(query, (songid, albumid, pathid, artists, genre, name, track, duration, year, filename, musicBrainzId, playcount, lastplayed)) # Create the reference in emby table query = "INSERT INTO emby(emby_id, kodi_id, media_type, checksum) values(?, ?, ?, ?)" cursor.execute(query, (embyId, songid, "song", checksum)) # Add genres self.AddGenresToMedia(songid, genres, "song", cursor) # Link song to album if albumid: query = "INSERT OR REPLACE INTO albuminfosong(idAlbumInfoSong, idAlbumInfo, iTrack, strTitle, iDuration) values(?, ?, ?, ?, ?)" cursor.execute(query, (songid, albumid, track, name, duration)) # Link song to artist for artist in MBitem.get('ArtistItems'): cursor.execute("SELECT kodi_id FROM emby WHERE emby_id = ?", (artist['Id'],)) try: artistid = cursor.fetchone()[0] except: pass else: query = "INSERT OR REPLACE INTO song_artist(idArtist, idSong, strArtist) values(?, ?, ?)" cursor.execute(query, (artistid, songid, artist['Name'])) # Update artwork self.textureCache.addArtwork(API().getAllArtwork(MBitem), songid, "song", cursor)
def getThemeMedia(): doUtils = DownloadUtils() playUtils = PlayUtils() currUser = WINDOW.getProperty('currUser') server = WINDOW.getProperty('server%s' % currUser) playback = None library = xbmc.translatePath("special://profile/addon_data/plugin.video.emby/library/").decode('utf-8') # Choose playback method resp = xbmcgui.Dialog().select("Choose playback method for your themes", ["Direct Play", "Direct Stream"]) if resp == 0: # Direct Play playback = "DirectPlay" elif resp == 1: # Direct Stream playback = "DirectStream" else:return # Set custom path for user tvtunes_path = xbmc.translatePath("special://profile/addon_data/script.tvtunes/").decode('utf-8') if xbmcvfs.exists(tvtunes_path): tvtunes = xbmcaddon.Addon(id="script.tvtunes") tvtunes.setSetting('custom_path_enable', "true") tvtunes.setSetting('custom_path', library) xbmc.log("TV Tunes custom path is enabled and set.") else: # if it does not exist this will not work so warn user, often they need to edit the settings first for it to be created. dialog = xbmcgui.Dialog() dialog.ok('Warning', 'The settings file does not exist in tvtunes. Go to the tvtunes addon and change a setting, then come back and re-run') return # Create library directory if not xbmcvfs.exists(library): xbmcvfs.mkdir(library) # Get every user view Id userViews = [] url = "{server}/mediabrowser/Users/{UserId}/Items?format=json" result = doUtils.downloadUrl(url) for view in result[u'Items']: userviewId = view[u'Id'] userViews.append(userviewId) # Get Ids with Theme Videos itemIds = {} for view in userViews: url = "{server}/mediabrowser/Users/{UserId}/Items?HasThemeVideo=True&ParentId=%s&format=json" % view result = doUtils.downloadUrl(url) if result[u'TotalRecordCount'] != 0: for item in result[u'Items']: itemId = item[u'Id'] folderName = item[u'Name'] folderName = utils.normalize_string(folderName.encode('utf-8')) itemIds[itemId] = folderName # Get paths for theme videos for itemId in itemIds: nfo_path = xbmc.translatePath("special://profile/addon_data/plugin.video.emby/library/%s/" % itemIds[itemId]) # Create folders for each content if not xbmcvfs.exists(nfo_path): xbmcvfs.mkdir(nfo_path) # Where to put the nfos nfo_path = "%s%s" % (nfo_path, "tvtunes.nfo") url = "{server}/mediabrowser/Items/%s/ThemeVideos?format=json" % itemId result = doUtils.downloadUrl(url) # Create nfo and write themes to it nfo_file = open(nfo_path, 'w') pathstowrite = "" # May be more than one theme for theme in result[u'Items']: if playback == "DirectPlay": playurl = playUtils.directPlay(theme) else: playurl = playUtils.directStream(result, server, theme[u'Id'], "ThemeVideo") pathstowrite += ('<file>%s</file>' % playurl.encode('utf-8')) # Check if the item has theme songs and add them url = "{server}/mediabrowser/Items/%s/ThemeSongs?format=json" % itemId result = doUtils.downloadUrl(url) # May be more than one theme for theme in result[u'Items']: if playback == "DirectPlay": playurl = playUtils.directPlay(theme) else: playurl = playUtils.directStream(result, server, theme[u'Id'], "Audio") pathstowrite += ('<file>%s</file>' % playurl.encode('utf-8')) nfo_file.write( '<tvtunes>%s</tvtunes>' % pathstowrite ) # Close nfo file nfo_file.close() # Get Ids with Theme songs musicitemIds = {} for view in userViews: url = "{server}/mediabrowser/Users/{UserId}/Items?HasThemeSong=True&ParentId=%s&format=json" % view result = doUtils.downloadUrl(url) if result[u'TotalRecordCount'] != 0: for item in result[u'Items']: itemId = item[u'Id'] folderName = item[u'Name'] folderName = utils.normalize_string(folderName.encode('utf-8')) musicitemIds[itemId] = folderName # Get paths for itemId in musicitemIds: # if the item was already processed with video themes back out if itemId in itemIds: continue nfo_path = xbmc.translatePath("special://profile/addon_data/plugin.video.emby/library/%s/" % musicitemIds[itemId]) # Create folders for each content if not xbmcvfs.exists(nfo_path): xbmcvfs.mkdir(nfo_path) # Where to put the nfos nfo_path = "%s%s" % (nfo_path, "tvtunes.nfo") url = "{server}/mediabrowser/Items/%s/ThemeSongs?format=json" % itemId result = doUtils.downloadUrl(url) # Create nfo and write themes to it nfo_file = open(nfo_path, 'w') pathstowrite = "" # May be more than one theme for theme in result[u'Items']: if playback == "DirectPlay": playurl = playUtils.directPlay(theme) else: playurl = playUtils.directStream(result, server, theme[u'Id'], "Audio") pathstowrite += ('<file>%s</file>' % playurl.encode('utf-8')) nfo_file.write( '<tvtunes>%s</tvtunes>' % pathstowrite ) # Close nfo file nfo_file.close()
def getThemeMedia(): doUtils = DownloadUtils() playUtils = PlayUtils() currUser = WINDOW.getProperty('currUser') server = WINDOW.getProperty('server%s' % currUser) playback = None library = xbmc.translatePath("special://profile/addon_data/plugin.video.emby/library/") # Choose playback method resp = xbmcgui.Dialog().select("Choose playback method for your themes", ["Direct Play", "Direct Stream"]) if resp == 0: # Direct Play playback = "DirectPlay" elif resp == 1: # Direct Stream playback = "DirectStream" else:return # Create library directory if not xbmcvfs.exists(library): xbmcvfs.mkdir(library) # Get every user view Id userViews = [] url = "{server}/mediabrowser/Users/{UserId}/Items?format=json" result = doUtils.downloadUrl(url) for view in result[u'Items']: userviewId = view[u'Id'] userViews.append(userviewId) # Get Ids with Theme songs itemIds = {} for view in userViews: url = "{server}/mediabrowser/Users/{UserId}/Items?HasThemeSong=True&ParentId=%s&format=json" % view result = doUtils.downloadUrl(url) if result[u'TotalRecordCount'] != 0: for item in result[u'Items']: itemId = item[u'Id'] folderName = item[u'Name'] itemIds[itemId] = folderName # Get paths for itemId in itemIds: nfo_path = xbmc.translatePath("special://profile/addon_data/plugin.video.emby/library/%s/" % itemIds[itemId]) # Create folders for each content if not xbmcvfs.exists(nfo_path): xbmcvfs.mkdir(nfo_path) # Where to put the nfos nfo_path = "%s%s" % (nfo_path, "tvtunes.nfo") url = "{server}/mediabrowser/Items/%s/ThemeSongs?format=json" % itemId result = doUtils.downloadUrl(url) # Create nfo and write themes to it nfo_file = open(nfo_path, 'w') pathstowrite = "" # May be more than one theme for theme in result[u'Items']: if playback == "DirectPlay": playurl = playUtils.directPlay(theme) else: playurl = playUtils.directStream(result, server, theme[u'Id'], "Audio") pathstowrite += ('<file>%s</file>' % playurl) nfo_file.write( '<tvtunes>%s</tvtunes>' % pathstowrite ) # Close nfo file nfo_file.close()