Index: /ipk/source/system_permanenttimeshift_3_0/usr/lib/enigma2/python/Plugins/Extensions/PermanentTimeshift/plugin.py
===================================================================
--- /ipk/source/system_permanenttimeshift_3_0/usr/lib/enigma2/python/Plugins/Extensions/PermanentTimeshift/plugin.py	(revision 3436)
+++ /ipk/source/system_permanenttimeshift_3_0/usr/lib/enigma2/python/Plugins/Extensions/PermanentTimeshift/plugin.py	(revision 3436)
@@ -0,0 +1,1136 @@
+#######################################################
+# Permanent Timeshift Plugin for Enigma2 Dreamboxes
+# Coded by Homey (c) 2010
+#
+# Version: 1.00 RC9
+# Support: www.i-have-a-dreambox.com
+#######################################################
+from Components.ActionMap import ActionMap
+from Components.ConfigList import ConfigList, ConfigListScreen
+from Components.config import config, configfile, getConfigListEntry, ConfigSubsection, ConfigYesNo, ConfigInteger, ConfigSelection
+from Components.Label import Label
+from Components.Language import language
+from Components.Pixmap import Pixmap
+from Components.ServiceEventTracker import ServiceEventTracker
+from Components.Sources.StaticText import StaticText
+from Components.UsageConfig import preferredInstantRecordPath, defaultMoviePath
+from Screens.ChoiceBox import ChoiceBox
+from Screens.ChannelSelection import ChannelSelection
+from Screens.InfoBar import InfoBar
+from Screens.InfoBarGenerics import NumberZap, InfoBarSeek, InfoBarNumberZap, InfoBarEPG, InfoBarTimeshiftState, InfoBarInstantRecord, InfoBarChannelSelection
+from Screens.MessageBox import MessageBox
+from Screens.Screen import Screen
+from Screens.Setup import SetupSummary
+from Screens.PVRState import TimeshiftState
+from ServiceReference import ServiceReference
+from Tools import Directories, ASCIItranslit
+from Tools.Directories import fileExists, copyfile, resolveFilename, SCOPE_LANGUAGE, SCOPE_PLUGINS
+from Plugins.Plugin import PluginDescriptor
+from RecordTimer import RecordTimerEntry, parseEvent
+
+from re import search as re_search
+from enigma import eTimer, eServiceCenter, eBackgroundFileEraser, eConsoleAppContainer, iPlayableService, iServiceInformation
+from os import environ, stat as os_stat, listdir as os_listdir, link as os_link
+from time import localtime, time, strftime
+
+import gettext
+import Screens.InfoBar
+
+##############################
+#####  CONFIG SETTINGS   #####
+##############################
+
+config.plugins.pts = ConfigSubsection()
+config.plugins.pts.enabled = ConfigYesNo(default = True)
+config.plugins.pts.cleanOnZap = ConfigYesNo(default = True)
+config.plugins.pts.copyptsfile = ConfigYesNo(default = False)
+config.plugins.pts.mergerecords = ConfigYesNo(default = False)
+config.plugins.pts.marginrecords = ConfigYesNo(default = False)
+config.plugins.pts.showinfobar = ConfigYesNo(default = False)
+config.plugins.pts.maxevents = ConfigInteger(default=5, limits=(1, 99))
+config.plugins.pts.maxlength = ConfigInteger(default=180, limits=(5, 999))
+config.plugins.pts.startdelay = ConfigInteger(default=5, limits=(5, 999))
+config.plugins.pts.favoriteSaveAction = ConfigSelection([("askuser", _("Ask user")),("savetimeshift", _("Save and stop")),("savetimeshiftandrecord", _("Save and record")),("noSave", _("Don't save"))], "askuser")
+
+##############################
+###   Multilanguage Init   ###
+##############################
+
+def localeInit():
+	lang = language.getLanguage()
+	environ["LANGUAGE"] = lang[:2]
+	gettext.bindtextdomain("enigma2", resolveFilename(SCOPE_LANGUAGE))
+	gettext.textdomain("enigma2")
+	gettext.bindtextdomain("PTSPlugin", "%s%s" % (resolveFilename(SCOPE_PLUGINS), "Extensions/PermanentTimeshift/locale/"))
+
+def _(txt):
+	t = gettext.dgettext("PTSPlugin", txt)
+	if t == txt:
+		t = gettext.gettext(txt)
+	return t
+
+localeInit()
+language.addCallback(localeInit)
+
+###################################
+###  PTS TimeshiftState Screen  ###
+###################################
+
+class PTSTimeshiftState(Screen):
+	skin = """
+		<screen position="center,40" zPosition="2" size="420,50" backgroundColor="transpBlack" flags="wfNoBorder">
+			<widget name="state" position="10,3" size="80,27" font="Regular;20" halign="center" backgroundColor="transpBlack" />
+			<widget source="session.CurrentService" render="Label" position="95,5" size="120,27" font="Regular;20" halign="left" foregroundColor="white" backgroundColor="transpBlack">
+				<convert type="ServicePosition">Remaining</convert>
+			</widget>
+			<widget source="session.CurrentService" render="Label" position="350,5" size="60,27" font="Regular;20" halign="left" foregroundColor="white" backgroundColor="transpBlack">
+				<convert type="ServicePosition">Length</convert>
+			</widget>
+			<widget name="PTSSeekPointer" position="8,30" zPosition="3" size="19,50" pixmap="/usr/lib/enigma2/python/Plugins/Extensions/PermanentTimeshift/images/timeline-now.png" alphatest="on" />
+			<ePixmap position="10,33" size="840,15" zPosition="1" pixmap="/usr/lib/enigma2/python/Plugins/Extensions/PermanentTimeshift/images/slider_back.png" alphatest="on"/>
+			   <widget source="session.CurrentService" render="Progress" position="10,33" size="390,15" zPosition="2" pixmap="/usr/lib/enigma2/python/Plugins/Extensions/PermanentTimeshift/images/slider.png" transparent="1">
+				<convert type="ServicePosition">Position</convert>
+			</widget>
+		</screen>"""
+
+	def __init__(self, session):
+		Screen.__init__(self, session)
+		self["state"] = Label(text="")
+		self["PTSSeekPointer"] = Pixmap()
+
+##############################
+#####  Class InfoBarPTS  #####
+##############################
+class InfoBarPTS(InfoBar):
+	def __init__(self, session):
+		InfoBar.__init__(self, session)
+		self.skinName = "InfoBar"
+
+		self.__event_tracker = ServiceEventTracker(screen = self, eventmap =
+			{
+				iPlayableService.evStart: self.__evStart,
+				iPlayableService.evEnd: self.__evEnd,
+				iPlayableService.evUpdatedInfo: self.__evInfoChanged,
+				iPlayableService.evUpdatedEventInfo: self.__evEventInfoChanged,
+				iPlayableService.evSeekableStatusChanged: self.__seekableStatusChanged
+			})
+
+		self["PTSactions"] = ActionMap(["PTS_InstantRecordActions"],{"instantRecord": self.instantRecord},-2)
+		self["PTSSeekPointerActions"] = ActionMap(["PTS_SeekPointerActions"],{"SeekPointerOK": self.ptsSeekPointerOK, "SeekPointerLeft": self.ptsSeekPointerLeft, "SeekPointerRight": self.ptsSeekPointerRight, "SeekPointerStop": self.stopTimeshift},-2)
+		
+		self["PTSSeekPointerActions"].setEnabled(False)
+
+		self.pts_begintime = 0
+		self.pts_pathchecked = False
+		self.pts_uptdateeventcount = True
+		self.pts_delmergeRecordName = None
+		self.pts_pvrStateDialog = "TimeshiftState"
+		self.save_current_timeshift = False
+		self.save_timeshift_postaction = None
+		self.save_timeshift_filename = None
+		self.service_changed = 0
+
+		# Init eBackgroundFileEraser
+		self.BgFileEraser = eBackgroundFileEraser.getInstance()
+
+		# Init PTS Delay-Timer
+		self.pts_delay_timer = eTimer()
+		self.pts_delay_timer.callback.append(self.ActivatePermanentTimeshift)
+		
+		# Init PTS LengthCheck-Timer
+		self.pts_LengthCheck_timer = eTimer()
+		self.pts_LengthCheck_timer.callback.append(self.ptsLengthCheck)
+
+		# Init PTS MergeRecords-Timer
+		self.pts_mergeRecords_timer = eTimer()
+		self.pts_mergeRecords_timer.callback.append(self.ptsMergeRecords)
+
+		# Init PTS CleanUp-Timer
+		self.pts_cleanUp_timer = eTimer()
+		self.pts_cleanUp_timer.callback.append(self.cleanTimeshiftFolder)
+		self.pts_cleanUp_timer.start(30000, True)
+
+		# Keep Current Event Info for recordings
+		self.pts_eventcount = 1
+		self.pts_curevent_begin = int(time())
+		self.pts_curevent_end = 0
+		self.pts_curevent_name = _("Timeshift")
+		self.pts_curevent_description = ""
+		self.pts_curevent_servicerefname = ""
+		self.pts_curevent_station = ""
+		self.pts_curevent_eventid = None
+
+		# Init PTS Infobar
+		self.pts_seekpointer_MinX = 8
+		self.pts_seekpointer_MaxX = 396 # make sure you can divide this through 2
+
+	def __evStart(self):
+		self.service_changed = 1
+
+	def __evEnd(self):
+		self.service_changed = 0
+
+	def __evInfoChanged(self):
+		if self.service_changed:
+			self.service_changed = 0
+
+			# Delete Timeshift Records on zap if enabled
+			if config.plugins.pts.cleanOnZap.value:
+				self.pts_eventcount = 0
+				self.pts_cleanUp_timer.start(3000, True)
+			else:
+				self.pts_uptdateeventcount = False
+
+			# Ooops, we zapped away before saving the file :(
+			if self.save_current_timeshift:
+				self.session.open(MessageBox,_("OH NO!\nThe timeshift that was marked to save at end of event, was lost because you zapped away!"), MessageBox.TYPE_INFO)
+				self.save_current_timeshift = False
+
+	def __evEventInfoChanged(self):
+		if not config.plugins.pts.enabled.value:
+			return
+
+		service = self.session.nav.getCurrentService()
+		old_begin_time = self.pts_begintime
+		info = service and service.info()
+		ptr = info and info.getEvent(0)
+		self.pts_begintime = ptr and ptr.getBeginTime() or 0
+
+		if info.getInfo(iServiceInformation.sVideoPID) != -1:
+			# Save Current TimeShift to file now ...
+			if self.save_current_timeshift and self.timeshift_enabled:
+				# Take care of Record Margin Time ...
+				if config.plugins.pts.marginrecords.value and config.recording.margin_after.value > 0 and len(self.recording) == 0:
+					self.SaveTimeshift(mergelater=True)
+					recording = RecordTimerEntry(ServiceReference(self.session.nav.getCurrentlyPlayingServiceReference()), time(), time()+(config.recording.margin_after.value*60), self.pts_curevent_name, self.pts_curevent_description, self.pts_curevent_eventid, dirname = "/media/hdd/movie/")
+					recording.dontSave = True
+					self.session.nav.RecordTimer.record(recording)
+					self.recording.append(recording)
+				else:
+					self.SaveTimeshift()
+
+			# Restarting active timers after zap ...
+			if self.pts_delay_timer.isActive() and not self.timeshift_enabled:
+				self.pts_delay_timer.start(config.plugins.pts.startdelay.value*1000, True)
+			if self.pts_cleanUp_timer.isActive() and not self.timeshift_enabled:
+				self.pts_cleanUp_timer.start(3000, True)
+
+			# (Re)Start TimeShift
+			# ToDo: We only want delayed start when zapping, not on event change on same channel!
+			if not self.pts_delay_timer.isActive():
+				if not self.timeshift_enabled or old_begin_time != self.pts_begintime or old_begin_time == 0:
+					self.pts_delay_timer.start(config.plugins.pts.startdelay.value*1000, True)
+
+	def __seekableStatusChanged(self):
+		enabled = False
+		if not self.isSeekable() and self.timeshift_enabled:
+			enabled = True
+		self["TimeshiftActivateActions"].setEnabled(enabled)
+
+		enabled = False
+		if config.plugins.pts.enabled.value and config.plugins.pts.showinfobar.value and self.isSeekable() and self.timeshift_enabled:
+			enabled = True
+
+		self["PTSSeekPointerActions"].setEnabled(enabled)
+
+		# Reset Seek Pointer
+		self.ptsSeekPointerReset()
+
+	def instantRecord(self):
+		InfoBarInstantRecord.instantRecord(self)
+
+	def ActivatePermanentTimeshift(self):
+		if not self.ptsCheckTimeshiftPath():
+			return
+
+		# Replace PVR Timeshift State Icon
+		if config.plugins.pts.showinfobar.value:
+			if self.pts_pvrStateDialog != "PTSTimeshiftState":
+				self.pts_pvrStateDialog = "PTSTimeshiftState"
+				self.pvrStateDialog = self.session.instantiateDialog(PTSTimeshiftState)
+		elif not config.plugins.pts.showinfobar.value and self.pts_pvrStateDialog != "TimeshiftState":
+			self.pts_pvrStateDialog = "TimeshiftState"
+			self.pvrStateDialog = self.session.instantiateDialog(TimeshiftState)
+
+		# Update internal Event Counter
+		if self.pts_eventcount >= config.plugins.pts.maxevents.value:
+			if self.pts_uptdateeventcount:
+				self.pts_eventcount = 0
+			else:
+				self.pts_eventcount = 1
+
+		if self.pts_uptdateeventcount:
+			self.pts_eventcount += 1
+		else:
+			self.pts_uptdateeventcount = True
+
+		# Do not switch back to LiveTV while timeshifting
+		# Note: This only works with enigma from JAN 2010 or later
+		if InfoBarSeek.isSeekable(self):
+			switchToLive = False
+		else:
+			switchToLive = True
+
+		# (Re)start Timeshift now
+		self.stopTimeshiftConfirmed(True, switchToLive)
+		ts = self.getTimeshift()
+		if ts and not ts.startTimeshift():
+			self.pts_starttime = time()
+			self.pts_LengthCheck_timer.start(120000)
+			self.timeshift_enabled = 1
+			self.__seekableStatusChanged()
+			self.save_timeshift_postaction = None
+			self.ptsGetEventInfo()
+			self.ptsCreateHardlink()
+		else:
+			self.pts_eventcount = 0
+			if self.pts_eventcount > 1:
+				self.pts_cleanUp_timer.start(3000, True)
+				self.pts_delay_timer.start(30000, True)
+				self.session.open(MessageBox, _("Timeshift Buffer Full!\n Cleaning Buffer and restarting timeshift ..."), MessageBox.TYPE_ERROR, timeout=5)
+
+	def stopTimeshift(self):
+		if not self.timeshift_enabled:
+			return 0
+
+		# Jump Back to Live TV
+		if config.plugins.pts.enabled.value and self.timeshift_enabled:
+			if InfoBarSeek.isSeekable(self):
+				# Jump back to Live TV
+				# ToDo: This is dirty somehow. Isn't there a better way to switch back to live?
+				if self.seekstate != self.SEEK_STATE_PLAY:
+					self.setSeekState(self.SEEK_STATE_PLAY)
+				#self.doSeek(+1) # seek 1 gop before end
+				#self.seekFwd() # seekFwd to switch to live TV
+				self.fwdSeekTo(+1)
+				return 1
+			return 0
+		InfoBar.stopTimeshift(self)
+
+	def stopTimeshiftConfirmed(self, confirmed, switchToLive=True):
+		was_enabled = self.timeshift_enabled
+
+		if not confirmed:
+			return
+		ts = self.getTimeshift()
+		if ts is None:
+			return
+
+		try:
+			ts.stopTimeshift(switchToLive)
+		except:
+			ts.stopTimeshift()
+
+		self.timeshift_enabled = 0
+		self.__seekableStatusChanged()
+
+		if was_enabled and not self.timeshift_enabled:
+			self.timeshift_enabled = 0
+			self.pts_LengthCheck_timer.stop()
+
+	def cleanTimeshiftFolder(self):
+		if not config.plugins.pts.enabled.value or not self.ptsCheckTimeshiftPath():
+			return
+
+		for filename in os_listdir(config.usage.timeshift_path.value):
+			if (filename.startswith("timeshift.") or filename.startswith("pts_livebuffer.")) and (filename.endswith(".del") is False and filename.endswith(".meta") is False and filename.endswith(".copy") is False):
+				statinfo = os_stat("%s/%s" % (config.usage.timeshift_path.value,filename))
+				# if no write for 5 sec = stranded timeshift
+				if statinfo.st_mtime < (time()-5.0):
+					print "PTS-Plugin: Erasing stranded timeshift %s" % filename
+					self.BgFileEraser.erase("%s/%s" % (config.usage.timeshift_path.value,filename))
+
+					# Delete Meta File too
+					if filename.startswith("pts_livebuffer.") is True:
+						self.BgFileEraser.erase("%s/%s.meta" % (config.usage.timeshift_path.value,filename))
+
+	def SaveTimeshift(self, timeshiftfile=None, mergelater=False):
+		# B0rked by Gutemine. Thx :)
+		self.save_current_timeshift = False
+		savefilename = None
+
+		if not self.timeshift_enabled:
+			return
+
+		if timeshiftfile is not None:
+			savefilename = timeshiftfile
+
+		if savefilename is None:
+			for filename in os_listdir(config.usage.timeshift_path.value):
+				if filename.startswith("timeshift.") and not filename.endswith(".del") and not filename.endswith(".copy"):
+					statinfo = os_stat("%s/%s" % (config.usage.timeshift_path.value,filename))
+					if statinfo.st_mtime > (time()-5.0):
+						savefilename=filename
+
+		if savefilename is None:
+			self.session.open(MessageBox, _("No Timeshift found to save as recording!"), MessageBox.TYPE_ERROR, timeout=5)
+		else:
+			timeshift_saved = True
+			timeshift_saveerror1 = ""
+			timeshift_saveerror2 = ""
+			metamergestring = ""
+
+			if mergelater:
+				self.pts_mergeRecords_timer.start(120000, True)
+				metamergestring = "pts_merge\n"
+
+			try:
+				if timeshiftfile is None:
+					# Save Current Event by creating hardlink to ts file
+
+					ptsfilename = "%s - %s - %s" % (strftime("%Y%m%d %H%M",localtime(self.pts_curevent_begin)),self.pts_curevent_station,self.pts_curevent_name)
+					if config.recording.ascii_filenames.value:
+						ptsfilename = ASCIItranslit.legacyEncode(ptsfilename)
+
+					fullname = Directories.getRecordingFilename(ptsfilename,"/media/hdd/movie/")
+					os_link("%s/%s" % (config.usage.timeshift_path.value, savefilename), "%s.ts" % (fullname))
+					metafile = open("%s.ts.meta" % (fullname), "w")
+					metafile.write("%s\n%s\n%s\n%i\n%s" % (self.pts_curevent_servicerefname,self.pts_curevent_name,self.pts_curevent_description,int(self.pts_starttime),metamergestring))
+					metafile.close()
+				elif timeshiftfile.startswith("pts_livebuffer"):
+					# Save stored timeshift by creating hardlink to ts file
+					readmetafile = open("%s/%s.meta" % (config.usage.timeshift_path.value,timeshiftfile), "r")
+					servicerefname = readmetafile.readline()[0:-1]
+					eventname = readmetafile.readline()[0:-1]
+					description = readmetafile.readline()[0:-1]
+					begintime = readmetafile.readline()[0:-1]
+					readmetafile.close()
+
+					ptsfilename = "%s - %s - %s" % (strftime("%Y%m%d %H%M",localtime(int(begintime))),self.pts_curevent_station,eventname)
+					if config.recording.ascii_filenames.value:
+						ptsfilename = ASCIItranslit.legacyEncode(ptsfilename)
+
+					fullname=Directories.getRecordingFilename(ptsfilename,"/media/hdd/movie/")
+					os_link("%s/%s" % (config.usage.timeshift_path.value, timeshiftfile),"%s.ts" % (fullname))
+					os_link("%s/%s.meta" % (config.usage.timeshift_path.value, timeshiftfile),"%s.ts.meta" % (fullname))
+
+				self.session.open(MessageBox, _("Timeshift saved to your harddisk!"), MessageBox.TYPE_INFO, timeout=5)
+			except Exception, errormsg:
+				timeshift_saved = False
+				timeshift_saveerror1 = errormsg
+
+			# Hmpppf! Saving Timeshift via Hardlink-Method failed. Probably other device?
+			# Let's try to copy the file in background now! This might take a while ...
+			if not timeshift_saved and config.plugins.pts.copyptsfile.value:
+				self.container_save = eConsoleAppContainer()
+				self.container_save.appClosed.append(self.ptsCopyFilefinished)
+
+				self.session.open(MessageBox, _("We try to copy the file now. This might take a while!"), MessageBox.TYPE_INFO, timeout=5)
+
+				# Start Blinking FrontPanel LED
+				self.ptsFrontpanelActions("start")
+
+				try:
+					if timeshiftfile is None:
+						# Save Current Event by copying it to the other device
+						os_link("%s/%s" % (config.usage.timeshift_path.value, savefilename), "%s/%s.copy" % (config.usage.timeshift_path.value, savefilename))
+						copy_cmd = "cp '%s/%s.copy' '%s.ts'" % (config.usage.timeshift_path.value, savefilename, fullname)
+						metafile = open("%s.ts.meta" % (fullname), "w")
+						metafile.write("%s\n%s\n%s\n%i\n%s" % (self.pts_curevent_servicerefname,self.pts_curevent_name,self.pts_curevent_description,int(self.pts_starttime),metamergestring))
+						metafile.close()
+					elif timeshiftfile.startswith("pts_livebuffer"):
+						# Save stored timeshift by copying it to the other device
+						os_link("%s/%s" % (config.usage.timeshift_path.value, timeshiftfile), "%s/%s.copy" % (config.usage.timeshift_path.value, timeshiftfile))
+						copyfile("%s/%s.meta" % (config.usage.timeshift_path.value, timeshiftfile),"%s.ts.meta" % (fullname))
+						copy_cmd = "cp '%s/%s.copy' '%s.ts'" % (config.usage.timeshift_path.value, timeshiftfile, fullname)
+
+					self.container_save.execute(copy_cmd)
+					timeshift_saved = True
+				except Exception, errormsg:
+					timeshift_saved = False
+					timeshift_saveerror2 = errormsg
+
+			if not timeshift_saved:
+				errormessage = str(timeshift_saveerror1) + "\n" + str(timeshift_saveerror2)
+				self.session.open(MessageBox, _("Timeshift save failed!")+"\n\n%s" % errormessage, MessageBox.TYPE_ERROR)
+
+	def saveTimeshiftPopup(self):
+		self.session.openWithCallback(self.saveTimeshiftPopupCallback, ChoiceBox, \
+			title=_("The Timeshift record was not saved yet!\nWhat do you want to do now with the timeshift file?"), \
+			list=((_("Save Timeshift as Movie and stop recording"), "savetimeshift"), \
+			(_("Save Timeshift as Movie and continue recording"), "savetimeshiftandrecord"), \
+			(_("Don't save Timeshift as Movie"), "noSave")))
+
+	def saveTimeshiftPopupCallback(self, answer):
+		if answer is None:
+			return
+
+		if answer[1] == "savetimeshift":
+			self.saveTimeshiftActions("savetimeshift")
+		elif answer[1] == "savetimeshiftandrecord":
+			self.saveTimeshiftActions("savetimeshiftandrecord")
+		elif answer[1] == "noSave":
+			self.save_current_timeshift = False
+			self.saveTimeshiftActions("noSave")
+
+	def saveTimeshiftEventPopup(self):
+		filecount = 0
+		entrylist = []
+		entrylist.append((_("Current Event:")+" %s" % (self.pts_curevent_name), "savetimeshift"))
+
+		filelist = os_listdir(config.usage.timeshift_path.value)
+
+		if filelist is not None:
+			filelist.sort()
+
+		for filename in filelist:
+			if (filename.startswith("pts_livebuffer.") is True) and (filename.endswith(".del") is False and filename.endswith(".meta") is False and filename.endswith(".copy") is False):
+				statinfo = os_stat("%s/%s" % (config.usage.timeshift_path.value,filename))
+				if statinfo.st_mtime < (time()-5.0):
+					# Get Event Info from meta file
+					readmetafile = open("%s/%s.meta" % (config.usage.timeshift_path.value,filename), "r")
+					servicerefname = readmetafile.readline()[0:-1]
+					eventname = readmetafile.readline()[0:-1]
+					readmetafile.close()
+
+					# Add Event to list
+					filecount += 1
+					entrylist.append((_("Record #%s: %s" % (filecount, eventname)), "%s" % filename))
+
+		self.session.openWithCallback(self.recordQuestionCallback, ChoiceBox, title=_("Which event do you want to save permanently?"), list=entrylist)
+
+	def saveTimeshiftActions(self, action = None):
+		if action is None:
+			if config.plugins.pts.favoriteSaveAction.value == "askuser":
+				self.saveTimeshiftPopup()
+				return
+			elif config.plugins.pts.favoriteSaveAction.value == "savetimeshift":
+				self.SaveTimeshift()
+			elif config.plugins.pts.favoriteSaveAction.value == "savetimeshiftandrecord":
+				self.SaveTimeshift(mergelater=True)
+				InfoBarInstantRecord.startInstantRecording(self, limitEvent = True)
+			elif config.plugins.pts.favoriteSaveAction.value == "noSave":
+				self.save_current_timeshift = False
+		elif action == "savetimeshift":
+			self.SaveTimeshift()
+		elif action == "savetimeshiftandrecord":
+			self.SaveTimeshift(mergelater=True)
+			InfoBarInstantRecord.startInstantRecording(self, limitEvent = True)
+		elif action == "noSave":
+			self.save_current_timeshift = False
+
+		# Post PTS Actions like ZAP or whatever the user requested
+		if self.save_timeshift_postaction == "zapUp":
+			InfoBarChannelSelection.zapUp(self)
+		elif self.save_timeshift_postaction == "zapDown":
+			InfoBarChannelSelection.zapDown(self)
+		elif self.save_timeshift_postaction == "historyBack":
+			InfoBarChannelSelection.historyBack(self)
+		elif self.save_timeshift_postaction == "historyNext":
+			InfoBarChannelSelection.historyNext(self)
+		elif self.save_timeshift_postaction == "switchChannelUp":
+			InfoBarChannelSelection.switchChannelUp(self)
+		elif self.save_timeshift_postaction == "switchChannelDown":
+			InfoBarChannelSelection.switchChannelDown(self)
+		elif self.save_timeshift_postaction == "openServiceList":
+			InfoBarChannelSelection.openServiceList(self)
+		elif self.save_timeshift_postaction == "showRadioChannelList":
+			InfoBarChannelSelection.showRadioChannelList(self, zap=True)
+
+	def ptsGetEventInfo(self):
+		event = None
+		try:
+			serviceref = self.session.nav.getCurrentlyPlayingServiceReference()
+			serviceHandler = eServiceCenter.getInstance()
+			info = serviceHandler.info(serviceref)
+
+			self.pts_curevent_servicerefname = serviceref.toString()
+			self.pts_curevent_station = info.getName(serviceref)
+
+			service = self.session.nav.getCurrentService()
+			info = service and service.info()
+			event = info and info.getEvent(0)
+		except Exception, errormsg:
+			self.session.open(MessageBox, _("Getting Event Info failed!")+"\n\n%s" % errormsg, MessageBox.TYPE_ERROR, timeout=10)
+
+		if event is not None:
+			curEvent = parseEvent(event)
+			self.pts_curevent_begin = int(curEvent[0])
+			self.pts_curevent_end = int(curEvent[1])
+			self.pts_curevent_name = curEvent[2]
+			self.pts_curevent_description = curEvent[3]
+			self.pts_curevent_eventid = curEvent[4]
+
+	def ptsFrontpanelActions(self, action=None):
+		if InfoBarInstantRecord.isInstantRecordRunning(self):
+			return
+
+		if action == "start":
+			try:
+				open("/proc/stb/fp/led0_pattern", "w").write("0x55555555")
+				open("/proc/stb/fp/led_pattern_speed", "w").write("20")
+			except IOError:
+				print "PTS-Plugin: No FrontPanel LED that can start blinking"
+		elif action == "stop":
+			try:
+				open("/proc/stb/fp/led0_pattern", "w").write("0")
+			except IOError:
+				print "PTS-Plugin: No FrontPanel LED that can stop blinking"
+
+	def ptsCreateHardlink(self):
+		for filename in os_listdir(config.usage.timeshift_path.value):
+			if filename.startswith("timeshift.") and not filename.endswith(".del") and not filename.endswith(".copy"):
+				statinfo = os_stat("%s/%s" % (config.usage.timeshift_path.value,filename))
+				if statinfo.st_mtime > (time()-5.0):
+					try:
+						self.BgFileEraser.erase("%s/pts_livebuffer.%s" % (config.usage.timeshift_path.value,self.pts_eventcount))
+					except Exception, e:
+						print "PTS Plugin: %s" % (e)
+
+					try:
+						os_link("%s/%s" % (config.usage.timeshift_path.value,filename), "%s/pts_livebuffer.%s" % (config.usage.timeshift_path.value,self.pts_eventcount))
+
+						# Create a Meta File
+						metafile = open("%s/pts_livebuffer.%s.meta" % (config.usage.timeshift_path.value,self.pts_eventcount), "w")
+						metafile.write("%s\n%s\n%s\n%i\n" % (self.pts_curevent_servicerefname,self.pts_curevent_name,self.pts_curevent_description,int(self.pts_starttime)))
+						metafile.close()
+					except Exception, errormsg:
+						self.session.open(MessageBox, _("Creating Hardlink to Timeshift file failed!")+"\nFilesystems like FAT32 do not support hardlinks!"+"\n\n%s" % errormsg, MessageBox.TYPE_ERROR)
+
+	def ptsMergeRecords(self):
+		if not config.plugins.pts.mergerecords.value:
+			return
+
+		if InfoBarInstantRecord.isInstantRecordRunning(self):
+			self.pts_mergeRecords_timer.start(120000, True)
+			return
+
+		ptsmergeSRC = ""
+		ptsmergeDEST = ""
+		ptsmergeeventname = ""
+		ptsgetnextfile = False
+
+		filelist = os_listdir("/media/hdd/movie/")
+
+		if filelist is not None:
+			filelist.sort(self.ptsNumsort)
+
+		for filename in filelist:
+			if filename.endswith(".meta"):
+				# Get Event Info from meta file
+				readmetafile = open("%s/%s" % ("/media/hdd/movie/",filename), "r")
+				servicerefname = readmetafile.readline()[0:-1]
+				eventname = readmetafile.readline()[0:-1]
+				eventtitle = readmetafile.readline()[0:-1]
+				eventtime = readmetafile.readline()[0:-1]
+				eventtag = readmetafile.readline()[0:-1]
+				readmetafile.close()
+
+				if ptsgetnextfile:
+					ptsgetnextfile = False
+					ptsmergeSRC = filename[0:-5]
+
+					if ASCIItranslit.legacyEncode(eventname) == ASCIItranslit.legacyEncode(ptsmergeeventname):
+						self.pts_delmergeRecordName = ptsmergeSRC
+						self.container_merge = eConsoleAppContainer()
+						self.container_merge.appClosed.append(self.ptsMergeFilefinished)
+
+						self.session.open(MessageBox,_("Merging Timeshift records now!\nThis might take a while ..."), MessageBox.TYPE_INFO, timeout=5)
+
+						# Rewrite Meta File to get rid of pts_merge tag
+						metafile = open("%s/%s.meta" % ("/media/hdd/movie/", ptsmergeDEST), "w")
+						metafile.write("%s\n%s\n%s\n%i\n" % (servicerefname,eventname,eventtitle,int(eventtime)))
+						metafile.close()
+
+						# Copy EIT File
+						copyfile("%s/%s.eit" % ("/media/hdd/movie/", ptsmergeSRC[0:-3]),"%s/%s.eit" % ("/media/hdd/movie/", ptsmergeDEST[0:-3]))
+
+						# Delete AP File
+						self.BgFileEraser.erase("%s/%s.ap" % ("/media/hdd/movie/", ptsmergeDEST))
+
+						self.ptsFrontpanelActions("start")
+						self.container_merge.execute("cat '%s/%s' >> '%s/%s'" % ("/media/hdd/movie/",ptsmergeSRC,"/media/hdd/movie/",ptsmergeDEST))
+						return
+					else:
+						self.session.open(MessageBox,_("PTS-Plugin: Merging records failed!\nEventnames did not match ...\n\nSRC: %s\nDEST:%s") % (ASCIItranslit.legacyEncode(eventname),ASCIItranslit.legacyEncode(ptsmergeeventname)), MessageBox.TYPE_ERROR, timeout=15)
+
+				if eventtag == "pts_merge":
+					ptsgetnextfile = True
+					ptsmergeDEST = filename[0:-5]
+					ptsmergeeventname = eventname
+
+					# If still recording or transfering, try again later ...
+					statinfo = os_stat("%s/%s" % ("/media/hdd/movie/",ptsmergeDEST))
+					if statinfo.st_mtime > (time()-10.0):
+						self.pts_mergeRecords_timer.start(120000, True)
+						return
+
+	def ptsCopyFilefinished(self,retval):
+		for filename in os_listdir(config.usage.timeshift_path.value):
+			if filename.endswith(".copy"):
+				self.BgFileEraser.erase("%s/%s" % (config.usage.timeshift_path.value,filename))
+
+		# Stop blinking frontpanel led
+		self.ptsFrontpanelActions("stop")
+
+		self.session.open(MessageBox,("Timeshift copied to your harddisk!"),  MessageBox.TYPE_INFO, timeout = 5)
+
+	def ptsMergeFilefinished(self,retval):
+		if self.pts_delmergeRecordName is not None:
+			# Delete Instant Record permanently now ... R.I.P.
+			self.BgFileEraser.erase("%s/%s" % ("/media/hdd/movie/",self.pts_delmergeRecordName))
+			self.BgFileEraser.erase("%s/%s.eit" % ("/media/hdd/movie/",self.pts_delmergeRecordName[0:-3]))
+			self.BgFileEraser.erase("%s/%s.ap" % ("/media/hdd/movie/",self.pts_delmergeRecordName))
+			self.BgFileEraser.erase("%s/%s.cuts" % ("/media/hdd/movie/",self.pts_delmergeRecordName))
+			self.BgFileEraser.erase("%s/%s.meta" % ("/media/hdd/movie/",self.pts_delmergeRecordName))
+			self.BgFileEraser.erase("%s/%s.sc" % ("/media/hdd/movie/",self.pts_delmergeRecordName))
+
+			self.pts_delmergeRecordName = None
+
+		self.ptsFrontpanelActions("stop")
+		self.session.open(MessageBox,("Records successfully merged!"),  MessageBox.TYPE_INFO, timeout = 10)
+
+	def ptsGetnum(self, filename):
+		m = re_search(r'\d+', filename)
+		if m: return float(m.group(0))
+		return None
+
+	def ptsNumsort(self, c, d):
+		return cmp(self.ptsGetnum(c), self.ptsGetnum(d))
+
+	def ptsGetSeekInfo(self):
+		s = self.session.nav.getCurrentService()
+		return s and s.seek()
+
+	def ptsGetPosition(self):
+		seek = self.ptsGetSeekInfo()
+		if seek is None:
+			return None
+		pos = seek.getPlayPosition()
+		if pos[0]:
+			return 0
+		return pos[1]
+
+	def ptsGetLength(self):
+		seek = self.ptsGetSeekInfo()
+		if seek is None:
+			return None
+		length = seek.getLength()
+		if length[0]:
+			return 0
+		return length[1]
+
+	def ptsSeekPointerOK(self):
+		if self.pts_pvrStateDialog == "PTSTimeshiftState" and self.timeshift_enabled and self.isSeekable():
+			if not self.pvrstate_hide_timer.isActive():
+				if self.seekstate != self.SEEK_STATE_PLAY:
+					self.setSeekState(self.SEEK_STATE_PLAY)
+				self.doShow()
+				return
+
+			length = self.ptsGetLength()
+			position = self.ptsGetPosition()
+
+			if length is None or position is None:
+				return
+
+			cur_pos = self.pvrStateDialog["PTSSeekPointer"].position
+			jumptox = int(cur_pos[0]) - int(self.pts_seekpointer_MinX)
+			jumptoperc = round((jumptox / 400.0) * 100, 0)
+			jumptotime = int((length / 100) * jumptoperc)
+			jumptodiff = position - jumptotime
+
+			self.doSeekRelative(-jumptodiff)
+			InfoBarTimeshiftState._mayShow(self)
+		else:
+			return
+
+	def ptsSeekPointerLeft(self):
+		if self.pts_pvrStateDialog == "PTSTimeshiftState" and self.timeshift_enabled and self.isSeekable():
+			self.ptsMoveSeekPointer(direction="left")
+		else:
+			return
+
+	def ptsSeekPointerRight(self):
+		if self.pts_pvrStateDialog == "PTSTimeshiftState" and self.timeshift_enabled and self.isSeekable():
+			self.ptsMoveSeekPointer(direction="right")
+		else:
+			return
+
+	def ptsSeekPointerReset(self):
+		if self.pts_pvrStateDialog == "PTSTimeshiftState" and self.timeshift_enabled:
+			self.pvrStateDialog["PTSSeekPointer"].setPosition(self.pts_seekpointer_MinX, self.pvrStateDialog["PTSSeekPointer"].position[1])
+
+	def ptsMoveSeekPointer(self, direction=None):
+		if direction is None or self.pts_pvrStateDialog != "PTSTimeshiftState":
+			return
+
+		isvalidjump = False
+		cur_pos = self.pvrStateDialog["PTSSeekPointer"].position
+		InfoBarTimeshiftState._mayShow(self)
+
+		if direction == "left":
+			minmaxval = self.pts_seekpointer_MinX
+			movepixels = -15
+			if cur_pos[0]+movepixels > minmaxval:
+				isvalidjump = True
+		elif direction == "right":
+			minmaxval = self.pts_seekpointer_MaxX
+			movepixels = 15
+			if cur_pos[0]+movepixels < minmaxval:
+				isvalidjump = True
+		else:
+			return 0
+
+		if isvalidjump:
+			self.pvrStateDialog["PTSSeekPointer"].setPosition(cur_pos[0]+movepixels, cur_pos[1])
+		else:
+			self.pvrStateDialog["PTSSeekPointer"].setPosition(minmaxval, cur_pos[1])
+
+	def ptsCheckTimeshiftPath(self):
+		if self.pts_pathchecked:
+			return True
+		else:
+			if fileExists(config.usage.timeshift_path.value, 'w'):
+				self.pts_pathchecked = True
+				return True
+			else:
+				self.session.open(MessageBox, _("Could not activate Permanent-Timeshift!\n\nTimeshift-Path does not exist"), MessageBox.TYPE_ERROR, timeout=15)
+				if self.pts_delay_timer.isActive():
+					self.pts_delay_timer.stop()
+				if self.pts_cleanUp_timer.isActive():
+					self.pts_cleanUp_timer.stop()
+				return False
+
+	def ptsLengthCheck(self):
+		if self.session.screen["Standby"].boolean is not True and config.plugins.pts.enabled.value and self.timeshift_enabled and (time() - self.pts_starttime) >= (config.plugins.pts.maxlength.value * 60):
+			if self.save_current_timeshift:
+				self.saveTimeshiftActions("savetimeshift")
+				self.ActivatePermanentTimeshift()
+				self.save_current_timeshift = True
+			else:
+				self.ActivatePermanentTimeshift()
+			self.session.open(MessageBox,_("Maximum Timeshift length per Event reached!\nRestarting Timeshift now ..."), MessageBox.TYPE_INFO, timeout=5)
+
+#Replace the InfoBar with our version ;)
+Screens.InfoBar.InfoBar = InfoBarPTS
+
+############
+#zapUp Hack#
+############
+InfoBarChannelSelection_zapUp = InfoBarChannelSelection.zapUp
+
+def zapUp(self):
+	if self.save_current_timeshift and self.timeshift_enabled:
+		self.save_timeshift_postaction = "zapUp"
+		InfoBarPTS.saveTimeshiftActions(self)
+	else:
+		InfoBarChannelSelection_zapUp(self)
+
+InfoBarChannelSelection.zapUp = zapUp
+
+##############
+#zapDown Hack#
+##############
+InfoBarChannelSelection_zapDown = InfoBarChannelSelection.zapDown
+
+def zapDown(self):
+	if self.save_current_timeshift and self.timeshift_enabled:
+		self.save_timeshift_postaction = "zapDown"
+		InfoBarPTS.saveTimeshiftActions(self)
+	else:
+		InfoBarChannelSelection_zapDown(self)
+
+InfoBarChannelSelection.zapDown = zapDown
+
+##################
+#historyBack Hack#
+##################
+InfoBarChannelSelection_historyBack = InfoBarChannelSelection.historyBack
+
+def historyBack(self):
+	if self.save_current_timeshift and self.timeshift_enabled:
+		self.save_timeshift_postaction = "historyBack"
+		InfoBarPTS.saveTimeshiftActions(self)
+	elif self.pts_pvrStateDialog == "PTSTimeshiftState" and self.timeshift_enabled and self.isSeekable():
+		InfoBarTimeshiftState._mayShow(self)
+		self.pvrStateDialog["PTSSeekPointer"].setPosition(self.pts_seekpointer_MinX, self.pvrStateDialog["PTSSeekPointer"].position[1])
+		if self.seekstate != self.SEEK_STATE_PLAY:
+			self.setSeekState(self.SEEK_STATE_PLAY)
+		self.ptsSeekPointerOK()
+	else:
+		InfoBarChannelSelection_historyBack(self)
+
+InfoBarChannelSelection.historyBack = historyBack
+
+##################
+#historyNext Hack#
+##################
+InfoBarChannelSelection_historyNext = InfoBarChannelSelection.historyNext
+
+def historyNext(self):
+	if self.save_current_timeshift and self.timeshift_enabled:
+		self.save_timeshift_postaction = "historyNext"
+		InfoBarPTS.saveTimeshiftActions(self)
+	elif self.pts_pvrStateDialog == "PTSTimeshiftState" and self.timeshift_enabled and self.isSeekable():
+		InfoBarTimeshiftState._mayShow(self)
+		self.pvrStateDialog["PTSSeekPointer"].setPosition(self.pts_seekpointer_MaxX, self.pvrStateDialog["PTSSeekPointer"].position[1])
+		if self.seekstate != self.SEEK_STATE_PLAY:
+			self.setSeekState(self.SEEK_STATE_PLAY)
+		self.ptsSeekPointerOK()
+	else:
+		InfoBarChannelSelection_historyNext(self)
+
+InfoBarChannelSelection.historyNext = historyNext
+
+######################
+#switchChannelUp Hack#
+######################
+InfoBarChannelSelection_switchChannelUp = InfoBarChannelSelection.switchChannelUp
+
+def switchChannelUp(self):
+	if self.save_current_timeshift and self.timeshift_enabled:
+		self.save_timeshift_postaction = "switchChannelUp"
+		InfoBarPTS.saveTimeshiftActions(self)
+	else:
+		InfoBarChannelSelection_switchChannelUp(self)
+
+InfoBarChannelSelection.switchChannelUp = switchChannelUp
+
+########################
+#switchChannelDown Hack#
+########################
+InfoBarChannelSelection_switchChannelDown = InfoBarChannelSelection.switchChannelDown
+
+def switchChannelDown(self):
+	if self.save_current_timeshift and self.timeshift_enabled:
+		self.save_timeshift_postaction = "switchChannelDown"
+		InfoBarPTS.saveTimeshiftActions(self)
+	else:
+		InfoBarChannelSelection_switchChannelDown(self)
+
+InfoBarChannelSelection.switchChannelDown = switchChannelDown
+
+######################
+#openServiceList Hack#
+######################
+InfoBarChannelSelection_openServiceList = InfoBarChannelSelection.openServiceList
+
+def openServiceList(self):
+	if self.save_current_timeshift and self.timeshift_enabled:
+		self.save_timeshift_postaction = "openServiceList"
+		InfoBarPTS.saveTimeshiftActions(self)
+	else:
+		InfoBarChannelSelection_openServiceList(self)
+
+InfoBarChannelSelection.openServiceList = openServiceList
+
+###########################
+#showRadioChannelList Hack#
+###########################
+InfoBarChannelSelection_showRadioChannelList = InfoBarChannelSelection.showRadioChannelList
+
+def showRadioChannelList(self, zap=False):
+	if self.save_current_timeshift and self.timeshift_enabled:
+		self.save_timeshift_postaction = "showRadioChannelList"
+		InfoBarPTS.saveTimeshiftActions(self)
+	else:
+		InfoBarChannelSelection_showRadioChannelList(self, zap)
+
+InfoBarChannelSelection.showRadioChannelList = showRadioChannelList
+
+#######################
+#InfoBarNumberZap Hack#
+#######################
+InfoBarNumberZap_keyNumberGlobal = InfoBarNumberZap.keyNumberGlobal
+
+def keyNumberGlobal(self, number):
+	if self.save_current_timeshift and self.timeshift_enabled:
+		InfoBarPTS.saveTimeshiftActions(self)
+		return
+
+	if self.pts_pvrStateDialog == "PTSTimeshiftState" and self.timeshift_enabled and self.isSeekable() and number == 0:
+		InfoBarTimeshiftState._mayShow(self)
+		self.pvrStateDialog["PTSSeekPointer"].setPosition(self.pts_seekpointer_MaxX/2, self.pvrStateDialog["PTSSeekPointer"].position[1])
+		if self.seekstate != self.SEEK_STATE_PLAY:
+			self.setSeekState(self.SEEK_STATE_PLAY)
+		self.ptsSeekPointerOK()
+		return
+
+	InfoBarNumberZap_keyNumberGlobal(self, number)
+	if number and config.plugins.pts.enabled.value and self.timeshift_enabled and not self.isSeekable():
+		self.session.openWithCallback(self.numberEntered, NumberZap, number)
+
+InfoBarNumberZap.keyNumberGlobal = keyNumberGlobal
+
+###########################
+#InfoBarInstantRecord Hack#
+###########################
+InfoBarInstantRecord_recordQuestionCallback = InfoBarInstantRecord.recordQuestionCallback
+
+def recordQuestionCallback(self, answer):
+	InfoBarInstantRecord_recordQuestionCallback(self, answer)
+
+	if config.plugins.pts.enabled.value:
+		if answer is not None and answer[1] == "savetimeshift":
+			self.session.open(MessageBox,_("Timeshift will get saved at end of event!"), MessageBox.TYPE_INFO, timeout=5)
+			self.save_current_timeshift = True
+
+		if answer is not None and answer[1] == "savetimeshiftEvent":
+			InfoBarPTS.saveTimeshiftEventPopup(self)
+
+		if answer is not None and answer[1].startswith("pts_livebuffer") is True:
+			InfoBarPTS.SaveTimeshift(self, timeshiftfile=answer[1])
+
+InfoBarInstantRecord.recordQuestionCallback = recordQuestionCallback
+
+############################
+#InfoBarTimeshiftState Hack#
+############################
+def _mayShow(self):
+	if self.execing and self.timeshift_enabled and self.isSeekable():
+		self.pvrStateDialog.show()
+
+		self.pvrstate_hide_timer = eTimer()
+		self.pvrstate_hide_timer.callback.append(self.pvrStateDialog.hide)
+
+		if self.seekstate == self.SEEK_STATE_PLAY:
+			idx = config.usage.infobar_timeout.index
+			if not idx:
+				idx = 5
+			self.pvrstate_hide_timer.start(idx*1000, True)
+		else:
+			self.pvrstate_hide_timer.stop()
+	elif self.execing and self.timeshift_enabled and not self.isSeekable():
+		self.pvrStateDialog.hide()
+
+InfoBarTimeshiftState._mayShow = _mayShow
+
+####################
+#instantRecord Hack#
+####################
+InfoBarInstantRecord_instantRecord = InfoBarInstantRecord.instantRecord
+
+def instantRecord(self):
+	if not config.plugins.pts.enabled.value or not self.timeshift_enabled:
+		InfoBarInstantRecord_instantRecord(self)
+		return
+
+	dir = preferredInstantRecordPath()
+	if not dir or not fileExists(dir, 'w'):
+		dir = defaultMoviePath()
+	try:
+		stat = os_stat(dir)
+	except:
+		# XXX: this message is a little odd as we might be recording to a remote device
+		self.session.open(MessageBox, _("No HDD found or HDD not initialized!"), MessageBox.TYPE_ERROR)
+		return
+
+	if self.isInstantRecordRunning():
+		self.session.openWithCallback(self.recordQuestionCallback, ChoiceBox, \
+			title=_("A recording is currently running.\nWhat do you want to do?"), \
+			list=((_("stop recording"), "stop"), \
+			(_("add recording (stop after current event)"), "event"), \
+			(_("add recording (indefinitely)"), "indefinitely"), \
+			(_("add recording (enter recording duration)"), "manualduration"), \
+			(_("add recording (enter recording endtime)"), "manualendtime"), \
+			(_("change recording (duration)"), "changeduration"), \
+			(_("change recording (endtime)"), "changeendtime"), \
+			(_("Timeshift")+" "+_("save recording (stop after current event)"), "savetimeshift"), \
+			(_("Timeshift")+" "+_("save recording (Select event)"), "savetimeshiftEvent"), \
+			(_("do nothing"), "no")))
+	else:
+		self.session.openWithCallback(self.recordQuestionCallback, ChoiceBox, \
+			title=_("Start recording?"), \
+			list=((_("add recording (stop after current event)"), "event"), \
+			(_("add recording (indefinitely)"), "indefinitely"), \
+			(_("add recording (enter recording duration)"), "manualduration"), \
+			(_("add recording (enter recording endtime)"), "manualendtime"), \
+			(_("Timeshift")+" "+_("save recording (stop after current event)"), "savetimeshift"), \
+			(_("Timeshift")+" "+_("save recording (Select event)"), "savetimeshiftEvent"), \
+			(_("don't record"), "no")))
+
+InfoBarInstantRecord.instantRecord = instantRecord
+
+############################
+#####  SETTINGS SCREEN #####
+############################
+class PermanentTimeShiftSetup(Screen, ConfigListScreen):
+	def __init__(self, session):
+		Screen.__init__(self, session)
+		self.skinName = [ "PTSSetup", "Setup" ]
+		self.setup_title = _("Permanent Timeshift Settings")
+
+		self.onChangedEntry = [ ]
+		self.list = [ ]
+		ConfigListScreen.__init__(self, self.list, session = session, on_change = self.changedEntry)
+
+		self["actions"] = ActionMap(["SetupActions", "ColorActions"],
+		{
+			"ok": self.SaveSettings,
+			"green": self.SaveSettings,
+			"red": self.Exit,
+			"cancel": self.Exit
+		}, -2)
+
+		self["key_green"] = StaticText(_("OK"))
+		self["key_red"] = StaticText(_("Cancel"))
+
+		self.createSetup()
+		self.onLayoutFinish.append(self.layoutFinished)
+
+	def layoutFinished(self):
+		self.setTitle(self.setup_title)
+
+	def createSetup(self):
+		self.list = [ getConfigListEntry(_("Permanent Timeshift Enable"), config.plugins.pts.enabled) ]
+		if config.plugins.pts.enabled.value:
+			self.list.extend((
+				getConfigListEntry(_("Permanent Timeshift Max Events"), config.plugins.pts.maxevents),
+				getConfigListEntry(_("Permanent Timeshift Max Length"), config.plugins.pts.maxlength),
+				getConfigListEntry(_("Permanent Timeshift Start Delay"), config.plugins.pts.startdelay),
+				getConfigListEntry(_("Timeshift-Save Action on zap"), config.plugins.pts.favoriteSaveAction),
+				getConfigListEntry(_("Clean Timeshift Buffer on zap?"), config.plugins.pts.cleanOnZap),
+				getConfigListEntry(_("Beta: Copy Movie when hardlinking failed?"), config.plugins.pts.copyptsfile),
+				getConfigListEntry(_("Beta: Show PTS Infobar while timeshifting?"), config.plugins.pts.showinfobar),
+				getConfigListEntry(_("Beta: Merge PTS and Instant Record later?"), config.plugins.pts.mergerecords),
+				getConfigListEntry(_("Beta: Margin after recording current event?"), config.plugins.pts.marginrecords)
+			))
+
+		self["config"].list = self.list
+		self["config"].setList(self.list)
+
+	def keyLeft(self):
+		ConfigListScreen.keyLeft(self)
+		if self["config"].getCurrent()[1] == config.plugins.pts.enabled:
+			self.createSetup()
+
+	def keyRight(self):
+		ConfigListScreen.keyRight(self)
+		if self["config"].getCurrent()[1] == config.plugins.pts.enabled:
+			self.createSetup()
+
+	def changedEntry(self):
+		for x in self.onChangedEntry:
+			x()
+
+	def getCurrentEntry(self):
+		return self["config"].getCurrent()[0]
+
+	def getCurrentValue(self):
+		return str(self["config"].getCurrent()[1].getText())
+
+	def createSummary(self):
+		return SetupSummary
+
+	def SaveSettings(self):
+		config.plugins.pts.save()
+		configfile.save()
+		self.close()
+
+	def Exit(self):
+		self.close()
+
+#################################################
+
+def startSetup(menuid):
+	if menuid != "system":
+		return [ ]
+	return [(_("Timeshift Settings"), PTSSetupMenu, "pts_setup", 50)]
+
+def PTSSetupMenu(session, **kwargs):
+	session.open(PermanentTimeShiftSetup)
+
+def Plugins(path, **kwargs):
+	return [ PluginDescriptor(name="Permanent Timeshift", description=_("Permanent Timeshift Settings"), where=[PluginDescriptor.WHERE_PLUGINMENU,PluginDescriptor.WHERE_EXTENSIONSMENU], icon="plugin.png", fnc=PTSSetupMenu), \
+		PluginDescriptor(name=_("Permanent Timeshift Settings"), description=_("Permanent Timeshift Settings"), where=PluginDescriptor.WHERE_MENU, fnc=startSetup)  ]
