GCC Code Coverage Report


Directory: ./
File: ScheduleEntry.h
Date: 2026-10-29 08:11:58
Exec Total Coverage
Lines: 1 1 100.0%
Functions: 1 1 100.0%
Branches: 0 0 -%

Line Branch Exec Source
1 #pragma once
2 /*
3 * This file is part of the Falcon Player (FPP) and is Copyright (C)
4 * 2013-2022 by the Falcon Player Developers.
5 *
6 * The Falcon Player (FPP) is free software, and is covered under
7 * multiple Open Source licenses. Please see the included 'LICENSES'
8 * file for descriptions of what files are covered by each license.
9 *
10 * This source file is covered under the LGPL v2.1 as described in the
11 * included LICENSE.LGPL file.
12 */
13
14 #include <string>
15 #include "fpp-json.h"
16 #include <time.h>
17 #include <utility>
18 #include <vector>
19
20 #define SECONDS_PER_MINUTE 60
21 #define SECONDS_PER_HOUR 3600
22 #define SECONDS_PER_DAY 86400
23 #define SECONDS_PER_WEEK 604800
24 #define DAYS_PER_WEEK 7
25
26 // Longest a scheduled FPP command may fire after its second has passed (a
27 // stall, a clock step, a reload landing just after it).
28 #define SCHEDULE_COMMAND_CATCHUP_S 60
29 // How far ahead repeat-interval entries are expanded into occurrences. The
30 // schedule reloads every day, so two days always covers what can run; a full
31 // schedule-distance expansion of a 5-minute repeat was hundreds of thousands
32 // of items.
33 #define SCHEDULE_REPEAT_HORIZON_S (2 * SECONDS_PER_DAY)
34
35 // Values for ScheduleEntry::dayIndex
36 #define INX_SUN 0
37 #define INX_MON 1
38 #define INX_TUE 2
39 #define INX_WED 3
40 #define INX_THU 4
41 #define INX_FRI 5
42 #define INX_SAT 6
43 #define INX_EVERYDAY 7
44 #define INX_WKDAYS 8
45 #define INX_WKEND 9
46 #define INX_M_W_F 10
47 #define INX_T_TH 11
48 #define INX_SUN_TO_THURS 12
49 #define INX_FRI_SAT 13
50 #define INX_ODD_DAY 14
51 #define INX_EVEN_DAY 15
52 #define INX_DAY_MASK 0x10000
53 #define INX_DAY_MASK_SUNDAY 0x04000
54 #define INX_DAY_MASK_MONDAY 0x02000
55 #define INX_DAY_MASK_TUESDAY 0x01000
56 #define INX_DAY_MASK_WEDNESDAY 0x00800
57 #define INX_DAY_MASK_THURSDAY 0x00400
58 #define INX_DAY_MASK_FRIDAY 0x00200
59 #define INX_DAY_MASK_SATURDAY 0x00100
60 // The masks below are for internal use only, not in UI
61 #define INX_DAY_MASK_EVERYDAY 0x07F00
62 #define INX_DAY_MASK_WEEKDAYS 0x03E00
63 #define INX_DAY_MASK_WEEKEND 0x04100
64 #define INX_DAY_MASK_M_W_F 0x02A00
65 #define INX_DAY_MASK_T_TH 0x01400
66 #define INX_DAY_MASK_SUN_TO_THURS 0x07C00
67 #define INX_DAY_MASK_FRI_SAT 0x00300
68 #define INX_DAY_MASK_START_ODD 0x05500
69 #define INX_DAY_MASK_START_EVEN 0x02A00
70
71 // Warnings about the schedule's configuration (a bad time, an unknown
72 // holiday, a missing playlist...). Raised while the schedule is loaded or
73 // expanded; ClearScheduleLoadWarnings() at the start of each load retracts the
74 // previous set, so fixing and saving the schedule clears the banner and an
75 // entry that was deleted stops warning.
76 void ScheduleLoadWarning(int id, const std::string& msg);
77 void ClearScheduleLoadWarnings();
78
79 // While one of these is alive on a thread, ScheduleLoadWarning() on that
80 // thread raises no banner and records nothing for ClearScheduleLoadWarnings();
81 // the warnings are collected here instead. For expanding the schedule outside
82 // a load -- the calendar preview runs on an API thread over any range the
83 // viewer browses to, and a far-future year past the lunar tables raised a
84 // load warning that only the next schedule load would clear.
85 class SchedulePreviewScope {
86 public:
87 SchedulePreviewScope();
88 ~SchedulePreviewScope();
89 SchedulePreviewScope(const SchedulePreviewScope&) = delete;
90 SchedulePreviewScope& operator=(const SchedulePreviewScope&) = delete;
91
92 16 const std::vector<std::pair<int, std::string>>& warnings() const { return m_warnings; }
93
94 private:
95 friend void ScheduleLoadWarning(int id, const std::string& msg);
96 std::vector<std::pair<int, std::string>> m_warnings;
97 SchedulePreviewScope* m_prev;
98 };
99
100 class ScheduleEntry {
101 public:
102 ScheduleEntry();
103 ~ScheduleEntry();
104
105 void CalculateEaster(int year, int& month, int& day);
106 void CalculateChineseNewYear(int year, int& month, int& day);
107 void CalculateHebrewDate(int year, const std::string& hebrewMonth, int hebrewDay, int& month, int& day);
108 void CalculateIslamicDate(int year, int islamicMonth, int islamicDay, int& month, int& day);
109 void CalculateHinduDiwali(int year, int& month, int& day);
110
111 // refYear resolves a floating holiday against a specific year. Pass 0 (the
112 // default) for the historic behaviour of resolving against the current year
113 // and rolling forward to the next one once the date has passed.
114 std::string DateFromLocaleHoliday(Json::Value& holiday, int refYear = 0);
115 std::string CheckHoliday(std::string date, int refYear = 0);
116 std::string ResolveDate(const std::string& date, int offsetDays, int refYear = 0);
117
118 int LoadFromJson(Json::Value& entry);
119
120 // Map a UI dayIndex (INX_SUN..INX_FRI_SAT) to its INX_DAY_MASK_* bitmask.
121 // A custom mask or an odd/even index is returned unchanged, matching the
122 // switch this replaces: both the live scheduler and the calendar preview
123 // resolve day selections through here so they cannot drift apart.
124 static int DayIndexToMask(int dayIndex);
125
126 // For an INX_ODD_DAY / INX_EVEN_DAY entry, does the given day's parity
127 // (counted from the FPP epoch, the first commit on 2013-07-15) match this
128 // entry's odd/even selection? Meaningless for non-odd/even entries.
129 bool IsOddEvenMatch(time_t dayTime) const;
130
131 // 'now' is taken once per schedule load and passed to every call, so
132 // that every occurrence of the load is anchored to the same week.
133 void pushStartEndTimes(int day, int &delta, time_t deltaThreshold, time_t now);
134
135 // Occurrence expansion anchored to an absolute calendar date rather than to
136 // an offset from today. pushStartEndTimes() can only ever describe the
137 // rolling window fppd actually schedules out; these let the schedule be
138 // expanded over an arbitrary range for the calendar preview.
139 void GetDateRangeForYear(int year, int& sDate, int& eDate);
140 bool OccursOnDate(int year, int month, int mday);
141 void GetOccurrencesOnDate(int year, int month, int mday,
142 std::vector<std::pair<time_t, time_t>>& occurrences);
143
144 void GetTimeFromSun(time_t& when, const std::string info,
145 const int infoOffset, int& h, int& m, int& s);
146
147 Json::Value GetJson(void);
148
149 bool enabled;
150 std::string playlist;
151 bool sequence;
152 std::string command;
153 Json::Value args;
154 bool multisyncCommand;
155 std::string multisyncHosts;
156
157 int dayIndex;
158 int startHour;
159 int startMinute;
160 int startSecond;
161 int endHour;
162 int endMinute;
163 int endSecond;
164 bool repeat;
165 int repeatInterval;
166
167 std::vector<std::pair<int, int>> startEndSeconds;
168 std::vector<std::pair<time_t, time_t>> startEndTimes;
169
170 int startDate; // YYYYMMDD format as an integer
171 int endDate; // YYYYMMDD format as an integer
172 int stopType;
173
174 int startTimeOffset;
175 int endTimeOffset;
176 int startDateOffset; // days, applied only when startDate is a holiday name
177 int endDateOffset; // days, applied only when endDate is a holiday name
178 std::string startTimeStr;
179 std::string endTimeStr;
180 std::string startDateStr;
181 std::string endDateStr;
182 };
183