コード例 #1
0
    def onInit(self):
        # Need to clear the list of the default items
        self.clearList()

        # Start by adding an option to Play All
        if len(self.files) > 0:
            anItem = xbmcgui.ListItem(ADDON.getLocalizedString(32101), path=SourceDetails.getFilenameAndPath())
            # Get the first items fanart for the play all option
            anItem.setProperty("Fanart_Image", self.files[0].getFanArt())

            if SourceDetails.getTvShowTitle() != "":
                anItem.setInfo('video', {'TvShowTitle': SourceDetails.getTvShowTitle()})

            if SourceDetails.getTitle() != "":
                anItem.setInfo('video', {'Title': SourceDetails.getTitle()})

            self.addItem(anItem)

        # Check if we want to have YouTube Extra Support
        if Settings.isYouTubeSearchSupportEnabled():
            # Create the message to the YouTube Plugin
            li = xbmcgui.ListItem(ADDON.getLocalizedString(32116))
            # Need to set the title to get it in the header
            if SourceDetails.getTvShowTitle() != "":
                li.setInfo('video', {'TvShowTitle': SourceDetails.getTvShowTitle()})
            if SourceDetails.getTitle() != "":
                li.setInfo('video', {'Title': SourceDetails.getTitle()})

            li.setProperty("Fanart_Image", SourceDetails.getFanArt())
            li.setProperty("search", "/search/?q=%s+Extras" % urllib.quote_plus(SourceDetails.getTitle().encode('utf8')))
            self.addItem(li)

        # Check if we want to have Vimeo Extra Support
        if Settings.isVimeoSearchSupportEnabled():
            # Create the message to the Vimeo Plugin
            li = xbmcgui.ListItem(ADDON.getLocalizedString(32122))
            # Need to set the title to get it in the header
            if SourceDetails.getTvShowTitle() != "":
                li.setInfo('video', {'TvShowTitle': SourceDetails.getTvShowTitle()})
            if SourceDetails.getTitle() != "":
                li.setInfo('video', {'Title': SourceDetails.getTitle()})

            li.setProperty("Fanart_Image", SourceDetails.getFanArt())
            li.setProperty("search", "/search/?q=%s+Extras" % urllib.quote_plus(SourceDetails.getTitle().encode('utf8')))
            self.addItem(li)

        for anExtra in self.files:
            log("VideoExtrasWindow: filename: %s" % anExtra.getFilename())

            # Create the list item
            anItem = anExtra.createListItem(path=SourceDetails.getFilenameAndPath(), parentTitle=SourceDetails.getTitle(), tvShowTitle=SourceDetails.getTvShowTitle())

            self.addItem(anItem)

        # Before we return, set back the selected on screen item to the one just watched
        # This is in the case of a reload
        if self.lastRecordedListPosition > 0:
            self.setCurrentListPosition(self.lastRecordedListPosition)

        xbmcgui.WindowXML.onInit(self)
コード例 #2
0
def start():
    global log
    settings = Settings()
    settings.getSettings()
    kl = KodiLogger()
    if settings.general['elevate_loglevel'] is True:
        kl.setLogLevel(xbmc.LOGNOTICE)
    else:
        kl.setLogLevel(xbmc.LOGDEBUG)
    log = kl.log
    log(msg=_('Settings read'))
    Cache.dispatcher = PubSub_Threaded.Dispatcher(interval=settings.general['TaskFreq'], sleepfxn=xbmc.sleep)
    log(msg=_('Dispatcher initialized'))

    subscriberfactory = SubscriberFactory(settings, kl)
    subscribers = subscriberfactory.createSubscribers()
    for subscriber in subscribers:
        Cache.dispatcher.addSubscriber(subscriber)
    publisherfactory = PublisherFactory(settings, subscriberfactory.topics, Cache.dispatcher, kl, debug)
    publisherfactory.createPublishers()
    Cache.publishers = publisherfactory.ipublishers

    Cache.dispatcher.start()
    log(msg=_('Dispatcher started'))

    for p in Cache.publishers:
        try:
            p.start()
        except threading.ThreadError:
            raise
    log(msg=_('Publisher(s) started'))
コード例 #3
0
ファイル: service.py プロジェクト: jatlaoui/script.pinsentry
    def check(self):
        # If we have found the correct user, then we need to ensure we are
        # in the valid time duration and have not exceeded the limit
        if not self.isEnabled:
            return True
        # Check for the case where we didn't get the user ID - this means we are
        # already shutting down
        if self.userId in [None, ""]:
            return False

        log("UserPinControl: Performing check for user %s" % self.userId)

        # First check that the current time is within the allowed boundaries
        localTime = time.localtime()
        currentTime = (localTime.tm_hour * 60) + localTime.tm_min

        if self.allowedStartTime > currentTime or self.allowedEndTime < currentTime:
            log("UserPinControl: User not allowed access until %d to %d currently %d" % (self.allowedStartTime, self.allowedEndTime, currentTime))
            self.shutdown(32130)
            return False

        # Check if the screensaver is running, if so we need to make sure we do not
        # class that as time used by the user
        if xbmc.getCondVisibility("System.ScreenSaverActive"):
            if self.screensaverStart < 1:
                self.screensaverStart = currentTime
        else:
            # Not the screensaver, check to see if this is the first check
            # after the screensaver stopped
            if self.screensaverStart > 0:
                screensaverDuration = currentTime - self.screensaverStart
                self.screensaverStart = 0
                log("UserPinControl: Updating duration for screensaver, %d minutes" % screensaverDuration)
                # Now we roll the time forward that we started viewing so that
                # we are not counting the screensaver
                self.startedViewing = self.startedViewing + screensaverDuration

            # Check to see if we need to update the record for how long the user has already been viewing
            viewingLimit = Settings.getUserViewingLimit(self.userId)
            self.usedViewingLimit = currentTime - self.startedViewing
            log("UserPinControl: Time used by user is %d" % self.usedViewingLimit)

            # Update the settings record for how much this user has viewed so far
            Settings.setUserViewingUsedTime(self.userId, self.usedViewingLimit)

            # Now check to see if the user has exceeded their limit
            if self.usedViewingLimit >= viewingLimit:
                self.shutdown(32133)
                return False

            # Check if we need to warn the user that the time is running out
            warningTime = Settings.getWarnExpiringTime()
            if (not self.warningDisplayed) and ((self.usedViewingLimit + warningTime) >= viewingLimit):
                self.warningDisplayed = True
                # Calculate the time left
                remainingTime = viewingLimit - self.usedViewingLimit
                msg = "%d %s" % (remainingTime, ADDON.getLocalizedString(32134))
                xbmcgui.Dialog().notification(ADDON.getLocalizedString(32001).encode('utf-8'), msg, ICON, 3000, False)

        return True
コード例 #4
0
    def _updatePlaylistForSettings(self, playlist):
        if playlist.size() < 1:
            return playlist

        filename = playlist[0].getfilename()
        duration = self._getVideoDuration(filename)
        log("Duration is %d for file %s" % (duration, filename))

        startTime = 0

        # Check if we have a random start time
        if Settings.isRandomStart():
            startTime = random.randint(0, int(duration * 0.75))

        clockStart = Settings.getTimeForClock(filename, duration)
        if clockStart > 0:
            startTime = clockStart

        # Set the random start
        if (startTime > 0) and (duration > 10):
            listitem = xbmcgui.ListItem()
            # Record if the theme should start playing part-way through
            listitem.setProperty('StartOffset', str(startTime))

            log("Setting start of %d for %s" % (startTime, filename))

            # Remove the old item from the playlist
            playlist.remove(filename)
            # Add the new item at the start of the list
            playlist.add(filename, listitem, 0)

        return playlist
コード例 #5
0
ファイル: plugin.py プロジェクト: kodibrasil/KodiBrasil
    def _moveToThemeFolder(self, directory):
        log("moveToThemeFolder: path = %s" % directory)

        # Handle the case where we have a disk image
        if (os_path_split(directory)[1] == 'VIDEO_TS') or (os_path_split(directory)[1] == 'BDMV'):
            directory = os_path_split(directory)[0]

        dirs, files = list_dir(directory)
        for aFile in files:
            m = re.search(Settings.getThemeFileRegEx(directory), aFile, re.IGNORECASE)
            if m:
                srcpath = os_path_join(directory, aFile)
                log("fetchAllMissingThemes: Found match: %s" % srcpath)
                targetpath = os_path_join(directory, Settings.getThemeDirectory())
                # Make sure the theme directory exists
                if not dir_exists(targetpath):
                    try:
                        xbmcvfs.mkdir(targetpath)
                    except:
                        log("fetchAllMissingThemes: Failed to create directory: %s" % targetpath, True, xbmc.LOGERROR)
                        break
                else:
                    log("moveToThemeFolder: directory already exists %s" % targetpath)
                # Add the filename to the path
                targetpath = os_path_join(targetpath, aFile)
                if not xbmcvfs.rename(srcpath, targetpath):
                    log("moveToThemeFolder: Failed to move file from %s to %s" % (srcpath, targetpath))
コード例 #6
0
    def __init__(self):
        # special://skin - This path points to the currently active skin's root directory.
        skinExtrasOverlayBase = xbmc.translatePath("special://skin").decode("utf-8")
        skinExtrasOverlayBase = os_path_join(skinExtrasOverlayBase, "media")

        # Now check to see if the user has defines a different overlay image in the
        # settings, as that is the main one that will be used
        self.skinExtrasOverlay = Settings.getCustomOverlayImage()
        self.skinExtrasOverlayList = Settings.getCustomListImage()

        # Next check the skin specific overlay
        if self.skinExtrasOverlay in [None, '']:
            self.skinExtrasOverlay = os_path_join(skinExtrasOverlayBase, "videoextras_overlay.png")
        if self.skinExtrasOverlayList in [None, '']:
            self.skinExtrasOverlayList = os_path_join(skinExtrasOverlayBase, "videoextras_overlay_list.png")

        log("VideoExtrasService: Looking for image overlay file: %s" % self.skinExtrasOverlay)

        if not xbmcvfs.exists(self.skinExtrasOverlay):
            log("VideoExtrasService: No custom image, using default")
            # Add default image setting to skinExtrasOverlay
            self.skinExtrasOverlay = os_path_join(RES_DIR, "skins")
            self.skinExtrasOverlay = os_path_join(self.skinExtrasOverlay, "icons")
            self.skinExtrasOverlay = os_path_join(self.skinExtrasOverlay, "overlay1.png")

        log("VideoExtrasService: Looking for list image overlay file: %s" % self.skinExtrasOverlayList)

        if not xbmcvfs.exists(self.skinExtrasOverlayList):
            log("VideoExtrasService: No custom wide image, using default")
            # Add default image setting to skinExtrasOverlay
            self.skinExtrasOverlayList = os_path_join(RES_DIR, "skins")
            self.skinExtrasOverlayList = os_path_join(self.skinExtrasOverlayList, "icons")
            self.skinExtrasOverlayList = os_path_join(self.skinExtrasOverlayList, "list1.png")

        self.forceOverlayOverwrite = False

        # We now know the file that we are going to use for the overlay
        # Check to see if this is different from the last overlay file used
        filename = os_path_join(PROFILE_DIR, "overlay_image_used.txt")
        try:
            previousOverlay = None
            if xbmcvfs.exists(filename):
                fileHandle = xbmcvfs.File(filename, 'r')
                previousOverlay = fileHandle.read()
                fileHandle.close()

            # Check if the overlay has changed
            if self.skinExtrasOverlay != previousOverlay:
                self.forceOverlayOverwrite = True
                # Update the record of the file we are now using
                if xbmcvfs.exists(filename):
                    xbmcvfs.delete(filename)
                fileHandle = xbmcvfs.File(filename, 'w')
                fileHandle.write(self.skinExtrasOverlay.encode("UTF-8"))
                fileHandle.close()
        except:
            log("VideoExtrasService: Failed to write: %s" % filename, xbmc.LOGERROR)
            log("VideoExtrasService: %s" % traceback.format_exc(), xbmc.LOGERROR)
コード例 #7
0
    def onClick(self, control):
        WINDOW_LIST_ID = 51
        # Check to make sure that this click was for the extras list
        if control != WINDOW_LIST_ID:
            return

        # Check the YouTube Search first, as if there are no Extras on disk
        # There will not be a PlayAll button and it will just be the YouTube Link
        youtubePosition = 0
        vimeoPosition = 0
        if len(self.files) > 0:
            youtubePosition = youtubePosition + 1
            vimeoPosition = vimeoPosition + 1

        if Settings.isYouTubeSearchSupportEnabled():
            vimeoPosition = vimeoPosition + 1
            if self.getCurrentListPosition() == youtubePosition:
                anItem = self.getListItem(youtubePosition)
                searchDetails = anItem.getProperty("search")
                log("VideoExtras: Running YouTube Addon/Plugin with search %s" % searchDetails)
                xbmc.executebuiltin("RunAddon(plugin.video.youtube,%s)" % searchDetails)
                return

        if Settings.isVimeoSearchSupportEnabled() and self.getCurrentListPosition() == vimeoPosition:
                anItem = self.getListItem(vimeoPosition)
                searchDetails = anItem.getProperty("search")
                log("VideoExtras: Running Vimeo Addon/Plugin with search %s" % searchDetails)
                xbmc.executebuiltin("RunAddon(plugin.video.vimeo,%s)" % searchDetails)
                return

        # Check for the Play All case
        if self.getCurrentListPosition() == 0:
            ExtrasPlayer.playAll(self.files, SourceDetails.getTitle())
            return

        # Get the item that was clicked on
        extraItem = self._getCurrentSelection()

        if extraItem is None:
            # Something has gone very wrong, there is no longer the item that was selected
            log("VideoExtrasWindow: Unable to match item to current selection")
            return

        # If part way viewed prompt the user for resume or play from beginning
        if extraItem.getResumePoint() > 0:
            resumeWindow = VideoExtrasResumeWindow.createVideoExtrasResumeWindow(extraItem.getDisplayResumePoint())
            resumeWindow.doModal()

            # Check the return value, if exit, then we play nothing
            if resumeWindow.isExit():
                return
            # If requested to restart from beginning, reset the resume point before playing
            if resumeWindow.isRestart():
                extraItem.setResumePoint(0)
            # Default is to actually resume
            del resumeWindow

        ExtrasPlayer.performPlayAction(extraItem, SourceDetails.getTitle())
コード例 #8
0
    def getScheduleEntry(self):
        # Get the current time that we are checking the schedule for
        localTime = time.localtime()
        currentTime = (localTime.tm_hour * 60) + localTime.tm_min

        # Get the current day of the week
        # 0 = Monday 6 = Sunday
        today = localTime.tm_wday
        # Make sure that the day returned is within our expected list
        if today not in Settings.DAY_TYPE:
            log("Schedule: Unknown day today %d, setting to everyday" % today)
            today = Settings.EVERY_DAY

        # Check if we need to refresh the schedule details from the file
        # in case they have changed
        if Settings.getScheduleSetting() == Settings.SCHEDULE_FILE:
            # Check if the file has changed
            scheduleFileName = Settings.getScheduleFile()
            if scheduleFileName not in [None, ""]:
                if xbmcvfs.exists(scheduleFileName):
                    statFile = xbmcvfs.Stat(scheduleFileName)
                    modified = statFile.st_mtime()
                    if modified != self.lastScheduleModified:
                        log("Schedule: Schedule file has changed (%s)" % str(modified))
                        # We use the offset to work out if the data has changed
                        if self.idOffset > 0:
                            self.idOffset = 0
                        else:
                            self.idOffset = 1000
                        # Clear the existing schedule items
                        self.scheduleDetails = []
                        # Load the new schedule items
                        self._loadFromFile()

        # Check the scheduled items to see if any cover the current time
        for item in self.scheduleDetails:
            if (item['start'] <= currentTime) and (item['end'] >= currentTime):
                # Make sure this is for the current day
                if (today == Settings.EVERY_DAY) or (item['day'] in [Settings.EVERY_DAY, today]):
                    return item['id']
            # Check for the case where the time laps over midnight
            if item['start'] > item['end']:
                if (currentTime >= item['start']) or (currentTime <= item['end']):
                    # Check to see if we are restricting to day
                    if (today == Settings.EVERY_DAY) or (item['day'] == Settings.EVERY_DAY):
                        return item['id']
                    else:
                        if (currentTime >= item['start']) and (item['day'] in [Settings.EVERY_DAY, today]):
                            return item['id']
                        else:
                            # The day is set for the start of the time interval
                            # so if we go over to the next day we need to update
                            # what the expected day is
                            nextDay = Settings.getNextDay(item['day'])
                            if (currentTime <= item['end']) and (item['day'] in [Settings.EVERY_DAY, nextDay]):
                                return item['id']
        return -1
