def do_setup(self): try: localConfigPath = self._configPath configPath = VirtualPath.virtualize(localConfigPath, self._local) self.debug("Loading configuration from '%s'", localConfigPath) self._config = TranscodingConfig() loader = IniFile() loader.loadFromFile(self._config, localConfigPath) if self._inputPath: confInputFile = self._config.source.inputFile if not self._inputPath.endswith(confInputFile): raise Exception("The source file path " + "doesn't match the configuration " + "source input-file property") altInputDir = self._inputPath[:-len(confInputFile)] else: altInputDir=None #TODO add cue points in report self._report = TranscodingReport() self._report.init(self._config) self._report.configPath = configPath if not self._diagnoseMode: moveInputFile = self._moveInputFile else: self.info("Entering diagnose mode") moveInputFile = False self._job = job.TranscodingJob(self, self, self._pathAttr) self._job.setup(self._local, self._config, self._report, moveInputFile=moveInputFile, altInputDir=altInputDir, niceLevel=self._niceLevel) d = self._job.start() self._reportDefaultPath = self._job.getTempReportPath() self.__syncReport(self._report) d.addCallbacks(self.__cbJobDone, self.__ebJobFailed) return None except: self.__unexpectedError(task="component setup")
class FileTranscoder(component.BaseComponent, job.JobEventSink): componentMediumClass = FileTranscoderMedium logCategory = compconsts.TRANSCODER_LOG_CATEGORY ## Public Methods ## def getStatus(self): return self._status def do_acknowledge(self): self.onAcknowledged() d = self._job.acknowledge() d.addCallback(self.__cbJobTerminated) d.addErrback(self.__ebAcknowledgeError) return d ## Overriden Methods ## def init(self): log.setDefaultCategory(compconsts.TRANSCODER_LOG_CATEGORY) log.setDebugNotifier(self.__notifyDebug) self.logName = None self._diagnoseMode = False self._waitAcknowledge = False self._moveInputFile = True self._niceLevel = None self._job = None self._report = None self._reportDefaultPath = None self._reportForcedPath = None self._configPath = None self._config = None self._inputPath = None self._local = None self._status = TranscoderStatusEnum.pending self._pathAttr = None self.uiState.addDictKey('job-data', {}) self.uiState.addDictKey('source-data', {}) self.uiState.addDictKey('targets-data', {}) self.uiState.setitem('job-data', "progress", 0.0) self.uiState.setitem('job-data', "job-state", JobStateEnum.pending) self.uiState.setitem('job-data', "acknowledged", False) self.uiState.setitem('job-data', "status", self._status) def check_properties(self, props, addMessage): #TODO: Add directories/files right checks if props.has_key("config"): if props.has_key("diagnose"): msg = ("Component properties 'config' " + "and 'diagnose' should not be " + "specified at the same time") raise TranscoderConfigError(msg) local = Local.createFromComponentProperties(props) configPath = VirtualPath(props["config"]) localConfigPath = configPath.localize(local) if not os.path.exists(localConfigPath): msg = "Config file not found ('%s')" % localConfigPath raise TranscoderConfigError(msg) elif props.has_key("diagnose"): localReportPath = props["diagnose"] if not os.path.exists(localReportPath): msg = "Report file not found ('%s')" % localReportPath raise TranscoderConfigError(msg) else: msg = ("One of the component properties " + "'config' and 'diagnose' " + "should be specified") raise TranscoderConfigError(msg) if props.has_key("report"): localRealPath = os.path.realpath(props["report"]) localReportDir = os.path.dirname(localRealPath) if not os.path.exists(localReportDir): msg = "Output report directory not found ('%s')" % localReportDir raise TranscoderConfigError(msg) def do_check(self): def transcoder_checks(result): # PyChecker doesn't like dynamic attributes __pychecker__ = "no-objattrs" props = self.config["properties"] #FIXME: Better checks for path roots self._waitAcknowledge = props.get("wait-acknowledge", False) self._moveInputFile = props.get("move-input-file", True) self._niceLevel = props.get("nice-level", None) self._pathAttr = fileutils.PathAttributes.createFromComponentProperties(props) localRepPath = props.get("report", None) self._reportForcedPath = localRepPath and os.path.realpath(localRepPath) if props.has_key("config"): self._local = Local.createFromComponentProperties(props) configPath = VirtualPath(props["config"]) localConfigPath = configPath.localize(self._local) self.debug("Loading configuration from '%s'", localConfigPath) self._configPath = localConfigPath self._inputPath = None self._diagnoseMode = False else: localReportPath = props["diagnose"] self.debug("Loading report from '%s'", localReportPath) baseReport = TranscodingReport() loader = IniFile() loader.loadFromFile(baseReport, localReportPath) self.info("Using local '%s' from report file", baseReport.local.name) self._local = baseReport.local.getLocal() self._local.updateFromComponentProperties(props) configPath = baseReport.configPath localConfigPath = configPath.localize(self._local) if not os.path.exists(localConfigPath): msg = "Config file not found ('%s')" % localConfigPath raise TranscoderConfigError(msg) self._configPath = localConfigPath alternatives = [baseReport.source.lastPath, baseReport.source.failedPath, baseReport.source.donePath, baseReport.source.inputPath] for virtAltPath in alternatives: self._inputPath = virtAltPath.localize(self._local) if os.path.isfile(self._inputPath): break self._diagnoseMode = True return result try: self._fireStatusChanged(TranscoderStatusEnum.checking) d = component.BaseComponent.do_check(self) d.addCallback(transcoder_checks) d.addErrback(self.__ebErrorFilter, "component checking") return d except: self.__unexpectedError(task="component checks") def do_setup(self): try: localConfigPath = self._configPath configPath = VirtualPath.virtualize(localConfigPath, self._local) self.debug("Loading configuration from '%s'", localConfigPath) self._config = TranscodingConfig() loader = IniFile() loader.loadFromFile(self._config, localConfigPath) if self._inputPath: confInputFile = self._config.source.inputFile if not self._inputPath.endswith(confInputFile): raise Exception("The source file path " + "doesn't match the configuration " + "source input-file property") altInputDir = self._inputPath[:-len(confInputFile)] else: altInputDir=None #TODO add cue points in report self._report = TranscodingReport() self._report.init(self._config) self._report.configPath = configPath if not self._diagnoseMode: moveInputFile = self._moveInputFile else: self.info("Entering diagnose mode") moveInputFile = False self._job = job.TranscodingJob(self, self, self._pathAttr) self._job.setup(self._local, self._config, self._report, moveInputFile=moveInputFile, altInputDir=altInputDir, niceLevel=self._niceLevel) d = self._job.start() self._reportDefaultPath = self._job.getTempReportPath() self.__syncReport(self._report) d.addCallbacks(self.__cbJobDone, self.__ebJobFailed) return None except: self.__unexpectedError(task="component setup") def do_stop(self, *args, **kwargs): def component_stop(result): return component.BaseComponent.do_stop(self) try: if self._job: d = self._job.stop() else: d = defer.succeed(None) d.addCallback(component_stop) d.addErrback(self.__ebStopErrorFilter) return d except: self.__unexpectedError(task="component stopping") ## Overriden Methods ## def onJobInfo(self, info): for key, value in info.iteritems(): self.uiState.setitem('job-data', key, value) def onAcknowledged(self): self.uiState.setitem('job-data', "acknowledged", True) def onJobError(self, error): self.uiState.setitem('job-data', "job-error", error) def onJobWarning(self, warning): self.uiState.setitem('job-data', "job-warning", warning) def onProgress(self, percent): if percent == None: self.info("Progression not supported") elif self._diagnoseMode: self.info("Progress: %d %%" % int(percent)) else: self.log("Progress: %d %%" % int(percent)) self.uiState.setitem('job-data', "progress", percent) def onJobStateChanged(self, state): self.uiState.setitem('job-data', "job-state", state) def onSourceInfo(self, info): inputFile = info["input-file"] virtFile = VirtualPath.virtualize(inputFile, self._local) info["input-file"] = str(virtFile) for key, value in info.iteritems(): self.uiState.setitem('source-data', key, value) def onTargetStateChanged(self, label, state): self.uiState.setitem('targets-data', (label, "target-state"), state) def onTargetInfo(self, label, info): for key, value in info.iteritems(): self.uiState.setitem('targets-data', (label, key), value) def onTargetError(self, label, error): self.uiState.setitem('targets-data', (label, "target-error"), error) def onTargetWarning(self, label, warning): self.uiState.setitem('targets-data', (label, "target-warning"), warning) def onSyncReport(self, report): self.__syncReport(report) ## Protected/Friend Methods ## def _getReportPath(self): if self._reportDefaultPath: virtPath = VirtualPath.virtualize(self._reportDefaultPath, self._local) return virtPath return None def _fireStatusChanged(self, status): self._status = status self.uiState.setitem('job-data', "status", status) def _fireTranscodingReport(self, reportPath): virtPath = VirtualPath.virtualize(reportPath, self._local) self.uiState.setitem('job-data', "transcoding-report", virtPath) ## Private Methods ## def __notifyDebug(self, msg, info=None, debug=None, failure=None, exception=None, documents=None): infoMsg = ["File Transcoder Debug Notification: %s" % msg] debugMsg = [] if info: infoMsg.append("Information:\n\n%s" % info) if debug: debugMsg.append("Additional Debug Info:\n\n%s" % debug) if failure: debugMsg.append("Failure Message: %s\nFailure Traceback:\n%s" % (log.getFailureMessage(failure), log.getFailureTraceback(failure))) if exception: debugMsg.append("Exception Message: %s\n\nException Traceback:\n%s" % (log.getExceptionMessage(exception), log.getExceptionTraceback(exception))) m = messages.Warning(T_("\n\n".join(infoMsg)), debug="\n\n".join(debugMsg)) self.addMessage(m) def __ebErrorFilter(self, failure, task=None): if failure.check(FlumotionError, PropertyError): return self.__transcodingError(failure, task) return self.__unexpectedError(failure, task) def __ebStopErrorFilter(self, failure): self.__unexpectedError(failure) return component.BaseComponent.do_stop(self) def __transcodingError(self, failure=None, task=None): self._fireStatusChanged(TranscoderStatusEnum.error) if not failure: failure = Failure() self.onJobError(failure.getErrorMessage()) log.notifyFailure(self, failure, "Transocding error%s", (task and " during %s" % task) or "", cleanTraceback=True) self.setMood(moods.sad) return failure def __unexpectedError(self, failure=None, task=None): self._fireStatusChanged(TranscoderStatusEnum.unexpected_error) if not failure: failure = Failure() self.onJobError(failure.getErrorMessage()) log.notifyFailure(self, failure, "Unexpected error%s", (task and " during %s" % task) or "", cleanTraceback=True) m = messages.Error(T_(failure.getErrorMessage()), debug=log.getFailureMessage(failure)) self.addMessage(m) return failure def __syncReport(self, report): report.reportPath = self._getReportPath() self.debug("Report path is: %s", report.reportPath) self.__writeReport(report) self._fireTranscodingReport(self._reportDefaultPath) def __deleteTempReport(self): if self._reportForcedPath: return current = self._reportDefaultPath temp = self._job.getTempReportPath() if ((current != temp) and os.path.isfile(current) and os.path.isfile(temp)): try: os.remove(temp) except OSError, e: msg = "Fail to delete temporary report" self.warning("%s '%s'", msg, temp) info = "File path: '%s'" % temp debug = log.getExceptionMessage(e) self.__notifyDebug(msg, info=info, debug=debug, exception=e)