service: service listing was broken
I think it was quite possible for two services on the same multiplex not to share the same tuner. Also I wasn't convinced about how it kicked running services.
This commit is contained in:
parent
3fec2653ff
commit
fe9bd60192
5 changed files with 68 additions and 45 deletions
|
@ -156,7 +156,7 @@ mpegts_service_config_save(service_t *t)
|
|||
static void
|
||||
mpegts_service_enlist(service_t *t, struct service_instance_list *sil)
|
||||
{
|
||||
int p = 0, w; // TODO: priority
|
||||
int p = 0, w;
|
||||
mpegts_service_t *s = (mpegts_service_t*)t;
|
||||
mpegts_mux_t *m = s->s_dvb_mux;
|
||||
mpegts_mux_instance_t *mmi;
|
||||
|
@ -173,11 +173,15 @@ mpegts_service_enlist(service_t *t, struct service_instance_list *sil)
|
|||
|
||||
if (!mmi->mmi_input->mi_is_enabled(mmi->mmi_input)) continue;
|
||||
|
||||
/* Set weight to 0 for already active mux */
|
||||
if (mmi->mmi_mux->mm_active == mmi)
|
||||
w = 0;
|
||||
else
|
||||
/* Set weight to -1 (forced) for already active mux */
|
||||
if (mmi->mmi_mux->mm_active == mmi) {
|
||||
w = -1;
|
||||
p = -1;
|
||||
} else {
|
||||
w = mmi->mmi_input->mi_current_weight(mmi->mmi_input);
|
||||
p = 0;//mmi->mmi_input->mi_priority(mmi->mmi_input);
|
||||
}
|
||||
|
||||
service_instance_add(sil, t, mmi->mmi_input->mi_instance, p, w);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -377,58 +377,68 @@ service_start(service_t *t, int instance)
|
|||
* Main entry point for starting a service based on a channel
|
||||
*/
|
||||
service_instance_t *
|
||||
service_find_instance(service_t *s, channel_t *ch, struct service_instance_list *sil,
|
||||
int *error, int weight)
|
||||
service_find_instance
|
||||
(service_t *s, channel_t *ch, service_instance_list_t *sil,
|
||||
int *error, int weight)
|
||||
{
|
||||
channel_service_mapping_t *csm;
|
||||
service_instance_t *si, *next;
|
||||
|
||||
lock_assert(&global_lock);
|
||||
|
||||
// First, update list of candidates
|
||||
|
||||
LIST_FOREACH(si, sil, si_link)
|
||||
/* Build list */
|
||||
TAILQ_FOREACH(si, sil, si_link)
|
||||
si->si_mark = 1;
|
||||
|
||||
if (ch) {
|
||||
LIST_FOREACH(csm, &ch->ch_services, csm_chn_link) {
|
||||
s = csm->csm_svc;
|
||||
if (!s->s_is_enabled(s)) continue;
|
||||
s->s_enlist(s, sil);
|
||||
if (s->s_is_enabled(s))
|
||||
s->s_enlist(s, sil);
|
||||
}
|
||||
} else {
|
||||
s->s_enlist(s, sil);
|
||||
}
|
||||
|
||||
for(si = LIST_FIRST(sil); si != NULL; si = next) {
|
||||
next = LIST_NEXT(si, si_link);
|
||||
/* Clean */
|
||||
for(si = TAILQ_FIRST(sil); si != NULL; si = next) {
|
||||
next = TAILQ_NEXT(si, si_link);
|
||||
if(si->si_mark)
|
||||
service_instance_destroy(si);
|
||||
service_instance_destroy(sil, si);
|
||||
}
|
||||
|
||||
/* Debug */
|
||||
TAILQ_FOREACH(si, sil, si_link) {
|
||||
const char *name = ch ? ch->ch_name : NULL;
|
||||
if (!name && s) name = s->s_nicename;
|
||||
tvhdebug("service", "%s si %p weight %d prio %d error %d\n",
|
||||
name, si, si->si_weight, si->si_prio, si->si_error);
|
||||
}
|
||||
|
||||
// Check if any service is already running, if so, use that
|
||||
LIST_FOREACH(si, sil, si_link)
|
||||
/* Already running? */
|
||||
TAILQ_FOREACH(si, sil, si_link)
|
||||
if(si->si_s->s_status == SERVICE_RUNNING && si->si_error == 0)
|
||||
return si;
|
||||
|
||||
// Check if any is idle
|
||||
LIST_FOREACH(si, sil, si_link)
|
||||
if(si->si_weight == 0 && si->si_error == 0)
|
||||
/* Forced or Idle */
|
||||
TAILQ_FOREACH(si, sil, si_link)
|
||||
if(si->si_weight <= 0 && si->si_error == 0)
|
||||
break;
|
||||
|
||||
// Check if to kick someone out
|
||||
if(si == NULL) {
|
||||
LIST_FOREACH(si, sil, si_link) {
|
||||
if(si->si_weight < weight && si->si_error == 0)
|
||||
/* Bump someone */
|
||||
if (!si) {
|
||||
TAILQ_FOREACH_REVERSE(si, sil, service_instance_list, si_link)
|
||||
if (weight > si->si_weight && si->si_error == 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Failed */
|
||||
if(si == NULL) {
|
||||
*error = SM_CODE_NO_FREE_ADAPTER;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Start */
|
||||
service_start(si->si_s, si->si_instance);
|
||||
return si;
|
||||
}
|
||||
|
@ -1097,24 +1107,30 @@ service_refresh_channel(service_t *t)
|
|||
|
||||
|
||||
/**
|
||||
*
|
||||
* Weight then prio?
|
||||
*/
|
||||
static int
|
||||
si_cmp(const service_instance_t *a, const service_instance_t *b)
|
||||
{
|
||||
return a->si_prio - b->si_prio;
|
||||
int r;
|
||||
r = a->si_weight - b->si_weight;
|
||||
if (!r)
|
||||
r = a->si_prio - b->si_prio;
|
||||
return r;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
service_instance_t *
|
||||
service_instance_add(struct service_instance_list *sil,
|
||||
service_instance_add(service_instance_list_t *sil,
|
||||
struct service *s, int instance, int prio,
|
||||
int weight)
|
||||
{
|
||||
service_instance_t *si;
|
||||
LIST_FOREACH(si, sil, si_link)
|
||||
|
||||
/* Existing */
|
||||
TAILQ_FOREACH(si, sil, si_link)
|
||||
if(si->si_s == s && si->si_instance == instance)
|
||||
break;
|
||||
|
||||
|
@ -1128,11 +1144,11 @@ service_instance_add(struct service_instance_list *sil,
|
|||
si->si_mark = 0;
|
||||
if(si->si_prio == prio && si->si_weight == weight)
|
||||
return si;
|
||||
LIST_REMOVE(si, si_link);
|
||||
TAILQ_REMOVE(sil, si, si_link);
|
||||
}
|
||||
si->si_weight = weight;
|
||||
si->si_prio = prio;
|
||||
LIST_INSERT_SORTED(sil, si, si_link, si_cmp);
|
||||
si->si_prio = prio;
|
||||
TAILQ_INSERT_SORTED(sil, si, si_link, si_cmp);
|
||||
return si;
|
||||
}
|
||||
|
||||
|
@ -1141,9 +1157,10 @@ service_instance_add(struct service_instance_list *sil,
|
|||
*
|
||||
*/
|
||||
void
|
||||
service_instance_destroy(service_instance_t *si)
|
||||
service_instance_destroy
|
||||
(service_instance_list_t *sil, service_instance_t *si)
|
||||
{
|
||||
LIST_REMOVE(si, si_link);
|
||||
TAILQ_REMOVE(sil, si, si_link);
|
||||
service_unref(si->si_s);
|
||||
free(si);
|
||||
}
|
||||
|
@ -1153,13 +1170,13 @@ service_instance_destroy(service_instance_t *si)
|
|||
*
|
||||
*/
|
||||
void
|
||||
service_instance_list_clear(struct service_instance_list *sil)
|
||||
service_instance_list_clear(service_instance_list_t *sil)
|
||||
{
|
||||
lock_assert(&global_lock);
|
||||
|
||||
service_instance_t *si;
|
||||
while((si = LIST_FIRST(sil)) != NULL)
|
||||
service_instance_destroy(si);
|
||||
while((si = TAILQ_FIRST(sil)) != NULL)
|
||||
service_instance_destroy(sil, si);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -128,14 +128,14 @@ typedef struct elementary_stream {
|
|||
} elementary_stream_t;
|
||||
|
||||
|
||||
LIST_HEAD(service_instance_list, service_instance);
|
||||
typedef TAILQ_HEAD(service_instance_list, service_instance) service_instance_list_t;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
typedef struct service_instance {
|
||||
|
||||
LIST_ENTRY(service_instance) si_link;
|
||||
TAILQ_ENTRY(service_instance) si_link;
|
||||
|
||||
int si_prio;
|
||||
|
||||
|
@ -162,15 +162,16 @@ typedef struct service_instance {
|
|||
/**
|
||||
*
|
||||
*/
|
||||
service_instance_t *service_instance_add(struct service_instance_list *sil,
|
||||
service_instance_t *service_instance_add(service_instance_list_t *sil,
|
||||
struct service *s,
|
||||
int instance,
|
||||
int prio,
|
||||
int weight);
|
||||
|
||||
void service_instance_destroy(service_instance_t *si);
|
||||
void service_instance_destroy
|
||||
(service_instance_list_t *sil, service_instance_t *si);
|
||||
|
||||
void service_instance_list_clear(struct service_instance_list *sil);
|
||||
void service_instance_list_clear(service_instance_list_t *sil);
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -268,7 +269,7 @@ typedef struct service {
|
|||
|
||||
int (*s_is_enabled)(struct service *t);
|
||||
|
||||
void (*s_enlist)(struct service *s, struct service_instance_list *sil);
|
||||
void (*s_enlist)(struct service *s, service_instance_list_t *sil);
|
||||
|
||||
int (*s_start_feed)(struct service *s, int instance);
|
||||
|
||||
|
@ -442,7 +443,7 @@ service_t *service_find(const char *identifier);
|
|||
|
||||
service_instance_t *service_find_instance(struct service *s,
|
||||
struct channel *ch,
|
||||
struct service_instance_list *sil,
|
||||
service_instance_list_t *sil,
|
||||
int *error,
|
||||
int weight);
|
||||
|
||||
|
|
|
@ -422,6 +422,7 @@ subscription_create
|
|||
th_subscription_t *s = calloc(1, sizeof(th_subscription_t));
|
||||
int reject = 0;
|
||||
static int tally;
|
||||
TAILQ_INIT(&s->ths_instances);
|
||||
|
||||
if(flags & SUBSCRIPTION_NONE)
|
||||
reject |= (SMT_TO_MASK(SMT_PACKET) | SMT_TO_MASK(SMT_MPEGTS));
|
||||
|
|
|
@ -74,7 +74,7 @@ typedef struct th_subscription {
|
|||
/**
|
||||
* This is the list of service candidates we have
|
||||
*/
|
||||
struct service_instance_list ths_instances;
|
||||
service_instance_list_t ths_instances;
|
||||
struct service_instance *ths_current_instance;
|
||||
|
||||
#if ENABLE_MPEGTS
|
||||
|
|
Loading…
Add table
Reference in a new issue