Beispiel #1
0
    def GetDefaultCachePath(self):
        """ returns the default cache path for this channel"""

        # set the UZG path
        if AddonSettings.GetUzgCacheDuration() > 0:
            cachPath = AddonSettings.GetUzgCachePath()
            if cachPath:
                Logger.Trace("UZG Cache path resolved to: %s", cachPath)
                return cachPath

        cachePath = chn_class.Channel.GetDefaultCachePath(self)
        Logger.Trace("UZG Cache path resolved chn_class default: %s", cachePath)
        return cachePath
Beispiel #2
0
    def __init__(self, pluginName, params, handle=0):
        """Initialises the plugin with given arguments."""

        # some constants
        self.actionDownloadVideo = "downloadVideo".lower()              # : Action used to download a video item
        self.actionFavourites = "favourites".lower()                    # : Action used to show favorites for a channel
        self.actionAllFavourites = "allfavourites".lower()              # : Action used to show all favorites
        self.actionRemoveFavourite = "removefromfavourites".lower()     # : Action used to remove items from favorites
        self.actionAddFavourite = "addtofavourites".lower()             # : Action used to add items to favorites
        self.actionPlayVideo = "playvideo".lower()                      # : Action used to play a video item
        self.actionUpdateChannels = "updatechannels".lower()            # : Action used to update channels
        self.actionListFolder = "listfolder".lower()                    # : Action used to list a folder
        self.actionListCategory = "listcategory"                        # : Action used to show the channels from a category
        self.actionConfigureChannel = "configurechannel"                # : Action used to configure a channel

        self.keywordPickle = "pickle".lower()                           # : Keyword used for the pickle item
        self.keywordAction = "action".lower()                           # : Keyword used for the action item
        self.keywordChannel = "channel".lower()                         # : Keyword used for the channel
        self.keywordChannelCode = "channelcode".lower()                 # : Keyword used for the channelcode
        self.keywordCategory = "category"                               # : Keyword used for the category
        self.keywordRandomLive = "rnd"                                  # : Keyword used for randomizing live items

        self.pluginName = pluginName
        self.handle = int(handle)

        # channel objects
        self.channelObject = None
        self.channelFile = ""
        self.channelCode = None

        self.contentType = "episodes"
        self.methodContainer = dict()   # : storage for the inspect.getmembers(channel) method. Improves performance

        # determine the query parameters
        self.params = self.__GetParameters(params)

        Logger.Info("*********** Starting %s add-on version %s ***********", Config.appName, Config.version)
        Logger.Debug("Plugin Params: %s (%s) [handle=%s, name=%s, query=%s]", self.params, len(self.params),
                     self.handle, self.pluginName, params)

        # are we in session?
        sessionActive = SessionHelper.IsSessionActive(Logger.Instance())

        # fetch some environment settings
        envCtrl = envcontroller.EnvController(Logger.Instance())
        # self.FavouritesEnabled = envCtrl.SQLiteEnabled()
        self.FavouritesEnabled = not envCtrl.IsPlatform(Environments.Xbox)

        if not sessionActive:
            # do add-on start stuff
            Logger.Info("Add-On start detected. Performing startup actions.")

            # print the folder structure
            envCtrl.DirectoryPrinter(Config, AddonSettings)

            # show notification
            XbmcWrapper.ShowNotification(None, LanguageHelper.GetLocalizedString(LanguageHelper.StartingAddonId) % (
                Config.appName,), fallback=False, logger=Logger)

            # check for updates
            if envCtrl.IsPlatform(Environments.Xbox):
                Updater().AutoUpdate()

            # check if the repository is available
            envCtrl.IsInstallMethodValid(Config)

            # check for cache folder
            envCtrl.CacheCheck()

            # do some cache cleanup
            envCtrl.CacheCleanUp(Config.cacheDir, Config.cacheValidTime)
            envCtrl.CacheCleanUp(AddonSettings.GetUzgCachePath(), AddonSettings.GetUzgCacheDuration() * 24 * 3600,
                                 "xot.*")

        # create a session
        SessionHelper.CreateSession(Logger.Instance())

        #===============================================================================
        #        Start the plugin version of progwindow
        #===============================================================================
        if len(self.params) == 0:

            # Show initial start if not in a session
            # now show the list
            if AddonSettings.ShowCategories():
                self.ShowCategories()
            else:
                self.ShowChannelList()

        #===============================================================================
        #        Start the plugin verion of the episode window
        #===============================================================================
        else:
            try:
                # Determine what stage we are in. Check that there are more than 2 Parameters
                if len(self.params) > 1 and self.keywordChannel in self.params:
                    # retrieve channel characteristics
                    self.channelFile = os.path.splitext(self.params[self.keywordChannel])[0]
                    self.channelCode = self.params[self.keywordChannelCode]
                    Logger.Debug("Found Channel data in URL: channel='%s', code='%s'", self.channelFile,
                                 self.channelCode)

                    # import the channel
                    channelRegister = ChannelImporter.GetRegister()
                    channel = channelRegister.GetSingleChannel(self.channelFile, self.channelCode)

                    if channel is not None:
                        self.channelObject = channel
                    else:
                        Logger.Critical("None or more than one channels were found, unable to continue.")
                        return

                    # init the channel as plugin
                    self.channelObject.InitChannel()
                    Logger.Info("Loaded: %s", self.channelObject.channelName)

                elif self.keywordCategory in self.params:
                    # no channel needed.
                    pass

                elif self.keywordAction in self.params and (
                        self.params[self.keywordAction] == self.actionAllFavourites or
                        self.params[self.keywordAction] == self.actionRemoveFavourite):
                    # no channel needed for these favourites actions.
                    pass

                else:
                    Logger.Critical("Error determining Plugin action")
                    return

                #===============================================================================
                # See what needs to be done.
                #===============================================================================
                if self.keywordAction not in self.params:
                    Logger.Critical("Action parameters missing from request. Parameters=%s", self.params)
                    return

                if self.params[self.keywordAction] == self.actionListCategory:
                    self.ShowChannelList(self.params[self.keywordCategory])

                elif self.params[self.keywordAction] == self.actionConfigureChannel:
                    self.__ConfigureChannel(self.channelObject)

                elif self.params[self.keywordAction] == self.actionFavourites:
                    # we should show the favourites
                    self.ShowFavourites(self.channelObject)

                elif self.params[self.keywordAction] == self.actionAllFavourites:
                    if self.channelObject is not None:
                        Logger.Warning("We have a self.channelObject with self.actionAllFavourites")
                    self.ShowFavourites(None)

                elif self.params[self.keywordAction] == self.actionRemoveFavourite:
                    self.RemoveFavourite()

                elif self.params[self.keywordAction] == self.actionAddFavourite:
                    self.AddFavourite()

                elif self.params[self.keywordAction] == self.actionListFolder:
                    # channelName and URL is present, Parse the folder
                    self.ProcessFolderList()

                elif self.params[self.keywordAction] == self.actionPlayVideo:
                    self.PlayVideoItem()

                elif not self.params[self.keywordAction] == "":
                    self.OnActionFromContextMenu(self.params[self.keywordAction])

                else:
                    Logger.Warning("Number of parameters (%s) or parameter (%s) values not implemented",
                                   len(self.params), self.params)

            except:
                Logger.Critical("Error parsing for add-on", exc_info=True)

        self.__FetchTextures()
        return
