summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJaromil <jaromil@dyne.org>2011-04-19 08:54:35 (GMT)
committer Jaromil <jaromil@dyne.org>2011-04-19 08:54:35 (GMT)
commit87d9b2208fdf3555cc2a227014e88090b9075daf (patch)
treefeb2805e0184ab05183775c9cd11fd77821a6473
parent650be405d5bbfd944b3d49986ac30226c75a1a25 (diff)
support for upnp auto-discovery via miniupnpc library
-rw-r--r--configure.ac25
-rw-r--r--src/Makefile.am3
-rw-r--r--src/cmdline.c92
-rw-r--r--src/discover.c75
-rw-r--r--src/discover.h6
5 files changed, 166 insertions, 35 deletions
diff --git a/configure.ac b/configure.ac
index 6110b72..3a521e4 100644
--- a/configure.ac
+++ b/configure.ac
@@ -47,6 +47,29 @@ AC_CHECK_HEADERS([stdio.h stdlib.h unistd.h strings.h sys/types.h sys/stat.h])
dnl ==============================================================
+dnl enable UPNP
+dnl ==============================================================
+AC_ARG_ENABLE(discovery,
+ AS_HELP_STRING([--enable-discovery],[compile with miniupnp to enable auto-discovery]),
+ [have_upnp=$enableval],
+ [have_upnp=no])
+AC_MSG_CHECKING([if UPNP support (miniupnp) is enabled])
+UPNP_LIBS=""
+if test x$have_upnp = xyes; then
+# this is the default behaviour for --enable-upnp with no arguments
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(USE_UPNP,1,[Define if building auto-detect for UPNP devices via miniupnp])
+else
+ AC_MSG_RESULT(no)
+fi
+if test x$have_upnp = xyes; then
+ UPNP_LIBS="-lminiupnpc"
+ # TODO OSX and WIN
+fi
+AC_SUBST(UPNP_LIBS)
+
+
+dnl ==============================================================
dnl compile with full warnings and debugging symbols
dnl ==============================================================
AC_ARG_ENABLE(debug,
@@ -56,6 +79,8 @@ AC_ARG_ENABLE(debug,
if test x$enable_debug = xyes; then
GLOBAL_CFLAGS="$GLOBAL_CFLAGS -Wall -g -ggdb"
+else
+ GLOBAL_CFLAGS="$GLOBAL_CFLAGS -O3"
fi
diff --git a/src/Makefile.am b/src/Makefile.am
index 1b6d7b7..478c3a5 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,4 +1,5 @@
bin_PROGRAMS = avremote
-avremote_SOURCES = avremote.c avremote.h cmdline.c
+avremote_SOURCES = avremote.c avremote.h cmdline.c discover.c
+avremote_LDADD = $(UPNP_LIBS)
diff --git a/src/cmdline.c b/src/cmdline.c
index d646815..39736a9 100644
--- a/src/cmdline.c
+++ b/src/cmdline.c
@@ -33,6 +33,7 @@
#include <errno.h>
#include <avremote.h>
+#include <discover.h>
// our exit codes are shell style: 1 is error, 0 is success
#define ERR 1
@@ -45,6 +46,7 @@ char command[64];
char server[512];
int port = 0;
int dry_run = 0;
+int discover = 0;
// we use only getopt, no _long
static const char *short_options = "-hvs:p:t";
@@ -74,6 +76,9 @@ void cmdline(int argc, char **argv) {
" play start playing the selected file\n"
" pause pause currently running playback\n"
" stop stop playback and return to menu\n"
+#ifdef USE_UPNP
+ " discover search for upnp devices on the network\n"
+#endif
"\n"
"Options:\n"
"\n"
@@ -126,13 +131,17 @@ void cmdline(int argc, char **argv) {
} while(res != -1);
- if(!dry_run) {
+ if(command[0] == 'd') { // discover
+ discover = 1;
+ } else if(!dry_run) {
// check requires args
if(!command[0]) {
fprintf(stderr,"command not specified, see %s -h for help\n",argv[0]);
exit(1);
}
+
+ // not in dry run nor discovery, check for necessary options
if(!port) {
fprintf(stderr,"port not specified, use -p\n");
exit(1);
@@ -143,7 +152,6 @@ void cmdline(int argc, char **argv) {
sprintf(server,"%s","localhost");
}
}
-
}
int main(int argc, char **argv) {
@@ -151,22 +159,36 @@ int main(int argc, char **argv) {
cmdline(argc, argv);
- upnp = create_upnp();
-
- if(!dry_run) {
- if ( connect_upnp(upnp, server, port) < 0 ) {
- fprintf(stderr,"can't connect to %s:%u: operation aborted.\n", server, port);
- exit(ERR);
- }
-
- } else {
-
- sprintf(upnp->hostname,"%s","dry run");
- upnp->port = 0;
-
- }
+#ifdef USE_UPNP
+ if (discover)
+ {
+ fprintf(stderr,"Performing upnp autodiscovery...\n");
+ upnp_discover();
+ exit(0);
+ }
+#endif
+
+ upnp = create_upnp();
+ if(!dry_run)
+ {
+
+ if ( connect_upnp (upnp, server, port) < 0 )
+ {
+ fprintf(stderr,"can't connect to %s:%u: operation aborted.\n", server, port);
+ exit(ERR);
+ }
+
+ }
+ else
+ {
+
+ sprintf(upnp->hostname,"%s","dry run");
+ upnp->port = 0;
+
+ }
+
// command parsing is a cascade switch on single letters
// this is supposedly faster than strcmp
switch(command[0]) {
@@ -179,15 +201,18 @@ int main(int argc, char **argv) {
case 'p':
- if(command[1]=='l') { // 'pl*' is play
-
- render_upnp(upnp,"Play","<Speed>1</Speed>");
-
- } else if(command[1]=='a') { // 'pa*' is pause
-
- render_upnp(upnp,"Pause","");
-
- }
+ if(command[1]=='l')
+ { // 'pl*' is play
+
+ render_upnp(upnp,"Play","<Speed>1</Speed>");
+
+ }
+ else if (command[1]=='a')
+ { // 'pa*' is pause
+
+ render_upnp(upnp,"Pause","");
+
+ }
break;
case 's': // stop
@@ -204,16 +229,15 @@ int main(int argc, char **argv) {
exit(1);
}
- if(dry_run)
+ if (dry_run)
print_upnp(upnp);
- else {
- send_upnp(upnp);
- recv_upnp(upnp);
- fprintf(stderr,"%s\n",upnp->res);
-
- }
- // TODO recv when needed
-
+ else
+ {
+ send_upnp(upnp);
+ recv_upnp(upnp);
+ fprintf(stderr,"%s\n",upnp->res);
+ }
+
free_upnp(upnp);
exit(0);
diff --git a/src/discover.c b/src/discover.c
new file mode 100644
index 0000000..43fc168
--- /dev/null
+++ b/src/discover.c
@@ -0,0 +1,75 @@
+
+#include <config.h>
+
+#include <stdio.h>
+#include <string.h>
+
+#ifdef USE_UPNP
+
+#include <miniupnpc/miniwget.h>
+#include <miniupnpc/miniupnpc.h>
+#include <miniupnpc/upnpcommands.h>
+#include <miniupnpc/upnperrors.h>
+
+
+int upnp_discover()
+{
+ const char * rootdescurl = 0;
+ const char * multicastif = 0;
+ const char * minissdpdpath = 0;
+ char lanaddr[64];
+ struct UPNPDev *devlist = 0;
+ struct UPNPDev *dev;
+ struct UPNPUrls urls;
+ struct IGDdatas data;
+ int r;
+
+ devlist = upnpDiscover(1000, multicastif, minissdpdpath, 0);
+
+ r = UPNP_GetValidIGD(devlist, &urls, &data, lanaddr, sizeof(lanaddr));
+ if (!r) {
+ fprintf(stderr,"no valid UPnP IGDs found\n");
+
+ } else if (r == 3) { // 3 = an UPnP device has been found (not an IGD)
+
+ fprintf(stderr,"UPnP found an AVTransport device:\n",r);
+ dev = devlist;
+ while(dev) {
+
+ // parse out ip and port from url
+ char ip[256];
+ char port[64];
+ char tmp[512];
+ char *p, *pp;
+
+ memcpy(tmp,dev->descURL,511);
+ p = tmp;
+
+ // ip
+ do p+=2; while(*p != '/'); p++;
+ pp = p; do pp++; while(*pp != ':'); *pp = 0;
+ snprintf(ip,255,"%s",p);
+
+ // port
+ p = pp+1; pp = p;
+ do pp++; while(*pp != '/'); *pp = 0;
+ snprintf(port,63,"%s",p);
+
+ fprintf(stderr,"%s\t%s\t%s\t%s\n", dev->st, dev->descURL, ip, port);
+ dev = dev->pNext;
+ }
+
+ /* fprintf(stderr,
+ " controlURL: %s\n"
+ " ipcondescURL: %s\n"
+ " controlURL_CIF: %s\n",
+ urls.controlURL, urls.ipcondescURL, urls.controlURL_CIF); */
+
+ FreeUPNPUrls(&urls);
+ }
+ freeUPNPDevlist(devlist); devlist = 0;
+
+ return(r);
+}
+
+#endif
diff --git a/src/discover.h b/src/discover.h
new file mode 100644
index 0000000..52fd25d
--- /dev/null
+++ b/src/discover.h
@@ -0,0 +1,6 @@
+
+#ifdef USE_UPNP
+
+int upnp_discover();
+
+#endif