//Request rqInProgress;
        public void ScheduleRecording(RecordingRequest rr, EventWaitHandle _ewh)
        {
            // Store pointer to handle locally
            ewhScheduleRecording = _ewh;
            ScheduleInitialFailureResult = new RecordingResult();  // For now, set shared result to assume failure  (in case of time outs etc)
            ScheduleInitialFailureResult.ErrorMessage = "An error message was never generated.";
            ScheduleInitialSucceeded = false;

            // Channel check
            if (rr.MCChannelID < 1)
            {
                ScheduleInitialFailureResult.ErrorMessage = "No MC Channel ID was specified.";
                ScheduleInitialFailureResult.RequestResult = RecordingResult.RequestResults.FailedWithError;
                ScheduleRecordingCompleted();
                return;
            }

            // Too much padding
            if ((rr.Postpadding > 1800) && (rr.Prepadding > 1800))
            {
                ScheduleInitialFailureResult.ErrorMessage = "Pre or Post padding must be less than 30 minutes.";
                ScheduleInitialFailureResult.RequestResult = RecordingResult.RequestResults.FailedWithError;
                ScheduleRecordingCompleted();
                return;
            }

            // Get service
            StoredObject so = os.Fetch(rr.MCChannelID);
            if (!(so is Channel))
            {
                ScheduleInitialFailureResult.ErrorMessage = "The retrieved TV channel was not valid.";
                DebugError("OSM: Retrieved TV channel not valid: ID is [" + rr.MCChannelID.ToString() + "] and so is [" + so.ToString() + "]");
                ScheduleInitialFailureResult.RequestResult = RecordingResult.RequestResults.FailedWithError;
                ScheduleRecordingCompleted();
                return;
            }

            Channel channel = (Channel)so;

            // Get TV programme (ie schedule entry)
            ScheduleEntry schedEntry = null;
            if (rr.RequestType != RecordingRequestType.Manual)
            {
                StoredObject sto = os.Fetch(rr.TVProgrammeID);
                if (!(sto is ScheduleEntry))
                {
                    ScheduleRecordingCompleted();
                    return;
                }

                schedEntry = (ScheduleEntry)sto;
            }

            // Store request
            requestInProgress = null;
            switch (rr.RequestType)
            {
                case RecordingRequestType.Series:
                    // Check schedentry has series info
                    if (schedEntry.Program != null)
                        if (schedEntry.Program.Series == null)
                        {
                            ScheduleInitialFailureResult.ErrorMessage = "This show is not part of a recognised series within Media Center.";
                            ScheduleInitialFailureResult.RequestResult = RecordingResult.RequestResults.FailedWithError;
                            ScheduleRecordingCompleted();
                            return;
                        }
                    SeriesRequest sreq = recScheduler.CreateSeriesRequest(schedEntry, channel);
                    sreq.RunType = (rr.FirstRunOnly) ? RunType.FirstRunOnly : RunType.Any;

                    // sreq.IsRecurring = true  ??
                    sreq.AnyChannel = (rr.SeriesRequestSubType == SeriesRequestSubTypes.AnyChannelAnyTime);
                    // Series request HAS to have IsRecurring set to TRUE.  Series requests CANNOT be non recurring!
                    sreq.IsRecurring = true; //= ((rr.SeriesRequestSubType == SeriesRequestSubTypes.AnyChannelAnyTime) || (rr.SeriesRequestSubType == SeriesRequestSubTypes.ThisChannelAnyTime));

                    /*
                    // Experimental - AIR TIME
                    string strAirtimecheck = "";
                        if (!sreq.Airtime.HasValue)
                            strAirtimecheck += "null";
                        else
                            strAirtimecheck += sreq.Airtime.Value.ToString();

                        DebugNormal("Airtime (before alteration) is:" + strAirtimecheck);

                    // 12 hour window
                    if (rr.SeriesRequestSubType == SeriesRequestSubTypes.ThisChannelAnyTime)
                    {
                        sreq.Airtime = TimeSpan.FromHours(12);
                    }
                    else if (rr.SeriesRequestSubType == SeriesRequestSubTypes.ThisChannelThisTime)
                    {
                        sreq.Airtime = TimeSpan.FromHours(3);
                    }
                    */
                    // Look also at...
                    //sreq.Airtime
                    //sreq.DaysOfWeek
                    // sreq.ScheduleLimit - maximum number to schedule

                    // If keep until is 'latest episodes', set the number here...
                    if (rr.KeepUntil == KeepUntilTypes.LatestEpisodes)
                    {
                        if (rr.KeepNumberOfEpisodes > 0)
                            sreq.RecordingLimit = rr.KeepNumberOfEpisodes;
                    }

                    requestInProgress = (Request)sreq;
                    break;

                case RecordingRequestType.OneTime:
                    OneTimeRequest oreq = recScheduler.CreateOneTimeRequest(schedEntry, channel);
                    requestInProgress = (Request)oreq;
                    requestInProgress.AnyChannel = false;
                    //requestInProgress.ScheduleLimit = 5; // This didn't do anything!
                    break;

                case RecordingRequestType.Manual:

                    ManualRequest mreq = recScheduler.CreateManualRequest(rr.StartTime, TimeSpan.FromMinutes(rr.Duration), channel, rr.ManualRecordingName, "", "", "", (System.Globalization.CultureInfo.CurrentCulture.LCID), false);
                    requestInProgress = (Request)mreq;
                    break;
            }

            // Universal Request Settings - all types of recording
            requestInProgress.PostPaddingRequested = TimeSpan.FromSeconds(rr.Postpadding);
            requestInProgress.PrePaddingRequested = TimeSpan.FromSeconds(rr.Prepadding);
            // Keep Until
            if (rr.KeepUntil != KeepUntilTypes.NotSet)
            {
                try
                {
                    DebugNormal("OSM: Setting 7MC request keeplength using string " + rr.KeepUntil.ToString());
                    requestInProgress.KeepLength = (KeepLength)Enum.Parse(typeof(KeepLength), rr.KeepUntil.ToString(), true);
                    DebugNormal("OSM: 7MC request keepLength is now " + requestInProgress.KeepLength.ToString());
                }
                catch { DebugNormal("ERROR: Couldn't parse KeepUntil value."); }
            }
            // ELSE ...  ASSUME media center uses KeepUntil default when creating recording?  If not, SET HERE ===>

            requestInProgress.Quality = rr.Quality;

            // Update request... (TODO is this step strictly necessary?)
            //rqInProgress.Updated += new StoredObjectEventHandler(ScheduleRecording_2);
            //rqInProgress.UpdateRequest();
            requestInProgress.UpdateRequestedPrograms();
            UpdateDelegate upd = new UpdateDelegate(ScheduleRecording_Done);
            requestInProgress.UpdateAndSchedule(upd, recScheduler);
        }