コード例 #9
0
    def __init__(self, *args):
        self.scheduleDetails = []
        self.idOffset = 0
        self.lastScheduleModified = 0

        if Settings.getScheduleSetting() == Settings.SCHEDULE_SETTINGS:
            self._loadFromSettings()
        elif Settings.getScheduleSetting() == Settings.SCHEDULE_FILE:
            self._loadFromFile()
コード例 #10
0
ファイル: service.py プロジェクト: jatlaoui/script.pinsentry
    def checkPlugins(self):
        navPath = xbmc.getInfoLabel("Container.FolderPath")
        if 'plugin://' not in navPath:
            # No Plugin currently set
            self.lastPluginChecked = ""
            return

        # Check if we are in a plugin location
        pluginName = xbmc.getInfoLabel("Container.FolderName")

        if pluginName in [None, "", self.lastPluginChecked]:
            # No Plugin currently set or this is a Plugin that has already been checked
            return

        # If we reach here we have aPlugin that we need to check
        log("NavigationRestrictions: Checking access to view Plugin: %s" % pluginName)
        self.lastPluginChecked = pluginName

        # Check for the case where the user does not want to check plugins
        # but the Pin Sentry plugin is selected, we always need to check this
        # as it is how permissions are set
        if (not Settings.isActivePlugins()) and ('PinSentry' not in pluginName):
            return

        securityLevel = 0
        # Check to see if the user should have access to this plugin
        pinDB = PinSentryDB()
        securityLevel = pinDB.getPluginSecurityLevel(pluginName)
        if securityLevel < 1:
            # Check for the special case that we are accessing ourself
            # in which case we have a minimum security level
            if 'PinSentry' in pluginName:
                securityLevel = Settings.getSettingsSecurityLevel()
            else:
                log("NavigationRestrictions: No security enabled for plugin %s" % pluginName)
                return
        del pinDB

        # Check if we have already cached the pin number and at which level
        if PinSentry.getCachedPinLevel() >= securityLevel:
            log("NavigationRestrictions: Already cached pin at level %d, allowing access" % PinSentry.getCachedPinLevel())
            return

        # Prompt the user for the pin, returns True if they knew it
        if PinSentry.promptUserForPin(securityLevel):
            log("NavigationRestrictions: Allowed access to plugin %s" % pluginName)
        else:
            log("NavigationRestrictions: Not allowed access to plugin %s which has security level %d" % (pluginName, securityLevel))
            # Move back to the Video plugin Screen as they are not allowed where they are at the moment
            xbmc.executebuiltin("ActivateWindow(Video,addons://sources/video/)", True)
            # Clear the previous plugin as we will want to prompt for the pin again if the
            # user navigates there again
            self.lastPluginChecked = ""
            PinSentry.displayInvalidPinMessage(securityLevel)
コード例 #11
0
def test(key):
    global log
    log = KodiLogger.log
    import resources.lib.tests.direct_test as direct_test
    from resources.lib.events import Events
    import traceback
    log(msg=_('Running Test for Event: %s') % key)
    events = Events().AllEvents
    settings = Settings()
    settings.getSettings()
    if settings.general['elevate_loglevel'] is True:
        KodiLogger.setLogLevel(xbmc.LOGNOTICE)
    else:
        KodiLogger.setLogLevel(xbmc.LOGDEBUG)
    log(msg=_('Settings for test read'))
    evtsettings = settings.events[key]
    topic = settings.topicFromSettingsEvent(key)
    task_key = settings.events[key]['task']
    tasksettings = settings.tasks[task_key]
    testlogger = direct_test.TestLogger()
    log(msg=_('Creating subscriber for test'))
    subscriberfactory = SubscriberFactory(settings, testlogger)
    subscriber = subscriberfactory.createSubscriber(key)
    if subscriber is not None:
        log(msg=_('Test subscriber created successfully'))
        try:
            kwargs = events[evtsettings['type']]['expArgs']
        except KeyError:
            kwargs = {}
        testRH = direct_test.TestHandler(direct_test.testMsg(subscriber.taskmanagers[0], tasksettings, kwargs))
        subscriber.taskmanagers[0].returnHandler = testRH.testReturnHandler
        # Run test
        log(msg=_('Running test'))
        nMessage = PubSub_Threaded.Message(topic=topic, **kwargs)
        try:
            subscriber.notify(nMessage)
        except Exception:
            msg = _('Unspecified error during testing')
            e = sys.exc_info()[0]
            if hasattr(e, 'message'):
                msg = str(e.message)
            msg = msg + '\n' + traceback.format_exc()
            log(msg=msg)
            msgList = msg.split('\n')
            import resources.lib.dialogtb as dialogtb
            dialogtb.show_textbox('Error', msgList)
    else:
        log(msg=_('Test subscriber creation failed due to errors'))
        msgList = testlogger.retrieveLogAsList()
        import resources.lib.dialogtb as dialogtb
        dialogtb.show_textbox('Error', msgList)

    xbmc.sleep(2000)
コード例 #12
0
ファイル: service.py プロジェクト: jatlaoui/script.pinsentry
    def checkSystemSettings(self):
        # Check if the system restriction is enabled
        if not Settings.isActiveSystemSettings():
            return

        # Check to see if the main system settings has been selected
        systemSettings = xbmc.getCondVisibility("Window.IsActive(10004)")
        addonBrowser = xbmc.getCondVisibility("Window.IsActive(10040)")
        profiles = xbmc.getCondVisibility("Window.IsActive(10034)")

        # Check if we are in any of the restricted sections
        if not systemSettings and not addonBrowser and not profiles:
            log("NavigationRestrictions: Not is restricted system settings")
            return

        # If we have already allowed the user to change settings, no need to check again
        # Check if we are still in the allowed time limit to edit
        if int(time.time()) < self.canChangeSettings:
            return

        # Need to make sure this user has access to change the settings
        pinDB = PinSentryDB()
        securityLevel = pinDB.getPluginSecurityLevel('PinSentry')
        del pinDB

        if securityLevel < 1:
            # If the user hasn't reset the permissions, then set it to the highest
            # security level available
            securityLevel = Settings.getSettingsSecurityLevel()
            log("NavigationRestrictions: Settings screen requires security level %d" % securityLevel)

        # Check if we have already cached the pin number and at which level
        if PinSentry.getCachedPinLevel() >= securityLevel:
            log("NavigationRestrictions: Already cached pin at level %d, allowing access" % PinSentry.getCachedPinLevel())
            return

        # Before we prompt the user we need to close the dialog, otherwise the pin
        # dialog will appear behind it
        xbmc.executebuiltin("Dialog.Close(all, true)", True)

        # Prompt the user for the pin, returns True if they knew it
        if PinSentry.promptUserForPin(securityLevel):
            log("NavigationRestrictions: Allowed access to settings")
            # Allow the user 5 minutes to change the settings
            self.canChangeSettings = int(time.time()) + 300
            xbmcgui.Dialog().notification(ADDON.getLocalizedString(32001).encode('utf-8'), ADDON.getLocalizedString(32110).encode('utf-8'), ICON, 3000, False)
        else:
            log("NavigationRestrictions: Not allowed access to settings which has security level %d" % securityLevel)
            self.canChangeSettings = False
            PinSentry.displayInvalidPinMessage(securityLevel)
            # Return the user to the home page as they should not be here
            xbmc.executebuiltin("ActivateWindow(home)", True)
コード例 #13
0
    def onInit(self):
        xbmcgui.WindowXML.onInit(self)
        self.volumeCtrl = None

        # Get the videos to use as a screensaver
        playlist = self._getPlaylist()
        # If there is nothing to play, then exit now
        if playlist is None:
            self.close()
            return

        # Update the playlist with any settings such as random start time
        self._updatePlaylistForSettings(playlist)

        # Update the volume if needed
        self.volumeCtrl = VolumeDrop()
        self.volumeCtrl.lowerVolume()

        # Now play the video
        self.player.play(playlist)

        # Set the video to loop, as we want it running as long as the screensaver
        self._setRepeat()
        log("Started playing")

        # Now check to see if we are overlaying the time on the screen
        # Default is hidden
        timeControl = self.getControl(ScreensaverWindow.TIME_CONTROL)
        timeControl.setVisible(Settings.isShowTime())

        # Check if we need to show the weather
        weatherControl = self.getControl(ScreensaverWindow.WEATHER_CONTROL)
        if Settings.getWeatherAddon() not in ["", None]:
            weatherControl.setVisible(True)
        else:
            weatherControl.setVisible(False)

        # Set the value of the dimming for the video
        dimLevel = Settings.getDimValue()
        if dimLevel is not None:
            log("Setting Dim Level to: %s" % dimLevel)
            dimControl = self.getControl(ScreensaverWindow.DIM_CONTROL)
            dimControl.setColorDiffuse(dimLevel)

        # Set the overlay image
        self._setOverlayImage()

        # Update any settings that need to be done after the video is playing
        self._updatePostPlayingForSettings(playlist)
コード例 #14
0
ファイル: service.py プロジェクト: jatlaoui/script.pinsentry
 def displayInvalidPinMessage(level=1):
     # Invalid Key Notification: Dialog, Popup Notification, None
     notifType = Settings.getInvalidPinNotificationType()
     if notifType == Settings.INVALID_PIN_NOTIFICATION_POPUP:
         cmd = ""
         if Settings.getNumberOfLevels() > 1:
             cmd = 'Notification("{0}", "{1} {2}", 3000, "{3}")'.format(ADDON.getLocalizedString(32104).encode('utf-8'), ADDON.getLocalizedString(32211).encode('utf-8'), str(level), ICON)
         else:
             cmd = 'Notification("{0}", "{1}", 3000, "{2}")'.format(ADDON.getLocalizedString(32001).encode('utf-8'), ADDON.getLocalizedString(32104).encode('utf-8'), ICON)
         xbmc.executebuiltin(cmd)
     elif notifType == Settings.INVALID_PIN_NOTIFICATION_DIALOG:
         line3 = None
         if Settings.getNumberOfLevels() > 1:
             line3 = "%s %d" % (ADDON.getLocalizedString(32211), level)
         xbmcgui.Dialog().ok(ADDON.getLocalizedString(32001).encode('utf-8'), ADDON.getLocalizedString(32104).encode('utf-8'), line3)
コード例 #15
0
ファイル: plugin.py プロジェクト: kodibrasil/KodiBrasil
    def _doesThemeExist(self, directory, checkParent=False, incAudioThemes=True, incVideoThemes=True):
        log("doesThemeExist: Checking directory: %s" % directory)
        # Check for custom theme directory
        if Settings.isThemeDirEnabled():
            themeDir = os_path_join(directory, Settings.getThemeDirectory())
            # Check if this directory exists
            if not dir_exists(themeDir):
                workingPath = directory
                # If the path currently ends in the directory separator
                # then we need to clear an extra one
                if (workingPath[-1] == os.sep) or (workingPath[-1] == os.altsep):
                    workingPath = workingPath[:-1]
                # If not check to see if we have a DVD VOB
                if (os_path_split(workingPath)[1] == 'VIDEO_TS') or (os_path_split(workingPath)[1] == 'BDMV'):
                    # Check the parent of the DVD Dir
                    themeDir = os_path_split(workingPath)[0]
                    themeDir = os_path_join(themeDir, Settings.getThemeDirectory())
            directory = themeDir

        # Check to see if we need to check the parent directory
        if checkParent:
            directory = os_path_split(directory)[0]

        # check if the directory exists before searching
        if dir_exists(directory):
            # Generate the regex
            audioOnly = False
            videoOnly = False
            if not incAudioThemes:
                videoOnly = True
            if not incVideoThemes:
                audioOnly = True

            themeFileRegEx = Settings.getThemeFileRegEx(audioOnly=audioOnly, videoOnly=videoOnly)

            dirs, files = list_dir(directory)
            for aFile in files:
                m = re.search(themeFileRegEx, aFile, re.IGNORECASE)
                if m:
                    log("doesThemeExist: Found match: " + aFile)
                    return True
        # Check if an NFO file exists
        nfoFileName = os_path_join(directory, "tvtunes.nfo")
        if xbmcvfs.exists(nfoFileName):
            log("doesThemeExist: Found match: " + nfoFileName)
            return True

        return False
コード例 #16
0
    def _getAllFilesInDirectory(self, baseDir, includeSubDirs=True):
        videoFiles = []
        dirs, files = list_dir(baseDir)

        # Get the list of files that are to be excluded
        collectionCtrl = CollectSets()
        disabledVideos = collectionCtrl.getDisabledVideos()
        del collectionCtrl

        # Get all the files in the current directory
        for vidFile in files:
            # Check if this file is excluded
            if vidFile in disabledVideos:
                log("Ignoring disabled screensaver video %s" % vidFile)
                continue

            fullPath = os_path_join(baseDir, vidFile)
            videoFiles.append(fullPath)

        # Now check each directory
        if includeSubDirs and Settings.isFolderNested():
            for aDir in dirs:
                fullPath = os_path_join(baseDir, aDir)
                dirContents = self._getAllFilesInDirectory(fullPath)
                videoFiles = videoFiles + dirContents

        return videoFiles
コード例 #17
0
    def removeCollection(self, name, link):
        if name in [None, ""]:
            return

        collectionCtrl = CollectSets()
        collectionDetails = collectionCtrl.loadCollection(link)

        filesToDelete = []
        # If the file was not processed just don't display anything
        if collectionDetails not in [None, ""]:
            screensaverFolder = Settings.getScreensaverFolder()

            for videoItem in collectionDetails['videos']:
                # If theme exists we need to check if we want to delete it
                if screensaverFolder not in [None, ""]:
                    videoLocation = os_path_join(screensaverFolder, videoItem['filename'])

                    log("VideoScreensaverPlugin: Checking if %s already downloaded to %s" % (videoItem['filename'], videoLocation))
                    if xbmcvfs.exists(videoLocation):
                        filesToDelete.append(videoLocation)

        # If there are possible files to delete, then prompt the user to see if we should
        if len(filesToDelete) > 0:
            needDelete = xbmcgui.Dialog().yesno(ADDON.getLocalizedString(32005), ADDON.getLocalizedString(32086))

            if needDelete:
                for vidFile in filesToDelete:
                    xbmcvfs.delete(vidFile)

        # Now remove the actual collection
        collectionCtrl.removeCustomCollection(name)
        del collectionCtrl

        # Now reload the screen to reflect the change
        xbmc.executebuiltin("Container.Refresh")
