Index: DirectShowFilters/TsWriter/source/TsChannel.cpp
===================================================================
--- DirectShowFilters/TsWriter/source/TsChannel.cpp	(revision 27796)
+++ DirectShowFilters/TsWriter/source/TsChannel.cpp	(working copy)
@@ -33,13 +33,16 @@
 CTsChannel::CTsChannel(LPUNKNOWN pUnk, HRESULT *phr,int id) 
 {
 	m_id=id;
+	
+	b_grabCustomPackets=false;
 	m_pVideoAnalyzer = new CVideoAnalyzer(pUnk,phr);
 	m_pPmtGrabber = new CPmtGrabber(pUnk,phr);
 	m_pRecorder = new CDiskRecorder(RecordingMode::Recording);
 	m_pTimeShifting= new CDiskRecorder(RecordingMode::TimeShift);
 	m_pTeletextGrabber= new CTeletextGrabber(pUnk,phr);
-  m_pCaGrabber= new CCaGrabber(pUnk,phr);
-}
+    m_pCaGrabber= new CCaGrabber(pUnk,phr);
+    m_CustomPacketWriter= new FileWriter;
+} 
 
 CTsChannel::~CTsChannel(void)
 {
@@ -79,6 +82,12 @@
 		delete m_pCaGrabber;
 		m_pCaGrabber=NULL;
 	}
+	if (m_CustomPacketWriter!=NULL)
+	{
+		LogDebug("del m_CustomPacketWriter");
+		delete m_CustomPacketWriter;
+		m_CustomPacketWriter=NULL;
+	}
 	LogDebug("del done...");
 }
 
@@ -91,10 +100,27 @@
 		m_pRecorder->OnTsPacket(tsPacket);
 		m_pTimeShifting->OnTsPacket(tsPacket);
 		m_pTeletextGrabber->OnTsPacket(tsPacket);
-    m_pCaGrabber->OnTsPacket(tsPacket);
-	}
-	catch(...)
-	{
-		LogDebug("exception in AnalyzeTsPacket");
-	}
-}
\ No newline at end of file
+        m_pCaGrabber->OnTsPacket(tsPacket);
+
+	    if(b_grabCustomPackets)
+	    {
+	      if (m_CustomPacketWriter!=NULL)
+	      {
+            int pid=((tsPacket[1] & 0x1F) <<8)+tsPacket[2];
+	        for (int i=0; i < (int)m_vecCustomPids.size();++i)
+	        {
+	          if(m_vecCustomPids[i]==pid)
+		      {
+		        m_CustomPacketWriter->Write(tsPacket,188);
+		      }
+	        }
+          }
+	    }
+      }
+	  catch(...)
+	  {
+	    LogDebug("exception in AnalyzeTsPacket");
+	  }
+
+}
+
Index: DirectShowFilters/TsWriter/source/TsChannel.h
===================================================================
--- DirectShowFilters/TsWriter/source/TsChannel.h	(revision 27796)
+++ DirectShowFilters/TsWriter/source/TsChannel.h	(working copy)
@@ -27,6 +27,7 @@
 #include "DiskRecorder.h"
 #include "teletextgrabber.h"
 #include "cagrabber.h"
+#include <vector>
 
 // {C564CEB9-FC77-4776-8CB8-96DD87624161}
 
@@ -35,7 +36,7 @@
 public:
 	CTsChannel(LPUNKNOWN pUnk, HRESULT *phr, int id);
 	virtual ~CTsChannel(void);
-  void OnTsPacket(byte* tsPacket);
+    void OnTsPacket(byte* tsPacket);
 	int Handle() { return m_id;}
 
 	CVideoAnalyzer* m_pVideoAnalyzer;
@@ -43,6 +44,10 @@
 	CDiskRecorder*	m_pRecorder;
 	CDiskRecorder*	m_pTimeShifting;
 	CTeletextGrabber*	m_pTeletextGrabber;
-  CCaGrabber*     m_pCaGrabber;
+    CCaGrabber*     m_pCaGrabber;
+    FileWriter*     m_CustomPacketWriter;
+	bool b_grabCustomPackets;
+	vector<int> m_vecCustomPids;
+	typedef vector<int>::iterator* ivecCustomPids;
 	int m_id;
 };
Index: DirectShowFilters/TsWriter/source/TsWriter.cpp
===================================================================
--- DirectShowFilters/TsWriter/source/TsWriter.cpp	(revision 27796)
+++ DirectShowFilters/TsWriter/source/TsWriter.cpp	(working copy)
@@ -322,6 +322,7 @@
 
 void CMpTsFilterPin::OnTsPacket(byte* tsPacket)
 {
+	
 	m_pWriterFilter->AnalyzeTsPacket(tsPacket);
 }
 
@@ -394,7 +395,7 @@
 	delete m_pChannelScanner;
 	delete m_pEpgScanner;
 	delete m_pChannelLinkageScanner;
