def DownloadVideoItem(self, item): """Downloads an existing MediaItem with more data. Arguments: item : MediaItem - the MediaItem that should be downloaded. Returns: The original item with more data added to it's properties. Used to download an <item>. If the item is not complete, the self.UpdateVideoItem method is called to update the item. The method downloads only the MediaStream with the bitrate that was set in the addon settings. After downloading the self.downloaded property is set. """ if not item.IsPlayable(): Logger.Error("Cannot download a folder item.") return item if item.IsPlayable(): if not item.complete: Logger.Info("Fetching MediaUrl for PlayableItem[%s]", item.type) item = self.ProcessVideoItem(item) if not item.complete or not item.HasMediaItemParts(): Logger.Error("Cannot download incomplete item or item without MediaItemParts") return item i = 1 bitrate = AddonSettings.GetMaxStreamBitrate() for mediaItemPart in item.MediaItemParts: Logger.Info("Trying to download %s", mediaItemPart) stream = mediaItemPart.GetMediaStreamForBitrate(bitrate) downloadUrl = stream.Url extension = UriHandler.GetExtensionFromUrl(downloadUrl) if len(item.MediaItemParts) > 1: saveFileName = "%s-Part_%s.%s" % (item.name, i, extension) else: saveFileName = "%s.%s" % (item.name, extension) Logger.Debug(saveFileName) # headers = item.HttpHeaders + mediaItemPart.HttpHeaders headers = item.HttpHeaders.copy() headers.update(mediaItemPart.HttpHeaders) progressDialog = XbmcDialogProgressWrapper("Downloading Item", item.name, stream.Url) folderName = XbmcWrapper.ShowFolderSelection('Select download destination for "%s"' % (saveFileName, )) UriHandler.Download(downloadUrl, saveFileName, folderName, progressDialog, proxy=self.proxy, additionalHeaders=headers) i += 1 item.downloaded = True return item
def __init__(self, channelInfo): """Initialisation of the class. Arguments: channelInfo: ChannelInfo - The channel info object to base this channel on. All class variables should be instantiated here and this method should not be overridden by any derived classes. """ chn_class.Channel.__init__(self, channelInfo) self.mainListUri = "#mainlist" self._AddDataParser(url="#mainlist", preprocessor=self.ParseRadioList) self._AddDataParser(url="*", preprocessor=self.ParseSubList) # ============== Actual channel setup STARTS here and should be overwritten from derived classes =============== self.noImage = "radionlimage.png" #=============================================================================================================== # non standard items # download the stream data dataPath = os.path.join(self.path, "data") Logger.Debug("Checking '%s' for data", dataPath) if not os.path.isdir(dataPath): Logger.Info("No data found at '%s', downloading stream data", dataPath) url = "http://www.rieter.net/net.rieter.xot.repository/net.rieter.xot.channel.streams/" \ "net.rieter.xot.channel.streams.radionl.data.zip" # give the user feedback progressDialog = XbmcDialogProgressWrapper( "Downloading Data", "net.rieter.xot.channel.streams.radionl.data.zip", url) # download the zipfile zipFile = UriHandler.Download( url, "net.rieter.xot.channel.streams.radionl.data.zip", self.GetDefaultCachePath(), progressDialog) # and unzip it ZipHelper.Unzip(zipFile, dataPath) if os.path.isdir(dataPath): Logger.Info("Data successfully downloaded to: %s", dataPath) #=============================================================================================================== # Test cases: # ====================================== Actual channel setup STOPS here ======================================= return
def __UpdateFromUrl(self, url, zipName): """ Update a channel from an URL @param url: The url to download @param zipName: The name to give the download """ Logger.Info("Going to update from %s", url) # wrapper = XbmcDialogProgressWrapper("Updating XOT", url) # destFilename = UriHandler.Download(url, zipName, Config.cacheDir, wrapper.ProgressUpdate) destFilename = UriHandler.Download(url, zipName, Config.cacheDir, self.__RetrieveProgressDummy) Logger.Debug("Download succeeded: %s", destFilename) # we extract to the deploy folder, so with the first start of XOT, the new channel is deployed deployDir = os.path.abspath(os.path.join(Config.rootDir, "deploy")) zipFile = zipfile.ZipFile(destFilename) # now extract first = True Logger.Debug("Extracting %s to %s", destFilename, deployDir) for name in zipFile.namelist(): if first: folder = os.path.split(name)[0] if os.path.exists(os.path.join(deployDir, folder)): shutil.rmtree(os.path.join(deployDir, folder)) first = False if not name.endswith("/") and not name.endswith("\\"): fileName = os.path.join(deployDir, name) path = os.path.dirname(fileName) if not os.path.exists(path): os.makedirs(path) Logger.Debug("Extracting %s", fileName) outfile = open(fileName, 'wb') outfile.write(zipFile.read(name)) outfile.close() zipFile.close() os.remove(destFilename) Logger.Info("Update completed and zip file (%s) removed", destFilename) message = LanguageHelper.GetLocalizedString( LanguageHelper.UpdateCompleteId, splitOnPipes=False) % (zipName.replace(".zip", ""), ) message = message.split("|") XbmcWrapper.ShowNotification(LanguageHelper.GetLocalizedString( LanguageHelper.RestartId), message, displayTime=5000, logger=Logger.Instance())
def PlayVideoItem(self, item, bitrate=None): """Starts the playback of the <item> with the specific <bitrate> in the selected <player>. Arguments: item : MediaItem - The item to start playing Keyword Arguments: bitrate : [opt] integer - The requested bitrate in Kbps or None. plugin : [opt] boolean - Indication whether we are in plugin mode. If True, there will not actually be playback, rather a tuple with info. Returns: The updated <item>. Starts the playback of the selected MediaItem <item>. Before playback is started the item is check for completion (item.complete), if not completed, the self.UpdateVideoItem method is called to update the item. After updating the requested bitrate playlist is selected, if bitrate was set to None the bitrate is retrieved from the addon settings. The playlist is then played using the requested player. """ if bitrate is None: # use the bitrate from the xbmc settings if bitrate was not specified and the item is MultiBitrate bitrate = AddonSettings.GetMaxStreamBitrate() # should we download items? Logger.Debug("Checking for not streamable parts") # We need to substract the download time from processing time downloadStart = datetime.now() for part in item.MediaItemParts: if not part.CanStream: stream = part.GetMediaStreamForBitrate(bitrate) if not stream.Downloaded: Logger.Debug("Downloading not streamable part: %s\nDownloading Stream: %s", part, stream) # we need a unique filename fileName = encodinghelper.EncodingHelper.EncodeMD5(stream.Url) extension = UriHandler.GetExtensionFromUrl(stream.Url) # now we force the busy dialog to close, else we cannot cancel the download # setResolved will not work. xbmc.executebuiltin("Dialog.Close(busydialog)") # headers = item.HttpHeaders + part.HttpHeaders headers = item.HttpHeaders.copy() headers.update(part.HttpHeaders) Logger.Error(headers) streamFilename = "xot.%s.%skbps-%s.%s" % (fileName, stream.Bitrate, item.name, extension) progressDialog = XbmcDialogProgressWrapper("Downloading Item", item.name, stream.Url) cacheFile = UriHandler.Download(stream.Url, streamFilename, self.GetDefaultCachePath(), progressDialog.ProgressUpdate, proxy=self.proxy, additionalHeaders=headers) if cacheFile == "": Logger.Error("Cannot download stream %s \nFrom: %s", stream, part) return if cacheFile.startswith("\\\\"): cacheFile = cacheFile.replace("\\", "/") stream.Url = "file:///%s" % (cacheFile,) else: stream.Url = "file://%s" % (cacheFile,) # stream.Url = cacheFile stream.Downloaded = True # We need to substract the download time from processing time downloadTime = datetime.now() - downloadStart downloadDuration = 1000 * downloadTime.seconds + downloadTime.microseconds / 1000 # Set item as downloaded item.downloaded = True # get the playlist (playList, srt) = item.GetXBMCPlayList(bitrate, updateItemUrls=True, proxy=self.proxy) # call for statistics with timing Statistics.RegisterPlayback(self, item, Initializer.StartTime, -downloadDuration) # if the item urls have been updated, don't start playback, but return return playList, srt