def _updateNextPoints(self): # query the scheduler for what the next points are in its window # and set it on the UI state current = self.uiState.get('next-points')[:] points = self.icalScheduler.getPoints() new = [] # twisted says 'Currently can't jelly datetime objects with tzinfo', # so convert all to UTC then remove tzinfo. def _utcAndStripTZ(dt): return dt.astimezone(eventcalendar.UTC).replace(tzinfo=None) for p in points: dtUTC = _utcAndStripTZ(p.dt) dtStart = p.eventInstance.start.replace(tzinfo=None) new.append((dtUTC, p.which, formatting.strftime(p.eventInstance.event.content, dtStart.timetuple()))) for t in current: if t not in new: self.debug('removing tuple %r from next-points', t) self.uiState.remove('next-points', t) for t in new: if t not in current: self.debug('appending tuple %r to next-points', t) self.uiState.append('next-points', t)
def changeFilename(self, filenameTemplate=None, datetime=None): """ @param filenameTemplate: strftime format string to decide filename @param time: an aware datetime used for the filename and to compare if an existing file needs to be overwritten. defaulting to datetime.now(). """ mime = self.getMime() ext = mimeTypeToExtention(mime) # if the events comes from the calendar, datetime is aware and we can # deduce from it both the local and utc time. # in case datetime is None datetime.now() doesn't return an aware # datetime, so we need to get both the local time and the utc time. tm = datetime or dt.datetime.now() tmutc = datetime or dt.datetime.utcnow() # delay the stop of the current recording to ensure there are no gaps # in the recorded files. We could think that emitting first the signal # to add a new client before the one to remove the client and syncing # with the latest keyframe should be enough, but it doesn't ensure the # stream continuity if it's done close to a keyframe because when # multifdsink looks internally for the latest keyframe it's already to # late and a gap is introduced. reactor.callLater(self.timeOverlap, self._stopRecordingFull, self.file, self.location, self.last_tstamp, True) sink = self.get_element('fdsink') if sink.get_state() == gst.STATE_NULL: sink.set_state(gst.STATE_READY) filename = "" if not filenameTemplate: filenameTemplate = self._defaultFilenameTemplate filename = "%s.%s" % ( formatting.strftime( filenameTemplate, # for the filename we want to use the local time tm.timetuple()), ext) self.location = os.path.join(self.directory, filename) # only overwrite existing files if it was last changed before the # start of this event; ie. if it is a recording of a previous event location = self.location i = 1 while os.path.exists(location): mtimeTuple = time.gmtime(os.stat(location).st_mtime) # time.gmtime returns a time tuple in utc, so we compare against # the utc timetuple of the datetime if mtimeTuple <= tmutc.utctimetuple(): self.info( "Existing recording %s from previous event, overwriting", location) break self.info( "Existing recording %s from current event, changing name", location) location = self.location + '.' + str(i) i += 1 self.location = location self.info("Changing filename to %s", self.location) self.file = _openFile(self, self, self.location, 'wb') if self.file is None: return self._recordingStarted(self.file, self.location) sink.emit('add', self.file.fileno()) self.last_tstamp = time.time() self.uiState.set('filename', self.location) self.uiState.set('recording', True) if self._symlinkToCurrentRecording: self._updateSymlink(self.location, self._symlinkToCurrentRecording)