summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas White <taw@physics.org>2023-04-25 20:36:42 +0200
committerThomas White <taw@physics.org>2023-04-25 20:41:01 +0200
commit52c58f11955dac3185ea6c6c18776e428cbaf800 (patch)
treef0138dac143f2f00f63fca10e00ed91b3eaba733
parent540c125ee6821cd84dd1e72f58c2ec1d39f2ac72 (diff)
Add blocking server
-rw-r--r--README.md19
-rw-r--r--guile-osc.c87
-rw-r--r--open-sound-control/api.scm3
-rw-r--r--open-sound-control/server.scm25
4 files changed, 126 insertions, 8 deletions
diff --git a/README.md b/README.md
index 7361a3b..85f3b07 100644
--- a/README.md
+++ b/README.md
@@ -39,8 +39,23 @@ Then, to receive OSC messages from within a Guile program:
(do-stuff ...)))
```
-Or, to send messages (with parameters):
-
+If the separate server thread doesn't work for you, there's also a blocking
+server option:
+
+```
+(use-modules (open-sound-control server))
+
+(define s (make-osc-server "osc.udp://:7770"))
+
+(add-osc-method s ....)
+
+(osc-recv s) ;; Blocks for 1 second, or until a message is received
+```
+
+You can even have multiple blocking servers at once: `(osc-recv server1 server2)`.
+
+To send messages (with parameters):
+
```
(use-modules (open-sound-control client))
diff --git a/guile-osc.c b/guile-osc.c
index 84cb285..71122e1 100644
--- a/guile-osc.c
+++ b/guile-osc.c
@@ -27,6 +27,7 @@
static SCM osc_server_thread_type;
+static SCM osc_server_type;
static SCM osc_method_type;
static SCM osc_address_type;
@@ -59,6 +60,27 @@ static void finalize_osc_server_thread(SCM obj)
}
+static SCM make_osc_server(SCM url_obj)
+{
+ const char *url = scm_to_utf8_stringn(url_obj, NULL);
+ lo_server srv = lo_server_new_from_url(url, error_callback);
+ if ( srv == NULL ) {
+ return SCM_BOOL_F;
+ } else {
+ return scm_make_foreign_object_1(osc_server_type, srv);
+ }
+}
+
+
+static void finalize_osc_server(SCM obj)
+{
+ lo_server srv;
+ scm_assert_foreign_object_type(osc_server_type, obj);
+ srv = scm_foreign_object_ref(obj, 0);
+ lo_server_free(srv);
+}
+
+
static SCM make_osc_address(SCM url_obj)
{
lo_address addr;
@@ -203,15 +225,11 @@ static int method_callback(const char *path, const char *types, lo_arg **argv,
static SCM add_osc_method(SCM server_obj, SCM path_obj, SCM argtypes_obj,
SCM proc)
{
- lo_server_thread srv;
lo_method method;
char *path;
char *argtypes;
struct method_callback_data *data;
- scm_assert_foreign_object_type(osc_server_thread_type, server_obj);
- srv = scm_foreign_object_ref(server_obj, 0);
-
argtypes = scm_to_utf8_stringn(argtypes_obj, NULL);
data = malloc(sizeof(struct method_callback_data));
@@ -219,8 +237,28 @@ static SCM add_osc_method(SCM server_obj, SCM path_obj, SCM argtypes_obj,
scm_gc_protect_object(proc);
path = scm_to_utf8_stringn(path_obj, NULL);
- method = lo_server_thread_add_method(srv, path, argtypes,
- method_callback, data);
+
+ if ( SCM_IS_A_P(server_obj, osc_server_thread_type) ) {
+ lo_server_thread srv;
+ srv = scm_foreign_object_ref(server_obj, 0);
+ method = lo_server_thread_add_method(srv, path, argtypes,
+ method_callback, data);
+ } else if ( SCM_IS_A_P(server_obj, osc_server_type) ) {
+ lo_server srv;
+ srv = scm_foreign_object_ref(server_obj, 0);
+ method = lo_server_add_method(srv, path, argtypes,
+ method_callback, data);
+ } else {
+ scm_error_scm(scm_from_utf8_symbol("argument-error"),
+ scm_from_locale_string("add-osc-method"),
+ scm_from_locale_string("Not an OSC server object"),
+ SCM_EOL,
+ SCM_BOOL_F);
+ free(path);
+ free(argtypes);
+ return SCM_UNSPECIFIED;
+ }
+
free(path);
free(argtypes);
@@ -228,6 +266,35 @@ static SCM add_osc_method(SCM server_obj, SCM path_obj, SCM argtypes_obj,
}
+static SCM osc_recv(SCM rest)
+{
+ int i;
+ int n_srv;
+ lo_server *servers;
+ int *rcv;
+
+ SCM le = scm_length(rest);
+ n_srv = scm_to_int(le);
+
+ servers = malloc(n_srv*sizeof(lo_server));
+ rcv = malloc(n_srv*sizeof(int));
+ if ( (servers == NULL) || (rcv == NULL) ) return SCM_UNSPECIFIED;
+
+ for ( i=0; i<n_srv; i++ ) {
+ SCM item = scm_list_ref(rest, scm_from_int(i));
+ scm_assert_foreign_object_type(osc_server_type, item);
+ servers[i] = scm_foreign_object_ref(item, 0);
+ rcv[i] = 0;
+ }
+ lo_servers_recv_noblock(servers, rcv, n_srv, 1000);
+
+ free(servers);
+ free(rcv);
+
+ return SCM_UNSPECIFIED;
+}
+
+
static SCM osc_send(SCM addr_obj, SCM path_obj, SCM rest)
{
lo_address addr;
@@ -278,6 +345,12 @@ void init_guile_osc()
slots,
finalize_osc_server_thread);
+ name = scm_from_utf8_symbol("OSCServer");
+ slots = scm_list_1(scm_from_utf8_symbol("data"));
+ osc_server_type = scm_make_foreign_object_type(name,
+ slots,
+ finalize_osc_server);
+
name = scm_from_utf8_symbol("OSCMethod");
slots = scm_list_1(scm_from_utf8_symbol("data"));
osc_method_type = scm_make_foreign_object_type(name, slots, NULL);
@@ -287,6 +360,8 @@ void init_guile_osc()
osc_address_type = scm_make_foreign_object_type(name, slots, finalize_osc_address);
scm_c_define_gsubr("make-osc-server-thread", 1, 0, 0, make_osc_server_thread);
+ scm_c_define_gsubr("make-osc-server", 1, 0, 0, make_osc_server);
+ scm_c_define_gsubr("osc-recv", 0, 0, 1, osc_recv);
scm_c_define_gsubr("add-osc-method", 4, 0, 0, add_osc_method);
scm_c_define_gsubr("make-osc-address", 1, 0, 0, make_osc_address);
scm_c_define_gsubr("osc-send", 2, 0, 1, osc_send);
diff --git a/open-sound-control/api.scm b/open-sound-control/api.scm
index b34b874..6ee3c9f 100644
--- a/open-sound-control/api.scm
+++ b/open-sound-control/api.scm
@@ -20,8 +20,11 @@
;;
(define-module (open-sound-control api)
#:export (make-osc-server-thread
+ make-osc-server
add-osc-method
+ osc-recv
+
make-osc-address
osc-send))
diff --git a/open-sound-control/server.scm b/open-sound-control/server.scm
new file mode 100644
index 0000000..308faf1
--- /dev/null
+++ b/open-sound-control/server.scm
@@ -0,0 +1,25 @@
+;;
+;; open-sound-control/server.scm
+;;
+;; Copyright © 2023 Thomas White <taw@bitwiz.me.uk>
+;;
+;; This file is part of Guile-OSC.
+;;
+;; Guile-OSC is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU 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 General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see <http://www.gnu.org/licenses/>.
+;;
+(define-module (open-sound-control server)
+ #:use-module (open-sound-control api)
+ #:re-export (make-osc-server
+ add-osc-method
+ osc-recv))