void streaming_queue_deinit(streaming_queue_t *sq) { streaming_queue_clear(&sq->sq_queue); pthread_mutex_destroy(&sq->sq_mutex); pthread_cond_destroy(&sq->sq_cond); }
void timeshift_destroy(streaming_target_t *pad) { timeshift_t *ts = (timeshift_t*)pad; streaming_message_t *sm; int i; /* Must hold global lock */ lock_assert(&global_lock); /* Ensure the threads exits */ // Note: this is a workaround for the fact the Q might have been flushed // in reader thread (VERY unlikely) pthread_mutex_lock(&ts->state_mutex); sm = streaming_msg_create(SMT_EXIT); streaming_target_deliver2(&ts->wr_queue.sq_st, sm); timeshift_write_exit(ts->rd_pipe.wr); pthread_mutex_unlock(&ts->state_mutex); /* Wait for all threads */ pthread_join(ts->rd_thread, NULL); pthread_join(ts->wr_thread, NULL); /* Shut stuff down */ streaming_queue_deinit(&ts->wr_queue); for (i = 0; i < TIMESHIFT_BACKLOG_MAX; i++) streaming_queue_clear(&ts->backlog[i]); close(ts->rd_pipe.rd); close(ts->rd_pipe.wr); /* Flush files */ timeshift_filemgr_flush(ts, NULL); /* Release SMT_START index */ if (ts->smt_start) streaming_start_unref(ts->smt_start); if (ts->path) free(ts->path); free(ts); }
static void * serviceprobe_thread(void *aux) { service_t *t; th_subscription_t *s; int was_doing_work = 0; streaming_queue_t sq; streaming_message_t *sm; // transport_feed_status_t status; int run; const char *err; channel_t *ch; uint32_t checksubscr; pthread_mutex_lock(&global_lock); streaming_queue_init(&sq, 0); err = NULL; while(1) { while((t = TAILQ_FIRST(&serviceprobe_queue)) == NULL) { if(was_doing_work) { tvhlog(LOG_INFO, "serviceprobe", "Now idle"); was_doing_work = 0; } pthread_cond_wait(&serviceprobe_cond, &global_lock); } if(!was_doing_work) { tvhlog(LOG_INFO, "serviceprobe", "Starting"); was_doing_work = 1; } if (t->s_dvb_mux_instance) checksubscr = !t->s_dvb_mux_instance->tdmi_adapter->tda_skip_checksubscr; else checksubscr = 1; if (checksubscr) { tvhlog(LOG_INFO, "serviceprobe", "%20s: checking...", t->s_svcname); s = subscription_create_from_service(t, "serviceprobe", &sq.sq_st, 0, NULL, NULL, "serviceprobe"); if(s == NULL) { t->s_sp_onqueue = 0; TAILQ_REMOVE(&serviceprobe_queue, t, s_sp_link); tvhlog(LOG_INFO, "serviceprobe", "%20s: could not subscribe", t->s_svcname); continue; } } service_ref(t); pthread_mutex_unlock(&global_lock); if (checksubscr) { run = 1; pthread_mutex_lock(&sq.sq_mutex); while(run) { while((sm = TAILQ_FIRST(&sq.sq_queue)) == NULL) pthread_cond_wait(&sq.sq_cond, &sq.sq_mutex); TAILQ_REMOVE(&sq.sq_queue, sm, sm_link); pthread_mutex_unlock(&sq.sq_mutex); if(sm->sm_type == SMT_SERVICE_STATUS) { int status = sm->sm_code; if(status & TSS_PACKETS) { run = 0; err = NULL; } else if(status & (TSS_GRACEPERIOD | TSS_ERRORS)) { run = 0; err = service_tss2text(status); } } streaming_msg_free(sm); pthread_mutex_lock(&sq.sq_mutex); } streaming_queue_clear(&sq.sq_queue); pthread_mutex_unlock(&sq.sq_mutex); } else { err = NULL; } pthread_mutex_lock(&global_lock); if (checksubscr) { subscription_unsubscribe(s); } if(t->s_status != SERVICE_ZOMBIE) { if(err != NULL) { tvhlog(LOG_INFO, "serviceprobe", "%20s: skipped: %s", t->s_svcname, err); } else if(t->s_ch == NULL) { int channum = t->s_channel_number; const char *str; if (!channum && t->s_dvb_mux_instance->tdmi_adapter->tda_sidtochan) channum = t->s_dvb_service_id; ch = channel_find_by_name(t->s_svcname, 1, channum); service_map_channel(t, ch, 1); tvhlog(LOG_INFO, "serviceprobe", "%20s: mapped to channel \"%s\"", t->s_svcname, t->s_svcname); if(service_is_tv(t)) { channel_tag_map(ch, channel_tag_find_by_name("TV channels", 1), 1); tvhlog(LOG_INFO, "serviceprobe", "%20s: joined tag \"%s\"", t->s_svcname, "TV channels"); } switch(t->s_servicetype) { case ST_SDTV: case ST_AC_SDTV: case ST_EX_SDTV: case ST_DN_SDTV: case ST_SK_SDTV: case ST_NE_SDTV: str = "SDTV"; break; case ST_HDTV: case ST_AC_HDTV: case ST_EX_HDTV: case ST_EP_HDTV: case ST_ET_HDTV: case ST_DN_HDTV: str = "HDTV"; break; case ST_RADIO: str = "Radio"; break; default: str = NULL; } if(str != NULL) { channel_tag_map(ch, channel_tag_find_by_name(str, 1), 1); tvhlog(LOG_INFO, "serviceprobe", "%20s: joined tag \"%s\"", t->s_svcname, str); } if(t->s_provider != NULL) { channel_tag_map(ch, channel_tag_find_by_name(t->s_provider, 1), 1); tvhlog(LOG_INFO, "serviceprobe", "%20s: joined tag \"%s\"", t->s_svcname, t->s_provider); } channel_save(ch); } t->s_sp_onqueue = 0; TAILQ_REMOVE(&serviceprobe_queue, t, s_sp_link); } service_unref(t); } return NULL; }