case SMT_SERVICE_STATUS:
if(sm->sm_code & TSS_PACKETS) {
- } else if(sm->sm_code & (TSS_GRACEPERIOD | TSS_ERRORS)) {
+ } else if(sm->sm_code & TSS_ERRORS) {
int code = SM_CODE_UNDEFINED_ERROR;
-
if(sm->sm_code & TSS_NO_DESCRAMBLER)
code = SM_CODE_NO_DESCRAMBLER;
{
if(status & TSS_PACKETS) {
htsp_subscription_status(hs, NULL);
- } else if(status & (TSS_GRACEPERIOD | TSS_ERRORS)) {
+ } else if(status & TSS_ERRORS) {
htsp_subscription_status(hs, service_tss2text(status));
}
}
void (*mi_stopping_mux) (mpegts_input_t*,mpegts_mux_instance_t*);
void (*mi_stopped_mux) (mpegts_input_t*,mpegts_mux_instance_t*);
int (*mi_has_subscription) (mpegts_input_t*, mpegts_mux_t *mm);
+ void (*mi_tuning_error) (mpegts_input_t*,mpegts_mux_t *);
idnode_set_t *(*mi_network_list) (mpegts_input_t*);
};
void mpegts_mux_save ( mpegts_mux_t *mm, htsmsg_t *c );
+void mpegts_mux_tuning_error( mpegts_mux_t *mm );
+
mpegts_mux_instance_t *mpegts_mux_instance_create0
( mpegts_mux_instance_t *mmi, const idclass_t *class, const char *uuid,
mpegts_input_t *mi, mpegts_mux_t *mm );
( mpegts_input_t *mi, mpegts_mux_instance_t *mmi )
{
char buf[256];
- service_t *s;
+ service_t *s, *s_next;
/* no longer active */
LIST_REMOVE(mmi, mmi_active_link);
mi->mi_display_name(mi, buf, sizeof(buf));
tvhtrace("mpegts", "%s - flush subscribers", buf);
- s = LIST_FIRST(&mi->mi_transports);
- while (s) {
+ for (s = LIST_FIRST(&mi->mi_transports); s; s = s_next) {
+ s_next = LIST_NEXT(s, s_active_link);
if (((mpegts_service_t*)s)->s_dvb_mux == mmi->mmi_mux)
service_remove_subscriber(s, NULL, SM_CODE_SUBSCRIPTION_OVERRIDDEN);
- s = LIST_NEXT(s, s_active_link);
}
notify_reload("input_status");
mpegts_input_dbus_notify(mi, 0);
return ret;
}
+static void
+mpegts_input_tuning_error ( mpegts_input_t *mi, mpegts_mux_t *mm )
+{
+ service_t *t, *t_next;
+ pthread_mutex_lock(&mi->mi_output_lock);
+ for (t = LIST_FIRST(&mi->mi_transports); t; t = t_next) {
+ t_next = LIST_NEXT(t, s_active_link);
+ if (((mpegts_service_t*)t)->s_dvb_mux == mm) {
+ pthread_mutex_lock(&t->s_stream_mutex);
+ service_set_streaming_status_flags(t, TSS_TUNING);
+ pthread_mutex_unlock(&t->s_stream_mutex);
+ }
+ }
+ pthread_mutex_unlock(&mi->mi_output_lock);
+}
+
/* **************************************************************************
* Data processing
* *************************************************************************/
goto done;
}
- /* Remove in future or move it outside this loop */
- lock_assert(&mi->mi_output_lock);
-
/* Find PID */
if ((mp = mpegts_mux_find_pid(mm, pid, 0))) {
mi->mi_stopping_mux = mpegts_input_stopping_mux;
mi->mi_stopped_mux = mpegts_input_stopped_mux;
mi->mi_has_subscription = mpegts_input_has_subscription;
+ mi->mi_tuning_error = mpegts_input_tuning_error;
mi->ti_get_streams = mpegts_input_get_streams;
/* Index */
return save;
}
-int mpegts_input_grace( mpegts_input_t *mi, mpegts_mux_t *mm )
+int
+mpegts_input_grace( mpegts_input_t *mi, mpegts_mux_t *mm )
{
/* Get timeout */
int t = 0;
#include "queue.h"
#include "input.h"
#include "subscriptions.h"
+#include "streaming.h"
#include "channels.h"
#include "access.h"
#include "profile.h"
}
}
+void
+mpegts_mux_tuning_error ( mpegts_mux_t *mm )
+{
+ th_subscription_t *sub;
+ mpegts_mux_instance_t *mmi;
+ streaming_message_t *sm;
+
+ lock_assert(&global_lock);
+
+ if ((mmi = mm->mm_active) != NULL) {
+ LIST_FOREACH(sub, &mmi->mmi_subs, ths_mmi_link) {
+ sm = streaming_msg_create_code(SMT_SERVICE_STATUS, TSS_TUNING);
+ streaming_target_deliver(sub->ths_output, sm);
+ }
+ if (mmi->mmi_input)
+ mmi->mmi_input->mi_tuning_error(mmi->mmi_input, mm);
+ }
+}
+
/* **************************************************************************
* Search
* *************************************************************************/
mpegts_service_t *
-mpegts_mux_find_service ( mpegts_mux_t *mm, uint16_t sid)
+mpegts_mux_find_service ( mpegts_mux_t *mm, uint16_t sid )
{
mpegts_service_t *ms;
LIST_FOREACH(ms, &mm->mm_services, s_dvb_mux_link)
return r;
}
+static void
+satip_frontend_tuning_error ( satip_frontend_t *lfe, satip_tune_req_t *tr )
+{
+ pthread_mutex_lock(&global_lock);
+ pthread_mutex_lock(&lfe->sf_dvr_lock);
+ if (lfe->sf_running && lfe->sf_req == tr &&
+ tr->sf_mmi && tr->sf_mmi->mmi_mux)
+ mpegts_mux_tuning_error(tr->sf_mmi->mmi_mux);
+ pthread_mutex_unlock(&lfe->sf_dvr_lock);
+ pthread_mutex_unlock(&global_lock);
+}
+
static void *
satip_frontend_input_thread ( void *aux )
{
mmi = tr->sf_mmi;
changing = 0;
- ms = -1;
+ ms = 500;
fatal = 0;
running = 1;
seq = -1;
if (udp_bind_double(&rtp, &rtcp,
"satip", "rtp", "rtpc",
satip_frontend_bindaddr(lfe), lfe->sf_udp_rtp_port,
- NULL, SATIP_BUF_SIZE, 16384) < 0)
+ NULL, SATIP_BUF_SIZE, 16384) < 0) {
+ satip_frontend_tuning_error(lfe, tr);
goto done;
+ }
rtp_port = ntohs(IP_PORT(rtp->ip));
ntohs(IP_PORT(rtp->ip)),
ntohs(IP_PORT(rtcp->ip)));
- if (rtp == NULL || rtcp == NULL || mmi == NULL)
+ if (rtp == NULL || rtcp == NULL || mmi == NULL) {
+ satip_frontend_tuning_error(lfe, tr);
goto done;
+ }
lm = (dvb_mux_t *)mmi->mmi_mux;
rtsp = http_client_connect(lfe, RTSP_VERSION_1_0, "rstp",
lfe->sf_device->sd_info.addr, 554,
satip_frontend_bindaddr(lfe));
- if (rtsp == NULL)
+ if (rtsp == NULL) {
+ satip_frontend_tuning_error(lfe, tr);
goto done;
+ }
/* Setup poll */
memset(ev, 0, sizeof(ev));
rtsp_flags |= SATIP_SETUP_PIDS0;
if (lfe->sf_device->sd_pilot_on)
rtsp_flags |= SATIP_SETUP_PILOT_ON;
- r = 0xa59234;
+ r = -12345678;
pthread_mutex_lock(&lfe->sf_dvr_lock);
if (lfe->sf_req == lfe->sf_req_thread)
r = satip_rtsp_setup(rtsp,
rtsp_flags);
pthread_mutex_unlock(&lfe->sf_dvr_lock);
if (r < 0) {
- if (r != 0xa59234)
- tvherror("satip", "%s - failed to tune", buf);
+ tvherror("satip", "%s - failed to tune", buf);
+ satip_frontend_tuning_error(lfe, tr);
goto done;
}
reply = 1;
udp_multirecv_init(&um, RTP_PKTS, RTP_PKT_SIZE);
sbuf_init_fixed(&sb, RTP_PKTS * RTP_PKT_SIZE);
-
+
while ((reply || running) && !fatal) {
nfds = tvhpoll_wait(efd, ev, 1, ms);
}
if (changing && rtsp->hc_cmd == HTTP_CMD_NONE) {
- ms = -1;
+ ms = 500;
changing = 0;
if (satip_frontend_pid_changed(rtsp, lfe, buf) > 0)
reply = 1;
if (r < 0) {
tvhlog(LOG_ERR, "satip", "%s - RTSP error %d (%s) [%i-%i]",
buf, r, strerror(-r), rtsp->hc_cmd, rtsp->hc_code);
+ satip_frontend_tuning_error(lfe, tr);
fatal = 1;
} else if (r == HTTP_CON_DONE) {
reply = 0;
if (r < 0) {
tvhlog(LOG_ERR, "satip", "%s - RTSP OPTIONS error %d (%s) [%i-%i]",
buf, r, strerror(-r), rtsp->hc_cmd, rtsp->hc_code);
+ satip_frontend_tuning_error(lfe, tr);
fatal = 1;
}
break;
rtsp->hc_rtpc_port != rtp_port + 1) {
tvhlog(LOG_ERR, "satip", "%s - RTSP SETUP error %d (%s) [%i-%i]",
buf, r, strerror(-r), rtsp->hc_cmd, rtsp->hc_code);
+ satip_frontend_tuning_error(lfe, tr);
fatal = 1;
} else {
tvhdebug("satip", "%s #%i - new session %s stream id %li",
rtsp->hc_host, lfe->sf_number,
rtsp->hc_rtsp_session, rtsp->hc_rtsp_stream_id);
if (lfe->sf_play2) {
- r = 0xa59234;
+ r = -12345678;
pthread_mutex_lock(&lfe->sf_dvr_lock);
if (lfe->sf_req == lfe->sf_req_thread)
r = satip_rtsp_setup(rtsp, position, lfe->sf_number,
rtsp_flags | SATIP_SETUP_PLAY);
pthread_mutex_unlock(&lfe->sf_dvr_lock);
if (r < 0) {
- if (r != 0xa59234)
- tvherror("satip", "%s - failed to tune2", buf);
+ tvherror("satip", "%s - failed to tune2", buf);
+ satip_frontend_tuning_error(lfe, tr);
fatal = 1;
}
reply = 1;
if (rtsp->hc_code >= 400) {
tvhlog(LOG_ERR, "satip", "%s - RTSP cmd error %d (%s) [%i-%i]",
buf, r, strerror(-r), rtsp->hc_cmd, rtsp->hc_code);
+ satip_frontend_tuning_error(lfe, tr);
fatal = 1;
}
break;
t->s_streaming_status = set;
- tvhlog(LOG_DEBUG, "service", "%s: Status changed to %s%s%s%s%s%s%s%s",
+ tvhlog(LOG_DEBUG, "service", "%s: Status changed to %s%s%s%s%s%s%s%s%s",
service_nicename(t),
set & TSS_INPUT_HARDWARE ? "[Hardware input] " : "",
set & TSS_INPUT_SERVICE ? "[Input on service] " : "",
set & TSS_PACKETS ? "[Reassembled packets] " : "",
set & TSS_NO_DESCRAMBLER ? "[No available descrambler] " : "",
set & TSS_NO_ACCESS ? "[No access] " : "",
+ set & TSS_TUNING ? "[Tuning failed] " : "",
set & TSS_GRACEPERIOD ? "[Graceperiod expired] " : "",
set & TSS_TIMEOUT ? "[Data timeout] " : "");
if(flags & TSS_NO_ACCESS)
return "No access";
+ if(flags & TSS_TUNING)
+ return "Tuning failed";
+
if(flags & TSS_NO_DESCRAMBLER)
return "No descrambler";
if(tss & TSS_NO_ACCESS)
return SM_CODE_NO_ACCESS;
+ if(tss & TSS_TUNING)
+ return SM_CODE_TUNING_FAILED;
+
if(tss & TSS_NO_DESCRAMBLER)
return SM_CODE_NO_DESCRAMBLER;
#define TSS_PACKETS 0x8
#define TSS_NO_ACCESS 0x10
-#define TSS_GRACEPERIOD 0x8000
// Errors
-#define TSS_NO_DESCRAMBLER 0x10000
-#define TSS_TIMEOUT 0x20000
+#define TSS_GRACEPERIOD 0x10000
+#define TSS_NO_DESCRAMBLER 0x20000
+#define TSS_TIMEOUT 0x40000
+#define TSS_TUNING 0x80000
#define TSS_ERRORS 0xffff0000
} else if (sm->sm_type == SMT_SERVICE_STATUS) {
int status = sm->sm_code;
- if(status & (TSS_GRACEPERIOD | TSS_ERRORS)) {
+ if(status & TSS_ERRORS) {
run = 0;
err = service_tss2text(status);
}
}
if(sm->sm_type == SMT_SERVICE_STATUS &&
- sm->sm_code & (TSS_GRACEPERIOD | TSS_ERRORS)) {
+ sm->sm_code & TSS_ERRORS) {
// No, mark our subscription as bad_service
// the scheduler will take care of things
error = tss2errcode(sm->sm_code);
}
if (sm->sm_type == SMT_SERVICE_STATUS &&
- sm->sm_code & TSS_TIMEOUT) {
+ sm->sm_code & (TSS_TUNING|TSS_TIMEOUT)) {
error = tss2errcode(sm->sm_code);
if (error > s->ths_testing_error)
s->ths_testing_error = error;