コード例 #18
0
    def onPlayBackStarted(self):
        # The first item in a playlist will have already had it's start time
        # set correctly if it is a clock
        if self.initialStart is True:
            self.initialStart = False
            log("onPlayBackStarted received for initial video")
            return

        if self.isPlayingVideo():
            # Get the currently playing file
            filename = self.getPlayingFile()
            log("onPlayBackStarted received for file %s" % filename)

            duration = self._getVideoDuration(filename)
            log("onPlayBackStarted: Duration is %d for file %s" % (duration, filename))

            startTime = Settings.getTimeForClock(filename, duration)

            # Set the clock start time
            if startTime > 0 and duration > 10:
                self.seekTime(startTime)
        else:
            log("onPlayBackStarted received, but not playing video file")

        xbmc.Player.onPlayBackStarted(self)
コード例 #19
0
 def getFilenameAndPath():
     if SourceDetails.filenameAndPath is None:
         extrasDirName = Settings.getExtrasDirName()
         if (extrasDirName is None) or (extrasDirName == ""):
             extrasDirName = "Extras"
         SourceDetails.filenameAndPath = "%s%s" % (xbmc.getInfoLabel("ListItem.FilenameAndPath"), extrasDirName)
     return SourceDetails.filenameAndPath
コード例 #20
0
ファイル: default.py プロジェクト: robwebset/script.sonos
    def updateDisplay(self, eventDetails=None):
        SonosControllerWindow.updateDisplay(self, eventDetails)

        # Now we have updated the track currently playing read the details out and
        # set the windows properties for ArtistSlideshow
        # Only update if the track has changed
        if self.currentTrack not in [None, '']:
            # Check if we want to show lyrics for the track, although not part of the
            # artist slideshow feature (it is part of script.cu.lrclyrics) we treat
            # this in a similar manner, first set the values
            lyrics = None
            if Settings.isLyricsInfoLayout():
                lyrics = Lyrics(self.currentTrack, self.getControl(SonosArtistSlideshow.LYRICS), self.lyricListLinesCount)
                lyrics.setLyricRequest()

            # Artist Slideshow will set these properties for us
            xbmcgui.Window(self.windowId).setProperty('CURRENTARTIST', self.currentTrack['artist'])
            xbmcgui.Window(self.windowId).setProperty('CURRENTTITLE', self.currentTrack['title'])
            xbmcgui.Window(self.windowId).setProperty('CURRENTALBUM', self.currentTrack['album'])

            # Check if lyrics are enabled, and set the test if they are
            if lyrics is not None:
                self.currentTrack = lyrics.populateLyrics()
                lyrics.refresh()
                del lyrics
コード例 #21
0
    def _getContextMenu(self, videoItem):
        ctxtMenu = []

        # Check if the file has already been downloaded
        if self._getVideoLocation(Settings.getScreensaverFolder(), videoItem['filename']) in [None, ""]:
            # If not already exists, add a download option
            cmd = self._build_url({'mode': 'download', 'name': videoItem['name'], 'filename': videoItem['filename'], 'primary': videoItem['primary']})
            ctxtMenu.append((ADDON.getLocalizedString(32013), 'RunPlugin(%s)' % cmd))
            # If not already exists, add a download option
            cmd = self._build_url({'mode': 'play', 'name': videoItem['name'], 'filename': videoItem['primary']})
            ctxtMenu.append((ADDON.getLocalizedString(32019), 'RunPlugin(%s)' % cmd))
        else:
            # If already exists then add a play option
            cmd = self._build_url({'mode': 'play', 'name': videoItem['name'], 'filename': videoItem['filename']})
            ctxtMenu.append((ADDON.getLocalizedString(32015), 'RunPlugin(%s)' % cmd))
            # If already exists then add a delete option
            cmd = self._build_url({'mode': 'delete', 'name': videoItem['name'], 'filename': videoItem['filename']})
            ctxtMenu.append((ADDON.getLocalizedString(32014), 'RunPlugin(%s)' % cmd))

            # Check if we need a menu item to enable and disable the videos
            if videoItem['enabled']:
                cmd = self._build_url({'mode': 'enable', 'disable': 'true', 'filename': videoItem['filename']})
                ctxtMenu.append((ADDON.getLocalizedString(32017), 'RunPlugin(%s)' % cmd))
            else:
                cmd = self._build_url({'mode': 'enable', 'disable': 'false', 'filename': videoItem['filename']})
                ctxtMenu.append((ADDON.getLocalizedString(32018), 'RunPlugin(%s)' % cmd))

        return ctxtMenu
コード例 #22
0
ファイル: plugin.py プロジェクト: croneter/script.videoextras
    def hasVideoExtras(self, target, dbid, file, title=None):
        # If the service is on, then we can just check to see if the overlay image exists
        if Settings.isServiceEnabled():
            # Get the path where the file exists
            rootPath = os_path_join(PROFILE_DIR, target)
            if not dir_exists(rootPath):
                # Directory does not exist yet, so can't have extras
                return False

            # Generate the name of the file that the overlay will be copied to
            targetFile = os_path_join(rootPath, ("%d.png" % dbid))
            if xbmcvfs.exists(targetFile):
                return True

        # Otherwise, need to do the lookup the old fashioned way of looking for the
        # extras files on the file system (This is much slower)
        else:
            videoExtras = VideoExtrasBase(file, target, title)
            # We are only checking for existence of extras, no need for fanart
            firstExtraFile = videoExtras.findExtras(True)
            del videoExtras
            if firstExtraFile:
                log("MenuNavigator: Extras found for (%d) %s" % (dbid, file))
                return True

        return False
コード例 #23
0
    def _getNewSettingsXml(self):
        regexSection = ''
        # Put together the regex section details
        extrasTag = Settings.getExtrasFileTag()
        if extrasTag != "":
            log("Setting Tag Name to: %s" % extrasTag)
            regexSection = AdvSettings.REGEX_SECTION.format(extrasTag)
        # Check what the directory name is
        extrasDir = Settings.getExtrasDirName()
        log("Setting Directory Name to: %s" % extrasDir)
        regexSection += AdvSettings.REGEX_SECTION.format('/' + extrasDir + '/')
        regexSection += AdvSettings.REGEX_SECTION.format('[\\\\\\/]' + extrasDir + '[\\\\\\/]')

        # Now put together the ignore section
        ignoreSection = AdvSettings.IGNORE_SECTION.format(regexSection)
        return ignoreSection
コード例 #24
0
ファイル: plugin.py プロジェクト: kodibrasil/KodiBrasil
    def fetchTheme(self, title, path, originaltitle=None, isTvShow=None, year=None, imdb=None):
        # If there is already a theme then start playing it
        self._startPlayingExistingTheme(path)

        if Settings.isThemeDirEnabled() and self._doesThemeExist(path, True):
            # Prompt user if we should move themes in the parent
            # directory into the theme directory
            moveExistingThemes = xbmcgui.Dialog().yesno(ADDON.getLocalizedString(32105), ADDON.getLocalizedString(32206), ADDON.getLocalizedString(32207))

            # Check if we need to move a theme file
            if moveExistingThemes:
                log("fetchAllMissingThemes: Moving theme for %s" % title)
                self._moveToThemeFolder(path)
                # Stop playing any theme that started
                self._stopPlayingTheme()
                # Now reload the screen to reflect the change
                xbmc.executebuiltin("Container.Refresh")
                return

        if originaltitle is not None:
            originaltitle = normalize_string(originaltitle)

        # Perform the fetch
        videoList = []
        normtitle = normalize_string(title)
        videoItem = {'title': normtitle, 'path': path, 'originalTitle': originaltitle, 'isTvShow': isTvShow, 'year': year, 'imdb': imdb}
        videoList.append(videoItem)
        TvTunesFetcher(videoList)

        # Stop playing any theme that started
        self._stopPlayingTheme()

        # Now reload the screen to reflect the change
        xbmc.executebuiltin("Container.Refresh")
コード例 #25
0
    def _getNewSettingsXml(self):
        regexSection = ''
        # Put together the regex section details
        # Check what the directory name is
        themeDir = Settings.getThemeDirectory()
        log("Setting Directory Name to: %s" % themeDir)
        regexSection += AdvSettings.REGEX_SECTION.format('/' + themeDir + '/')
        regexSection += AdvSettings.REGEX_SECTION.format('[\\\\\\/]' + themeDir + '[\\\\\\/]')

        # Put together the list of file endings
        videoFileTypes = Settings.getVideoThemeFileExtensions()
        if videoFileTypes not in [None, ""]:
            regexSection += AdvSettings.REGEX_SECTION.format('theme([0-9]*)\.(' + videoFileTypes.lower() + '|' + videoFileTypes.upper() + ')$')

        # Now put together the ignore section
        ignoreSection = AdvSettings.IGNORE_SECTION.format(regexSection)
        return ignoreSection
コード例 #26
0
ファイル: plugin.py プロジェクト: kodibrasil/KodiBrasil
    def getPathForVideoItem(self, videoItem):
        path = ""
        # Get the path where the theme should be stored
        if Settings.isCustomPathEnabled():
            path = os_path_join(Settings.getCustomPath(), normalize_string(videoItem['title']))
        else:
            path = videoItem['file']
            # Handle stacked files that have a custom file name format
            if path.startswith("stack://"):
                path = path.replace("stack://", "").split(" , ", 1)[0]
            # Need to remove the filename from the end  as we just want the directory
            fileExt = os.path.splitext(path)[1]
            # If this is a file, then get it's parent directory
            if fileExt is not None and fileExt != "":
                path = os_path_split(path)[0]

        return path
コード例 #27
0
ファイル: service.py プロジェクト: robwebset/script.sonos
    def checkVolumeChange(self):
        # Check to see if the Sonos Volume Redirect is Enabled
        if not Settings.redirectVolumeControls():
            return

        self.volumeChangeNotification = self.volumeChangeNotification - 1
        redirect = xbmcgui.Window(10000).getProperty("SonosVolumeRedirect")

        while redirect not in [None, ""]:
            xbmcgui.Window(10000).clearProperty("SonosVolumeRedirect")

            volumeChange = 0
            isMute = False
            if redirect.lower() == "up":
                volumeChange = Settings.getVolumeChangeIncrements()
            elif redirect.lower() == "down":
                volumeChange = Settings.getVolumeChangeIncrements() * -1
            elif redirect.lower() == "mute":
                isMute = True

            log("SonosVolumeRedirect: Changing by %d" % volumeChange)

            # Check to see if it has changed, and if we need to change the sonos value
            if isMute:
                # Check the current muted state
                if sonosDevice.mute:
                    sonosDevice.fullMute(False)
                else:
                    sonosDevice.fullMute(True)
                self.volumeChangeNotification = Settings.getChecksPerSecond() * 2
            elif volumeChange != 0:
                sonosDevice.setGroupVolume(sonosDevice.volume + volumeChange, True)
                self.volumeChangeNotification = Settings.getChecksPerSecond() * 2

            redirect = xbmcgui.Window(10000).getProperty("SonosVolumeRedirect")

        # Check if we have started changing the volume and have now stopped
        # for a little while
        if self.volumeChangeNotification == 0:
            self.volumeChangeNotification = -1
            if sonosDevice.mute:
                xbmcgui.Dialog().notification(ADDON.getLocalizedString(32074), ADDON.getLocalizedString(32075), ICON, 2000, False)
            else:
                displayMsg = "%d" % sonosDevice.volume
                xbmcgui.Dialog().notification(ADDON.getLocalizedString(32074), displayMsg, ICON, 2000, False)
コード例 #28
0
 def restoreVolume(self):
     try:
         if Settings.isUseAudioSuspend():
             xbmc.audioResume()
         # Don't change the volume unless requested to
         elif self.screensaverVolume > -1:
             self._setVolume(self.original_volume)
     except:
         log("VolumeDrop: %s" % traceback.format_exc(), xbmc.LOGERROR)
コード例 #29
0
def checkVimeoSettings():
    # Check to see if the Vimeo support is enabled
    if Settings.isVimeoSearchSupportEnabled():
        # It is enabled in settings, but we should check to ensure that the
        # Vimeo addon is actually installed
        vimeoInstalled = False
        try:
            vimeoAddon = xbmcaddon.Addon(id='plugin.video.vimeo')
            if vimeoAddon not in [None, ""]:
                vimeoInstalled = True
        except:
            # We will get an exception if we can not find the Vimeo addon
            vimeoInstalled = False

        if not vimeoInstalled:
            # There is no Vimeo addon installed, so disable this option in settings
            log("VideoExtrasService: Disabling Vimeo support as addon not installed")
            Settings.disableVimeoSearchSupport()
コード例 #30
0
def checkYouTubeSettings():
    # Check to see if the YouTube support is enabled
    if Settings.isYouTubeSearchSupportEnabled():
        # It is enabled in settings, but we should check to ensure that the
        # YouTube addon is actually installed
        youtubeInstalled = False
        try:
            youtubeAddon = xbmcaddon.Addon(id='plugin.video.youtube')
            if youtubeAddon not in [None, ""]:
                youtubeInstalled = True
        except:
            # We will get an exception if we can not find the YouTube addon
            youtubeInstalled = False

        if not youtubeInstalled:
            # There is no YouTube addon installed, so disable this option in settings
            log("VideoExtrasService: Disabling YouTube support as addon not installed")
            Settings.disableYouTubeSearchSupport()
コード例 #31
0
 def onSettingsChanged(self):
     log("TvTunesMonitor: Notification of settings change received")
     Settings.reloadSettings()
コード例 #32
0
##################################
# Main of the Video Screensaver
##################################
if __name__ == '__main__':
    # Check for the case where the screensaver has been launched as a script
    # But needs to behave like the full screensaver, not just a video player
    # This is the case for things like screensaver.random
    if (len(sys.argv) > 1) and ("screensaver" in sys.argv[1]):
        # Launch the core screensaver script - this will ensure all the pre-checks
        # are done (like TvTunes) before running the screensaver
        log("Screensaver started by script with screensaver argument")
        xbmc.executebuiltin('RunScript(%s)' %
                            (os.path.join(CWD, "default.py")))
    else:
        # Check if we need to load the weather settings
        weatherAddon = Settings.getWeatherAddon()
        if weatherAddon not in ["", None]:
            log("Using weather addon %s" % weatherAddon)
            xbmc.executebuiltin('RunScript(%s,0)' % weatherAddon, False)

        # Before we start, make sure that the settings have been updated correctly
        Settings.cleanAddonSettings()

        screenWindow = ScreensaverWindow.createScreensaverWindow()

        xbmcgui.Window(10000).setProperty("VideoScreensaverRunning", "true")

        didScreensaverTimeout = False
        try:
            # Now show the window and block until we exit
            screensaverTimeout = Settings.screensaverTimeout()
コード例 #33
0
 def _updatePostPlayingForSettings(self, playlist):
     # Check if we need to start at a random location
     if Settings.isRandomStart() and playlist.size() > 0:
         # Need to reset the offset to the start so that if it loops
         # it will play from the start
         playlist[0].setProperty('StartOffset', "0")
コード例 #34
0
 def __init__(self, *args):
     self.screensaverVolume = Settings.getVolume()
     if self.screensaverVolume > -1:
         # Save the volume from before any alterations
         self.original_volume = self._getVolume()
