def GetChannels(self, includeDisabled=False, **kwargs): # type: (object) -> list """ Retrieves all enabled channels within Retrospect. If updated channels are found, the those channels are indexed and the channel index is rebuild. @type kwargs: here for backward compatibility @return: a list of ChannelInfo objects of enabled channels. """ sw = StopWatch("ChannelIndex.GetChannels Importer", Logger.Instance()) Logger.Info("Fetching all enabled channels.") self.__enabledChannels = [] self.__allChannels = [] self.__validChannels = [] # What platform are we platform = envcontroller.EnvController.GetPlatform() channelsUpdated = False for channelSet in self.__channelIndex[self.__CHANNEL_INDEX_CHANNEL_KEY]: channelSet = self.__channelIndex[self.__CHANNEL_INDEX_CHANNEL_KEY][channelSet] channelSetInfoPath = channelSet[self.__CHANNEL_INDEX_CHANNEL_INFO_KEY] channelSetVersion = channelSet[self.__CHANNEL_INDEX_CHANNEL_VERSION_KEY] # Check if file exists. If not, rebuild index if not os.path.isfile(channelSetInfoPath) and not self.__reindexed: Logger.Warning("Missing channelSet file: %s.", channelSetInfoPath) self.__RebuildIndex() return self.GetChannels() channelInfos = ChannelInfo.FromJson(channelSetInfoPath, channelSetVersion) # Check if the channel was updated if self.__IsChannelSetUpdated(channelInfos[0]): # let's see if the index has already been updated this section, of not, do it and # restart the ChannelRetrieval. if not self.__reindexed: # rebuild and restart Logger.Warning("Re-index channel index due to channelSet update: %s.", channelSetInfoPath) self.__RebuildIndex() return self.GetChannels() else: Logger.Warning("Found updated channelSet: %s.", channelSetInfoPath) if not channelsUpdated: # this was the first update found (otherwise channelsUpdated was True) show a message: title = LanguageHelper.GetLocalizedString(LanguageHelper.InitChannelTitle) text = LanguageHelper.GetLocalizedString(LanguageHelper.InitChannelText) XbmcWrapper.ShowNotification(title, text, displayTime=15000, logger=Logger.Instance()) channelsUpdated |= True # Initialise the channelset. self.__InitialiseChannelSet(channelInfos[0]) # And perform all first actions for the included channels in the set for channelInfo in channelInfos: self.__InitialiseChannel(channelInfo) # Check the channel validity for channelInfo in channelInfos: if not self.__ChannelIsCorrect(channelInfo): continue self.__allChannels.append(channelInfo) # valid channel for this platform ? if not channelInfo.compatiblePlatforms & platform == platform: Logger.Warning("Not loading: %s -> platform '%s' is not compatible.", channelInfo, Environments.Name(platform)) continue self.__validChannels.append(channelInfo) # was the channel disabled? if not (AddonSettings.ShowChannel( channelInfo) and AddonSettings.ShowChannelWithLanguage( channelInfo.language)): Logger.Warning("Not loading: %s -> Channel was disabled from settings.", channelInfo) continue self.__enabledChannels.append(channelInfo) Logger.Debug("Loading: %s", channelInfo) if channelsUpdated: Logger.Info("New or updated channels found. Updating add-on configuration for all channels and user agent.") AddonSettings.UpdateAddOnSettingsWithChannels(self.__validChannels, Config) AddonSettings.UpdateUserAgent() else: Logger.Debug("No channel changes found. Skipping add-on configuration for channels.") # TODO: perhaps we should check that the settings.xml is correct and not broken? self.__enabledChannels.sort() Logger.Info("Fetch a total of %d channels of which %d are enabled.", len(self.__allChannels), len(self.__enabledChannels)) sw.Stop() if includeDisabled: return self.__validChannels return self.__enabledChannels
def __ImportChannels(self): # , className = None): """Import the available channels This method will: - iterate through the Addons folder and find all the folders name <basename>.channel.<channelname>. - then adds all the subfolders into a list (with paths). - then all paths are added to the system path, so they can be imported. - then read all the chn_<name>.xml metadata files and add the ChannelInfo objects to the self.__channelsToImport - then the channels in the self.__channelsToImport list are instantiated into the self.channels list. """ Logger.Debug("Importing available channels") # import each channelPath. On import, the channelPath will call the RegisterChannel Method try: # clear a possible previous import self.__enabledChannels = [] self.__allChannels = [] self.__validChannels = [] self.__channelVersions = [] # first find all folders with channels that we might need to import channelImport = [] importTimer = StopWatch("ChannelImporter :: importing channels", Logger.Instance()) addonPath = self.__GetAddonPath() channelPathStart = "%s.channel" % (Config.addonDir,) for directory in os.listdir(addonPath): if channelPathStart in directory and "BUILD" not in directory: path = os.path.join(addonPath, directory) channelVersion = self.__ParseChannelVersionInfo(path) if channelVersion: self.__channelVersions.append(channelVersion) else: # no info was returned, so we will not include the channel continue # get all nested channels subDirs = os.listdir(path) channelImport.extend( [os.path.abspath(os.path.join(path, weapon)) for weapon in subDirs]) channelImport.sort() importTimer.Lap("Directories scanned for .channel") # we need to make sure we don't load multiple channel classes and track if we found updates channelsUpdated = False loadedChannels = [] channelsToImport = [] # now import the channels for channelPath in channelImport: if not os.path.isdir(channelPath): continue # determine channelname channelName = os.path.split(channelPath)[-1] if channelName == self.__updateChannelPath: Logger.Trace("Update path found and skipping: %s", channelName) continue # if loadedChannels.count(channelName) > 0: if channelName in loadedChannels: Logger.Warning( "Not loading: chn_%s.xml in %s because there is already a path with " "name '%s' that name loaded", channelName, channelPath, channelName) continue if channelName.startswith("."): continue # now we can continue loadedChannels.append(channelName) fileName = os.path.join(channelPath, "chn_" + channelName + ".json") Logger.Trace("Loading info for chn_%s @ %s", channelName, fileName) if os.path.isfile(fileName): try: ci = ChannelInfo.FromJson(fileName) if len(ci) <= 0: Logger.Warning("No channels found in '%s'", fileName) continue # Add them to the list to import channelsToImport += ci if self.__IsChannelSetUpdated(ci[0]): if not channelsUpdated: # this was the first update found (otherwise channelsUpdated was True) show a message: title = LanguageHelper.GetLocalizedString( LanguageHelper.InitChannelTitle) text = LanguageHelper.GetLocalizedString( LanguageHelper.InitChannelText) XbmcWrapper.ShowNotification(title, text, displayTime=15000) # set the updates found bit channelsUpdated |= True # Initialise the channelset. self.__InitialiseChannelSet(ci[0]) # And perform all first actions for the included channels in the set for channelInfo in ci: self.__FirstTimeChannelActions(channelInfo) except: Logger.Error("Error import chn_%s.json", channelName, exc_info=True) importTimer.Lap() # What platform are we platform = envcontroller.EnvController.GetPlatform() # instantiate the registered channels for channelInfo in channelsToImport: # noinspection PyUnusedLocal isValid = self.__ValidateChannelInfo(channelInfo, platform) # sort the channels self.__enabledChannels.sort() if channelsUpdated: Logger.Info("New or updated channels found. Updating add-on configuration for all " "channels and user agent") AddonSettings.UpdateAddOnSettingsWithChannels(self.__validChannels, Config) AddonSettings.UpdateUserAgent() else: Logger.Debug("No channel changes found. Skipping add-on configuration for channels") # Should we update the channel index? if channelsUpdated or not os.path.isfile(self.__CHANNEL_INDEX): self.__CreateChannelIndex() Logger.Info("Imported %s channels from which %s are enabled", len(self.__allChannels), len(self.__enabledChannels)) importTimer.Stop() except: Logger.Critical("Error loading channel modules", exc_info=True)