/*
*
*/
-static int
-dvr_entry_assign_sched_state(dvr_entry_t *de, int state)
+int
+dvr_entry_set_state(dvr_entry_t *de, dvr_entry_sched_state_t state,
+ dvr_rs_state_t rec_state, int error_code)
{
char id[16];
- if (de->de_sched_state != state) {
+ if (de->de_sched_state != state ||
+ de->de_rec_state != rec_state ||
+ de->de_last_error != error_code) {
if (de->de_bcast) {
snprintf(id, sizeof(id), "%u", de->de_bcast->id);
notify_delayed(id, "epg", "dvr_update");
}
de->de_sched_state = state;
+ de->de_rec_state = rec_state;
+ de->de_last_error = error_code;
idnode_notify_changed(&de->de_id);
+ htsp_dvr_entry_update(de);
return 1;
}
return 0;
/*
* Completed
*/
-static void
-_dvr_entry_completed(dvr_entry_t *de)
+void
+dvr_entry_completed(dvr_entry_t *de, int error_code)
{
- dvr_entry_assign_sched_state(de, DVR_COMPLETED);
+ dvr_entry_set_state(de, DVR_COMPLETED, DVR_RS_PENDING, error_code);
#if ENABLE_INOTIFY
dvr_inotify_add(de);
#endif
if(now >= stop || de->de_dont_reschedule) {
if(htsmsg_is_empty(de->de_files))
- dvr_entry_assign_sched_state(de, DVR_MISSED_TIME);
+ dvr_entry_set_state(de, DVR_MISSED_TIME, DVR_RS_PENDING, de->de_last_error);
else
- _dvr_entry_completed(de);
+ dvr_entry_completed(de, de->de_last_error);
gtimer_arm_abs(&de->de_timer, dvr_timer_expire, de,
de->de_stop + dvr_entry_get_retention(de) * 86400);
} else if (de->de_channel && de->de_channel->ch_enabled) {
- dvr_entry_assign_sched_state(de, DVR_SCHEDULED);
+ dvr_entry_set_state(de, DVR_SCHEDULED, DVR_RS_PENDING, de->de_last_error);
tvhtrace("dvr", "entry timer scheduled for %"PRItime_t, start);
gtimer_arm_abs(&de->de_timer, dvr_timer_start_recording, de, start);
} else {
- dvr_entry_assign_sched_state(de, DVR_NOSTATE);
+ dvr_entry_set_state(de, DVR_NOSTATE, DVR_RS_PENDING, de->de_last_error);
}
}
continue;
// only successful earlier recordings qualify as master
- if (de2->de_sched_state == DVR_MISSED_TIME || (de2->de_sched_state == DVR_COMPLETED && de2->de_last_error != SM_CODE_OK))
+ if (de2->de_sched_state == DVR_MISSED_TIME ||
+ (de2->de_sched_state == DVR_COMPLETED &&
+ de2->de_last_error != SM_CODE_OK))
continue;
// if titles are not defined or do not match, don't dedup
static void
dvr_stop_recording(dvr_entry_t *de, int stopcode, int saveconf)
{
- if (de->de_rec_state == DVR_RS_PENDING ||
- de->de_rec_state == DVR_RS_WAIT_PROGRAM_START ||
+ dvr_rs_state_t rec_state = de->de_rec_state;
+
+ dvr_rec_unsubscribe(de);
+
+ if (rec_state == DVR_RS_PENDING ||
+ rec_state == DVR_RS_WAIT_PROGRAM_START ||
htsmsg_is_empty(de->de_files))
- dvr_entry_assign_sched_state(de, DVR_MISSED_TIME);
+ dvr_entry_set_state(de, DVR_MISSED_TIME, DVR_RS_PENDING, stopcode);
else
- _dvr_entry_completed(de);
-
- dvr_rec_unsubscribe(de, stopcode);
+ dvr_entry_completed(de, stopcode);
tvhlog(LOG_INFO, "dvr", "\"%s\" on \"%s\": "
"End of program: %s",
if (saveconf)
dvr_entry_save(de);
- idnode_notify_changed(&de->de_id);
- htsp_dvr_entry_update(de);
gtimer_arm_abs(&de->de_timer, dvr_timer_expire, de,
de->de_stop + dvr_entry_get_retention(de) * 86400);
static void
dvr_timer_stop_recording(void *aux)
{
- dvr_stop_recording(aux, 0, 1);
+ dvr_stop_recording(aux, SM_CODE_OK, 1);
}
dvr_entry_t *de = aux;
if (de->de_channel == NULL || !de->de_channel->ch_enabled) {
- dvr_entry_assign_sched_state(de, DVR_NOSTATE);
+ dvr_entry_set_state(de, DVR_NOSTATE, DVR_RS_PENDING, de->de_last_error);
return;
}
return;
}
- dvr_entry_assign_sched_state(de, DVR_RECORDING);
- de->de_rec_state = DVR_RS_PENDING;
- de->de_last_error = SM_CODE_OK;
+ dvr_entry_set_state(de, DVR_RECORDING, DVR_RS_PENDING, SM_CODE_OK);
tvhlog(LOG_INFO, "dvr", "\"%s\" on \"%s\" recorder starting",
lang_str_get(de->de_title, NULL), DVR_CH_NAME(de));
- idnode_changed(&de->de_id);
- htsp_dvr_entry_update(de);
- dvr_rec_subscribe(de);
+ if (dvr_rec_subscribe(de))
+ dvr_entry_completed(de, SM_CODE_BAD_SOURCE);
gtimer_arm_abs(&de->de_timer, dvr_timer_stop_recording, de,
dvr_entry_get_stop_time(de));
/**
*
*/
-void
+int
dvr_rec_subscribe(dvr_entry_t *de)
{
char buf[100];
if (profile_chain_open(prch, &de->de_config->dvr_muxcnf, 0, 0)) {
tvherror("dvr", "unable to create new channel streaming chain for '%s'",
channel_get_name(de->de_channel));
- return;
+ free(prch);
+ return -1;
}
de->de_s = subscription_create_from_channel(prch, NULL, weight,
channel_get_name(de->de_channel));
profile_chain_close(prch);
free(prch);
- de->de_chain = NULL;
- return;
+ return -1;
}
de->de_chain = prch;
tvhthread_create(&de->de_thread, NULL, dvr_thread, de);
+ return 0;
}
/**
*
*/
void
-dvr_rec_unsubscribe(dvr_entry_t *de, int stopcode)
+dvr_rec_unsubscribe(dvr_entry_t *de)
{
profile_chain_t *prch = de->de_chain;
de->de_chain = NULL;
profile_chain_close(prch);
free(prch);
-
- de->de_last_error = stopcode;
}
*
*/
static void
-dvr_notify(dvr_entry_t *de, int now)
+dvr_notify(dvr_entry_t *de)
{
- if (now || de->de_last_notify + 5 < dispatch_clock) {
+ if (de->de_last_notify + 5 < dispatch_clock) {
idnode_notify_changed(&de->de_id);
de->de_last_notify = dispatch_clock;
htsp_dvr_entry_update(de);
static void
dvr_rec_set_state(dvr_entry_t *de, dvr_rs_state_t newstate, int error)
{
- int notify = 0;
- if(de->de_rec_state != newstate) {
- de->de_rec_state = newstate;
- notify = 1;
- }
- if(de->de_last_error != error) {
- de->de_last_error = error;
- notify = 1;
- if(error)
- de->de_errors++;
- }
- if (notify)
- dvr_notify(de, 1);
+ if (de->de_last_error != error && error)
+ de->de_errors++;
+ dvr_entry_set_state(de, de->de_sched_state, newstate, error);
}
/**
pb = ((th_pkt_t*)sm->sm_data)->pkt_payload;
if (((th_pkt_t*)sm->sm_data)->pkt_err) {
de->de_data_errors += ((th_pkt_t*)sm->sm_data)->pkt_err;
- dvr_notify(de, 0);
+ dvr_notify(de);
}
}
else if (sm->sm_type == SMT_MPEGTS) {
pb = sm->sm_data;
if (pb->pb_err) {
de->de_data_errors += pb->pb_err;
- dvr_notify(de, 0);
+ dvr_notify(de);
}
}
if (pb)
if(started) {
muxer_write_pkt(prch->prch_muxer, sm->sm_type, sm->sm_data);
sm->sm_data = NULL;
- dvr_notify(de, 0);
+ dvr_notify(de);
}
break;
dvr_rec_set_state(de, DVR_RS_RUNNING, 0);
muxer_write_pkt(prch->prch_muxer, sm->sm_type, sm->sm_data);
sm->sm_data = NULL;
- dvr_notify(de, 0);
+ dvr_notify(de);
}
break;
if(!started) {
pthread_mutex_lock(&global_lock);
dvr_rec_set_state(de, DVR_RS_WAIT_PROGRAM_START, 0);
- if(dvr_rec_start(de, sm->sm_data) == 0) {
+ if(dvr_rec_start(de, sm->sm_data) == 0)
started = 1;
- idnode_changed(&de->de_id);
- htsp_dvr_entry_update(de);
- }
pthread_mutex_unlock(&global_lock);
}
break;
} else if(sm->sm_code == 0) {
// Recording is completed
- de->de_last_error = SM_CODE_OK;
+ dvr_entry_set_state(de, de->de_sched_state, de->de_rec_state, SM_CODE_OK);
tvhlog(LOG_INFO,
"dvr", "Recording completed: \"%s\"",
dvr_get_filename(de) ?: lang_str_get(de->de_title, NULL));
muxer_close(prch->prch_muxer);
muxer_destroy(prch->prch_muxer);
prch->prch_muxer = NULL;
- dvr_notify(de, 1);
dvr_config_t *cfg = de->de_config;
if(cfg && cfg->dvr_postproc)