コード例 #35
0
    def _loadFromFile(self):
        # Get the videos schedule that is stored in the file
        scheduleFileName = Settings.getScheduleFile()
        if scheduleFileName in [None, ""]:
            log("Schedule: No schedule file set")
            return

        log("Schedule: Searching for schedule file: %s" % scheduleFileName)

        # Return False if file does not exist
        if not xbmcvfs.exists(scheduleFileName):
            log("Schedule: No schedule file found: %s" % scheduleFileName)
            return

        # Save off the time this file was modified
        statFile = xbmcvfs.Stat(scheduleFileName)
        self.lastScheduleModified = statFile.st_mtime()
        log("Schedule: Reading in schedule file with modify time: %s" %
            str(self.lastScheduleModified))

        # The file exists, so start loading it
        try:
            # Need to first load the contents of the file into
            # a string, this is because the XML File Parse option will
            # not handle formats like smb://
            scheduleFile = xbmcvfs.File(scheduleFileName, 'r')
            scheduleFileStr = scheduleFile.read()
            scheduleFile.close()

            # Create an XML parser
            scheduleXml = ET.ElementTree(ET.fromstring(scheduleFileStr))
            rootElement = scheduleXml.getroot()

            log("Schedule: Root element is = %s" % rootElement.tag)

            # Check which format if being used
            if rootElement.tag == "schedule":
                log("Schedule: Schedule format file detected")
                #    <schedule>
                #        <rule start="14:24" end="14:37" video="video3.mkv" overlay="WindowFrame1.png" />
                #    </schedule>

                # Get the directory that the schedule file is in as this might be needed
                # if we have local paths in the XML file
                directory = os_path_split(scheduleFileName)[0]

                # There could be multiple rule entries, so loop through all of them
                itemNum = self.idOffset + 1
                for ruleElem in scheduleXml.findall('rule'):
                    if ruleElem is not None:
                        videoFile = ruleElem.get('video', None)
                        overlayFile = ruleElem.get('overlay', None)
                        startTime = self._convertTimeToMinutes(
                            ruleElem.get('start', "00:00"))
                        endTime = self._convertTimeToMinutes(
                            ruleElem.get('end', "00:00"))
                        day = self._convertDayFormat(ruleElem.get('day', None))

                    if (videoFile not in [None, ""]) and (startTime not in [
                            None, ""
                    ]) and (endTime not in [None, ""]):
                        # Make it a full path if it is not already
                        if videoFile.startswith('..') or (
                            ("/" not in videoFile) and
                            ("\\" not in videoFile)):
                            videoFile = os_path_join(directory, videoFile)
                        if overlayFile not in [None, ""]:
                            if overlayFile.startswith('..') or (
                                ("/" not in overlayFile) and
                                ("\\" not in overlayFile)):
                                overlayFile = os_path_join(
                                    directory, overlayFile)
                        log("Schedule File: Item %d (Start:%d, End:%d) contains video %s"
                            % (itemNum, startTime, endTime, videoFile))

                        # Check if the video file exists
                        if os_path_isfile(videoFile):
                            details = {
                                'id': itemNum,
                                'start': startTime,
                                'end': endTime,
                                'day': day,
                                'video': videoFile,
                                'overlay': overlayFile
                            }
                            self.scheduleDetails.append(details)
                        else:
                            log("Schedule: File does not exist: %s" %
                                videoFile)

                        itemNum = itemNum + 1
            else:
                log("Schedule: Unknown schedule file format")

            del scheduleXml
        except:
            log(
                "Schedule: Failed to process schedule file: %s" %
                scheduleFileName, xbmc.LOGERROR)
            log("Schedule: %s" % traceback.format_exc(), xbmc.LOGERROR)
コード例 #36
0
    def getThemes(self):
        themePath = ""
        # Only need the theme path for videos
        if not WindowShowing.isMusicSection():
            # Check if the files are stored in a custom path
            if Settings.isCustomPathEnabled():
                if not WindowShowing.isMovies():
                    videotitle = xbmc.getInfoLabel("ListItem.TVShowTitle")
                else:
                    videotitle = xbmc.getInfoLabel("ListItem.Title")
                videotitle = normalize_string(videotitle)
                themePath = os_path_join(Settings.getCustomPath(), videotitle)

            # Looking at the TV Show information page
            elif WindowShowing.isMovieInformation() and (
                    WindowShowing.isTvShowTitles()
                    or WindowShowing.isTvShows()):
                themePath = xbmc.getInfoLabel("ListItem.FilenameAndPath")
            else:
                themePath = xbmc.getInfoLabel("ListItem.Path")

        # To try and reduce the amount of "noise" in the logging, where the
        # same check is logged again and again, we record if it has been
        # logged for this video, and then do not do it again until the
        # video changes and what we would print wound be different
        debug_logging_enabled = False

        # Only log if something is different from the last time we logged
        if self.lastLoggedThemePath != themePath:
            debug_logging_enabled = True
            self.lastLoggedThemePath = themePath

        log("TunesBackend: themePath = %s" % themePath, debug_logging_enabled)

        # Check if the selection is a Movie Set
        if WindowShowing.isMovieSet():
            movieSetMap = self._getMovieSetFileList()

            if Settings.isCustomPathEnabled():
                # Need to make the values part (the path) point to the custom path
                # rather than the video file
                for aKey in movieSetMap.keys():
                    videotitle = normalize_string(aKey)
                    movieSetMap[aKey] = os_path_join(Settings.getCustomPath(),
                                                     videotitle)

            if len(movieSetMap) < 1:
                themefile = ThemeFiles(
                    "", debug_logging_enabled=debug_logging_enabled)
            else:
                themefile = ThemeFiles(
                    themePath,
                    movieSetMap.values(),
                    debug_logging_enabled=debug_logging_enabled)

        # When the reference is into the database and not the file system
        # then don't return it
        elif themePath.startswith("videodb:"):
            # If in either the Tv Show List or the Movie list then
            # need to stop the theme is selecting the back button
            if WindowShowing.isMovies() or WindowShowing.isTvShowTitles():
                themefile = ThemeFiles(
                    "", debug_logging_enabled=debug_logging_enabled)
            else:
                # Load the previous theme
                themefile = self.newThemeFiles
        else:
            if WindowShowing.isMusicSection():
                themefile = MusicThemeFiles(debug_logging_enabled)
            else:
                themefile = ThemeFiles(
                    themePath, debug_logging_enabled=debug_logging_enabled)

                # Check if no themes were found for this item, there is a case if it is a
                # TV Show and it is nested Show-Name/Series-X/Episode-Directory/Episode.ext
                # Then this will not pick up themes in the root of the TV Show directory
                if (not themefile.hasThemes()) and (
                        not Settings.isCustomPathEnabled()
                ) and WindowShowing.isEpisodes():
                    tvshowTitle = xbmc.getInfoLabel("ListItem.TVShowTitle")
                    if tvshowTitle not in [None, ""]:
                        try:
                            # Make a call to the database to find out the root path of this TV Show
                            filterStr = '{"operator": "is", "field": "title", "value": "%s"}' % tvshowTitle
                            cmd = '{"jsonrpc": "2.0", "method": "VideoLibrary.GetTVShows", "params": {"properties": ["file"], "filter": %s},"id": 1 }' % filterStr
                            json_query = executeJSONRPC(cmd)
                            json_query = simplejson.loads(json_query)
                            if ("result" in json_query) and (
                                    'tvshows' in json_query['result']):
                                # Get the path to the TV Show and compare it to where we were previously
                                # looking
                                tvshowList = json_query['result']['tvshows']
                                if len(tvshowList) == 1:
                                    tvshowPath = json_query['result'][
                                        'tvshows'][0]['file']
                                    # Make sure we have not already checked this path
                                    # We will already have checked the parent path as well
                                    if (tvshowPath != themePath) and (
                                            tvshowPath !=
                                            os_path_split(themePath)[0]):
                                        # So we know that we haven't checked the root of this TV Show yet
                                        log(
                                            "TunesBackend: Checking root TV Show Path = %s"
                                            % tvshowPath,
                                            debug_logging_enabled)
                                        themefile = ThemeFiles(
                                            tvshowPath,
                                            debug_logging_enabled=
                                            debug_logging_enabled)
                        except:
                            log(
                                "TunesBackend: Failed to check root TV Show %s"
                                % traceback.format_exc(),
                                debug_logging_enabled)

        return themefile
コード例 #37
0
class MediathekView(KodiPlugin):
    def __init__(self):
        super(MediathekView, self).__init__()
        self.settings = Settings()
        self.notifier = Notifier()
        self.database = Store(self.getNewLogger('Store'), self.notifier,
                              self.settings)

    def show_main_menu(self):
        # Search
        self.addFolderItem(30901, {'mode': "search", 'extendedsearch': False})
        # Search all
        self.addFolderItem(30902, {'mode': "search", 'extendedsearch': True})
        # Browse livestreams
        self.addFolderItem(30903, {'mode': "livestreams"})
        # Browse recently added
        self.addFolderItem(30904, {'mode': "recent", 'channel': 0})
        # Browse recently added by channel
        self.addFolderItem(30905, {'mode': "recentchannels"})
        # Browse by Initial->Show
        self.addFolderItem(30906, {'mode': "initial", 'channel': 0})
        # Browse by Channel->Initial->Shows
        self.addFolderItem(30907, {'mode': "channels"})
        # Database Information
        self.addActionItem(30908, {'mode': "action-dbinfo"})
        # Manual database update
        if self.settings.updmode == 1 or self.settings.updmode == 2:
            self.addActionItem(30909, {'mode': "action-dbupdate"})
        self.endOfDirectory()
        self._check_outdate()

    def show_searches(self, extendedsearch=False):
        self.addFolderItem(30931, {
            'mode': "newsearch",
            'extendedsearch': extendedsearch
        })
        RecentSearches(self, extendedsearch).load().populate()
        self.endOfDirectory()

    def new_search(self, extendedsearch=False):
        settingid = 'lastsearch2' if extendedsearch is True else 'lastsearch1'
        headingid = 30902 if extendedsearch is True else 30901
        # are we returning from playback ?
        search = self.addon.getSetting(settingid)
        if search:
            # restore previous search
            self.database.Search(search, FilmUI(self), extendedsearch)
        else:
            # enter search term
            (search, confirmed) = self.notifier.GetEnteredText('', headingid)
            if len(search) > 2 and confirmed is True:
                RecentSearches(self, extendedsearch).load().add(search).save()
                if self.database.Search(search, FilmUI(self),
                                        extendedsearch) > 0:
                    self.addon.setSetting(settingid, search)
            else:
                # pylint: disable=line-too-long
                self.info(
                    'The following ERROR can be ignored. It is caused by the architecture of the Kodi Plugin Engine'
                )
                self.endOfDirectory(False, cacheToDisc=True)
                # self.show_searches( extendedsearch )

    def show_db_info(self):
        info = self.database.GetStatus()
        heading = self.language(30907)
        infostr = self.language({
            'NONE': 30941,
            'UNINIT': 30942,
            'IDLE': 30943,
            'UPDATING': 30944,
            'ABORTED': 30945
        }.get(info['status'], 30941))
        infostr = self.language(30965) % infostr
        totinfo = self.language(30971) % (info['tot_chn'], info['tot_shw'],
                                          info['tot_mov'])
        updatetype = self.language(30972 if info['fullupdate'] > 0 else 30973)
        if info['status'] == 'UPDATING' and info['filmupdate'] > 0:
            updinfo = self.language(30967) % (
                updatetype, datetime.datetime.fromtimestamp(
                    info['filmupdate']).strftime('%Y-%m-%d %H:%M:%S'),
                info['add_chn'], info['add_shw'], info['add_mov'])
        elif info['status'] == 'UPDATING':
            updinfo = self.language(30968) % (updatetype, info['add_chn'],
                                              info['add_shw'], info['add_mov'])
        elif info['lastupdate'] > 0 and info['filmupdate'] > 0:
            updinfo = self.language(30969) % (
                updatetype, datetime.datetime.fromtimestamp(
                    info['lastupdate']).strftime('%Y-%m-%d %H:%M:%S'),
                datetime.datetime.fromtimestamp(
                    info['filmupdate']).strftime('%Y-%m-%d %H:%M:%S'),
                info['add_chn'], info['add_shw'], info['add_mov'],
                info['del_chn'], info['del_shw'], info['del_mov'])
        elif info['lastupdate'] > 0:
            updinfo = self.language(30970) % (
                updatetype, datetime.datetime.fromtimestamp(
                    info['lastupdate']).strftime('%Y-%m-%d %H:%M:%S'),
                info['add_chn'], info['add_shw'], info['add_mov'],
                info['del_chn'], info['del_shw'], info['del_mov'])
        else:
            updinfo = self.language(30966)

        xbmcgui.Dialog().textviewer(
            heading, infostr + '\n\n' + totinfo + '\n\n' + updinfo)

    def _check_outdate(self, maxage=172800):
        if self.settings.updmode != 1 and self.settings.updmode != 2:
            # no check with update disabled or update automatic
            return
        if self.database is None:
            # should never happen
            self.notifier.ShowOutdatedUnknown()
            return
        status = self.database.GetStatus()
        if status['status'] == 'NONE' or status['status'] == 'UNINIT':
            # should never happen
            self.notifier.ShowOutdatedUnknown()
            return
        elif status['status'] == 'UPDATING':
            # great... we are updating. nuthin to show
            return
        # lets check how old we are
        tsnow = int(time.time())
        tsold = int(status['lastupdate'])
        if tsnow - tsold > maxage:
            self.notifier.ShowOutdatedKnown(status)

    def init(self):
        if self.database.Init():
            if self.settings.HandleFirstRun():
                pass
            self.settings.HandleUpdateOnStart()

    def run(self):
        # save last activity timestamp
        self.settings.ResetUserActivity()
        # process operation
        mode = self.get_arg('mode', None)
        if mode is None:
            self.show_main_menu()
        elif mode == 'search':
            extendedsearch = self.get_arg('extendedsearch', 'False') == 'True'
            self.show_searches(extendedsearch)
        elif mode == 'newsearch':
            self.new_search(self.get_arg('extendedsearch', 'False') == 'True')
        elif mode == 'research':
            search = self.get_arg('search', '')
            extendedsearch = self.get_arg('extendedsearch', 'False') == 'True'
            self.database.Search(search, FilmUI(self), extendedsearch)
            RecentSearches(self, extendedsearch).load().add(search).save()
        elif mode == 'delsearch':
            search = self.get_arg('search', '')
            extendedsearch = self.get_arg('extendedsearch', 'False') == 'True'
            RecentSearches(
                self, extendedsearch).load().delete(search).save().populate()
            self.runBuiltin('Container.Refresh')
        elif mode == 'livestreams':
            self.database.GetLiveStreams(
                FilmUI(self, [xbmcplugin.SORT_METHOD_LABEL]))
        elif mode == 'recent':
            channel = self.get_arg('channel', 0)
            self.database.GetRecents(channel, FilmUI(self))
        elif mode == 'recentchannels':
            self.database.GetRecentChannels(ChannelUI(self, nextdir='recent'))
        elif mode == 'channels':
            self.database.GetChannels(ChannelUI(self, nextdir='shows'))
        elif mode == 'action-dbinfo':
            self.show_db_info()
        elif mode == 'action-dbupdate':
            self.settings.TriggerUpdate()
            self.notifier.ShowNotification(30963, 30964, time=10000)
        elif mode == 'initial':
            channel = self.get_arg('channel', 0)
            self.database.GetInitials(channel, InitialUI(self))
        elif mode == 'shows':
            channel = self.get_arg('channel', 0)
            initial = self.get_arg('initial', None)
            self.database.GetShows(channel, initial, ShowUI(self))
        elif mode == 'films':
            show = self.get_arg('show', 0)
            self.database.GetFilms(show, FilmUI(self))
        elif mode == 'downloadmv':
            filmid = self.get_arg('id', 0)
            quality = self.get_arg('quality', 1)
            Downloader(self).download_movie(filmid, quality)
        elif mode == 'downloadep':
            filmid = self.get_arg('id', 0)
            quality = self.get_arg('quality', 1)
            Downloader(self).download_episode(filmid, quality)
        elif mode == 'playwithsrt':
            filmid = self.get_arg('id', 0)
            only_sru = self.get_arg('only_set_resolved_url', 'False') == 'True'
            Downloader(self).play_movie_with_subs(filmid, only_sru)

        # cleanup saved searches
        if mode is None or mode != 'search':
            self.addon.setSetting('lastsearch1', '')
        if mode is None or mode != 'searchall':
            self.addon.setSetting('lastsearch2', '')

    def exit(self):
        self.database.Exit()
