CSL  5.2
oscsend.c
Go to the documentation of this file.
1 /*
2  * oscsend - Send OpenSound Control message.
3  *
4  * Copyright (C) 2008 Kentaro Fukuchi <fukuchi@megaui.net>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU Lesser General Public License as
8  * published by the Free Software Foundation; either version 2.1 of the
9  * License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19  *
20  * TODO:
21  * - support binary blob.
22  * - support TimeTag.
23  * - receive replies.
24  */
25 
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <math.h>
29 #include <string.h>
30 #include <errno.h>
31 #include <config.h>
32 #include <limits.h>
33 #include <lo/lo.h>
34 
35 void usage(void)
36 {
37  printf("oscsend version %s\n"
38  "Copyright (C) 2008 Kentaro Fukuchi\n\n"
39  "Usage: oscsend hostname port address types values...\n"
40  "Send OpenSound Control message via UDP.\n\n"
41  "Description\n"
42  "hostname: specifies the remote host's name.\n"
43  "port : specifies the port number to connect to the remote host.\n"
44  "address : the OSC address where the message to be sent.\n"
45  "types : specifies the types of the following values.\n",
46  VERSION);
47  printf(" %c - 32bit integer\n", LO_INT32);
48  printf(" %c - 64bit integer\n", LO_INT64);
49  printf(" %c - 32bit floating point number\n", LO_FLOAT);
50  printf(" %c - 64bit (double) floating point number\n", LO_DOUBLE);
51  printf(" %c - string\n", LO_STRING);
52  printf(" %c - symbol\n", LO_SYMBOL);
53  printf(" %c - char\n", LO_CHAR);
54  printf(" %c - 4 byte midi packet (8 digits hexadecimal)\n", LO_MIDI);
55  printf(" %c - TRUE (no value required)\n", LO_TRUE);
56  printf(" %c - FALSE (no value required)\n", LO_FALSE);
57  printf(" %c - NIL (no value required)\n", LO_NIL);
58  printf(" %c - INFINITUM (no value required)\n", LO_INFINITUM);
59  printf("values : space separated values.\n\n"
60  "Example\n"
61  "$ oscsend localhost 7777 /sample/address %c%c%c%c 1 3.14 hello\n",
63 }
64 
66 {
67  /* Note:
68  * argv[1] <- hostname
69  * argv[2] <- port
70  * argv[3] <- OSC address
71  * argv[4] <- types
72  * argv[5..] <- values
73  */
74  int i, argi;
75  lo_message message;
76  const char *types, *arg;
77  int values;
78 
79  message = lo_message_new();
80  if(argv[4] == NULL) {
81  /* empty message is allowed. */
82  values = 0;
83  } else {
84  types = argv[4];
85  values = strlen(types);
86  }
87 
88  argi = 5;
89  for(i=0; i<values; i++) {
90  arg = argv[argi];
91  if(arg == NULL) {
92  fprintf(stderr, "Value #%d is not given.\n", i + 1);
93  goto EXIT;
94  }
95  switch(types[i]) {
96  case LO_INT32:
97  {
98  char *endp;
99  int64_t v;
100 
101  v = strtol(arg, &endp, 10);
102  if(*endp != '\0') {
103  fprintf(stderr, "An invalid value was given: '%s'\n", arg);
104  goto EXIT;
105  }
106  if((v == LONG_MAX || v == LONG_MIN) && errno == ERANGE) {
107  fprintf(stderr, "Value out of range: '%s'\n", arg);
108  goto EXIT;
109  }
110  if(v > INT_MAX || v < INT_MIN) {
111  fprintf(stderr, "Value out of range: '%s'\n", arg);
112  goto EXIT;
113  }
114  lo_message_add_int32(message, (int32_t)v);
115  argi++;
116  break;
117  }
118  case LO_INT64:
119  {
120  char *endp;
121  int64_t v;
122 
123  v = strtoll(arg, &endp, 10);
124  if(*endp != '\0') {
125  fprintf(stderr, "An invalid value was given: '%s'\n", arg);
126  goto EXIT;
127  }
128  if((v == LONG_MAX || v == LONG_MIN) && errno == ERANGE) {
129  fprintf(stderr, "Value out of range: '%s'\n", arg);
130  goto EXIT;
131  }
132  lo_message_add_int64(message, v);
133  argi++;
134  break;
135  }
136  case LO_FLOAT:
137  {
138  char *endp;
139  float v;
140 
141 #ifdef __USE_ISOC99
142  v = strtof(arg, &endp);
143 #else
144  v = (float)strtod(arg, &endp);
145 #endif /* __USE_ISOC99 */
146  if(*endp != '\0') {
147  fprintf(stderr, "An invalid value was given: '%s'\n", arg);
148  goto EXIT;
149  }
150  lo_message_add_float(message, v);
151  argi++;
152  break;
153  }
154  case LO_DOUBLE:
155  {
156  char *endp;
157  double v;
158 
159  v = strtod(arg, &endp);
160  if(*endp != '\0') {
161  perror(NULL);
162  fprintf(stderr, "An invalid value was given: '%s'\n", arg);
163  goto EXIT;
164  }
165  lo_message_add_double(message, v);
166  argi++;
167  break;
168  }
169  case LO_STRING:
170  lo_message_add_string(message, arg);
171  argi++;
172  break;
173  case LO_SYMBOL:
174  lo_message_add_symbol(message, arg);
175  argi++;
176  break;
177  case LO_CHAR:
178  lo_message_add_char(message, arg[0]);
179  argi++;
180  break;
181  case LO_MIDI:
182  {
183  unsigned int midi;
184  uint8_t packet[4];
185  int ret;
186 
187  ret = sscanf(arg, "%08x", &midi);
188  if(ret != 1) {
189  fprintf(stderr, "An invalid hexadecimal value was given: '%s'\n", arg);
190  goto EXIT;
191  }
192  packet[0] = (midi>>24) & 0xff;
193  packet[1] = (midi>>16) & 0xff;
194  packet[2] = (midi>> 8) & 0xff;
195  packet[3] = midi & 0xff;
196  lo_message_add_midi(message, packet);
197  argi++;
198  break;
199  }
200  case LO_TRUE:
201  lo_message_add_true(message);
202  break;
203  case LO_FALSE:
204  lo_message_add_false(message);
205  break;
206  case LO_NIL:
207  lo_message_add_nil(message);
208  break;
209  case LO_INFINITUM:
210  lo_message_add_infinitum(message);
211  break;
212  default:
213  fprintf(stderr, "Type '%c' is not supported or invalid.\n", types[i]);
214  goto EXIT;
215  break;
216  }
217  }
218 
219  return message;
220 EXIT:
221  lo_message_free(message);
222  return NULL;
223 }
224 
225 int main(int argc, char **argv)
226 {
227  lo_address target;
228  lo_message message;
229  int ret;
230 
231  if(argc < 4) {
232  usage();
233  exit(1);
234  }
235 
236  if(argv[1] == NULL) {
237  fprintf(stderr, "No hostname is given.\n");
238  exit(1);
239  }
240  if(argv[2] == NULL) {
241  fprintf(stderr, "No port number is given.\n");
242  exit(1);
243  }
244 
245  target = lo_address_new(argv[1], argv[2]);
246  if(target == NULL) {
247  fprintf(stderr, "Failed to open %s:%s\n", argv[1], argv[2]);
248  exit(1);
249  }
250 
251  if(argv[3] == NULL) {
252  fprintf(stderr, "No path is given.\n");
253  exit(1);
254  }
255 
256  message = create_message(argv);
257  if(message == NULL) {
258  fprintf(stderr, "Failed to create OSC message.\n");
259  exit(1);
260  }
261 
262  ret = lo_send_message(target, argv[3], message);
263  if(ret == -1) {
264  fprintf(stderr, "An error occured: %s\n", lo_address_errstr(target));
265  exit(1);
266  }
267 
268  return 0;
269 }