diff --git a/Makefile b/Makefile index 2d7cee83..6f8ab599 100644 --- a/Makefile +++ b/Makefile @@ -203,6 +203,7 @@ SRCS-$(CONFIG_MPEGTS) += \ src/input/mpegts/dvb_psi.c \ src/input/mpegts/tsdemux.c \ src/input/mpegts/mpegts_mux_sched.c \ + src/input/mpegts/mpegts_network_scan.c \ # MPEGTS DVB SRCS-${CONFIG_MPEGTS_DVB} += \ diff --git a/src/input.h b/src/input.h index 1597236f..946b21f3 100644 --- a/src/input.h +++ b/src/input.h @@ -116,6 +116,7 @@ void tvh_input_stream_destroy ( tvh_input_stream_t *st ); #if ENABLE_MPEGTS #include "input/mpegts.h" #include "input/mpegts/mpegts_mux_sched.h" +#include "input/mpegts/mpegts_network_scan.h" #if ENABLE_MPEGTS_DVB #include "input/mpegts/mpegts_dvb.h" #endif diff --git a/src/input/mpegts.h b/src/input/mpegts.h index 0e3da176..2fec1bf5 100644 --- a/src/input/mpegts.h +++ b/src/input/mpegts.h @@ -241,14 +241,6 @@ struct mpegts_network */ char *mn_network_name; - /* - * Scanning - */ - mpegts_mux_queue_t mn_initial_scan_pending_queue; - mpegts_mux_queue_t mn_initial_scan_current_queue; - int mn_initial_scan_num; - gtimer_t mn_initial_scan_timer; - /* * Inputs */ @@ -280,6 +272,13 @@ struct mpegts_network char *mn_charset; }; +typedef enum mpegts_mux_scan_state +{ + MM_SCAN_STATE_IDLE, // Nothing + MM_SCAN_STATE_PEND, // Queue'd pending scan + MM_SCAN_STATE_ACTIVE, // Scan is active +} mpegts_mux_scan_state_t; + /* Multiplex */ struct mpegts_mux { @@ -304,17 +303,15 @@ struct mpegts_mux * Scanning */ - int mm_initial_scan_init; - gtimer_t mm_initial_scan_timeout; - TAILQ_ENTRY(mpegts_mux) mm_initial_scan_link; - enum { - MM_SCAN_DONE, // All done - MM_SCAN_PENDING, // Waiting to be tuned for initial scan - MM_SCAN_CURRENT, // Currently tuned for initial scan - } mm_initial_scan_status; - int mm_initial_scan_done; - mpegts_mux_t *mm_dmc_origin; - time_t mm_dmc_origin_expire; + int mm_scan_ok; ///< Has been succesfully scanned + int mm_scan_weight; ///< Scan priority + int mm_scan_init; ///< Flag to timeout handler + gtimer_t mm_scan_timeout; ///< Timer to handle timeout + TAILQ_ENTRY(mpegts_mux) mm_scan_link; ///< Link to Queue + mpegts_mux_scan_state_t mm_scan_state; ///< Scanning state + + mpegts_mux_t *mm_dmc_origin; + time_t mm_dmc_origin_expire; /* * Physical instances @@ -614,9 +611,6 @@ void mpegts_network_class_delete ( const idclass_t *idc, int delconf ); void mpegts_network_delete ( mpegts_network_t *mn, int delconf ); -void mpegts_network_schedule_initial_scan - ( mpegts_network_t *mm ); - int mpegts_network_set_nid ( mpegts_network_t *mn, uint16_t nid ); int mpegts_network_set_network_name ( mpegts_network_t *mn, const char *name ); @@ -639,9 +633,6 @@ mpegts_mux_t *mpegts_mux_create0 #define mpegts_mux_delete_by_uuid(u, delconf)\ { mpegts_mux_t *mm = mpegts_mux_find(u); if (mm) mm->mm_delete(mm, delconf); } -void mpegts_mux_initial_scan_done ( mpegts_mux_t *mm, int log ); -void mpegts_mux_initial_scan_fail ( mpegts_mux_t *mm ); - void mpegts_mux_delete ( mpegts_mux_t *mm, int delconf ); void mpegts_mux_save ( mpegts_mux_t *mm, htsmsg_t *c ); @@ -672,6 +663,8 @@ void mpegts_mux_remove_subscriber(mpegts_mux_t *mm, th_subscription_t *s, int re int mpegts_mux_subscribe(mpegts_mux_t *mm, const char *name, int weight); void mpegts_mux_unsubscribe_by_name(mpegts_mux_t *mm, const char *name); +void mpegts_mux_scan_done ( mpegts_mux_t *mm, const char *buf, int res ); + mpegts_pid_t *mpegts_mux_find_pid_(mpegts_mux_t *mm, int pid, int create); static inline mpegts_pid_t * diff --git a/src/input/mpegts/mpegts_mux.c b/src/input/mpegts/mpegts_mux.c index 80658226..cf69ac55 100644 --- a/src/input/mpegts/mpegts_mux.c +++ b/src/input/mpegts/mpegts_mux.c @@ -27,10 +27,7 @@ SKEL_DECLARE(mpegts_pid_skel, mpegts_pid_t); -static void -mpegts_mux_initial_scan_timeout ( void *aux ); -static void -mpegts_mux_initial_scan_link ( mpegts_mux_t *mm ); +static void mpegts_mux_scan_timeout ( void *p ); /* **************************************************************************** * Mux instance (input linkage) @@ -75,28 +72,20 @@ mpegts_mux_instance_create0 } static void -mpegts_mux_add_to_current +mpegts_mux_scan_active ( mpegts_mux_t *mm, const char *buf, mpegts_input_t *mi ) { int t; - mpegts_network_t *mn = mm->mm_network; - /* Initial scanning */ - if (mm->mm_initial_scan_status == MM_SCAN_PENDING) { - tvhtrace("mpegts", "%s - adding to current scan Q", buf); - TAILQ_REMOVE(&mn->mn_initial_scan_pending_queue, mm, - mm_initial_scan_link); - mm->mm_initial_scan_status = MM_SCAN_CURRENT; - mm->mm_initial_scan_init = 0; - TAILQ_INSERT_TAIL(&mn->mn_initial_scan_current_queue, mm, - mm_initial_scan_link); + /* Setup scan */ + if (mm->mm_scan_state == MM_SCAN_STATE_PEND) { + mpegts_network_scan_mux_active(mm); /* Get timeout */ t = mpegts_input_grace(mi, mm); /* Setup timeout */ - gtimer_arm(&mm->mm_initial_scan_timeout, - mpegts_mux_initial_scan_timeout, mm, t); + gtimer_arm(&mm->mm_scan_timeout, mpegts_mux_scan_timeout, mm, t); } } @@ -114,7 +103,7 @@ mpegts_mux_instance_start if (mm->mm_active) { *mmiptr = mm->mm_active; tvhdebug("mpegts", "%s - already active", buf); - mpegts_mux_add_to_current(mm, buf, mmi->mmi_input); + mpegts_mux_scan_active(mm, buf, mmi->mmi_input); return 0; } @@ -132,7 +121,7 @@ mpegts_mux_instance_start mpegts_fire_event(mm, ml_mux_start); /* Link */ - mpegts_mux_add_to_current(mm, buf, mmi->mmi_input); + mpegts_mux_scan_active(mm, buf, mmi->mmi_input); return 0; } @@ -232,23 +221,17 @@ mpegts_mux_class_get_name ( void *ptr ) } static void -mpegts_mux_class_initscan_notify ( void *p ) +mpegts_mux_class_scan_notify ( void *p ) { mpegts_mux_t *mm = p; - mpegts_network_t *mn = mm->mm_network; /* Start */ - if (!mm->mm_initial_scan_done) { - if (mm->mm_initial_scan_status == MM_SCAN_DONE) - mpegts_mux_initial_scan_link(mm); + if (!mm->mm_scan_ok) { + mpegts_network_scan_queue_add(mm, SUBSCRIPTION_PRIO_SCAN_USER); /* Stop */ } else { - if (mm->mm_initial_scan_status == MM_SCAN_CURRENT) - mpegts_mux_initial_scan_done(mm, 1); - else if (mm->mm_initial_scan_status == MM_SCAN_PENDING) - TAILQ_REMOVE(&mn->mn_initial_scan_pending_queue, mm, - mm_initial_scan_link); + mpegts_network_scan_mux_cancel(mm, 0); } } @@ -305,11 +288,12 @@ const idclass_t mpegts_mux_class = }, { .type = PT_BOOL, - .id = "initscan", - .name = "Initial Scan Complete", - .off = offsetof(mpegts_mux_t, mm_initial_scan_done), - .notify = mpegts_mux_class_initscan_notify, + .id = "scanned", + .name = "Scan Complete", + .off = offsetof(mpegts_mux_t, mm_scan_ok), + .notify = mpegts_mux_class_scan_notify, }, + // TODO: need flag for ok/fail and fini/notfini { .type = PT_STR, .id = "charset", @@ -344,7 +328,6 @@ void mpegts_mux_delete ( mpegts_mux_t *mm, int delconf ) { mpegts_mux_instance_t *mmi; - mpegts_network_t *mn = mm->mm_network; mpegts_service_t *s; char buf[256]; @@ -354,13 +337,12 @@ mpegts_mux_delete ( mpegts_mux_t *mm, int delconf ) /* Stop */ mm->mm_stop(mm, 1); - /* Remove from lists */ - LIST_REMOVE(mm, mm_network_link); - if (mm->mm_initial_scan_status != MM_SCAN_DONE) { - TAILQ_REMOVE(&mn->mn_initial_scan_pending_queue, mm, mm_initial_scan_link); - } + /* Cancel scan */ + mpegts_network_scan_mux_cancel(mm, 0); + + /* Remove instances */ while ((mmi = LIST_FIRST(&mm->mm_instances))) { - mmi->mmi_delete(mmi); + mmi->mmi_delete(mmi); } /* Delete services */ @@ -416,7 +398,7 @@ mpegts_mux_start /* Already tuned */ if (mm->mm_active) { tvhtrace("mpegts", "%s - already active", buf); - mpegts_mux_add_to_current(mm, buf, mm->mm_active->mmi_input); + mpegts_mux_scan_active(mm, buf, mm->mm_active->mmi_input); return 0; } @@ -560,19 +542,9 @@ mpegts_mux_stop ( mpegts_mux_t *mm, int force ) } /* Scanning */ - if (mm->mm_initial_scan_status == MM_SCAN_CURRENT) { - tvhtrace("mpegts", "%s - add to pending scan Q", buf); - mpegts_network_t *mn = mm->mm_network; - TAILQ_REMOVE(&mn->mn_initial_scan_current_queue, mm, mm_initial_scan_link); - mm->mm_initial_scan_status = MM_SCAN_PENDING; - gtimer_disarm(&mm->mm_initial_scan_timeout); - if (mm->mm_initial_scan_done) - TAILQ_INSERT_TAIL(&mn->mn_initial_scan_pending_queue, mm, mm_initial_scan_link); - else - TAILQ_INSERT_HEAD(&mn->mn_initial_scan_pending_queue, mm, mm_initial_scan_link); - mpegts_network_schedule_initial_scan(mn); - } + mpegts_network_scan_mux_cancel(mm, 1); + /* Events */ mpegts_fire_event(mm, ml_mux_stop); /* Clear */ @@ -609,33 +581,31 @@ mpegts_mux_close_table ( mpegts_mux_t *mm, mpegts_table_t *mt ) * Scanning * *************************************************************************/ -static void -mpegts_mux_initial_scan_link ( mpegts_mux_t *mm ) +void +mpegts_mux_scan_done ( mpegts_mux_t *mm, const char *buf, int res ) { - char buf1[256], buf2[256]; - mpegts_network_t *mn = mm->mm_network; + mpegts_table_t *mt; - assert(mn != NULL); - assert(mm->mm_initial_scan_status == MM_SCAN_DONE); + /* Log */ + LIST_FOREACH(mt, &mm->mm_tables, mt_link) { + if (mt->mt_flags & MT_QUICKREQ) { + const char *s = "not found"; + if (mt->mt_complete) + s = "complete"; + else if (mt->mt_count) + s = "incomplete"; + tvhdebug("mpegts", "%s - %s %s", buf, mt->mt_name, s); + } + } - mm->mm_initial_scan_status = MM_SCAN_PENDING; - if (mm->mm_initial_scan_done) - TAILQ_INSERT_TAIL(&mn->mn_initial_scan_pending_queue, mm, - mm_initial_scan_link); + if (res) + mpegts_network_scan_mux_done(mm); else - TAILQ_INSERT_HEAD(&mn->mn_initial_scan_pending_queue, mm, - mm_initial_scan_link); - mn->mn_initial_scan_num++; - - mn->mn_display_name(mn, buf1, sizeof(buf1)); - mm->mm_display_name(mm, buf2, sizeof(buf2)); - tvhdebug("mpegts", "%s - added %s to scan pending q", - buf1, buf2); - mpegts_network_schedule_initial_scan(mn); + mpegts_network_scan_mux_fail(mm); } static void -mpegts_mux_initial_scan_timeout ( void *aux ) +mpegts_mux_scan_timeout ( void *aux ) { int c, q; char buf[256]; @@ -644,12 +614,12 @@ mpegts_mux_initial_scan_timeout ( void *aux ) mm->mm_display_name(mm, buf, sizeof(buf)); /* Timeout */ - if (mm->mm_initial_scan_init) { + if (mm->mm_scan_init) { tvhinfo("mpegts", "%s - initial scan timed out", buf); - mpegts_mux_initial_scan_done(mm, 0); + mpegts_mux_scan_done(mm, buf, 0); return; } - mm->mm_initial_scan_init = 1; + mm->mm_scan_init = 1; /* Check tables */ c = q = 0; @@ -668,80 +638,19 @@ mpegts_mux_initial_scan_timeout ( void *aux ) /* No DATA - give up now */ if (!c) { tvhinfo("mpegts", "%s - initial scan no data, failed", buf); - mpegts_mux_initial_scan_done(mm, 0); + mpegts_mux_scan_done(mm, buf, 0); /* Pending tables (another 20s - bit arbitrary) */ } else if (q) { tvhinfo("mepgts", "%s - initial scan needs more time", buf); - gtimer_arm(&mm->mm_initial_scan_timeout, - mpegts_mux_initial_scan_timeout, mm, 20); + gtimer_arm(&mm->mm_scan_timeout, mpegts_mux_scan_timeout, mm, 20); return; /* Complete */ } else { - mpegts_mux_initial_scan_done(mm, 1); - } -} - -void -mpegts_mux_initial_scan_done ( mpegts_mux_t *mm, int log ) -{ - char buf[256]; - mpegts_network_t *mn = mm->mm_network; - mpegts_table_t *mt; - - mm->mm_display_name(mm, buf, sizeof(buf)); - - /* Log */ - if (log) tvhinfo("mpegts", "%s - initial scan complete", buf); - LIST_FOREACH(mt, &mm->mm_tables, mt_link) { - if (mt->mt_flags & MT_QUICKREQ) { - const char *s = "not found"; - if (mt->mt_complete) - s = "complete"; - else if (mt->mt_count) - s = "incomplete"; - tvhinfo("mpegts", "%s - %s %s", buf, mt->mt_name, s); - } + mpegts_mux_scan_done(mm, buf, 1); } - - /* Stop */ - gtimer_disarm(&mm->mm_initial_scan_timeout); - assert(mm->mm_initial_scan_status == MM_SCAN_CURRENT); - mn->mn_initial_scan_num--; - mm->mm_initial_scan_status = MM_SCAN_DONE; - TAILQ_REMOVE(&mn->mn_initial_scan_current_queue, mm, mm_initial_scan_link); - mpegts_network_schedule_initial_scan(mn); - - /* Unsubscribe */ - mpegts_mux_unsubscribe_by_name(mm, "initscan"); - - /* Save */ - mm->mm_initial_scan_done = 1; - mm->mm_config_save(mm); - idnode_updated(&mm->mm_id); - idnode_updated(&mm->mm_network->mn_id); -} - -void -mpegts_mux_initial_scan_fail ( mpegts_mux_t *mm ) -{ - char buf[256]; - mpegts_network_t *mn = mm->mm_network; - - /* Stop */ - mm->mm_display_name(mm, buf, sizeof(buf)); - tvhinfo("mpegts", "%s - initial scan failed (remove mux)", buf); - gtimer_disarm(&mm->mm_initial_scan_timeout); - mn->mn_initial_scan_num--; - mm->mm_initial_scan_status = MM_SCAN_DONE; - - /* Save */ - mm->mm_initial_scan_done = 1; - mm->mm_config_save(mm); - idnode_updated(&mm->mm_id); - idnode_updated(&mm->mm_network->mn_id); } /* ************************************************************************** @@ -791,8 +700,8 @@ mpegts_mux_create0 idnode_load(&mm->mm_id, conf); /* Initial scan */ - if (!mm->mm_initial_scan_done || !mn->mn_skipinitscan) - mpegts_mux_initial_scan_link(mm); + if (!mm->mm_scan_ok || !mn->mn_skipinitscan) + mpegts_network_scan_queue_add(mm, SUBSCRIPTION_PRIO_SCAN_INIT); mm->mm_display_name(mm, buf, sizeof(buf)); tvhtrace("mpegts", "%s - created", buf); diff --git a/src/input/mpegts/mpegts_network.c b/src/input/mpegts/mpegts_network.c index c83098f3..0e93ae1d 100644 --- a/src/input/mpegts/mpegts_network.c +++ b/src/input/mpegts/mpegts_network.c @@ -79,15 +79,14 @@ mpegts_network_class_get_num_svc ( void *ptr ) static const void * mpegts_network_class_get_scanq_length ( void *ptr ) { - static int n; + static __thread int n; mpegts_mux_t *mm; mpegts_network_t *mn = ptr; n = 0; - TAILQ_FOREACH(mm, &mn->mn_initial_scan_pending_queue, mm_initial_scan_link) - n++; - TAILQ_FOREACH(mm, &mn->mn_initial_scan_current_queue, mm_initial_scan_link) - n++; + LIST_FOREACH(mm, &mn->mn_muxes, mm_network_link) + if (mm->mm_scan_state != MM_SCAN_STATE_IDLE) + n++; return &n; } @@ -232,13 +231,6 @@ mpegts_network_delete mm->mm_delete(mm, delconf); } - /* Check */ - assert(TAILQ_FIRST(&mn->mn_initial_scan_pending_queue) == NULL); - assert(TAILQ_FIRST(&mn->mn_initial_scan_current_queue) == NULL); - - /* Disable timer */ - gtimer_disarm(&mn->mn_initial_scan_timer); - /* Remove from input */ while ((mnl = LIST_FIRST(&mn->mn_inputs))) mpegts_network_link_delete(mnl); @@ -250,62 +242,6 @@ mpegts_network_delete free(mn); } -/* **************************************************************************** - * Scanning - * ***************************************************************************/ - -static void -mpegts_network_initial_scan(void *aux) -{ - int r; - mpegts_network_t *mn = aux; - mpegts_mux_t *mm, *mark = NULL; - - tvhtrace("mpegts", "setup initial scan for %p", mn); - while((mm = TAILQ_FIRST(&mn->mn_initial_scan_pending_queue)) != NULL) { - - /* Stop */ - if (mm == mark) break; - - assert(mm->mm_initial_scan_status == MM_SCAN_PENDING); - r = mpegts_mux_subscribe(mm, "initscan", SUBSCRIPTION_PRIO_SCAN); - - /* Stop scanning here */ - if (r == SM_CODE_NO_FREE_ADAPTER) - break; - - /* Started */ - if (!r) { - assert(mm->mm_initial_scan_status == MM_SCAN_CURRENT); - continue; - } - - TAILQ_REMOVE(&mn->mn_initial_scan_pending_queue, mm, mm_initial_scan_link); - - /* Available tuners can't be used - * Note: this is subtly different it does not imply there are no free - * tuners, just that none of the free ones can service this mux. - * therefore we move this to the back of the queue and see if we - * can find one we can tune - */ - if (r == SM_CODE_NO_VALID_ADAPTER) { - if (!mark) mark = mm; - TAILQ_INSERT_TAIL(&mn->mn_initial_scan_pending_queue, mm, mm_initial_scan_link); - continue; - } - - /* Remove */ - mpegts_mux_initial_scan_fail(mm); - } - gtimer_arm(&mn->mn_initial_scan_timer, mpegts_network_initial_scan, mn, 10); -} - -void -mpegts_network_schedule_initial_scan ( mpegts_network_t *mn ) -{ - gtimer_arm(&mn->mn_initial_scan_timer, mpegts_network_initial_scan, mn, 0); -} - /* **************************************************************************** * Creation/Config * ***************************************************************************/ @@ -330,10 +266,6 @@ mpegts_network_create0 mn->mn_mux_class = mpegts_network_mux_class; mn->mn_mux_create2 = mpegts_network_mux_create2; - /* Init Qs */ - TAILQ_INIT(&mn->mn_initial_scan_pending_queue); - TAILQ_INIT(&mn->mn_initial_scan_current_queue); - /* Add to global list */ LIST_INSERT_HEAD(&mpegts_network_all, mn, mn_global_link); diff --git a/src/input/mpegts/mpegts_network_scan.c b/src/input/mpegts/mpegts_network_scan.c new file mode 100644 index 00000000..00d89b24 --- /dev/null +++ b/src/input/mpegts/mpegts_network_scan.c @@ -0,0 +1,214 @@ +/* + * Tvheadend - Network Scanner + * + * Copyright (C) 2014 Adam Sutton + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "input.h" + +/****************************************************************************** + * Data + *****************************************************************************/ + +mpegts_mux_queue_t mpegts_network_scan_pend; // Pending muxes +mpegts_mux_queue_t mpegts_network_scan_active; // Active muxes +gtimer_t mpegts_network_scan_timer; // Timer for activity + + +/****************************************************************************** + * Timer + *****************************************************************************/ + +static void mpegts_network_scan_timer_cb ( void *p ); + +static int +mm_cmp ( mpegts_mux_t *a, mpegts_mux_t *b ) +{ + return a->mm_scan_weight - b->mm_scan_weight; +} + +static void +mpegts_network_scan_timer_arm ( int period ) +{ + gtimer_arm(&mpegts_network_scan_timer, + mpegts_network_scan_timer_cb, + NULL, + period); +} + +static void +mpegts_network_scan_timer_cb ( void *p ) +{ + mpegts_mux_t *mm, *mark = NULL; + int r; + + /* Process Q */ + while ((mm = TAILQ_FIRST(&mpegts_network_scan_pend))) { + assert(mm->mm_scan_state == MM_SCAN_STATE_PEND); + + /* Stop (looped) */ + if (mm == mark) break; + + /* Attempt to tune */ + // TODO: change reason? + r = mpegts_mux_subscribe(mm, "scan", mm->mm_scan_weight); + + /* Stop (no free tuners) */ + if (r == SM_CODE_NO_FREE_ADAPTER) + break; + + /* Started */ + if (!r) { + assert(mm->mm_scan_state == MM_SCAN_STATE_ACTIVE); + continue; + } + + /* Available tuners can't be used + * Note: this is subtly different it does not imply there are no free + * tuners, just that none of the free ones can service this mux. + * therefore we move this to the back of the queue and see if we + * can find one we can tune + */ + if (r == SM_CODE_NO_VALID_ADAPTER) { + if (!mark) mark = mm; + TAILQ_INSERT_SORTED(&mpegts_network_scan_pend, mm, mm_scan_link, mm_cmp); + continue; + } + + /* Failed */ + mpegts_network_scan_mux_fail(mm); + } + + /* Re-arm (backstop, most things will auto-rearm at point of next event + * such as timeout of scan or completion) + */ + mpegts_network_scan_timer_arm(10); +} + +/****************************************************************************** + * Mux transition + *****************************************************************************/ + +/* Failed - couldn't start */ +void +mpegts_network_scan_mux_fail ( mpegts_mux_t *mm ) +{ + mm->mm_scan_ok = 0; + mpegts_network_scan_queue_del(mm); +} + +/* Completed succesfully */ +void +mpegts_network_scan_mux_done ( mpegts_mux_t *mm ) +{ + mm->mm_scan_ok = 1; + mpegts_network_scan_queue_del(mm); +} + +/* Failed - no input */ +void +mpegts_network_scan_mux_timeout ( mpegts_mux_t *mm ) +{ + mpegts_network_scan_mux_fail(mm); +} + +/* Interrupted (re-add) */ +void +mpegts_network_scan_mux_cancel ( mpegts_mux_t *mm, int reinsert ) +{ + assert(mm->mm_scan_state == MM_SCAN_STATE_ACTIVE); + + /* Remove */ + mpegts_network_scan_queue_del(mm); + + /* Re-insert */ + if (reinsert) + mpegts_network_scan_queue_add(mm, mm->mm_scan_weight); +} + +/* Mux has been started */ +void +mpegts_network_scan_mux_active ( mpegts_mux_t *mm ) +{ + if (mm->mm_scan_state != MM_SCAN_STATE_PEND) + return; + mm->mm_scan_state = MM_SCAN_STATE_ACTIVE; + mm->mm_scan_init = 0; + TAILQ_REMOVE(&mpegts_network_scan_pend, mm, mm_scan_link); + TAILQ_INSERT_TAIL(&mpegts_network_scan_active, mm, mm_scan_link); +} + +/****************************************************************************** + * Mux queue handling + *****************************************************************************/ + +void +mpegts_network_scan_queue_del ( mpegts_mux_t *mm ) +{ + if (mm->mm_scan_state != MM_SCAN_STATE_IDLE) + TAILQ_REMOVE(&mpegts_network_scan_active, mm, mm_scan_link); + mm->mm_scan_state = MM_SCAN_STATE_IDLE; + gtimer_disarm(&mm->mm_scan_timeout); +} + +void +mpegts_network_scan_queue_add ( mpegts_mux_t *mm, int weight ) +{ + int reload = 0; + + if (weight > mm->mm_scan_weight) { + mm->mm_scan_weight = weight; + reload = 1; + } + + /* Already active */ + if (mm->mm_scan_state == MM_SCAN_STATE_ACTIVE) + return; + + /* Remove entry (or ignore) */ + if (mm->mm_scan_state == MM_SCAN_STATE_PEND) { + if (!reload) + return; + TAILQ_REMOVE(&mpegts_network_scan_pend, mm, mm_scan_link); + } + + /* Add new entry */ + mm->mm_scan_state = MM_SCAN_STATE_PEND; + TAILQ_INSERT_SORTED(&mpegts_network_scan_pend, mm, mm_scan_link, mm_cmp); + mpegts_network_scan_timer_arm(0); +} + +/****************************************************************************** + * Subsystem setup / tear down + *****************************************************************************/ + +void +mpegts_network_scan_init ( void ) +{ + TAILQ_INIT(&mpegts_network_scan_pend); + TAILQ_INIT(&mpegts_network_scan_active); +} + +void +mpegts_network_scan_done ( void ) +{ +} + +/****************************************************************************** + * Editor Configuration + * + * vim:sts=2:ts=2:sw=2:et + *****************************************************************************/ diff --git a/src/input/mpegts/mpegts_network_scan.h b/src/input/mpegts/mpegts_network_scan.h new file mode 100644 index 00000000..9f8a0c58 --- /dev/null +++ b/src/input/mpegts/mpegts_network_scan.h @@ -0,0 +1,55 @@ +/* + * Tvheadend - Network Scanner + * + * Copyright (C) 2014 Adam Sutton + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef __TVH_MPEGTS_NETWORK_SCAN_H__ +#define __TVH_MPEGTS_NETWORK_SCAN_H__ + +#include "tvheadend.h" +#include "cron.h" +#include "idnode.h" +#include "subscriptions.h" + +/* + * Registration functions + */ +void mpegts_network_scan_queue_add ( mpegts_mux_t *mm, int weight ); +void mpegts_network_scan_queue_del ( mpegts_mux_t *mm ); + +/* + * Events + */ +void mpegts_network_scan_mux_fail ( mpegts_mux_t *mm ); +void mpegts_network_scan_mux_done ( mpegts_mux_t *mm ); +void mpegts_network_scan_mux_timeout ( mpegts_mux_t *mm ); +void mpegts_network_scan_mux_cancel ( mpegts_mux_t *mm, int reinsert ); +void mpegts_network_scan_mux_active ( mpegts_mux_t *mm ); + +/* + * Init / Teardown + */ +void mpegts_network_scan_init ( void ); +void mpegts_network_scan_done ( void ); + +#endif /* __TVH_MPEGTS_NETWORK_SCAN_H__*/ + +/****************************************************************************** + * Editor Configuration + * + * vim:sts=2:ts=2:sw=2:et + *****************************************************************************/ diff --git a/src/input/mpegts/mpegts_table.c b/src/input/mpegts/mpegts_table.c index f0be04ad..995ad023 100644 --- a/src/input/mpegts/mpegts_table.c +++ b/src/input/mpegts/mpegts_table.c @@ -24,9 +24,10 @@ static void mpegts_table_fastswitch ( mpegts_mux_t *mm ) { + char buf[256]; mpegts_table_t *mt; - if(mm->mm_initial_scan_status == MM_SCAN_DONE) + if(mm->mm_scan_state != MM_SCAN_STATE_ACTIVE) return; LIST_FOREACH(mt, &mm->mm_tables, mt_link) { @@ -35,8 +36,9 @@ mpegts_table_fastswitch ( mpegts_mux_t *mm ) return; } - tvhlog(LOG_DEBUG, "mpegts", "initial scan for mm %p done", mm); - mpegts_mux_initial_scan_done(mm, 1); + mm->mm_display_name(mm, buf, sizeof(buf)); + tvhinfo("mpegts", "%s initial scan complete", buf); + mpegts_mux_scan_done(mm, buf, 1); } void @@ -181,7 +183,7 @@ mpegts_table_add } else if (flags & MT_SKIPSUBS) { subscribe = 0; } else if (flags & MT_SCANSUBS) { - if (mm->mm_initial_scan_status == MM_SCAN_DONE) + if (mm->mm_scan_ok) subscribe = 0; } if (subscribe) { diff --git a/src/subscriptions.h b/src/subscriptions.h index 86ff2c6c..51163971 100644 --- a/src/subscriptions.h +++ b/src/subscriptions.h @@ -28,10 +28,13 @@ extern struct th_subscription_list subscriptions; #define SUBSCRIPTION_FULLMUX 0x4 /* Some internal prioties */ -#define SUBSCRIPTION_PRIO_EPG 1 -#define SUBSCRIPTION_PRIO_SCAN 2 -#define SUBSCRIPTION_PRIO_MAPPER 3 -#define SUBSCRIPTION_PRIO_MIN 10 +#define SUBSCRIPTION_PRIO_SCAN_IDLE 1 ///< Idle scanning +#define SUBSCRIPTION_PRIO_SCAN_SCHED 2 ///< Scheduled scan +#define SUBSCRIPTION_PRIO_EPG 3 ///< EPG scanner +#define SUBSCRIPTION_PRIO_SCAN_INIT 4 ///< Initial scan +#define SUBSCRIPTION_PRIO_SCAN_USER 5 ///< User defined scan +#define SUBSCRIPTION_PRIO_MAPPER 6 ///< Channel mapper +#define SUBSCRIPTION_PRIO_MIN 10 ///< User defined / Normal levels typedef struct th_subscription {