コード例 #38
0
 def __init__(self):
     super(MediathekView, self).__init__()
     self.settings = Settings()
     self.notifier = Notifier()
     self.database = Store(self.getNewLogger('Store'), self.notifier,
                           self.settings)
コード例 #39
0
# Class to detect when something in the system has changed
class TvTunesMonitor(xbmc.Monitor):
    def onSettingsChanged(self):
        log("TvTunesMonitor: Notification of settings change received")
        Settings.reloadSettings()


##################################
# Main of the TvTunes Service
##################################
if __name__ == '__main__':
    log("Starting TvTunes Service %s" % ADDON.getAddonInfo('version'))

    # Check if the settings mean we want to reset the volume on startup
    startupVol = Settings.getStartupVolume()

    if startupVol < 0:
        log("TvTunesService: No Volume Change Required")
    else:
        log("TvTunesService: Setting volume to %s" % startupVol)
        executebuiltin('SetVolume(%d)' % startupVol, True)

    # Make sure the user wants to play themes
    if Settings.isThemePlayingEnabled():
        log("TvTunesService: Theme playing enabled")

        # Create a monitor so we can reload the settings if they change
        systemMonitor = TvTunesMonitor()

        # Start looping to perform the TvTune theme operations
コード例 #40
0
class MediathekViewPlugin(KodiPlugin):
    """ The main plugin class """
    def __init__(self):
        super(MediathekViewPlugin, self).__init__()
        self.settings = Settings()
        self.notifier = Notifier()
        self.database = Store(self.get_new_logger('Store'), self.notifier,
                              self.settings)
        self.unicodePath = unicode(self.path, 'utf-8')

    def show_main_menu(self):
        """ Creates the main menu of the plugin """
        # Search
        self.add_folder_item(30901, {
            'mode': "search",
            'extendedsearch': False
        },
                             icon=os.path.join(self.unicodePath, 'resources',
                                               'icons', 'search-m.png'))
        # Search all
        self.add_folder_item(30902, {
            'mode': "search",
            'extendedsearch': True
        },
                             icon=os.path.join(self.unicodePath, 'resources',
                                               'icons', 'search-m.png'))
        # Browse livestreams
        self.add_folder_item(30903, {'mode': "livestreams"},
                             icon=os.path.join(self.unicodePath, 'resources',
                                               'icons', 'live2-m.png'))
        # Browse recently added
        self.add_folder_item(30904, {
            'mode': "recent",
            'channel': 0
        },
                             icon=os.path.join(self.unicodePath, 'resources',
                                               'icons', 'new-m.png'))
        # Browse recently added by channel
        self.add_folder_item(30905, {'mode': "recentchannels"},
                             icon=os.path.join(self.unicodePath, 'resources',
                                               'icons', 'new-m.png'))
        # Browse by Initial->Show
        self.add_folder_item(30906, {
            'mode': "initial",
            'channel': 0
        },
                             icon=os.path.join(self.unicodePath, 'resources',
                                               'icons', 'movie-m.png'))
        # Browse by Channel->Initial->Shows
        self.add_folder_item(30907, {'mode': "channels"},
                             icon=os.path.join(self.unicodePath, 'resources',
                                               'icons', 'movie-m.png'))
        # Database Information
        self.add_action_item(30908, {'mode': "action-dbinfo"},
                             icon=os.path.join(self.unicodePath, 'resources',
                                               'icons', 'dbinfo-m.png'))
        # Manual database update
        if self.settings.updmode == 1 or self.settings.updmode == 2:
            self.add_action_item(30909, {'mode': "action-dbupdate"})
        self.end_of_directory()
        self._check_outdate()

    def show_searches(self, extendedsearch=False):
        """
        Fill the search screen with "New Search..." and the
        list of recent searches

        Args:
            extendedsearch(bool, optionsl): If `True`, the searches
                are performed both in show title and description.
                Default is `False`
        """
        self.add_folder_item(30931, {
            'mode': "newsearch",
            'extendedsearch': extendedsearch
        },
                             icon=os.path.join(self.unicodePath, 'resources',
                                               'icons', 'search-m.png'))
        RecentSearches(self, extendedsearch).load().populate()
        self.end_of_directory()

    def new_search(self, extendedsearch=False):
        """
        Asks the user to enter his search terms and then
        performs the search and displays the results.

        Args:
            extendedsearch(bool, optionsl): If `True`, the searches
                are performed both in show title and description.
                Default is `False`
        """
        settingid = 'lastsearch2' if extendedsearch is True else 'lastsearch1'
        headingid = 30902 if extendedsearch is True else 30901
        # are we returning from playback ?
        search = self.get_setting(settingid)
        if search:
            # restore previous search
            self.database.search(search, FilmUI(self), extendedsearch)
        else:
            # enter search term
            (search, confirmed) = self.notifier.get_entered_text('', headingid)
            if len(search) > 2 and confirmed is True:
                RecentSearches(self, extendedsearch).load().add(search).save()
                if self.database.search(search, FilmUI(self),
                                        extendedsearch) > 0:
                    self.set_setting(settingid, search)
            else:
                # pylint: disable=line-too-long
                self.info(
                    'The following ERROR can be ignored. It is caused by the architecture of the Kodi Plugin Engine'
                )
                self.end_of_directory(False, cache_to_disc=True)

    def show_db_info(self):
        """ Displays current information about the database """
        info = self.database.get_status()
        heading = self.language(30907)
        infostr = self.language({
            'NONE': 30941,
            'UNINIT': 30942,
            'IDLE': 30943,
            'UPDATING': 30944,
            'ABORTED': 30945
        }.get(info['status'], 30941))
        infostr = self.language(30965) % infostr
        totinfo = self.language(30971) % (info['tot_chn'], info['tot_shw'],
                                          info['tot_mov'])
        updatetype = self.language(30972 if info['fullupdate'] > 0 else 30973)
        if info['status'] == 'UPDATING' and info['filmupdate'] > 0:
            updinfo = self.language(30967) % (
                updatetype, datetime.datetime.fromtimestamp(
                    info['filmupdate']).strftime('%Y-%m-%d %H:%M:%S'),
                info['add_chn'], info['add_shw'], info['add_mov'])
        elif info['status'] == 'UPDATING':
            updinfo = self.language(30968) % (updatetype, info['add_chn'],
                                              info['add_shw'], info['add_mov'])
        elif info['lastupdate'] > 0 and info['filmupdate'] > 0:
            updinfo = self.language(30969) % (
                updatetype, datetime.datetime.fromtimestamp(
                    info['lastupdate']).strftime('%Y-%m-%d %H:%M:%S'),
                datetime.datetime.fromtimestamp(
                    info['filmupdate']).strftime('%Y-%m-%d %H:%M:%S'),
                info['add_chn'], info['add_shw'], info['add_mov'],
                info['del_chn'], info['del_shw'], info['del_mov'])
        elif info['lastupdate'] > 0:
            updinfo = self.language(30970) % (
                updatetype, datetime.datetime.fromtimestamp(
                    info['lastupdate']).strftime('%Y-%m-%d %H:%M:%S'),
                info['add_chn'], info['add_shw'], info['add_mov'],
                info['del_chn'], info['del_shw'], info['del_mov'])
        else:
            updinfo = self.language(30966)

        xbmcgui.Dialog().textviewer(
            heading, infostr + '\n\n' + totinfo + '\n\n' + updinfo)

    def _check_outdate(self, maxage=172800):
        if self.settings.updmode != 1 and self.settings.updmode != 2:
            # no check with update disabled or update automatic
            return
        if self.database is None:
            # should never happen
            self.notifier.show_outdated_unknown()
            return
        status = self.database.get_status()
        if status['status'] == 'NONE' or status['status'] == 'UNINIT':
            # should never happen
            self.notifier.show_outdated_unknown()
            return
        elif status['status'] == 'UPDATING':
            # great... we are updating. nuthin to show
            return
        # lets check how old we are
        tsnow = int(time.time())
        tsold = int(status['lastupdate'])
        if tsnow - tsold > maxage:
            self.notifier.show_outdated_known(status)

    def init(self):
        """ Initialisation of the plugin """
        if self.database.init():
            if self.settings.handle_first_run():
                pass
            self.settings.handle_update_on_start()

    def run(self):
        """ Execution of the plugin """
        # save last activity timestamp
        self.settings.reset_user_activity()
        # process operation
        self.info("Plugin invoked with parameters {}", self.args)
        mode = self.get_arg('mode', None)
        if mode is None:
            self.show_main_menu()
        elif mode == 'search':
            extendedsearch = self.get_arg('extendedsearch', 'False') == 'True'
            self.show_searches(extendedsearch)
        elif mode == 'newsearch':
            self.new_search(self.get_arg('extendedsearch', 'False') == 'True')
        elif mode == 'research':
            search = self.get_arg('search', '')
            extendedsearch = self.get_arg('extendedsearch', 'False') == 'True'
            self.database.search(search, FilmUI(self), extendedsearch)
            RecentSearches(self, extendedsearch).load().add(search).save()
        elif mode == 'delsearch':
            search = self.get_arg('search', '')
            extendedsearch = self.get_arg('extendedsearch', 'False') == 'True'
            RecentSearches(
                self, extendedsearch).load().delete(search).save().populate()
            self.run_builtin('Container.Refresh')
        elif mode == 'livestreams':
            self.database.get_live_streams(
                FilmUI(self, [xbmcplugin.SORT_METHOD_LABEL]))
        elif mode == 'recent':
            channel = self.get_arg('channel', 0)
            self.database.get_recents(channel, FilmUI(self))
        elif mode == 'recentchannels':
            self.database.get_recent_channels(ChannelUI(self,
                                                        nextdir='recent'))
        elif mode == 'channels':
            self.database.get_channels(ChannelUI(self, nextdir='shows'))
        elif mode == 'action-dbinfo':
            self.show_db_info()
        elif mode == 'action-dbupdate':
            self.settings.trigger_update()
            self.notifier.show_notification(30963, 30964, time=10000)
        elif mode == 'initial':
            channel = self.get_arg('channel', 0)
            self.database.get_initials(channel, InitialUI(self))
        elif mode == 'shows':
            channel = self.get_arg('channel', 0)
            initial = self.get_arg('initial', None)
            self.database.get_shows(channel, initial, ShowUI(self))
        elif mode == 'films':
            show = self.get_arg('show', 0)
            self.database.get_films(show, FilmUI(self))
        elif mode == 'downloadmv':
            filmid = self.get_arg('id', 0)
            quality = self.get_arg('quality', 1)
            Downloader(self).download_movie(filmid, quality)
        elif mode == 'downloadep':
            filmid = self.get_arg('id', 0)
            quality = self.get_arg('quality', 1)
            Downloader(self).download_episode(filmid, quality)
        elif mode == 'playwithsrt':
            filmid = self.get_arg('id', 0)
            Downloader(self).play_movie_with_subs(filmid)

        # cleanup saved searches
        if mode is None or mode != 'newsearch':
            self.set_setting('lastsearch1', '')
            self.set_setting('lastsearch2', '')

    def exit(self):
        """ Shutdown of the application """
        self.database.exit()
コード例 #41
0
    def play(self, item=None, listitem=None, windowed=True, fastFade=False):
        self.tvtunesPlayerStarted = True

        # if something is already playing, then we do not want
        # to replace it with the theme
        if not self.isPlaying():
            self.updateVideoRefreshRate(item)
            # Save the volume from before any alterations
            self.original_volume = self._getVolume()
            # Perform and lowering of the sound for theme playing
            self._lowerVolume()

            if Settings.isFadeIn():
                # Get the current volume - this is our target volume
                targetVol = self._getVolume()
                cur_vol_perc = 1

                # Calculate how fast to fade the theme, this determines
                # the number of step to drop the volume in
                numSteps = 10
                if fastFade:
                    numSteps = numSteps / 2

                vol_step = targetVol / numSteps
                # Reduce the volume before starting
                # do not mute completely else the mute icon shows up
                self._setVolume(1)
                # Now start playing before we start increasing the volume
                xbmc.Player.play(self,
                                 item=item,
                                 listitem=listitem,
                                 windowed=windowed)

                # Wait until playing has started
                maxLoop = 100
                while (not self.isPlaying()) and (
                        not xbmc.abortRequested) and (maxLoop > 0):
                    maxLoop = maxLoop - 1
                    xbmc.sleep(30)

                for step in range(0, (numSteps - 1)):
                    # If the system is going to be shut down then we need to reset
                    # everything as quickly as possible
                    if WindowShowing.isShutdownMenu() or xbmc.abortRequested:
                        log("ThemePlayer: Shutdown menu detected, cancelling fade in"
                            )
                        break
                    vol = cur_vol_perc + vol_step
                    log("ThemePlayer: fadeIn_vol: %s" % str(vol))
                    self._setVolume(vol)
                    cur_vol_perc = vol
                    xbmc.sleep(200)
                # Make sure we end on the correct volume
                self._setVolume(targetVol)
            else:
                xbmc.Player.play(self,
                                 item=item,
                                 listitem=listitem,
                                 windowed=windowed)

            if Settings.isLoop():
                xbmc.executebuiltin("PlayerControl(RepeatAll)")
                # We no longer use the JSON method to repeat as it does not work with videos
                # executeJSONRPC('{ "jsonrpc": "2.0", "method": "Player.SetRepeat", "params": {"playerid": 0, "repeat": "all" }, "id": 1 }')

                # If we had a random start and we are looping then we need to make sure
                # when it comes to play the theme for a second time it starts at the beginning
                # and not from the same mid-point
                if Settings.isRandomStart():
                    item[0].setProperty('StartOffset', "0")
            else:
                xbmc.executebuiltin("PlayerControl(RepeatOff)")
                # We no longer use the JSON method to repeat as it does not work with videos
                # executeJSONRPC('{ "jsonrpc": "2.0", "method": "Player.SetRepeat", "params": {"playerid": 0, "repeat": "off" }, "id": 1 }')

            # Record the time that playing was started
            self.startTime = int(time.time())

            # Clear the current playlist, as we will re-populate it
            self.playListItems = []

            # Save off the number of items in the playlist
            if item is not None:
                self.playlistSize = item.size()
                log("ThemePlayer: Playlist size = %d" % self.playlistSize)

                # Store a list of all the tracks in the playlist
                try:
                    i = 0
                    while i < self.playlistSize:
                        self.playListItems.append(item[i].getfilename())
                        i = i + 1
                except:
                    log("ThemePlayer: Failed to save off playlist")

                # Check if we are limiting each track in the list
                if not Settings.isLoop():
                    # Already started playing the first, so the remaining number of
                    # tracks is one less than the total
                    self.remainingTracks = self.playlistSize - 1
                self._setNextSkipTrackTime(self.startTime)
            else:
                self.playlistSize = 1
コード例 #42
0
# Class to detect when something in the system has changed
class TvTunesMonitor(xbmc.Monitor):
    def onSettingsChanged(self):
        log("TvTunesMonitor: Notification of settings change received")
        Settings.reloadSettings()