Beispiel #3
0
    def __UpdateVideoItem(self, item, episodeId):
        """Updates an existing MediaItem with more data.

        Arguments:
        item      : MediaItem - the MediaItem that needs to be updated
        episodeId : String    - The episodeId, e.g.: VARA_xxxxxx

        Returns:
        The original item with more data added to it's properties.

        Used to update none complete MediaItems (self.complete = False). This
        could include opening the item's URL to fetch more data and then process that
        data or retrieve it's real media-URL.

        The method should at least:
        * cache the thumbnail to disk (use self.noImage if no thumb is available).
        * set at least one MediaItemPart with a single MediaStream.
        * set self.complete = True.

        if the returned item does not have a MediaItemPart then the self.complete flag
        will automatically be set back to False.

        """

        Logger.Trace("Using Generic UpdateVideoItem method")

        # get the subtitle
        subTitleUrl = "http://e.omroep.nl/tt888/%s" % (episodeId,)
        subTitlePath = subtitlehelper.SubtitleHelper.DownloadSubtitle(subTitleUrl, episodeId + ".srt", format='srt',
                                                                      proxy=self.proxy)

        # we need an hash code
        hashCode = NpoStream.GetNpoToken(self.proxy, Config.cacheDir)

        item.MediaItemParts = []
        part = item.CreateNewEmptyMediaPart()
        part.Subtitle = subTitlePath

        # then we fetch alternative streams locations and start with the non-adapative ones
        streamsUrls = []
        directStreamVideos = AddonSettings.GetUzgCacheDuration() == 0
        streamSource = [
            "http://ida.omroep.nl/odi/?prid=%s&puboptions=h264_bb,h264_sb,h264_std&adaptive=no&part=1&token=%s" % (
                episodeId, hashCode,)]
        if directStreamVideos:
            # if we stream, then we first look for adaptive streams
            Logger.Debug("UZG is configured to streams, so also check for the adaptive streams")
            streamSource.insert(0,
                                "http://ida.omroep.nl/odi/?prid=%s&puboptions=adaptive&adaptive=yes&part=1&token=%s" % (
                                    episodeId, hashCode,))
        else:
            Logger.Debug("UZG is configured to download. Not going to fetch the adaptive streams")

        # get the actual stream locations streams:
        for streamSourceUrl in streamSource:
            streamUrlData = UriHandler.Open(streamSourceUrl, proxy=self.proxy, noCache=True)
            streamJson = JsonHelper(streamUrlData, logger=Logger.Instance())
            for url in streamJson.GetValue('streams'):
                Logger.Trace("Going to look for streams in: %s", url)
                streamsUrls.append(url)

        # should we cache before playback
        if not directStreamVideos:
            part.CanStream = False

        # now we should now actually go and fetch urls
        for url in streamsUrls:
            data = UriHandler.Open(url, proxy=self.proxy)
            jsonData = JsonHelper(data, logger=Logger.Instance())

            # check for errors
            streamData = jsonData.GetValue()
            if "errorstring" in streamData:
                Logger.Warning("Found error response: %s", streamData["errorstring"])
                continue

            # either do m3u8 or hls
            if "m3u8" in url.lower():
                Logger.Trace("Processing M3U8 Json: %s", url)
                m3u8url = jsonData.GetValue("url")
                if m3u8url is None:
                    Logger.Warning("Could not find stream in: %s", m3u8url)
                    continue
                Logger.Trace("Processing M3U8 Streams: %s", m3u8url)

                for s, b in M3u8.GetStreamsFromM3u8(m3u8url, self.proxy):
                    item.complete = True
                    part.AppendMediaStream(s, b)

                # if we found an adaptive m3u8, we take that one as it's better
                Logger.Info("Found M3u8 streams and using those. Stop looking further for non-adaptive ones.")
                break
            else:
                Logger.Trace("Processing HLS: %s", url)
                if "h264_bb" in url:
                    bitrate = 500
                elif "h264_sb" in url:
                    bitrate = 220
                elif "h264_std" in url:
                    bitrate = 1000
                else:
                    bitrate = None

                protocol = jsonData.GetValue('protocol')
                if protocol:
                    url = "%s://%s%s" % (protocol, jsonData.GetValue('server'), jsonData.GetValue('path'))
                    part.AppendMediaStream(url, bitrate=bitrate)
                else:
                    Logger.Warning("Found UZG Stream without a protocol. Probably a expired page.")

        if not item.HasMediaItemParts():
            Logger.Warning("Apparently no streams were present in the normal places. Trying streams in metadata")

            # fetch the meta data to get more streams
            metaUrl = "http://e.omroep.nl/metadata/%s" % (episodeId,)
            metaData = UriHandler.Open(metaUrl, proxy=self.proxy)
            metaJson = JsonHelper(metaData, logger=Logger.Instance())

            # sometimes there are streams direct in the meta data file
            directStreams = metaJson.GetValue("streams", fallback=[])
            for stream in directStreams:
                quality = stream.get("kwaliteit", 0)
                if quality == 1:
                    bitrate = 180
                elif quality == 2:
                    bitrate = 1000
                elif quality == 3:
                    bitrate = 1500
                else:
                    bitrate = 0

                if "formaat" in stream and stream["formaat"] == "h264":
                    bitrate += 1
                part.AppendMediaStream(stream["url"], bitrate)

            # now we can get extra info from the data
            item.description = metaJson.GetValue("info")
            item.title = metaJson.GetValue('aflevering_titel')
            station = metaJson.GetValue('streamSense', 'station')

            if station is None:
                item.icon = self.icon
            elif station.startswith('nederland_1'):
                item.icon = self.GetImageLocation("1large.png")
            elif station.startswith('nederland_2'):
                item.icon = self.GetImageLocation("2large.png")
            elif station.startswith('nederland_3'):
                item.icon = self.GetImageLocation("3large.png")
            Logger.Trace("Icon for station %s = %s", station, item.icon)

            # <image size="380x285" ratio="4:3">http://u.omroep.nl/n/a/2010-12/380x285_boerzoektvrouw_yvon.png</image>
            thumbUrls = metaJson.GetValue('images')  # , {"size": "380x285"}, {"ratio":"4:3"})
            Logger.Trace(thumbUrls)
            if thumbUrls:
                thumbUrl = thumbUrls[-1]['url']
                if "http" not in thumbUrl:
                    thumbUrl = "http://u.omroep.nl/n/a/%s" % (thumbUrl,)
            else:
                thumbUrl = self.noImage

            item.thumb = thumbUrl

        item.complete = True
        return item