示例#1
0
 public static void Parse(CsvReader csvReader,
                          IRemoteRecorderManagement rrMgr,
                          Utilities.RemoteRecorderManagement42.AuthenticationInfo rrAuth,
                          ISessionManagement sessionMgr,
                          Utilities.SessionManagement46.AuthenticationInfo sessionAuth,
                          int lineNumber,
                          List <ScheduleRecording> schedule,
                          Dictionary <int, RecordingValidityCode> badSchedules,
                          Dictionary <ScheduleRecording, int> recordingToLine)
 {
     while (csvReader.Read())
     {
         if (csvReader.Context.Record.Length != Formats[SupportedFileType.Legacy].Length)
         {
             // if the number of fields is not good, then continue to the next record
             badSchedules.Add(lineNumber, RecordingValidityCode.ParseError);
         }
         else
         {
             ScheduleRecording record = csvReader.GetRecord <ScheduleRecording>();
             ParseCommon(rrMgr,
                         rrAuth,
                         sessionMgr,
                         sessionAuth,
                         record,
                         lineNumber,
                         schedule,
                         badSchedules,
                         recordingToLine);
         }
         lineNumber++;
     }
 }
示例#2
0
 /// <summary>
 /// Common method calls an actions for all parsers.
 /// </summary>
 /// <param name="rrMgr">The client in which holds the information about the recorders available.</param>
 /// <param name="rrAuth">The authentication information for which to access the information from <paramref name="rrMgr"/>.</param>
 /// <param name="sessionMgr">The client in which holds the information about the sessions.</param>
 /// <param name="sessionAuth">The authentication information for which to access the information from <paramref name="sessionMgr"/>.</param>
 /// <param name="record">The line currently being parsed.</param>
 /// <param name="lineNumber">The line number on the original file.</param>
 /// <param name="schedule">The schedule to update after <paramref name="record"/> is parsed.</param>
 /// <param name="badSchedules">The mappings from line number to error code to be populated, if needed.</param>
 /// <param name="recordingToLine">The mappings from recording to line number.</param>
 public static void ParseCommon(IRemoteRecorderManagement rrMgr,
                                Utilities.RemoteRecorderManagement42.AuthenticationInfo rrAuth,
                                ISessionManagement sessionMgr,
                                Utilities.SessionManagement46.AuthenticationInfo sessionAuth,
                                ScheduleRecording record,
                                int lineNumber,
                                List <ScheduleRecording> schedule,
                                Dictionary <int, RecordingValidityCode> badSchedules,
                                Dictionary <ScheduleRecording, int> recordingToLine)
 {
     // Now grab the IDs if possible and set them in the object
     record.RecorderID = Checker.GetRecorderID(record.RecorderName, rrMgr, rrAuth);
     if (record.FolderName != "" && record.FolderID == Guid.Empty)
     {
         // a specific folder was specified so try to look it up
         record.FolderID = Checker.GetFolderID(record.FolderName, sessionMgr, sessionAuth);
     }
     else if (record.FolderName == "" && record.RecorderID != Guid.Empty)
     {
         // case for a default folder/unspecified folder
         // Each RR has their own default folder, so call that and directly get folderID from that
         record.FolderID = rrMgr.GetDefaultFolderForRecorder(rrAuth, record.RecorderID);
         // Need to update the FolderName if we used the remote recorder's default folder
         Folder[] folder = sessionMgr.GetFoldersById(sessionAuth, new Guid[] { record.FolderID });
         record.FolderName = folder[0].Name;
     }
     if (record.CheckValidity() != RecordingValidityCode.Valid)
     {
         badSchedules.Add(lineNumber, record.CheckValidity());
     }
     recordingToLine.Add(record, lineNumber);
     schedule.Add(record);
 }