##################################
# Main of the TvTunes Service
##################################
if __name__ == '__main__':
    log("Starting TvTunes Service %s" % ADDON.getAddonInfo('version'))

    # Make sure we have recorded this machines Id
    Settings.setTvTunesId()

    # Check if the settings mean we want to reset the volume on startup
    startupVol = Settings.getStartupVolume()

    if startupVol < 0:
        log("TvTunesService: No Volume Change Required")
    else:
        log("TvTunesService: Setting volume to %s" % startupVol)
        xbmc.executebuiltin('SetVolume(%d)' % startupVol, True)

    # Check if the video info button should be hidden, we do this here as this will be
    # called when the system is loaded, it can then be read by the skin
    # when it comes to draw the button
    WindowShowing.updateHideVideoInfoButton()
    WindowShowing.updateShowOnContextMenu()
コード例 #43
0
    def showAudiobooks(self, directory=None):
        # Get the setting for the audio book directory
        audioBookFolder = Settings.getAudioBookFolder()

        if audioBookFolder in [None, ""]:
            # Prompt the user to set the eBooks Folder
            audioBookFolder = xbmcgui.Dialog().browseSingle(
                0, ADDON.getLocalizedString(32005), 'files')

            # Check to make sure the directory is set now
            if audioBookFolder in [None, ""]:
                xbmcgui.Dialog().ok(ADDON.getLocalizedString(32001),
                                    ADDON.getLocalizedString(32006))
                return

            # Save the directory in settings for future use
            log("AudioBooksPlugin: Setting Audio Books folder to %s" %
                audioBookFolder)
            Settings.setAudioBookFolder(audioBookFolder)

        # We may be looking at a subdirectory
        if directory not in [None, ""]:
            audioBookFolder = directory

        dirs, files = xbmcvfs.listdir(audioBookFolder)
        files.sort()
        dirs.sort()

        bookDirs = []
        # For each directory list allow the user to navigate into it
        for adir in dirs:
            if adir.startswith('.'):
                continue

            fullDir = os_path_join(audioBookFolder, adir)

            # Check if this directory is a book directory
            if self._isAudioBookDir(fullDir):
                bookDirs.append(fullDir)
                continue

            log("AudioBooksPlugin: Adding directory %s" % adir)

            try:
                displayName = "[%s]" % adir.encode("utf-8")
            except:
                displayName = "[%s]" % adir
            try:
                fullDir = fullDir.encode("utf-8")
            except:
                pass

            plot = ""
            try:
                plot = "[B]%s[/B]" % adir.encode("utf-8")
            except:
                plot = adir

            # Check if there are any images for this directory
            iconImage = 'DefaultFolder.png'
            fanartImage = FANART
            subDirs, subFiles = xbmcvfs.listdir(fullDir)
            for fileInDir in subFiles:
                if fileInDir.lower() in ['fanart.jpg', 'fanart.png']:
                    fanartImage = os_path_join(fullDir, fileInDir)
                elif fileInDir.lower() in ['folder.jpg', 'folder.png']:
                    iconImage = os_path_join(fullDir, fileInDir)

            url = self._build_url({'mode': 'directory', 'directory': fullDir})
            li = xbmcgui.ListItem(displayName, iconImage=iconImage)
            li.setProperty("Fanart_Image", fanartImage)
            li.setInfo('video', {'Plot': plot})
            li.addContextMenuItems([], replaceItems=True)
            xbmcplugin.addDirectoryItem(handle=self.addon_handle,
                                        url=url,
                                        listitem=li,
                                        isFolder=True)

        m4bAudioBooks = []
        for m4bBookFile in files:
            # Check to ensure that this is an eBook
            if not m4bBookFile.lower().endswith('.m4b'):
                log("AudioBooksPlugin: Skipping non audiobook file: %s" %
                    m4bBookFile)
                continue

            fullpath = os_path_join(audioBookFolder, m4bBookFile)

            m4bAudioBooks.append(fullpath)

        # Get all the audiobook in a nicely sorted order
        allAudioBooks = sorted(bookDirs + m4bAudioBooks)

        audioBookHandlers = []
        # Now list all of the books
        for audioBookFile in allAudioBooks:
            log("AudioBooksPlugin: Adding audiobook %s" % audioBookFile)

            audioBookHandlers.append(
                AudioBookHandler.createHandler(audioBookFile))

        # Now sort the list by title
        audioBookHandlers.sort()

        # Now list all of the books
        for audioBookHandler in audioBookHandlers:
            log("AudioBooksPlugin: Processing audiobook %s" %
                audioBookHandler.getFile())

            title = audioBookHandler.getTitle()
            coverTargetName = audioBookHandler.getCoverImage(True)

            isRead = False
            if Settings.isMarkCompletedItems():
                if audioBookHandler.isCompleted():
                    isRead = True

            displayString = title
            try:
                displayString = title.encode("utf-8")
            except:
                displayString = title

            try:
                log("AudioBooksPlugin: Display title is %s for %s" %
                    (displayString, audioBookFile))
            except:
                # No need to have an error for logging
                pass

            plot = ""
            try:
                plot = "[B]%s[/B]" % displayString
            except:
                plot = displayString

            if isRead:
                displayString = '* %s' % displayString

            url = self._build_url({
                'mode': 'chapters',
                'filename': audioBookHandler.getFile(True),
                'cover': coverTargetName
            })
            li = xbmcgui.ListItem(displayString, iconImage=coverTargetName)
            li.setProperty("Fanart_Image", audioBookHandler.getFanArt())
            li.setInfo('video', {'Plot': plot})
            li.addContextMenuItems(self._getContextMenu(audioBookHandler),
                                   replaceItems=True)
            xbmcplugin.addDirectoryItem(handle=self.addon_handle,
                                        url=url,
                                        listitem=li,
                                        isFolder=True)

            del audioBookHandler

        xbmcplugin.endOfDirectory(self.addon_handle)
コード例 #44
0
ファイル: plugin.py プロジェクト: id192313/repository.xvbmc
    def showRootMenu(self):
        # Movies
        url = self._build_url({
            'mode': 'folder',
            'foldername': MenuNavigator.MOVIES
        })
        li = xbmcgui.ListItem(ADDON.getLocalizedString(32201), iconImage=ICON)
        li.setProperty("Fanart_Image", FANART)
        li.addContextMenuItems(self._getContextMenu(MenuNavigator.MOVIES),
                               replaceItems=True)
        xbmcplugin.addDirectoryItem(handle=self.addon_handle,
                                    url=url,
                                    listitem=li,
                                    isFolder=True)

        # TV Shows
        url = self._build_url({
            'mode': 'folder',
            'foldername': MenuNavigator.TVSHOWS
        })
        li = xbmcgui.ListItem(ADDON.getLocalizedString(32202), iconImage=ICON)
        li.setProperty("Fanart_Image", FANART)
        li.addContextMenuItems(self._getContextMenu(MenuNavigator.TVSHOWS),
                               replaceItems=True)
        xbmcplugin.addDirectoryItem(handle=self.addon_handle,
                                    url=url,
                                    listitem=li,
                                    isFolder=True)

        # Movie Sets
        url = self._build_url({
            'mode': 'folder',
            'foldername': MenuNavigator.MOVIESETS
        })
        li = xbmcgui.ListItem(ADDON.getLocalizedString(32203), iconImage=ICON)
        li.setProperty("Fanart_Image", FANART)
        li.addContextMenuItems(self._getContextMenu(MenuNavigator.MOVIESETS),
                               replaceItems=True)
        xbmcplugin.addDirectoryItem(handle=self.addon_handle,
                                    url=url,
                                    listitem=li,
                                    isFolder=True)

        # Music Videos
        url = self._build_url({
            'mode': 'folder',
            'foldername': MenuNavigator.MUSICVIDEOS
        })
        li = xbmcgui.ListItem(ADDON.getLocalizedString(32205), iconImage=ICON)
        li.setProperty("Fanart_Image", FANART)
        li.addContextMenuItems(self._getContextMenu(MenuNavigator.MUSICVIDEOS),
                               replaceItems=True)
        xbmcplugin.addDirectoryItem(handle=self.addon_handle,
                                    url=url,
                                    listitem=li,
                                    isFolder=True)

        # Plugins
        if Settings.isActivePlugins():
            url = self._build_url({
                'mode': 'folder',
                'foldername': MenuNavigator.PLUGINS
            })
            li = xbmcgui.ListItem(ADDON.getLocalizedString(32128),
                                  iconImage=ICON)
            li.setProperty("Fanart_Image", FANART)
            li.addContextMenuItems([], replaceItems=True)
            xbmcplugin.addDirectoryItem(handle=self.addon_handle,
                                        url=url,
                                        listitem=li,
                                        isFolder=True)

        # Files
        if Settings.isActiveFileSource():
            url = self._build_url({
                'mode': 'folder',
                'foldername': MenuNavigator.FILESOURCE
            })
            li = xbmcgui.ListItem(ADDON.getLocalizedString(32204),
                                  iconImage=ICON)
            li.setProperty("Fanart_Image", FANART)
            li.addContextMenuItems([], replaceItems=True)
            xbmcplugin.addDirectoryItem(handle=self.addon_handle,
                                        url=url,
                                        listitem=li,
                                        isFolder=True)

        # Classifications
        url = self._build_url({
            'mode': 'folder',
            'foldername': MenuNavigator.CLASSIFICATIONS
        })
        li = xbmcgui.ListItem(ADDON.getLocalizedString(32206), iconImage=ICON)
        li.setProperty("Fanart_Image", FANART)
        li.addContextMenuItems([], replaceItems=True)
        xbmcplugin.addDirectoryItem(handle=self.addon_handle,
                                    url=url,
                                    listitem=li,
                                    isFolder=True)

        # Add a blank line before the Operations
        li = xbmcgui.ListItem("", iconImage=ICON)
        li.setProperty("Fanart_Image", FANART)
        li.addContextMenuItems([], replaceItems=True)
        xbmcplugin.addDirectoryItem(handle=self.addon_handle,
                                    url="",
                                    listitem=li,
                                    isFolder=False)

        # Force Pin Entry
        url = self._build_url({'mode': 'forcepin', 'foldername': 'none'})
        menuItemName = ADDON.getLocalizedString(32213)
        try:
            menuItemName = "[%s]" % menuItemName
        except:
            pass
        li = xbmcgui.ListItem(menuItemName, iconImage=ICON)
        li.setProperty("Fanart_Image", FANART)
        li.addContextMenuItems([], replaceItems=True)
        xbmcplugin.addDirectoryItem(handle=self.addon_handle,
                                    url=url,
                                    listitem=li,
                                    isFolder=False)

        xbmcplugin.endOfDirectory(self.addon_handle)
コード例 #45
0
    def showExtras(self,
                   path,
                   target,
                   extrasParentTitle="",
                   extrasDefaultFanArt="",
                   extrasDefaultIconImage=""):
        # Check if the use database setting is enabled
        extrasDb = None
        if Settings.isDatabaseEnabled():
            extrasDb = ExtrasDB()

        # Create the extras class that will be used to process the extras
        videoExtras = VideoExtrasBase(path, target, extrasParentTitle)

        # Perform the search command
        files = videoExtras.findExtras(extrasDb=extrasDb,
                                       defaultFanArt=extrasDefaultFanArt)
        del videoExtras

        tvShowTitle = ""
        if target == MenuNavigator.TVSHOWS:
            tvShowTitle = extrasParentTitle

        if len(files) > 0:
            # Start by adding an option to Play All
            anItem = xbmcgui.ListItem(ADDON.getLocalizedString(32101),
                                      path=path)
            # Get the first items fanart for the play all option
            anItem.setProperty("Fanart_Image", files[0].getFanArt())

            if tvShowTitle != "":
                anItem.setInfo('video', {'TvShowTitle': tvShowTitle})

            if extrasParentTitle != "":
                anItem.setInfo('video', {'Title': extrasParentTitle})

            if extrasDefaultIconImage != "":
                anItem.setIconImage(extrasDefaultIconImage)

            anItem.addContextMenuItems([], replaceItems=True)
            url = self._build_url({
                'mode': 'playallextras',
                'foldername': target,
                'path': path,
                'parentTitle': extrasParentTitle
            })
            xbmcplugin.addDirectoryItem(handle=self.addon_handle,
                                        url=url,
                                        listitem=anItem,
                                        isFolder=False)

        # Check if we want to have YouTube Extra Support
        if Settings.isYouTubeSearchSupportEnabled():
            self._getVideoPluginLink(extrasParentTitle, 'plugin.video.youtube',
                                     32116, extrasDefaultIconImage,
                                     extrasDefaultFanArt)

        # Check if we want to have Vimeo Extra Support
        if Settings.isVimeoSearchSupportEnabled():
            self._getVideoPluginLink(extrasParentTitle, 'plugin.video.vimeo',
                                     32122, extrasDefaultIconImage,
                                     extrasDefaultFanArt)

        # Add each of the extras to the list to display
        for anExtra in files:
            # Create the list item
            li = anExtra.createListItem(
                parentTitle=extrasParentTitle,
                tvShowTitle=tvShowTitle,
                defaultIconImage=extrasDefaultIconImage)
            # Hack, if the "TotalTime" and "ResumeTime" are set on the list item
            # and it is partially watched, then Kodi will display the continue dialog
            # However we can not get what the user selects from this dialog, so it
            # will always continue.  Found out that we can hack this by clearing
            # the "TotalTime" property
            # http://forum.xbmc.org/showthread.php?tid=192627
            li.setProperty("TotalTime", "")

            li.addContextMenuItems([], replaceItems=True)
            li.addContextMenuItems(self._getContextMenu(
                anExtra, target, path, extrasParentTitle),
                                   replaceItems=True)
            url = self._build_url({
                'mode':
                'playextra',
                'foldername':
                target,
                'path':
                path,
                'filename':
                anExtra.getFilename().encode("utf-8"),
                'parentTitle':
                extrasParentTitle
            })
            xbmcplugin.addDirectoryItem(handle=self.addon_handle,
                                        url=url,
                                        listitem=li,
                                        isFolder=False)

        xbmcplugin.endOfDirectory(self.addon_handle)
コード例 #46
0
        if okToRunVideoScreensaver:
            try:
                # Stop TvTunes trying to start while we load the screensaver
                xbmcgui.Window(10025).setProperty("TvTunesBlocked", "true")

                # Give a little bit of time for everything to shake out before starting the screensaver
                # waiting another few seconds to start a screensaver is not going to make a difference
                # to the user
                xbmc.sleep(1000)

                # Check if media (Music or video) is playing already when the screensaver
                # starts, as the user may want to stop the screensaver running if they are
                # playing music
                if not (xbmc.Player().isPlaying()
                        and Settings.isBlockScreensaverIfMediaPlaying()):
                    # When we are called to start the screensaver we need to immediately stop
                    # the screensaver, this is because we want to play a video file, an action
                    # which in itself will cause the screensaver to stop
                    log("Waking screensaver with call to context menu")
                    xbmc.executeJSONRPC(
                        '{"jsonrpc": "2.0", "method": "Input.ContextMenu", "id": 1}'
                    )

                    # Limit the maximum amount of time to wait for the screensaver to end
                    maxWait = 30

                    while (not exitMon.isStopScreensaver()) and (maxWait > 0):
                        log("still running default screensaver, waiting for stop"
                            )
                        xbmc.sleep(100)
