diff --git a/src/input/mpegts.h b/src/input/mpegts.h index 59bb3086..d0400af3 100644 --- a/src/input/mpegts.h +++ b/src/input/mpegts.h @@ -34,6 +34,7 @@ typedef struct mpegts_network mpegts_network_t; typedef struct mpegts_mux mpegts_mux_t; typedef struct mpegts_service mpegts_service_t; typedef struct mpegts_mux_instance mpegts_mux_instance_t; +typedef struct mpegts_mux_sub mpegts_mux_sub_t; typedef struct mpegts_input mpegts_input_t; typedef struct mpegts_table_feed mpegts_table_feed_t; @@ -251,8 +252,9 @@ struct mpegts_mux void (*mm_config_save) (mpegts_mux_t *mm); void (*mm_display_name) (mpegts_mux_t*, char *buf, size_t len); int (*mm_is_enabled) (mpegts_mux_t *mm); - int (*mm_start) (mpegts_mux_t *mm, const char *r, int w); - void (*mm_stop) (mpegts_mux_t *mm); + int (*mm_start) (mpegts_mux_t *mm, + void *src, const char *r, int w); + void (*mm_stop) (mpegts_mux_t *mm, void *src, int force); void (*mm_open_table) (mpegts_mux_t*,mpegts_table_t*); void (*mm_close_table) (mpegts_mux_t*,mpegts_table_t*); void (*mm_create_instances) (mpegts_mux_t*); @@ -349,12 +351,21 @@ struct mpegts_mux_instance mpegts_mux_t *mmi_mux; mpegts_input_t *mmi_input; + RB_HEAD(,mpegts_mux_sub) mmi_subs; + // TODO: remove this int mmi_tune_failed; // this is really DVB void (*mmi_delete) (mpegts_mux_instance_t *mmi); }; +struct mpegts_mux_sub +{ + RB_ENTRY(mpegts_mux_sub) mms_link; + void *mms_src; + int mms_weight; +}; + /* Input source */ struct mpegts_input { @@ -512,7 +523,8 @@ mpegts_mux_instance_t *mpegts_mux_instance_create0 (struct type*)mpegts_mux_instance_create0(calloc(1, sizeof(struct type)),\ &type##_class, uuid,\ mi, mm); -int mpegts_mux_instance_start ( mpegts_mux_instance_t **mmiptr ); +int mpegts_mux_instance_start + ( mpegts_mux_instance_t **mmiptr, void *src, int weight ); int mpegts_mux_set_tsid ( mpegts_mux_t *mm, uint16_t tsid ); int mpegts_mux_set_onid ( mpegts_mux_t *mm, uint16_t onid ); diff --git a/src/input/mpegts/linuxdvb/linuxdvb_frontend.c b/src/input/mpegts/linuxdvb/linuxdvb_frontend.c index bd6838b8..874c10a8 100644 --- a/src/input/mpegts/linuxdvb/linuxdvb_frontend.c +++ b/src/input/mpegts/linuxdvb/linuxdvb_frontend.c @@ -673,7 +673,7 @@ linuxdvb_frontend_tune0 return 0; /* Stop current */ - cur->mmi_mux->mm_stop(cur->mmi_mux); + cur->mmi_mux->mm_stop(cur->mmi_mux, NULL, 1); } assert(LIST_FIRST(&lfe->mi_mux_active) == NULL); diff --git a/src/input/mpegts/mpegts_input.c b/src/input/mpegts/mpegts_input.c index 79b39c75..9bc5de8c 100644 --- a/src/input/mpegts/mpegts_input.c +++ b/src/input/mpegts/mpegts_input.c @@ -93,6 +93,7 @@ int mpegts_input_current_weight ( mpegts_input_t *mi ) { const mpegts_mux_instance_t *mmi; + const mpegts_mux_sub_t *mms; const service_t *s; const th_subscription_t *ths; int w = 0; @@ -101,10 +102,8 @@ mpegts_input_current_weight ( mpegts_input_t *mi ) /* Check for scan (weight 1) */ LIST_FOREACH(mmi, &mi->mi_mux_active, mmi_active_link) { - if (mmi->mmi_mux->mm_initial_scan_status == MM_SCAN_CURRENT) { - w = 1; - break; - } + RB_FOREACH(mms, &mmi->mmi_subs, mms_link) + w = MAX(w, mms->mms_weight); } /* Check subscriptions */ diff --git a/src/input/mpegts/mpegts_mux.c b/src/input/mpegts/mpegts_mux.c index b7143d53..5dd688da 100644 --- a/src/input/mpegts/mpegts_mux.c +++ b/src/input/mpegts/mpegts_mux.c @@ -68,8 +68,17 @@ mpegts_mux_instance_create0 return mmi; } +static int +mms_cmp ( mpegts_mux_sub_t *a, mpegts_mux_sub_t *b ) +{ + if (a->mms_src < b->mms_src) return -1; + if (a->mms_src > b->mms_src) return 1; + return 0; +} + int -mpegts_mux_instance_start ( mpegts_mux_instance_t **mmiptr ) +mpegts_mux_instance_start + ( mpegts_mux_instance_t **mmiptr, void *src, int weight ) { int r; char buf[256], buf2[256];; @@ -91,6 +100,21 @@ mpegts_mux_instance_start ( mpegts_mux_instance_t **mmiptr ) r = mmi->mmi_input->mi_start_mux(mmi->mmi_input, mmi); if (r) return r; + /* Add sub */ + if (src) { + mpegts_mux_sub_t *sub; + static mpegts_mux_sub_t *skel = NULL; + if (!skel) + skel = calloc(1, sizeof(mpegts_mux_sub_t)); + skel->mms_src = src; + sub = RB_INSERT_SORTED(&mmi->mmi_subs, skel, mms_link, mms_cmp); + if (!sub) { + sub = skel; + skel = NULL; + sub->mms_weight = weight; + } + } + /* Start */ tvhdebug("mpegts", "%s - started", buf); mmi->mmi_input->mi_started_mux(mmi->mmi_input, mmi); @@ -251,7 +275,7 @@ mpegts_mux_delete ( mpegts_mux_t *mm ) tvhinfo("mpegts", "%s - deleting", buf); /* Stop */ - mm->mm_stop(mm); + mm->mm_stop(mm, NULL, 1); /* Remove from lists */ LIST_REMOVE(mm, mm_network_link); @@ -290,7 +314,8 @@ mpegts_mux_create_instances ( mpegts_mux_t *mm ) } static int -mpegts_mux_start ( mpegts_mux_t *mm, const char *reason, int weight ) +mpegts_mux_start + ( mpegts_mux_t *mm, void *src, const char *reason, int weight ) { int pass, fail; char buf[256]; @@ -353,7 +378,7 @@ mpegts_mux_start ( mpegts_mux_t *mm, const char *reason, int weight ) if (tune) { tvhinfo("mpegts", "%s - starting for '%s' (weight %d)", buf, reason, weight); - if (!(fail = mpegts_mux_instance_start(&tune))) break; + if (!(fail = mpegts_mux_instance_start(&tune, src, weight))) break; tune = NULL; tvhwarn("mpegts", "%s - failed to start, try another", buf); } @@ -371,12 +396,44 @@ mpegts_mux_start ( mpegts_mux_t *mm, const char *reason, int weight ) return 0; } +static int +mpegts_mux_has_subscribers ( mpegts_mux_t *mm ) +{ + mpegts_mux_instance_t *mmi = mm->mm_active; + if (mmi) { + if (RB_FIRST(&mmi->mmi_subs)) + return 1; + return mmi->mmi_input->mi_has_subscription(mmi->mmi_input, mm); + } + return 0; +} + static void -mpegts_mux_stop ( mpegts_mux_t *mm ) +mpegts_mux_stop ( mpegts_mux_t *mm, void *src, int force ) { char buf[256]; mpegts_mux_instance_t *mmi = mm->mm_active; mpegts_input_t *mi = NULL; + mpegts_mux_sub_t *sub, skel; + + /* Remove subs */ + if (mmi) { + if (force) { + while ((sub = RB_FIRST(&mmi->mmi_subs))) { + RB_REMOVE(&mmi->mmi_subs, sub, mms_link); + free(sub); + } + } else if (src) { + skel.mms_src = src; + if ((sub = RB_FIND(&mmi->mmi_subs, &skel, mms_link, mms_cmp))) { + RB_REMOVE(&mmi->mmi_subs, sub, mms_link); + free(sub); + } + } + } + + if (mpegts_mux_has_subscribers(mm)) + return; mm->mm_display_name(mm, buf, sizeof(buf)); tvhdebug("mpegts", "%s - stopping mux", buf); @@ -442,15 +499,6 @@ mpegts_mux_close_table ( mpegts_mux_t *mm, mpegts_table_t *mt ) * Scanning * *************************************************************************/ -static int -mpegts_mux_has_subscribers ( mpegts_mux_t *mm ) -{ - mpegts_mux_instance_t *mmi = mm->mm_active; - if (mmi) - return mmi->mmi_input->mi_has_subscription(mmi->mmi_input, mm); - return 0; -} - static void mpegts_mux_initial_scan_link ( mpegts_mux_t *mm ) { @@ -497,10 +545,7 @@ mpegts_mux_initial_scan_done ( mpegts_mux_t *mm ) mpegts_network_schedule_initial_scan(mn); /* Stop */ - if (!mpegts_mux_has_subscribers(mm)) { - tvhtrace("mpegts", "%s - no active subscribers, stop", buf); - mm->mm_stop(mm); - } + mm->mm_stop(mm, mn, 0); /* Save */ mm->mm_initial_scan_done = 1; diff --git a/src/input/mpegts/mpegts_network.c b/src/input/mpegts/mpegts_network.c index 91e82677..8774df67 100644 --- a/src/input/mpegts/mpegts_network.c +++ b/src/input/mpegts/mpegts_network.c @@ -241,7 +241,7 @@ mpegts_network_initial_scan(void *aux) tvhtrace("mpegts", "setup initial scan for %p", mn); while((mm = TAILQ_FIRST(&mn->mn_initial_scan_pending_queue)) != NULL) { assert(mm->mm_initial_scan_status == MM_SCAN_PENDING); - if (mm->mm_start(mm, "initial scan", 1)) + if (mm->mm_start(mm, mn, "initial scan", 1)) break; assert(mm->mm_initial_scan_status == MM_SCAN_CURRENT); } diff --git a/src/input/mpegts/mpegts_service.c b/src/input/mpegts/mpegts_service.c index f3d83810..e68e7de4 100644 --- a/src/input/mpegts/mpegts_service.c +++ b/src/input/mpegts/mpegts_service.c @@ -182,7 +182,7 @@ mpegts_service_start(service_t *t, int instance) return SM_CODE_UNDEFINED_ERROR; /* Start Mux */ - r = mpegts_mux_instance_start(&mmi); + r = mpegts_mux_instance_start(&mmi, NULL, 0); /* Start */ if (!r) { @@ -200,8 +200,9 @@ mpegts_service_start(service_t *t, int instance) static void mpegts_service_stop(service_t *t) { - mpegts_service_t *s = (mpegts_service_t*)t; - mpegts_input_t *i = s->s_dvb_active_input; + mpegts_service_t *s = (mpegts_service_t*)t; + mpegts_mux_t *mm = (mpegts_mux_t*)s->s_dvb_mux; + mpegts_input_t *i = s->s_dvb_active_input; /* Validate */ assert(s->s_source_type == S_MPEG_TS); @@ -209,6 +210,7 @@ mpegts_service_stop(service_t *t) lock_assert(&global_lock); /* Stop */ + mm->mm_stop(mm, NULL, 0); i->mi_close_service(i, s); s->s_status = SERVICE_IDLE; }