Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
DVR: centralize status updates, fix dvr_rec_subscribe error path, fix…
…es#2857
  • Loading branch information
perexg committed May 20, 2015
1 parent 3a36e86 commit ee69d63
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 61 deletions.
9 changes: 7 additions & 2 deletions src/dvr/dvr.h
Expand Up @@ -419,6 +419,11 @@ void dvr_entry_save(dvr_entry_t *de);

void dvr_entry_destroy_by_config(dvr_config_t *cfg, int delconf);

int dvr_entry_set_state(dvr_entry_t *de, dvr_entry_sched_state_t state,
dvr_rs_state_t rec_state, int error_code);

void dvr_entry_completed(dvr_entry_t *de, int error_code);

const char *dvr_entry_status(dvr_entry_t *de);

const char *dvr_entry_schedstatus(dvr_entry_t *de);
Expand Down Expand Up @@ -460,9 +465,9 @@ dvr_entry_update( dvr_entry_t *de,

void dvr_destroy_by_channel(channel_t *ch, int delconf);

void dvr_rec_subscribe(dvr_entry_t *de);
int dvr_rec_subscribe(dvr_entry_t *de);

void dvr_rec_unsubscribe(dvr_entry_t *de, int stopcode);
void dvr_rec_unsubscribe(dvr_entry_t *de);

void dvr_event_replaced(epg_broadcast_t *e, epg_broadcast_t *new_e);

Expand Down
59 changes: 32 additions & 27 deletions src/dvr/dvr_db.c
Expand Up @@ -50,17 +50,23 @@ static int dvr_entry_class_disp_subtitle_set(void *o, const void *v);
/*
*
*/
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;
Expand Down Expand Up @@ -201,10 +207,10 @@ dvr_dbus_timer_cb( void *aux )
/*
* 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
Expand Down Expand Up @@ -348,9 +354,9 @@ dvr_entry_set_timer(dvr_entry_t *de)
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);

Expand All @@ -360,7 +366,7 @@ dvr_entry_set_timer(dvr_entry_t *de)

} 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);
Expand All @@ -370,7 +376,7 @@ dvr_entry_set_timer(dvr_entry_t *de)

} else {

dvr_entry_assign_sched_state(de, DVR_NOSTATE);
dvr_entry_set_state(de, DVR_NOSTATE, DVR_RS_PENDING, de->de_last_error);

}
}
Expand Down Expand Up @@ -718,7 +724,9 @@ static dvr_entry_t* _dvr_duplicate_event(dvr_entry_t* de)
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
Expand Down Expand Up @@ -1122,14 +1130,16 @@ void dvr_event_updated ( epg_broadcast_t *e )
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",
Expand All @@ -1138,8 +1148,6 @@ dvr_stop_recording(dvr_entry_t *de, int stopcode, int saveconf)

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);
Expand All @@ -1152,7 +1160,7 @@ dvr_stop_recording(dvr_entry_t *de, int stopcode, int saveconf)
static void
dvr_timer_stop_recording(void *aux)
{
dvr_stop_recording(aux, 0, 1);
dvr_stop_recording(aux, SM_CODE_OK, 1);
}


Expand All @@ -1166,7 +1174,7 @@ dvr_timer_start_recording(void *aux)
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;
}

Expand All @@ -1176,16 +1184,13 @@ dvr_timer_start_recording(void *aux)
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));
Expand Down
49 changes: 17 additions & 32 deletions src/dvr/dvr_rec.c
Expand Up @@ -58,7 +58,7 @@ const static int prio2weight[6] = {
/**
*
*/
void
int
dvr_rec_subscribe(dvr_entry_t *de)
{
char buf[100];
Expand All @@ -82,7 +82,8 @@ dvr_rec_subscribe(dvr_entry_t *de)
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,
Expand All @@ -93,20 +94,20 @@ dvr_rec_subscribe(dvr_entry_t *de)
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;

Expand All @@ -123,8 +124,6 @@ dvr_rec_unsubscribe(dvr_entry_t *de, int stopcode)
de->de_chain = NULL;
profile_chain_close(prch);
free(prch);

de->de_last_error = stopcode;
}


Expand Down Expand Up @@ -320,9 +319,9 @@ dvr_rec_fatal_error(dvr_entry_t *de, const char *fmt, ...)
*
*/
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);
Expand All @@ -335,19 +334,9 @@ dvr_notify(dvr_entry_t *de, int now)
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);
}

/**
Expand Down Expand Up @@ -524,14 +513,14 @@ dvr_thread(void *aux)
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)
Expand Down Expand Up @@ -562,7 +551,7 @@ dvr_thread(void *aux)
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;

Expand All @@ -571,7 +560,7 @@ dvr_thread(void *aux)
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;

Expand All @@ -591,11 +580,8 @@ dvr_thread(void *aux)
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;
Expand All @@ -607,7 +593,7 @@ dvr_thread(void *aux)
} 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));
Expand Down Expand Up @@ -754,7 +740,6 @@ dvr_thread_epilog(dvr_entry_t *de)
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)
Expand Down

0 comments on commit ee69d63

Please sign in to comment.