コード例 #47
0
ファイル: plugin.py プロジェクト: id192313/repository.xvbmc
    def _setList(self, target):
        items = []
        if target == MenuNavigator.PLUGINS:
            items = self._setPluginList()
        elif target == MenuNavigator.FILESOURCE:
            items = self._setFileSourceList()
        else:
            # Everything other plugins are forms of video
            items = self._getVideos(target)

        # Now add the security details to the list
        items = self._addSecurityFlags(target, items)
        # Update the classifications
        items = self._cleanClassification(target, items)

        for item in items:
            # Create the list-item for this video
            li = xbmcgui.ListItem(item['title'], iconImage=item['thumbnail'])

            # Remove the default context menu
            li.addContextMenuItems([], replaceItems=True)
            # Get the title of the video
            title = item['title']
            try:
                title = item['title'].encode("utf-8")
            except:
                pass

            # Make sure the dbid is coded correctly
            dbid = item['dbid']
            try:
                dbid = item['dbid'].encode("utf-8")
            except:
                pass

            # Check if the classification is restricting this item
            isBlockedByClassification = False
            if 'mpaa' in item:
                if item['mpaa'] not in [None, ""]:
                    isBlockedByClassification = True

            # Add a tick if security is set
            if item['securityLevel'] != 0:
                li.setInfo('video', {'PlayCount': 1})
                # Not the best display format - but the only way that I can get a number to display
                # In the list, the problem is it will display 01:00 - but at least it's something
                if Settings.showSecurityLevelInPlugin():
                    li.setInfo('video', {'Duration': item['securityLevel']})
            elif Settings.isHighlightClassificationUnprotectedVideos():
                # If the user wishes to see which files are not protected by one of the rules
                # currently applied, we put the play signal next to them
                if not isBlockedByClassification:
                    li.setProperty("TotalTime", "")
                    li.setProperty("ResumeTime", "1")

            # Handle the case where we want to turn off security for a video
            if isBlockedByClassification and (item['securityLevel'] == -1):
                # This is the case where the user has forced access to be allowed, this
                # is useful if you have classification enabled and you want to allow a
                # given video for a classification to be unprotected
                li.setProperty("TotalTime", "")
                li.setProperty("ResumeTime", "1")

            li.setProperty("Fanart_Image", item['fanart'])
            url = self._build_url({
                'mode':
                'setsecurity',
                'level':
                item['securityLevel'],
                'type':
                target,
                'title':
                title,
                'id':
                dbid,
                'classificationBlocked':
                str(isBlockedByClassification)
            })
            xbmcplugin.addDirectoryItem(handle=self.addon_handle,
                                        url=url,
                                        listitem=li,
                                        isFolder=False)

        xbmcplugin.endOfDirectory(self.addon_handle)
コード例 #48
0
    def onAction(self, action):
        # actioncodes from https://github.com/xbmc/xbmc/blob/master/xbmc/guilib/Key.h
        ACTION_PREVIOUS_MENU = 10
        ACTION_NAV_BACK = 92

        # For remote control
        ACTION_PAUSE = 12
        ACTION_STOP = 13
        ACTION_NEXT_ITEM = 14
        ACTION_PREV_ITEM = 15
        # The following 4 are active forward and back
        ACTION_FORWARD = 16
        ACTION_REWIND = 17
        ACTION_PLAYER_FORWARD = 77
        ACTION_PLAYER_REWIND = 78

        ACTION_PLAYER_PLAY = 79
        ACTION_VOLUME_UP = 88
        ACTION_VOLUME_DOWN = 89
        ACTION_MUTE = 91

        # Values Used in the custom keymap
        ACTION_FIRST_PAGE = 159  # Next Track
        ACTION_LAST_PAGE = 160  # Previous Track
        ACTION_PAGE_UP = 5  # Increase Volume
        ACTION_PAGE_DOWN = 6  # Decrease Volume
        ACTION_TOGGLE_WATCHED = 200  # Mute volume

        if (action == ACTION_PREVIOUS_MENU) or (action == ACTION_NAV_BACK):
            log("SonosControllerWindow: Close Action received: %s" %
                str(action.getId()))
            self.close()
        else:
            # Handle remote control commands
            if ((action == ACTION_PLAYER_PLAY) or (action == ACTION_PAUSE)):
                # Get the initial state of the device
                playStatus = self.sonosDevice.get_current_transport_info()

                # Play/pause is a toggle, so pause if playing
                if playStatus is not None:
                    if playStatus['current_transport_state'] == 'PLAYING':
                        self.onClick(SonosControllerWindow.BUTTON_PAUSE)
                    else:
                        self.onClick(SonosControllerWindow.BUTTON_PLAY)
            elif (action == ACTION_STOP):
                self.onClick(SonosControllerWindow.BUTTON_STOP)
            elif (action == ACTION_NEXT_ITEM) or (action == ACTION_FIRST_PAGE):
                self.onClick(SonosControllerWindow.BUTTON_NEXT)
            elif (action == ACTION_PREV_ITEM) or (action == ACTION_LAST_PAGE):
                self.onClick(SonosControllerWindow.BUTTON_PREVIOUS)
            elif (action == ACTION_MUTE) or (action == ACTION_TOGGLE_WATCHED):
                # Check if currently muted
                if self.sonosDevice.mute is False:
                    self.onClick(SonosControllerWindow.BUTTON_NOT_MUTED)
                else:
                    self.onClick(SonosControllerWindow.BUTTON_MUTED)
            elif (action == ACTION_VOLUME_UP) or (action == ACTION_PAGE_UP):
                # Get the current slider position
                volumeSlider = self.getControl(
                    SonosControllerWindow.SLIDER_VOLUME)
                currentSliderPosition = int(volumeSlider.getPercent())
                if currentSliderPosition < 100:
                    # Bump the volume by double the wait time (otherwise we can't skip forward accurately)
                    volumeSlider.setPercent(
                        currentSliderPosition +
                        Settings.getVolumeChangeIncrements())
                    self.onClick(SonosControllerWindow.SLIDER_VOLUME)
            elif (action == ACTION_VOLUME_DOWN) or (action
                                                    == ACTION_PAGE_DOWN):
                # Get the current slider position
                volumeSlider = self.getControl(
                    SonosControllerWindow.SLIDER_VOLUME)
                currentSliderPosition = int(volumeSlider.getPercent())
                if currentSliderPosition > 0:
                    # Bump the volume down by double the wait time (otherwise we can't skip forward accurately)
                    volumeSlider.setPercent(
                        currentSliderPosition -
                        Settings.getVolumeChangeIncrements())
                    self.onClick(SonosControllerWindow.SLIDER_VOLUME)
            elif ((action == ACTION_FORWARD)
                  or (action == ACTION_PLAYER_FORWARD)):
                # Get the current slider position
                seekSlider = self.getControl(SonosControllerWindow.SLIDER_SEEK)
                currentSliderPosition = int(seekSlider.getPercent())
                if currentSliderPosition < 99:
                    # Bump the slider by double the wait time (otherwise we can't skip forward accurately)
                    seekSlider.setPercent(currentSliderPosition + (
                        int(Settings.getAvoidDuplicateCommands()) * 2))
                    self.onClick(SonosControllerWindow.SLIDER_SEEK)
            elif ((action == ACTION_REWIND)
                  or (action == ACTION_PLAYER_REWIND)):
                # Get the current slider position
                seekSlider = self.getControl(SonosControllerWindow.SLIDER_SEEK)
                currentSliderPosition = int(seekSlider.getPercent())
                if currentSliderPosition > 0:
                    # Bump the slider down by double the wait time (otherwise we can't skip forward accurately)
                    seekSlider.setPercent(currentSliderPosition - (
                        int(Settings.getAvoidDuplicateCommands()) * 2))
                    self.onClick(SonosControllerWindow.SLIDER_SEEK)
コード例 #49
0
    def runAsAService(self):
        logVideoLibraryNotShowing = True

        while not xbmc.Monitor().abortRequested():
            # Wait a little before starting the check each time
            xbmc.sleep(200)

            # Check the forced TV Tunes status at the start of the loop, if this is True
            # then we don't want to stop themes until the next iteration, this stops the case
            # where some checks are done and the value changes part was through a single
            # loop iteration
            isForcedTvTunesContinue = WindowShowing.isTvTunesOverrideContinuePlaying(
            )

            # Stop the theme if the shutdown menu appears - it normally means
            # we are about to shut the system down, so get ahead of the game
            if WindowShowing.isShutdownMenu():
                self.stop(fastFade=True)
                continue

            # NOTE: The screensaver kicking in will only be picked up if the option
            # "Use Visualization if Playing Audio" is disabled
            if WindowShowing.isScreensaver():
                if self.isAlive:
                    log("TunesBackend: Screensaver active")
                    self.stop(fastFade=True)

                    # It may be possible that we stopped for the screen-saver about to kick in
                    # If we are using Gotham or higher, it is possible for us to re-kick off the
                    # screen-saver, otherwise the action of us stopping the theme will reset the
                    # timeout and the user will have to wait longer
                    log("TunesBackend: Restarting screensaver that TvTunes stopped"
                        )
                    executebuiltin("ActivateScreensaver", True)
                continue

            # Check if TvTunes is blocked from playing any themes
            if xbmcgui.Window(10025).getProperty('TvTunesBlocked') not in [
                    None, ""
            ]:
                self.stop(fastFade=True)
                continue

            if (not WindowShowing.isVideoLibrary()) and (
                    not WindowShowing.isMusicSection()):
                log("TunesBackend: Video Library no longer visible",
                    logVideoLibraryNotShowing)
                logVideoLibraryNotShowing = False
                # End playing cleanly (including any fade out) and then stop everything
                self.stop()
                continue
            else:
                logVideoLibraryNotShowing = True

            # There is a valid page selected and there is currently nothing playing
            if self.isPlayingZone(
            ) and not WindowShowing.isTvTunesOverrideContinuePrevious():
                newThemes = self.getThemes()
                if self.newThemeFiles != newThemes:
                    self.newThemeFiles = newThemes

            # Check if the file path has changed, if so there is a new file to play
            if self.newThemeFiles != self.oldThemeFiles and self.newThemeFiles.hasThemes(
            ):
                log("TunesBackend: old path: %s" %
                    self.oldThemeFiles.getPath())
                log("TunesBackend: new path: %s" %
                    self.newThemeFiles.getPath())
                if self.start_playing():
                    # Now that playing has started, update the current themes that are being used
                    self.oldThemeFiles = self.newThemeFiles

            # Check the operations where we are currently running and we need to stop
            # playing the current theme
            if self.isAlive:
                if self.themePlayer.isPlayingTheme():
                    # There is no theme at this location, so make sure we are stopped
                    if not self.newThemeFiles.hasThemes():
                        log("TunesBackend: No themes to play for current item")
                        self.themePlayer.endPlaying()
                        self.oldThemeFiles.clear()
                        self.prevThemeFiles.clear()
                        self.delayedStart.clear()
                        self.isAlive = False
                else:
                    # This will occur when a theme has stopped playing, maybe is is not set to loop
                    # There can be a delay when playing between playlist items, so give it a little
                    # time to start playing the next one
                    themeIsStillPlaying = False
                    maxLoop = 500
                    while (maxLoop > 0) and (not themeIsStillPlaying):
                        maxLoop = maxLoop - 1
                        xbmc.sleep(1)
                        if self.themePlayer.isPlayingTheme():
                            themeIsStillPlaying = True
                            break

                    if not themeIsStillPlaying:
                        log("TunesBackend: playing ended, restoring settings")
                        self.themePlayer.restoreSettings()
                        self.isAlive = False

            # This is the case where the user has moved from within an area where the themes
            # to an area where the theme is no longer played, so it will trigger a stop and
            # reset everything to highlight that nothing is playing
            if (not self.isPlayingZone()) and (not isForcedTvTunesContinue):
                self.stop()
            else:
                # Check for the case where we are playing the trailer as a theme
                # video, if so we want to stop the trailer playing when the video
                # information screen is displayed. If we don't, when the trailer is
                # started then TvTunes will automatically stop it
                if Settings.useTrailers() and WindowShowing.isMovieInformation(
                ) and self.themePlayer.isPlayingTrailerTheme():
                    self.stop()

            # Check to see if the setting to restrict the theme duration is enabled
            # and if it is we need to stop the current theme playing
            self.themePlayer.checkEnding()

        # We have finished running, just make one last check to ensure
        # we do not need to stop any audio
        self.stop(True)
        del self.themePlayer
コード例 #50
0
from resources.lib.lyrics import Lyrics

ADDON = xbmcaddon.Addon(id='script.sonos')
CWD = ADDON.getAddonInfo('path').decode("utf-8")
ICON = ADDON.getAddonInfo('icon')
RES_DIR = xbmc.translatePath(os.path.join(
    CWD, 'resources').encode("utf-8")).decode("utf-8")

log('script version %s started' % ADDON.getAddonInfo('version'))

# The base type of the window depends on if we are just having the basic controls
# (In which case it is a dialog, so you can see the rest of the screen)
# If we want to use ArtistSlideshow then it needs to be a Window, as it does
# not work with dialogs (And we want to full the whole screen anyway)
BaseWindow = xbmcgui.WindowXMLDialog
if Settings.displayArtistInfo():
    BaseWindow = xbmcgui.WindowXML


#####################################################
# Main window for the Sonos controller
#####################################################
class SonosControllerWindow(BaseWindow):  # xbmcgui.WindowXMLDialog
    ALBUM_ART = 801
    ARTIST_LABEL = 802
    TITLE_LABEL = 803
    ALBUM_LABEL = 804
    NEXT_LABEL = 805

    TRACK_POSITION_LABEL = 810
    DURATION_LABEL = 812
コード例 #51
0
    def getScheduleEntry(self):
        # Get the current time that we are checking the schedule for
        localTime = time.localtime()
        currentTime = (localTime.tm_hour * 60) + localTime.tm_min

        # Get the current day of the week
        # 0 = Monday 6 = Sunday
        today = localTime.tm_wday
        # Make sure that the day returned is within our expected list
        if today not in Settings.DAY_TYPE:
            log("Schedule: Unknown day today %d, setting to everyday" % today)
            today = Settings.EVERY_DAY

        # Check if we need to refresh the schedule details from the file
        # in case they have changed
        if Settings.getScheduleSetting() == Settings.SCHEDULE_FILE:
            # Check if the file has changed
            scheduleFileName = Settings.getScheduleFile()
            if scheduleFileName not in [None, ""]:
                if xbmcvfs.exists(scheduleFileName):
                    statFile = xbmcvfs.Stat(scheduleFileName)
                    modified = statFile.st_mtime()
                    if modified != self.lastScheduleModified:
                        log("Schedule: Schedule file has changed (%s)" %
                            str(modified))
                        # We use the offset to work out if the data has changed
                        if self.idOffset > 0:
                            self.idOffset = 0
                        else:
                            self.idOffset = 1000
                        # Clear the existing schedule items
                        self.scheduleDetails = []
                        # Load the new schedule items
                        self._loadFromFile()

        # Check the scheduled items to see if any cover the current time
        for item in self.scheduleDetails:
            if (item['start'] <= currentTime) and (item['end'] >= currentTime):
                # Make sure this is for the current day
                if (today == Settings.EVERY_DAY) or (item['day'] in [
                        Settings.EVERY_DAY, today
                ]):
                    return item['id']
            # Check for the case where the time laps over midnight
            if item['start'] > item['end']:
                if (currentTime >= item['start']) or (currentTime <=
                                                      item['end']):
                    # Check to see if we are restricting to day
                    if (today
                            == Settings.EVERY_DAY) or (item['day']
                                                       == Settings.EVERY_DAY):
                        return item['id']
                    else:
                        if (currentTime >= item['start']) and (item['day'] in [
                                Settings.EVERY_DAY, today
                        ]):
                            return item['id']
                        else:
                            # The day is set for the start of the time interval
                            # so if we go over to the next day we need to update
                            # what the expected day is
                            nextDay = Settings.getNextDay(item['day'])
                            if (currentTime <= item['end']) and (
                                    item['day']
                                    in [Settings.EVERY_DAY, nextDay]):
                                return item['id']
        return -1