示例#3
0
 /// <summary>
 /// Takes the recording client and authentication, and attempts to schedule sessions provided in <paramref name="schedule"/>.
 /// </summary>
 /// <param name="rrMgr">The client in which holds the information about the recorders available.</param>
 /// <param name="rrAuth">The authentication information for which to access the information from <paramref name="rrMgr"/>.</param>
 /// <param name="schedule">The recording schedule.</param>
 /// <returns>The results of the scheduling attempt.</returns>
 public static Dictionary <ScheduleRecording, ScheduledRecordingResult> ScheduleRecordings(
     IRemoteRecorderManagement rrMgr,
     Utilities.RemoteRecorderManagement42.AuthenticationInfo rrAuth,
     List <ScheduleRecording> schedule)
 {
     return(ScheduleRecordings(rrMgr, rrAuth, schedule, sender: null));
 }
示例#4
0
        /// <summary>
        /// Gets the unique ID of the recorder specified by <paramref name="recorderName"/>.
        /// </summary>
        /// <param name="recorderName">Name of the recorder to get the ID for.</param>
        /// <param name="rrMgr">The client in which holds the information about the recorder <paramref name="recorderName"/>.</param>
        /// <param name="rrAuth">The authentication information for which to access the information from <paramref name="rrMgr"/>.</param>
        /// <returns>Returns the unique ID, if found. Else, will return Guid.Empty.</returns>
        public static Guid GetRecorderID(string recorderName, IRemoteRecorderManagement rrMgr, RemoteRecorderManagement42.AuthenticationInfo rrAuth)
        {
            Guid rrID = Guid.Empty;

            // Handle no recorder name here
            if (recorderName.Equals(""))
            {
                return(rrID);
            }

            // set the recorderName to lowercase for insensitive lookup
            recorderName = recorderName.ToLowerInvariant();

            if (recorderIds.ContainsKey(recorderName))
            {
                return(recorderIds[recorderName]);
            }

            if (recorderIds.Count > 0)
            {
                return(Guid.Empty);
            }

            bool lastPage       = false;
            int  resultsPerPage = 5;
            int  pageNumber     = 0;

            while (!lastPage)
            {
                RemoteRecorderManagement42.Pagination rrPage = new RemoteRecorderManagement42.Pagination()
                {
                    MaxNumberResults = resultsPerPage,
                    PageNumber       = pageNumber
                };

                ListRecordersResponse rrResponse = rrMgr.ListRecorders(rrAuth, rrPage, RecorderSortField.Name);
                if (resultsPerPage * (pageNumber + 1) >= rrResponse.TotalResultCount)
                {
                    lastPage = true;
                }
                // Populate the lookup map with the lowercase'd names of the recorders
                foreach (RemoteRecorder rr in rrResponse.PagedResults)
                {
                    recorderIds[rr.Name.ToLowerInvariant()] = rr.Id;
                }
                // keep looking
                pageNumber++;
            }
            // If rrID stays empty then remote recorder wasn't found or handle the case in which not found
            return(GetRecorderID(recorderName, rrMgr, rrAuth));
        }
示例#5
0
 /// <summary>
 /// Sets up the access to the server.
 /// </summary>
 /// <param name="userName">The username of the account that has access to schedule recordings.</param>
 /// <param name="password">The password associated with the account <paramref name="userName"/>.</param>
 /// <param name="rrMgr">The client in which holds the information about the recorders available.</param>
 /// <param name="rrAuth">The authentication information for which to access the information from <paramref name="rrMgr"/>.</param>
 /// <param name="sessionMgr">The client in which holds the information about the sessions.</param>
 /// <param name="sessionAuth">The authentication information for which to access the information from <paramref name="sessionMgr"/>.</param>
 public static void SetupSiteAccess(string userName,
                                    string password,
                                    out IRemoteRecorderManagement rrMgr,
                                    out Utilities.RemoteRecorderManagement42.AuthenticationInfo rrAuth,
                                    out ISessionManagement sessionMgr,
                                    out Utilities.SessionManagement46.AuthenticationInfo sessionAuth)
 {
     SetupSiteAccess(userName: userName,
                     password: password,
                     siteName: Properties.Settings.Default.sitename,
                     rrMgr: out rrMgr,
                     rrAuth: out rrAuth,
                     sessionMgr: out sessionMgr,
                     sessionAuth: out sessionAuth);
 }