-	delete m_rawPaketWriter;
+ 	delete m_rawPaketWriter;
   CAutoLock lock(&m_Lock);
   for (int i=0; i < (int)m_vecChannels.size();++i)
   {
@@ -503,13 +504,14 @@
 	try
 	{
     CAutoLock lock(&m_Lock);
-    for (int i=0; i < (int)m_vecChannels.size();++i)
+	for (int i=0; i < (int)m_vecChannels.size();++i)
     {
       m_vecChannels[i]->OnTsPacket(tsPacket);
     }
 		m_pChannelScanner->OnTsPacket(tsPacket);
-		m_pEpgScanner->OnTsPacket(tsPacket);
+	 	m_pEpgScanner->OnTsPacket(tsPacket);
 		m_pChannelLinkageScanner->OnTsPacket(tsPacket);
+	  // Check if custom PID Grabber is enabled
 	}
 	catch(...)
 	{
@@ -695,6 +697,9 @@
   if (pChannel==NULL) return S_OK;
 
   b_dumpRawPakets=false;
+ 
+
+
   if (DumpRawTS())
   {
     b_dumpRawPakets=true;
@@ -705,18 +710,29 @@
     LogDebug(L"Setting name for raw packet dump file to %s", fileName.c_str());
     m_rawPaketWriter->SetFileName(fileName.c_str());
   }
+
   pChannel->m_pTimeShifting->SetFileNameW(pwszFileName);
   return S_OK;
 }
+
 STDMETHODIMP CMpTs::TimeShiftStart( int handle )
 {
   CTsChannel* pChannel=GetTsChannel(handle);
   if (pChannel==NULL) return S_OK;
+  
+  //Added to open file for custom PID grabber
+  if(pChannel->b_grabCustomPackets)
+  {
+    pChannel->m_CustomPacketWriter->OpenFile();
+    LogDebug("Custom Data grabber file created");
+  }
+ 
   if (b_dumpRawPakets)
   {
-	  m_rawPaketWriter->OpenFile();
+    m_rawPaketWriter->OpenFile();
     LogDebug("Raw packet dump file created. Now dumping raw packets to dump file");
   }
+  
   if (pChannel->m_pTimeShifting->Start())
 		return S_OK;
 	else
@@ -727,6 +743,13 @@
 {
   CTsChannel* pChannel=GetTsChannel(handle);
   if (pChannel==NULL) return S_OK;
+   if(pChannel->b_grabCustomPackets)
+   {
+     pChannel->m_CustomPacketWriter->CloseFile();
+	 pChannel->m_vecCustomPids.clear();
+	 LogDebug("Custom file closed");
+   }
+
   if (b_dumpRawPakets)
   {
 	  m_rawPaketWriter->CloseFile();
@@ -739,9 +762,15 @@
 STDMETHODIMP CMpTs:: TimeShiftReset( int handle )
 {
   CTsChannel* pChannel=GetTsChannel(handle);
-  if (pChannel==NULL) return S_OK;
+  if (pChannel==NULL) return S_OK;  
+ if(pChannel->b_grabCustomPackets)
+ {
+  pChannel->m_CustomPacketWriter->CloseFile();
+  pChannel->m_CustomPacketWriter->OpenFile();
+ }
   if (b_dumpRawPakets)
   {
+	
 	  m_rawPaketWriter->CloseFile();
 	  m_rawPaketWriter->OpenFile();
     LogDebug("Raw packet dump file reset");
@@ -858,8 +887,7 @@
 	return pChannel->m_pCaGrabber->Reset( );
 }
 
-STDMETHODIMP CMpTs::GetStreamQualityCounters(int handle, int* totalTsBytes, int* totalRecordingBytes, 
-      int* TsDiscontinuity, int* recordingDiscontinuity)
+STDMETHODIMP CMpTs::GetStreamQualityCounters(int handle, int* totalTsBytes, int* totalRecordingBytes, int* TsDiscontinuity, int* recordingDiscontinuity)
 {
   CTsChannel* pChannel=GetTsChannel(handle);
   if (pChannel==NULL) return S_FALSE;
@@ -882,7 +910,6 @@
     return S_FALSE;
 }
 
-
 STDMETHODIMP CMpTs::TimeShiftSetChannelType(int handle, int channelType)
 {
   CTsChannel* pChannel=GetTsChannel(handle);
@@ -890,4 +917,22 @@
 	pChannel->m_pRecorder->SetChannelType(channelType);
 	pChannel->m_pTimeShifting->SetChannelType(channelType);
 	return S_OK;
+}
+
+STDMETHODIMP CMpTs::AddPidtoCustomData(int handle, int pid)
+{
+    CTsChannel* pChannel=GetTsChannel(handle);
+    if (pChannel==NULL) return S_OK;
+    LogDebug("Added CustomPid %x",pid);
+	pChannel->m_vecCustomPids.push_back(pid);
+	return S_OK;
+}
+
+STDMETHODIMP CMpTs::SetCustomDataFilename(int handle, wchar_t* pwszFileName)
+{
+    CTsChannel* pChannel=GetTsChannel(handle);
+    if (pChannel==NULL) return S_OK;
+	pChannel->m_CustomPacketWriter->SetFileName(pwszFileName);
+	pChannel->b_grabCustomPackets = true;
+	return S_OK;
 }
\ No newline at end of file
Index: DirectShowFilters/TsWriter/source/TsWriter.h
===================================================================
--- DirectShowFilters/TsWriter/source/TsWriter.h	(revision 27796)
+++ DirectShowFilters/TsWriter/source/TsWriter.h	(working copy)
@@ -29,6 +29,7 @@
 #include "channellinkagescanner.h"
 #include "tschannel.h"
 #include "videoaudioobserver.h"
+#include "MultiFileWriter.h"
 #include <map>
 #include <vector>
 using namespace std;
@@ -45,9 +46,8 @@
 DECLARE_INTERFACE_(ITSFilter, IUnknown)
 {
 	STDMETHOD(AddChannel)(THIS_ int* handle)PURE;
-  STDMETHOD(DeleteChannel)(THIS_ int handle)PURE;
-  STDMETHOD(DeleteAllChannels)()PURE;
-
+    STDMETHOD(DeleteChannel)(THIS_ int handle)PURE;
+    STDMETHOD(DeleteAllChannels)()PURE;
 	STDMETHOD(AnalyzerSetVideoPid)(THIS_ int handle, int videoPid)PURE;
 	STDMETHOD(AnalyzerGetVideoPid)(THIS_ int handle,  int* videoPid)PURE;
 	STDMETHOD(AnalyzerSetAudioPid)(THIS_ int handle,  int audioPid)PURE;
@@ -55,19 +55,14 @@
 	STDMETHOD(AnalyzerIsVideoEncrypted)(THIS_ int handle,  int* yesNo)PURE;
 	STDMETHOD(AnalyzerIsAudioEncrypted)(THIS_ int handle,  int* yesNo)PURE;
 	STDMETHOD(AnalyzerReset)(THIS_ int handle )PURE;
-
-	
-	STDMETHOD(PmtSetPmtPid)(THIS_ int handle,  int pmtPid, long serviceId);
-	STDMETHOD(PmtSetCallBack)(THIS_ int handle,   IPMTCallback* callback);
-	STDMETHOD(PmtGetPMTData) (THIS_ int handle,   BYTE *pmtData);
-
-	
-  STDMETHOD(RecordSetRecordingFileNameW)(THIS_ int handle,wchar_t* pwszFileName)PURE;
-  STDMETHOD(RecordStartRecord)(THIS_ int handle)PURE;
-  STDMETHOD(RecordStopRecord)(THIS_ int handle)PURE;
+	STDMETHOD(PmtSetPmtPid)(THIS_ int handle,  int pmtPid, long serviceId)PURE;
+	STDMETHOD(PmtSetCallBack)(THIS_ int handle,   IPMTCallback* callback)PURE;
+	STDMETHOD(PmtGetPMTData) (THIS_ int handle,   BYTE *pmtData)PURE;
+    STDMETHOD(RecordSetRecordingFileNameW)(THIS_ int handle,wchar_t* pwszFileName)PURE;
+    STDMETHOD(RecordStartRecord)(THIS_ int handle)PURE;
+    STDMETHOD(RecordStopRecord)(THIS_ int handle)PURE;
 	STDMETHOD(RecordSetPmtPid)(THIS_ int handle,int mtPid,int serviceId,byte* pmtData,int pmtLength)PURE;
 	STDMETHOD(RecordSetVideoAudioObserver)(THIS_ int handle, IVideoAudioObserver* callback)PURE;
-
 	STDMETHOD(TimeShiftSetTimeShiftingFileNameW)(THIS_ int handle, wchar_t* pwszFileName)PURE;
 	STDMETHOD(TimeShiftStart)(THIS_ int handle )PURE;
 	STDMETHOD(TimeShiftStop)(THIS_ int handle )PURE;
@@ -78,20 +73,17 @@
 	STDMETHOD(TimeShiftSetParams) (THIS_ int handle, int minFiles, int maxFiles, ULONG chunkSize) PURE;
 	STDMETHOD(TimeShiftGetCurrentFilePosition) (THIS_ int handle,__int64 * position, long * bufferId) PURE;
 	STDMETHOD(SetVideoAudioObserver)(THIS_ int handle, IVideoAudioObserver* callback)PURE;
-
 	STDMETHOD(TTxStart)(THIS_ int handle)PURE;
 	STDMETHOD(TTxStop)(THIS_ int handle )PURE;
 	STDMETHOD(TTxSetTeletextPid)(THIS_ int handle,int teletextPid)PURE;
 	STDMETHOD(TTxSetCallBack)(THIS_ int handle,ITeletextCallBack* callback)PURE;
-
-  STDMETHOD(CaSetCallBack)(THIS_ int handle,ICACallback* callback)PURE;
+    STDMETHOD(CaSetCallBack)(THIS_ int handle,ICACallback* callback)PURE;
 	STDMETHOD(CaGetCaData) (THIS_ int handle,BYTE *caData)PURE;
 	STDMETHOD(CaReset)(THIS_ int handle)PURE;
-
-  STDMETHOD(GetStreamQualityCounters)(THIS_ int handle, int* totalTsBytes, int* totalRecordingBytes, 
-      int* TsDiscontinuity, int* recordingDiscontinuity)PURE;
-  
+    STDMETHOD(GetStreamQualityCounters)(THIS_ int handle, int* totalTsBytes, int* totalRecordingBytes, int* TsDiscontinuity, int* recordingDiscontinuity)PURE;
     STDMETHOD(TimeShiftSetChannelType)(THIS_ int handle, int channelType)PURE;
+	STDMETHOD(AddPidtoCustomData)(THIS_ int handle, int pid)PURE;
+	STDMETHOD(SetCustomDataFilename)(THIS_ int handle, wchar_t* pwszFileName)PURE;
 };
 
 // Main filter object
@@ -149,6 +141,8 @@
 private:
 	CCritSec		m_section;
 	FileWriter *m_rawPaketWriter;
+	
+
 };
 
 
@@ -165,8 +159,10 @@
     CCritSec 		m_ReceiveLock;         // Sublock for received samples
 public:
     DECLARE_IUNKNOWN
+	STDMETHODIMP AddPidtoCustomData(int handle, int pid);
+	STDMETHODIMP SetCustomDataFilename(int handle, wchar_t* pwszFileName);
 
-		STDMETHODIMP AddChannel( int* handle);
+	STDMETHODIMP AddChannel( int* handle);
     STDMETHODIMP DeleteChannel( int handle);
     STDMETHODIMP DeleteAllChannels();
 
@@ -199,7 +195,6 @@
 		STDMETHODIMP TimeShiftSetParams(int handle, int minFiles, int maxFiles, ULONG chunkSize) ;
 		STDMETHODIMP TimeShiftGetCurrentFilePosition(int handle,__int64 * position,long * bufferId);
 		STDMETHODIMP SetVideoAudioObserver(int handle, IVideoAudioObserver* callback);
-
 		STDMETHODIMP TTxStart( int handle);
 		STDMETHODIMP TTxStop( int handle );
 		STDMETHODIMP TTxSetTeletextPid( int handle,int teletextPid);
@@ -221,13 +216,14 @@
 private:
     // Overriden to say what interfaces we support where
 		CTsChannel* GetTsChannel(int handle);	
-    STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void ** ppv);
+        STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void ** ppv);
 		CChannelScan*   m_pChannelScanner;
-		CEpgScanner*		m_pEpgScanner;
-		FileWriter* m_rawPaketWriter;
+		CEpgScanner*	m_pEpgScanner;
+		FileWriter*     m_rawPaketWriter;
 		bool b_dumpRawPakets;
 		CChannelLinkageScanner* m_pChannelLinkageScanner;
 		vector<CTsChannel*> m_vecChannels;
-    typedef vector<CTsChannel*>::iterator ivecChannels;
+        typedef vector<CTsChannel*>::iterator ivecChannels;
+		
 		int m_id;
 };
Index: TvEngine3/TVLibrary/TvControl/Controller.cs
===================================================================
--- TvEngine3/TVLibrary/TvControl/Controller.cs	(revision 27796)
+++ TvEngine3/TVLibrary/TvControl/Controller.cs	(working copy)
@@ -726,6 +726,16 @@
     TvResult StartTimeShifting(ref IUser user, ref string fileName);
 
     /// <summary>
+    /// Start timeshifting.
+    /// </summary>
+    /// <param name="user">The user.</param>
+    /// <param name="fileName">Name of the timeshiftfile.</param>
+    /// <returns>
+    /// TvResult indicating whether method succeeded
+    /// </returns>
+    TvResult StartTimeShiftingWithCustom(ref IUser user, ref string fileName, ref string CustomFileName, ref List<int> Pids);
+
+    /// <summary>
     /// Stops the card.
     /// </summary>
     /// <param name="user">The user.</param>
@@ -783,12 +793,53 @@
     /// </returns>
     TvResult StartTimeShifting(ref IUser user, int idChannel, out VirtualCard card);
 
+    /// <summary>
+    /// Start timeshifting on a specific channel
+    /// </summary>
+    /// <param name="user">user credentials.</param>
+    /// <param name="idChannel">The id channel.</param>
+    /// <param name="card">returns on which card timeshifting is started</param>
+    /// <param name="forceCardId">Indicated, if the card should be forced</param>
+    /// <param name="CustomFileName">CustomFilename</param>
+    /// <param name="Pids">List of Pids</param>
+    /// <returns>
+    /// TvResult indicating whether method succeeded
+    /// </returns>
+    TvResult StartTimeShiftingWithCustom(ref IUser user, int idChannel, out VirtualCard card, bool forceCardId,string CustomFileName, List<int> Pids);
 
     /// <summary>
+    /// Start timeshifting on a specific channel
+    /// </summary>
+    /// <param name="user">user credentials.</param>
+    /// <param name="idChannel">The id channel.</param>
+    /// <param name="card">returns on which card timeshifting is started</param>
+    /// <param name="cardChanged">indicates if card was changed</param>
+    /// <param name="CustomFileName">CustomFilename</param>
+    /// <param name="Pids">List of Pids</param>
+    /// <returns>
+    /// TvResult indicating whether method succeeded
+    /// </returns>
+    TvResult StartTimeShiftingWithCustom(ref IUser user, int idChannel, out VirtualCard card, out bool cardChanged, string CustomFileName, List<int> Pids);
+
+    /// <summary>
+    /// Start timeshifting on a specific channel
+    /// </summary>
+    /// <param name="user">user credentials.</param>
+    /// <param name="idChannel">The id channel.</param>
+    /// <param name="card">returns on which card timeshifting is started</param>
+    /// <param name="CustomFileName">CustomFilename</param>
+    /// <param name="Pids">List of Pids</param>
+    /// <returns>
+    /// TvResult indicating whether method succeeded
+    /// </returns>
+    TvResult StartTimeShiftingWithCustom(ref IUser user, int idChannel, out VirtualCard card, string CustomFileName, List<int> Pids);
+
+    /// <summary>
     /// Stops the time shifting.
     /// </summary>
     /// <param name="user">user credentials.</param>
     /// <param name="reason">reason why timeshifting is stopped.</param>
+    /// 
     /// <returns>true if success otherwise false</returns>
     bool StopTimeShifting(ref IUser user, TvStoppedReason reason);
 
Index: TvEngine3/TVLibrary/TvControl/TvServer.cs
===================================================================
--- TvEngine3/TVLibrary/TvControl/TvServer.cs	(revision 27796)
+++ TvEngine3/TVLibrary/TvControl/TvServer.cs	(working copy)
@@ -348,8 +348,85 @@
       return TvResult.UnknownError;
     }
 
