diff --git a/resources/language/resource.language.en_gb/strings.po b/resources/language/resource.language.en_gb/strings.po index cd0cbc89..54dda540 100644 --- a/resources/language/resource.language.en_gb/strings.po +++ b/resources/language/resource.language.en_gb/strings.po @@ -486,6 +486,10 @@ msgctxt "#33048" msgid "You may need to verify your network credentials in the add-on settings or use the Emby path substitution to format your path correctly (Emby dashboard > library). Stop syncing?" msgstr "" +msgctxt "#33049" +msgid "New" +msgstr "" + msgctxt "#33054" msgid "Add user to session" msgstr "" diff --git a/resources/lib/helper/api.py b/resources/lib/helper/api.py index b82ccaa3..beee246f 100644 --- a/resources/lib/helper/api.py +++ b/resources/lib/helper/api.py @@ -18,10 +18,10 @@ LOG = logging.getLogger("EMBY."+__name__) class API(object): - def __init__(self, item, server): + def __init__(self, item, server=None): ''' Get item information in special cases. - server is the server address + server is the server address, provide if your functions requires it. ''' self.item = item self.server = server @@ -33,6 +33,25 @@ class API(object): ''' return (playcount or 1) if played else None + def get_naming(self): + + if self.item['Type'] == 'Episode': + + if 'SeriesName' in self.item: + return "%s: %s" % (self.item['SeriesName'], self.item['Name']) + + elif self.item['Type'] == 'MusicAlbum': + + if 'AlbumArtist' in self.item: + return "%s: %s" % (self.item['AlbumArtist'], self.item['Name']) + + elif self.item['Type'] == 'Audio': + + if self.item.get('Artists'): + return "%s: %s" % (self.item['Artists'][0], self.item['Name']) + + return self.item['Name'] + def get_actors(self): cast = [] diff --git a/resources/lib/helper/utils.py b/resources/lib/helper/utils.py index dde7c045..ba0329ab 100644 --- a/resources/lib/helper/utils.py +++ b/resources/lib/helper/utils.py @@ -406,8 +406,9 @@ def copy_file(path, dest): def normalize_string(text): - ''' For theme media, do not modify unless - modified in TV Tunes. + ''' For theme media, do not modify unless modified in TV Tunes. + Remove dots from the last character as windows can not have directories + with dots at the end ''' text = text.replace(":", "") text = text.replace("/", "-") @@ -418,13 +419,14 @@ def normalize_string(text): text = text.replace("?", "") text = text.replace('|', "") text = text.strip() - # Remove dots from the last character as windows can not have directories - # with dots at the end + text = text.rstrip('.') text = unicodedata.normalize('NFKD', unicode(text, 'utf-8')).encode('ascii', 'ignore') return text def split_list(itemlist, size): - # Split up list in pieces of size. Will generate a list of lists + + ''' Split up list in pieces of size. Will generate a list of lists + ''' return [itemlist[i:i+size] for i in range(0, len(itemlist), size)] diff --git a/resources/lib/library.py b/resources/lib/library.py index 45a05d5b..93db663d 100644 --- a/resources/lib/library.py +++ b/resources/lib/library.py @@ -16,7 +16,7 @@ from database import Database, emby_db, get_sync, save_sync from full_sync import FullSync from views import Views from downloader import GetItemWorker -from helper import _, stop, settings, window, dialog, event, progress, LibraryException +from helper import _, api, stop, settings, window, dialog, event, progress, LibraryException from helper.utils import split_list, set_screensaver, get_screensaver from emby import Emby @@ -58,6 +58,7 @@ class Library(threading.Thread): self.direct_path = settings('useDirectPaths') == "1" self.progress_display = int(settings('syncProgress') or 50) self.monitor = monitor + self.player = monitor.monitor.player self.server = Emby() self.updated_queue = Queue.Queue() self.userdata_queue = Queue.Queue() @@ -65,9 +66,11 @@ class Library(threading.Thread): self.updated_output = self.__new_queues__() self.userdata_output = self.__new_queues__() self.removed_output = self.__new_queues__() + self.notify_output = Queue.Queue() self.emby_threads = [] self.download_threads = [] + self.notify_threads = [] self.writer_threads = {'updated': [], 'userdata': [], 'removed': []} self.database_lock = threading.Lock() self.music_database_lock = threading.Lock() @@ -132,10 +135,11 @@ class Library(threading.Thread): self.worker_updates() self.worker_userdata() self.worker_remove() + self.worker_notify() if self.pending_refresh: - if self.total_updates > self.progress_display: + if self.total_updates > self.progress_display and (not self.player.isPlayingVideo() or xbmc.getCondVisibility('VideoPlayer.Content(livetv)')): queue_size = self.worker_queue_size() if self.progress_updates is None: @@ -227,9 +231,9 @@ class Library(threading.Thread): if queue.qsize() and len(self.writer_threads['updated']) < 4: if queues in ('Audio', 'MusicArtist', 'AlbumArtist', 'MusicAlbum'): - new_thread = UpdatedWorker(queue, self.music_database_lock, "music", self.server, self.direct_path) + new_thread = UpdatedWorker(queue, self.notify_output, self.music_database_lock, "music", self.server, self.direct_path) else: - new_thread = UpdatedWorker(queue, self.database_lock, "video", self.server, self.direct_path) + new_thread = UpdatedWorker(queue, self.notify_output, self.database_lock, "video", self.server, self.direct_path) new_thread.start() LOG.info("-->[ q:updated/%s/%s ]", queues, id(new_thread)) @@ -274,6 +278,17 @@ class Library(threading.Thread): self.writer_threads['removed'].append(new_thread) self.pending_refresh = True + def worker_notify(self): + + ''' Notify the user of new additions. + ''' + if self.notify_output.qsize() and len(self.notify_threads) < 1: + + new_thread = NotifyWorker(self.notify_output, self.player) + new_thread.start() + LOG.info("-->[ q:notify/%s ]", id(new_thread)) + self.notify_threads.append(new_thread) + def startup(self): @@ -587,9 +602,11 @@ class UpdatedWorker(threading.Thread): is_done = False - def __init__(self, queue, lock, database, *args): + def __init__(self, queue, notify, lock, database, *args): self.queue = queue + self.notify_output = notify + self.notify = settings('newContent.bool') self.lock = lock self.database = Database(database) self.args = args @@ -613,9 +630,10 @@ class UpdatedWorker(threading.Thread): break obj = MEDIA[item['Type']](self.args[0], embydb, kodidb, self.args[1])[item['Type']] - + LOG.info(item['Type']) try: - obj(item) + if obj(item) and self.notify: + self.notify_output.put((item['Type'], api.API(item).get_naming())) except LibraryException as error: if error.status == 'StopCalled': break @@ -763,8 +781,13 @@ class NotifyWorker(threading.Thread): is_done = False - def __init__(self, queue): + def __init__(self, queue, player): + self.queue = queue + self.video_time = int(settings('newvideotime')) * 1000 + self.music_time = int(settings('newmusictime')) * 1000 + self.player = player + threading.Thread.__init__(self) def run(self): @@ -779,11 +802,13 @@ class NotifyWorker(threading.Thread): break + time = self.music_time if item[0] == 'Audio' else self.video_time + + if time and (not self.player.isPlayingVideo() or xbmc.getCondVisibility('VideoPlayer.Content(livetv)')): + dialog("notification", heading="%s %s" % (_(33049), item[0]), message=item[1], + icon="{emby}", time=time, sound=False) + self.queue.task_done() - if xbmc.Monitor().abortRequested(): + if window('emby_should_stop.bool'): break - - if not self.pdialog and self.content_msg and self.new_time and (not xbmc.Player().isPlayingVideo() or xbmc.getCondVisibility('VideoPlayer.Content(livetv)')): - dialog("notification", heading="{emby}", message="%s %s" % (lang(33049), name), - icon="{emby}", time=self.new_time, sound=False) diff --git a/resources/lib/objects/movies.py b/resources/lib/objects/movies.py index 730884b2..247e2e5d 100644 --- a/resources/lib/objects/movies.py +++ b/resources/lib/objects/movies.py @@ -129,6 +129,8 @@ class Movies(KodiDb): self.item_ids.append(obj['Id']) + return not update + def movie_add(self, obj): ''' Add object to kodi. diff --git a/resources/lib/objects/music.py b/resources/lib/objects/music.py index b25e4779..71e4609f 100644 --- a/resources/lib/objects/music.py +++ b/resources/lib/objects/music.py @@ -294,6 +294,8 @@ class Music(KodiDb): if obj['SongAlbumId'] is None: self.artwork.add(obj['Artwork'], obj['AlbumId'], "album") + return not update + def song_add(self, obj): ''' Add object to kodi. diff --git a/resources/lib/objects/musicvideos.py b/resources/lib/objects/musicvideos.py index a779a143..1a4c2bd4 100644 --- a/resources/lib/objects/musicvideos.py +++ b/resources/lib/objects/musicvideos.py @@ -137,6 +137,8 @@ class MusicVideos(KodiDb): self.add_streams(*values(obj, QU.add_streams_obj)) self.artwork.add(obj['Artwork'], obj['MvideoId'], "musicvideo") + return not update + def musicvideo_add(self, obj): ''' Add object to kodi. diff --git a/resources/lib/objects/tvshows.py b/resources/lib/objects/tvshows.py index 00123893..cf9fce4c 100644 --- a/resources/lib/objects/tvshows.py +++ b/resources/lib/objects/tvshows.py @@ -346,6 +346,8 @@ class TVShows(KodiDb): self.update_file(*values(temp_obj, QU.update_file_obj)) self.add_playstate(*values(temp_obj, QU.add_bookmark_obj)) + return not update + def episode_add(self, obj): ''' Add object to kodi. diff --git a/resources/settings.xml b/resources/settings.xml index 2348d645..526e1d53 100644 --- a/resources/settings.xml +++ b/resources/settings.xml @@ -21,7 +21,6 @@ - @@ -75,6 +74,7 @@ +