示例#6
0
 public static void Parse(CsvReader csvReader,
                          IRemoteRecorderManagement rrMgr,
                          Utilities.RemoteRecorderManagement42.AuthenticationInfo rrAuth,
                          ISessionManagement sessionMgr,
                          Utilities.SessionManagement46.AuthenticationInfo sessionAuth,
                          DateTime startDate,
                          DateTime endDate,
                          int lineNumber,
                          string term,
                          List <ScheduleRecording> schedule,
                          Dictionary <int, RecordingValidityCode> badSchedules,
                          Dictionary <ScheduleRecording, int> recordingToLine)
 {
     while (csvReader.Read())
     {
         // maybe problem due to inconsistent header lengths (with/without exclusion date header) or can just ignore and continue
         // and the Sunday sheet example where there is nothing, header check might catch and ignore this case though
         if (csvReader.Context.Record.Length != Formats[SupportedFileType.Georgetown].Length)
         {
             // if the number of fields is not good, then continue to the next record
             badSchedules.Add(lineNumber, RecordingValidityCode.ParseError);
         }
         else if (csvReader.Context.Record[1] == "")
         {
             // skip it: this line was probably scheduled manually
         }
         else
         {
             RecurringRecording record = csvReader.GetRecord <RecurringRecording>();
             record.FolderName += "." + term;
             ParseCommon(rrMgr,
                         rrAuth,
                         sessionMgr,
                         sessionAuth,
                         record,
                         lineNumber,
                         schedule,
                         badSchedules,
                         recordingToLine);
         }
         lineNumber++;
         if (lineNumber % 10 == 0)
         {
             Console.WriteLine(lineNumber);
         }
     }
 }
示例#7
0
 public static void Parse(CsvReader csvReader,
                          IRemoteRecorderManagement rrMgr,
                          Utilities.RemoteRecorderManagement42.AuthenticationInfo rrAuth,
                          ISessionManagement sessionMgr,
                          Utilities.SessionManagement46.AuthenticationInfo sessionAuth,
                          int lineNumber,
                          DateTime startDate,
                          DateTime endDate,
                          string term,
                          List <ScheduleRecording> schedule,
                          Dictionary <int, RecordingValidityCode> badSchedules,
                          Dictionary <ScheduleRecording, int> recordingToLine)
 {
     while (csvReader.Read())
     {
         if (csvReader.Context.Record.Length != Formats[SupportedFileType.Banner].Length)
         {
             // if the number of fields is not good, then continue to the next record
             badSchedules.Add(lineNumber, RecordingValidityCode.ParseError);
         }
         else
         {
             RecurringRecording record = csvReader.GetRecord <RecurringRecording>();
             // Put in start date and end date record index 6 and 7 for times
             // Don't adjust the start date onto the cadence here, adjust at schedule time.
             record.StartDate = ParseTime(startDate, csvReader.Context.Record[6], BannerTimeFormat);
             record.EndDate   = ParseTime(endDate, csvReader.Context.Record[7], BannerTimeFormat);
             // Use local time to calculate recording duration due to UTC conversion causing negative durations
             // with the use of TimeOfDay. Alternate solutions include subtracting days from end and start so that they are
             // on the same day but that introduces lots of overhead and more calculations.
             record.Duration    = record.EndDate.ToLocalTime().TimeOfDay - record.StartDate.ToLocalTime().TimeOfDay;
             record.FolderName += term;
             ParseCommon(rrMgr,
                         rrAuth,
                         sessionMgr,
                         sessionAuth,
                         record,
                         lineNumber,
                         schedule,
                         badSchedules,
                         recordingToLine);
         }
         lineNumber++;
     }
 }