+//Custom TimeShifter
 
     /// <summary>
+    /// Start timeshifting on a specific channel
+    /// </summary>
+    /// <param name="user">The user.</param>
+    /// <param name="idChannel">id of the channel</param>
+    /// <param name="card">returns on which card timeshifting is started</param>
+    /// <returns>
+    /// TvResult indicating whether method succeeded
+    /// </returns>
+    public TvResult StartTimeShiftingWithCustom(ref IUser user, int idChannel, out VirtualCard card, string CustomFileName, List<int> Pids)
+    {
+        card = null;
+        try
+        {
+            TvResult result = RemoteControl.Instance.StartTimeShiftingWithCustom(ref user, idChannel, out card, CustomFileName, Pids);
+            return result;
+        }
+        catch (Exception)
+        {
+            HandleFailure();
+        }
+        return TvResult.UnknownError;
+    }
+
+    /// <summary>
+    /// Start timeshifting on a specific channel
+    /// </summary>
+    /// <param name="user">The user.</param>
+    /// <param name="idChannel">id of the channel</param>
+    /// <param name="card">returns on which card timeshifting is started</param>
+    /// <param name="cardChanged">indicates if card was changed</param>
+    /// <returns>
+    /// TvResult indicating whether method succeeded
+    /// </returns>
+    public TvResult StartTimeShiftingWithCustom(ref IUser user, int idChannel, out VirtualCard card, out bool cardChanged, string CustomFileName, List<int> Pids)
+    {
+        card = null;
+        cardChanged = false;
+        try
+        {
+            TvResult result = RemoteControl.Instance.StartTimeShiftingWithCustom(ref user, idChannel, out card, out cardChanged, CustomFileName, Pids);
+            return result;
+        }
+        catch (Exception)
+        {
+            HandleFailure();
+        }
+        return TvResult.UnknownError;
+    }
+
+    /// <summary>
+    /// Start timeshifting on a specific channel
+    /// </summary>
+    /// <param name="user">The user.</param>
+    /// <param name="idChannel">id of the channel</param>
+    /// <param name="card">returns on which card timeshifting is started</param>
+    /// <param name="forceCardId">Indicated, if the card should be forced</param>
+    /// <returns>
+    /// TvResult indicating whether method succeeded
+    /// </returns>
+    public TvResult StartTimeShiftingWithCustom(ref IUser user, int idChannel, out VirtualCard card, bool forceCardId, string CustomFileName, List<int> Pids)
+    {
+        card = null;
+        try
+        {
+            TvResult result = RemoteControl.Instance.StartTimeShiftingWithCustom(ref user, idChannel, out card, forceCardId, CustomFileName, Pids);
+            return result;
+        }
+        catch (Exception)
+        {
+            HandleFailure();
+        }
+        return TvResult.UnknownError;
+    }
+      
+// Custom FileShifter
+      /// <summary>
     /// Checks if the schedule specified is currently being recorded and ifso
     /// returns on which card
     /// </summary>
Index: TvEngine3/TVLibrary/TvLibrary.Interfaces/Interfaces/ITvSubChannel.cs
===================================================================
--- TvEngine3/TVLibrary/TvLibrary.Interfaces/Interfaces/ITvSubChannel.cs	(revision 27796)
+++ TvEngine3/TVLibrary/TvLibrary.Interfaces/Interfaces/ITvSubChannel.cs	(working copy)
@@ -117,6 +117,14 @@
     /// <param name="fileName">filename used for the timeshiftbuffer</param>
     /// <returns>true if succeeded else false</returns>
     bool StartTimeShifting(string fileName);
+    /// <summary>
+    /// Starts timeshifting. Note card has to be tuned first
+    /// </summary>
+    /// <param name="fileName">filename used for the timeshiftbuffer</param>
+    /// <param name="CustomFileName">Custom Filename</param>
+    /// <param name="Pids">List of Pids</param>
+    /// <returns>true if succeeded else false</returns>
+    bool StartTimeShiftingWithCustom(string fileName, string CustomFileName, List<int> Pids);
 
     /// <summary>
     /// Stops timeshifting
Index: TvEngine3/TVLibrary/TvLibrary.sln
===================================================================
--- TvEngine3/TVLibrary/TvLibrary.sln	(revision 27796)
+++ TvEngine3/TVLibrary/TvLibrary.sln	(working copy)
@@ -5,8 +5,6 @@
 EndProject
 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Library", "Library", "{E5B37E07-6E84-4F14-859D-69A40E871034}"
 EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "TestApps", "TestApps", "{CB80D13D-DB70-4292-A2C1-C9D0360D214C}"
-EndProject
 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Database", "Database", "{2D534797-AC32-428E-9E36-A6DDFE3E4229}"
 EndProject
 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Setup GUI", "Setup GUI", "{1481FA11-87E9-4850-AEAD-5E47BDF718BF}"
@@ -33,8 +31,6 @@
 EndProject
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TVLibrary", "TVLibrary\TVLibrary.csproj", "{59C2EBC8-0FEA-4B2E-B5D1-476347332331}"
 EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestApp", "TestApp\TestApp.csproj", "{E9D3F443-A654-4D94-BBAA-080362D25D7C}"
-EndProject
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TvService", "TvService\TvService.csproj", "{3BE4F3AA-36EB-4956-B000-E29C74FC6AB0}"
 	ProjectSection(ProjectDependencies) = postProject
 		{AD20D519-D1AF-484E-ADDE-251F7CA912D9} = {AD20D519-D1AF-484E-ADDE-251F7CA912D9}
@@ -116,12 +112,6 @@
 		{59C2EBC8-0FEA-4B2E-B5D1-476347332331}.Release|Any CPU.Build.0 = Release|Any CPU
 		{59C2EBC8-0FEA-4B2E-B5D1-476347332331}.Release|x86.ActiveCfg = Release|x86
 		{59C2EBC8-0FEA-4B2E-B5D1-476347332331}.Release|x86.Build.0 = Release|x86
-		{E9D3F443-A654-4D94-BBAA-080362D25D7C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
-		{E9D3F443-A654-4D94-BBAA-080362D25D7C}.Debug|Any CPU.Build.0 = Debug|Any CPU
-		{E9D3F443-A654-4D94-BBAA-080362D25D7C}.Debug|x86.ActiveCfg = Debug|x86
-		{E9D3F443-A654-4D94-BBAA-080362D25D7C}.Release|Any CPU.ActiveCfg = Release|Any CPU
-		{E9D3F443-A654-4D94-BBAA-080362D25D7C}.Release|Any CPU.Build.0 = Release|Any CPU
-		{E9D3F443-A654-4D94-BBAA-080362D25D7C}.Release|x86.ActiveCfg = Release|x86
 		{3BE4F3AA-36EB-4956-B000-E29C74FC6AB0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 		{3BE4F3AA-36EB-4956-B000-E29C74FC6AB0}.Debug|Any CPU.Build.0 = Debug|Any CPU
 		{3BE4F3AA-36EB-4956-B000-E29C74FC6AB0}.Debug|x86.ActiveCfg = Debug|x86
@@ -309,7 +299,6 @@
 		{AE752FB4-7450-4150-9BAD-19EFA9D2AC37} = {E5B37E07-6E84-4F14-859D-69A40E871034}
 		{954F9929-7FDA-4F59-88E3-FD2B9A7B6E6E} = {E5B37E07-6E84-4F14-859D-69A40E871034}
 		{CE009BFA-5EF6-4153-B2A1-2FA79698A9AE} = {E5B37E07-6E84-4F14-859D-69A40E871034}
-		{E9D3F443-A654-4D94-BBAA-080362D25D7C} = {CB80D13D-DB70-4292-A2C1-C9D0360D214C}
 		{0FD8DEAE-37A4-49CC-A7BE-E86E0E0D85BD} = {2D534797-AC32-428E-9E36-A6DDFE3E4229}
 		{58C35C9D-F18D-40F2-8024-24E50D01E9C5} = {2D534797-AC32-428E-9E36-A6DDFE3E4229}
 		{FF9AAD68-BBE0-41F7-9183-F2B8474B9224} = {1481FA11-87E9-4850-AEAD-5E47BDF718BF}
Index: TvEngine3/TVLibrary/TVLibrary/Implementations/Analog/Graphs/Analog/AnalogSubChannel.cs
===================================================================
--- TvEngine3/TVLibrary/TVLibrary/Implementations/Analog/Graphs/Analog/AnalogSubChannel.cs	(revision 27796)
+++ TvEngine3/TVLibrary/TVLibrary/Implementations/Analog/Graphs/Analog/AnalogSubChannel.cs	(working copy)
@@ -144,7 +144,10 @@
     #endregion
 
     #region Timeshifting - Recording methods
-
+    protected override bool OnStartTimeShiftingWithCustom(string fileName, string CustomFileName, List<int> Pids)
+    {
+        throw new NotImplementedException();
+    }
     /// <summary>
     /// sets the filename used for timeshifting
     /// </summary>
Index: TvEngine3/TVLibrary/TVLibrary/Implementations/Analog/Graphs/HDPVR/HDPVRChannel.cs
===================================================================
--- TvEngine3/TVLibrary/TVLibrary/Implementations/Analog/Graphs/HDPVR/HDPVRChannel.cs	(revision 27796)
+++ TvEngine3/TVLibrary/TVLibrary/Implementations/Analog/Graphs/HDPVR/HDPVRChannel.cs	(working copy)
@@ -189,6 +189,11 @@
 
     #region Timeshifting - Recording methods
 
+    protected override bool OnStartTimeShiftingWithCustom(string fileName, string CustomFileName, List<int> Pids)
+    {
+        throw new NotImplementedException();
+    }
+
     /// <summary>
     /// sets the filename used for timeshifting
     /// </summary>
Index: TvEngine3/TVLibrary/TVLibrary/Implementations/BaseSubChannel.cs
===================================================================
--- TvEngine3/TVLibrary/TVLibrary/Implementations/BaseSubChannel.cs	(revision 27796)
+++ TvEngine3/TVLibrary/TVLibrary/Implementations/BaseSubChannel.cs	(working copy)
@@ -323,8 +323,26 @@
       }
       return false;
     }
-
     /// <summary>
+    /// Starts timeshifting. Note card has to be tuned first
+    /// </summary>
+    /// <param name="fileName">filename used for the timeshiftbuffer</param>
+    /// <returns></returns>
+    public bool StartTimeShiftingWithCustom(string fileName,string CustomFileName, List<int> Pids)
+    {
+        try
+        {
+            return OnStartTimeShiftingWithCustom(fileName,CustomFileName,Pids);
+        }
+        catch (Exception e)
+        {
+            //cleanup
+            Log.Log.WriteFile("StartTimeShifting with Custom failed, cleaning up {0}", e.Message);
+            StopTimeShifting();
+        }
+        return false;
+    }
+    /// <summary>
     /// Stops timeshifting
     /// </summary>
     /// <returns></returns>
@@ -589,6 +607,11 @@
     protected abstract bool OnStartTimeShifting(string fileName);
 
     /// <summary>
+    /// A derrived class should start here the timeshifting on the tv card. It will be called from StartTimeshifting()
+    /// </summary>
+    protected abstract bool OnStartTimeShiftingWithCustom(string fileName,string CustomFileName, List<int> Pids);
+
+    /// <summary>
     /// A derrived class should stop here the timeshifting on the tv card. It will be called from StopTimeshifting()
     /// </summary>
     protected abstract void OnStopTimeShifting();
Index: TvEngine3/TVLibrary/TVLibrary/Implementations/DVB/Graphs/TvDvbChannel.cs
===================================================================
--- TvEngine3/TVLibrary/TVLibrary/Implementations/DVB/Graphs/TvDvbChannel.cs	(revision 27796)
+++ TvEngine3/TVLibrary/TVLibrary/Implementations/DVB/Graphs/TvDvbChannel.cs	(working copy)
@@ -597,7 +597,56 @@
       }
       return (_channelInfo.pids.Count != 0);
     }
+    /// <summary>
+    /// sets the filename used for timeshifting
+    /// </summary>
+    /// <param name="fileName">timeshifting filename</param>
+    protected override bool OnStartTimeShiftingWithCustom(string fileName, string CustomFileName, List<int> Pids)
+    {
+        //if (_channelInfo.pids.Count == 0)
+        if (!PMTreceived)
+        {
+            Log.Log.WriteFile("subch:{0} SetTimeShiftFileName no pmt received. Timeshifting failed", _subChannelId);
+            return false;
+        }
 
+        _timeshiftFileName = fileName;
+        Log.Log.WriteFile("subch:{0} SetTimeShiftFileName:{1}", _subChannelId, fileName);
+        //int hr;
+        if (_tsFilterInterface != null)
+        {
+            Log.Log.WriteFile("Set video / audio observer");
+            _tsFilterInterface.SetVideoAudioObserver(_subChannelIndex, this);
+            _tsFilterInterface.TimeShiftSetParams(_subChannelIndex, _parameters.MinimumFiles, _parameters.MaximumFiles,
+                                                  _parameters.MaximumFileSize);
+            _tsFilterInterface.TimeShiftSetTimeShiftingFileNameW(_subChannelIndex, fileName);
+
+
+            if (CurrentChannel == null)
+            {
+                Log.Log.Error("CurrentChannel is null when trying to start timeshifting");
+                return false;
+            }
+
+            //  Set the channel type (0=tv, 1=radio)
+            _tsFilterInterface.TimeShiftSetChannelType(_subChannelId, (CurrentChannel.IsTv ? 0 : 1));
+
+            Log.Log.WriteFile("subch:{0} SetTimeShiftFileName fill in pids", _subChannelId);
+            _startTimeShifting = false;
+            SetTimeShiftPids();
+            _tsFilterInterface.SetCustomDataFilename(_subChannelIndex, CustomFileName);
+            foreach (int i in Pids)
+            {
+                _tsFilterInterface.AddPidtoCustomData(_subChannelIndex, i);
+            }
+            Log.Log.WriteFile("subch:{0}-{1} tswriter StartTimeshifting...", _subChannelId, _subChannelIndex);
+            _tsFilterInterface.TimeShiftStart(_subChannelIndex);
+
+            _graphState = GraphState.TimeShifting;
+        }
+        return (_channelInfo.pids.Count != 0);
+    }
+
     /// <summary>
     /// Stop recording
     /// </summary>
Index: TvEngine3/TVLibrary/TVLibrary/Interfaces/Analyzer/ITsFilter.cs
===================================================================
--- TvEngine3/TVLibrary/TVLibrary/Interfaces/Analyzer/ITsFilter.cs	(revision 27796)
+++ TvEngine3/TVLibrary/TVLibrary/Interfaces/Analyzer/ITsFilter.cs	(working copy)
@@ -365,5 +365,24 @@
     /// <returns></returns>
     [PreserveSig]
     int TimeShiftSetChannelType(int handle, int channelType);
+    
+    /// <summary>
+    /// Adds a Pid to the Custom Data Watcher
+    /// </summary>
+    /// <param name="handle">Handle of the sub channel</param>
+    /// <param name="pid">Pid</param>
+    /// <returns></returns>
+    [PreserveSig]
+    int AddPidtoCustomData(int handle, int pid);
+
+          /// <summary>
+    /// Sets the Custom Pid Watcher filename
+    /// </summary>
+    /// <param name="handle">Handle of the sub channel</param>
+    /// <param name="fileName">Filename</param>
+    /// <returns></returns>
+    [PreserveSig]
+    int SetCustomDataFilename(int handle, [In, MarshalAs(UnmanagedType.LPWStr)] string fileName);
+
   }
 }
\ No newline at end of file
Index: TvEngine3/TVLibrary/TvService/CardManagement/CardHandler/TimeShifter.cs
===================================================================
--- TvEngine3/TVLibrary/TvService/CardManagement/CardHandler/TimeShifter.cs	(revision 27796)
+++ TvEngine3/TVLibrary/TvService/CardManagement/CardHandler/TimeShifter.cs	(working copy)
@@ -19,6 +19,7 @@
 #endregion
 
 using System;
+using System.Collections.Generic;
 using System.Threading;
 using TvLibrary.Implementations;
 using TvLibrary.Interfaces;
@@ -478,7 +479,166 @@
       Stop(ref user);
       return TvResult.UnknownError;
     }
+    /// <summary>
+    /// Start timeshifting.
+    /// </summary>
+    /// <param name="user">User</param>
+    /// <param name="fileName">Name of the timeshiftfile.</param>
+    /// <returns>TvResult indicating whether method succeeded</returns>
+    public TvResult StartWithCustom(ref IUser user, ref string fileName, ref string CustomFileName, ref List<int> Pids)
+    {
+        try
+        {
+            // Is the card enabled ?
+            if (_cardHandler.DataBaseCard.Enabled == false)
+            {
+                return TvResult.CardIsDisabled;
+            }
 
+            lock (this)
+            {
+                try
+                {
+                    RemoteControl.HostName = _cardHandler.DataBaseCard.ReferencedServer().HostName;
+                    if (!RemoteControl.Instance.CardPresent(_cardHandler.DataBaseCard.IdCard))
+                        return TvResult.CardIsDisabled;
+
+
+                    // Let's verify if hard disk drive has enough free space before we start time shifting. The function automatically handles both local and UNC paths
+                    if (!IsTimeShifting(ref user))
+                    {
+                        ulong FreeDiskSpace = Utils.GetFreeDiskSpace(fileName);
+
+                        TvBusinessLayer layer = new TvBusinessLayer();
+                        UInt32 MaximumFileSize = UInt32.Parse(layer.GetSetting("timeshiftMaxFileSize", "256").Value); // in MB
+                        ulong DiskSpaceNeeded = Convert.ToUInt64(MaximumFileSize);
+                        DiskSpaceNeeded *= 1000000 * 2; // Convert to bytes; 2 times of timeshiftMaxFileSize
+                        if (FreeDiskSpace < DiskSpaceNeeded)
+                        // TimeShifter need at least this free disk space otherwise, it will not start.
+                        {
+                            Stop(ref user);
+                            return TvResult.NoFreeDiskSpace;
+                        }
+                    }
+
+                    Log.Write("card: StartTimeShifting {0} {1} ", _cardHandler.DataBaseCard.IdCard, fileName);
+
+                    if (_cardHandler.IsLocal == false)
+                    {
+                        return RemoteControl.Instance.StartTimeShiftingWithCustom(ref user, ref fileName, ref CustomFileName, ref Pids);
+                    }
+                }
+                catch (Exception)
+                {
+                    Log.Error("card: unable to connect to slave controller at:{0}",
+                              _cardHandler.DataBaseCard.ReferencedServer().HostName);
+                    Stop(ref user);
+                    return TvResult.UnknownError;
+                }
+
+                ITvCardContext context = _cardHandler.Card.Context as ITvCardContext;
+                if (context == null)
+                {
+                    Stop(ref user);
+                    return TvResult.UnknownChannel;
+                }
+
+                context.GetUser(ref user);
+                ITvSubChannel subchannel = _cardHandler.Card.GetSubChannel(user.SubChannel);
+
+                if (subchannel == null)
+                {
+                    Stop(ref user);
+                    return TvResult.UnknownChannel;
+                }
+
+                _subchannel = subchannel;
+
+                Log.Write("card: CAM enabled : {0}", _cardHandler.HasCA);
+
+                if (subchannel is TvDvbChannel)
+                {
+                    if (!((TvDvbChannel)subchannel).PMTreceived)
+                    {
+                        Log.Info("start subch:{0} No PMT received. Timeshifting failed", subchannel.SubChannelId);
+                        Stop(ref user);
+                        return TvResult.UnableToStartGraph;
+                    }
+                }
+
+                if (subchannel is BaseSubChannel)
+                {
+                    ((BaseSubChannel)subchannel).AudioVideoEvent += AudioVideoEventHandler;
+                }
+
+                bool isScrambled;
+                if (subchannel.IsTimeShifting)
+                {
+                    if (!WaitForTimeShiftFile(ref user, out isScrambled))
+                    {
+                        Stop(ref user);
+                        if (isScrambled)
+                        {
+                            return TvResult.ChannelIsScrambled;
+                        }
+                        return TvResult.NoVideoAudioDetected;
+                    }
+
+                    context.OnZap(user);
+                    if (_linkageScannerEnabled)
+                        _cardHandler.Card.StartLinkageScanner(_linkageGrabber);
+                    if (_timeshiftingEpgGrabberEnabled)
+                    {
+                        Channel channel = Channel.Retrieve(user.IdChannel);
+                        if (channel.GrabEpg)
+                            _cardHandler.Card.GrabEpg();
+                        else
+                            Log.Info("TimeshiftingEPG: channel {0} is not configured for grabbing epg",
+                                     channel.DisplayName);
+                    }
+                    return TvResult.Succeeded;
+                }
+
+                bool result = subchannel.StartTimeShiftingWithCustom(fileName,CustomFileName,Pids);
+                if (result == false)
+                {
+                    Stop(ref user);
+                    return TvResult.UnableToStartGraph;
+                }
+
+                fileName += ".tsbuffer";
+                if (!WaitForTimeShiftFile(ref user, out isScrambled))
+                {
+                    Stop(ref user);
+                    if (isScrambled)
+                    {
+                        return TvResult.ChannelIsScrambled;
+                    }
+                    return TvResult.NoVideoAudioDetected;
+                }
+                context.OnZap(user);
+                if (_linkageScannerEnabled)
+                    _cardHandler.Card.StartLinkageScanner(_linkageGrabber);
+                if (_timeshiftingEpgGrabberEnabled)
+                {
+                    Channel channel = Channel.Retrieve(user.IdChannel);
+                    if (channel.GrabEpg)
+                        _cardHandler.Card.GrabEpg();
+                    else
+                        Log.Info("TimeshiftingEPG: channel {0} is not configured for grabbing epg",
+                                 channel.DisplayName);
+                }
+                return TvResult.Succeeded;
+            }
+        }
+        catch (Exception ex)
+        {
+            Log.Write(ex);
+        }
+
+        Stop(ref user);
+        return TvResult.UnknownError;
+    }
     /// <summary>
     /// Stops the time shifting.
     /// </summary>
Index: TvEngine3/TVLibrary/TvService/TVController.cs
===================================================================
--- TvEngine3/TVLibrary/TvService/TVController.cs	(revision 27796)
+++ TvEngine3/TVLibrary/TvService/TVController.cs	(working copy)
@@ -1887,6 +1887,94 @@
       return TvResult.UnknownError;
     }
 
+    /// <summary>
+    /// Start timeshifting.
+    /// </summary>
+    /// <param name="user"></param>
+    /// <param name="fileName">Name of the timeshiftfile.</param>
+    /// <param name="CustomFileName">CustomFileName</param>
+    /// <param name="Pids">Pids</param>
+    /// <returns>
+    /// TvResult indicating whether method succeeded
+    /// </returns>
+    /// 
+    public TvResult StartTimeShiftingWithCustom(ref IUser user, ref string fileName,ref string CustomFileName, ref List<int> Pids)
+    {
+        if (ValidateTvControllerParams(user))
+            return TvResult.UnknownError;
+        try
+        {
+            int cardId = user.CardId;
+            if (false == _cards[cardId].IsLocal)
+            {
+                try
+                {
+                    RemoteControl.HostName = _cards[cardId].DataBaseCard.ReferencedServer().HostName;
+                    return RemoteControl.Instance.StartTimeShiftingWithCustom(ref user, ref fileName, ref CustomFileName, ref Pids);
+                }
+                catch (Exception)
+                {
+                    Log.Error("card: unable to connect to slave controller at:{0}",
+                              _cards[cardId].DataBaseCard.ReferencedServer().HostName);
+                    return TvResult.UnknownError;
+                }
+            }
+
+            Fire(this, new TvServerEventArgs(TvServerEventType.StartTimeShifting, GetVirtualCard(user), (User)user));
+            if (_epgGrabber != null)
+            {
+                _epgGrabber.Stop();
+            }
+
+            bool isTimeShifting;
+            try
+            {
+                isTimeShifting = _cards[cardId].TimeShifter.IsTimeShifting(ref user);
+            }
+            catch (Exception ex)
+            {
+                isTimeShifting = false;
+                Log.Error("Exception in checking  " + ex.Message);
+            }
+            TvResult result = _cards[cardId].TimeShifter.StartWithCustom(ref user, ref fileName, ref CustomFileName, ref Pids);
+            if (result == TvResult.Succeeded)
+            {
+                if (!isTimeShifting)
+                {
+                    Log.Info("user:{0} card:{1} sub:{2} add stream:{3}", user.Name, user.CardId, user.SubChannel, fileName);
+                    if (File.Exists(fileName))
+                    {
+                        _streamer.Start();
+
+                        //  Default to tv
+                        bool isTv = true;
+
+                        ITvSubChannel subChannel = _cards[cardId].Card.GetSubChannel(user.SubChannel);
+
+                        if (subChannel != null && subChannel.CurrentChannel != null)
+                            isTv = subChannel.CurrentChannel.IsTv;
+                        else
+                            Log.Error("SubChannel or CurrentChannel is null when starting streaming");
+
+                        RtspStream stream = new RtspStream(String.Format("stream{0}.{1}", cardId, user.SubChannel), fileName,
+                                                           _cards[cardId].Card, isTv);
+                        _streamer.AddStream(stream);
+                    }
+                    else
+                    {
+                        Log.Write("Controller: streaming: file not found:{0}", fileName);
+                    }
+                }
+            }
+            return result;
+        }
+        catch (Exception ex)
+        {
+            Log.Write(ex);
+        }
+        return TvResult.UnknownError;
+    }
+
     public void StopCard(IUser user)
     {
       if (ValidateTvControllerParams(user))
@@ -2856,7 +2944,312 @@
       return StartTimeShifting(ref user, idChannel, out card, false, out cardChanged);
     }
 
+//Custom TimeShifting
+
     /// <summary>
+    /// Start timeshifting on a specific channel
+    /// </summary>
+    /// <param name="user">user credentials.</param>
+    /// <param name="idChannel">The id channel.</param>
+    /// <param name="card">returns card for which timeshifting is started</param>
+    /// <param name="forceCardId">Indicated, if the card should be forced</param>
+    /// <param name="cardChanged">indicates if card was changed</param>
+    /// <returns>
+    /// TvResult indicating whether method succeeded
+    /// </returns>
+    public TvResult StartTimeShiftingWithCustom(ref IUser user, int idChannel, out VirtualCard card, bool forceCardId,string CustomFileName, List<int> Pids)
+    {
+        bool cardChanged = false;
+        return StartTimeShiftingWithCustom(ref user, idChannel, out card, forceCardId, out cardChanged,CustomFileName,Pids);
+    }
+
+    /// <summary>
+    /// Start timeshifting on a specific channel
+    /// </summary>
+    /// <param name="user">user credentials.</param>
+    /// <param name="idChannel">The id channel.</param>
+    /// <param name="card">returns card for which timeshifting is started</param>
+    /// <param name="forceCardId">Indicated, if the card should be forced</param>
+    /// <param name="cardChanged">indicates if card was changed</param>
+    /// <returns>
+    /// TvResult indicating whether method succeeded
+    /// </returns>
+    public TvResult StartTimeShiftingWithCustom(ref IUser user, int idChannel, out VirtualCard card, bool forceCardId,
+                                      out bool cardChanged,string CustomFileName, List<int> Pids)
+    {
+        cardChanged = false;
+        if (user == null)
+        {
+            card = null;
+            return TvResult.UnknownError;
+        }
+
+        string intialTimeshiftingFilename = "";
+
+        VirtualCard initialCard = null;
+
+        if (user.CardId != -1)
+            initialCard = GetVirtualCard(user);
+
+        if (initialCard != null && initialCard.TimeShiftFileName != null)
+        {
+            intialTimeshiftingFilename = initialCard.TimeShiftFileName;
+        }
+
+        Channel channel = Channel.Retrieve(idChannel);
+        Log.Write("Controller: StartTimeShifting {0} {1}", channel.DisplayName, channel.IdChannel);
+        card = null;
+        if (_epgGrabber != null)
+        {
+            _epgGrabber.Stop();
+        }
+        IUser userCopy = null;
+        try
+        {
+            TvResult result;
+            List<CardDetail> freeCards = _cardAllocation.GetFreeCardsForChannel(_cards, channel, ref user, out result);
+            if (freeCards.Count == 0)
+            {
+                //no free cards available
+                Log.Write("Controller: StartTimeShifting failed:{0}", result);
+
+                if (_epgGrabber != null && AllCardsIdle)
+                {
+                    _epgGrabber.Start();
+                }
+                return result;
+            }
+
+            int maxCards;
+            if (_maxFreeCardsToTry == 0)
+            {
+                maxCards = freeCards.Count;
+            }
+            else
+            {
+                maxCards = Math.Min(_maxFreeCardsToTry, freeCards.Count);
+
+                if (maxCards > freeCards.Count)
+                {
+                    maxCards = freeCards.Count;
+                }
+            }
+
+            Log.Write("Controller: try max {0} of {1} cards for timeshifting", maxCards, freeCards.Count);
+            TvBusinessLayer layer = new TvBusinessLayer();
+            //keep tuning each card until we are succesful                
+            for (int i = 0; i < maxCards; i++)
+            {
+                int nrOfOtherUsersTimeshiftingOnCard = 0;
+                if (i > 0)
+                {
+                    Log.Write("Controller: Timeshifting failed, lets try next available card.");
+                    cardChanged = (maxCards > 1);
+                }
+                userCopy = new User(user.Name, user.IsAdmin);
+
+                CardDetail cardInfo = freeCards[i];
+                userCopy.CardId = cardInfo.Id;
+                if (forceCardId && user.CardId != cardInfo.Id)
+                {
+                    continue;
+                }
+                IChannel tuneChannel = cardInfo.TuningDetail;
+
+                //setup folders
+                if (cardInfo.Card.RecordingFolder == String.Empty)
+                {
+                    cardInfo.Card.RecordingFolder = String.Format(@"{0}\Team MediaPortal\MediaPortal TV Server\recordings",
+                                                                  Environment.GetFolderPath(
+                                                                    Environment.SpecialFolder.CommonApplicationData));
+                    if (!Directory.Exists(cardInfo.Card.RecordingFolder))
+                    {
+                        Log.Write("Controller: creating recording folder {0} for card {0}", cardInfo.Card.RecordingFolder,
+                                  cardInfo.Card.Name);
+                        Directory.CreateDirectory(cardInfo.Card.RecordingFolder);
+                    }
+                }
+                if (cardInfo.Card.TimeShiftFolder == String.Empty)
+                {
+                    cardInfo.Card.TimeShiftFolder = String.Format(
+                      @"{0}\Team MediaPortal\MediaPortal TV Server\timeshiftbuffer",
+                      Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData));
+                    if (!Directory.Exists(cardInfo.Card.TimeShiftFolder))
+                    {
+                        Log.Write("Controller: creating timeshifting folder {0} for card {0}", cardInfo.Card.TimeShiftFolder,
+                                  cardInfo.Card.Name);
+                        Directory.CreateDirectory(cardInfo.Card.TimeShiftFolder);
+                    }
+                }
+
+                //todo : if the owner is changing channel to a new transponder, then kick any leeching users.
+                ITvCardHandler tvcard = _cards[cardInfo.Id];
+                bool isTS = tvcard.TimeShifter.IsAnySubChannelTimeshifting;
+                bool skipCard = false;
+                if (isTS)
+                {
+                    IUser[] users = tvcard.Users.GetUsers();
+                    for (int j = users.Length - 1; j > -1; j--)
+                    {
+                        IUser u = users[j];
+                        if (user.Name.Equals(u.Name))
+                        {
+                            continue;
+                        }
+
+                        IChannel tmpChannel = tvcard.CurrentChannel(ref u);
+
+                        if (tmpChannel == null)
+                        {
+                            tvcard.Users.RemoveUser(u);
+                            //removing inactive user which shouldnt happen, but atleast its better than having timeshfiting fail.
+                            continue;
+                        }
+
+                        bool isDiffTS = tuneChannel.IsDifferentTransponder(tmpChannel);
+
+                        if (isDiffTS)
+                        {
+                            Log.Write("Controller: kicking leech user {0} off card {1} since owner {2} changed transponder", u.Name,
+                                      cardInfo.Card.Name, user.Name);
+                            StopTimeShifting(ref u, TvStoppedReason.OwnerChangedTS);
+                        }
+                        else
+                        {
+                            DVBBaseChannel dvbBaseChannel = tmpChannel as DVBBaseChannel;
+                            if (dvbBaseChannel != null)
+                            {
+                                TuningDetail userChannel = layer.GetTuningDetail(dvbBaseChannel);
+                                bool isOnSameChannel = (idChannel == userChannel.IdChannel);
+
+                                if (isOnSameChannel)
+                                {
+                                    if (tvcard.Users.IsOwner(userCopy))
+                                    {
+                                        if (i < maxCards)
+                                        {
+                                            Log.Write("Controller: skipping card:{0} since other users are present on the same channel.",
+                                                      userCopy.CardId);
+                                            skipCard = true;
+                                            break; //try next card  
+                                        }
+                                    }
+                                    else
+                                    {
+                                        nrOfOtherUsersTimeshiftingOnCard++;
+                                        if (!u.IsAdmin)
+                                        {
+                                            userCopy.SubChannel = u.SubChannel;
+                                        }
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+
+                if (skipCard)
+                {
+                    continue;
+                }
+
+                //tune to the new channel                  
+                result = CardTune(ref userCopy, tuneChannel, channel);
+                if (result != TvResult.Succeeded)
+                {
+                    user.FailedCardId = userCopy.FailedCardId;
+                    StopTimeShifting(ref userCopy);
+                    continue; //try next card            
+                }
+                Log.Info("control2:{0} {1} {2}", userCopy.Name, userCopy.CardId, userCopy.SubChannel);
+                if (!IsTimeShifting(ref userCopy))
+                {
+                    CleanTimeShiftFiles(cardInfo.Card.TimeShiftFolder,
+                                        String.Format("live{0}-{1}.ts", userCopy.CardId, userCopy.SubChannel));
+                }
+                string timeshiftFileName = String.Format(@"{0}\live{1}-{2}.ts", cardInfo.Card.TimeShiftFolder, userCopy.CardId,
+                                                         userCopy.SubChannel);
+
+                //start timeshifting
+                result = StartTimeShiftingWithCustom(ref userCopy, ref timeshiftFileName, ref CustomFileName, ref Pids);
+                if (result != TvResult.Succeeded)
+                {
+                    StopTimeShifting(ref userCopy);
+                    continue; //try next card
+                }
+                Log.Write("Controller: StartTimeShifting started on card:{0} to {1}", userCopy.CardId, timeshiftFileName);
+                card = GetVirtualCard(userCopy);
+                card.NrOfOtherUsersTimeshiftingOnCard = nrOfOtherUsersTimeshiftingOnCard;
+                RemoveUserFromOtherCards(card.Id, userCopy); //only remove user from other cards if new tuning was a success
+                UpdateChannelStatesForUsers();
+
+                if (card != null && card.TimeShiftFileName != null)
+                {
+                    string newTimeshiftingFilename = card.TimeShiftFileName;
+                    cardChanged = (intialTimeshiftingFilename != newTimeshiftingFilename);
+                }
+
+                break; //if we made it to the bottom, then we have a successful timeshifting.
+            }
+
+            if (result != TvResult.Succeeded)
+            {
+                if (_epgGrabber != null && AllCardsIdle)
+                {
+                    _epgGrabber.Start();
+                }
+            }
+
+            return result;
+        }
+        catch (Exception ex)
+        {
+            if (userCopy != null)
+            {
+                user.FailedCardId = userCopy.FailedCardId;
+            }
+            if (_epgGrabber != null && AllCardsIdle)
+            {
+                _epgGrabber.Start();
+            }
+            Log.Write(ex);
+            return TvResult.UnknownError;
+        }
+    }
+
+    /// <summary>
+    /// Start timeshifting on a specific channel
+    /// </summary>
+    /// <param name="user">user credentials.</param>
+    /// <param name="idChannel">The id channel.</param>
+    /// <param name="card">returns card for which timeshifting is started</param>    
+    /// <returns>
+    /// TvResult indicating whether method succeeded
+    /// </returns>
+    public TvResult StartTimeShiftingWithCustom(ref IUser user, int idChannel, out VirtualCard card, string CustomFileName, List<int> Pids)
+    {
+        bool cardChanged = false;
+        return StartTimeShiftingWithCustom(ref user, idChannel, out card, false, out cardChanged,CustomFileName,Pids);
+    }
+
+    /// <summary>
+    /// Start timeshifting on a specific channel
+    /// </summary>
+    /// <param name="user">user credentials.</param>
+    /// <param name="idChannel">The id channel.</param>
+    /// <param name="card">returns card for which timeshifting is started</param>
+    /// <param name="cardChanged">indicates if card was changed</param>
+    /// <returns>
+    /// TvResult indicating whether method succeeded
+    /// </returns>
+    public TvResult StartTimeShiftingWithCustom(ref IUser user, int idChannel, out VirtualCard card, out bool cardChanged,string CustomFileName, List<int> Pids)
+    {
+        return StartTimeShiftingWithCustom(ref user, idChannel, out card, false, out cardChanged, CustomFileName, Pids);
+    }
+
+//End Custom Fileshifting
+
+    /// <summary>
     /// Checks if the schedule specified is currently being recorded and ifso
     /// returns on which card
     /// </summary>
