1 /*
2 * oscdump - Receive and dump OpenSound Control messages.
3 *
4 * Copyright (C) 2008 Kentaro Fukuchi <kentaro@fukuchi.org>
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public License
8 * as published by the Free Software Foundation; either version 2.1 of
9 * the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 * 02110-1301 USA.
20 *
21 */
22
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <ctype.h>
27 #include <errno.h>
28 #include <signal.h>
29 #include <config.h>
30 #include <lo/lo.h>
31
32 int done = 0;
33 int bundled = 0;
34 lo_timetag tt_now;
35 lo_timetag tt_bundle;
36 FILE *fout = NULL;
37 int dump_raw = 0;
38
usage(void)39 void usage(void)
40 {
41 printf("oscdump version %s\n"
42 "Copyright (C) 2008 Kentaro Fukuchi\n\n"
43 "Usage: oscdump [-L] [-r] <port>\n"
44 "or oscdump [-L] [-r] <url>\n"
45 "Receive OpenSound Control messages and dump to standard output.\n\n"
46 "Description\n"
47 "-L : specifies line buffering even if stdout is a pipe or file\n"
48 "-r : specifies to dump raw message data to stdout (binary)\n"
49 "port : specifies the listening port number.\n"
50 "url : specifies the server parameters using a liblo URL.\n"
51 " e.g. UDP \"osc.udp://:9000\"\n"
52 " Multicast \"osc.udp://224.0.1.9:9000\"\n"
53 " TCP \"osc.tcp://:9000\"\n\n", VERSION);
54 }
55
bundleStartHandler(lo_timetag tt,void * user_data)56 int bundleStartHandler(lo_timetag tt, void *user_data)
57 {
58 if (tt.sec == LO_TT_IMMEDIATE.sec &&
59 tt.frac == LO_TT_IMMEDIATE.frac)
60 {
61 lo_timetag_now(&tt_now);
62 tt_bundle.sec = tt_now.sec;
63 tt_bundle.frac = tt_now.frac;
64 }
65 else {
66 tt_bundle.sec = tt.sec;
67 tt_bundle.frac = tt.frac;
68 }
69 bundled = 1;
70 return 0;
71 }
72
bundleEndHandler(void * user_data)73 int bundleEndHandler(void *user_data)
74 {
75 bundled = 0;
76 return 0;
77 }
78
errorHandler(int num,const char * msg,const char * where)79 void errorHandler(int num, const char *msg, const char *where)
80 {
81 fprintf(stderr, "liblo server error %d in path %s: %s\n", num, where, msg);
82 }
83
messageHandler(const char * path,const char * types,lo_arg ** argv,int argc,lo_message msg,void * user_data)84 int messageHandler(const char *path, const char *types, lo_arg ** argv,
85 int argc, lo_message msg, void *user_data)
86 {
87 int i;
88
89 if (bundled) {
90 printf("%08x.%08x %s %s", tt_bundle.sec, tt_bundle.frac, path, types);
91 }
92 else {
93 lo_timetag tt = lo_message_get_timestamp(msg);
94 if (tt.sec == LO_TT_IMMEDIATE.sec &&
95 tt.frac == LO_TT_IMMEDIATE.frac)
96 {
97 lo_timetag_now(&tt_now);
98 printf("%08x.%08x %s %s", tt_now.sec, tt_now.frac, path, types);
99 }
100 else
101 printf("%08x.%08x %s %s", tt.sec, tt.frac, path, types);
102 }
103
104 for (i = 0; i < argc; i++) {
105 printf(" ");
106 lo_arg_pp((lo_type) types[i], argv[i]);
107 }
108 printf("\n");
109
110 return 0;
111 }
112
rawMessageHandler(const char * path,const char * types,lo_arg ** argv,int argc,lo_message msg,void * user_data)113 int rawMessageHandler(const char *path, const char *types, lo_arg ** argv,
114 int argc, lo_message msg, void *user_data)
115 {
116 size_t size;
117 void *msg_ptr;
118
119 if(!fout){return 1;}
120
121 msg_ptr=lo_message_serialise(msg, path, NULL, &size);
122 if(!msg_ptr){return 1;}
123
124 fwrite(msg_ptr, 1, size, fout);
125 fflush(fout);
126 free(msg_ptr);
127
128 return 0;
129 }
130
ctrlc(int sig)131 void ctrlc(int sig)
132 {
133 done = 1;
134 }
135
main(int argc,char ** argv)136 int main(int argc, char **argv)
137 {
138 lo_server server;
139 char *port=0, *group=0;
140 int i=1;
141
142 #ifdef WIN32
143 #ifdef HAVE_SETVBUF
144 setvbuf(stdout, 0, _IONBF, BUFSIZ);
145 #endif
146 #endif
147
148 if (argc > i && argv[i][0]=='-') {
149 #ifdef HAVE_SETVBUF
150 if (argv[i][1]=='L') { // line buffering
151 setvbuf(stdout, 0, _IOLBF, BUFSIZ);
152 i++;
153 }
154 else
155 #endif
156 if (argv[i][1]=='h') {
157 usage();
158 exit(0);
159 }
160 else if (argv[i][1]=='r') {
161 dump_raw = 1;
162 i++;
163 }
164 else {
165 fprintf(stderr, "Unknown option `%s'\n", argv[i]);
166 exit(1);
167 }
168 }
169
170 if (argc > i) {
171 port = argv[i];
172 i++;
173 } else {
174 usage();
175 exit(1);
176 }
177
178 if (argc > i) {
179 group = argv[i];
180 }
181
182 if (group) {
183 server = lo_server_new_multicast(group, port, errorHandler);
184 } else if (isdigit(port[0])) {
185 server = lo_server_new(port, errorHandler);
186 } else {
187 server = lo_server_new_from_url(port, errorHandler);
188 }
189
190 if (server == NULL) {
191 fprintf(stderr, "Could not start a server with port %s", port);
192 if (group)
193 fprintf(stderr, ", multicast group %s\n", group);
194 else
195 fprintf(stderr, "\n");
196 exit(1);
197 }
198
199 if(!dump_raw)
200 {
201 lo_server_add_method(server, NULL, NULL, messageHandler, NULL);
202 }
203 else
204 {
205 fout = stdout;
206 lo_server_add_method(server, NULL, NULL, rawMessageHandler, NULL);
207 }
208 lo_server_add_bundle_handlers(server, bundleStartHandler, bundleEndHandler,
209 NULL);
210
211 signal(SIGINT, ctrlc);
212
213 while (!done) {
214 lo_server_recv_noblock(server, 1);
215 }
216
217 return 0;
218 }
219