示例#8
0
        /// <summary>
        /// Sets up the access to the server.
        /// </summary>
        /// <param name="userName">The username of the account that has access to schedule recordings.</param>
        /// <param name="password">The password associated with the account <paramref name="userName"/>.</param>
        /// <param name="siteName">The name of the site in which to gain access to.</param>
        /// <param name="rrMgr">The client in which holds the information about the recorders available.</param>
        /// <param name="rrAuth">The authentication information for which to access the information from <paramref name="rrMgr"/>.</param>
        /// <param name="sessionMgr">The client in which holds the information about the sessions.</param>
        /// <param name="sessionAuth">The authentication information for which to access the information from <paramref name="sessionMgr"/>.</param>
        public static void SetupSiteAccess(string userName,
                                           string password,
                                           string siteName,
                                           out IRemoteRecorderManagement rrMgr,
                                           out Utilities.RemoteRecorderManagement42.AuthenticationInfo rrAuth,
                                           out ISessionManagement sessionMgr,
                                           out Utilities.SessionManagement46.AuthenticationInfo sessionAuth)
        {
            if (siteName == "")
            {
                // sitename was not configured
                throw new System.Configuration.ConfigurationErrorsException("Sitename was not configured.");
            }
            // rr manager setup
            rrMgr = new RemoteRecorderManagementClient(
                new BasicHttpBinding(BasicHttpSecurityMode.Transport)
            {
                MaxReceivedMessageSize = Properties.Settings.Default.HttpBindingMessageSize,
                SendTimeout            = Properties.Settings.Default.HttpBindingTimeout,
                ReceiveTimeout         = Properties.Settings.Default.HttpBindingTimeout
            },
                new EndpointAddress("https://" + siteName + "/Panopto/PublicAPI/4.2/RemoteRecorderManagement.svc")
                );

            // rr auth info setup
            rrAuth          = new Utilities.RemoteRecorderManagement42.AuthenticationInfo();
            rrAuth.UserKey  = userName;
            rrAuth.Password = password;

            // session manager setup
            sessionMgr = new SessionManagementClient(
                new BasicHttpBinding(BasicHttpSecurityMode.Transport)
            {
                MaxReceivedMessageSize = Properties.Settings.Default.HttpBindingMessageSize,
                SendTimeout            = Properties.Settings.Default.HttpBindingTimeout,
                ReceiveTimeout         = Properties.Settings.Default.HttpBindingTimeout
            },
                new EndpointAddress("https://" + siteName + "/Panopto/PublicAPI/4.6/SessionManagement.svc")
                );

            // session auth info
            sessionAuth          = new Utilities.SessionManagement46.AuthenticationInfo();
            sessionAuth.UserKey  = userName;
            sessionAuth.Password = password;
        }
示例#9
0
 /// <summary>
 /// Parses the given <paramref name="filepath"/> and returns the recording schedule.
 /// </summary>
 /// <param name="filepath">The path at which the file is located.</param>
 /// <param name="rrMgr">The client in which holds the information about the recorders available.</param>
 /// <param name="rrAuth">The authentication information for which to access the information from <paramref name="rrMgr"/>.</param>
 /// <param name="sessionMgr">The client in which holds the information about the sessions.</param>
 /// <param name="sessionAuth">The authentication information for which to access the information from <paramref name="sessionMgr"/>.</param>
 /// <param name="badSchedules">The mappings from line number to error code to be populated, if needed.</param>
 /// <param name="conflicts">All the recordings that conflicted with an earlier recording or are invalid.</param>
 /// <returns>The recording schedule, as well as the output parameters <paramref name="badSchedules"/> and <paramref name="conflicts"/>.</returns>
 public static List <ScheduleRecording> ParseFile(string filepath,
                                                  IRemoteRecorderManagement rrMgr,
                                                  Utilities.RemoteRecorderManagement42.AuthenticationInfo rrAuth,
                                                  ISessionManagement sessionMgr,
                                                  Utilities.SessionManagement46.AuthenticationInfo sessionAuth,
                                                  out Dictionary <int, RecordingValidityCode> badSchedules,
                                                  out List <ScheduleRecording> conflicts)
 {
     return(ParseFile(filepath: filepath,
                      rrMgr: rrMgr,
                      rrAuth: rrAuth,
                      sessionMgr: sessionMgr,
                      sessionAuth: sessionAuth,
                      startDate: DateTime.MinValue,
                      endDate: DateTime.MinValue,
                      term: null,
                      folderId: null,
                      badSchedules: out badSchedules,
                      conflicts: out conflicts));
 }
