I managed to revive my development instance for this project and did some investigation.
Approximately 90 files are impacted by this change. Most of the changes involve retrofitting 2 new properties to each object class: '.ic_class_code' and '.ic_event_code'.
const idclass_t dvr_entry_class = {
.ic_class = "dvrentry",
.ic_class_code = ICC_DVRENTRY, <========= New property
.ic_caption = N_("Digital Video Recorder"),
.ic_event = "dvrentry",
.ic_event_code = EVT_DVRENTRY, <========= New property
.ic_doc = tvh_doc_dvrentry_class,
.ic_changed = dvr_entry_class_changed,
...
Event codes are designed so that a boolean OR can be used to create an event mask to trigger a conflict check.
...
EVT_DVRCONFIG = 0x0000000000000100,
EVT_DVRENTRY = 0x0000000000000200,
EVT_DVRTIMEREC = 0x0000000000000400,
...
Class codes are just an enum to facilitate speedier additional filtering via numerical values rather than string values.
...
ICC_DVRAUTOREC,
ICC_DVRCONFIG,
ICC_DVRENTRY,
ICC_DVRTIMEREC,
...
EPG entries have a simple binary flag indicating that an conflict is present. This property is only present if the conflict state is true.
I can't remember why I did it this way. I was probably because all of the other properties in this area of code only show if true. If it is better for the UI to always have this property, let me know.
"title": "The Tonight Show Starring Jimmy Fallon",
"subtitle": "Guests include Keke Palmer, Jacob Batalon and comedian Lady Miss Jacqueline.",
"conflict_flag": 1,
"ageRating": 11,
DVR Entry and TimeRec API endpoints have 3 new properties: 'conflict_flag', 'conflict_groups' and 'conflict_projection'. These properties are always present.
"conflict_flag": true,
"conflict_groups": [4, 5],
"conflict_projection": [{
"time": 1785499050,
"event_type": 1
}, {
"time": 1785499200,
"event_type": 2
}, {
"time": 1785499050,
"event_type": 4
}, {
"time": 1785499950,
"event_type": 10
}, {
"time": 1785500520,
"event_type": 5
}, {
"time": 1785500520,
"event_type": 4
}, {
"time": 1785501120,
"event_type": 3
}, {
"time": 1785501000,
"event_type": 12
}, {
"time": 1785501120,
"event_type": 13
}
]
Conflict groups are ephemeral and are not saved to disk. They are reevaluated when TVH loads and every time an object of interest changes. Group numbers are consistent within each scheduling conflict check, however, group numbers are subject to change between conflict checks.
The 'conflict_flag' and 'conflict_groups' properties are self evident. However, the 'conflict_projection' property contains an audit file of events that lead to the determination that an error occurred.
//Projection events for conflicts.
//The order may seem odd, but it is used in the UI to determine sort order of events with the same timestamp.
typedef enum {
CONFLICT_PROJECTION_NONE = 0,
CONFLICT_PROJECTION_SCHEDULED_START = 1,
CONFLICT_PROJECTION_ENTRY_START = 2,
CONFLICT_PROJECTION_STOPPED = 3,
CONFLICT_PROJECTION_STARTED = 4,
CONFLICT_PROJECTION_RESTARTING = 5,
CONFLICT_PROJECTION_NO_ADAPTOR = 6,
CONFLICT_PROJECTION_ADAPTOR_OVERLOAD = 7,
CONFLICT_PROJECTION_START_FAILED = 8,
CONFLICT_PROJECTION_STARTING_MISSED = 9,
CONFLICT_PROJECTION_INTERRUPTION = 10,
CONFLICT_PROJECTION_ABANDONED = 11,
CONFLICT_PROJECTION_ENTRY_STOP = 12,
CONFLICT_PROJECTION_SCHEDULED_STOP = 13
} conflict_projection_type_t;
There are 3 new API endpoints.
{ "dvr/entry/conflicts", ACCESS_RECORDER, api_dvr_entry_conflicts, NULL }, /* Check for scheduling conflicts */
{ "dvr/conflict/list", ACCESS_RECORDER, api_dvr_conflict_list, NULL }, /* List scheduling conflicts */
{ "dvr/conflict/check", ACCESS_RECORDER, api_dvr_conflict_check, NULL }, /* Check for scheduling conflicts */
I need to dig into these a little more.
dvr/conflict/list seems to be just a list of DVR entries grouped by conflict group.
{
"entries": [{
"group": 1,
"members": [{
"uuid": "d5f1636505958a7cea246c5b82091ed3",
"name": "Short start high",
"is_entry": true,
"is_timer": false,
"events": [{
"time": 1785314850,
"event_type": 1
}, {
"time": 1785315000,
"event_type": 2
}, {
"time": 1785314850,
"event_type": 4
}, {
"time": 1785316020,
"event_type": 3
}, {
"time": 1785315900,
"event_type": 12
}, {
"time": 1785316020,
"event_type": 13
}
]
}, {
"uuid": "783f7aa751d678df50435ed65fba8040",
"name": "Long Low",
"is_entry": true,
"is_timer": false,
"events": [{
"time": 1785315450,
"event_type": 1
}, {
"time": 1785315600,
"event_type": 2
}, {
"time": 1785315450,
"event_type": 8
}, {
"time": 1785316020,
"event_type": 5
}, {
"time": 1785316020,
"event_type": 4
}, {
"time": 1785322350,
"event_type": 10
}, {
"time": 1785322920,
"event_type": 11
}, {
"time": 1785322800,
"event_type": 12
}, {
"time": 1785322920,
"event_type": 13
}
]
}, {
"uuid": "ea123e1850814039dfc2c3ba5607471e",
"name": "Long Normal",
"is_entry": true,
"is_timer": false,
"events": [{
"time": 1785315450,
"event_type": 1
}, {
"time": 1785315600,
"event_type": 2
}, {
"time": 1785315450,
"event_type": 4
}, {
"time": 1785322920,
"event_type": 3
}, {
"time": 1785322800,
"event_type": 12
}, {
"time": 1785322920,
"event_type": 13
}
]
}
]
}, {
"group": 2,
"members": [{
"uuid": "783f7aa751d678df50435ed65fba8040",
"name": "Long Low",
"is_entry": true,
"is_timer": false,
"events": [{
"time": 1785315450,
"event_type": 1
}, {
"time": 1785315600,
"event_type": 2
}, {
"time": 1785315450,
"event_type": 8
}, {
"time": 1785316020,
"event_type": 5
}, {
"time": 1785316020,
"event_type": 4
}, {
"time": 1785322350,
"event_type": 10
}, {
"time": 1785322920,
"event_type": 11
}, {
"time": 1785322800,
"event_type": 12
}, {
"time": 1785322920,
"event_type": 13
}
]
}, {
"uuid": "ea123e1850814039dfc2c3ba5607471e",
"name": "Long Normal",
"is_entry": true,
"is_timer": false,
"events": [{
"time": 1785315450,
"event_type": 1
}, {
"time": 1785315600,
"event_type": 2
}, {
"time": 1785315450,
"event_type": 4
}, {
"time": 1785322920,
"event_type": 3
}, {
"time": 1785322800,
"event_type": 12
}, {
"time": 1785322920,
"event_type": 13
}
]
}, {
"uuid": "775ae88f94271270ce069845b91023be",
"name": "Short end high",
"is_entry": true,
"is_timer": false,
"events": [{
"time": 1785322350,
"event_type": 1
}, {
"time": 1785322500,
"event_type": 2
}, {
"time": 1785322350,
"event_type": 4
}, {
"time": 1785323520,
"event_type": 3
}, {
"time": 1785323400,
"event_type": 12
}, {
"time": 1785323520,
"event_type": 13
}
]
}
]
}, {
"group": 3,
"members": [{
"uuid": "5e5eb9a9a2f9b2fcd12d6affbfb39a4e",
"name": "From IPTV",
"is_entry": true,
"is_timer": false,
"events": [{
"time": 1785473790,
"event_type": 1
}, {
"time": 1785474000,
"event_type": 2
}, {
"time": 1785473790,
"event_type": 4
}, {
"time": 1785477600,
"event_type": 3
}, {
"time": 1785475800,
"event_type": 12
}, {
"time": 1785477600,
"event_type": 13
}
]
}, {
"uuid": "4697e92a0fd5fb16249153e695a52b32",
"name": "From IPTV-2",
"is_entry": true,
"is_timer": false,
"events": [{
"time": 1785473790,
"event_type": 1
}, {
"time": 1785474000,
"event_type": 2
}, {
"time": 1785473790,
"event_type": 4
}, {
"time": 1785477600,
"event_type": 3
}, {
"time": 1785475800,
"event_type": 12
}, {
"time": 1785477600,
"event_type": 13
}
]
}, {
"uuid": "7b28bf31c89f76ebf1504ccb8758e894",
"name": "From IPTV-2",
"is_entry": true,
"is_timer": false,
"events": [{
"time": 1785473790,
"event_type": 1
}, {
"time": 1785474000,
"event_type": 2
}, {
"time": 1785473790,
"event_type": 7
}, {
"time": 1785477600,
"event_type": 11
}, {
"time": 1785475800,
"event_type": 12
}, {
"time": 1785477600,
"event_type": 13
}
]
}
]
}, {
"group": 4,
"members": [{
"uuid": "fc55200bebb1c68d5617c5ed3ada1972",
"name": "Collide 1c",
"is_entry": true,
"is_timer": false,
"events": [{
"time": 1785499050,
"event_type": 1
}, {
"time": 1785499200,
"event_type": 2
}, {
"time": 1785499050,
"event_type": 4
}, {
"time": 1785499950,
"event_type": 10
}, {
"time": 1785500520,
"event_type": 5
}, {
"time": 1785500520,
"event_type": 4
}, {
"time": 1785501120,
"event_type": 3
}, {
"time": 1785501000,
"event_type": 12
}, {
"time": 1785501120,
"event_type": 13
}
]
}, {
"uuid": "39d2d582a59ae19607cc5656879d1178",
"name": "Collide 1b",
"is_entry": true,
"is_timer": false,
"events": [{
"time": 1785499050,
"event_type": 1
}, {
"time": 1785499200,
"event_type": 2
}, {
"time": 1785499050,
"event_type": 4
}, {
"time": 1785501120,
"event_type": 3
}, {
"time": 1785501000,
"event_type": 12
}, {
"time": 1785501120,
"event_type": 13
}
]
}, {
"uuid": "643691b0e1613c7cdc412d8f9451e757",
"name": "Collide 1a",
"is_entry": true,
"is_timer": false,
"events": [{
"time": 1785499050,
"event_type": 1
}, {
"time": 1785499200,
"event_type": 2
}, {
"time": 1785499050,
"event_type": 8
}, {
"time": 1785500520,
"event_type": 5
}, {
"time": 1785500520,
"event_type": 8
}, {
"time": 1785501120,
"event_type": 11
}, {
"time": 1785501000,
"event_type": 12
}, {
"time": 1785501120,
"event_type": 13
}
]
}
]
}, {
"group": 5,
"members": [{
"uuid": "fc55200bebb1c68d5617c5ed3ada1972",
"name": "Collide 1c",
"is_entry": true,
"is_timer": false,
"events": [{
"time": 1785499050,
"event_type": 1
}, {
"time": 1785499200,
"event_type": 2
}, {
"time": 1785499050,
"event_type": 4
}, {
"time": 1785499950,
"event_type": 10
}, {
"time": 1785500520,
"event_type": 5
}, {
"time": 1785500520,
"event_type": 4
}, {
"time": 1785501120,
"event_type": 3
}, {
"time": 1785501000,
"event_type": 12
}, {
"time": 1785501120,
"event_type": 13
}
]
}, {
"uuid": "892416cd15213824d6272e04a1c53996",
"name": "Collide 1d",
"is_entry": true,
"is_timer": false,
"events": [{
"time": 1785499950,
"event_type": 1
}, {
"time": 1785500100,
"event_type": 2
}, {
"time": 1785499950,
"event_type": 4
}, {
"time": 1785500520,
"event_type": 3
}, {
"time": 1785500400,
"event_type": 12
}, {
"time": 1785500520,
"event_type": 13
}
]
}, {
"uuid": "39d2d582a59ae19607cc5656879d1178",
"name": "Collide 1b",
"is_entry": true,
"is_timer": false,
"events": [{
"time": 1785499050,
"event_type": 1
}, {
"time": 1785499200,
"event_type": 2
}, {
"time": 1785499050,
"event_type": 4
}, {
"time": 1785501120,
"event_type": 3
}, {
"time": 1785501000,
"event_type": 12
}, {
"time": 1785501120,
"event_type": 13
}
]
}
]
}, {
"group": 6,
"members": [{
"uuid": "809ba2a33c53d0d48536ba41744e7ba6",
"name": "Get Clever",
"is_entry": true,
"is_timer": false,
"events": [{
"time": 1785619835,
"event_type": 1
}, {
"time": 1785619985,
"event_type": 2
}, {
"time": 1785619835,
"event_type": 8
}, {
"time": 1785621720,
"event_type": 5
}, {
"time": 1785621720,
"event_type": 4
}, {
"time": 1785621870,
"event_type": 3
}, {
"time": 1785621750,
"event_type": 12
}, {
"time": 1785621870,
"event_type": 13
}
]
}, {
"uuid": "5dbc293becf19b2213226ab81de7843d",
"name": "The Tonight Show Starring Jimmy Fallon",
"is_entry": true,
"is_timer": false,
"events": [{
"time": 1785619671,
"event_type": 1
}, {
"time": 1785619821,
"event_type": 2
}, {
"time": 1785619671,
"event_type": 4
}, {
"time": 1785623582,
"event_type": 3
}, {
"time": 1785623462,
"event_type": 12
}, {
"time": 1785623582,
"event_type": 13
}
]
}, {
"uuid": "4c134c92669be330092783e509ace9bb",
"name": "LEGO DreamZzz",
"is_entry": true,
"is_timer": false,
"events": [{
"time": 1785619650,
"event_type": 1
}, {
"time": 1785619800,
"event_type": 2
}, {
"time": 1785619650,
"event_type": 4
}, {
"time": 1785621720,
"event_type": 3
}, {
"time": 1785621600,
"event_type": 12
}, {
"time": 1785621720,
"event_type": 13
}
]
}
]
}
],
"total": 6
}
dvr/conflict/check and dvr/entry/conflicts seem to give the same results. More investigation is required.
{
"entries": [{
"group": 1,
"instigator_name": "Long Low",
"cohort": [{
"name": "Short start high",
"severity": 0,
"dvr_entry": "d5f1636505958a7cea246c5b82091ed3",
"channel": "85be728791d5af9bd03d527402a9d485",
"priority": 1,
"start_warmup": 1785314850,
"start_padding": 1785314880,
"start": 1785315000,
"stop": 1785315900,
"stop_padding": 1785316020,
"start_actual": 1785314850,
"stop_actual": 1785316020,
"error_flag": 0
}, {
"name": "Long Low",
"severity": 20,
"dvr_entry": "783f7aa751d678df50435ed65fba8040",
"channel": "3a8e18a3572c147d3b4f19b684968cc5",
"priority": 3,
"start_warmup": 1785315450,
"start_padding": 1785315480,
"start": 1785315600,
"stop": 1785322800,
"stop_padding": 1785322920,
"start_actual": 1785316020,
"stop_actual": 1785322350,
"error_flag": 1
}, {
"name": "Long Normal",
"severity": 0,
"dvr_entry": "ea123e1850814039dfc2c3ba5607471e",
"channel": "07ced9f0f98c63a46538ef619ab09e75",
"priority": 2,
"start_warmup": 1785315450,
"start_padding": 1785315480,
"start": 1785315600,
"stop": 1785322800,
"stop_padding": 1785322920,
"start_actual": 1785315450,
"stop_actual": 1785322920,
"error_flag": 0
}
]
}, {
"group": 2,
"instigator_name": "Long Low",
"cohort": [{
"name": "Long Low",
"severity": 20,
"dvr_entry": "783f7aa751d678df50435ed65fba8040",
"channel": "3a8e18a3572c147d3b4f19b684968cc5",
"priority": 3,
"start_warmup": 1785315450,
"start_padding": 1785315480,
"start": 1785315600,
"stop": 1785322800,
"stop_padding": 1785322920,
"start_actual": 1785316020,
"stop_actual": 1785322350,
"error_flag": 1
}, {
"name": "Long Normal",
"severity": 0,
"dvr_entry": "ea123e1850814039dfc2c3ba5607471e",
"channel": "07ced9f0f98c63a46538ef619ab09e75",
"priority": 2,
"start_warmup": 1785315450,
"start_padding": 1785315480,
"start": 1785315600,
"stop": 1785322800,
"stop_padding": 1785322920,
"start_actual": 1785315450,
"stop_actual": 1785322920,
"error_flag": 0
}, {
"name": "Short end high",
"severity": 0,
"dvr_entry": "775ae88f94271270ce069845b91023be",
"channel": "27e45e6ac284d65c51a181608d7818a4",
"priority": 1,
"start_warmup": 1785322350,
"start_padding": 1785322380,
"start": 1785322500,
"stop": 1785323400,
"stop_padding": 1785323520,
"start_actual": 1785322350,
"stop_actual": 1785323520,
"error_flag": 0
}
]
}, {
"group": 3,
"instigator_name": "From IPTV-2",
"cohort": [{
"name": "From IPTV",
"severity": 0,
"dvr_entry": "5e5eb9a9a2f9b2fcd12d6affbfb39a4e",
"channel": "137dd072c30dc9be9a636d20ba2e4404",
"priority": 2,
"start_warmup": 1785473790,
"start_padding": 1785473820,
"start": 1785474000,
"stop": 1785475800,
"stop_padding": 1785477600,
"start_actual": 1785473790,
"stop_actual": 1785477600,
"error_flag": 0
}, {
"name": "From IPTV-2",
"severity": 0,
"dvr_entry": "4697e92a0fd5fb16249153e695a52b32",
"channel": "1d304a428768f79b419ee96ff06d0108",
"priority": 2,
"start_warmup": 1785473790,
"start_padding": 1785473820,
"start": 1785474000,
"stop": 1785475800,
"stop_padding": 1785477600,
"start_actual": 1785473790,
"stop_actual": 1785477600,
"error_flag": 0
}, {
"name": "From IPTV-2",
"severity": 8,
"dvr_entry": "7b28bf31c89f76ebf1504ccb8758e894",
"channel": "7682e8f8a9272217754b0ad5c1dcc2e1",
"priority": 2,
"start_warmup": 1785473790,
"start_padding": 1785473820,
"start": 1785474000,
"stop": 1785475800,
"stop_padding": 1785477600,
"start_actual": 0,
"stop_actual": 0,
"error_flag": 1
}
]
}, {
"group": 4,
"instigator_name": "Collide 1a",
"cohort": [{
"name": "Collide 1c",
"severity": 20,
"dvr_entry": "fc55200bebb1c68d5617c5ed3ada1972",
"channel": "07ced9f0f98c63a46538ef619ab09e75",
"priority": 2,
"start_warmup": 1785499050,
"start_padding": 1785499080,
"start": 1785499200,
"stop": 1785501000,
"stop_padding": 1785501120,
"start_actual": 1785500520,
"stop_actual": 1785501120,
"error_flag": 1
}, {
"name": "Collide 1b",
"severity": 0,
"dvr_entry": "39d2d582a59ae19607cc5656879d1178",
"channel": "3a8e18a3572c147d3b4f19b684968cc5",
"priority": 2,
"start_warmup": 1785499050,
"start_padding": 1785499080,
"start": 1785499200,
"stop": 1785501000,
"stop_padding": 1785501120,
"start_actual": 1785499050,
"stop_actual": 1785501120,
"error_flag": 0
}, {
"name": "Collide 1a",
"severity": 8,
"dvr_entry": "643691b0e1613c7cdc412d8f9451e757",
"channel": "27e45e6ac284d65c51a181608d7818a4",
"priority": 2,
"start_warmup": 1785499050,
"start_padding": 1785499080,
"start": 1785499200,
"stop": 1785501000,
"stop_padding": 1785501120,
"start_actual": 0,
"stop_actual": 0,
"error_flag": 1
}
]
}, {
"group": 5,
"instigator_name": "Collide 1c",
"cohort": [{
"name": "Collide 1c",
"severity": 20,
"dvr_entry": "fc55200bebb1c68d5617c5ed3ada1972",
"channel": "07ced9f0f98c63a46538ef619ab09e75",
"priority": 2,
"start_warmup": 1785499050,
"start_padding": 1785499080,
"start": 1785499200,
"stop": 1785501000,
"stop_padding": 1785501120,
"start_actual": 1785500520,
"stop_actual": 1785501120,
"error_flag": 1
}, {
"name": "Collide 1d",
"severity": 0,
"dvr_entry": "892416cd15213824d6272e04a1c53996",
"channel": "09c2ca307b230178107619d30f3c615e",
"priority": 0,
"start_warmup": 1785499950,
"start_padding": 1785499980,
"start": 1785500100,
"stop": 1785500400,
"stop_padding": 1785500520,
"start_actual": 1785499950,
"stop_actual": 1785500520,
"error_flag": 0
}, {
"name": "Collide 1b",
"severity": 0,
"dvr_entry": "39d2d582a59ae19607cc5656879d1178",
"channel": "3a8e18a3572c147d3b4f19b684968cc5",
"priority": 2,
"start_warmup": 1785499050,
"start_padding": 1785499080,
"start": 1785499200,
"stop": 1785501000,
"stop_padding": 1785501120,
"start_actual": 1785499050,
"stop_actual": 1785501120,
"error_flag": 0
}
]
}, {
"group": 6,
"instigator_name": "Get Clever",
"cohort": [{
"name": "Get Clever",
"severity": 4,
"dvr_entry": "809ba2a33c53d0d48536ba41744e7ba6",
"channel": "25e2ca02cd732a7accd9ad2846fea8e3",
"priority": 2,
"start_warmup": 1785619835,
"start_padding": 1785619865,
"start": 1785619985,
"stop": 1785621750,
"stop_padding": 1785621870,
"start_actual": 1785621720,
"stop_actual": 1785621870,
"error_flag": 1
}, {
"name": "The Tonight Show Starring Jimmy Fallon",
"severity": 0,
"dvr_entry": "5dbc293becf19b2213226ab81de7843d",
"channel": "a1c086a4b3d3daf55b13c1e03eea5bef",
"priority": 2,
"start_warmup": 1785619671,
"start_padding": 1785619701,
"start": 1785619821,
"stop": 1785623462,
"stop_padding": 1785623582,
"start_actual": 1785619671,
"stop_actual": 1785623582,
"error_flag": 0
}, {
"name": "LEGO DreamZzz",
"severity": 0,
"dvr_entry": "4c134c92669be330092783e509ace9bb",
"channel": "a8a3c2feaf0144cf5f3ca3eaca5a1ad6",
"priority": 2,
"start_warmup": 1785619650,
"start_padding": 1785619680,
"start": 1785619800,
"stop": 1785621600,
"stop_padding": 1785621720,
"start_actual": 1785619650,
"stop_actual": 1785621720,
"error_flag": 0
}
]
}
],
"total": 6
}
This is just the start of my rediscovery of this project. I need to dig a lot deeper before making any further progress. I'll do the rebase first and see how that goes.