aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHanspeter Portner <dev@open-music-kontrollers.ch>2020-10-02 13:44:49 +0200
committerHanspeter Portner <dev@open-music-kontrollers.ch>2020-10-02 13:44:49 +0200
commit16632b7783805a05690821cf416577cc3f80e214 (patch)
tree8cc1a23557feb4a790a2ee08e8e2d3cdf29689a4
parent887ea4943e837add262c212f57c7a668fd91f6ed (diff)
downloadsherlock.lv2-16632b7783805a05690821cf416577cc3f80e214.tar.xz
Squashed 'osc.lv2/' changes from 3f2cb5db..cca99c96
cca99c96 fix last commit. 7337b70b stream: add method to get file descriptors. 75dfaf7f gitlab-ci: add aarch64 compile target. ef9caebc redesign reader pattern matching infrastructure. 8eee956e add unit test for lv2_osc_reader_match. 343a802c fix unused function on mingw. a7ad4082 fix last commit. 8b356228 ignore missing fnmatch.h on mingw. 8d93e692 ignore missing FNM_EXTMATCH definition on darwin. 4c14d725 meson: compile with -std=gnu11. c04f3bcd prototype reader message path matching. c9bb19d7 util: implement pattern matching via fnmatch. c471d994 add missing stdlib header. 6885c8f1 fix last commit for mingw. 4e5a72cd prototype pollin. d99b20c1 prototype '*' pattern matching. 52216f48 change hooks infra into recursive function. 3a634d97 fix compile warning. 1d0d2e31 prototype unrolling into hooks. git-subtree-dir: osc.lv2 git-subtree-split: cca99c96f82b6b1142899a23ec1ac370a7652f8e
-rw-r--r--.gitlab-ci.yml3
-rw-r--r--VERSION2
-rw-r--r--osc.lv2/reader.h58
-rw-r--r--osc.lv2/stream.h56
-rw-r--r--osc.lv2/util.h126
-rw-r--r--test/osc_test.c411
6 files changed, 651 insertions, 5 deletions
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index ebc4676..f0e54dd 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -52,6 +52,9 @@ i686-linux-gnu:
arm-linux-gnueabihf:
<<: *arm_linux_definition
+aarch64-linux-gnu:
+ <<: *arm_linux_definition
+
x86_64-w64-mingw32:
<<: *universal_w64_definition
diff --git a/VERSION b/VERSION
index 2317587..3170382 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-0.1.105
+0.1.143
diff --git a/osc.lv2/reader.h b/osc.lv2/reader.h
index 8e0ae45..ae46dfa 100644
--- a/osc.lv2/reader.h
+++ b/osc.lv2/reader.h
@@ -24,14 +24,25 @@
#include <osc.lv2/osc.h>
#include <osc.lv2/endian.h>
+#include <osc.lv2/util.h>
#ifdef __cplusplus
extern "C" {
#endif
+
+typedef struct _LV2_OSC_Tree LV2_OSC_Tree;
typedef struct _LV2_OSC_Reader LV2_OSC_Reader;
typedef struct _LV2_OSC_Item LV2_OSC_Item;
typedef struct _LV2_OSC_Arg LV2_OSC_Arg;
+typedef void (*LV2_OSC_Branch)(LV2_OSC_Reader *reader, LV2_OSC_Arg *arg,
+ const LV2_OSC_Tree *tree, void *data);
+
+struct _LV2_OSC_Tree {
+ const char *name;
+ const LV2_OSC_Tree *trees;
+ LV2_OSC_Branch branch;
+};
struct _LV2_OSC_Reader {
const uint8_t *buf;
@@ -564,6 +575,53 @@ lv2_osc_reader_is_message(LV2_OSC_Reader *reader)
return reader->ptr[0] == '/'; //FIXME check path
}
+static inline void
+_lv2_osc_trees_internal(LV2_OSC_Reader *reader, const char *path, const char *from,
+ LV2_OSC_Arg *arg, const LV2_OSC_Tree *trees, void *data)
+{
+ const char *ptr = strchr(from, '/');
+ const char *pattern = strpbrk(from, "*?[]{}/");
+ const bool has_pattern = pattern && (pattern[0] != '/');
+ (void)has_pattern; //FIXME
+
+ const size_t len = ptr
+ ? (size_t)(ptr - from)
+ : strlen(from);
+
+ for(const LV2_OSC_Tree *tree = trees; tree && tree->name; tree++)
+ {
+ if(lv2_osc_pattern_match(from, tree->name, len))
+ {
+ if(tree->trees && ptr)
+ {
+ if(tree->branch)
+ {
+ LV2_OSC_Reader reader_clone = *reader;
+ tree->branch(&reader_clone, arg, tree, data);
+ }
+
+ _lv2_osc_trees_internal(reader, path, &ptr[1], arg, tree->trees, data);
+ }
+ else if(tree->branch && !ptr)
+ {
+ LV2_OSC_Reader reader_clone = *reader;
+ tree->branch(&reader_clone, arg, tree, data);
+ }
+ }
+ }
+}
+
+static inline void
+lv2_osc_reader_match(LV2_OSC_Reader *reader, size_t len,
+ const LV2_OSC_Tree *trees, void *data)
+{
+ LV2_OSC_Arg *arg = OSC_READER_MESSAGE_BEGIN(reader, len);
+ const char *path = arg->path;
+ const char *from = &path[1];
+
+ _lv2_osc_trees_internal(reader, path, from, arg, trees, data);
+}
+
#ifdef __cplusplus
} // extern "C"
#endif
diff --git a/osc.lv2/stream.h b/osc.lv2/stream.h
index a86c230..47d338a 100644
--- a/osc.lv2/stream.h
+++ b/osc.lv2/stream.h
@@ -19,6 +19,7 @@
#define LV2_OSC_STREAM_H
#include <stdbool.h>
+#include <stdlib.h>
#include <string.h>
#if !defined(_WIN32)
# include <arpa/inet.h>
@@ -34,6 +35,7 @@
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
+#include <poll.h>
#include <osc.lv2/osc.h>
@@ -665,7 +667,7 @@ lv2_osc_stream_init(LV2_OSC_Stream *stream, const char *url,
{
memset(stream, 0x0, sizeof(LV2_OSC_Stream));
- strncpy(stream->url, url, sizeof(stream->url));
+ strncpy(stream->url, url, sizeof(stream->url) - 1);
stream->driv = driv;
stream->data = data;
stream->sock = -1;
@@ -1372,6 +1374,58 @@ lv2_osc_stream_run(LV2_OSC_Stream *stream)
return ev;
}
+static int
+lv2_osc_stream_get_file_descriptors(LV2_OSC_Stream *stream, int fds [2])
+{
+ if(!fds)
+ {
+ return 1;
+ }
+
+ fds[0] = stream->sock;
+ fds[1] = stream->fd;
+
+ return 0;
+}
+
+static LV2_OSC_Enum
+lv2_osc_stream_pollin(LV2_OSC_Stream *stream, int timeout_ms)
+{
+ int fd [2];
+
+ if(lv2_osc_stream_get_file_descriptors(stream, fd) != 0)
+ {
+ return LV2_OSC_STREAM_ERRNO(LV2_OSC_NONE, EBADF);
+ }
+
+ struct pollfd fds [2] = {
+ [0] = {
+ .fd = fd[0],
+ .events = POLLIN,
+ .revents = 0
+ },
+ [1] = {
+ .fd = fd[1],
+ .events = POLLIN,
+ .revents = 0
+ }
+ };
+
+ const int res = poll(fds, 2, timeout_ms);
+ if(res < 0)
+ {
+ return LV2_OSC_STREAM_ERRNO(LV2_OSC_NONE, errno);
+ }
+
+#if 0
+ fprintf(stderr, "++ %i: %i %i %i %i\n", res,
+ fds[0].fd, (int)fds[0].revents,
+ fds[1].fd, (int)fds[1].revents);
+#endif
+
+ return lv2_osc_stream_run(stream);
+}
+
#ifdef __cplusplus
} // extern "C"
#endif
diff --git a/osc.lv2/util.h b/osc.lv2/util.h
index 195bb86..3517618 100644
--- a/osc.lv2/util.h
+++ b/osc.lv2/util.h
@@ -23,6 +23,9 @@
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
+#if !defined(_WIN32)
+# include <fnmatch.h>
+#endif
#include <osc.lv2/osc.h>
@@ -45,6 +48,15 @@ extern "C" {
typedef void (*LV2_OSC_Method)(const char *path,
const LV2_Atom_Tuple *arguments, void *data);
+typedef struct _LV2_OSC_Hook LV2_OSC_Hook;
+
+struct _LV2_OSC_Hook {
+ const char *name;
+ const LV2_OSC_Hook *hooks;
+ LV2_OSC_Method method;
+ void *data;
+};
+
// characters not allowed in OSC path string
static const char invalid_path_chars [] = {
' ', '#',
@@ -60,6 +72,120 @@ static const char valid_format_chars [] = {
'\0'
};
+static bool
+lv2_osc_pattern_match(const char *from, const char *name, size_t len)
+{
+#if !defined(_WIN32)
+ size_t nbrace = 0;
+
+# if defined(FNM_EXTMATCH)
+ // count opening curly braces
+ for(size_t i = 0; i < len; i++)
+ {
+ if(from[i] == '{')
+ {
+ nbrace++;
+ }
+ }
+# endif
+
+ // allocate temporary pattern buffer
+ char *pattern = alloca(len + nbrace + 1);
+
+ if(!pattern)
+ {
+ return false;
+ }
+
+# if defined(FNM_EXTMATCH)
+ // convert {x,y} to @(x|y) for extended fnmatch
+ if(nbrace)
+ {
+ char *ptr = pattern;
+
+ for(size_t i = 0; i < len; i++)
+ {
+ switch(from[i])
+ {
+ case '{':
+ {
+ *ptr++ = '@';
+ *ptr++ = '(';
+ } break;
+ case ',':
+ {
+ *ptr++ = '|';
+ } break;
+ case '}':
+ {
+ *ptr++ = ')';
+ } break;
+ default:
+ {
+ *ptr++ = from[i];
+ } break;
+ }
+ }
+ }
+ else
+# endif
+ {
+ memcpy(pattern, from, len);
+ }
+
+ // terminate pattern string with null terminator
+ pattern[len + nbrace] = '\0';
+
+# if defined(FNM_EXTMATCH)
+ return fnmatch(pattern, name, FNM_NOESCAPE | FNM_EXTMATCH) == 0 ? true : false;
+# else
+ return fnmatch(pattern, name, FNM_NOESCAPE) == 0 ? true : false;
+# endif
+#else
+ return strncmp(from, name, len) == 0 ? true : false;
+#endif
+}
+
+static void
+_lv2_osc_hooks_internal(const char *path, const char *from,
+ const LV2_Atom_Tuple *arguments, const LV2_OSC_Hook *hooks)
+{
+ const char *ptr = strchr(from, '/');
+
+ const size_t len = ptr
+ ? (size_t)(ptr - from)
+ : strlen(from);
+
+ for(const LV2_OSC_Hook *hook = hooks; hook && hook->name; hook++)
+ {
+ if(lv2_osc_pattern_match(from, hook->name, len))
+ {
+ if(hook->hooks && ptr)
+ {
+ from = &ptr[1];
+
+ _lv2_osc_hooks_internal(path, from, arguments, hook->hooks);
+ }
+ else if(hook->method && !ptr)
+ {
+ hook->method(path, arguments, hook->data);
+ }
+ }
+ }
+}
+
+/**
+ TODO
+*/
+static void
+lv2_osc_hooks(const char *path, const LV2_Atom_Tuple *arguments, void *data)
+{
+ const LV2_OSC_Hook *hooks = data;
+ const char *from = &path[1];
+
+ _lv2_osc_hooks_internal(path, from, arguments, hooks);
+}
+
/**
TODO
*/
diff --git a/test/osc_test.c b/test/osc_test.c
index a535277..2c6a710 100644
--- a/test/osc_test.c
+++ b/test/osc_test.c
@@ -931,16 +931,421 @@ static const pair_t pairs [] = {
};
#endif
+#if !defined(_WIN32)
+static unsigned foo_sub_one = 0;
+static unsigned foo_sub_two [2] = { 0, 0 };
+static unsigned foo = 0;
+static unsigned bar = 0;
+
+static void
+_one(const char *path, unsigned *flag)
+{
+ *flag += 1;
+
+ if(!path)
+ {
+ return;
+ }
+
+ assert(!strcmp(path, "/sub/one")
+ || !strcmp(path, "/*/one")
+ || !strcmp(path, "/s*/one")
+ || !strcmp(path, "/su*/one")
+ || !strcmp(path, "/sub*/one")
+ || !strcmp(path, "/sub/*")
+ || !strcmp(path, "/*sub/one")
+ || !strcmp(path, "/*s*u*b*/one")
+ || !strcmp(path, "/su[ab]/one")
+ || !strcmp(path, "/su[a-b]/[!a-np-z]ne")
+ || !strcmp(path, "/su[a-b]/one")
+ || !strcmp(path, "/s?b/?ne")
+ || !strcmp(path, "/s?*/?ne")
+ || !strcmp(path, "/s?*/*?e")
+ || !strcmp(path, "/sub/{one,two}"));
+}
+
+static void
+_two(const char *path, unsigned *flag)
+{
+ *flag += 1;
+
+ if(!path)
+ {
+ return;
+ }
+
+ assert(!strcmp(path, "/sub/two")
+ || !strcmp(path, "/sub/*")
+ || !strcmp(path, "/sub/{one,two}"));
+}
+
+static void
+_foo(const char *path, unsigned *flag)
+{
+ *flag += 1;
+
+ if(!path)
+ {
+ return;
+ }
+
+ assert(!strcmp(path, "/foo")
+ || !strcmp(path, "/{foo,bar}"));
+}
+
+static void
+_bar(const char *path, unsigned *flag)
+{
+ *flag += 1;
+
+ if(!path)
+ {
+ return;
+ }
+
+ assert(!strcmp(path, "/bar")
+ || !strcmp(path, "/{foo,bar}"));
+}
+
+static void
+_hook_one(const char *path, const LV2_Atom_Tuple *arguments __attribute__((unused)),
+ void *data)
+{
+ _one(path, data);
+}
+
+static void
+_hook_two(const char *path, const LV2_Atom_Tuple *arguments __attribute__((unused)),
+ void *data)
+{
+ _two(path, data);
+}
+
+static void
+_hook_foo(const char *path, const LV2_Atom_Tuple *arguments __attribute__((unused)),
+ void *data)
+{
+ _foo(path, data);
+}
+
+static void
+_hook_bar(const char *path, const LV2_Atom_Tuple *arguments __attribute__((unused)),
+ void *data)
+{
+ _bar(path, data);
+}
+
+static LV2_OSC_Hook hook_sub [] = {
+ { .name = "one", .method = _hook_one, .data = &foo_sub_one },
+ { .name = "two", .method = _hook_two, .data = &foo_sub_two[0] },
+ { .name = "two", .method = _hook_two, .data = &foo_sub_two[1] },
+ { .name = NULL }
+};
+
+static LV2_OSC_Hook hook_root [] = {
+ { .name = "foo", .method = _hook_foo, .data = &foo },
+ { .name = "bar", .method = _hook_bar, .data = &bar },
+ { .name = "sub", .hooks = hook_sub },
+ { .name = NULL }
+};
+
+static LV2_OSC_Tree tree_sub [4];
+
+static void
+_branch_one(LV2_OSC_Reader *reader __attribute__((unused)),
+ LV2_OSC_Arg *arg __attribute__((unused)),
+ const LV2_OSC_Tree *tree __attribute__((unused)),
+ void *data __attribute__((unused)))
+{
+ _one(NULL, &foo_sub_one);
+}
+
+static void
+_branch_two(LV2_OSC_Reader *reader __attribute__((unused)),
+ LV2_OSC_Arg *arg __attribute__((unused)),
+ const LV2_OSC_Tree *tree __attribute__((unused)),
+ void *data __attribute__((unused)))
+{
+ const size_t idx = tree - &tree_sub[1];
+
+ _two(NULL, &foo_sub_two[idx]);
+}
+
+static void
+_branch_foo(LV2_OSC_Reader *reader __attribute__((unused)),
+ LV2_OSC_Arg *arg __attribute__((unused)),
+ const LV2_OSC_Tree *tree __attribute__((unused)),
+ void *data __attribute__((unused)))
+{
+ _foo(NULL, &foo);
+}
+
+static void
+_branch_bar(LV2_OSC_Reader *reader __attribute__((unused)),
+ LV2_OSC_Arg *arg __attribute__((unused)),
+ const LV2_OSC_Tree *tree __attribute__((unused)),
+ void *data __attribute__((unused)))
+{
+ _bar(NULL, &bar);
+}
+
+static LV2_OSC_Tree tree_sub [] = {
+ { .name = "one", .branch = _branch_one },
+ { .name = "two", .branch = _branch_two },
+ { .name = "two", .branch = _branch_two },
+ { .name = NULL }
+};
+
+static LV2_OSC_Tree tree_root [] = {
+ { .name = "foo", .branch = _branch_foo },
+ { .name = "bar", .branch = _branch_bar },
+ { .name = "sub", .trees = tree_sub },
+ { .name = NULL }
+};
+
+static bool
+_run_test_hooks_internal(const char *path)
+{
+ foo_sub_one = foo_sub_two[0] = foo_sub_two[1] = foo = bar = false;
+
+ {
+ LV2_OSC_URID osc_urid;
+ LV2_Atom_Forge forge;
+
+ lv2_osc_urid_init(&osc_urid, &map);
+ lv2_atom_forge_init(&forge, &map);
+
+ lv2_atom_forge_set_buffer(&forge, buf0, BUF_SIZE);
+ assert(lv2_osc_forge_message_vararg(&forge, &osc_urid, path, ""));
+
+ const LV2_Atom_Object *obj = (const LV2_Atom_Object *)buf0;;
+ assert(lv2_osc_unroll(&osc_urid, obj, lv2_osc_hooks, hook_root) == true);
+ }
+
+ {
+ LV2_OSC_Writer writer;
+ LV2_OSC_Reader reader;
+
+ lv2_osc_writer_initialize(&writer, buf1, BUF_SIZE);
+ assert(lv2_osc_writer_message_vararg(&writer, path, "") == true);
+
+ size_t len;
+ const uint8_t *buf = lv2_osc_writer_finalize(&writer, &len);
+ assert(buf);
+ assert(len);
+
+ lv2_osc_reader_initialize(&reader, buf, len);
+ lv2_osc_reader_match(&reader, len, tree_root, NULL);
+ }
+
+ return true;
+}
+
+static int
+_run_test_hooks()
+{
+ {
+ assert(_run_test_hooks_internal("/nil") == true);
+ assert(foo == 0);
+ assert(bar == 0);
+ assert(foo_sub_one == 0);
+ assert(foo_sub_two[0] == 0);
+ assert(foo_sub_two[1] == 0);
+ }
+
+ {
+ assert(_run_test_hooks_internal("/foo") == true);
+ assert(foo == 2);
+ assert(bar == 0);
+ assert(foo_sub_one == 0);
+ assert(foo_sub_two[0] == 0);
+ assert(foo_sub_two[1] == 0);
+ }
+
+ {
+ assert(_run_test_hooks_internal("/bar") == true);
+ assert(foo == 0);
+ assert(bar == 2);
+ assert(foo_sub_one == 0);
+ assert(foo_sub_two[0] == 0);
+ assert(foo_sub_two[1] == 0);
+ }
+
+ {
+ assert(_run_test_hooks_internal("/sub/nil") == true);
+ assert(foo == 0);
+ assert(bar == 0);
+ assert(foo_sub_one == 0);
+ assert(foo_sub_two[0] == 0);
+ assert(foo_sub_two[1] == 0);
+ }
+
+ {
+ assert(_run_test_hooks_internal("/sub/one") == true);
+ assert(foo == 0);
+ assert(bar == 0);
+ assert(foo_sub_one == 2);
+ assert(foo_sub_two[0] == 0);
+ assert(foo_sub_two[1] == 0);
+ }
+
+ {
+ assert(_run_test_hooks_internal("/sub/two") == true);
+ assert(foo == 0);
+ assert(bar == 0);
+ assert(foo_sub_one == 0);
+ assert(foo_sub_two[0] == 2);
+ assert(foo_sub_two[1] == 2);
+ }
+
+ {
+ assert(_run_test_hooks_internal("/sub/*") == true);
+ assert(foo == 0);
+ assert(bar == 0);
+ assert(foo_sub_one == 2);
+ assert(foo_sub_two[0] == 2);
+ assert(foo_sub_two[1] == 2);
+ }
+
+ {
+ assert(_run_test_hooks_internal("/*/one") == true);
+ assert(foo == 0);
+ assert(bar == 0);
+ assert(foo_sub_one == 2);
+ assert(foo_sub_two[0] == 0);
+ assert(foo_sub_two[1] == 0);
+ }
+
+ {
+ assert(_run_test_hooks_internal("/s*/one") == true);
+ assert(foo == 0);
+ assert(bar == 0);
+ assert(foo_sub_one == 2);
+ assert(foo_sub_two[0] == 0);
+ assert(foo_sub_two[1] == 0);
+ }
+
+ {
+ assert(_run_test_hooks_internal("/su*/one") == true);
+ assert(foo == 0);
+ assert(bar == 0);
+ assert(foo_sub_one == 2);
+ assert(foo_sub_two[0] == 0);
+ assert(foo_sub_two[1] == 0);
+ }
+
+ {
+ assert(_run_test_hooks_internal("/sub*/one") == true);
+ assert(foo == 0);
+ assert(bar == 0);
+ assert(foo_sub_one == 2);
+ assert(foo_sub_two[0] == 0);
+ assert(foo_sub_two[1] == 0);
+ }
+
+ {
+ assert(_run_test_hooks_internal("/*sub/one") == true);
+ assert(foo == 0);
+ assert(bar == 0);
+ assert(foo_sub_one == 2);
+ assert(foo_sub_two[0] == 0);
+ assert(foo_sub_two[1] == 0);
+ }
+
+ {
+ assert(_run_test_hooks_internal("/*s*u*b*/one") == true);
+ assert(foo == 0);
+ assert(bar == 0);
+ assert(foo_sub_one == 2);
+ assert(foo_sub_two[0] == 0);
+ assert(foo_sub_two[1] == 0);
+ }
+
+ {
+ assert(_run_test_hooks_internal("/su[ab]/one") == true);
+ assert(foo == 0);
+ assert(bar == 0);
+ assert(foo_sub_one == 2);
+ assert(foo_sub_two[0] == 0);
+ assert(foo_sub_two[1] == 0);
+ }
+
+ {
+ assert(_run_test_hooks_internal("/su[a-b]/[!a-np-z]ne") == true);
+ assert(foo == 0);
+ assert(bar == 0);
+ assert(foo_sub_one == 2);
+ assert(foo_sub_two[0] == 0);
+ assert(foo_sub_two[1] == 0);
+ }
+
+ {
+ assert(_run_test_hooks_internal("/su[!a-b]/one") == true);
+ assert(foo == 0);
+ assert(bar == 0);
+ assert(foo_sub_one == 0);
+ assert(foo_sub_two[0] == 0);
+ assert(foo_sub_two[1] == 0);
+ }
+
+ {
+ assert(_run_test_hooks_internal("/s?b/?ne") == true);
+ assert(foo == 0);
+ assert(bar == 0);
+ assert(foo_sub_one == 2);
+ assert(foo_sub_two[0] == 0);
+ assert(foo_sub_two[1] == 0);
+ }
+
+ {
+ assert(_run_test_hooks_internal("/s?*/*?e") == true);
+ assert(foo == 0);
+ assert(bar == 0);
+ assert(foo_sub_one == 2);
+ assert(foo_sub_two[0] == 0);
+ assert(foo_sub_two[1] == 0);
+ }
+
+ {
+ assert(_run_test_hooks_internal("/{foo,bar}") == true);
+ assert(foo == 2);
+ assert(bar == 2);
+ assert(foo_sub_one == 0);
+ assert(foo_sub_two[0] == 0);
+ assert(foo_sub_two[1] == 0);
+ }
+
+ {
+ assert(_run_test_hooks_internal("/sub/{one,two}") == true);
+ assert(foo == 0);
+ assert(bar == 0);
+ assert(foo_sub_one == 2);
+ assert(foo_sub_two[0] == 2);
+ assert(foo_sub_two[1] == 2);
+ }
+
+ return 0;
+}
+#endif
+
int
-main(int argc, char **argv)
+main(int argc __attribute__((unused)), char **argv __attribute__((unused)))
{
- (void)argc;
- (void)argv;
+#if !defined(_WIN32)
+ (void)lv2_osc_stream_pollin; //FIXME
+#endif
fprintf(stdout, "running main tests:\n");
assert(_run_tests() == 0);
#if !defined(_WIN32)
+ fprintf(stdout, "running hook tests:\n");
+ assert(_run_test_hooks() == 0);
+#else
+ (void)lv2_osc_hooks; //FIXME
+#endif
+
+#if !defined(_WIN32)
for(const pair_t *pair = pairs; pair->server; pair++)
{
pthread_t thread_1;