Merge pull request #1054 from croneter/fix-album

Fix Recently Added Albums sort order (you will have to reset the Kodi database manually)
This commit is contained in:
croneter 2019-11-14 17:19:37 +01:00 committed by GitHub
commit ffeb79e4b5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 89 additions and 15 deletions

View file

@ -140,6 +140,67 @@ class KillableThread(threading.Thread):
return self._suspended
class OrderedQueue(Queue.PriorityQueue, object):
"""
Queue that enforces an order on the items it returns. An item you push
onto the queue must be a tuple
(index, item)
where index=-1 is the item that will be returned first. The Queue will block
until index=-1, 0, 1, 2, 3, ... is then made available
"""
def __init__(self, maxsize=0):
super(OrderedQueue, self).__init__(maxsize)
self.smallest = -1
self.not_next_item = threading.Condition(self.mutex)
def _put(self, item, heappush=heapq.heappush):
heappush(self.queue, item)
if item[0] == self.smallest:
self.not_next_item.notify()
def get(self, block=True, timeout=None):
"""Remove and return an item from the queue.
If optional args 'block' is true and 'timeout' is None (the default),
block if necessary until an item is available. If 'timeout' is
a non-negative number, it blocks at most 'timeout' seconds and raises
the Empty exception if no item was available within that time.
Otherwise ('block' is false), return an item if one is immediately
available, else raise the Empty exception ('timeout' is ignored
in that case).
"""
self.not_empty.acquire()
try:
if not block:
if not self._qsize() or self.queue[0][0] != self.smallest:
raise Queue.Empty
elif timeout is None:
while not self._qsize():
self.not_empty.wait()
while self.queue[0][0] != self.smallest:
self.not_next_item.wait()
elif timeout < 0:
raise ValueError("'timeout' must be a non-negative number")
else:
endtime = Queue._time() + timeout
while not self._qsize():
remaining = endtime - Queue._time()
if remaining <= 0.0:
raise Queue.Empty
self.not_empty.wait(remaining)
while self.queue[0][0] != self.smallest:
remaining = endtime - Queue._time()
if remaining <= 0.0:
raise Queue.Empty
self.not_next_item.wait(remaining)
item = self._get()
self.smallest += 1
self.not_full.notify()
return item
finally:
self.not_empty.release()
class Tasks(list):
def add(self, task):
for t in self:

View file