示例#10
0
        /// <summary>
        /// Attempts to get any remote recorder with the provided <paramref name="rrAuth"/> credentials.
        /// </summary>
        /// <param name="rrMgr">The client in which holds the information about the recorders</param>
        /// <param name="rrAuth">The authentication information for which to access the information from <paramref name="rrMgr"/>.</param>
        /// <returns>A code that determines the result of the attempted login.</returns>
        public static LoginResults TryLoginGetRecorder(IRemoteRecorderManagement rrMgr, RemoteRecorderManagement42.AuthenticationInfo rrAuth)
        {
            try
            {
                var pagination = new RemoteRecorderManagement42.Pagination {
                    MaxNumberResults = 1, PageNumber = 0
                };
                var recorderListResponse = rrMgr.ListRecorders(rrAuth, pagination, RecorderSortField.Name);

                // no Remote Recorders found
                if (recorderListResponse.TotalResultCount < 1)
                {
                    return(LoginResults.NoAccess);
                }
            }
            catch
            {
                // ListRecorders throws an exception if authentication fails either incorrect credentials or not admin.
                return(LoginResults.Failure);
            }
            return(LoginResults.Success);
        }
示例#11
0
        /// <summary>
        /// Parses the given <paramref name="filepath"/> and returns the recording schedule.
        /// </summary>
        /// <param name="filepath">The path at which the file is located.</param>
        /// <param name="rrMgr">The client in which holds the information about the recorders available.</param>
        /// <param name="rrAuth">The authentication information for which to access the information from <paramref name="rrMgr"/>.</param>
        /// <param name="sessionMgr">The client in which holds the information about the sessions.</param>
        /// <param name="sessionAuth">The authentication information for which to access the information from <paramref name="sessionMgr"/>.</param>
        /// <param name="startDate">The start date of the term.</param>
        /// <param name="endDate">The end date of the term.</param>
        /// <param name="term">The string representation of the term.</param>
        /// <param name="badSchedules">The mappings from line number to error code to be populated, if needed.</param>
        /// <param name="conflicts">All the recordings that conflicted with an earlier recording or are invalid.</param>
        /// <returns>The recording schedule, as well as the output parameters <paramref name="badSchedules"/> and <paramref name="conflicts"/>.</returns>
        public static List <ScheduleRecording> ParseFile(string filepath,
                                                         IRemoteRecorderManagement rrMgr,
                                                         Utilities.RemoteRecorderManagement42.AuthenticationInfo rrAuth,
                                                         ISessionManagement sessionMgr,
                                                         Utilities.SessionManagement46.AuthenticationInfo sessionAuth,
                                                         DateTime startDate,
                                                         DateTime endDate,
                                                         string term,
                                                         Guid?folderId,
                                                         out Dictionary <int, RecordingValidityCode> badSchedules,
                                                         out List <ScheduleRecording> conflicts)
        {
            List <ScheduleRecording> result = new List <ScheduleRecording>();

            // Handle CSV style case
            using (TextReader reader = File.OpenText(filepath))
            {
                // Create the CsvReader
                CsvReader csvReader = new CsvReader(reader);
                // Ignore missing fields since we don't know the format yet
                // The corresponding classmap class will and should handle those missing fields
                csvReader.Configuration.MissingFieldFound = null;
                // Now read the header to determine its format.
                badSchedules = new Dictionary <int, RecordingValidityCode>();
                conflicts    = null;
                Dictionary <ScheduleRecording, int> recordingToLine = new Dictionary <ScheduleRecording, int>();
                List <ScheduleRecording>            schedule        = new List <ScheduleRecording>();
                int lineNumber             = 1;
                SupportedFileType fileType = SupportedFileType.NotSupported;
                bool foundHeader           = false;
                while (csvReader.Read())
                {
                    if (!foundHeader)
                    {
                        csvReader.ReadHeader();
                        // see if this line is a header we recognize
                        foreach (SupportedFileType sft in Enum.GetValues(typeof(SupportedFileType)))
                        {
                            string[] format = Formats[sft];
                            foundHeader = IsHeader(format, csvReader.Context.Record);
                            if (foundHeader)
                            {
                                // set the filetype and the appropriate map.
                                fileType = sft;
                                switch (fileType)
                                {
                                // Call appropriate parser here, with lineNumber + 1
                                case SupportedFileType.Legacy:
                                    csvReader.Configuration.RegisterClassMap <ScheduleRecordingMap>();
                                    LegacyParser.Parse(csvReader,
                                                       rrMgr,
                                                       rrAuth,
                                                       sessionMgr,
                                                       sessionAuth,
                                                       lineNumber + 1,
                                                       schedule,
                                                       badSchedules,
                                                       recordingToLine);
                                    // Need to check the schedule for internal conflicts
                                    // done parsing so check the schedule
                                    conflicts = Checker.CheckConflicts(schedule, recordingToLine, badSchedules);
                                    break;

                                case SupportedFileType.Banner:
                                    csvReader.Configuration.RegisterClassMap <RecurringRecordingMap>();
                                    BannerParser.Parse(csvReader,
                                                       rrMgr,
                                                       rrAuth,
                                                       sessionMgr,
                                                       sessionAuth,
                                                       lineNumber + 1,
                                                       startDate,
                                                       endDate,
                                                       term,
                                                       schedule,
                                                       badSchedules,
                                                       recordingToLine);
                                    // We trust that the Banner format is internally consistent so set conflicts to new empty list.
                                    conflicts = new List <ScheduleRecording>();
                                    break;

                                case SupportedFileType.Georgetown:
                                    csvReader.Configuration.RegisterClassMap <GeorgetownMap>();
                                    GeorgetownParser.Parse(csvReader,
                                                           rrMgr,
                                                           rrAuth,
                                                           sessionMgr,
                                                           sessionAuth,
                                                           startDate,
                                                           endDate,
                                                           lineNumber + 1,
                                                           term,
                                                           schedule,
                                                           badSchedules,
                                                           recordingToLine);
                                    // We trust that Georgetown has scrubbed their file so that there are no conflicts
                                    conflicts = new List <ScheduleRecording>();
                                    break;

                                case SupportedFileType.Mediasite:
                                    csvReader.Configuration.RegisterClassMap <MediasiteMap>();
                                    MediasiteParser.Parse(csvReader,
                                                          rrMgr,
                                                          rrAuth,
                                                          sessionMgr,
                                                          sessionAuth,
                                                          folderId,
                                                          lineNumber + 1,
                                                          schedule,
                                                          badSchedules,
                                                          recordingToLine);
                                    // Need to check the schedule for internal conflicts
                                    // done parsing so check the schedule
                                    conflicts = Checker.CheckConflicts(schedule, recordingToLine, badSchedules);
                                    break;

                                default:
                                    break;
                                }
                                break;
                            }
                        }
                    }
                    lineNumber++;
                }
                // This step can still be done for all formats
                for (int i = 0; i < schedule.Count; i++)
                {
                    if (!badSchedules.ContainsKey(recordingToLine[schedule[i]]) && schedule[i].CheckValidity() == RecordingValidityCode.Valid)
                    {
                        result.Add(schedule[i]);
                    }
                }
                // we are done reading but no SupportedFileType detected.
                if (!foundHeader)
                {
                    // give a special line number to badSchedules
                    badSchedules.Add(-1, RecordingValidityCode.ParseError);
                    conflicts = new List <ScheduleRecording>();
                }
            }
            return(result);
        }
