def favorites_export(what): name = 'favo_%s_%s.cfg' % (what, datetime.now().strftime('%Y-%m-%d-%H%M%S')) if not session.is_logged_in: return if what == 'playlists': session.user.favorites.export_ids( what=_P(what), filename=name, action=session.user.favorites.playlists) elif what == 'artists': session.user.favorites.export_ids( what=_P('Artists'), filename=name, action=session.user.favorites.artists) elif what == 'albums': session.user.favorites.export_ids(what=_P('Albums'), filename=name, action=session.user.favorites.albums) elif what == 'tracks': session.user.favorites.export_ids(what=_P('Tracks'), filename=name, action=session.user.favorites.tracks) elif what == 'videos': session.user.favorites.export_ids(what=_P('Videos'), filename=name, action=session.user.favorites.videos)
def favorites_delete_all(what): ok = xbmcgui.Dialog().yesno( _S(Msg.i30430).format(what=_P(what)), _S(Msg.i30431).format(what=_P(what))) if ok: if what == 'playlists': session.user.favorites.delete_all( what=_T('Playlists'), action=session.user.favorites.playlists, remove=session.user.favorites.remove_playlist) elif what == 'artists': session.user.favorites.delete_all( what=_T('Artists'), action=session.user.favorites.artists, remove=session.user.favorites.remove_artist) elif what == 'albums': session.user.favorites.delete_all( what=_T('Albums'), action=session.user.favorites.albums, remove=session.user.favorites.remove_album) elif what == 'tracks': session.user.favorites.delete_all( what=_T('Tracks'), action=session.user.favorites.tracks, remove=session.user.favorites.remove_track) elif what == 'videos': session.user.favorites.delete_all( what=_T('Videos'), action=session.user.favorites.videos, remove=session.user.favorites.remove_video) return ok
def progress_update(self, heading): try: self.progress.update( percent=int( ((self.artistCount - self.artistQueue.qsize()) * 100) / self.artistCount), heading=heading, message='%s:%s, %s:%s, %s:%s (Threads:%s)' % (_P('albums'), len(self.found_albums), _P('tracks'), len(self.found_tracks), _P('videos'), len( self.found_videos), len(self.runningThreads.keys()))) except: pass
def export_playlists(self, playlists, filename): path = settings.import_export_path if len(path) == 0: return full_path = os.path.join(path, filename) fd = xbmcvfs.File(full_path, 'w') numItems = 0 progress = xbmcgui.DialogProgress() progress.create(_S(Msg.i30433)) idx = 0 for playlist in playlists: idx = idx + 1 percent = int((idx * 100) / len(playlists)) progress.update(percent, playlist.getLabel(extended=False)) items = self._session.get_playlist_items(playlist=playlist) items = [item for item in items if item.available] if len(items) > 0: numItems = numItems + playlist.numberOfItems fd.write( repr({ 'uuid': playlist.id, 'title': playlist.title, 'description': playlist.description, 'parentFolderId': playlist.parentFolderId, 'parentFolderName': playlist.parentFolderName, 'ids': [item.id for item in items] }) + '\n') fd.close() progress.close() xbmcgui.Dialog().notification(_P('Playlists'), _S(Msg.i30428).format(n=numItems), xbmcgui.NOTIFICATION_INFO)
def export_ids(self, what, filename, action): try: ok = False path = settings.import_export_path if len(path) == 0: return items = action() items = [ item for item in items if not isinstance(item, PlayableMedia) or item.available ] if items and len(items) > 0: lines = [ '%s' % item.id + '\t' + item.getLabel(extended=False) + '\n' for item in items ] full_path = os.path.join(path, filename) f = xbmcvfs.File(full_path, 'w') for line in lines: f.write(line.encode('utf-8')) f.close() xbmcgui.Dialog().notification( _P(what), _S(Msg.i30428).format(n=len(lines)), xbmcgui.NOTIFICATION_INFO) ok = True except Exception as e: log.logException(e) return ok
def import_ids(self, what, filename, action): try: ok = False f = xbmcvfs.File(filename, 'r') ids = f.read().decode('utf-8').split('\n') f.close() ids = [item.split('\t')[0] for item in ids] ids = [item for item in ids if len(item) > 0] if len(ids) > 0: ok = action(ids) if ok: xbmcgui.Dialog().notification( _P(what), _S(Msg.i30429).format(n=len(ids)), xbmcgui.NOTIFICATION_INFO) except Exception as e: log.logException(e) return ok
def delete_all(self, what, action, remove): try: ok = False progress = xbmcgui.DialogProgress() progress.create(_S(Msg.i30430).format(what=_P(what))) idx = 0 items = action() for item in items: if progress.iscanceled(): break idx = idx + 1 percent = int((idx * 100) / len(items)) progress.update(percent, item.getLabel(extended=False)) remove(item.id) ok = not progress.iscanceled() except Exception as e: log.logException(e) finally: progress.close() return ok
def context_menu(): commands = [] item = item_info.getSelectedListItem() if item.get('Artist') and item.get('Title'): commands.append((_S(Msg.i30420), search_fuzzy)) commands.append((_S(Msg.i30419), search_selected)) commands.append((_S(Msg.i30421), 'RunPlugin(plugin://%s/convert_to_playlist/tracks)' % Const.addon_id)) commands.append((_S(Msg.i30422), 'RunPlugin(plugin://%s/convert_to_playlist/videos)' % Const.addon_id)) if item.get('FileNameAndPath').find( '%s/favorites/artists' % _tidal2_addon_id_) >= 0: commands.append( (_S(Msg.i30437), 'RunPlugin(plugin://%s/search_artist_music)' % Const.addon_id)) commands.append((_S(Msg.i30426).format(what=_P('artists')), 'RunPlugin(plugin://%s/favorites/export/artists)' % Const.addon_id)) commands.append((_S(Msg.i30427).format(what=_P('artists')), 'RunPlugin(plugin://%s/favorites/import/artists)' % Const.addon_id)) commands.append( (_S(Msg.i30436).format(what=_P('artists')), 'RunPlugin(plugin://%s/favorites/delete_all/artists)' % Const.addon_id)) elif item.get('FileNameAndPath').find( '%s/favorites/albums' % _tidal2_addon_id_) >= 0: commands.append((_S(Msg.i30426).format(what=_P('albums')), 'RunPlugin(plugin://%s/favorites/export/albums)' % Const.addon_id)) commands.append((_S(Msg.i30427).format(what=_P('albums')), 'RunPlugin(plugin://%s/favorites/import/albums)' % Const.addon_id)) commands.append((_S(Msg.i30436).format(what=_P('albums')), 'RunPlugin(plugin://%s/favorites/delete_all/albums)' % Const.addon_id)) elif item.get('FileNameAndPath').find( '%s/favorites/playlists' % _tidal2_addon_id_) >= 0: commands.append((_S(Msg.i30426).format(what=_P('playlists')), 'RunPlugin(plugin://%s/favorites/export/playlists)' % Const.addon_id)) commands.append((_S(Msg.i30427).format(what=_P('playlists')), 'RunPlugin(plugin://%s/favorites/import/playlists)' % Const.addon_id)) commands.append( (_S(Msg.i30436).format(what=_P('playlists')), 'RunPlugin(plugin://%s/favorites/delete_all/playlists)' % Const.addon_id)) elif item.get('FileNameAndPath').find( '%s/favorites/tracks' % _tidal2_addon_id_) >= 0: commands.append((_S(Msg.i30426).format(what=_P('tracks')), 'RunPlugin(plugin://%s/favorites/export/tracks)' % Const.addon_id)) commands.append((_S(Msg.i30427).format(what=_P('tracks')), 'RunPlugin(plugin://%s/favorites/import/tracks)' % Const.addon_id)) commands.append((_S(Msg.i30436).format(what=_P('tracks')), 'RunPlugin(plugin://%s/favorites/delete_all/tracks)' % Const.addon_id)) elif item.get('FileNameAndPath').find( '%s/favorites/videos' % _tidal2_addon_id_) >= 0: commands.append((_S(Msg.i30426).format(what=_P('videos')), 'RunPlugin(plugin://%s/favorites/export/videos)' % Const.addon_id)) commands.append((_S(Msg.i30427).format(what=_P('videos')), 'RunPlugin(plugin://%s/favorites/import/videos)' % Const.addon_id)) commands.append((_S(Msg.i30436).format(what=_P('videos')), 'RunPlugin(plugin://%s/favorites/delete_all/videos)' % Const.addon_id)) elif item.get('FileNameAndPath').find( '%s/user_playlists' % _tidal2_addon_id_) >= 0: commands.append((_S(Msg.i30433), 'RunPlugin(plugin://%s/user_playlist_export_all)' % Const.addon_id)) commands.append( (_S(Msg.i30434), 'RunPlugin(plugin://%s/user_playlist_import)' % Const.addon_id)) if item.get('FileNameAndPath').find('%s/artist/' % _tidal2_addon_id_) >= 0: commands.append( (_S(Msg.i30437), 'RunPlugin(plugin://%s/search_artist_music)' % Const.addon_id)) if item.get('FolderPath').find( '%s/user_playlists' % _tidal2_addon_id_) >= 0 and item.get( 'FileNameAndPath').find('playlist/') > 0: uuid = item.get('FileNameAndPath').split('playlist/')[1].split('/')[0] commands.append( (_S(Msg.i30435), 'RunPlugin(plugin://%s/user_playlist_export/%s)' % (Const.addon_id, uuid))) commands.append( (_S(Msg.i30423), 'Addon.OpenSettings("%s")' % Const.addon_id)) commands.append(('TIDAL2-' + _S(Msg.i30423), 'Addon.OpenSettings("%s")' % _tidal2_addon_id_)) if settings.debug: commands.append((_S(Msg.i30424), item_info.itemInfoDialog)) menu = [txt for txt, func in commands] try: selected = xbmcgui.Dialog().contextmenu(menu) except: selected = xbmcgui.Dialog().select(Const.addon_name, menu) if selected >= 0: txt, func = commands[selected] if callable(func): func() else: xbmc.executebuiltin(func)
def search_artist_music(): if not session.is_logged_in: xbmcgui.Dialog().notification(plugin.name, _S(Msg.i30404), xbmcgui.NOTIFICATION_ERROR) return if settings.getSetting('search_artist_music_running') == 'true': if xbmcgui.Dialog().yesno(_S(Msg.i30437), _S(Msg.i30445) + '\n' + _S(Msg.i30446)): settings.setSetting('search_artist_music_abort', 'true') return item = item_info.getSelectedListItem() artists = [] if item.get('FileNameAndPath').find('%s/artist/' % _tidal2_addon_id_) >= 0: artist_id = item.get('FileNameAndPath').split('/artist/')[1].split( '/')[0] artist = session.get_artist(artist_id) if artist: artists.append(artist) else: artists = session.user.favorites.get('artists') if len(artists) == 0: log.error('No selected Artists found') return if not session.is_logged_in: xbmcgui.Dialog().notification(plugin.name, _S(Msg.i30404), xbmcgui.NOTIFICATION_ERROR) return # Submenu: Parameters for Playlist-Generation cmds = [ ('action', _S(Msg.i30405)), ('album_playlist', _S(Msg.i30409).format(what=_P('albums')) + ': '), ('track_playlist', _S(Msg.i30409).format(what=_P('tracks')) + ': '), ('video_playlist', _S(Msg.i30409).format(what=_P('videos')) + ': '), ('limit', _S(Msg.i30438) + ': '), ('diff_days', _S(Msg.i30439) + ': '), ] album_playlist = None track_playlist = None video_playlist = None if settings.getSetting('default_albumplaylist_id'): album_playlist = session.get_playlist( settings.getSetting('default_albumplaylist_id')) if not album_playlist and tidalSettings.default_albumplaylist_id: album_playlist = session.get_playlist( tidalSettings.default_albumplaylist_id) if not album_playlist: album_playlist = PlaylistItem(Playlist()) album_playlist.title = '' if settings.getSetting('default_trackplaylist_id'): track_playlist = session.get_playlist( settings.getSetting('default_trackplaylist_id')) if not track_playlist and tidalSettings.default_trackplaylist_id: track_playlist = session.get_playlist( tidalSettings.default_trackplaylist_id) if not track_playlist: track_playlist = PlaylistItem(Playlist()) track_playlist.title = '' if settings.getSetting('default_videoplaylist_id'): video_playlist = session.get_playlist( settings.getSetting('default_videoplaylist_id')) if not video_playlist and tidalSettings.default_videoplaylist_id: video_playlist = session.get_playlist( tidalSettings.default_videoplaylist_id) if not video_playlist: video_playlist = PlaylistItem(Playlist()) video_playlist.title = '' item = { 'action': '', 'album_playlist': album_playlist.title, 'album_playlist_id': album_playlist.id, 'track_playlist': track_playlist.title, 'track_playlist_id': track_playlist.id, 'video_playlist': video_playlist.title, 'video_playlist_id': video_playlist.title, 'limit': 40, 'diff_days': 90 } answer = 1 while answer > 0: menue = [ '%s%s' % (FOLDER_MASK % s_head, item.get(s_key)) for s_key, s_head in cmds ] answer = xbmcgui.Dialog().select(_S(Msg.i30437), menue) if answer > 0: if answer >= 1 and answer <= 3: playlist = session.user.selectPlaylistDialog(_S( Msg.i30409).format( what=_P(['', 'albums', 'tracks', 'videos'][answer])), allowNew=True) if playlist: item[[ '', 'album_playlist_id', 'track_playlist_id', 'video_playlist_id' ][answer]] = playlist.id item[[ '', 'album_playlist', 'track_playlist', 'video_playlist' ][answer]] = playlist.title if answer == 1: album_playlist = playlist elif answer == 2: track_playlist = playlist elif answer == 3: video_playlist = playlist else: item[[ '', 'album_playlist_id', 'track_playlist_id', 'video_playlist_id' ][answer]] = None item[[ '', 'album_playlist', 'track_playlist', 'video_playlist' ][answer]] = '' if answer == 1: album_playlist = PlaylistItem(Playlist()) album_playlist.title = '' elif answer == 2: track_playlist = PlaylistItem(Playlist()) track_playlist.title = '' elif answer == 3: video_playlist = PlaylistItem(Playlist()) video_playlist.title = '' elif answer >= 4 and answer <= 5: value = int( '0%s' % xbmcgui.Dialog().input(cmds[answer][1], str(item.get(cmds[answer][0])), type=xbmcgui.INPUT_NUMERIC)) item.update({cmds[answer][0]: value}) if answer < 0: return # Saving used Playlist-IDs settings.setSetting('default_albumplaylist_id', album_playlist.id if album_playlist.id else '') settings.setSetting('default_trackplaylist_id', track_playlist.id if track_playlist.id else '') settings.setSetting('default_videoplaylist_id', video_playlist.id if video_playlist.id else '') # Searching now searcher = NewMusicSearcher(session, album_playlist, track_playlist, video_playlist, limit=item.get('limit', 20), diffDays=item.get('diff_days', 90)) settings.setSetting('search_artist_music_running', 'true') settings.setSetting('search_artist_music_abort', 'false') searcher.search(artists, thread_count=settings.max_thread_count) settings.setSetting('search_artist_music_running', 'false')
def convert_to_playlist(item_type): if not session.is_logged_in: xbmcgui.Dialog().notification(plugin.name, _S(Msg.i30404), xbmcgui.NOTIFICATION_ERROR) return # Submenu: Parameters for Playlist-Generation cmds = [ ('action', _S(Msg.i30405)), ('playlist', _T('playlist') + ': '), ('Position', _S(Msg.i30406) + ': '), ('NumItems', _S(Msg.i30407) + ': '), ] item = item_info.getSelectedListItem() item['action'] = '' item['playlist_id'] = '' item['playlist'] = '' playlist_id = tidalSettings.default_videoplaylist_id if item_type.startswith( 'video') else tidalSettings.default_trackplaylist_id if playlist_id: try: playlist = session.get_playlist(playlist_id) if playlist: item['playlist_id'] = playlist.id item['playlist'] = playlist.title except: pass numItems = item['NumItems'] answer = 1 while answer > 0: menue = [ '%s%s' % (FOLDER_MASK % s_head, item.get(s_key)) for s_key, s_head in cmds ] answer = xbmcgui.Dialog().select(_S(Msg.i30408), menue) if answer == 0 and not item['playlist_id']: answer = 1 # Playlist not set if answer > 0: if answer == 1: playlist = session.user.selectPlaylistDialog(_S( Msg.i30409).format( what=_P('tracks' if item_type. startswith('track') else 'videos')), allowNew=True) if playlist: item['playlist_id'] = playlist.id item['playlist'] = playlist.title elif answer >= 2 and answer <= 3: value = int( '0%s' % xbmcgui.Dialog().input(cmds[answer][1], str(item.get(cmds[answer][0])), type=xbmcgui.INPUT_NUMERIC)) if ( answer == 2 and value <= numItems and value <= item['NumItems'] ) or \ ( answer == 3 and value <= numItems and value >= item['Position'] ): item.update({cmds[answer][0]: value}) else: keyboard = xbmc.Keyboard(item.get(cmds[answer][0]), cmds[answer][1]) keyboard.doModal() if keyboard.isConfirmed(): value = keyboard.getText() item.update({cmds[answer][0]: value}) if answer == 0: convert_to_playlist_run(item_type, '0%s' % item['Position'], '0%s' % item['NumItems'], item['playlist_id'])
def search(self, artists, thread_count=1): for artist in artists: try: if VARIOUS_ARTIST_ID != '%s' % artist.id and not artist._isLocked: self.artistQueue.put(artist) except: if VARIOUS_ARTIST_ID != '%s' % artist.id: self.artistQueue.put(artist) self.artistCount = self.artistQueue.qsize() if self.artistCount < 1: log.info('No Artist to search ...') return log.info('Start: Searching new Music for %s Artists ...' % self.artistCount) self.abortThreads = False threadsToStart = thread_count if thread_count < self.artistCount else self.artistCount self.runningThreads = {} self.progress = xbmcgui.DialogProgressBG() self.progress.create(heading=_S(Msg.i30437)) try: self.progress_update(heading=_S(Msg.i30437)) xbmc.sleep(500) while len(self.runningThreads.keys()) < threadsToStart: try: worker = Thread(target=self.search_thread) worker.start() self.runningThreads.update({worker.ident: worker}) except Exception as e: log.logException(e) log.info('Waiting until all Threads are terminated') startTime = datetime.today() stopWatch = startTime remainingArtists = self.artistCount lastCount = self.artistCount while len(list(self.runningThreads.keys()) ) > 0 and not xbmc.Monitor().waitForAbort(timeout=0.05): remaining_workers = list(self.runningThreads.values()) for worker in remaining_workers: worker.join(5) if settings.getSetting( 'search_artist_music_abort') == 'true': log.info('Stopping all Workers ...') self.abortThreads = True settings.setSetting('search_artist_music_abort', 'false') if worker.is_alive(): now = datetime.today() runningTime = now - startTime remainingArtists = self.artistQueue.qsize() log.info( 'Workers still running after %s seconds, %s Artists remaining ...' % (runningTime.seconds, remainingArtists)) diff = now - stopWatch if lastCount > remainingArtists: # Workers are still removing artists from the queue lastCount = remainingArtists stopWatch = now elif diff.seconds >= 60: # Timeout: Stopping Threads with the Stop-Flag log.info('Timeout, sending Stop to Workers ...') self.abortThreads = True break else: # Removing terminates Thread self.runningThreads.pop(worker.ident, None) break if self.abortThreads: xbmcgui.Dialog().notification( _S(Msg.i30437), _S(Msg.i30444), icon=xbmcgui.NOTIFICATION_WARNING) worker_keys = list(self.runningThreads.keys()) for worker_key in worker_keys: log.info('Waiting for Thread %s to terminate ...' % worker_key) worker = self.runningThreads.pop(worker_key, None) if worker != None and worker.is_alive(): worker.join(5) xbmc.sleep(2000) if len(self.found_albums) > 0 or len(self.found_tracks) > 0 or len( self.found_videos) > 0: self.progress_update(heading=_S(Msg.i30441)) if len(self.found_albums) > 0 and self.album_playlist.id: self.album_playlist._etag = None try: self.session.user.add_playlist_entries( self.album_playlist, self.found_albums) except: pass if len(self.found_tracks) > 0 and self.track_playlist.id: self.track_playlist._etag = None try: self.session.user.add_playlist_entries( self.track_playlist, self.found_tracks) except: pass if len(self.found_videos) > 0 and self.video_playlist.id: self.video_playlist._etag = None try: self.session.user.add_playlist_entries( self.video_playlist, self.found_videos) except: pass message = '%s:%s, %s:%s, %s:%s' % ( _P('albums'), len(self.found_albums), _P('tracks'), len(self.found_tracks), _P('videos'), len( self.found_videos)) xbmcgui.Dialog().notification(_S(Msg.i30440), message, icon=xbmcgui.NOTIFICATION_INFO) log.info('Found: %s' % message) else: log.info('No new Music found !') xbmcgui.Dialog().notification(_S(Msg.i30437), _S(Msg.i30443), icon=xbmcgui.NOTIFICATION_INFO) except Exception as e: log.logException(e, 'Error in search loop') xbmcgui.Dialog().notification(_S(Msg.i30437), _S(Msg.i30442), icon=xbmcgui.NOTIFICATION_ERROR) traceback.print_exc() finally: xbmc.sleep(2000) self.progress.close() log.info('End: Searching for new Music.') # End of File