summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJaromil <jaromil@dyne.org>2011-04-15 12:02:56 (GMT)
committer Jaromil <jaromil@dyne.org>2011-04-15 12:02:56 (GMT)
commit7c32ba4d1be78cd05fd43ee1076a57896587eafe (patch)
tree8938a2802cecf3c83233d9e431e3d5ff920a594b
parenta747976de48fb110ac13a7755ce33d4f7bcc0d9c (diff)
separated source in header and cmdline main()
-rw-r--r--src/Makefile.am3
-rw-r--r--src/avremote.c201
-rw-r--r--src/avremote.h68
-rw-r--r--src/cmdline.c184
4 files changed, 256 insertions, 200 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index f9ec688..f981d23 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,3 +1,4 @@
bin_PROGRAMS = avremote
-avremote_SOURCES = avremote.c
+avremote_SOURCES = avremote.c cmdline.c
+
diff --git a/src/avremote.c b/src/avremote.c
index cf989fe..7b49274 100644
--- a/src/avremote.c
+++ b/src/avremote.c
@@ -37,54 +37,7 @@
#include <errno.h>
-#include <libgen.h>
-
-// our exit codes are shell style: 1 is error, 0 is success
-#define ERR 1
-
-// uncomment to debug
-#define DEBUG 1
-
-
-// format (printf style) to be used when generating xml markup
-#define UPNP_MSG_FORMAT "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n" \
- "<s:Envelope s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\"" \
- "xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\">\r\n<s:Body>\r\n" \
- "<u:%s xmlns:u=\"urn:schemas-upnp-org:service:AVTransport:1\">\r\n" \
- "<InstanceID>0</InstanceID>\r\n%s\r\n</u:%s>\r\n</s:Body>\r\n</s:Envelope>\r\n"
-
-#define UPNP_HDR_FORMAT "POST /MediaRenderer_AVTransport/control HTTP/1.0\r\n" \
- "SOAPACTION: \"urn:schemas-upnp-org:service:AVTransport:1#%s\"\r\n" \
- "CONTENT-TYPE: text/xml ; charset=\"utf-8\"\r\n" \
- "HOST: %s:%u\r\n" \
- "Connection: close\r\n" \
- "Content-Length: %u\r\n" \
- "\r\n"
-
-char filename[512];
-char command[64];
-char server[512];
-int port = 0;
-int dry_run = 0;
-
-// messages get rendered in this structure
-// allocated and freed with create/free_upnp
-typedef struct {
- char *hostname;
- int port;
- int sockfd;
-
- char *hdr;
- size_t hdrlen;
-
- char *msg;
- size_t msglen;
-
- char *res;
-
-} upnp_t;
-
-
+#include <avremote.h>
upnp_t *create_upnp() {
@@ -193,10 +146,7 @@ void render_upnp(upnp_t *upnp, char *action, char *arg) {
upnp->msglen = strlen(upnp->msg);
snprintf(upnp->hdr,1023,UPNP_HDR_FORMAT,
- action,
- (dry_run?"dry run":upnp->hostname),
- (dry_run?0:upnp->port),
- upnp->msglen);
+ action, upnp->hostname, upnp->port, upnp->msglen);
upnp->hdrlen = strlen(upnp->hdr);
@@ -236,150 +186,3 @@ int load(upnp_t *upnp, char *file) {
// TODO
}
-int play(upnp_t *upnp) {
- if(!check_upnp(upnp, __PRETTY_FUNCTION__)) return(0);
- render_upnp(upnp,"Play","<Speed>1</Speed>");
- if(dry_run)
- print_upnp(upnp);
- else
- send_upnp(upnp);
- return(1);
-}
-
-int stop(upnp_t *upnp) {
- if(!check_upnp(upnp, __PRETTY_FUNCTION__)) return(0);
- render_upnp(upnp,"Stop","");
- if(dry_run)
- print_upnp(upnp);
- else
- send_upnp(upnp);
- return(1);
-}
-
-int get_trans_info(upnp_t *upnp) {
- if(!check_upnp(upnp, __PRETTY_FUNCTION__)) return(0);
- render_upnp(upnp,"GetTransportInfo","");
- if(dry_run)
- print_upnp(upnp);
- else {
- send_upnp(upnp);
- recv_upnp(upnp);
- }
- return(1);
-}
-
-
-// we use only getopt, no _long
-static const char *short_options = "-hvs:p:t";
-void cmdline(int argc, char **argv) {
- command[0] = 0;
- filename[0] = 0;
- server[0] = 0;
-
- int res, optlen;
- do {
- res = getopt(argc, argv, short_options);
- switch(res) {
- case 'h':
- fprintf(stderr,"usage: %s [options] command [file]\n",argv[0]);
- break;
- case 'v':
- fprintf(stderr,"AVRemote - simple commandline tool to send AVTransport commands over UPNP\n"
- "version 0.1 (Apr/2011) by Jaromil - Netherlands Media Art Institute\n"
- "Copyright (C) 2011 NIMk Artlab, License GNU AGPL v3+\n"
- "This is free software: you are free to change and redistribute it\n");
- exit(0);
-
- case 's':
- snprintf(server,511,"%s",optarg);
- break;
-
- case 'p':
- sscanf (optarg, "%u", &port);
- break;
-
- case 't':
- // test dry run
- dry_run = 1;
- fprintf(stderr,"dry run: printint out rendered upnp message without establishing connection\n");
- break;
-
- case '?':
- fprintf(stderr,"unrecognized option: %s\n",optarg);
- break;
-
- case 1:
- {
- struct stat filestatus;
- if( stat(optarg,&filestatus) >= 0 ) { // its a file
- snprintf(filename,511,"%s",optarg);
- } else {
- snprintf(command,63,"%s",optarg);
- fprintf("executing command '%s'\n",command);
- }
- }
- break;
- default:
- break;
- }
-
- } while(res != -1);
-
- if(!dry_run) {
- // check requires args
- if(!command[0]) {
- fprintf(stderr,"command not specified, see %s -h for help\n",argv[0]);
- exit(1);
- }
-
- if(!port) {
- fprintf(stderr,"port not specified, use -p\n");
- exit(1);
- }
-
- if(!server[0]) {
- fprintf(stderr,"server not specified, using localhost\n");
- sprintf(server,"%s","localhost");
- }
- }
-
-}
-
-int main(int argc, char **argv) {
- int sock, port, n;
-
- cmdline(argc, argv);
-
- upnp_t *upnp;
- upnp = create_upnp();
-
- if(!dry_run) {
-
- if ( connect_upnp(upnp, server, port) < 0 ) {
- fprintf(stderr,"can't connect to server %s: operation aborted.\n", server);
- exit(ERR);
- }
-
- }
-
- // fprintf(stderr,"socket: %u\n",upnp->sockfd);
-
- switch(command[0]) {
- case 'p': // play
- play(upnp);
- break;
- case 's':
- stop(upnp);
- break;
- case 'g':
- get_trans_info(upnp);
- break;
- default:
- fprintf(stderr,"error: command not understood.\n");
- break;
- }
-
- free_upnp(upnp);
-
- exit(0);
-}
diff --git a/src/avremote.h b/src/avremote.h
new file mode 100644
index 0000000..0d1fa9c
--- /dev/null
+++ b/src/avremote.h
@@ -0,0 +1,68 @@
+/* AVRemote
+
+ (c) 2011 Nederlands Instituut voor Mediakunst (NIMk)
+ 2011 Denis Roio <jaromil@nimk.nl>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero 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 Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>
+
+*/
+
+// messages get rendered in this structure
+// allocated and freed with create/free_upnp
+typedef struct {
+ char *hostname;
+ int port;
+ int sockfd;
+
+ char *hdr;
+ size_t hdrlen;
+
+ char *msg;
+ size_t msglen;
+
+ char *res;
+
+} upnp_t;
+
+// format (printf style) to be used when generating xml markup
+#define UPNP_MSG_FORMAT "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n" \
+ "<s:Envelope s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\"" \
+ "xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\">\r\n<s:Body>\r\n" \
+ "<u:%s xmlns:u=\"urn:schemas-upnp-org:service:AVTransport:1\">\r\n" \
+ "<InstanceID>0</InstanceID>\r\n%s\r\n</u:%s>\r\n</s:Body>\r\n</s:Envelope>\r\n"
+
+#define UPNP_HDR_FORMAT "POST /MediaRenderer_AVTransport/control HTTP/1.0\r\n" \
+ "SOAPACTION: \"urn:schemas-upnp-org:service:AVTransport:1#%s\"\r\n" \
+ "CONTENT-TYPE: text/xml ; charset=\"utf-8\"\r\n" \
+ "HOST: %s:%u\r\n" \
+ "Connection: close\r\n" \
+ "Content-Length: %u\r\n" \
+ "\r\n"
+
+upnp_t *create_upnp();
+void free_upnp(upnp_t *upnp);
+
+int connect_upnp(upnp_t *upnp, char *hostname, int port);
+void render_upnp(upnp_t *upnp, char *action, char *arg);
+
+int send_upnp(upnp_t *upnp);
+int recv_upnp(upnp_t *upnp);
+int print_upnp(upnp_t *upnp);
+
+
+
+
+
+
+int check_upnp(upnp_t *upnp, const char *caller);
diff --git a/src/cmdline.c b/src/cmdline.c
new file mode 100644
index 0000000..fc2f350
--- /dev/null
+++ b/src/cmdline.c
@@ -0,0 +1,184 @@
+/* AVRemote
+
+ (c) 2011 Nederlands Instituut voor Mediakunst (NIMk)
+ 2011 Denis Roio <jaromil@nimk.nl>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero 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 Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>
+
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+
+#include <errno.h>
+
+#include <avremote.h>
+
+// our exit codes are shell style: 1 is error, 0 is success
+#define ERR 1
+
+// uncomment to debug
+#define DEBUG 1
+
+char filename[512];
+char command[64];
+char server[512];
+int port = 0;
+int dry_run = 0;
+
+// we use only getopt, no _long
+static const char *short_options = "-hvs:p:t";
+
+void cmdline(int argc, char **argv) {
+ command[0] = 0;
+ filename[0] = 0;
+ server[0] = 0;
+
+ int res, optlen;
+ do {
+ res = getopt(argc, argv, short_options);
+ switch(res) {
+ case 'h':
+ fprintf(stderr,"usage: %s [options] command [file]\n",argv[0]);
+ break;
+ case 'v':
+ fprintf(stderr,"AVRemote - simple commandline tool to send AVTransport commands over UPNP\n"
+ "version 0.1 (Apr/2011) by Jaromil - Netherlands Media Art Institute\n"
+ "Copyright (C) 2011 NIMk Artlab, License GNU AGPL v3+\n"
+ "This is free software: you are free to change and redistribute it\n");
+ exit(0);
+
+ case 's':
+ snprintf(server,511,"%s",optarg);
+ break;
+
+ case 'p':
+ sscanf (optarg, "%u", &port);
+ break;
+
+ case 't':
+ // test dry run
+ dry_run = 1;
+ fprintf(stderr,"dry run: printint out rendered upnp message without establishing connection\n");
+ break;
+
+ case '?':
+ fprintf(stderr,"unrecognized option: %s\n",optarg);
+ break;
+
+ case 1:
+ {
+ struct stat filestatus;
+ if( stat(optarg,&filestatus) >= 0 ) { // its a file
+ snprintf(filename,511,"%s",optarg);
+ } else {
+ snprintf(command,63,"%s",optarg);
+ fprintf(stderr,"executing command '%s'\n",command);
+ }
+ }
+ break;
+ default:
+ break;
+ }
+
+ } while(res != -1);
+
+ if(!dry_run) {
+ // check requires args
+ if(!command[0]) {
+ fprintf(stderr,"command not specified, see %s -h for help\n",argv[0]);
+ exit(1);
+ }
+
+ if(!port) {
+ fprintf(stderr,"port not specified, use -p\n");
+ exit(1);
+ }
+
+ if(!server[0]) {
+ fprintf(stderr,"server not specified, using localhost\n");
+ sprintf(server,"%s","localhost");
+ }
+ }
+
+}
+
+int main(int argc, char **argv) {
+ int sock, port, n;
+
+ cmdline(argc, argv);
+
+ upnp_t *upnp;
+ upnp = create_upnp();
+
+ if(!dry_run) {
+
+ if ( connect_upnp(upnp, server, port) < 0 ) {
+ fprintf(stderr,"can't connect to server %s: operation aborted.\n", server);
+ 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]) {
+ 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","");
+
+ }
+ break;
+
+ case 's':
+ render_upnp(upnp,"Stop","");
+ break;
+ case 'g':
+ render_upnp(upnp,"GetTransportInfo","");
+ break;
+ default:
+ fprintf(stderr,"error: command not understood.\n");
+ free_upnp(upnp);
+ exit(1);
+ }
+
+ if(dry_run)
+ print_upnp(upnp);
+ else
+ send_upnp(upnp);
+
+ // TODO recv when needed
+
+ free_upnp(upnp);
+
+ exit(0);
+}