liblo: nonblocking_server_example.c Source File

liblo 0.36

nonblocking_server_example.c
1/*
2 * nonblocking_server_example.c
3 *
4 * This code demonstrates two methods of monitoring both an lo_server
5 * and other I/O from a single thread.
6 *
7 * Copyright (C) 2014 Steve Harris et al. (see AUTHORS)
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU Lesser General Public License as
11 * published by the Free Software Foundation; either version 2.1 of the
12 * License, or (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU Lesser General Public License for more details.
18 *
19 * $Id$
20 */
21
22#include <stdio.h>
23#include <stdlib.h>
24#include <sys/types.h>
25#ifndef WIN32
26#include <sys/time.h>
27#include <unistd.h>
28#endif
29
30#include "lo/lo.h"
31
32int done = 0;
33
34void error(int num, const char *m, const char *path);
35
36int generic_handler(const char *path, const char *types, lo_arg ** argv,
37 int argc, lo_message data, void *user_data);
38
39int foo_handler(const char *path, const char *types, lo_arg ** argv,
40 int argc, lo_message data, void *user_data);
41
42int quit_handler(const char *path, const char *types, lo_arg ** argv,
43 int argc, lo_message data, void *user_data);
44
45void read_stdin(void);
46
47int main()
48{
49 int lo_fd;
50 fd_set rfds;
51#ifndef WIN32
52 struct timeval tv;
53#endif
54 int retval;
55
56 /* start a new server on port 7770 */
57 lo_server s = lo_server_new("7770", error);
58
59 /* add method that will match any path and args */
60 lo_server_add_method(s, NULL, NULL, generic_handler, NULL);
61
62 /* add method that will match the path /foo/bar, with two numbers, coerced
63 * to float and int */
64 lo_server_add_method(s, "/foo/bar", "fi", foo_handler, NULL);
65
66 /* add method that will match the path /quit with no args */
67 lo_server_add_method(s, "/quit", "", quit_handler, NULL);
68
69 /* get the file descriptor of the server socket, if supported */
70 lo_fd = lo_server_get_socket_fd(s);
71
72 if (lo_fd > 0) {
73
74 /* select() on lo_server fd is supported, so we'll use select()
75 * to watch both stdin and the lo_server fd. */
76
77 do {
78
79 FD_ZERO(&rfds);
80#ifndef WIN32
81 FD_SET(0, &rfds); /* stdin */
82#endif
83 FD_SET(lo_fd, &rfds);
84
85 retval = select(lo_fd + 1, &rfds, NULL, NULL, NULL); /* no timeout */
86
87 if (retval == -1) {
88
89 printf("select() error\n");
90 exit(1);
91
92 } else if (retval > 0) {
93
94 if (FD_ISSET(0, &rfds)) {
95
96 read_stdin();
97
98 }
99 if (FD_ISSET(lo_fd, &rfds)) {
100
101 lo_server_recv_noblock(s, 0);
102
103 }
104 }
105
106 } while (!done);
107
108 } else {
109
110 /* lo_server protocol does not support select(), so we'll watch
111 * stdin while polling the lo_server. */
112#ifdef WIN32
113 printf
114 ("non-blocking input from stdin not supported under Windows\n");
115 exit(1);
116#else
117 do {
118
119 FD_ZERO(&rfds);
120 FD_SET(0, &rfds);
121 tv.tv_sec = 0;
122 tv.tv_usec = 10000;
123
124 retval = select(1, &rfds, NULL, NULL, &tv); /* timeout every 10ms */
125
126 if (retval == -1) {
127
128 printf("select() error\n");
129 exit(1);
130
131 } else if (retval > 0 && FD_ISSET(0, &rfds)) {
132
133 read_stdin();
134
135 }
136
137 lo_server_recv_noblock(s, 0);
138
139 } while (!done);
140#endif
141 }
142
143 return 0;
144}
145
146void error(int num, const char *msg, const char *path)
147{
148 printf("liblo server error %d in path %s: %s\n", num, path, msg);
149}
150
151/* catch any incoming messages and display them. returning 1 means that the
152 * message has not been fully handled and the server should try other methods */
153int generic_handler(const char *path, const char *types, lo_arg ** argv,
154 int argc, lo_message data, void *user_data)
155{
156 int i;
157
158 printf("path: <%s>\n", path);
159 for (i = 0; i < argc; i++) {
160 printf("arg %d '%c' ", i, types[i]);
161 lo_arg_pp((lo_type)types[i], argv[i]);
162 printf("\n");
163 }
164 printf("\n");
165 fflush(stdout);
166
167 return 1;
168}
169
170int foo_handler(const char *path, const char *types, lo_arg ** argv,
171 int argc, lo_message data, void *user_data)
172{
173 /* example showing pulling the argument values out of the argv array */
174 printf("%s <- f:%f, i:%d\n\n", path, argv[0]->f, argv[1]->i);
175 fflush(stdout);
176
177 return 0;
178}
179
180int quit_handler(const char *path, const char *types, lo_arg ** argv,
181 int argc, lo_message data, void *user_data)
182{
183 done = 1;
184 printf("quiting\n\n");
185
186 return 0;
187}
188
189void read_stdin(void)
190{
191#ifdef WIN32
192 return;
193#else
194 char buf[256];
195 int len = read(0, buf, 256);
196 if (len > 0) {
197 printf("stdin: ");
198 fwrite(buf, len, 1, stdout);
199 printf("\n");
200 fflush(stdout);
201 }
202#endif
203}
204
205/* vi:set ts=8 sts=4 sw=4: */
lo_type
lo_type
An enumeration of the OSC types liblo can send and receive.
Definition lo_osc_types.h:61
lo_server_add_method
lo_method lo_server_add_method(lo_server s, const char *path, const char *typespec, lo_method_handler h, const void *user_data)
Add an OSC method to the specifed server.
lo_server_recv_noblock
int lo_server_recv_noblock(lo_server s, int timeout)
Look for an OSC message waiting to be received.
lo_server_new
lo_server lo_server_new(const char *port, lo_err_handler err_h)
Create a new server instance.
lo_server_get_socket_fd
int lo_server_get_socket_fd(lo_server s)
Return the file descriptor of the server socket.
lo_arg_pp
void lo_arg_pp(lo_type type, void *data)
Pretty-print a set of typed arguments.
lo.h
lo_server
struct lo_server_ * lo_server
An object representing an instance of an OSC server.
Definition lo_types.h:85
lo_message
struct lo_message_ * lo_message
A low-level object used to represent messages passed over OSC.
Definition lo_types.h:60
lo_arg
Union used to read values from incoming messages.
Definition lo_osc_types.h:104