@ -102,14 +102,15 @@ class FullSync(common.fullsync_mixin):
self.threader.addTask(GetMetadataTask(self.queue,
plex_id,
self.plex_type,
self.get_children))
self.get_children,
self.item_count))
self.item_count += 1
def update_library(self):
LOG.debug('Writing changes to Kodi library now')
i = 0
if not self.section:
self.section = self.queue.get()
_, self.section = self.queue.get()
self.queue.task_done()
while not self.isCanceled() and self.item_count > 0:
section = self.section
@ -125,7 +126,7 @@ class FullSync(common.fullsync_mixin):
with section.context(self.current_sync) as context:
while not self.isCanceled() and self.item_count > 0:
try:
item = self.queue.get(block=False)
_, item = self.queue.get(block=False)
except backgroundthread.Queue.Empty:
if self.threader.threader.working():
app.APP.monitor.waitForAbort(0.02)
@ -174,7 +175,7 @@ class FullSync(common.fullsync_mixin):
iterator.get('title1')),
section.section_id,
section.plex_type)
self.queue.put(queue_info)
self.queue.put((-1, queue_info))
last = True
# To keep track of the item-number in order to kill while loops
self.item_count = 0
@ -216,7 +217,7 @@ class FullSync(common.fullsync_mixin):
section.name,
section.section_id,
section.plex_type)
self.queue.put(queue_info)
self.queue.put((-1, queue_info))
self.total = iterator.total
self.section_name = section.name
self.section_type_text = utils.lang(
@ -268,6 +269,7 @@ class FullSync(common.fullsync_mixin):
element.section_type = element.plex_type
element.context = kind[2]
element.get_children = kind[3]
element.Queue = kind[4]
if self.repair or all_items:
updated_at = None
else:
@ -292,16 +294,22 @@ class FullSync(common.fullsync_mixin):
def full_library_sync(self):
"""
"""
# structure:
# (plex_type,
# section_type,
# context for itemtype,
# download children items, e.g. songs for a specific album?,
# Queue)
kinds = [
(v.PLEX_TYPE_MOVIE, v.PLEX_TYPE_MOVIE, itemtypes.Movie, False),
(v.PLEX_TYPE_SHOW, v.PLEX_TYPE_SHOW, itemtypes.Show, False),
(v.PLEX_TYPE_SEASON, v.PLEX_TYPE_SHOW, itemtypes.Season, False),
(v.PLEX_TYPE_EPISODE, v.PLEX_TYPE_SHOW, itemtypes.Episode, False)
(v.PLEX_TYPE_MOVIE, v.PLEX_TYPE_MOVIE, itemtypes.Movie, False, Queue.Queue),
(v.PLEX_TYPE_SHOW, v.PLEX_TYPE_SHOW, itemtypes.Show, False, Queue.Queue),
(v.PLEX_TYPE_SEASON, v.PLEX_TYPE_SHOW, itemtypes.Season, False, Queue.Queue),
(v.PLEX_TYPE_EPISODE, v.PLEX_TYPE_SHOW, itemtypes.Episode, False, Queue.Queue)
]
if app.SYNC.enable_music:
kinds.extend([
(v.PLEX_TYPE_ARTIST, v.PLEX_TYPE_ARTIST, itemtypes.Artist, False),
(v.PLEX_TYPE_ALBUM, v.PLEX_TYPE_ARTIST, itemtypes.Album, True),
(v.PLEX_TYPE_ARTIST, v.PLEX_TYPE_ARTIST, itemtypes.Artist, False, Queue.Queue),
(v.PLEX_TYPE_ALBUM, v.PLEX_TYPE_ARTIST, itemtypes.Album, True, backgroundthread.OrderedQueue),
])
# ADD NEW ITEMS
# Already start setting up the iterators. We need to enforce
@ -323,6 +331,7 @@ class FullSync(common.fullsync_mixin):
self.section_type = section.section_type
self.context = section.context
self.get_children = section.get_children
self.queue = section.Queue()
# Now do the heavy lifting
if self.isCanceled() or not self.addupdate_section(section):
return False
@ -352,8 +361,11 @@ class FullSync(common.fullsync_mixin):
LOG.info('Start synching playstate and userdata for every item')
# In order to not delete all your songs again
if app.SYNC.enable_music:
# We don't need to enforce the album order now
kinds.pop(5)
kinds.extend([
(v.PLEX_TYPE_SONG, v.PLEX_TYPE_ARTIST, itemtypes.Song, True),
(v.PLEX_TYPE_ALBUM, v.PLEX_TYPE_ARTIST, itemtypes.Album, True, Queue.Queue),
(v.PLEX_TYPE_SONG, v.PLEX_TYPE_ARTIST, itemtypes.Song, True, Queue.Queue),
])
# Make sure we're not showing an item's title in the sync dialog
self.title = ''
@ -429,7 +441,6 @@ class FullSync(common.fullsync_mixin):
return
self.successful = True
try:
self.queue = backgroundthread.Queue.Queue()
if self.show_dialog:
self.dialog = xbmcgui.DialogProgressBG()
self.dialog.create(utils.lang(39714))

View file

@ -36,11 +36,13 @@ class GetMetadataTask(common.fullsync_mixin, backgroundthread.Task):
queue Queue.Queue() object where this thread will store
the downloaded metadata XMLs as etree objects
"""
def __init__(self, queue, plex_id, plex_type, get_children=False):
def __init__(self, queue, plex_id, plex_type, get_children=False,
count=None):
self.queue = queue
self.plex_id = plex_id
self.plex_type = plex_type
self.get_children = get_children
self.count = count
super(GetMetadataTask, self).__init__()
def _collections(self, item):
@ -120,4 +122,4 @@ class GetMetadataTask(common.fullsync_mixin, backgroundthread.Task):
else:
item['children'] = children_xml
if not self.isCanceled():
self.queue.put(item)
self.queue.put((self.count, item))