void tvhdhomerun_device_destroy( tvhdhomerun_device_t *hd ) { tvhdhomerun_frontend_t *lfe; lock_assert(&global_lock); gtimer_disarm(&hd->hd_destroy_timer); tvhlog(LOG_INFO, "tvhdhomerun", "Releasing locks for devices"); while ((lfe = TAILQ_FIRST(&hd->hd_frontends)) != NULL) { tvhdhomerun_frontend_delete(lfe); } #define FREEM(x) free(hd->hd_info.x) FREEM(ip_address); FREEM(friendlyname); FREEM(uuid); FREEM(deviceModel); #undef FREEM tvh_hardware_delete((tvh_hardware_t*)hd); #define FREEM(x) free(hd->x) FREEM(hd_override_type); #undef FREEM free(hd); }
static void tvhdhomerun_device_class_override_notify( void * obj, const char *lang ) { tvhdhomerun_device_t *hd = obj; tvhdhomerun_frontend_t *hfe; dvb_fe_type_t type = dvb_str2type(hd->hd_override_type); struct hdhomerun_discover_device_t discover_info; unsigned int tuner; htsmsg_t *conf; conf = hts_settings_load("input/tvhdhomerun/adapters/%s", hd->hd_info.uuid); if (conf) conf = htsmsg_get_map(conf, "frontends"); lock_assert(&global_lock); while ((hfe = TAILQ_FIRST(&hd->hd_frontends)) != NULL) { if (hfe->hf_type == type) break; discover_info.device_id = hdhomerun_device_get_device_id(hfe->hf_hdhomerun_tuner); discover_info.ip_addr = hdhomerun_device_get_device_ip(hfe->hf_hdhomerun_tuner); tuner = hfe->hf_tunerNumber; tvhdhomerun_frontend_delete(hfe); tvhdhomerun_frontend_create(hd, &discover_info, conf, type, tuner); } }
static void satip_discovery_timerq_cb(void *aux) { satip_discovery_t *d, *next; int r; lock_assert(&global_lock); next = TAILQ_FIRST(&satip_discoveries); while (next) { d = next; next = TAILQ_NEXT(d, disc_link); if (d->http_client) { if (dispatch_clock - d->http_start > 4) satip_discovery_destroy(d, 1); continue; } d->http_client = http_client_connect(d, HTTP_VERSION_1_1, d->url.scheme, d->url.host, d->url.port, NULL); if (d->http_client == NULL) satip_discovery_destroy(d, 1); else { d->http_start = dispatch_clock; d->http_client->hc_conn_closed = satip_discovery_http_closed; http_client_register(d->http_client); r = http_client_simple(d->http_client, &d->url); if (r < 0) satip_discovery_destroy(d, 1); } } if (TAILQ_FIRST(&satip_discoveries)) gtimer_arm(&satip_discovery_timerq, satip_discovery_timerq_cb, NULL, 5); }
void tvhdhomerun_device_destroy( tvhdhomerun_device_t *hd ) { tvhdhomerun_frontend_t *lfe; lock_assert(&global_lock); mtimer_disarm(&hd->hd_destroy_timer); idnode_save_check(&hd->th_id, 0); tvhinfo(LS_TVHDHOMERUN, "Releasing locks for devices"); while ((lfe = TAILQ_FIRST(&hd->hd_frontends)) != NULL) { tvhdhomerun_frontend_delete(lfe); } #define FREEM(x) free(hd->hd_info.x) FREEM(friendlyname); FREEM(uuid); FREEM(deviceModel); #undef FREEM tvh_hardware_delete((tvh_hardware_t*)hd); #define FREEM(x) free(hd->x) FREEM(hd_override_type); #undef FREEM free(hd); }
/* * Stop connection */ static void iptv_rtsp_stop ( iptv_mux_t *im ) { rtsp_priv_t *rp = im->im_data; int play; lock_assert(&global_lock); if (rp == NULL) return; play = rp->play; im->im_data = NULL; rp->hc->hc_aux = NULL; if (play) rtsp_teardown(rp->hc, rp->path, ""); pthread_mutex_unlock(&iptv_lock); gtimer_disarm(&rp->alive_timer); udp_multirecv_free(&rp->um); if (!play) http_client_close(rp->hc); free(rp->path); free(rp->query); rtcp_destroy(rp->rtcp_info); free(rp->rtcp_info); free(rp); pthread_mutex_lock(&iptv_lock); }
void timeshift_destroy(streaming_target_t *pad) { timeshift_t *ts = (timeshift_t*)pad; streaming_message_t *sm; /* 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); close(ts->rd_pipe.rd); close(ts->rd_pipe.wr); /* Flush files */ timeshift_filemgr_flush(ts, NULL); free(ts->path); free(ts); }
static void satip_discovery_static(const char *descurl) { satip_discovery_t *d; lock_assert(&global_lock); if (satip_device_find_by_descurl(descurl)) return; d = calloc(1, sizeof(satip_discovery_t)); if (urlparse(descurl, &d->url)) { satip_discovery_destroy(d, 0); return; } d->myaddr = strdup(""); d->location = strdup(descurl); d->server = strdup(""); d->uuid = strdup(""); d->bootid = strdup(""); d->configid = strdup(""); d->deviceid = strdup(""); TAILQ_INSERT_TAIL(&satip_discoveries, d, disc_link); satip_discoveries_count++; satip_discovery_timerq_cb(NULL); }
void bouquet_destroy_by_channel_tag(channel_tag_t *ct) { bouquet_t *bq; lock_assert(&global_lock); RB_FOREACH(bq, &bouquets, bq_link) if (bq->bq_chtag_ptr == ct) bq->bq_chtag_ptr = NULL; }
void gtimer_arm_abs(gtimer_t *gti, gti_callback_t *callback, void *opaque, time_t when) { lock_assert(&global_lock); if(gti->gti_callback != NULL) LIST_REMOVE(gti, gti_link); gti->gti_callback = callback; gti->gti_opaque = opaque; gti->gti_expire = when; LIST_INSERT_SORTED(>imers, gti, gti_link, gtimercmp); }
void bouquet_destroy_by_service(service_t *t) { bouquet_t *bq; service_lcn_t *sl; lock_assert(&global_lock); RB_FOREACH(bq, &bouquets, bq_link) if (idnode_set_exists(bq->bq_services, &t->s_id)) idnode_set_remove(bq->bq_services, &t->s_id); while ((sl = LIST_FIRST(&t->s_lcns)) != NULL) { LIST_REMOVE(sl, sl_link); free(sl); } }
/** * Create timeshift buffer * * max_period of buffer in seconds (0 = unlimited) * max_size of buffer in bytes (0 = unlimited) */ streaming_target_t *timeshift_create (streaming_target_t *out, time_t max_time) { timeshift_t *ts = calloc(1, sizeof(timeshift_t)); memoryinfo_alloc(×hift_memoryinfo, sizeof(timeshift_t)); /* Must hold global lock */ lock_assert(&global_lock); /* Setup structure */ TAILQ_INIT(&ts->files); ts->output = out; ts->path = NULL; ts->max_time = max_time; ts->state = TS_LIVE; ts->exit = 0; ts->full = 0; ts->vididx = -1; ts->id = timeshift_index; ts->ondemand = timeshift_conf.ondemand; ts->dobuf = ts->ondemand ? 0 : 1; ts->packet_mode= 1; ts->last_wr_time = 0; ts->buf_time = 0; ts->start_pts = 0; ts->ref_time = 0; ts->seek.file = NULL; ts->seek.frame = NULL; ts->ram_segments = 0; ts->file_segments = 0; pthread_mutex_init(&ts->state_mutex, NULL); /* Initialise output */ tvh_pipe(O_NONBLOCK, &ts->rd_pipe); /* Initialise input */ streaming_queue_init(&ts->wr_queue, 0, 0); streaming_target_init(&ts->input, ×hift_input_ops, ts, 0); tvhthread_create(&ts->wr_thread, NULL, timeshift_writer, ts, "tshift-wr"); tvhthread_create(&ts->rd_thread, NULL, timeshift_reader, ts, "tshift-rd"); /* Update index */ timeshift_index++; return &ts->input; }
bouquet_t * bouquet_create(const char *uuid, htsmsg_t *conf, const char *name, const char *src) { bouquet_t *bq, *bq2; int i; lock_assert(&global_lock); bq = calloc(1, sizeof(bouquet_t)); bq->bq_services = idnode_set_create(1); bq->bq_active_services = idnode_set_create(1); if (idnode_insert(&bq->bq_id, uuid, &bouquet_class, 0)) { if (uuid) tvherror("bouquet", "invalid uuid '%s'", uuid); free(bq); return NULL; } if (conf) { bq->bq_in_load = 1; idnode_load(&bq->bq_id, conf); bq->bq_in_load = 0; if (!htsmsg_get_bool(conf, "shield", &i) && i) bq->bq_shield = 1; } if (name) { free(bq->bq_name); bq->bq_name = strdup(name); } if (src) { free(bq->bq_src); bq->bq_src = strdup(src); } bq2 = RB_INSERT_SORTED(&bouquets, bq, bq_link, _bq_cmp); assert(bq2 == NULL); bq->bq_saveflag = 1; return bq; }
void epggrab_ota_queue_mux( mpegts_mux_t *mm ) { epggrab_ota_mux_t *om; int epg_flag; if (!mm) return; lock_assert(&global_lock); epg_flag = mm->mm_is_epg(mm); if (epg_flag < 0 || epg_flag == MM_EPG_DISABLE) return; om = epggrab_ota_find_mux(mm); if (om && epggrab_ota_queue_one(om)) epggrab_ota_kick(4); }
/** * Create timeshift buffer * * max_period of buffer in seconds (0 = unlimited) * max_size of buffer in bytes (0 = unlimited) */ streaming_target_t *timeshift_create (streaming_target_t *out, time_t max_time) { timeshift_t *ts = calloc(1, sizeof(timeshift_t)); int i; /* Must hold global lock */ lock_assert(&global_lock); /* Setup structure */ TAILQ_INIT(&ts->files); ts->output = out; ts->path = NULL; ts->max_time = max_time; ts->state = TS_INIT; ts->full = 0; ts->vididx = -1; ts->id = timeshift_index; ts->ondemand = timeshift_conf.ondemand; ts->dobuf = ts->ondemand ? 0 : 1; ts->packet_mode= 1; ts->last_time = 0; ts->start_pts = 0; ts->ref_time = 0; for (i = 0; i < TIMESHIFT_BACKLOG_MAX; i++) TAILQ_INIT(&ts->backlog[i]); pthread_mutex_init(&ts->rdwr_mutex, NULL); pthread_mutex_init(&ts->state_mutex, NULL); /* Initialise output */ tvh_pipe(O_NONBLOCK, &ts->rd_pipe); /* Initialise input */ streaming_queue_init(&ts->wr_queue, 0, 0); streaming_target_init(&ts->input, timeshift_input, ts, 0); tvhthread_create(&ts->wr_thread, NULL, timeshift_writer, ts, "tshift-wr"); tvhthread_create(&ts->rd_thread, NULL, timeshift_reader, ts, "tshift-rd"); /* Update index */ timeshift_index++; return &ts->input; }
void timeshift_packets_clone ( timeshift_t *ts, struct streaming_message_queue *dst, int delivered ) { streaming_message_t *lowest, *sm, *sm2; struct streaming_message_queue *sq, *sq2, *backlogs; th_pkt_t *pkt; int i; lock_assert(&ts->state_mutex); /* init temporary queues and copy the backlog data */ backlogs = alloca(ts->backlog_max * sizeof(*backlogs)); for (i = 0; i < ts->backlog_max; i++) { sq = &backlogs[i]; sq2 = &ts->backlog[i]; TAILQ_INIT(sq); TAILQ_FOREACH(sm, sq2, sm_link) { if (!delivered) { pkt = sm->sm_data; if (pkt->pkt_delivered) continue; } sm2 = streaming_msg_clone(sm); TAILQ_INSERT_TAIL(sq, sm2, sm_link); } } /* push to destination (pts sorted) */ while (1) { lowest = NULL; for (i = 0; i < ts->backlog_max; i++) { sq = &backlogs[i]; sm = TAILQ_FIRST(sq); if (sm && (lowest == NULL || lowest->sm_time > sm->sm_time)) lowest = sm; } if (!lowest) break; TAILQ_REMOVE(sq, lowest, sm_link); TAILQ_INSERT_TAIL(dst, lowest, sm_link); } }
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); }
void gtimer_arm_abs2 (gtimer_t *gti, gti_callback_t *callback, void *opaque, struct timespec *when) { lock_assert(&global_lock); if (gti->gti_callback != NULL) LIST_REMOVE(gti, gti_link); gti->gti_callback = callback; gti->gti_opaque = opaque; gti->gti_expire = *when; LIST_INSERT_SORTED(>imers, gti, gti_link, gtimercmp); //tvhdebug("gtimer", "%p @ %ld.%09ld", gti, when->tv_sec, when->tv_nsec); if (LIST_FIRST(>imers) == gti) pthread_cond_signal(>imer_cond); // force timer re-check }
bouquet_t * bouquet_find_by_source(const char *name, const char *src, int create) { bouquet_t *bq; bouquet_t bqs; assert(src); lock_assert(&global_lock); bqs.bq_src = (char *)src; bq = RB_FIND(&bouquets, &bqs, bq_link, _bq_cmp); if (bq) { if (name && *name && strcmp(name, bq->bq_name)) { tvhwarn("bouquet", "bouquet name '%s' changed to '%s'", bq->bq_name ?: "", name); free(bq->bq_name); bq->bq_name = strdup(name); } return bq; }
void GTIMER_FCN(gtimer_arm_absn) (GTIMER_TRACEID_ gtimer_t *gti, gti_callback_t *callback, void *opaque, time_t when) { lock_assert(&global_lock); if (gti->gti_callback != NULL) LIST_REMOVE(gti, gti_link); gti->gti_callback = callback; gti->gti_opaque = opaque; gti->gti_expire = when; #if ENABLE_GTIMER_CHECK gti->gti_id = id; #endif LIST_INSERT_SORTED(>imers, gti, gti_link, gtimercmp); if (LIST_FIRST(>imers) == gti) pthread_cond_signal(>imer_cond); // force timer re-check }
void GTIMER_FCN(mtimer_arm_abs) (GTIMER_TRACEID_ mtimer_t *mti, mti_callback_t *callback, void *opaque, int64_t when) { lock_assert(&global_lock); if (mti->mti_callback != NULL) LIST_REMOVE(mti, mti_link); mti->mti_callback = callback; mti->mti_opaque = opaque; mti->mti_expire = when; #if ENABLE_GTIMER_CHECK mti->mti_id = id; #endif LIST_INSERT_SORTED(&mtimers, mti, mti_link, mtimercmp); if (LIST_FIRST(&mtimers) == mti) tvh_cond_signal(&mtimer_cond, 0); // force timer re-check }
/** * Create timeshift buffer * * max_period of buffer in seconds (0 = unlimited) * max_size of buffer in bytes (0 = unlimited) */ streaming_target_t *timeshift_create (streaming_target_t *out, time_t max_time) { char buf[512]; timeshift_t *ts = calloc(1, sizeof(timeshift_t)); /* Must hold global lock */ lock_assert(&global_lock); /* Create directories */ if (timeshift_filemgr_makedirs(timeshift_index, buf, sizeof(buf))) return NULL; /* Setup structure */ TAILQ_INIT(&ts->files); ts->output = out; ts->path = strdup(buf); ts->max_time = max_time; ts->state = TS_INIT; ts->full = 0; ts->vididx = -1; ts->id = timeshift_index; ts->ondemand = timeshift_ondemand; pthread_mutex_init(&ts->rdwr_mutex, NULL); pthread_mutex_init(&ts->state_mutex, NULL); /* Initialise output */ tvh_pipe(O_NONBLOCK, &ts->rd_pipe); /* Initialise input */ streaming_queue_init(&ts->wr_queue, 0); streaming_target_init(&ts->input, timeshift_input, ts, 0); pthread_create(&ts->wr_thread, NULL, timeshift_writer, ts); pthread_create(&ts->rd_thread, NULL, timeshift_reader, ts); /* Update index */ timeshift_index++; return &ts->input; }
void satip_device_destroy( satip_device_t *sd ) { satip_frontend_t *lfe; lock_assert(&global_lock); gtimer_disarm(&sd->sd_destroy_timer); while ((lfe = TAILQ_FIRST(&sd->sd_frontends)) != NULL) satip_frontend_delete(lfe); satip_device_dbus_notify(sd, "stop"); #define FREEM(x) free(sd->sd_info.x) FREEM(myaddr); FREEM(addr); FREEM(uuid); FREEM(bootid); FREEM(configid); FREEM(deviceid); FREEM(location); FREEM(server); FREEM(friendlyname); FREEM(manufacturer); FREEM(manufacturerURL); FREEM(modeldesc); FREEM(modelname); FREEM(modelnum); FREEM(serialnum); FREEM(presentation); FREEM(tunercfg); #undef FREEM free(sd->sd_bindaddr); free(sd->sd_tunercfg); tvh_hardware_delete((tvh_hardware_t*)sd); free(sd); }
/** * Create timeshift buffer * * max_period of buffer in seconds (0 = unlimited) * max_size of buffer in bytes (0 = unlimited) */ streaming_target_t *timeshift_create (streaming_target_t *out, time_t max_time) { timeshift_t *ts = calloc(1, sizeof(timeshift_t)); int i; /* Must hold global lock */ lock_assert(&global_lock); /* Setup structure */ TAILQ_INIT(&ts->files); ts->output = out; ts->path = NULL; ts->max_time = max_time; ts->state = TS_INIT; ts->full = 0; ts->vididx = -1; ts->id = timeshift_index; ts->ondemand = timeshift_ondemand; ts->pts_delta = PTS_UNSET; for (i = 0; i < ARRAY_SIZE(ts->pts_val); i++) ts->pts_val[i] = PTS_UNSET; pthread_mutex_init(&ts->rdwr_mutex, NULL); pthread_mutex_init(&ts->state_mutex, NULL); /* Initialise output */ tvh_pipe(O_NONBLOCK, &ts->rd_pipe); /* Initialise input */ streaming_queue_init(&ts->wr_queue, 0, 0); streaming_target_init(&ts->input, timeshift_input, ts, 0); tvhthread_create(&ts->wr_thread, NULL, timeshift_writer, ts); tvhthread_create(&ts->rd_thread, NULL, timeshift_reader, ts); /* Update index */ timeshift_index++; return &ts->input; }
void epggrab_ota_queue_mux( mpegts_mux_t *mm ) { const char *id = idnode_uuid_as_str(&mm->mm_id); epggrab_ota_mux_t *om; int epg_flag; if (!mm) return; lock_assert(&global_lock); epg_flag = mm->mm_is_epg(mm); if (epg_flag < 0 || epg_flag == MM_EPG_DISABLE) return; RB_FOREACH(om, &epggrab_ota_all, om_global_link) if (!strcmp(om->om_mux_uuid, id)) { if (epggrab_ota_queue_one(om)) epggrab_ota_kick(4); break; } }