コード例 #52
0
    # Remove the busy dialog
    xbmc.executebuiltin("Dialog.Close(busydialog)")

    # Check to see if there are any speakers
    if len(speakers) < 1:
        xbmcgui.Dialog().ok(ADDON.getLocalizedString(32001),
                            ADDON.getLocalizedString(32014))
    else:
        # Now prompt the user to pick one of the speakers
        select = xbmcgui.Dialog().select(ADDON.getLocalizedString(32001),
                                         speakers.keys())

        if select != -1:
            selectedDisplayName = speakers.keys()[select]
            log("SonosDiscovery: Entry chosen = %s" % selectedDisplayName)
            chosenIPAddress = speakers.get(selectedDisplayName)[0]
            chosenZoneName = speakers.get(selectedDisplayName)[1]
            chosenIsCoordinator = speakers.get(selectedDisplayName)[2]

            # Warn the user if they have selected something that is not the zone coordinator
            if not chosenIsCoordinator:
                xbmcgui.Dialog().ok(
                    ADDON.getLocalizedString(32001), "%s %s:" %
                    (chosenIPAddress, ADDON.getLocalizedString(32032)),
                    "          \"%s\"" % chosenZoneName,
                    ADDON.getLocalizedString(32033))
            # Set the selected item into the settings
            Settings.setIPAddress(chosenIPAddress)
            Settings.setZoneName(chosenZoneName)
コード例 #53
0
 def _setRepeat(self):
     # Set the video to loop, as we want it running as long as the screensaver
     repeatType = Settings.getFolderRepeatType()
     if repeatType is not None:
         log("Setting Repeat Type to %s" % repeatType)
         xbmc.executebuiltin("PlayerControl(%s)" % repeatType)
コード例 #54
0
# Import the common settings
from resources.lib.settings import log
from resources.lib.settings import Settings
from resources.lib.sync import LibrarySync
from resources.lib.summary import Summary

ADDON = xbmcaddon.Addon(id='script.theaudiodb.sync')

##################################
# Main of TheAudioDBSync Script
##################################
if __name__ == '__main__':
    log("TheAudioDBSync Service Starting %s" % ADDON.getAddonInfo('version'))

    # Get the username
    username = Settings.getUsername()

    # If the username is not set, then nothing to do yet
    if username not in [None, ""]:
        performResync = False

        if Settings.isUploadRatingsOnStartup():
            LibrarySync.checkForChangedTrackRatings(username, False)
            LibrarySync.checkForChangedAlbumRatings(username, False)

        # Only check for resync if it is enabled
        if Settings.isUpdateAlbumRatings() or Settings.isUpdateTrackRatings():
            nextResyncTime = Settings.getNextScheduledResyncTime()

            if nextResyncTime not in [None, "", "0"]:
                log("Service: Next Sync time is %d" % nextResyncTime)
コード例 #55
0
    def _getPlaylist(self):
        playlist = xbmc.PlayList(xbmc.PLAYLIST_VIDEO)
        # Note: The playlist clear option seems to impact all playlist settings,
        # so will remove the repeat settings on a playlist that is currently playing,
        # not just this instance - a bit nasty, but not much we can do about it
        playlist.clear()

        # Check to see if we should be using a video from the schedule
        scheduleEntry = self.scheduler.getScheduleEntry()

        if scheduleEntry != -1:
            # There is an item scheduled, so check to see if the item has actually changed
            if scheduleEntry == self.currentScheduleItem:
                return None
            # Set the entry we are about to play
            self.currentScheduleItem = scheduleEntry
            # Get the actual video file that should be played
            scheduledVideo = self.scheduler.getScheduleVideo(scheduleEntry)
            # Do a quick check to see if the video exists
            if xbmcvfs.exists(scheduledVideo):
                log("Screensaver video for scheduled item %d is: %s" %
                    (scheduleEntry, scheduledVideo))
                playlist.add(scheduledVideo)

        # Check if we are showing all the videos in a given folder
        elif Settings.isFolderSelection():
            videosFolder = Settings.getScreensaverFolder()

            # Check if we are dealing with a Folder of videos
            if videosFolder not in [None, ""]:
                if dir_exists(videosFolder):
                    self.currentScheduleItem = -1
                    files = self._getAllFilesInDirectory(videosFolder)

                    # Check if we are limiting to a single folder per session
                    if Settings.isLimitSessionToSingleCollection():
                        # Select just one file at random
                        singleVideo = random.choice(files)

                        # Check if this file is part of a collection
                        justFilename = (os_path_split(singleVideo))[-1]
                        collectionCtrl = CollectSets()
                        collectionVideos = collectionCtrl.getFilesInSameCollection(
                            justFilename)
                        del collectionCtrl

                        # If it is part of a collection, then limit to only files in
                        # this collection
                        if len(collectionVideos) > 0:
                            log("Screensaver restricting to collection containing %s"
                                % singleVideo)
                            # Check each of the videos to see which are in the collection
                            collectionFileList = []
                            for aFile in files:
                                # Get just the filename
                                aFilename = (os_path_split(aFile))[-1]
                                if aFilename in collectionVideos:
                                    log("Screensaver including collection video %s"
                                        % aFile)
                                    collectionFileList.append(aFile)
                                else:
                                    log("Screensaver excluding non collection video %s"
                                        % aFile)
                        else:
                            log("Screensaver restricting to directory containing %s"
                                % singleVideo)
                            # Not in a collection, so just gather the files in the same directory
                            # Get the directory that file was part of
                            parentPath = (os_path_split(singleVideo))[0]

                            # Now only select videos from that directory
                            files = self._getAllFilesInDirectory(
                                parentPath, False)

                    # Now shuffle the playlist to ensure that if there are more
                    # than one video a different one starts each time
                    random.shuffle(files)
                    for vidFile in files:
                        log("Screensaver video in directory is: %s" % vidFile)
                        playlist.add(vidFile)
        else:
            # Must be dealing with a single file
            videoFile = Settings.getScreensaverVideo()

            # Check to make sure the screensaver video file exists
            if videoFile not in [None, ""]:
                if xbmcvfs.exists(videoFile):
                    self.currentScheduleItem = -1
                    log("Screensaver video is: %s" % videoFile)
                    playlist.add(videoFile)

        # If there are no videos in the playlist yet, then display an error
        if playlist.size() < 1:
            errorLocation = Settings.getScreensaverVideo()
            if Settings.isFolderSelection():
                errorLocation = Settings.getScreensaverFolder()

            log("No Screensaver file set or not valid %s" % errorLocation)
            cmd = 'Notification("{0}", "{1}", 3000, "{2}")'.format(
                ADDON.getLocalizedString(32300).encode('utf-8'), errorLocation,
                ADDON.getAddonInfo('icon'))
            xbmc.executebuiltin(cmd)
            return None

        return playlist
コード例 #56
0
ファイル: plugin.py プロジェクト: id192313/repository.xvbmc
    def setSecurity(self,
                    type,
                    title,
                    id,
                    oldLevel,
                    classBlocked=False,
                    forceLevel=None):
        log("Setting security for (id:%s) %s" % (id, title))

        level = 1

        # Check if we need to prompt the user or the new security level has been supplied
        if forceLevel is None:
            # Set the new security level to be used
            if oldLevel > 0:
                # Default is to disable it if it was enabled
                level = 0

            numLevels = Settings.getNumberOfLevels()
            if numLevels > 1 or classBlocked:
                # Need to prompt the user to see which pin they are trying to set
                displayNameList = []
                # Add the option to turn it off
                displayNameList.append("%s %s" %
                                       (ADDON.getLocalizedString(32211),
                                        ADDON.getLocalizedString(32013)))
                for i in range(1, numLevels + 1):
                    secLevStr = str(i)
                    if numLevels < 2:
                        # If there is only one security level, use "On" rather than the number
                        secLevStr = ADDON.getLocalizedString(32014)
                    displayString = "%s %s" % (ADDON.getLocalizedString(32211),
                                               secLevStr)
                    displayNameList.append(displayString)

                # Check if we need the option to disable a classification restriction
                if classBlocked:
                    displayNameList.append(ADDON.getLocalizedString(32212))

                select = xbmcgui.Dialog().select(
                    ADDON.getLocalizedString(32001), displayNameList)

                if select != -1:
                    level = select
                    if classBlocked and (select >= (len(displayNameList) - 1)):
                        level = -1
                    log("Setting security level to %d" % level)
                else:
                    log("Exiting set security as no level selected")
                    return
        else:
            level = forceLevel

        # This could take a little time to set the value so show the busy dialog
        xbmc.executebuiltin("ActivateWindow(busydialog)")

        if title not in [None, ""]:
            pinDB = PinSentryDB()
            if type == MenuNavigator.TVSHOWS:
                # Set the security level for this title, setting it to zero
                # will result in the entry being removed from the database
                # as the default for an item is unset
                pinDB.setTvShowSecurityLevel(title, int(id), level)
            elif type == MenuNavigator.MOVIES:
                pinDB.setMovieSecurityLevel(title, int(id), level)
            elif type == MenuNavigator.MOVIESETS:
                pinDB.setMovieSetSecurityLevel(title, int(id), level)
                # As well as setting the security on the Movie set, we need
                # to also set it on each movie in the Movie Set
                self._setSecurityOnMoviesInMovieSets(int(id), level)
            elif type == MenuNavigator.MUSICVIDEOS:
                pinDB.setMusicVideoSecurityLevel(title, int(id), level)
            elif type == MenuNavigator.PLUGINS:
                pinDB.setPluginSecurityLevel(title, id, level)
            elif type == MenuNavigator.FILESOURCE:
                pinDB.setFileSourceSecurityLevel(title, id, level)
            elif type == MenuNavigator.CLASSIFICATIONS_MOVIES:
                pinDB.setMovieClassificationSecurityLevel(id, title, level)
            elif type == MenuNavigator.CLASSIFICATIONS_TV:
                pinDB.setTvClassificationSecurityLevel(id, title, level)
            del pinDB
        else:
            # Handle the bulk operations like set All security for the movies
            self._setBulkSecurity(type, level)

        xbmc.executebuiltin("Dialog.Close(busydialog)")
        xbmc.executebuiltin("Container.Refresh")
コード例 #57
0
    if displayNotice:
        json_query = xbmc.executeJSONRPC(
            '{"jsonrpc": "2.0", "method": "Addons.GetAddonDetails", "params": { "addonid": "repository.urepo", "properties": ["enabled", "broken", "name", "author"]  }, "id": 1}'
        )
        json_response = json.loads(json_query)

        if ("result" in json_response) and ('addon'
                                            in json_response['result']):
            addonItem = json_response['result']['addon']
            if (addonItem['enabled'] is
                    True) and (addonItem['broken'] is False) and (
                        addonItem['type'] == 'xbmc.addon.repository') and (
                            addonItem['addonid'] == 'repository.urepo'):
                displayNotice = False

    if displayNotice:
        xbmc.executebuiltin(
            'Notification("robwebset or URepo Repository Required","github.com/robwebset/repository.robwebset",10000,%s)'
            % ADDON.getAddonInfo('icon'))
    else:
        # Check if we should be running sync when the system starts
        if Settings.isRunOnStartup():
            addonSync = AddonSync()
            addonSync.startSync()
            del addonSync
        else:
            log("AddonSync: Not running at startup")

    log("AddonSync: Service Ended")
コード例 #58
0
 def __init__(self):
     self.proxy = ProxyTCPD()
     self.s = Settings()
     self.s.log('Proxy Bound to 127.0.0.1:{}'.format(self.proxy.port))
     self.proxy_thread = threading.Thread(target=self.proxy.serve_forever)
     self.s.setSetting('proxy', '127.0.0.1:{}'.format(self.proxy.port))
コード例 #59
0
    def setVideoList(self, jsonGet, target):
        videoItems = self.getVideos(jsonGet, target)

        for videoItem in videoItems:
            # Get the path where the theme should be stored
            path = self.getPathForVideoItem(videoItem)

            # Create the list-item for this video
            li = xbmcgui.ListItem(videoItem['title'],
                                  iconImage=videoItem['thumbnail'])
            # Remove the default context menu
            li.addContextMenuItems([], replaceItems=True)
            # Set the background image
            if videoItem['fanart'] is not None:
                li.setProperty("Fanart_Image", videoItem['fanart'])
            # If theme already exists flag it using the play count
            # This will normally put a tick on the GUI
            if self._doesThemeExist(path):
                # A theme already exists, see if we are showing only missing themes
                if self.missingThemesOnly == 1:
                    # skip this theme
                    continue

                li.setInfo('video', {'PlayCount': 1})
            # Check the parent directory
            elif Settings.isThemeDirEnabled() and self._doesThemeExist(
                    path, True):
                # The Theme directory is set, there is no theme in there
                # but we have a theme that will play, so flag it
                li.setProperty("ResumeTime", "50")

            if videoItem['originaltitle'] is not None:
                url = self._build_url({
                    'mode':
                    'findtheme',
                    'foldername':
                    target,
                    'path':
                    path.encode("utf-8"),
                    'title':
                    videoItem['title'].encode("utf-8"),
                    'isTvShow':
                    videoItem['isTvShow'],
                    'year':
                    videoItem['year'],
                    'imdb':
                    videoItem['imdb'],
                    'originaltitle':
                    videoItem['originaltitle'].encode("utf-8")
                })
            else:
                url = self._build_url({
                    'mode':
                    'findtheme',
                    'foldername':
                    target,
                    'path':
                    path.encode("utf-8"),
                    'title':
                    videoItem['title'].encode("utf-8"),
                    'isTvShow':
                    videoItem['isTvShow'],
                    'year':
                    videoItem['year'],
                    'imdb':
                    videoItem['imdb']
                })
            xbmcplugin.addDirectoryItem(handle=self.addon_handle,
                                        url=url,
                                        listitem=li,
                                        isFolder=False)

        xbmcplugin.endOfDirectory(self.addon_handle)
コード例 #60
0
    def _getContextMenu(self, bookHandle):
        ctxtMenu = []

        # Play from resume point
        secondsIn, chapterPosition = bookHandle.getPosition()
        if (secondsIn > 0) or (chapterPosition > 1):
            cmd = self._build_url({
                'mode': 'play',
                'filename': bookHandle.getFile(True),
                'startTime': secondsIn,
                'chapter': chapterPosition
            })
            displayTime = self._getDisplayTimeFromSeconds(secondsIn)
            displayName = "%s %s" % (ADDON.getLocalizedString(32019),
                                     displayTime)

            if chapterPosition > 1:
                displayName = "%s (%s: %d)" % (displayName,
                                               ADDON.getLocalizedString(32017),
                                               chapterPosition)

            ctxtMenu.append((displayName, 'RunPlugin(%s)' % cmd))

        # Play from start
        cmd = self._build_url({
            'mode': 'play',
            'filename': bookHandle.getFile(True),
            'startTime': 0,
            'chapter': 0
        })
        ctxtMenu.append(
            (ADDON.getLocalizedString(32018), 'RunPlugin(%s)' % cmd))

        # If this item is not already complete, allow it to be marked as complete
        if not bookHandle.isCompleted():
            # Mark as complete
            cmd = self._build_url({
                'mode': 'progress',
                'filename': bookHandle.getFile(True),
                'isComplete': 1,
                'startTime': 0
            })
            ctxtMenu.append(
                (ADDON.getLocalizedString(32010), 'RunPlugin(%s)' % cmd))

        # Clear History
        cmd = self._build_url({
            'mode': 'clear',
            'filename': bookHandle.getFile(True)
        })
        ctxtMenu.append(
            (ADDON.getLocalizedString(32011), 'RunPlugin(%s)' % cmd))

        # Add delete support if it is enabled
        if Settings.isDeleteSupported():
            cmd = self._build_url({
                'mode': 'delete',
                'filename': bookHandle.getFile(True)
            })
            ctxtMenu.append(
                (ADDON.getLocalizedString(32032), 'RunPlugin(%s)' % cmd))

        return ctxtMenu