Skip to content

Commit

Permalink
Add blocking server
Browse files Browse the repository at this point in the history
  • Loading branch information
taw10 committed Apr 25, 2023
1 parent 540c125 commit 52c58f1
Show file tree
Hide file tree
Showing 4 changed files with 126 additions and 8 deletions.
19 changes: 17 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down
87 changes: 81 additions & 6 deletions guile-osc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -203,31 +225,76 @@ 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));

data->proc = proc;
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);

return scm_make_foreign_object_1(osc_method_type, method);
}


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;
Expand Down Expand Up @@ -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);
Expand All @@ -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);
Expand Down
3 changes: 3 additions & 0 deletions open-sound-control/api.scm
Original file line number Diff line number Diff line change
Expand Up @@ -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))

Expand Down
25 changes: 25 additions & 0 deletions open-sound-control/server.scm
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
;;
;; open-sound-control/server.scm
;;
;; Copyright © 2023 Thomas White <[email protected]>
;;
;; 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))

0 comments on commit 52c58f1

Please sign in to comment.