def showPictureMenu(piclist, slidetime): # Picture viewer and menu pselect = 0 select = 0 while pselect >= 0: try: pictures = [] a = 0 while a < len(piclist): pictures.append( piclist[a]['title']) # Convert rows to list for dialog box a += 1 ddialog = xbmcgui.Dialog() pselect = ddialog.select(translate(30416), pictures) if pselect < 0: # User cancel if select > 0: xbmc.executebuiltin('Action(ParentDir)') break else: # Show picture selection = picURL(piclist[pselect]['url']) json_query = xbmc.executeJSONRPC( '{"jsonrpc":"2.0", "method":"Player.Open", \ "params":{"item":{"file":%s }},"id":1}' % (selection)) xbmc.sleep(slidetime * 1000) select = +1 except Exception as e: printexception() mgenlog = 'Mezzmo error displaying picture.' xbmc.log(mgenlog, xbmc.LOGNOTICE) mgenlogUpdate(mgenlog)
def ShowSlides(piclist, slidetime): # Slidehow viewier try: kbmonitor = KodiMonitor() slideIdx = 0 #xbmc.log('Mezzmo picture url is: ' + str(playitem) , xbmc.LOGNOTICE) while slideIdx < len(piclist): if kbmonitor.flag == 'play': playitem = picURL( piclist[slideIdx]['url']) # Verify proper file name #xbmc.log('Mezzmo picture index is: ' + str(playitem) , xbmc.LOGNOTICE) json_query = xbmc.executeJSONRPC( '{"jsonrpc":"2.0", "method":"Player.Open", \ "params":{"item":{"file":%s }},"id":1}' % (playitem)) #xbmc.log('Mezzmo picture dictionary list is: ' + str(piclist) , xbmc.LOGNOTICE) xbmc.sleep(slidetime * 1000) slideIdx += 1 #xbmc.log('Mezzmo monitor data is: ' + (kbmonitor.flag) , xbmc.LOGNOTICE) if kbmonitor.flag == 'stop': del kbmonitor return break if kbmonitor.flag == 'pause': slideIdx = slideIdx xbmc.executebuiltin('Action(ParentDir)') del kbmonitor except Exception as e: printexception() mgenlog = 'Mezzmo error displaying slides.' xbmc.log(mgenlog, xbmc.LOGNOTICE) mgenlogUpdate(mgenlog)
def exportData(selectbl): # CSV Output selected table try: #xbmc.log("Mezzmo selectable is: " + str(selectbl), xbmc.LOGNOTICE) folderpath = xbmc.translatePath(os.path.join("special://home/", "output/")) if not xbmcvfs.exists(folderpath): xbmcvfs.mkdir(folderpath) xbmc.log("Mezzmo Export Output folder not found: " + str(folderpath), xbmc.LOGNOTICE) for a in range(len(selectbl)): fpart = datetime.now().strftime('%H%M%S') selectindex = int(selectbl[a][:2]) # Get list index to determine DB selectname = selectbl[a][2:] # Parse table name in DB outfile = folderpath + "mezzmo_" + selectname + "_" + fpart + ".csv" #xbmc.log("Mezzmo selectable is: " + str(selectindex) + ' ' + selectname, xbmc.LOGNOTICE) if selectindex < 8: dbexport = openKodiDB() else: dbexport = openNosyncDB() curm = dbexport.execute('SELECT * FROM '+selectname+'') recs = curm.fetchall() headers = [i[0] for i in curm.description] csvFile = csv.writer(open(outfile, 'wb'), delimiter=',', lineterminator='\n', quoting=csv.QUOTE_ALL, escapechar='\\') csvFile.writerow(headers) # Add the headers and data to the CSV file. for row in recs: recsencode = [] # xbmc.log("Mezzmo output string length is: " + str(len(row)), xbmc.LOGNOTICE) for item in range(len(row)): if isinstance(row[item], int) or isinstance(row[item], float): # Convert to strings recitem = str(row[item]) recitem = recitem.encode('utf-8') elif row[item] != None: recitem = row[item].encode('utf-8') else: recitem = row[item] recsencode.append(recitem) csvFile.writerow(recsencode) dbexport.close() outmsg = folderpath dialog_text = translate(30428) + outmsg xbmcgui.Dialog().ok(translate(30429), dialog_text) except Exception as e: printexception() dbexport.close() mgenlog = translate(30430) + selectname xbmcgui.Dialog().notification(translate(30431), mgenlog, addon_icon, 5000) xbmc.log(mgenlog, xbmc.LOGNOTICE) mgenlogUpdate(mgenlog)
def picURL(itemurl): # Check for proper file extension try: if itemurl[len(itemurl) - 4] == '.': # Add .jpg for urllib issue newurl = '"' + itemurl + '"' else: newurl = '"' + itemurl + '.jpg' + '"' xbmc.log('Mezzmo new picture URL: ' + str(newurl), xbmc.LOGDEBUG) return newurl except Exception as e: printexception() mgenlog = 'Mezzmo error converting picture URL' xbmc.log(mgenlog, xbmc.LOGNOTICE) mgenlogUpdate(mgenlog)
def clearPictures(): # Clear picture data try: picfile = openNosyncDB() # Open picture database picfile.execute('DELETE FROM mPictures', ) picfile.commit() picfile.close() mgenlog = 'Mezzmo picture DB cleared.' xbmc.log(mgenlog, xbmc.LOGDEBUG) #mgenlogUpdate(mgenlog) except Exception as e: printexception() mgenlog = 'Mezzmo clearing picture error.' xbmc.log(mgenlog, xbmc.LOGNOTICE) mgenlogUpdate(mgenlog)
def autoStart(): autdialog = xbmcgui.Dialog() if sys.argv[ 2] == "clear": # Ensure user reMost Recenty wants to clear autostart aumsg = "Are you sure you want to clear your curent Mezzmo addon autostart setting ?" cselect = autdialog.yesno('Mezzmo Autostart Clear', aumsg) else: # Confirm new autostart setting auplaylist = sys.argv[3].encode('utf-8', 'ignore') aumsg = "Confirm setting Mezzmo addon autostart to: \n\n" + auplaylist cselect = autdialog.yesno('Mezzmo Autostart Setting', aumsg) if cselect == 1: media.settings('autostart', sys.argv[2]) mgenlog = 'Mezzmo autostart set to: ' + str(sys.argv[2]) xbmc.log(mgenlog, xbmc.LOGNOTICE) media.mgenlogUpdate(mgenlog) xbmc.executebuiltin('Container.Refresh()')
def clearPerf(): # Clear performance statistics perfile = openNosyncDB() # Open perf stats database perfdialog = xbmcgui.Dialog() kcmsg = "Confirm clearing the Mezzmo performance logs. " cselect = perfdialog.yesno('Mezzmo Clear Performance Logs', kcmsg) if cselect == 1: perfile.execute('DELETE FROM mperfStats', ) perfile.execute('DELETE FROM mperfIndex', ) perfile.commit() mgenlog = 'Mezzmo performance logs cleared by user.' xbmc.log(mgenlog, xbmc.LOGNOTICE) media.mgenlogUpdate(mgenlog) dialog_text = "Most Recent Mezzmo performance logs were deleted." perfdialog.ok("Mezzmo Clear Performance Logs", dialog_text) perfile.close() return
def showSingle(url): # Display individual native picture try: if 'upnp' in str(url[0]): # Kodi cannot display pictures over uPNP dialog_text = translate(30413) xbmcgui.Dialog().ok(translate(30406), dialog_text) xbmc.executebuiltin('Action(ParentDir)') return else: itemurl = picURL(url[0]) json_query = xbmc.executeJSONRPC( '{"jsonrpc":"2.0", "method":"Player.Open", \ "params":{"item":{"file":%s }},"id":1}' % (itemurl)) except Exception as e: printexception() mgenlog = 'Mezzmo error displaying single picture.' xbmc.log(mgenlog, xbmc.LOGNOTICE) mgenlogUpdate(mgenlog)
def picDisplay(): # Picture slideshow presenter try: piclist = getPictures() # Get pictures from picture DB slidetime = int(settings('slidetime')) # Get slide pause time #xbmc.log('Mezzmo picture list: ' + str(piclist) , xbmc.LOGNOTICE) if 'upnp' in str( piclist[0]['url']): # Kodi cannot display pictures over uPNP dialog_text = translate(30413) xbmcgui.Dialog().ok(translate(30412), dialog_text) xbmc.executebuiltin('Action(ParentDir)') return else: cselect = 3 while cselect >= 0: #pictures = ['Slideshow','Pictures Normal Delay'] pictures = [ translate(30417), translate(30418), translate(30419) ] ddialog = xbmcgui.Dialog() cselect = ddialog.select(translate(30415), pictures) if cselect == 1: # User selects pictures normal showPictureMenu(piclist, slidetime) #xbmc.executebuiltin('Action(ParentDir)') if cselect == 2: # User selects pictures extended showPictureMenu(piclist, (slidetime * 3)) #xbmc.executebuiltin('Action(ParentDir)') elif cselect == 0: # User selects slideshow ShowSlides(piclist, slidetime) elif cselect < 0: #xbmc.executebuiltin('Action(ParentDir)') break #return except Exception as e: printexception() mgenlog = 'Mezzmo error displaying picture slideshow.' xbmc.log(mgenlog, xbmc.LOGNOTICE) mgenlogUpdate(mgenlog)
def deleteTexturesCache(contenturl): # do not cache texture images if caching disabled if media.settings('caching') == 'false': try: from sqlite3 import dbapi2 as sqlite except: from pysqlite2 import dbapi2 as sqlite DB = os.path.join(xbmc.translatePath("special://database"), "Textures13.db") db = sqlite.connect(DB) serverport = '%' + media.getServerport(contenturl) + '%' # Get Mezzmo server port info cur = db.execute('DELETE FROM texture WHERE url LIKE ?', (serverport,)) rows = cur.rowcount mgenlog ='Mezzmo addon texture rows deleted: ' + str(rows) xbmc.log(mgenlog, xbmc.LOGNOTICE) media.mgenlogUpdate(mgenlog) db.commit() cur.close() db.close() media.settings('caching', 'true') # reset back to true after clearing
def updateTexturesCache(contenturl): # Update Kodi image cache timers try: from sqlite3 import dbapi2 as sqlite except: from pysqlite2 import dbapi2 as sqlite DB = os.path.join(xbmc.translatePath("special://database"), "Textures13.db") db = sqlite.connect(DB) serverport = '%' + media.getServerport(contenturl) + '%' # Get Mezzmo server port info newtime = (datetime.datetime.now() + datetime.timedelta(days=-3)).strftime('%Y-%m-%d %H:%M:%S') cur = db.execute('UPDATE texture SET lasthashcheck=? WHERE URL LIKE ? and lasthashcheck=?', \ (newtime, serverport, "")) # Update Mezzmo image cache timers with no dates rows = cur.rowcount db.commit() cur.close() db.close() mgenlog = 'Mezzmo textures cache timers ' + str(rows) + ' rows updated.' xbmc.log(mgenlog, xbmc.LOGNOTICE) media.mgenlogUpdate(mgenlog)
def upnpCheck(): # Check Kodi uPNP setting json_query = xbmc.executeJSONRPC( '{"jsonrpc":"2.0", "method":"Settings.GetSettingValue", \ "params":{"setting":"services.upnp"}, "id":1}') json_query = json.loads(json_query) upnp_enabled = '' if 'result' in json_query and 'value' in json_query['result']: upnp_enabled = json_query['result']['value'] xbmc.log('The uPNP status is: ' + str(upnp_enabled), xbmc.LOGDEBUG) if upnp_enabled == True: return else: dialog_text = translate(30394) cselect = xbmcgui.Dialog().yesno("Mezzmo uPNP Playback", dialog_text) if cselect == 1: # Enable uPNP support in Kodi json_query = xbmc.executeJSONRPC( '{"jsonrpc":"2.0", "method":"Settings.SetSettingValue", \ "params":{"setting":"services.upnp","value":true}, "id":1}') json_query = xbmc.executeJSONRPC( '{"jsonrpc":"2.0", "method":"Settings.GetSettingValue", \ "params":{"setting":"services.upnp"}, "id":1}') json_query = json.loads(json_query) upnp_enabled = '' if 'result' in json_query and 'value' in json_query['result']: upnp_enabled = json_query['result']['value'] if upnp_enabled == True: dialog_text = translate(30397) xbmcgui.Dialog().ok(translate(30396), dialog_text) mgenlog = 'Mezzmo Kodi uPNP Set to Enabled.' xbmc.log(mgenlog, xbmc.LOGNOTICE) mgenlogUpdate(mgenlog) else: dialog_text = translate(30395) xbmcgui.Dialog().ok(translate(30396), dialog_text) mgenlog = 'Mezzmo Kodi uPNP Setting failed.' xbmc.log(mgenlog, xbmc.LOGNOTICE) mgenlogUpdate(mgenlog)
def setPlaycount(url, objectID, count, mtitle): # Set Mezzmo play count headers = { 'content-type': 'text/xml', 'accept': '*/*', 'SOAPACTION': '"urn:schemas-upnp-org:service:ContentDirectory:1#X_SetPlaycount"', 'User-Agent': 'Kodi (Mezzmo Addon)' } body = '''<?xml version="1.0"?> <s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"> <s:Body> <u:X_SetPlaycount xmlns:u="urn:schemas-upnp-org:service:ContentDirectory:1"> <ObjectID>''' body += objectID body += '''</ObjectID> <Playcount>''' body += count body += '''</Playcount> </u:X_SetPlaycount> </s:Body> </s:Envelope>''' req = urllib2.Request(url, body, headers) response = '' try: response = urllib2.urlopen(req, timeout=60).read() except Exception as e: xbmc.log('EXCEPTION IN SetPlaycount: ' + str(e)) pass mgenlog ='Mezzmo server playcount set to ' + count + ' for: ' + \ mtitle.encode('utf-8', 'ignore') xbmc.log(mgenlog, xbmc.LOGNOTICE) mgenlog = '###' + mtitle.encode('utf-8', 'ignore') media.mgenlogUpdate(mgenlog) mgenlog = 'Mezzmo server playcount set to ' + count + ' for: ' media.mgenlogUpdate(mgenlog) return response
def updatePictures(piclist): # Update picture DB with list try: picfile = openNosyncDB() # Open picture DB a = 0 while a < len(piclist): title = str(piclist[a]['title']) url = str(piclist[a]['url']) picfile.execute( 'INSERT into mPictures (mpTitle, mpUrl) values (?, ?)', ( title, url, )) a += 1 picfile.commit() picfile.close() except Exception as e: printexception() mgenlog = 'Mezzmo update picture error.' xbmc.log(mgenlog, xbmc.LOGNOTICE) mgenlogUpdate(mgenlog)
def getPictures(): # Get pictures from DB try: picfile = openNosyncDB() # Open picture DB curps = picfile.execute('SELECT mpTitle, mpUrl FROM mPictures') pictuple = curps.fetchall() # Get pictures from database piclist = [] for a in range(len(pictuple)): itemdict = { 'title': pictuple[a][0], 'url': pictuple[a][1], } piclist.append(itemdict) picfile.close() #xbmc.log('Mezzmo piclist dictionary: ' + str(piclist), xbmc.LOGNOTICE) return (piclist) except Exception as e: printexception() mgenlog = 'Mezzmo get picture error.' xbmc.log(mgenlog, xbmc.LOGNOTICE) mgenlogUpdate(mgenlog)
def getContentURL(contenturl): # Check for manufacturer match try: rfpos = contenturl.rfind('/', 7) searchurl = contenturl[:rfpos] + '%' svrfile = openNosyncDB() # Open server database curps = svrfile.execute( 'SELECT sManuf FROM mServers WHERE controlUrl LIKE ?', (searchurl, )) srvrtuple = curps.fetchone() # Get server from database if srvrtuple: manufacturer = srvrtuple[0] else: manufacturer = 'None' xbmc.log('Mezzmo manufacturer is: ' + str(manufacturer), xbmc.LOGDEBUG) svrfile.close() return manufacturer except Exception as e: printexception() mgenlog = 'Mezzmo content server search error.' xbmc.log(mgenlog, xbmc.LOGNOTICE) mgenlogUpdate(mgenlog)
def updateKodiPlaycount(mplaycount, mtitle, murl, mseason, mepisode, mseries, kdbfile): try: from sqlite3 import dbapi2 as sqlite except: from pysqlite2 import dbapi2 as sqlite DB = os.path.join(xbmc.translatePath("special://database"), kdbfile) db = sqlite.connect(DB) rfpos = murl.find(':', 7) # Get Mezzmo server port info serverport = '%' + murl[rfpos + 1:rfpos + 6] + '%' lastplayed = datetime.now().strftime('%Y-%m-%d %H:%M:%S') newcount = '0' xbmc.log( 'Mezzmo playcount mtitle and murl ' + mtitle.encode('utf-8', 'ignore') + ' ' + murl, xbmc.LOGDEBUG) xbmc.log('Mezzmo playcount mseason, mepisode and mseries ' + str(mseason) + ' ' + str(mepisode) + \ ' ' + str(mseries), xbmc.LOGDEBUG) if mseason == 0 and mepisode == 0: # Find movie file number curf = db.execute( 'SELECT idFile FROM movie_view WHERE strPATH LIKE ? and c00=?', ( serverport, mtitle, )) filetuple = curf.fetchone() if filetuple != None: filenumb = filetuple[0] else: filenumb = 0 curf.close() elif mseason > 0 or mseason > 0: # Find TV Episode file number curf = db.execute( 'SELECT idFile FROM episode_view WHERE strPATH LIKE ? and strTitle=? and c12=? \ and c13=? ', ( serverport, mseries, mseason, mepisode, )) filetuple = curf.fetchone() if filetuple != None: filenumb = filetuple[0] else: filenumb = 0 curf.close() if filenumb != 0 and mseason == 0 and mepisode == 0: # Update movie playcount if mplaycount == 0 and filenumb > 0: # Set playcount to 1 newcount = '1' db.execute( 'UPDATE files SET playCount=?, lastPlayed=? WHERE idFile=?', (newcount, lastplayed, filenumb)) elif mplaycount > 0 and filenumb > 0: # Set playcount to 0 db.execute( 'UPDATE files SET playCount=?, lastPlayed=? WHERE idFile=?', (newcount, '', filenumb)) elif filenumb != 0 and (mseason > 0 or mepisode > 0): # Update episode playcount if mplaycount == 0 and filenumb > 0: # Set playcount to 1 newcount = '1' db.execute( 'UPDATE files SET playCount=?, lastPlayed=? WHERE idFile=?', (newcount, lastplayed, filenumb)) elif mplaycount > 0 and filenumb > 0: # Set playcount to 0 db.execute( 'UPDATE files SET playCount=?, lastPlayed=? WHERE idFile=?', (newcount, '', filenumb)) elif filenumb == 0: mgenlog ='Mezzmo no watched action taken. File not found in Kodi DB. Please wait for sync. ' + \ mtitle.encode('utf-8', 'ignore') xbmc.log(mgenlog, xbmc.LOGNOTICE) mgenlog = '###' + mtitle.encode('utf-8', 'ignore') media.mgenlogUpdate(mgenlog) mgenlog = 'Mezzmo no watched action taken. File not found in Kodi DB. Please wait for sync.' media.mgenlogUpdate(mgenlog) if filenumb > 0: mgenlog = 'Mezzmo Kodi playcount set to ' + newcount + ' for: ' + mtitle.encode( 'utf-8', 'ignore') xbmc.log(mgenlog, xbmc.LOGNOTICE) mgenlog = '###' + mtitle.encode('utf-8', 'ignore') media.mgenlogUpdate(mgenlog) mgenlog = 'Mezzmo Kodi playcount set to ' + newcount + ' for: ' media.mgenlogUpdate(mgenlog) db.commit() db.close()
if pacount % 30 == 0: # Check for paused video every 30 seconds pastoptime = int(media.settings('pastop')) xbmc.log('Mezzmo count and stop time ' + str(pacount) + ' ' + str(pastoptime) + \ ' ' + str(player.paflag), xbmc.LOGDEBUG) try: if pastoptime > 0 and pacount >= pastoptime * 60 and player.paflag == 1: ptag = xbmc.Player().getVideoInfoTag() ptitle = media.displayTitles(ptag.getTitle().decode( 'utf-8', 'ignore')) xbmc.Player().stop() pacount = 0 mgenlog ='Mezzmo stopped paused playback: ' + ptitle.encode('utf-8','ignore') + \ ' at: ' + time.strftime("%H:%M:%S", time.gmtime(pos)) xbmc.log(mgenlog, xbmc.LOGNOTICE) mgenlog = '###' + ptitle.encode('utf-8', 'ignore') media.mgenlogUpdate(mgenlog) mgenlog = 'Mezzmo stopped paused playback at: ' + time.strftime( "%H:%M:%S", time.gmtime(pos)) media.mgenlogUpdate(mgenlog) elif player.paflag == 0: pacount = 0 except: pass if count % 1800 == 0 or count == 10: # Update cache on Kodi start and every 30 mins contenturl = media.settings('contenturl') if xbmc.Player().isPlayingVideo(): ptag = xbmc.Player().getVideoInfoTag() ptitle = media.displayTitles(ptag.getTitle().decode( 'utf-8', 'ignore')) mgenlog ='A video file is playing: ' + ptitle.encode('utf-8','ignore') + ' at: ' + \
def ghandleBrowse(content, contenturl, objectID, parentID): contentType = 'movies' itemsleft = -1 pitemsleft = -1 media.settings('contenturl', contenturl) slideshow = media.settings('slideshow') # Check if slideshow is enabled menuitem1 = addon.getLocalizedString(30347) menuitem2 = addon.getLocalizedString(30346) menuitem3 = addon.getLocalizedString(30372) menuitem4 = addon.getLocalizedString(30373) menuitem5 = addon.getLocalizedString(30379) menuitem6 = addon.getLocalizedString(30380) menuitem7 = addon.getLocalizedString(30384) menuitem8 = addon.getLocalizedString(30412) sync.deleteTexturesCache(contenturl) # Call function to delete textures cache if user enabled. #xbmc.log('Kodi version: ' + installed_version, xbmc.LOGNOTICE) try: while True: e = xml.etree.ElementTree.fromstring(content) body = e.find('.//{http://schemas.xmlsoap.org/soap/envelope/}Body') browseresponse = body.find('.//{urn:schemas-upnp-org:service:ContentDirectory:1}BrowseResponse') result = browseresponse.find('Result') NumberReturned = browseresponse.find('NumberReturned').text TotalMatches = browseresponse.find('TotalMatches').text if int(NumberReturned) == 0: dialog_text = media.translate(30421) + '\n' + xbmc.getInfoLabel("ListItem.Label") xbmcgui.Dialog().ok(media.translate(30424), dialog_text) xbmc.executebuiltin('Action(ParentDir)') break; #sanity check if itemsleft == -1: itemsleft = int(TotalMatches) elems = xml.etree.ElementTree.fromstring(result.text.encode('utf-8')) #elems = xml.etree.ElementTree.fromstring(result.text) picnotify = 0 for container in elems.findall('.//{urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/}container'): title = container.find('.//{http://purl.org/dc/elements/1.1/}title').text containerid = container.get('id') description_text = '' description = container.find('.//{urn:schemas-upnp-org:metadata-1-0/upnp/}longDescription') if description != None and description.text != None: description_text = description.text icon = container.find('.//{urn:schemas-upnp-org:metadata-1-0/upnp/}albumArtURI') if icon != None: icon = icon.text if (icon[-4:]) != '.jpg': icon = icon + '.jpg' xbmc.log('Handle browse initial icon is: ' + icon, xbmc.LOGDEBUG) itemurl = build_url({'mode': 'server', 'parentID': objectID, 'objectID': containerid, \ 'contentdirectory': contenturl}) li = xbmcgui.ListItem(title) li.setArt({'banner': icon, 'poster': icon, 'icon': icon, 'fanart': addon_fanart}) mediaClass_text = 'video' info = { 'plot': description_text, } li.setInfo(mediaClass_text, info) searchargs = urllib.urlencode({'mode': 'search', 'contentdirectory': contenturl, \ 'objectID': containerid}) li.addContextMenuItems([ (menuitem1, 'Container.Refresh'), (menuitem2, 'Action(ParentDir)') ]) xbmcplugin.addDirectoryItem(handle=addon_handle, url=itemurl, listitem=li, isFolder=True) picnotify += 1 if parentID == '0': contentType = 'top' else: contentType = 'folders' contentType = content_mapping(contentType) piclist = [] clearPictures() upnpnotify = 0 for item in elems.findall('.//{urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/}item'): title = item.find('.//{http://purl.org/dc/elements/1.1/}title').text itemid = item.get('id') icon = None albumartUri = item.find('.//{urn:schemas-upnp-org:metadata-1-0/upnp/}albumArtURI') if albumartUri != None: icon = albumartUri.text if (icon[-4:]) != '.jpg': icon = icon + '.jpg' xbmc.log('Handle browse second icon is: ' + icon, xbmc.LOGDEBUG) res = item.find('.//{urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/}res') subtitleurl = None duration_text = '' video_width = 0 video_height = 0 aspect = 0.0 validf = 0 protocol_text = '' if res != None: itemurl = res.text #xbmc.log('The current URL is: ' + itemurl, xbmc.LOGNOTICE) subtitleurl = res.get('{http://www.pv.com/pvns/}subtitleFileUri') duration_text = res.get('duration') if duration_text == None: duration_text = '00:00:00.000' elif len(duration_text) < 9: # Check for proper duration Twonky duration_text = duration_text + '.000' elif int(duration_text[len(duration_text)-3:len(duration_text)]) <> 0: duration_text = duration_text[:6] + '.000' #xbmc.log('The duration is: ' + str(duration_text), xbmc.LOGNOTICE) resolution_text = res.get('resolution') if resolution_text != None: mid = resolution_text.find('x') video_width = int(resolution_text[0:mid]) video_height = int(resolution_text[mid + 1:]) aspect = float(float(video_width) / float(video_height)) protocol = res.get('protocolInfo') if protocol != None: protocol_text = protocol #xbmc.log('The protocol is: ' + str(protocol), xbmc.LOGNOTICE) else: duration_text = '00:00:00.000' itemurl = getItemlUrl(contenturl, itemid) if upnpnotify == 0: # Do not repeat notification upnpCheck() # Check Kodi service uPNP setting upnpnotify = 1 if itemurl == 'None': dialog_text = media.translate(30393) xbmcgui.Dialog().ok(media.translate(30406), dialog_text) xbmc.executebuiltin('Action(ParentDir)') break backdropurl = item.find('.//{urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/}cvabackdrop') if backdropurl != None: backdropurl = backdropurl.text if (backdropurl [-4:]) != '.jpg': backdropurl = backdropurl + '.jpg' poster = '' thumb = '' res2 = item.findall('.//{urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/}res') for protocol in res2: protocolinfo = protocol.attrib["protocolInfo"] if 'poster' in protocolinfo: poster = protocol.text if 'thumb' in protocolinfo: thumb = protocol.text if 'fanart' in protocolinfo and backdropurl == None: backdropurl = protocol.text if 'icon' in protocolinfo and icon == None: icon = protocol.text upnpclass_text = '' upnpclass = item.find('.//{urn:schemas-upnp-org:metadata-1-0/upnp/}class') if upnpclass != None: upnpclass_text = upnpclass.text li = xbmcgui.ListItem(title) if len(thumb) > 0 and len(poster) > 0: li.setArt({'thumb': thumb, 'poster': poster, 'icon': icon, 'fanart': backdropurl}) else: li.setArt({'thumb': icon, 'poster': icon, 'icon': icon, 'fanart': backdropurl}) if subtitleurl != None: li.setSubtitles([subtitleurl]) trailerurl = item.find('.//{urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/}trailer') if trailerurl != None: trailerurl = trailerurl.text genre_text = [] for genre in item.findall('.//{urn:schemas-upnp-org:metadata-1-0/upnp/}genre'): if genre != None: genre_text.append(genre.text.encode('utf-8')) #xbmc.log('Mezzmo genre list is: ' + str(genre_text), xbmc.LOGNOTICE) aired_text = '' aired = item.find('.//{http://purl.org/dc/elements/1.1/}date') if aired != None: aired_text = aired.text album_text = '' album = item.find('.//{urn:schemas-upnp-org:metadata-1-0/upnp/}album') if album != None: album_text = album.text release_year_text = '' release_year = item.find('.//{urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/}release_year') if release_year != None: release_year_text = release_year.text release_date_text = '' release_date = item.find('.//{urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/}release_date') if release_date != None: release_date_text = release_date.text description_text = '' description = item.find('.//{urn:schemas-upnp-org:metadata-1-0/upnp/}longDescription') if description != None and description.text != None: description_text = description.text imageSearchUrl = '' imageSearchUrl = item.find('.//{urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/}imageSearchUrl') if imageSearchUrl != None: imageSearchUrl = imageSearchUrl.text artist_text = '' artist = item.find('.//{urn:schemas-upnp-org:metadata-1-0/upnp/}artist') if artist != None: artist_text = artist.text actor_list = '' cast_dict = [] # Added cast & thumbnail display from Mezzmo server cast_dict_keys = ['name','thumbnail'] actors = item.find('.//{urn:schemas-upnp-org:metadata-1-0/upnp/}artist') if actors != None and imageSearchUrl != None: actor_list = actors.text.encode('utf-8', 'ignore').replace(', Jr.' , ' Jr.').replace(', Sr.' , ' Sr.').split(',') for a in actor_list: actorSearchUrl = imageSearchUrl + "?imagesearch=" + a.lstrip().replace(" ","+") #xbmc.log('search URL: ' + actorSearchUrl, xbmc.LOGNOTICE) # uncomment for thumbnail debugging new_record = [ a.strip() , actorSearchUrl] cast_dict.append(dict(zip(cast_dict_keys, new_record))) elif actors == None: actor_list = [] for actor in item.findall('.//{urn:schemas-upnp-org:metadata-1-0/upnp/}actor'): if actor != None: actor_list.append(actor.text.encode('utf-8')) artist_text = actor_list #xbmc.log('Mezzmo actor list is: ' + str(actor_list), xbmc.LOGNOTICE) #if len(actor_list) == 0: # Sanity check for missing artists # artist_text = ["Unknown artist"] if isinstance(artist_text, str): # Sanity check for missing artists artist_text = ["Unknown artist"] creator_text = '' creator = item.find('.//{urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/}creator') if creator != None: creator_text = creator.text elif creator == None: creator = item.find('.//{http://purl.org/dc/elements/1.1/}creator') if creator != None: creator_text = creator.text director_text = '' director = item.find('.//{urn:schemas-upnp-org:metadata-1-0/upnp/}director') if director != None: creator_text = director.text date_added_text = '' date_added = item.find('.//{urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/}date_added') if date_added != None: date_added_text = date_added.text else: # Kodi uPNP date_added = item.find('.//{urn:schemas-xbmc-org:metadata-1-0/}dateadded') if date_added != None: date_added_text = date_added.text tagline_text = '' tagline = item.find('.//{urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/}tag_line') if tagline != None: tagline_text = tagline.text else: # Kodi uPNP tagline = item.find('.//{http://purl.org/dc/elements/1.1/}description') if tagline != None: tagline_text = tagline.text categories_text = 'movie' categories = item.find('.//{urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/}categories') if categories != None and categories.text != None: categories_text = categories.text.split(',')[0] # Kodi can only handle 1 media type if categories_text[:7].lower() == 'tv show': categories_text = 'episode' contentType = 'episodes' elif categories_text[:5].lower() == 'movie': categories_text = 'movie' contentType = 'movies' album_text = '' elif categories_text[:11].lower() == 'music video': categories_text = 'musicvideo' contentType = 'musicvideos' album_text = '' else: categories_text = 'video' contentType = 'videos' album_text = '' episode_text = '' episode = item.find('.//{urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/}episode') if episode != None: episode_text = episode.text season_text = '' season = item.find('.//{urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/}season') if season != None: season_text = season.text playcount = 0 playcount_text = '' playcountElem = item.find('.//{urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/}playcount') if playcountElem != None: playcount_text = playcountElem.text playcount = int(playcount_text) playcountElem = item.find('.//{urn:schemas-upnp-org:metadata-1-0/upnp/}playbackCount') if playcountElem != None: # Kodi uPNP playcount_text = playcountElem.text playcount = int(playcount_text) last_played_text = '' last_played = item.find('.//{urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/}last_played') if last_played != None: last_played_text = last_played.text last_played_text = '' # Kodi uPNP last_played = item.find('.//{urn:schemas-upnp-org:metadata-1-0/upnp/}lastPlaybackTime') if last_played != None: last_played_text = last_played.text writer_text = '' writer = item.find('.//{urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/}writers') if writer != None: writer_text = writer.text writer_text = '' # Kodi uPNP writer = item.find('.//{urn:schemas-upnp-org:metadata-1-0/upnp/}author') if writer != None: writer_text = writer.text content_rating_text = '' content_rating = item.find('.//{urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/}content_rating') if content_rating != None: content_rating_text = content_rating.text content_rating_text = '' # Kodi uPNP content_rating = item.find('.//{urn:schemas-upnp-org:metadata-1-0/upnp/}rating') if content_rating != None: content_rating_text = content_rating.text imdb_text = '' imdb = item.find('.//{urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/}imdb_id') if imdb != None: imdb_text = imdb.text dcmInfo_text = '0' dcmInfo = item.find('.//{http://www.sec.co.kr/}dcmInfo') if dcmInfo != None: dcmInfo_text = dcmInfo.text valPos = dcmInfo_text.find('BM=') + 3 dcmInfo_text = dcmInfo_text[valPos:] rating_val = '' rating = item.find('.//{urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/}rating') if rating != None: rating_val = rating.text rating_val = float(rating_val) * 2 rating_val = str(rating_val) #kodi ratings are out of 10, Mezzmo is out of 5 rating_val = '' # Kodi uPNP rating = item.find('.//{urn:schemas-xbmc-org:metadata-1-0/}userrating') if rating != None: rating_val = rating.text production_company_text = '' production_company = item.find('.//{urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/}production_company') if production_company != None: production_company_text = production_company.text production_company_text = '' production_company = item.find('.//{http://purl.org/dc/elements/1.1/}publisher') if production_company != None: production_company_text = production_company.text sort_title_text = '' sort_title = item.find('.//{urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/}sort_title') if sort_title != None: sort_title_text = sort_title.text video_codec_text = '' video_codec = item.find('.//{urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/}video_codec') if video_codec != None: video_codec_text = video_codec.text if video_codec_text == 'vc1': # adjust for proper Kodi codec display video_codec_text = 'vc-1' audio_codec_text = '' audio_codec = item.find('.//{urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/}audio_codec') if audio_codec != None: audio_codec_text = audio_codec.text audio_channels_text = '0' audio_channels = item.find('.//{urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/}audio_channels') if audio_channels != None: audio_channels_text = audio_channels.text audio_lang = '' audio_streams = item.find('.//{urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/}audio') if audio_streams != None: for stream in audio_streams.findall('.//{urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/}stream'): if stream.get('selected') == 'auto' or stream.get('selected') == 'true': audio_lang = stream.get('lang') break subtitle_lang = '' captions_streams = item.find('.//{urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/}captions') if captions_streams != None: for stream in captions_streams.findall('.//{urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/}stream'): if stream.get('selected') == 'auto' or stream.get('selected') == 'true': subtitle_lang = stream.get('language') break #mediaClass if 'video' in upnpclass_text or 'video' in protocol_text: mediaClass_text = 'video' if 'audio' in upnpclass_text or 'audio' in protocol_text: mediaClass_text = 'music' if 'photo' in upnpclass_text or 'image' in protocol_text: mediaClass_text = 'pictures' if mediaClass_text == 'video': li.addContextMenuItems([ (menuitem1, 'Container.Refresh'), (menuitem2, 'Action(ParentDir)') ]) info = { 'duration': sync.getSeconds(duration_text), 'genre': genre_text, 'year': release_year_text, 'title': title, 'plot': description_text, 'director': creator_text, 'tagline': tagline_text, 'writer': writer_text, 'cast': artist_text, 'artist': artist_text, 'rating': rating_val, 'imdbnumber': imdb_text, 'mediatype': categories_text, 'season': season_text, 'episode': episode_text, 'lastplayed': last_played_text, 'aired': aired_text, 'mpaa':content_rating_text, 'studio':production_company_text, 'playcount':playcount, 'trailer':trailerurl, 'tvshowtitle':album_text, 'dateadded':date_added_text, } li.setInfo(mediaClass_text, info) li.setProperty('ResumeTime', dcmInfo_text) li.setProperty('TotalTime', str(sync.getSeconds(duration_text))) video_info = { 'codec': video_codec_text, 'aspect': aspect, 'width': video_width, 'height': video_height, } li.addStreamInfo('video', video_info) li.addStreamInfo('audio', {'codec': audio_codec_text, 'language': audio_lang, 'channels': int(audio_channels_text)}) li.addStreamInfo('subtitle', {'language': subtitle_lang}) elif mediaClass_text == 'music': mtitle = media.displayTitles(title) # Normalize title pctitle = '"' + mtitle.encode('utf-8','ignore') + '"' # Handle commas li.addContextMenuItems([ (menuitem1, 'Container.Refresh'), (menuitem2, 'Action(ParentDir)') ]) #offsetmenu = 'Resume from ' + time.strftime("%H:%M:%S", time.gmtime(int(dcmInfo_text))) info = { 'duration': sync.getSeconds(duration_text), 'genre': genre_text, 'year': release_year_text, 'title': pctitle, 'artist': artist_text, 'rating': rating_val, 'discnumber': season_text, 'mediatype': 'song', 'tracknumber': episode_text, 'album': album_text, 'playcount':playcount, 'lastplayed': last_played_text, } #mcomment = media.mComment(info, duration_text, offsetmenu[11:]) #info.update(comment = mcomment) li.setInfo(mediaClass_text, info) contentType = 'songs' elif mediaClass_text == 'pictures': li.addContextMenuItems([ (menuitem1, 'Container.Refresh'), (menuitem2, 'Action(ParentDir)'), \ (menuitem8, 'RunScript(%s, %s)' % ("plugin.video.mezzmo", "pictures")) ]) info = { 'title': title, } li.setInfo(mediaClass_text, info) contentType = 'files' picnotify += 1 itemdict = { 'title': title, 'url': itemurl, } piclist.append(itemdict) if picnotify == int(NumberReturned): # Update picture DB updatePictures(piclist) if slideshow == 'true': # Slideshow display prompt picDisplay() itemurl = build_url({'mode': 'picture', 'itemurl': itemurl}) xbmcplugin.addDirectoryItem(handle=addon_handle, url=itemurl, listitem=li, isFolder=False) itemsleft = itemsleft - int(NumberReturned) - 1 xbmc.log('Mezzmo items left: ' + str(itemsleft), xbmc.LOGDEBUG) if itemsleft <= 0: break if pitemsleft == itemsleft: # Detect items left not incrementing mgenlog ='Mezzmo items not displayed: ' + str(pitemsleft) xbmc.log(mgenlog, xbmc.LOGNOTICE) media.mgenlogUpdate(mgenlog) break else: pitemsleft = itemsleft # get the next items offset = int(TotalMatches) - itemsleft requestedCount = 1000 if itemsleft < 1000: requestedCount = itemsleft pin = media.settings('content_pin') content = browse.Browse(contenturl, objectID, 'BrowseDirectChildren', offset, requestedCount, pin) except Exception as e: media.printexception() pass setViewMode(contentType) if contentType == 'top' or contentType == 'folders': contentType = '' xbmcplugin.setContent(addon_handle, contentType) xbmcplugin.addSortMethod(addon_handle, xbmcplugin.SORT_METHOD_UNSORTED) xbmcplugin.addSortMethod(addon_handle, xbmcplugin.SORT_METHOD_DATE) xbmcplugin.addSortMethod(addon_handle, xbmcplugin.SORT_METHOD_TITLE_IGNORE_THE) xbmcplugin.addSortMethod(addon_handle, xbmcplugin.SORT_METHOD_VIDEO_YEAR) xbmcplugin.addSortMethod(addon_handle, xbmcplugin.SORT_METHOD_GENRE) xbmcplugin.addSortMethod(addon_handle, xbmcplugin.SORT_METHOD_DURATION) xbmcplugin.endOfDirectory(addon_handle)