summaryrefslogtreecommitdiff
path: root/mcast/client/.svn/text-base/recv_tv.c.svn-base
diff options
context:
space:
mode:
Diffstat (limited to 'mcast/client/.svn/text-base/recv_tv.c.svn-base')
-rw-r--r--mcast/client/.svn/text-base/recv_tv.c.svn-base905
1 files changed, 905 insertions, 0 deletions
diff --git a/mcast/client/.svn/text-base/recv_tv.c.svn-base b/mcast/client/.svn/text-base/recv_tv.c.svn-base
new file mode 100644
index 0000000..f453ed4
--- /dev/null
+++ b/mcast/client/.svn/text-base/recv_tv.c.svn-base
@@ -0,0 +1,905 @@
+/*
+ * (c) BayCom GmbH, http://www.baycom.de, info@baycom.de
+ *
+ * See the COPYING file for copyright information and
+ * how to reach the author.
+ *
+ * modified by Reel Multimedia, http://www.reel-multimedia.com, info@reel-multimedia.com
+ * 01042010 DL: use a single thread for reading from network layer (uses less resources)
+ *
+ */
+
+//#define DEBUG 1
+#include "headers.h"
+#if ! defined WIN32 || defined __CYGWIN__
+#define RT
+#endif
+
+#define RE 1
+
+#if defined(RE)
+int set_redirected(recv_info_t *r, int sid);
+int check_if_already_redirected(recv_info_t *r, int sid);
+#endif
+
+recv_info_t receivers;
+pthread_mutex_t lock;
+
+int mld_start=0;
+
+int port=23000;
+char iface[IFNAMSIZ];
+
+static pthread_t recv_tra_thread;
+static pthread_t recv_tca_thread;
+
+#if ! defined WIN32 || defined __CYGWIN__
+static void sig_handler (int signal)
+{
+ dbg ("Signal: %d\n", signal);
+
+ switch (signal) {
+ case SIGUSR1:
+ recv_show_all_pids (&receivers);
+ break;
+ }
+}
+#endif
+
+#ifdef MULTI_THREAD_RECEIVER
+static void clean_recv_ts_thread (void *arg)
+{
+ pid_info_t *p = (pid_info_t *) arg;
+#ifdef DEBUG
+ dbg ("Stop stream receiving for pid %d\n", p->pid.pid);
+#endif
+
+ if (p->s) {
+ udp_close (p->s);
+ }
+}
+
+//-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+static void *recv_ts (void *arg)
+{
+ unsigned char buf[32712];
+ unsigned char *ptr;
+ int n, res;
+ int cont_old = -1;
+
+ pid_info_t *p = (pid_info_t *) arg;
+ recv_info_t *r = p->recv;
+
+#ifdef RT
+#if 1
+ if (setpriority (PRIO_PROCESS, 0, -15) == -1)
+#else
+ if (pthread_setschedprio (p->recv_ts_thread, -15))
+#endif
+ {
+ dbg ("Cannot raise priority to -15\n");
+ }
+#endif
+
+ pthread_cleanup_push (clean_recv_ts_thread, p);
+#ifdef DEBUG
+ char addr_str[INET6_ADDRSTRLEN];
+ inet_ntop (AF_INET6, p->mcg.s6_addr, addr_str, INET6_ADDRSTRLEN);
+ dbg ("Start stream receiving for %s on port %d %s\n", addr_str, port, iface);
+#endif
+ p->s = client_udp_open (&p->mcg, port, iface);
+ if (!p->s) {
+ warn ("client_udp_open error !\n");
+ } else {
+ p->run = 1;
+ }
+ while (p->run>0) {
+ n = udp_read (p->s, buf, sizeof (buf), 1000, NULL);
+ if (n >0 ) {
+ ptr = buf;
+ if (n % 188) {
+ warn ("Received %d bytes is not multiple of 188!\n", n);
+ }
+ int i;
+ for (i = 0; i < (n / 188); i++) {
+ unsigned char *ts = buf + (i * 188);
+ int adaption_field = (ts[3] >> 4) & 3;
+ int cont = ts[3] & 0xf;
+ int pid = ((ts[1] << 8) | ts[2]) & 0x1fff;
+ int transport_error_indicator = ts[1]&0x80;
+
+ if (pid != 8191 && (adaption_field & 1) && (((cont_old + 1) & 0xf) != cont) && cont_old >= 0) {
+ warn ("Discontinuity on receiver %p for pid %d: %d->%d at pos %d/%d\n", r, pid, cont_old, cont, i, n / 188);
+ }
+ if (transport_error_indicator) {
+ warn ("Transport error indicator set on receiver %p for pid %d: %d->%d at pos %d/%d\n", r, pid, cont_old, cont, i, n / 188);
+ }
+ cont_old = cont;
+ }
+ if(r->handle_ts) {
+ while (n) {
+ res = r->handle_ts (ptr, n, r->handle_ts_context);
+ if (res != n) {
+ warn ("Not same amount of data written: res:%d<=n:%d\n", res, n);
+ }
+ if (res < 0) {
+ warn ("write of %d bytes returned %d\n", n, res);
+ perror ("Write failed");
+ break;
+ } else {
+ ptr += res;
+ n -= res;
+ }
+ }
+ }
+ }
+ pthread_testcancel();
+ }
+ pthread_cleanup_pop (1);
+
+ return NULL;
+ }
+
+#else
+//-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+static void recv_ts_func (unsigned char *buf, int n, void *arg) {
+ if (n >0 ) {
+ pid_info_t *p = (pid_info_t *) arg;
+ recv_info_t *r = p->recv;
+ int i;
+ for (i = 0; i < n; i += 188) {
+ unsigned char *ts = buf + i;
+ int adaption_field = (ts[3] >> 4) & 3;
+ int cont = ts[3] & 0xf;
+ int pid = ((ts[1] << 8) | ts[2]) & 0x1fff;
+ int transport_error_indicator = ts[1]&0x80;
+
+ if (pid != 8191 && (adaption_field & 1) && (((p->cont_old + 1) & 0xf) != cont) && p->cont_old >= 0) {
+ warn ("Discontinuity on receiver %p for pid %d: %d->%d at pos %d/%d\n", r, pid, p->cont_old, cont, i / 188, n / 188);
+ }
+ if (transport_error_indicator) {
+ warn ("Transport error indicator set on receiver %p for pid %d: %d->%d at pos %d/%d\n", r, pid, p->cont_old, cont, i / 188, n / 188);
+ }
+ p->cont_old = cont;
+ }
+ if (i != n) {
+ warn ("Received %d bytes is not multiple of 188!\n", n);
+ }
+ if(r->handle_ts) {
+ while (n) {
+ int res = r->handle_ts (buf, n, r->handle_ts_context);
+ if (res != n) {
+ warn ("Not same amount of data written: res:%d<=n:%d\n", res, n);
+ }
+ if (res < 0) {
+ warn ("write of %d bytes returned %d\n", n, res);
+ perror ("Write failed");
+ break;
+ } else {
+ buf += res;
+ n -= res;
+ }
+ }
+ }
+ }
+}
+#endif
+//-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+int register_ts_handler (recv_info_t * r, int (*p)(unsigned char *, size_t, void *), void *c)
+{
+ r->handle_ts=(int (*)(unsigned char *buffer, size_t len, void *context))p;
+ r->handle_ts_context=c;
+ return 0;
+}
+
+//-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+static pid_info_t *find_slot_by_pid (recv_info_t * r, int pid, int id)
+{
+ pid_info_t *slot;
+ DVBMC_LIST_FOR_EACH_ENTRY (slot, &r->slots.list, pid_info_t, list) {
+ if (slot->run && slot->pid.pid == pid && (id == -1 || slot->pid.id == id)) {
+ return slot;
+ }
+ }
+
+ return NULL;
+}
+
+//-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+static pid_info_t *find_slot_by_mcg (recv_info_t * r, struct in6_addr *mcg)
+{
+ pid_info_t *slot;
+
+ DVBMC_LIST_FOR_EACH_ENTRY (slot, &r->slots.list, pid_info_t, list) {
+ if (slot->run && !memcmp (&slot->mcg, mcg, sizeof (struct in6_addr))) {
+ return slot;
+ }
+ }
+ return NULL;
+}
+
+//-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+int find_any_slot_by_mcg (recv_info_t * receivers, struct in6_addr *mcg)
+{
+ recv_info_t *r;
+ int ret=0;
+
+ DVBMC_LIST_FOR_EACH_ENTRY (r, &receivers->head->list, recv_info_t, list) {
+ pid_info_t *slot = find_slot_by_mcg (r, mcg);
+ if(slot) {
+ ret++;
+ }
+ }
+ return ret;
+}
+
+//-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+int count_receivers(recv_info_t *receivers)
+{
+ int ret=0;
+ struct list *pos;
+
+ DVBMC_LIST_FOR_EACH (pos, &receivers->list) {
+ ret++;
+ }
+ return ret;
+}
+
+//-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+static int count_pids(recv_info_t *r)
+{
+ int ret=0;
+ struct list *pos;
+
+ DVBMC_LIST_FOR_EACH (pos, &r->slots.list) {
+ ret++;
+ }
+ return ret;
+}
+
+//-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+int count_all_pids (recv_info_t * receivers)
+{
+ int ret=0;
+ recv_info_t *r;
+
+ DVBMC_LIST_FOR_EACH_ENTRY (r, &receivers->head->list, recv_info_t, list) {
+ ret += count_pids(r);
+ }
+ return ret;
+}
+
+//-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+void recv_show_pids(recv_info_t *r)
+{
+ pid_info_t *slot;
+ char addr_str[INET6_ADDRSTRLEN];
+ inet_ntop (AF_INET6, r->mcg.s6_addr, addr_str, INET6_ADDRSTRLEN);
+
+ info("pids on receiver %p (%s):\n",r, addr_str);
+ DVBMC_LIST_FOR_EACH_ENTRY (slot, &r->slots.list, pid_info_t, list) {
+ info("%d,", slot->pid.pid);
+ }
+ info("\n");
+}
+
+//-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+int recv_show_all_pids (recv_info_t * receivers)
+{
+ int ret=0;
+ recv_info_t *r;
+ DVBMC_LIST_FOR_EACH_ENTRY (r, &receivers->head->list, recv_info_t, list) {
+ recv_show_pids(r);
+ }
+ return ret;
+}
+
+//-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+static void deallocate_slot (recv_info_t * r, pid_info_t *p)
+{
+ int nodrop=0;
+
+#ifdef MULTI_THREAD_RECEIVER
+ if (pthread_exist(p->recv_ts_thread)) {
+#else
+ if (p->run) {
+
+#endif //info ("Deallocating PID %d from slot %p\n", p->pid.pid, p);
+ p->run = 0;
+
+ //Do not leave multicast group if there is another dvb adapter using the same group
+ if (find_any_slot_by_mcg (r, &p->mcg)) {
+ dbg ("MCG is still in use not dropping\n");
+ p->s->is_multicast = 0;
+ nodrop=1;
+ }
+
+#ifdef MULTI_THREAD_RECEIVER
+ pthread_join (p->recv_ts_thread, NULL);
+#else
+ udp_close_buff(p->s);
+#endif
+ p->dropped = MAX_DROP_NUM;
+ }
+ //printf("NO DROP: %d\n",nodrop);
+ if(!mld_start || nodrop) {
+ dvbmc_list_remove(&p->list);
+ free(p);
+ }
+}
+
+//-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+static pid_info_t *allocate_slot (recv_info_t * r, struct in6_addr *mcg, dvb_pid_t *pid)
+{
+ pid_info_t *p = (pid_info_t *)malloc(sizeof(pid_info_t));
+ if(!p) {
+ err ("Cannot get memory for pid\n");
+ }
+
+ dbg ("Allocating new PID %d to Slot %p\n", pid->pid, p);
+
+ memset(p, 0, sizeof(pid_info_t));
+
+ p->cont_old = -1;
+ p->mcg = *mcg;
+ mcg_set_pid (&p->mcg, pid->pid);
+#if defined(RE)
+ if (!check_if_already_redirected(r, pid->id)) {
+ //printf("PID %d not red. ===> SETTING ID to %d\n",pid->pid,pid->id);
+ mcg_set_id (&p->mcg, pid->id);
+ mcg_set_priority(&p->mcg, pid->priority);
+ } else {
+ set_redirected(r, pid->id);
+ //printf("send pid %d to noid mcg !\n",pid->pid);
+ mcg_set_id(&p->mcg, 0);
+ mcg_set_priority(&p->mcg, 0);
+ }
+ //mcg_set_id(&p->mcg,pid->id);
+#else
+ mcg_set_id (&p->mcg, pid->id);
+ mcg_set_priority(&p->mcg, pid->priority);
+#endif
+
+
+#ifdef DEBUG
+ print_mcg (&p->mcg);
+#endif
+ p->pid = *pid;
+ p->recv = r;
+#ifdef MULTI_THREAD_RECEIVER
+ int ret = pthread_create (&p->recv_ts_thread, NULL, recv_ts, p);
+ while (!ret && !p->run) {
+ usleep (10000);
+ }
+ if (ret) {
+ err ("pthread_create failed with %d\n", ret);
+#else
+ p->cont_old=-1;
+ p->s = client_udp_open_cb (&p->mcg, port, iface, recv_ts_func, p);
+ if (!p->s) {
+ warn ("client_udp_open error !\n");
+ return 0;
+#endif
+ } else {
+ p->run = 1;
+ dvbmc_list_add_head (&r->slots.list, &p->list);
+ }
+
+ return p;
+}
+
+//-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+static void stop_ten_receive (recv_info_t * r)
+{
+ dbg ("->>>>>>>>>>>>>>>>>stop_ten_receive on receiver %p\n",r);
+ if (pthread_exist(r->recv_ten_thread) && r->ten_run) {
+ dbg ("cancel TEN receiver %p %p\n", r, r->recv_ten_thread);
+
+ r->ten_run=0;
+ pthread_mutex_unlock (&lock);
+ do {
+ dbg ("wait TEN stop receiver %p %p\n", r, r->recv_ten_thread);
+ usleep(10000);
+ } while (!r->ten_run);
+ pthread_mutex_lock (&lock);
+ r->ten_run=0;
+ dbg ("cancel TEN done receiver %p\n", r);
+ pthread_detach (r->recv_ten_thread);
+ pthread_null(r->recv_ten_thread);
+ }
+}
+
+
+//-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+static void start_ten_receive (recv_info_t * r)
+{
+ if (r->pidsnum && !pthread_exist(r->recv_ten_thread)) {
+#ifdef DEBUG
+ char host[INET6_ADDRSTRLEN];
+ inet_ntop (AF_INET6, &r->mcg, (char *) host, INET6_ADDRSTRLEN);
+
+ dbg ("Start TEN for receiver %p %s\n", r, host);
+#endif
+ r->ten_run = 0;
+
+ int ret = pthread_create (&r->recv_ten_thread, NULL, recv_ten, r);
+ while (!ret && !r->ten_run) {
+ dbg ("wait TEN startup receiver %p %p\n", r, r->recv_ten_thread);
+ usleep (10000);
+ }
+ if (ret) {
+ err ("pthread_create failed with %d\n", ret);
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+static int cmppids(const void *p1, const void *p2)
+{
+ dvb_pid_t *pid1=(dvb_pid_t *)p1;
+ dvb_pid_t *pid2=(dvb_pid_t *)p2;
+
+ if(pid1->pid == pid2->pid) {
+ return pid1->id < pid2->id;
+ }
+ return pid1->pid < pid2->pid;
+}
+
+//-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+static void update_mcg (recv_info_t * r, int handle_ten)
+{
+ int i;
+ pid_info_t *p;
+ pid_info_t *ptmp;
+
+ if(handle_ten) {
+ if(r->pidsnum) {
+ start_ten_receive(r);
+ } else {
+ stop_ten_receive(r);
+ }
+ }
+ dbg("update_mcg(%p, %d)\n", r, handle_ten);
+ qsort(r->pids, r->pidsnum, sizeof(dvb_pid_t), cmppids);
+
+ DVBMC_LIST_FOR_EACH_ENTRY_SAFE (p, ptmp, &r->slots.list, pid_info_t, list) {
+ //dbg ("DVBMC_LIST_FOR_EACH_ENTRY_SAFE: %p\n", p);
+ if(p->run) {
+ int found_pid = 0;
+ for (i = 0; i < r->pidsnum; i++) {
+ // pid already there without id but now also with id required
+ if (r->pids[i].pid == p->pid.pid && r->pids[i].id && !p->pid.id) {
+ found_pid = 0;
+ break;
+ }
+ if (r->pids[i].pid == p->pid.pid && r->pids[i].id == p->pid.id) {
+ found_pid = 1;
+ }
+ }
+ if (!found_pid) {
+ deallocate_slot (r, p);
+ }
+ }
+ }
+
+ for (i = 0; i < r->pidsnum; i++) {
+ unsigned int pid = r->pids[i].pid;
+ if (!find_slot_by_pid (r, pid, -1)) { //pid with any id there?
+ allocate_slot (r, &r->mcg, r->pids+i);
+ }
+ }
+
+
+}
+//-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+static void stop_receive (recv_info_t * r, int mode)
+{
+ dbg ("stop_receive on receiver %p mode %d\n",r, mode);
+ int pidsnum=r->pidsnum;
+ //Remove all PIDs
+ r->pidsnum = 0;
+ update_mcg (r, mode);
+ r->pidsnum=pidsnum;
+}
+
+//-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+#ifdef RE
+#if 0
+static int find_redirected_sid (recv_info_t * r, int id)
+{
+ pid_info_t *slot;
+ DVBMC_LIST_FOR_EACH_ENTRY (slot, &r->slots.list, pid_info_t, list) {
+ if (slot->pid.id == id && slot->pid.re) {
+ return 1;
+ }
+ }
+
+ return 0;
+}
+#endif
+
+int check_if_already_redirected(recv_info_t *r, int sid)
+{
+ int i;
+ for (i = 0; i < r->pidsnum; i++) {
+ //printf("PID %d SID %d RE %d\n",r->pids[i].pid, r->pids[i].id, r->pids[i].re);
+ if (r->pids[i].re && r->pids[i].id == sid) {
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+int check_if_sid_in(recv_info_t *r, int sid)
+{
+ int i;
+ for (i = 0; i < r->pidsnum; i++) {
+ //printf("PID %d SID %d RE %d\n",r->pids[i].pid, r->pids[i].id, r->pids[i].re);
+ if (r->pids[i].id == sid) {
+// printf("%s: SID in %d!\n",__func__,sid);
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+int set_redirected(recv_info_t *r, int sid)
+{
+ int i;
+ for (i = 0; i < r->pidsnum; i++) {
+ if (r->pids[i].id == sid)
+ r->pids[i].re=1;
+ }
+
+ return 0;
+}
+//-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+int stop_sid_mcgs(recv_info_t *r, int sid)
+{
+ pid_info_t *p;
+ pid_info_t *ptmp;
+
+ DVBMC_LIST_FOR_EACH_ENTRY_SAFE (p, ptmp, &r->slots.list, pid_info_t, list) {
+ if(p->run) {
+ if (p->pid.pid && p->pid.id == sid) {
+ //info ("Deallocating PID %d ID %d RE %d from slot %p\n", p->pid.pid,p->pid.id,p->pid.re, p);
+ deallocate_slot (r, p);
+ }
+ }
+ }
+
+ return 0;
+}
+//-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+int rejoin_mcgs(recv_info_t *r, int sid)
+{
+
+ int i;
+ for (i = 0; i < r->pidsnum; i++) {
+ unsigned int pid = r->pids[i].pid;
+ unsigned int id = r->pids[i].id;
+ if (!find_slot_by_pid (r, pid, id) && id == sid) {
+ char addr_str[INET6_ADDRSTRLEN];
+ inet_ntop (AF_INET6, &r->mcg, addr_str, INET6_ADDRSTRLEN);
+ //info ("Rejoin mcg %s with no ID (PID %d ID %d RE %d)...\n", addr_str, pid, id, r->pids[i].re);
+ allocate_slot (r, &r->mcg, r->pids+i);
+ }
+ }
+
+ return 0;
+}
+//-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+#endif
+int recv_redirect (recv_info_t * r, struct in6_addr mcg)
+{
+ int ret = 0;
+
+ pthread_mutex_lock (&lock);
+ dbg ("\n+++++++++++++\nIn redirect for receiver %p\n", r);
+#if 0
+ char addr_str[INET6_ADDRSTRLEN];
+ inet_ntop (AF_INET6, &r->mcg, addr_str, INET6_ADDRSTRLEN);
+ info ("Redirect to ===> %s\n",addr_str);
+#endif
+ int sid;
+ mcg_get_id(&mcg,&sid);
+ mcg_set_id(&mcg,0);
+
+ //printf("SID in: %d\n",sid);
+
+ if (!sid || ( !check_if_already_redirected(r, sid) && check_if_sid_in(r, sid)) ) {
+ if (sid == 0) {
+ stop_receive (r, 0);
+ r->mcg = mcg;
+ update_mcg (r, 0);
+ ret = 1;
+ } else {
+ //stop sid mcgs
+ stop_sid_mcgs(r, sid);
+ set_redirected(r, sid);
+ //start new mcgs with no sid
+ rejoin_mcgs(r, sid);
+ }
+ }
+
+ dbg ("Redirect done for receiver %p\n", r);
+ pthread_mutex_unlock (&lock);
+
+ return ret;
+}
+
+//-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+int recv_stop (recv_info_t * r)
+{
+ pthread_mutex_lock (&lock);
+ stop_receive (r, 1);
+ pthread_mutex_unlock (&lock);
+ return 0;
+}
+
+//-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+int recv_count_pids(recv_info_t * r)
+{
+ int i;
+ for (i=0; r->pids[i].pid!=-1; i++);
+ return i;
+}
+
+//-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+static int recv_copy_pids(dvb_pid_t *dst, dvb_pid_t *src)
+{
+ int i;
+ for (i=0; (src[i].pid!=-1) && (i<(RECV_MAX_PIDS-1)); i++) {
+ dst[i]=src[i];
+ }
+ if(i==(RECV_MAX_PIDS-1)) {
+ warn("Cannot receive more than %d pids\n", RECV_MAX_PIDS-1);
+ }
+ return i;
+}
+
+//-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+int recv_pids (recv_info_t *r, dvb_pid_t *pids)
+{
+ pthread_mutex_lock (&lock);
+ if(pids) {
+ r->pidsnum=recv_copy_pids(r->pids, pids);
+ }
+ update_mcg(r, 1);
+ pthread_mutex_unlock (&lock);
+ return 0;
+}
+
+//-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+int recv_pids_get (recv_info_t *r, dvb_pid_t *pids)
+{
+ pthread_mutex_lock (&lock);
+ if(pids) {
+ memcpy(pids, r->pids, sizeof(dvb_pid_t)*r->pidsnum);
+ pids[r->pidsnum].pid=-1;
+ }
+ pthread_mutex_unlock (&lock);
+ return r->pidsnum;
+}
+
+//-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+int recv_pid_add (recv_info_t * r, dvb_pid_t *pid)
+{
+ int ret=0;
+
+ pthread_mutex_lock (&lock);
+ pid_info_t *p=find_slot_by_pid (r, pid->pid, pid->id);
+ if(!p && (r->pidsnum < (RECV_MAX_PIDS-2))) {
+#if defined(RE)
+ r->pids[r->pidsnum].re = 0;
+#endif
+ r->pids[r->pidsnum]=*pid;
+ r->pids[++r->pidsnum].pid=-1;
+ update_mcg(r, 1);
+ ret = 1;
+ }
+ pthread_mutex_unlock (&lock);
+
+ return ret;
+}
+
+//-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+int recv_pid_del (recv_info_t * r, int pid)
+{
+ int i;
+ int ret=0;
+
+ pthread_mutex_lock (&lock);
+ if(pid>=0) {
+ for (i = 0; i < r->pidsnum; i++) {
+ if(r->pids[i].pid==pid || ret) {
+ r->pids[i]=r->pids[i+1];
+ ret=1;
+ }
+ }
+ if(ret) {
+ r->pidsnum--;
+ update_mcg(r, 1);
+ }
+ } else {
+ r->pids[0].pid=-1;
+ r->pidsnum=0;
+ update_mcg(r, 1);
+ }
+ pthread_mutex_unlock (&lock);
+
+ return ret;
+}
+
+//-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+int recv_tune (recv_info_t * r, fe_type_t type, int satpos, recv_sec_t *sec, struct dvb_frontend_parameters *fe_parms, dvb_pid_t *pids)
+{
+ pthread_mutex_lock (&lock);
+ dbg ("kick_tune receiver %p\n", r);
+
+ stop_receive (r, 1);
+ if(fe_parms) {
+ r->fe_parms=*fe_parms;
+ }
+ if(sec) {
+ r->sec=*sec;
+ }
+ if(pids) {
+ r->pidsnum=recv_copy_pids(r->pids, pids);
+ }
+
+ fe_parms_to_mcg (&r->mcg, STREAMING_PID, type, &r->sec, &r->fe_parms, 0);
+ mcg_set_satpos (&r->mcg, satpos);
+
+ update_mcg (r, 1);
+
+ pthread_mutex_unlock (&lock);
+ dbg ("kick_tune done receiver %p\n", r);
+ return 0;
+}
+
+//-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+recv_info_t *recv_add (void)
+{
+ recv_info_t *r=(recv_info_t *)malloc(sizeof(recv_info_t));
+ if(!r) {
+ err ("Cannot get memory for receiver\n");
+ }
+ memset (r, 0, sizeof (recv_info_t));
+ r->head=&receivers;
+ dvbmc_list_init (&r->slots.list);
+ pthread_mutex_lock (&lock);
+ dvbmc_list_add_head(&receivers.list, &r->list);
+ pthread_mutex_unlock (&lock);
+ return r;
+}
+
+//-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+void recv_del (recv_info_t *r)
+{
+ pthread_mutex_lock (&lock);
+ stop_receive (r, 1);
+ dvbmc_list_remove(&r->list);
+ pthread_mutex_unlock (&lock);
+ free(r);
+}
+
+//-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+int recv_init(char *intf, int p)
+{
+ LIBXML_TEST_VERSION;
+#ifdef WIN32
+ WSADATA wsaData;
+ if (WSAStartup (MAKEWORD (2, 2), &wsaData) != 0) {
+ err ("WSAStartup failed\n");
+ }
+#endif
+
+ if(intf) {
+ strcpy(iface, intf);
+ } else {
+ iface[0]=0;
+ }
+ if(p) {
+ port=p;
+ }
+
+ g_conf = (struct conf*) malloc (sizeof (struct conf));
+ if (!g_conf) {
+ err ("Cannot get memory for configuration\n");
+ exit (-1);
+ }
+
+ memset (g_conf, 0, sizeof (struct conf));
+ update_interfaces (NULL);
+
+ if (!strlen (iface)) {
+ struct intnode *intn = int_find_first ();
+ if (intn) {
+ strcpy (iface, intn->name);
+ } else {
+ warn ("Cannot find any usable network interface\n");
+ if(g_conf->ints) {
+ free (g_conf->ints);
+ }
+ #ifdef PTW32_STATIC_LIB
+ pthread_win32_process_detach_np();
+ #endif
+ free(g_conf);
+ return -1;
+ }
+ }
+
+ dvbmc_list_init (&receivers.list);
+ pthread_mutex_init (&lock, NULL);
+ receivers.head=&receivers;
+#if ! defined WIN32 || defined __CYGWIN__
+ signal (SIGUSR1, &sig_handler);
+#endif
+#ifdef PTW32_STATIC_LIB
+ pthread_win32_process_attach_np();
+#endif
+ pthread_create (&recv_tra_thread, NULL, recv_tra, NULL);
+ pthread_create (&recv_tca_thread, NULL, recv_tca, NULL);
+
+ return 0;
+}
+
+//-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+int recv_exit(void)
+{
+ recv_info_t *r;
+ recv_info_t *rtmp;
+ if(pthread_exist(recv_tra_thread) && !pthread_cancel (recv_tra_thread)) {
+ pthread_join (recv_tra_thread, NULL);
+ }
+ if(pthread_exist(recv_tca_thread) && !pthread_cancel (recv_tca_thread)) {
+ pthread_join (recv_tca_thread, NULL);
+ }
+ DVBMC_LIST_FOR_EACH_ENTRY_SAFE (r, rtmp, &receivers.head->list, recv_info_t, list) {
+ recv_del(r);
+ }
+#if ! defined WIN32 || defined __CYGWIN__
+ signal (SIGUSR1, NULL);
+#endif
+ g_conf->maxinterfaces=0;
+ if(g_conf->ints) {
+ free (g_conf->ints);
+ }
+#ifdef PTW32_STATIC_LIB
+ pthread_win32_process_detach_np();
+#endif
+ free(g_conf);
+ xmlCleanupParser ();
+ xmlMemoryDump ();
+ return 0;
+}