Merge branch 'master' of https://github.com/marcelveldt/plugin.video.mb3sync
This commit is contained in:
commit
7e33194e84
7 changed files with 212 additions and 46 deletions
|
@ -130,8 +130,10 @@ class DownloadUtils():
|
|||
self.logMsg("Session Id : " + str(sessionId))
|
||||
|
||||
# post capability data
|
||||
playableMediaTypes = "Audio,Video,Photo"
|
||||
supportedCommands = "Play,Playstate,DisplayContent,GoHome,SendString,GoToSettings,DisplayMessage,PlayNext"
|
||||
#playableMediaTypes = "Audio,Video,Photo"
|
||||
playableMediaTypes = "Audio,Video"
|
||||
#supportedCommands = "Play,Playstate,DisplayContent,GoHome,SendString,GoToSettings,DisplayMessage,PlayNext"
|
||||
supportedCommands = "Play,Playstate,SendString,DisplayMessage,PlayNext"
|
||||
|
||||
url = "http://" + mb3Host + ":" + mb3Port + "/mediabrowser/Sessions/Capabilities?Id=" + sessionId + "&PlayableMediaTypes=" + playableMediaTypes + "&SupportedCommands=" + supportedCommands + "&SupportsMediaControl=True"
|
||||
postData = {}
|
||||
|
|
|
@ -10,6 +10,7 @@ import json
|
|||
|
||||
import Utils as utils
|
||||
from WriteKodiDB import WriteKodiDB
|
||||
from DownloadUtils import DownloadUtils
|
||||
|
||||
class Kodi_Monitor(xbmc.Monitor):
|
||||
def __init__(self, *args, **kwargs):
|
||||
|
@ -20,7 +21,10 @@ class Kodi_Monitor(xbmc.Monitor):
|
|||
|
||||
#this library monitor is used to detect a watchedstate change by the user through the library
|
||||
def onNotification (self,sender,method,data):
|
||||
|
||||
addon = xbmcaddon.Addon(id='plugin.video.mb3sync')
|
||||
port = addon.getSetting('port')
|
||||
host = addon.getSetting('ipaddress')
|
||||
server = host + ":" + port
|
||||
if method == "VideoLibrary.OnUpdate":
|
||||
|
||||
jsondata = json.loads(data)
|
||||
|
@ -33,4 +37,20 @@ class Kodi_Monitor(xbmc.Monitor):
|
|||
if playcount != None:
|
||||
utils.logMsg("MB# Sync","Kodi_Monitor--> VideoLibrary.OnUpdate : " + str(data),2)
|
||||
WriteKodiDB().updatePlayCountFromKodi(item, type, playcount)
|
||||
if method == "VideoLibrary.OnRemove":
|
||||
xbmc.log('Intercepted remove from sender: ' + sender + ' method: ' + method + ' data: ' + data)
|
||||
jsondata = json.loads(data)
|
||||
if jsondata != None:
|
||||
if jsondata.get("type") == "episode":
|
||||
episodeid = jsondata.get("id")
|
||||
WINDOW = xbmcgui.Window( 10000 )
|
||||
MBlist = WINDOW.getProperty("episodeid" + str(episodeid)).split(";;")
|
||||
#NEED TO CHECK IF ITEM STILL EXISTS ON EMBY SERVER
|
||||
#return_value = xbmcgui.Dialog().yesno("Confirm Delete", "Delete: "+ MBlist[0] + "\n on Emby Server?\nEmbyID: " + MBlist[1])
|
||||
#if return_value:
|
||||
# url='http://' + server + '/mediabrowser/Items/' + MBlist[1]
|
||||
# xbmc.log('Deleting via URL: ' + url)
|
||||
# DownloadUtils().downloadUrl(url, type="DELETE")
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -77,13 +77,14 @@ class LibrarySync():
|
|||
addon = xbmcaddon.Addon(id='plugin.video.mb3sync')
|
||||
WINDOW = xbmcgui.Window( 10000 )
|
||||
pDialog = None
|
||||
startedSync = datetime.today()
|
||||
|
||||
try:
|
||||
dbSyncIndication = addon.getSetting("dbSyncIndication")
|
||||
|
||||
if(addon.getSetting("SyncFirstMovieRunDone") != 'true'):
|
||||
if(addon.getSetting("SyncFirstMovieRunDone") != "true" or dbSyncIndication == "Dialog Progress"):
|
||||
pDialog = xbmcgui.DialogProgress()
|
||||
elif(dbSyncIndication == "Progress"):
|
||||
elif(dbSyncIndication == "BG Progress"):
|
||||
pDialog = xbmcgui.DialogProgressBG()
|
||||
|
||||
if(pDialog != None):
|
||||
|
@ -163,6 +164,14 @@ class LibrarySync():
|
|||
total = len(allMB3Movies) + 1
|
||||
count = 1
|
||||
|
||||
# process box sets - TODO cope with movies removed from a set
|
||||
boxsets = ReadEmbyDB().getBoxSets()
|
||||
for boxset in boxsets:
|
||||
boxsetMovies = ReadEmbyDB().getMoviesInBoxSet(boxset["Id"])
|
||||
WriteKodiDB().addBoxsetToKodiLibrary(boxset)
|
||||
for boxsetMovie in boxsetMovies:
|
||||
WriteKodiDB().updateBoxsetToKodiLibrary(boxsetMovie,boxset)
|
||||
|
||||
#process updates
|
||||
allKodiMovies = ReadKodiDB().getKodiMovies(True)
|
||||
for item in allMB3Movies:
|
||||
|
@ -217,18 +226,28 @@ class LibrarySync():
|
|||
|
||||
addon.setSetting("SyncFirstMovieRunDone", "true")
|
||||
|
||||
if(dbSyncIndication == "Notification"):
|
||||
notificationString = ""
|
||||
if(totalItemsAdded > 0):
|
||||
notificationString += "Added:" + str(totalItemsAdded) + " "
|
||||
if(totalItemsUpdated > 0):
|
||||
notificationString += "Updated:" + str(totalItemsUpdated) + " "
|
||||
if(totalItemsDeleted > 0):
|
||||
notificationString += "Deleted:" + str(totalItemsDeleted) + " "
|
||||
# display notification if set up
|
||||
notificationString = ""
|
||||
if(totalItemsAdded > 0):
|
||||
notificationString += "Added:" + str(totalItemsAdded) + " "
|
||||
if(totalItemsUpdated > 0):
|
||||
notificationString += "Updated:" + str(totalItemsUpdated) + " "
|
||||
if(totalItemsDeleted > 0):
|
||||
notificationString += "Deleted:" + str(totalItemsDeleted) + " "
|
||||
|
||||
timeTaken = datetime.today() - startedSync
|
||||
timeTakenString = str(int(timeTaken.seconds / 60)) + ":" + str(timeTaken.seconds % 60)
|
||||
utils.logMsg("Sync Movies", "Finished " + timeTakenString + " " + notificationString, 0)
|
||||
|
||||
if(dbSyncIndication == "Notify OnChange" and notificationString != ""):
|
||||
notificationString = "(" + timeTakenString + ") " + notificationString
|
||||
xbmc.executebuiltin("XBMC.Notification(Movie Sync: " + notificationString + ",)")
|
||||
elif(dbSyncIndication == "Notify OnFinish"):
|
||||
if(notificationString == ""):
|
||||
notificationString = "Done"
|
||||
notificationString = "(" + timeTakenString + ") " + notificationString
|
||||
xbmc.executebuiltin("XBMC.Notification(Movie Sync: " + notificationString + ",)")
|
||||
|
||||
|
||||
finally:
|
||||
if(pDialog != None):
|
||||
pDialog.close()
|
||||
|
@ -240,13 +259,14 @@ class LibrarySync():
|
|||
addon = xbmcaddon.Addon(id='plugin.video.mb3sync')
|
||||
WINDOW = xbmcgui.Window( 10000 )
|
||||
pDialog = None
|
||||
startedSync = datetime.today()
|
||||
|
||||
try:
|
||||
dbSyncIndication = addon.getSetting("dbSyncIndication")
|
||||
|
||||
if(addon.getSetting("SyncFirstTVRunDone") != 'true'):
|
||||
if(addon.getSetting("SyncFirstTVRunDone") != "true" or dbSyncIndication == "Dialog Progress"):
|
||||
pDialog = xbmcgui.DialogProgress()
|
||||
elif(dbSyncIndication == "Progress"):
|
||||
elif(dbSyncIndication == "BG Progress"):
|
||||
pDialog = xbmcgui.DialogProgressBG()
|
||||
|
||||
if(pDialog != None):
|
||||
|
@ -562,19 +582,29 @@ class LibrarySync():
|
|||
self.doKodiLibraryUpdate(True, pDialog)
|
||||
|
||||
addon.setSetting("SyncFirstTVRunDone", "true")
|
||||
|
||||
# display notification if set up
|
||||
notificationString = ""
|
||||
if(totalItemsAdded > 0):
|
||||
notificationString += "Added:" + str(totalItemsAdded) + " "
|
||||
if(totalItemsUpdated > 0):
|
||||
notificationString += "Updated:" + str(totalItemsUpdated) + " "
|
||||
if(totalItemsDeleted > 0):
|
||||
notificationString += "Deleted:" + str(totalItemsDeleted) + " "
|
||||
|
||||
timeTaken = datetime.today() - startedSync
|
||||
timeTakenString = str(int(timeTaken.seconds / 60)) + ":" + str(timeTaken.seconds % 60)
|
||||
utils.logMsg("Sync Episodes", "Finished " + timeTakenString + " " + notificationString, 0)
|
||||
|
||||
if(dbSyncIndication == "Notification"):
|
||||
notificationString = ""
|
||||
if(totalItemsAdded > 0):
|
||||
notificationString += "Added:" + str(totalItemsAdded) + " "
|
||||
if(totalItemsUpdated > 0):
|
||||
notificationString += "Updated:" + str(totalItemsUpdated) + " "
|
||||
if(totalItemsDeleted > 0):
|
||||
notificationString += "Deleted:" + str(totalItemsDeleted) + " "
|
||||
if(dbSyncIndication == "Notify OnChange" and notificationString != ""):
|
||||
notificationString = "(" + timeTakenString + ") " + notificationString
|
||||
xbmc.executebuiltin("XBMC.Notification(Episode Sync: " + notificationString + ",)")
|
||||
elif(dbSyncIndication == "Notify OnFinish"):
|
||||
if(notificationString == ""):
|
||||
notificationString = "Done"
|
||||
xbmc.executebuiltin("XBMC.Notification(TV Sync: " + notificationString + ",)")
|
||||
|
||||
notificationString = "(" + timeTakenString + ") " + notificationString
|
||||
xbmc.executebuiltin("XBMC.Notification(Episode Sync: " + notificationString + ",)")
|
||||
|
||||
finally:
|
||||
if(pDialog != None):
|
||||
pDialog.close()
|
||||
|
@ -590,9 +620,9 @@ class LibrarySync():
|
|||
try:
|
||||
dbSyncIndication = addon.getSetting("dbSyncIndication")
|
||||
|
||||
if(addon.getSetting("SyncFirstMusicVideoRunDone") != 'true'):
|
||||
if(addon.getSetting("SyncFirstMusicVideoRunDone") != "true" or dbSyncIndication == "Dialog Progress"):
|
||||
pDialog = xbmcgui.DialogProgress()
|
||||
elif(dbSyncIndication == "Progress"):
|
||||
elif(dbSyncIndication == "BG Progress"):
|
||||
pDialog = xbmcgui.DialogProgressBG()
|
||||
|
||||
if(pDialog != None):
|
||||
|
@ -732,16 +762,16 @@ class LibrarySync():
|
|||
addon = xbmcaddon.Addon(id='plugin.video.mb3sync')
|
||||
WINDOW = xbmcgui.Window( 10000 )
|
||||
pDialog = None
|
||||
|
||||
startedSync = datetime.today()
|
||||
processMovies = True
|
||||
processTvShows = True
|
||||
|
||||
try:
|
||||
playCountSyncIndication = addon.getSetting("playCountSyncIndication")
|
||||
|
||||
if(addon.getSetting("SyncFirstCountsRunDone") != 'true'):
|
||||
if(addon.getSetting("SyncFirstCountsRunDone") != "true" or playCountSyncIndication == "Dialog Progress"):
|
||||
pDialog = xbmcgui.DialogProgress()
|
||||
elif(playCountSyncIndication == "Progress"):
|
||||
elif(playCountSyncIndication == "BG Progress"):
|
||||
pDialog = xbmcgui.DialogProgressBG()
|
||||
|
||||
if(pDialog != None):
|
||||
|
@ -846,6 +876,8 @@ class LibrarySync():
|
|||
userData=API().getUserData(episode)
|
||||
timeInfo = API().getTimeInfo(episode)
|
||||
if kodiItem != None:
|
||||
WINDOW = xbmcgui.Window( 10000 )
|
||||
WINDOW.setProperty("episodeid" + str(kodiItem['episodeid']), episode.get('Name') + ";;" + episode.get('Id'))
|
||||
if kodiItem['playcount'] != int(userData.get("PlayCount")):
|
||||
updated = WriteKodiDB().updateProperty(kodiItem,"playcount",int(userData.get("PlayCount")),"episode")
|
||||
if(updated):
|
||||
|
@ -869,17 +901,27 @@ class LibrarySync():
|
|||
showCurrent += 1
|
||||
|
||||
addon.setSetting("SyncFirstCountsRunDone", "true")
|
||||
|
||||
# display notification if set up
|
||||
notificationString = ""
|
||||
if(totalPositionsUpdated > 0):
|
||||
notificationString += "Pos:" + str(totalPositionsUpdated) + " "
|
||||
if(totalCountsUpdated > 0):
|
||||
notificationString += "Counts:" + str(totalCountsUpdated) + " "
|
||||
|
||||
timeTaken = datetime.today() - startedSync
|
||||
timeTakenString = str(int(timeTaken.seconds / 60)) + ":" + str(timeTaken.seconds % 60)
|
||||
utils.logMsg("Sync PlayCount", "Finished " + timeTakenString + " " + notificationString, 0)
|
||||
|
||||
if(playCountSyncIndication == "Notification"):
|
||||
notificationString = ""
|
||||
if(totalPositionsUpdated > 0):
|
||||
notificationString += "Pos:" + str(totalPositionsUpdated) + " "
|
||||
if(totalCountsUpdated > 0):
|
||||
notificationString += "Counts:" + str(totalCountsUpdated) + " "
|
||||
if(playCountSyncIndication == "Notify OnChange" and notificationString != ""):
|
||||
notificationString = "(" + timeTakenString + ") " + notificationString
|
||||
xbmc.executebuiltin("XBMC.Notification(PlayCount Sync: " + notificationString + ",)")
|
||||
elif(playCountSyncIndication == "Notify OnFinish"):
|
||||
if(notificationString == ""):
|
||||
notificationString = "Done"
|
||||
xbmc.executebuiltin("XBMC.Notification(Play Sync: " + notificationString + ",)")
|
||||
|
||||
notificationString = "(" + timeTakenString + ") " + notificationString
|
||||
xbmc.executebuiltin("XBMC.Notification(PlayCount Sync: " + notificationString + ",)")
|
||||
|
||||
finally:
|
||||
if(pDialog != None):
|
||||
pDialog.close()
|
||||
|
|
|
@ -273,4 +273,46 @@ class ReadEmbyDB():
|
|||
'type' : type,
|
||||
'id' : view.get("Id")})
|
||||
return collections
|
||||
|
||||
def getBoxSets(self):
|
||||
result = None
|
||||
|
||||
addon = xbmcaddon.Addon(id='plugin.video.mb3sync')
|
||||
port = addon.getSetting('port')
|
||||
host = addon.getSetting('ipaddress')
|
||||
server = host + ":" + port
|
||||
|
||||
downloadUtils = DownloadUtils()
|
||||
userid = downloadUtils.getUserId()
|
||||
|
||||
url = server + '/mediabrowser/Users/' + userid + '/Items?SortBy=SortName&IsVirtualUnaired=false&IsMissing=False&Fields=Name,SortName,CumulativeRunTimeTicks&Recursive=true&SortOrder=Ascending&IncludeItemTypes=BoxSet&format=json&ImageTypeLimit=1'
|
||||
|
||||
jsonData = downloadUtils.downloadUrl(url, suppress=True, popup=0)
|
||||
|
||||
if jsonData != None and jsonData != "":
|
||||
result = json.loads(jsonData)
|
||||
if(result.has_key('Items')):
|
||||
result = result['Items']
|
||||
return result
|
||||
|
||||
def getMoviesInBoxSet(self,boxsetId):
|
||||
result = None
|
||||
|
||||
addon = xbmcaddon.Addon(id='plugin.video.mb3sync')
|
||||
port = addon.getSetting('port')
|
||||
host = addon.getSetting('ipaddress')
|
||||
server = host + ":" + port
|
||||
|
||||
downloadUtils = DownloadUtils()
|
||||
userid = downloadUtils.getUserId()
|
||||
|
||||
url = server + '/mediabrowser/Users/' + userid + '/Items?ParentId=' + boxsetId + '&Fields=ItemCounts&format=json&ImageTypeLimit=1'
|
||||
|
||||
jsonData = downloadUtils.downloadUrl(url, suppress=True, popup=0)
|
||||
|
||||
if jsonData != None and jsonData != "":
|
||||
result = json.loads(jsonData)
|
||||
if(result.has_key('Items')):
|
||||
result = result['Items']
|
||||
return result
|
||||
|
||||
|
|
|
@ -23,7 +23,8 @@ from PlayUtils import PlayUtils
|
|||
from DownloadUtils import DownloadUtils
|
||||
downloadUtils = DownloadUtils()
|
||||
addonSettings = xbmcaddon.Addon(id='plugin.video.mb3sync')
|
||||
language = addonSettings.getLocalizedString
|
||||
language = addonSettings.getLocalizedString
|
||||
DATABASE_VERSION_HELIX = "90"
|
||||
|
||||
def logMsg(title, msg, level = 1):
|
||||
logLevel = int(addonSettings.getSetting("logLevel"))
|
||||
|
@ -88,7 +89,7 @@ def addKodiSource(name, path, type):
|
|||
#add new source to database, common way is to add it directly to the Kodi DB. Fallback to adding it to the sources.xml
|
||||
#return boolean wether a manual reboot is required.
|
||||
#todo: Do feature request with Kodi team to get support for adding a source by the json API
|
||||
dbPath = xbmc.translatePath("special://userdata/Database/MyVideos90.db")
|
||||
dbPath = xbmc.translatePath("special://userdata/Database/MyVideos%s.db" % DATABASE_VERSION_HELIX)
|
||||
|
||||
error = False
|
||||
if xbmcvfs.exists(dbPath):
|
||||
|
|
|
@ -791,7 +791,7 @@ class WriteKodiDB():
|
|||
#if wanted this feature can be extended to also update the other artwork
|
||||
tvshowid = KodiItem["tvshowid"]
|
||||
|
||||
dbPath = xbmc.translatePath("special://userdata/Database/MyVideos90.db")
|
||||
dbPath = xbmc.translatePath("special://userdata/Database/MyVideos%s.db" % utils.DATABASE_VERSION_HELIX)
|
||||
connection = sqlite3.connect(dbPath)
|
||||
cursor = connection.cursor( )
|
||||
|
||||
|
@ -820,7 +820,7 @@ class WriteKodiDB():
|
|||
|
||||
utils.logMsg("MB3 Sync","setting resume point in kodi db..." + fileType + ": " + str(id))
|
||||
xbmc.sleep(sleepVal)
|
||||
dbPath = xbmc.translatePath("special://userdata/Database/MyVideos90.db")
|
||||
dbPath = xbmc.translatePath("special://userdata/Database/MyVideos%s.db" % utils.DATABASE_VERSION_HELIX)
|
||||
connection = sqlite3.connect(dbPath)
|
||||
cursor = connection.cursor( )
|
||||
|
||||
|
@ -874,7 +874,8 @@ class WriteKodiDB():
|
|||
|
||||
xbmc.sleep(sleepVal)
|
||||
|
||||
dbPath = xbmc.translatePath("special://userdata/Database/MyVideos90.db")
|
||||
dbPath = xbmc.translatePath("special://userdata/Database/MyVideos%s.db" % utils.DATABASE_VERSION_HELIX)
|
||||
|
||||
connection = sqlite3.connect(dbPath)
|
||||
cursor = connection.cursor()
|
||||
|
||||
|
@ -910,3 +911,61 @@ class WriteKodiDB():
|
|||
cursor.close()
|
||||
|
||||
return True
|
||||
|
||||
def addBoxsetToKodiLibrary(self, boxset):
|
||||
#use sqlite to set add the set
|
||||
dbPath = xbmc.translatePath("special://userdata/Database/MyVideos%s.db" % utils.DATABASE_VERSION_HELIX)
|
||||
|
||||
connection = sqlite3.connect(dbPath)
|
||||
cursor = connection.cursor()
|
||||
|
||||
strSet = boxset["Name"]
|
||||
# check if exists
|
||||
cursor.execute("SELECT idSet FROM sets WHERE strSet = ?", (strSet,))
|
||||
result = cursor.fetchone()
|
||||
setid = None
|
||||
if result != None:
|
||||
setid = result[0]
|
||||
currentsetartsql = "SELECT type, url FROM art where media_type = ? and media_id = ? and url != ''"
|
||||
cursor.execute(currentsetartsql, ("set", setid))
|
||||
existing_type_map = {}
|
||||
rows = cursor.fetchall()
|
||||
for row in rows:
|
||||
existing_type_map[row[0] ] = row[1]
|
||||
|
||||
artwork = {}
|
||||
artwork["poster"] = API().getArtwork(boxset, "Primary")
|
||||
artwork["banner"] = API().getArtwork(boxset, "Banner")
|
||||
artwork["clearlogo"] = API().getArtwork(boxset, "Logo")
|
||||
artwork["clearart"] = API().getArtwork(boxset, "Art")
|
||||
artwork["landscape"] = API().getArtwork(boxset, "Thumb")
|
||||
artwork["discart"] = API().getArtwork(boxset, "Disc")
|
||||
artwork["fanart"] = API().getArtwork(boxset, "Backdrop")
|
||||
|
||||
art_types = {'poster','fanart','landscape','clearlogo','clearart','banner','discart'}
|
||||
for update_type in art_types:
|
||||
if ( update_type in existing_type_map ):
|
||||
if ( existing_type_map[update_type] != artwork[update_type] ) and artwork[update_type] != '':
|
||||
setupdateartsql = "UPDATE art SET url = ? where media_type = ? and media_id = ? and type = ?"
|
||||
cursor.execute(setupdateartsql,(artwork[update_type],"set",setid,update_type))
|
||||
elif artwork[update_type] != '':
|
||||
setartsql = "INSERT INTO art(media_id, media_type, type, url) VALUES(?,?,?,?)"
|
||||
cursor.execute(setartsql,(setid,"set",update_type,artwork[update_type]))
|
||||
|
||||
if setid == None:
|
||||
# insert not exists
|
||||
setssql="INSERT INTO sets (idSet, strSet) values(?, ?)"
|
||||
cursor.execute(setssql, (None,strSet))
|
||||
#if OK:
|
||||
result = cursor.fetchone()
|
||||
if result != None:
|
||||
setid = result[0]
|
||||
connection.commit()
|
||||
cursor.close()
|
||||
|
||||
return True
|
||||
|
||||
def updateBoxsetToKodiLibrary(self, boxsetmovie, boxset):
|
||||
strSet = boxset["Name"]
|
||||
kodiMovie = ReadKodiDB().getKodiMovie(boxsetmovie["Id"])
|
||||
WriteKodiDB().updateProperty(kodiMovie,"set",strSet,"movie",True)
|
|
@ -11,8 +11,8 @@
|
|||
<setting id="enablePlayCountSync" type="bool" label="Enable watched/resume status sync" default="true" visible="true" enable="true" />
|
||||
<setting id="syncSettingStartup" type="labelenum" label="Startup Sync:" values="Full Sync|Incremental Sync|None" default="Full Sync" />
|
||||
<setting id="syncSettingBackground" type="labelenum" label="Scheduled Sync:" values="Full Sync|Incremental Sync|None" default="Full Sync" visible="true" enable="true" />
|
||||
<setting id="dbSyncIndication" type="labelenum" label="DB Sync Indication:" values="None|Notification|Progress" default="None" />
|
||||
<setting id="playCountSyncIndication" type="labelenum" label="Play Count Sync Indication:" values="None|Notification|Progress" default="None" />
|
||||
<setting id="dbSyncIndication" type="labelenum" label="DB Sync Indication:" values="None|Notify OnChange|Notify OnFinish|BG Progress|Dialog Progress" default="None" />
|
||||
<setting id="playCountSyncIndication" type="labelenum" label="Play Count Sync Indication:" values="None|Notify OnChange|Notify OnFinish|BG Progress|Dialog Progress" default="None" />
|
||||
</category>
|
||||
|
||||
<category label="30014"> <!-- MediaBrowser -->
|
||||
|
|
Loading…
Reference in a new issue