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:
commit
ffeb79e4b5
3 changed files with 89 additions and 15 deletions
|
@ -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:
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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))
|
||||
|
|
Loading…
Reference in a new issue