示例#12
0
        /// <summary>
        /// Takes the recording client and authentication, and attempts to schedule sessions provided in <paramref name="schedule"/>.
        /// </summary>
        /// <param name="rrMgr">The client in which holds the information about the recorders available.</param>
        /// <param name="rrAuth">The authentication information for which to access the information from <paramref name="rrMgr"/>.</param>
        /// <param name="schedule">The recording schedule.</param>
        /// <param name="sender">The BackgroundWorker to make this method asynchronous.</param>
        /// <returns>The results of the scheduling attempt.</returns>
        public static Dictionary <ScheduleRecording, ScheduledRecordingResult> ScheduleRecordings(
            IRemoteRecorderManagement rrMgr,
            Utilities.RemoteRecorderManagement42.AuthenticationInfo rrAuth,
            List <ScheduleRecording> schedule,
            BackgroundWorker sender)
        {
            Dictionary <ScheduleRecording, ScheduledRecordingResult> result = new Dictionary <ScheduleRecording, ScheduledRecordingResult>();

            for (int i = 0; i < schedule.Count; i++)
            {
                if (sender != null)
                {
                    sender.ReportProgress(i + 1);
                }
                else
                {
                    Console.WriteLine("Scheduling recording " + (i + 1) + "/" + schedule.Count + "...");
                }
                ScheduleRecording scheduleRecording = schedule[i];
                try
                {
                    // Currently only concerned with 1 RR for each session
                    RecorderSettings rs = new RecorderSettings()
                    {
                        RecorderId = scheduleRecording.RecorderID
                    };
                    RecurringRecording recurring = null;
                    // need to check to make sure start date is on cadence and adjust as needed if recurring.
                    if ((scheduleRecording as RecurringRecording) != null)
                    {
                        scheduleRecording.StartDate = AdjustDateOntoCadence(
                            scheduleRecording.StartDate,
                            ((RecurringRecording)scheduleRecording).Cadence);
                        // since we need to schedule the first occurrence, this is for accurate success/conflict counting
                        recurring = new RecurringRecording((RecurringRecording)scheduleRecording);
                    }
                    ScheduledRecordingResult scheduledResult = rrMgr.ScheduleRecording(
                        rrAuth,
                        scheduleRecording.SessionName,
                        scheduleRecording.FolderID,
                        scheduleRecording.IsBroadcast || Properties.Settings.Default.ScheduleBroadcasts,
                        scheduleRecording.StartDate,
                        scheduleRecording.StartDate + scheduleRecording.Duration,
                        new RecorderSettings[] { rs });
                    result.Add(scheduleRecording, scheduledResult);
                    if ((scheduleRecording as RecurringRecording) != null && !result[scheduleRecording].ConflictsExist)
                    {
                        // need to transform recurring.Cadence to a DayOfWeek[]
                        DayOfWeek[] days = CadenceToArray(recurring.Cadence);
                        // update the dictionary since this is recurring recording.
                        scheduledResult = rrMgr.ScheduleRecurringRecording(rrAuth,
                                                                           result[scheduleRecording].SessionIDs[0],
                                                                           days,
                                                                           recurring.EndDate);
                        result.Add(recurring, scheduledResult);
                    }
                }
                catch
                {
                    // Since something went wrong with scheduling, still log it in result to report it later.
                    result.Add(scheduleRecording, new ScheduledRecordingResult()
                    {
                        ConflictsExist = true
                    });
                }
            }
            return(result);
        }