Major music overhaul: Direct Paths should now work!

- Remember to always use Direct Paths with Music ;-)
- Fixes #84
This commit is contained in:
tomkat83 2017-05-06 17:04:09 +02:00
parent ec6a526f09
commit cbb44e4ccf
5 changed files with 154 additions and 19 deletions

View file

@ -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 ""

View file

@ -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:

View file

@ -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
View 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

View file

@ -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')