Major music overhaul: Direct Paths should now work!
- Remember to always use Direct Paths with Music ;-) - Fixes #84
This commit is contained in:
parent
ec6a526f09
commit
cbb44e4ccf
5 changed files with 154 additions and 19 deletions
|
@ -1894,3 +1894,8 @@ msgstr ""
|
|||
msgctxt "#39710"
|
||||
msgid "burn-in"
|
||||
msgstr ""
|
||||
|
||||
# Dialog text if PKC detected a new Music library and Kodi needs to be restarted
|
||||
msgctxt "#39711"
|
||||
msgid "New Plex music library detected. Sorry, but we need to restart Kodi now due to the changes made."
|
||||
msgstr ""
|
||||
|
|
|
@ -7,7 +7,7 @@ import xbmc
|
|||
import xbmcgui
|
||||
|
||||
from utils import settings, window, language as lang, tryEncode, \
|
||||
advancessettings_xml
|
||||
advancedsettings_xml
|
||||
import downloadutils
|
||||
from userclient import UserClient
|
||||
|
||||
|
@ -401,7 +401,7 @@ class InitialSetup():
|
|||
dialog = self.dialog
|
||||
|
||||
# Get current Kodi video cache setting
|
||||
cache = advancessettings_xml(['cache', 'memorysize'])
|
||||
cache, _ = advancedsettings_xml(['cache', 'memorysize'])
|
||||
if cache is not None:
|
||||
cache = str(cache.text)
|
||||
else:
|
||||
|
|
|
@ -29,6 +29,7 @@ from library_sync.get_metadata import Threaded_Get_Metadata
|
|||
from library_sync.process_metadata import Threaded_Process_Metadata
|
||||
import library_sync.sync_info as sync_info
|
||||
from library_sync.fanart import Process_Fanart_Thread
|
||||
import music
|
||||
|
||||
###############################################################################
|
||||
|
||||
|
@ -71,6 +72,7 @@ class LibrarySync(Thread):
|
|||
self.enableMusic = settings('enableMusic') == "true"
|
||||
self.enableBackgroundSync = settings(
|
||||
'enableBackgroundSync') == "true"
|
||||
self.direct_paths = settings('useDirectPaths') == '1'
|
||||
|
||||
# Init for replacing paths
|
||||
window('remapSMB', value=settings('remapSMB'))
|
||||
|
@ -295,6 +297,15 @@ class LibrarySync(Thread):
|
|||
}
|
||||
if self.enableMusic:
|
||||
process['music'] = self.PlexMusic
|
||||
if self.direct_paths is True:
|
||||
if music.set_excludefromscan_music_folders() is True:
|
||||
log.info('Detected new Music library - restarting now')
|
||||
# 'New Plex music library detected. Sorry, but we need to
|
||||
# restart Kodi now due to the changes made.'
|
||||
dialog('ok', lang(29999), lang(39711))
|
||||
from xbmc import executebuiltin
|
||||
executebuiltin('RestartApp')
|
||||
return False
|
||||
|
||||
# Do the processing
|
||||
for itemtype in process:
|
||||
|
|
119
resources/lib/music.py
Normal file
119
resources/lib/music.py
Normal file
|
@ -0,0 +1,119 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from logging import getLogger
|
||||
from re import compile as re_compile
|
||||
import xml.etree.ElementTree as etree
|
||||
|
||||
from utils import advancedsettings_xml, indent, tryEncode
|
||||
from PlexFunctions import get_plex_sections
|
||||
from PlexAPI import API
|
||||
import variables as v
|
||||
|
||||
###############################################################################
|
||||
log = getLogger("PLEX."+__name__)
|
||||
|
||||
REGEX_MUSICPATH = re_compile(r'''^\^(.+)\$$''')
|
||||
###############################################################################
|
||||
|
||||
|
||||
def get_current_music_folders():
|
||||
"""
|
||||
Returns a list of encoded strings as paths to the currently "blacklisted"
|
||||
excludefromscan music folders in the advancedsettings.xml
|
||||
"""
|
||||
paths = []
|
||||
root, _ = advancedsettings_xml(['audio', 'excludefromscan'])
|
||||
if root is None:
|
||||
return paths
|
||||
|
||||
for element in root:
|
||||
try:
|
||||
path = REGEX_MUSICPATH.findall(element.text)[0]
|
||||
except IndexError:
|
||||
log.error('Could not parse %s of xml element %s'
|
||||
% (element.text, element.tag))
|
||||
continue
|
||||
else:
|
||||
paths.append(path)
|
||||
return paths
|
||||
|
||||
|
||||
def set_excludefromscan_music_folders():
|
||||
"""
|
||||
Gets a complete list of paths for music libraries from the PMS. Sets them
|
||||
to be excluded in the advancedsettings.xml from being scanned by Kodi.
|
||||
Existing keys will be replaced
|
||||
|
||||
Returns False if no new Plex libraries needed to be exluded, True otherwise
|
||||
"""
|
||||
changed = False
|
||||
write_xml = False
|
||||
xml = get_plex_sections()
|
||||
try:
|
||||
xml[0].attrib
|
||||
except (TypeError, IndexError, AttributeError):
|
||||
log.error('Could not get Plex sections')
|
||||
return
|
||||
# Build paths
|
||||
paths = []
|
||||
api = API(item=None)
|
||||
for library in xml:
|
||||
if library.attrib['type'] != v.PLEX_TYPE_ARTIST:
|
||||
# Only look at music libraries
|
||||
continue
|
||||
for location in library:
|
||||
if location.tag == 'Location':
|
||||
path = api.validatePlayurl(location.attrib['path'],
|
||||
typus=v.PLEX_TYPE_ARTIST,
|
||||
forceCheck=True)
|
||||
path = tryEncode(path)
|
||||
paths.append(__turn_to_regex(path))
|
||||
# Get existing advancedsettings
|
||||
root, tree = advancedsettings_xml(['audio', 'excludefromscan'],
|
||||
force_create=True)
|
||||
|
||||
for path in paths:
|
||||
for element in root:
|
||||
if element.text == path:
|
||||
# Path already excluded
|
||||
break
|
||||
else:
|
||||
changed = True
|
||||
write_xml = True
|
||||
log.info('New Plex music library detected: %s' % path)
|
||||
element = etree.Element(tag='regexp')
|
||||
element.text = path
|
||||
root.append(element)
|
||||
|
||||
# Delete obsolete entries (unlike above, we don't change 'changed' to not
|
||||
# enforce a restart)
|
||||
for element in root:
|
||||
for path in paths:
|
||||
if element.text == path:
|
||||
break
|
||||
else:
|
||||
log.info('Deleting Plex music library from advancedsettings: %s'
|
||||
% element.text)
|
||||
root.remove(element)
|
||||
write_xml = True
|
||||
|
||||
if write_xml is True:
|
||||
indent(tree.getroot())
|
||||
tree.write('%sadvancedsettings.xml' % v.KODI_PROFILE)
|
||||
return changed
|
||||
|
||||
|
||||
def __turn_to_regex(path):
|
||||
"""
|
||||
Turns a path into regex expression to be fed to Kodi's advancedsettings.xml
|
||||
"""
|
||||
# Make sure we have a slash or backslash at the end of the path
|
||||
if '/' in path:
|
||||
if not path.endswith('/'):
|
||||
path = '%s/' % path
|
||||
else:
|
||||
if not path.endswith('\\'):
|
||||
path = '%s\\' % path
|
||||
# Need to escape backslashes
|
||||
path = path.replace('\\', '\\\\')
|
||||
# Beginning of path only needs to be similar
|
||||
return '^%s' % path
|
|
@ -23,7 +23,7 @@ import xbmcaddon
|
|||
import xbmcgui
|
||||
|
||||
from variables import DB_VIDEO_PATH, DB_MUSIC_PATH, DB_TEXTURE_PATH, \
|
||||
DB_PLEX_PATH
|
||||
DB_PLEX_PATH, KODI_PROFILE
|
||||
|
||||
###############################################################################
|
||||
|
||||
|
@ -522,9 +522,11 @@ def __setSubElement(element, subelement):
|
|||
return answ
|
||||
|
||||
|
||||
def advancessettings_xml(node_list, new_value=None, attrib=None):
|
||||
def advancedsettings_xml(node_list, new_value=None, attrib=None,
|
||||
force_create=False):
|
||||
"""
|
||||
Returns the etree element for nodelist (if it exists) and None if not set
|
||||
Returns the etree element for nodelist (if it exists) and the tree. None if
|
||||
not set
|
||||
|
||||
node_list is a list of node names starting from the outside, ignoring the
|
||||
outter advancedsettings. Example nodelist=['video', 'busydialogdelayms']
|
||||
|
@ -547,28 +549,29 @@ def advancessettings_xml(node_list, new_value=None, attrib=None):
|
|||
|
||||
If the dict attrib is set, the Element's attributs will be appended
|
||||
accordingly
|
||||
|
||||
force_create=True will forcibly create the key even if no value is provided
|
||||
"""
|
||||
path = '%sadvancedsettings.xml' % xbmc.translatePath("special://profile/")
|
||||
path = '%sadvancedsettings.xml' % KODI_PROFILE
|
||||
try:
|
||||
xml = etree.parse(path)
|
||||
tree = etree.parse(path)
|
||||
except IOError:
|
||||
# Document is blank or missing
|
||||
if new_value is None and attrib is None:
|
||||
if new_value is None and attrib is None and force_create is False:
|
||||
log.debug('Could not parse advancedsettings.xml, returning None')
|
||||
return
|
||||
# Create topmost xml entry
|
||||
root = etree.Element('advancedsettings')
|
||||
else:
|
||||
root = xml.getroot()
|
||||
tree = etree.ElementTree(element=etree.Element('advancedsettings'))
|
||||
root = tree.getroot()
|
||||
element = root
|
||||
|
||||
# Reading values
|
||||
if new_value is None and attrib is None:
|
||||
if new_value is None and attrib is None and force_create is False:
|
||||
for node in node_list:
|
||||
element = element.find(node)
|
||||
if element is None:
|
||||
break
|
||||
return element
|
||||
return element, tree
|
||||
|
||||
# Setting new values. Get correct element first
|
||||
for node in node_list:
|
||||
|
@ -581,11 +584,8 @@ def advancessettings_xml(node_list, new_value=None, attrib=None):
|
|||
# Indent and make readable
|
||||
indent(root)
|
||||
# Safe the changed xml
|
||||
try:
|
||||
xml.write(path)
|
||||
except NameError:
|
||||
etree.ElementTree(root).write(path)
|
||||
return element
|
||||
tree.write(path)
|
||||
return element, tree
|
||||
|
||||
|
||||
def advancedsettings_tweaks():
|
||||
|
@ -595,7 +595,7 @@ def advancedsettings_tweaks():
|
|||
Changes advancedsettings.xml, musiclibrary:
|
||||
backgroundupdate set to "true"
|
||||
"""
|
||||
advancessettings_xml(['musiclibrary', 'backgroundupdate'],
|
||||
advancedsettings_xml(['musiclibrary', 'backgroundupdate'],
|
||||
new_value='true')
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue