/// <summary>
        /// Starts recording.
        /// </summary>
        /// <param name="user">User</param>
        /// <param name="fileName">Name of the recording file.</param>
        /// <returns></returns>
        public TvResult Start(ref IUser user, ref string fileName)
        {
            TvResult result = TvResult.UnknownError;

            try
            {
#if DEBUG
                if (File.Exists(@"\failrec_" + _cardHandler.DataBaseCard.IdCard))
                {
                    throw new Exception("failed rec. on purpose");
                }
#endif
                if (IsTuneCancelled())
                {
                    result = TvResult.TuneCancelled;
                    return(result);
                }

                _eventTimeshift.Reset();
                if (_cardHandler.DataBaseCard.Enabled)
                {
                    var context = _cardHandler.Card.Context as TvCardContext;
                    if (context != null)
                    {
                        context.GetUser(ref user);
                        ITvSubChannel subchannel = GetSubChannel(user.SubChannel);
                        if (subchannel != null)
                        {
                            _subchannel = subchannel;

                            fileName = fileName.Replace("\r\n", " ");
                            fileName = Path.ChangeExtension(fileName, ".ts");

                            bool useErrorDetection = true;
                            if (useErrorDetection)
                            {
                                // fix mantis 0002807: A/V detection for recordings is not working correctly
                                // reset the events ONLY before attaching the observer, at a later position it can already miss the a/v callback.
                                if (IsTuneCancelled())
                                {
                                    result = TvResult.TuneCancelled;
                                    return(result);
                                }
                                _eventVideo.Reset();
                                _eventAudio.Reset();
                                Log.Debug("Recorder.start add audioVideoEventHandler");
                                AttachAudioVideoEventHandler(subchannel);
                            }

                            Log.Write("card: StartRecording {0} {1}", _cardHandler.DataBaseCard.IdCard, fileName);
                            bool recStarted = subchannel.StartRecording(fileName);
                            if (recStarted)
                            {
                                fileName      = subchannel.RecordingFileName;
                                context.Owner = user;
                                if (useErrorDetection)
                                {
                                    bool isScrambled;
                                    if (WaitForFile(ref user, out isScrambled))
                                    {
                                        result = TvResult.Succeeded;
                                    }
                                    else
                                    {
                                        DetachAudioVideoEventHandler(subchannel);
                                        result = GetFailedTvResult(isScrambled);
                                    }
                                }
                            }
                        }
                    }
                }
                else
                {
                    result = TvResult.CardIsDisabled;
                }
                if (result == TvResult.Succeeded)
                {
                    StartTimeShiftingEPGgrabber(user);
                }
            }
            catch (Exception ex)
            {
                Log.Write(ex);
                result = TvResult.UnknownError;
            }
            finally
            {
                _eventTimeshift.Set();
                _cancelled = false;
                if (result != TvResult.Succeeded)
                {
                    HandleFailedRecording(ref user, fileName);
                }
            }
            return(result);
        }
        /// <summary>
        /// Starts recording.
        /// </summary>
        /// <param name="user">User</param>
        /// <param name="fileName">Name of the recording file.</param>
        /// <param name="contentRecording">if true then create a content recording else a reference recording</param>
        /// <param name="startTime">not used</param>
        /// <returns></returns>
        public TvResult Start(ref IUser user, ref string fileName, bool contentRecording, long startTime)
        {
            bool useErrorDetection = false;

            try
            {
                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);
                        }

                        if (_cardHandler.IsLocal == false)
                        {
                            return(RemoteControl.Instance.StartRecording(ref user, ref fileName, contentRecording, startTime));
                        }
                    }
                    catch (Exception)
                    {
                        Log.Error("card: unable to connect to slave controller at:{0}",
                                  _cardHandler.DataBaseCard.ReferencedServer().HostName);
                        return(TvResult.UnknownError);
                    }

                    TvCardContext context = _cardHandler.Card.Context as TvCardContext;
                    if (context == null)
                    {
                        return(TvResult.UnknownChannel);
                    }

                    context.GetUser(ref user);
                    ITvSubChannel subchannel = _cardHandler.Card.GetSubChannel(user.SubChannel);
                    if (subchannel == null)
                    {
                        return(TvResult.UnknownChannel);
                    }

                    _subchannel = subchannel;

                    //gibman
                    // RecordingFormat 0 = ts
                    // RecordingFormat 1 = mpeg
                    fileName = fileName.Replace("\r\n", " ");
                    fileName = System.IO.Path.ChangeExtension(fileName, ".ts");

                    useErrorDetection = true;

                    if (useErrorDetection)
                    {
                        // fix mantis 0002807: A/V detection for recordings is not working correctly
                        // reset the events ONLY before attaching the observer, at a later position it can already miss the a/v callback.
                        _eventVideo.Reset();
                        _eventAudio.Reset();
                        Log.Debug("Recorder.start add audioVideoEventHandler");
                        ((BaseSubChannel)subchannel).AudioVideoEvent += AudioVideoEventHandler;
                    }

                    Log.Write("card: StartRecording {0} {1}", _cardHandler.DataBaseCard.IdCard, fileName);
                    bool result = subchannel.StartRecording(fileName);
                    bool isScrambled;
                    if (result)
                    {
                        fileName      = subchannel.RecordingFileName;
                        context.Owner = user;
                        if (useErrorDetection)
                        {
                            if (!WaitForRecordingFile(ref user, out isScrambled))
                            {
                                Log.Write("card: Recording failed! {0} {1}", _cardHandler.DataBaseCard.IdCard, fileName);

                                string cardRecordingFolderName = _cardHandler.DataBaseCard.RecordingFolder;
                                Stop(ref user);
                                _cardHandler.Users.RemoveUser(user);

                                string recordingfolderName = System.IO.Path.GetDirectoryName(fileName);
                                if (recordingfolderName == cardRecordingFolderName)
                                {
                                    Utils.FileDelete(fileName);
                                }
                                else
                                {
                                    // delete 0-byte file in case of error
                                    Utils.DeleteFileAndEmptyDirectory(fileName);
                                }
                                ((BaseSubChannel)subchannel).AudioVideoEvent -= AudioVideoEventHandler;
                                if (isScrambled)
                                {
                                    return(TvResult.ChannelIsScrambled);
                                }
                                return(TvResult.NoVideoAudioDetected);
                            }
                            ((BaseSubChannel)subchannel).AudioVideoEvent -= AudioVideoEventHandler;
                        }
                    }
                    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);
            }
            return(TvResult.UnknownError);
        }