17 files changed, 0 insertions(+), 5915 deletions(-)
D osc.lv2/.gitlab-ci.yml
D osc.lv2/COPYING
D osc.lv2/README.md
D osc.lv2/VERSION
D osc.lv2/gitlab-ci/generic.yml
D osc.lv2/lv2-osc.doap.ttl
D osc.lv2/manifest.ttl
D osc.lv2/meson.build
D osc.lv2/osc.lv2/endian.h
D osc.lv2/osc.lv2/forge.h
D osc.lv2/osc.lv2/osc.h
D osc.lv2/osc.lv2/reader.h
D osc.lv2/osc.lv2/stream.h
D osc.lv2/osc.lv2/util.h
D osc.lv2/osc.lv2/writer.h
D osc.lv2/osc.ttl
D osc.lv2/test/osc_test.c
D osc.lv2/.gitlab-ci.yml => osc.lv2/.gitlab-ci.yml +0 -2
@@ 1,2 0,0 @@
-include:
- - local: 'gitlab-ci/generic.yml'
D osc.lv2/COPYING => osc.lv2/COPYING +0 -201
@@ 1,201 0,0 @@
- The Artistic License 2.0
-
- Copyright (c) 2000-2006, The Perl Foundation.
-
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
-Preamble
-
-This license establishes the terms under which a given free software
-Package may be copied, modified, distributed, and/or redistributed.
-The intent is that the Copyright Holder maintains some artistic
-control over the development of that Package while still keeping the
-Package available as open source and free software.
-
-You are always permitted to make arrangements wholly outside of this
-license directly with the Copyright Holder of a given Package. If the
-terms of this license do not permit the full use that you propose to
-make of the Package, you should contact the Copyright Holder and seek
-a different licensing arrangement.
-
-Definitions
-
- "Copyright Holder" means the individual(s) or organization(s)
- named in the copyright notice for the entire Package.
-
- "Contributor" means any party that has contributed code or other
- material to the Package, in accordance with the Copyright Holder's
- procedures.
-
- "You" and "your" means any person who would like to copy,
- distribute, or modify the Package.
-
- "Package" means the collection of files distributed by the
- Copyright Holder, and derivatives of that collection and/or of
- those files. A given Package may consist of either the Standard
- Version, or a Modified Version.
-
- "Distribute" means providing a copy of the Package or making it
- accessible to anyone else, or in the case of a company or
- organization, to others outside of your company or organization.
-
- "Distributor Fee" means any fee that you charge for Distributing
- this Package or providing support for this Package to another
- party. It does not mean licensing fees.
-
- "Standard Version" refers to the Package if it has not been
- modified, or has been modified only in ways explicitly requested
- by the Copyright Holder.
-
- "Modified Version" means the Package, if it has been changed, and
- such changes were not explicitly requested by the Copyright
- Holder.
-
- "Original License" means this Artistic License as Distributed with
- the Standard Version of the Package, in its current version or as
- it may be modified by The Perl Foundation in the future.
-
- "Source" form means the source code, documentation source, and
- configuration files for the Package.
-
- "Compiled" form means the compiled bytecode, object code, binary,
- or any other form resulting from mechanical transformation or
- translation of the Source form.
-
-
-Permission for Use and Modification Without Distribution
-
-(1) You are permitted to use the Standard Version and create and use
-Modified Versions for any purpose without restriction, provided that
-you do not Distribute the Modified Version.
-
-
-Permissions for Redistribution of the Standard Version
-
-(2) You may Distribute verbatim copies of the Source form of the
-Standard Version of this Package in any medium without restriction,
-either gratis or for a Distributor Fee, provided that you duplicate
-all of the original copyright notices and associated disclaimers. At
-your discretion, such verbatim copies may or may not include a
-Compiled form of the Package.
-
-(3) You may apply any bug fixes, portability changes, and other
-modifications made available from the Copyright Holder. The resulting
-Package will still be considered the Standard Version, and as such
-will be subject to the Original License.
-
-
-Distribution of Modified Versions of the Package as Source
-
-(4) You may Distribute your Modified Version as Source (either gratis
-or for a Distributor Fee, and with or without a Compiled form of the
-Modified Version) provided that you clearly document how it differs
-from the Standard Version, including, but not limited to, documenting
-any non-standard features, executables, or modules, and provided that
-you do at least ONE of the following:
-
- (a) make the Modified Version available to the Copyright Holder
- of the Standard Version, under the Original License, so that the
- Copyright Holder may include your modifications in the Standard
- Version.
-
- (b) ensure that installation of your Modified Version does not
- prevent the user installing or running the Standard Version. In
- addition, the Modified Version must bear a name that is different
- from the name of the Standard Version.
-
- (c) allow anyone who receives a copy of the Modified Version to
- make the Source form of the Modified Version available to others
- under
-
- (i) the Original License or
-
- (ii) a license that permits the licensee to freely copy,
- modify and redistribute the Modified Version using the same
- licensing terms that apply to the copy that the licensee
- received, and requires that the Source form of the Modified
- Version, and of any works derived from it, be made freely
- available in that license fees are prohibited but Distributor
- Fees are allowed.
-
-
-Distribution of Compiled Forms of the Standard Version
-or Modified Versions without the Source
-
-(5) You may Distribute Compiled forms of the Standard Version without
-the Source, provided that you include complete instructions on how to
-get the Source of the Standard Version. Such instructions must be
-valid at the time of your distribution. If these instructions, at any
-time while you are carrying out such distribution, become invalid, you
-must provide new instructions on demand or cease further distribution.
-If you provide valid instructions or cease distribution within thirty
-days after you become aware that the instructions are invalid, then
-you do not forfeit any of your rights under this license.
-
-(6) You may Distribute a Modified Version in Compiled form without
-the Source, provided that you comply with Section 4 with respect to
-the Source of the Modified Version.
-
-
-Aggregating or Linking the Package
-
-(7) You may aggregate the Package (either the Standard Version or
-Modified Version) with other packages and Distribute the resulting
-aggregation provided that you do not charge a licensing fee for the
-Package. Distributor Fees are permitted, and licensing fees for other
-components in the aggregation are permitted. The terms of this license
-apply to the use and Distribution of the Standard or Modified Versions
-as included in the aggregation.
-
-(8) You are permitted to link Modified and Standard Versions with
-other works, to embed the Package in a larger work of your own, or to
-build stand-alone binary or bytecode versions of applications that
-include the Package, and Distribute the result without restriction,
-provided the result does not expose a direct interface to the Package.
-
-
-Items That are Not Considered Part of a Modified Version
-
-(9) Works (including, but not limited to, modules and scripts) that
-merely extend or make use of the Package, do not, by themselves, cause
-the Package to be a Modified Version. In addition, such works are not
-considered parts of the Package itself, and are not subject to the
-terms of this license.
-
-
-General Provisions
-
-(10) Any use, modification, and distribution of the Standard or
-Modified Versions is governed by this Artistic License. By using,
-modifying or distributing the Package, you accept this license. Do not
-use, modify, or distribute the Package, if you do not accept this
-license.
-
-(11) If your Modified Version has been derived from a Modified
-Version made by someone other than you, you are nevertheless required
-to ensure that your Modified Version complies with the requirements of
-this license.
-
-(12) This license does not grant you the right to use any trademark,
-service mark, tradename, or logo of the Copyright Holder.
-
-(13) This license includes the non-exclusive, worldwide,
-free-of-charge patent license to make, have made, use, offer to sell,
-sell, import and otherwise transfer the Package with respect to any
-patent claims licensable by the Copyright Holder that are necessarily
-infringed by the Package. If you institute patent litigation
-(including a cross-claim or counterclaim) against any party alleging
-that the Package constitutes direct or contributory patent
-infringement, then this Artistic License to you shall terminate on the
-date that such litigation is filed.
-
-(14) Disclaimer of Warranty:
-THE PACKAGE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS "AS
-IS' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES. THE IMPLIED
-WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
-NON-INFRINGEMENT ARE DISCLAIMED TO THE EXTENT PERMITTED BY YOUR LOCAL
-LAW. UNLESS REQUIRED BY LAW, NO COPYRIGHT HOLDER OR CONTRIBUTOR WILL
-BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
-DAMAGES ARISING IN ANY WAY OUT OF THE USE OF THE PACKAGE, EVEN IF
-ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
D osc.lv2/README.md => osc.lv2/README.md +0 -33
@@ 1,33 0,0 @@
-# osc.lv2
-
-## Open Sound Control Extension for the LV2 Plugin Specification
-
-### Build Status
-
-[![build status](https://gitlab.com/OpenMusicKontrollers/osc.lv2/badges/master/build.svg)](https://gitlab.com/OpenMusicKontrollers/osc.lv2/commits/master)
-
-### Build / test
-
- git clone https://git.open-music-kontrollers.ch/lv2/osc.lv2
- cd osc.lv2
- meson build
- cd build
- ninja -j4
- ninja test
-
-### License
-
-Copyright (c) 2017 Hanspeter Portner (dev@open-music-kontrollers.ch)
-
-This is free software: you can redistribute it and/or modify
-it under the terms of the Artistic License 2.0 as published by
-The Perl Foundation.
-
-This source 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
-Artistic License 2.0 for more details.
-
-You should have received a copy of the Artistic License 2.0
-along the source as a COPYING file. If not, obtain it from
-<http://www.perlfoundation.org/artistic_license_2_0>.
D osc.lv2/VERSION => osc.lv2/VERSION +0 -1
D osc.lv2/gitlab-ci/generic.yml => osc.lv2/gitlab-ci/generic.yml +0 -106
@@ 1,106 0,0 @@
-stages:
- - build
- - deploy
-
-variables:
- PKG_CONFIG_PATH: "/opt/lv2/lib/pkgconfig:/opt/${CI_BUILD_NAME}/lib/pkgconfig:/usr/lib/${CI_BUILD_NAME}/pkgconfig"
- BUILD_OPTS : ""
-
-.native_template: &native_definition
- stage: build
- script:
- - meson --prefix="${CI_PROJECT_DIR}/${CI_PROJECT_NAME}-$(cat VERSION)/${CI_BUILD_NAME}" -Dlv2libdir="" --cross-file "${CI_BUILD_NAME}" ${BUILD_OPTS} build
- - ninja -C build
- - ninja -C build test
- - ninja -C build install
-
- - scan-build --status-bugs meson --prefix="${CI_PROJECT_DIR}/${CI_PROJECT_NAME}-$(cat VERSION)/${CI_BUILD_NAME}" -Dlv2libdir="" --cross-file "${CI_BUILD_NAME}" ${BUILD_OPTS} scanbuild
- - scan-build --status-bugs ninja -C scanbuild
- - scan-build --status-bugs ninja -C scanbuild test
- artifacts:
- name: "${CI_PROJECT_NAME}-$(cat VERSION)-${CI_BUILD_NAME}"
- paths:
- - "${CI_PROJECT_NAME}-$(cat VERSION)/${CI_BUILD_NAME}/"
-
-.cross_template: &cross_definition
- stage: build
- script:
- - meson --prefix="${CI_PROJECT_DIR}/${CI_PROJECT_NAME}-$(cat VERSION)/${CI_BUILD_NAME}" -Dlv2libdir="" --cross-file "${CI_BUILD_NAME}" ${BUILD_OPTS} build
- - ninja -C build
- - ninja -C build test
- - ninja -C build install
- artifacts:
- name: "${CI_PROJECT_NAME}-$(cat VERSION)-${CI_BUILD_NAME}"
- paths:
- - "${CI_PROJECT_NAME}-$(cat VERSION)/${CI_BUILD_NAME}/"
-
-# build
-.universal_linux_template_stretch: &universal_linux_definition_stretch
- image: ventosus/universal-linux-gnu:stretch
- <<: *cross_definition
-
-.universal_linux_template_buster: &universal_linux_definition_buster
- image: ventosus/universal-linux-gnu:buster
- <<: *native_definition
-
-.universal_linux_template_bullseye: &universal_linux_definition_bullseye
- image: ventosus/universal-linux-gnu:bullseye
- <<: *native_definition
-
-.arm_linux_template_stretch: &arm_linux_definition_stretch
- image: ventosus/arm-linux-gnueabihf:stretch
- <<: *cross_definition
-
-.arm_linux_template_buster: &arm_linux_definition_buster
- image: ventosus/arm-linux-gnueabihf:buster
- <<: *cross_definition
-
-.arm_linux_template_bullseye: &arm_linux_definition_bullseye
- image: ventosus/arm-linux-gnueabihf:bullseye
- <<: *cross_definition
-
-# build
-x86_64-linux-gnu-stretch:
- <<: *universal_linux_definition_stretch
-
-x86_64-linux-gnu-buster:
- <<: *universal_linux_definition_buster
-
-x86_64-linux-gnu-bullseye:
- <<: *universal_linux_definition_bullseye
-
-i686-linux-gnu-stretch:
- <<: *universal_linux_definition_stretch
-
-i686-linux-gnu-buster:
- <<: *universal_linux_definition_buster
-
-i686-linux-gnu-bullseye:
- <<: *universal_linux_definition_bullseye
-
-arm-linux-gnueabihf-stretch:
- <<: *arm_linux_definition_stretch
-
-arm-linux-gnueabihf-buster:
- <<: *arm_linux_definition_buster
-
-arm-linux-gnueabihf-bullseye:
- <<: *arm_linux_definition_bullseye
-
-aarch64-linux-gnu-stretch:
- <<: *arm_linux_definition_stretch
-
-aarch64-linux-gnu-buster:
- <<: *arm_linux_definition_buster
-
-aarch64-linux-gnu-bullseye:
- <<: *arm_linux_definition_bullseye
-
-pack:
- stage: deploy
- script:
- - echo 'packing up'
- artifacts:
- name: "${CI_PROJECT_NAME}-$(cat VERSION)"
- paths:
- - "${CI_PROJECT_NAME}-$(cat VERSION)/"
D osc.lv2/lv2-osc.doap.ttl => osc.lv2/lv2-osc.doap.ttl +0 -40
@@ 1,40 0,0 @@
-# Copyright (c) 2015-2016 Hanspeter Portner (dev@open-music-kontrollers.ch)
-#
-# This is free software: you can redistribute it and/or modify
-# it under the terms of the Artistic License 2.0 as published by
-# The Perl Foundation.
-#
-# This source 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
-# Artistic License 2.0 for more details.
-#
-# You should have received a copy of the Artistic License 2.0
-# along the source as a COPYING file. If not, obtain it from
-# http://www.perlfoundation.org/artistic_license_2_0.
-
-@prefix dcs: <http://ontologi.es/doap-changeset#> .
-@prefix doap: <http://usefulinc.com/ns/doap#> .
-@prefix foaf: <http://xmlns.com/foaf/0.1/> .
-@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
-@prefix lic: <http://opensource.org/licenses/> .
-@prefix omk: <http://open-music-kontrollers.ch/ventosus#> .
-
-<http://open-music-kontrollers.ch/lv2/osc>
- a doap:Project ;
- doap:license lic:Artistic-2.0 ;
- doap:name "LV2 OSC" ;
- doap:shortdesc "A definition of atomified OSC." ;
- doap:maintainer omk:me ;
- doap:created "2015-06-19" ;
- doap:developer omk:me ;
- doap:release [
- doap:revision "1.0" ;
- doap:created "2015-06-19" ;
- dcs:blame omk:me ;
- dcs:changeset [
- dcs:item [
- rdfs:label "Initial release."
- ]
- ]
- ] .
D osc.lv2/manifest.ttl => osc.lv2/manifest.ttl +0 -23
@@ 1,23 0,0 @@
-# Copyright (c) 2015-2016 Hanspeter Portner (dev@open-music-kontrollers.ch)
-#
-# This is free software: you can redistribute it and/or modify
-# it under the terms of the Artistic License 2.0 as published by
-# The Perl Foundation.
-#
-# This source 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
-# Artistic License 2.0 for more details.
-#
-# You should have received a copy of the Artistic License 2.0
-# along the source as a COPYING file. If not, obtain it from
-# http://www.perlfoundation.org/artistic_license_2_0.
-
-@prefix lv2: <http://lv2plug.in/ns/lv2core#> .
-@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
-
-<http://open-music-kontrollers.ch/lv2/osc>
- a lv2:Specification ;
- lv2:minorVersion 1 ;
- lv2:microVersion 0 ;
- rdfs:seeAlso <osc.ttl> .
D osc.lv2/meson.build => osc.lv2/meson.build +0 -36
@@ 1,36 0,0 @@
-project('osc.lv2', 'c', default_options : [
- 'buildtype=release',
- 'warning_level=3',
- 'werror=true',
- 'b_lto=false',
- 'c_std=c11'])
-
-version = run_command('cat', 'VERSION').stdout().strip()
-
-add_project_arguments('-D_GNU_SOURCE', language : 'c')
-
-conf_data = configuration_data()
-cc = meson.get_compiler('c')
-
-lv2_dep = dependency('lv2')
-thread_dep = dependency('threads')
-deps = [lv2_dep, thread_dep]
-
-c_args = []
-
-if host_machine.system() == 'windows'
- deps += cc.find_library('ws2_32')
- c_args += '-Wno-error=format'
- c_args += '-Wno-error=format-extra-args'
-endif
-
-osc_test = executable('osc_test',
- join_paths('test', 'osc_test.c'),
- c_args : c_args,
- dependencies : deps,
- install : false)
-
-# FIXME start virautl serial pair before test
-# socat -d -d pty,raw,echo=0 pty,raw,echo=0
-test('Test', osc_test,
- timeout : 240)
D osc.lv2/osc.lv2/endian.h => osc.lv2/osc.lv2/endian.h +0 -120
@@ 1,120 0,0 @@
-// "License": Public Domain
-// I, Mathias Panzenböck, place this file hereby into the public domain. Use it at your own risk for whatever you like.
-// In case there are jurisdictions that don't support putting things in the public domain you can also consider it to
-// be "dual licensed" under the BSD, MIT and Apache licenses, if you want to. This code is trivial anyway. Consider it
-// an example on how to get the endian conversion functions on different platforms.
-
-#ifndef PORTABLE_ENDIAN_H__
-#define PORTABLE_ENDIAN_H__
-
-#if (defined(_WIN16) || defined(_WIN32) || defined(_WIN64)) && !defined(__WINDOWS__)
-
-# define __WINDOWS__
-
-#endif
-
-#if defined(__linux__) || defined(__CYGWIN__)
-
-# include <endian.h>
-
-#elif defined(__APPLE__)
-
-# include <libkern/OSByteOrder.h>
-
-# define htobe16(x) OSSwapHostToBigInt16(x)
-# define htole16(x) OSSwapHostToLittleInt16(x)
-# define be16toh(x) OSSwapBigToHostInt16(x)
-# define le16toh(x) OSSwapLittleToHostInt16(x)
-
-# define htobe32(x) OSSwapHostToBigInt32(x)
-# define htole32(x) OSSwapHostToLittleInt32(x)
-# define be32toh(x) OSSwapBigToHostInt32(x)
-# define le32toh(x) OSSwapLittleToHostInt32(x)
-
-# define htobe64(x) OSSwapHostToBigInt64(x)
-# define htole64(x) OSSwapHostToLittleInt64(x)
-# define be64toh(x) OSSwapBigToHostInt64(x)
-# define le64toh(x) OSSwapLittleToHostInt64(x)
-
-# define __BYTE_ORDER BYTE_ORDER
-# define __BIG_ENDIAN BIG_ENDIAN
-# define __LITTLE_ENDIAN LITTLE_ENDIAN
-# define __PDP_ENDIAN PDP_ENDIAN
-
-#elif defined(__OpenBSD__)
-
-# include <sys/endian.h>
-
-#elif defined(__NetBSD__) || defined(__FreeBSD__) || defined(__DragonFly__) || defined(__OpenBSD__)
-
-# include <sys/endian.h>
-
-#elif defined(__WINDOWS__)
-
-# include <winsock2.h>
-# include <sys/param.h>
-
-# if BYTE_ORDER == LITTLE_ENDIAN
-
-# define htobe16(x) htons(x)
-# define htole16(x) (x)
-# define be16toh(x) ntohs(x)
-# define le16toh(x) (x)
-
-# define htobe32(x) htonl(x)
-# define htole32(x) (x)
-# define be32toh(x) ntohl(x)
-# define le32toh(x) (x)
-
-# ifndef htonll
-static inline uint64_t htonll(uint64_t n)
-{
- return (((uint64_t)htonl(n)) << 32) + htonl(n >> 32);
-}
-# endif
-
-# ifndef ntohll
-# define ntohll htonll
-# endif
-
-# define htobe64(x) htonll(x)
-# define htole64(x) (x)
-# define be64toh(x) ntohll(x)
-# define le64toh(x) (x)
-
-# elif BYTE_ORDER == BIG_ENDIAN
-
- /* that would be xbox 360 */
-# define htobe16(x) (x)
-# define htole16(x) __builtin_bswap16(x)
-# define be16toh(x) (x)
-# define le16toh(x) __builtin_bswap16(x)
-
-# define htobe32(x) (x)
-# define htole32(x) __builtin_bswap32(x)
-# define be32toh(x) (x)
-# define le32toh(x) __builtin_bswap32(x)
-
-# define htobe64(x) (x)
-# define htole64(x) __builtin_bswap64(x)
-# define be64toh(x) (x)
-# define le64toh(x) __builtin_bswap64(x)
-
-# else
-
-# error byte order not supported
-
-# endif
-
-# define __BYTE_ORDER BYTE_ORDER
-# define __BIG_ENDIAN BIG_ENDIAN
-# define __LITTLE_ENDIAN LITTLE_ENDIAN
-# define __PDP_ENDIAN PDP_ENDIAN
-
-#else
-
-# error platform not supported
-
-#endif
-
-#endif
D osc.lv2/osc.lv2/forge.h => osc.lv2/osc.lv2/forge.h +0 -474
@@ 1,474 0,0 @@
-/*
- * Copyright (c) 2015-2016 Hanspeter Portner (dev@open-music-kontrollers.ch)
- *
- * This is free software: you can redistribute it and/or modify
- * it under the terms of the Artistic License 2.0 as published by
- * The Perl Foundation.
- *
- * This source 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
- * Artistic License 2.0 for more details.
- *
- * You should have received a copy of the Artistic License 2.0
- * along the source as a COPYING file. If not, obtain it from
- * http://www.perlfoundation.org/artistic_license_2_0.
- */
-
-#ifndef LV2_OSC_FORGE_H
-#define LV2_OSC_FORGE_H
-
-#include <inttypes.h>
-
-#include <osc.lv2/osc.h>
-#include <osc.lv2/util.h>
-#include <osc.lv2/reader.h>
-
-#include <lv2/lv2plug.in/ns/ext/atom/forge.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define lv2_osc_forge_int(forge, osc_urid, val) \
- lv2_atom_forge_int((forge), (val))
-
-#define lv2_osc_forge_float(forge, osc_urid, val) \
- lv2_atom_forge_float((forge), (val))
-
-#define lv2_osc_forge_string(forge, osc_urid, val, len) \
- lv2_atom_forge_string((forge), (val), (len))
-
-#define lv2_osc_forge_long(forge, osc_urid, val) \
- lv2_atom_forge_long((forge), (val))
-
-#define lv2_osc_forge_double(forge, osc_urid, val) \
- lv2_atom_forge_double((forge), (val))
-
-#define lv2_osc_forge_true(forge, osc_urid) \
- lv2_atom_forge_bool((forge), 1)
-
-#define lv2_osc_forge_false(forge, osc_urid) \
- lv2_atom_forge_bool((forge), 0)
-
-#define lv2_osc_forge_nil(forge, osc_urid) \
- lv2_atom_forge_literal((forge), "", 0, (osc_urid)->OSC_Nil, 0)
-
-#define lv2_osc_forge_impulse(forge, osc_urid) \
- lv2_atom_forge_literal((forge), "", 0, (osc_urid)->OSC_Impulse, 0)
-
-#define lv2_osc_forge_symbol(forge, osc_urid, val) \
- lv2_atom_forge_urid((forge), (val))
-
-static inline LV2_Atom_Forge_Ref
-lv2_osc_forge_chunk(LV2_Atom_Forge *forge, LV2_URID type,
- const uint8_t *buf, uint32_t size)
-{
- LV2_Atom_Forge_Ref ref;
-
- if( (ref = lv2_atom_forge_atom(forge, size, type))
- && (ref = lv2_atom_forge_raw(forge, buf, size)) )
- {
- lv2_atom_forge_pad(forge, size);
- return ref;
- }
-
- return 0;
-}
-
-static inline LV2_Atom_Forge_Ref
-lv2_osc_forge_midi(LV2_Atom_Forge *forge, LV2_OSC_URID *osc_urid,
- const uint8_t *buf, uint32_t size)
-{
- assert(size <= 3);
- return lv2_osc_forge_chunk(forge, osc_urid->MIDI_MidiEvent, buf, size);
-}
-
-static inline LV2_Atom_Forge_Ref
-lv2_osc_forge_blob(LV2_Atom_Forge* forge, LV2_OSC_URID *osc_urid,
- const uint8_t *buf, uint32_t size)
-{
- return lv2_osc_forge_chunk(forge, osc_urid->ATOM_Chunk, buf, size);
-}
-
-static inline LV2_Atom_Forge_Ref
-lv2_osc_forge_char(LV2_Atom_Forge* forge, LV2_OSC_URID *osc_urid,
- char val)
-{
- return lv2_atom_forge_literal(forge, &val, 1, osc_urid->OSC_Char, 0);
-}
-
-static inline LV2_Atom_Forge_Ref
-lv2_osc_forge_rgba(LV2_Atom_Forge* forge, LV2_OSC_URID *osc_urid,
- uint8_t r, uint8_t g, uint8_t b, uint8_t a)
-{
- char val [9];
- sprintf(val, "%02"PRIx8"%02"PRIx8"%02"PRIx8"%02"PRIx8, r, g, b, a);
- return lv2_atom_forge_literal(forge, val, 8, osc_urid->OSC_RGBA, 0);
-}
-
-static inline LV2_Atom_Forge_Ref
-lv2_osc_forge_timetag(LV2_Atom_Forge *forge, LV2_OSC_URID *osc_urid,
- const LV2_OSC_Timetag *timetag)
-{
- LV2_Atom_Forge_Frame frame;
- LV2_Atom_Forge_Ref ref;
-
- if( (ref = lv2_atom_forge_object(forge, &frame, 0, osc_urid->OSC_Timetag))
- && (ref = lv2_atom_forge_key(forge, osc_urid->OSC_timetagIntegral))
- && (ref = lv2_atom_forge_long(forge, timetag->integral))
- && (ref = lv2_atom_forge_key(forge, osc_urid->OSC_timetagFraction))
- && (ref = lv2_atom_forge_long(forge, timetag->fraction)) )
- {
- lv2_atom_forge_pop(forge, &frame);
- return ref;
- }
-
- return 0;
-}
-
-static inline LV2_Atom_Forge_Ref
-lv2_osc_forge_bundle_head(LV2_Atom_Forge* forge, LV2_OSC_URID *osc_urid,
- LV2_Atom_Forge_Frame frame [2], const LV2_OSC_Timetag *timetag)
-{
- LV2_Atom_Forge_Ref ref;
-
- if( (ref = lv2_atom_forge_object(forge, &frame[0], 0, osc_urid->OSC_Bundle))
- && (ref = lv2_atom_forge_key(forge, osc_urid->OSC_bundleTimetag))
- && (ref = lv2_osc_forge_timetag(forge, osc_urid, timetag))
- && (ref = lv2_atom_forge_key(forge, osc_urid->OSC_bundleItems))
- && (ref = lv2_atom_forge_tuple(forge, &frame[1])) )
- {
- return ref;
- }
-
- return 0;
-}
-
-/**
- TODO
-*/
-static inline LV2_Atom_Forge_Ref
-lv2_osc_forge_message_head(LV2_Atom_Forge *forge, LV2_OSC_URID *osc_urid,
- LV2_Atom_Forge_Frame frame [2], const char *path)
-{
- assert(path);
-
- LV2_Atom_Forge_Ref ref;
- if( (ref = lv2_atom_forge_object(forge, &frame[0], 0, osc_urid->OSC_Message))
- && (ref = lv2_atom_forge_key(forge, osc_urid->OSC_messagePath))
- && (ref = lv2_atom_forge_string(forge, path, strlen(path)))
- && (ref = lv2_atom_forge_key(forge, osc_urid->OSC_messageArguments))
- && (ref = lv2_atom_forge_tuple(forge, &frame[1])) )
- {
- return ref;
- }
-
- return 0;
-}
-
-/**
- TODO
-*/
-static inline void
-lv2_osc_forge_pop(LV2_Atom_Forge *forge, LV2_Atom_Forge_Frame frame [2])
-{
- lv2_atom_forge_pop(forge, &frame[1]); // a LV2_Atom_Tuple
- lv2_atom_forge_pop(forge, &frame[0]); // a LV2_Atom_Object
-}
-
-static inline LV2_Atom_Forge_Ref
-lv2_osc_forge_message_varlist(LV2_Atom_Forge *forge, LV2_OSC_URID *osc_urid,
- const char *path, const char *fmt, va_list args)
-{
- LV2_Atom_Forge_Frame frame [2];
- LV2_Atom_Forge_Ref ref;
-
- if(!lv2_osc_check_path(path) || !lv2_osc_check_fmt(fmt, 0))
- return 0;
- if(!(ref = lv2_osc_forge_message_head(forge, osc_urid, frame, path)))
- return 0;
-
- for(const char *type = fmt; *type; type++)
- {
- switch( (LV2_OSC_Type)*type)
- {
- case LV2_OSC_INT32:
- {
- if(!(ref = lv2_osc_forge_int(forge, osc_urid, va_arg(args, int32_t))))
- return 0;
- break;
- }
- case LV2_OSC_FLOAT:
- {
- if(!(ref = lv2_osc_forge_float(forge, osc_urid, (float)va_arg(args, double))))
- return 0;
- break;
- }
- case LV2_OSC_STRING:
- {
- const char *s = va_arg(args, const char *);
- if(!s || !(ref = lv2_osc_forge_string(forge, osc_urid, s, strlen(s))))
- return 0;
- break;
- }
- case LV2_OSC_BLOB:
- {
- const int32_t size = va_arg(args, int32_t);
- const uint8_t *b = va_arg(args, const uint8_t *);
- if(!b || !(ref = lv2_osc_forge_blob(forge, osc_urid, b, size)))
- return 0;
- break;
- }
-
- case LV2_OSC_INT64:
- {
- if(!(ref = lv2_osc_forge_long(forge, osc_urid, va_arg(args, int64_t))))
- return 0;
- break;
- }
- case LV2_OSC_DOUBLE:
- {
- if(!(ref = lv2_osc_forge_double(forge, osc_urid, va_arg(args, double))))
- return 0;
- break;
- }
- case LV2_OSC_TIMETAG:
- {
- const LV2_OSC_Timetag timetag = {
- .integral = va_arg(args, uint32_t),
- .fraction = va_arg(args, uint32_t)
- };
- if(!(ref = lv2_osc_forge_timetag(forge, osc_urid, &timetag)))
- return 0;
- break;
- }
-
- case LV2_OSC_TRUE:
- {
- if(!(ref = lv2_osc_forge_true(forge, osc_urid)))
- return 0;
- break;
- }
- case LV2_OSC_FALSE:
- {
- if(!(ref = lv2_osc_forge_false(forge, osc_urid)))
- return 0;
- break;
- }
- case LV2_OSC_NIL:
- {
- if(!(ref = lv2_osc_forge_nil(forge, osc_urid)))
- return 0;
- break;
- }
- case LV2_OSC_IMPULSE:
- {
- if(!(ref = lv2_osc_forge_impulse(forge, osc_urid)))
- return 0;
- break;
- }
-
- case LV2_OSC_SYMBOL:
- {
- if(!(ref = lv2_osc_forge_symbol(forge, osc_urid, va_arg(args, uint32_t))))
- return 0;
- break;
- }
- case LV2_OSC_MIDI:
- {
- const int32_t size = va_arg(args, int32_t);
- const uint8_t *m = va_arg(args, const uint8_t *);
- if(!m || !(ref = lv2_osc_forge_midi(forge, osc_urid, m, size)))
- return 0;
- break;
- }
- case LV2_OSC_CHAR:
- {
- if(!(ref = lv2_osc_forge_char(forge, osc_urid, (char)va_arg(args, int))))
- return 0;
- break;
- }
- case LV2_OSC_RGBA:
- {
- if(!(ref = lv2_osc_forge_rgba(forge, osc_urid,
- (uint8_t)va_arg(args, unsigned),
- (uint8_t)va_arg(args, unsigned),
- (uint8_t)va_arg(args, unsigned),
- (uint8_t)va_arg(args, unsigned))))
- return 0;
- break;
- }
- }
- }
-
- lv2_osc_forge_pop(forge, frame);
-
- return ref;
-}
-
-static inline LV2_Atom_Forge_Ref
-lv2_osc_forge_message_vararg(LV2_Atom_Forge *forge, LV2_OSC_URID *osc_urid,
- const char *path, const char *fmt, ...)
-{
- LV2_Atom_Forge_Ref ref;
- va_list args;
-
- va_start(args, fmt);
-
- ref = lv2_osc_forge_message_varlist(forge, osc_urid, path, fmt, args);
-
- va_end(args);
-
- return ref;
-}
-
-static inline LV2_Atom_Forge_Ref
-lv2_osc_forge_packet(LV2_Atom_Forge *forge, LV2_OSC_URID *osc_urid,
- LV2_URID_Map *map, const uint8_t *buf, size_t size)
-{
- LV2_OSC_Reader reader;
- LV2_Atom_Forge_Frame frame [2];
- LV2_Atom_Forge_Ref ref;
-
- lv2_osc_reader_initialize(&reader, buf, size);
-
- if(lv2_osc_reader_is_bundle(&reader))
- {
- LV2_OSC_Item *itm = OSC_READER_BUNDLE_BEGIN(&reader, size);
-
- if(itm && (ref = lv2_osc_forge_bundle_head(forge, osc_urid, frame,
- LV2_OSC_TIMETAG_CREATE(itm->timetag))))
- {
- OSC_READER_BUNDLE_ITERATE(&reader, itm)
- {
- if(!(ref = lv2_osc_forge_packet(forge, osc_urid, map, itm->body, itm->size)))
- return 0;
- }
-
- lv2_osc_forge_pop(forge, frame);
-
- return ref;
- }
- }
- else if(lv2_osc_reader_is_message(&reader))
- {
- LV2_OSC_Arg *arg = OSC_READER_MESSAGE_BEGIN(&reader, size);
-
- if(arg && (ref = lv2_osc_forge_message_head(forge, osc_urid, frame, arg->path)))
- {
- OSC_READER_MESSAGE_ITERATE(&reader, arg)
- {
- switch( (LV2_OSC_Type)*arg->type)
- {
- case LV2_OSC_INT32:
- {
- if(!(ref = lv2_osc_forge_int(forge, osc_urid, arg->i)))
- return 0;
- break;
- }
- case LV2_OSC_FLOAT:
- {
- if(!(ref = lv2_osc_forge_float(forge, osc_urid, arg->f)))
- return 0;
- break;
- }
- case LV2_OSC_STRING:
- {
- if(!(ref = lv2_osc_forge_string(forge, osc_urid, arg->s, arg->size - 1)))
- return 0;
- break;
- }
- case LV2_OSC_BLOB:
- {
- if(!(ref = lv2_osc_forge_blob(forge, osc_urid, arg->b, arg->size)))
- return 0;
- break;
- }
-
- case LV2_OSC_INT64:
- {
- if(!(ref = lv2_osc_forge_long(forge, osc_urid, arg->h)))
- return 0;
- break;
- }
- case LV2_OSC_DOUBLE:
- {
- if(!(ref = lv2_osc_forge_double(forge, osc_urid, arg->d)))
- return 0;
- break;
- }
- case LV2_OSC_TIMETAG:
- {
- if(!(ref = lv2_osc_forge_timetag(forge, osc_urid, LV2_OSC_TIMETAG_CREATE(arg->t))))
- return 0;
- break;
- }
-
- case LV2_OSC_TRUE:
- {
- if(!(ref = lv2_osc_forge_true(forge, osc_urid)))
- return 0;
- break;
- }
- case LV2_OSC_FALSE:
- {
- if(!(ref = lv2_osc_forge_false(forge, osc_urid)))
- return 0;
- break;
- }
- case LV2_OSC_NIL:
- {
- if(!(ref = lv2_osc_forge_nil(forge, osc_urid)))
- return 0;
- break;
- }
- case LV2_OSC_IMPULSE:
- {
- if(!(ref = lv2_osc_forge_impulse(forge, osc_urid)))
- return 0;
- break;
- }
-
- case LV2_OSC_SYMBOL:
- {
- if(!(ref = lv2_osc_forge_symbol(forge, osc_urid,
- map->map(map->handle, arg->S))))
- return 0;
- break;
- }
- case LV2_OSC_MIDI:
- {
- if(!(ref = lv2_osc_forge_midi(forge, osc_urid, &arg->b[1], arg->size - 1)))
- return 0;
- break;
- }
- case LV2_OSC_CHAR:
- {
- if(!(ref = lv2_osc_forge_char(forge, osc_urid, arg->c)))
- return 0;
- break;
- }
- case LV2_OSC_RGBA:
- {
- if(!(ref = lv2_osc_forge_rgba(forge, osc_urid, arg->R, arg->G, arg->B, arg->A)))
- return 0;
- break;
- }
- }
- }
-
- lv2_osc_forge_pop(forge, frame);
-
- return ref;
- }
- }
-
- return 0;
-}
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
-
-#endif // LV2_OSC_FORGE_H
D osc.lv2/osc.lv2/osc.h => osc.lv2/osc.lv2/osc.h +0 -192
@@ 1,192 0,0 @@
-/*
- * Copyright (c) 2015-2016 Hanspeter Portner (dev@open-music-kontrollers.ch)
- *
- * This is free software: you can redistribute it and/or modify
- * it under the terms of the Artistic License 2.0 as published by
- * The Perl Foundation.
- *
- * This source 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
- * Artistic License 2.0 for more details.
- *
- * You should have received a copy of the Artistic License 2.0
- * along the source as a COPYING file. If not, obtain it from
- * http://www.perlfoundation.org/artistic_license_2_0.
- */
-
-#ifndef LV2_OSC_H
-#define LV2_OSC_H
-
-#include <stdint.h>
-
-#include <lv2/lv2plug.in/ns/ext/urid/urid.h>
-#include <lv2/lv2plug.in/ns/ext/atom/atom.h>
-#include <lv2/lv2plug.in/ns/ext/midi/midi.h>
-
-#define LV2_OSC_URI "http://open-music-kontrollers.ch/lv2/osc"
-#define LV2_OSC_PREFIX LV2_OSC_URI "#"
-
-#define LV2_OSC__Event LV2_OSC_PREFIX "Event" // atom message type
-#define LV2_OSC__schedule LV2_OSC_PREFIX "schedule" // feature
-
-#define LV2_OSC__Packet LV2_OSC_PREFIX "Packet" // atom object type
-
-#define LV2_OSC__Bundle LV2_OSC_PREFIX "Bundle" // atom object type
-#define LV2_OSC__bundleTimetag LV2_OSC_PREFIX "bundleTimetag" // atom object property
-#define LV2_OSC__bundleItems LV2_OSC_PREFIX "bundleItems"
-
-#define LV2_OSC__Message LV2_OSC_PREFIX "Message" // atom object type
-#define LV2_OSC__messagePath LV2_OSC_PREFIX "messagePath" // atom object property
-#define LV2_OSC__messageArguments LV2_OSC_PREFIX "messageArguments" // atom object property
-
-#define LV2_OSC__Timetag LV2_OSC_PREFIX "Timetag" // atom object type
-#define LV2_OSC__timetagIntegral LV2_OSC_PREFIX "timetagIntegral" // atom object property
-#define LV2_OSC__timetagFraction LV2_OSC_PREFIX "timetagFraction" // atom object property
-
-#define LV2_OSC__Nil LV2_OSC_PREFIX "Nil" // atom literal type
-#define LV2_OSC__Impulse LV2_OSC_PREFIX "Impulse" // atom literal type
-#define LV2_OSC__Char LV2_OSC_PREFIX "Char" // atom literal type
-#define LV2_OSC__RGBA LV2_OSC_PREFIX "RGBA" // atom literal type
-
-#define LV2_OSC_PADDED_SIZE(size) ( ( (size_t)(size) + 3 ) & ( ~3 ) )
-#define LV2_OSC_IMMEDIATE 1ULL
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-typedef void *LV2_OSC_Schedule_Handle;
-
-typedef double (*LV2_OSC_Schedule_OSC2Frames)(
- LV2_OSC_Schedule_Handle handle,
- uint64_t timetag);
-
-typedef uint64_t (*LV2_OSC_Schedule_Frames2OSC)(
- LV2_OSC_Schedule_Handle handle,
- double frames);
-
-typedef struct _LV2_OSC_Schedule {
- LV2_OSC_Schedule_Handle handle;
- LV2_OSC_Schedule_OSC2Frames osc2frames;
- LV2_OSC_Schedule_Frames2OSC frames2osc;
-} LV2_OSC_Schedule;
-
-typedef enum LV2_OSC_Type {
- LV2_OSC_INT32 = 'i',
- LV2_OSC_FLOAT = 'f',
- LV2_OSC_STRING = 's',
- LV2_OSC_BLOB = 'b',
-
- LV2_OSC_TRUE = 'T',
- LV2_OSC_FALSE = 'F',
- LV2_OSC_NIL = 'N',
- LV2_OSC_IMPULSE = 'I',
-
- LV2_OSC_INT64 = 'h',
- LV2_OSC_DOUBLE = 'd',
- LV2_OSC_TIMETAG = 't',
-
- LV2_OSC_SYMBOL = 'S',
- LV2_OSC_CHAR = 'c',
- LV2_OSC_MIDI = 'm',
- LV2_OSC_RGBA = 'r'
-} LV2_OSC_Type;
-
-union swap32_t {
- uint32_t u;
-
- int32_t i;
- float f;
-};
-
-union swap64_t {
- uint64_t u;
-
- int64_t h;
- uint64_t t;
- double d;
-};
-
-typedef struct _LV2_OSC_Timetag {
- uint32_t integral;
- uint32_t fraction;
-} LV2_OSC_Timetag;
-
-typedef struct _LV2_OSC_URID {
- LV2_URID OSC_Packet;
-
- LV2_URID OSC_Bundle;
- LV2_URID OSC_bundleTimetag;
- LV2_URID OSC_bundleItems;
-
- LV2_URID OSC_Message;
- LV2_URID OSC_messagePath;
- LV2_URID OSC_messageArguments;
-
- LV2_URID OSC_Timetag;
- LV2_URID OSC_timetagIntegral;
- LV2_URID OSC_timetagFraction;
-
- LV2_URID OSC_Nil;
- LV2_URID OSC_Impulse;
- LV2_URID OSC_Char;
- LV2_URID OSC_RGBA;
-
- LV2_URID MIDI_MidiEvent;
-
- LV2_URID ATOM_Int;
- LV2_URID ATOM_Long;
- LV2_URID ATOM_String;
- LV2_URID ATOM_Literal;
- LV2_URID ATOM_Float;
- LV2_URID ATOM_Double;
- LV2_URID ATOM_URID;
- LV2_URID ATOM_Bool;
- LV2_URID ATOM_Tuple;
- LV2_URID ATOM_Object;
- LV2_URID ATOM_Chunk;
-} LV2_OSC_URID;
-
-static inline void
-lv2_osc_urid_init(LV2_OSC_URID *osc_urid, LV2_URID_Map *map)
-{
- osc_urid->OSC_Packet = map->map(map->handle, LV2_OSC__Packet);
-
- osc_urid->OSC_Bundle = map->map(map->handle, LV2_OSC__Bundle);
- osc_urid->OSC_bundleTimetag = map->map(map->handle, LV2_OSC__bundleTimetag);
- osc_urid->OSC_bundleItems = map->map(map->handle, LV2_OSC__bundleItems);
-
- osc_urid->OSC_Message = map->map(map->handle, LV2_OSC__Message);
- osc_urid->OSC_messagePath = map->map(map->handle, LV2_OSC__messagePath);
- osc_urid->OSC_messageArguments = map->map(map->handle, LV2_OSC__messageArguments);
-
- osc_urid->OSC_Timetag = map->map(map->handle, LV2_OSC__Timetag);
- osc_urid->OSC_timetagIntegral = map->map(map->handle, LV2_OSC__timetagIntegral);
- osc_urid->OSC_timetagFraction = map->map(map->handle, LV2_OSC__timetagFraction);
-
- osc_urid->OSC_Nil = map->map(map->handle, LV2_OSC__Nil);
- osc_urid->OSC_Impulse = map->map(map->handle, LV2_OSC__Impulse);
- osc_urid->OSC_Char = map->map(map->handle, LV2_OSC__Char);
- osc_urid->OSC_RGBA = map->map(map->handle, LV2_OSC__RGBA);
-
- osc_urid->MIDI_MidiEvent = map->map(map->handle, LV2_MIDI__MidiEvent);
-
- osc_urid->ATOM_Int = map->map(map->handle, LV2_ATOM__Int);
- osc_urid->ATOM_Long = map->map(map->handle, LV2_ATOM__Long);
- osc_urid->ATOM_String = map->map(map->handle, LV2_ATOM__String);
- osc_urid->ATOM_Literal = map->map(map->handle, LV2_ATOM__Literal);
- osc_urid->ATOM_Float = map->map(map->handle, LV2_ATOM__Float);
- osc_urid->ATOM_Double = map->map(map->handle, LV2_ATOM__Double);
- osc_urid->ATOM_URID = map->map(map->handle, LV2_ATOM__URID);
- osc_urid->ATOM_Bool = map->map(map->handle, LV2_ATOM__Bool);
- osc_urid->ATOM_Tuple = map->map(map->handle, LV2_ATOM__Tuple);
- osc_urid->ATOM_Object = map->map(map->handle, LV2_ATOM__Object);
- osc_urid->ATOM_Chunk = map->map(map->handle, LV2_ATOM__Chunk);
-}
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
-
-#endif // LV2_OSC_H
D osc.lv2/osc.lv2/reader.h => osc.lv2/osc.lv2/reader.h +0 -629
@@ 1,629 0,0 @@
-/*
- * Copyright (c) 2015-2016 Hanspeter Portner (dev@open-music-kontrollers.ch)
- *
- * This is free software: you can redistribute it and/or modify
- * it under the terms of the Artistic License 2.0 as published by
- * The Perl Foundation.
- *
- * This source 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
- * Artistic License 2.0 for more details.
- *
- * You should have received a copy of the Artistic License 2.0
- * along the source as a COPYING file. If not, obtain it from
- * http://www.perlfoundation.org/artistic_license_2_0.
- */
-
-#ifndef LV2_OSC_READER_H
-#define LV2_OSC_READER_H
-
-#include <stdbool.h>
-#include <string.h>
-#include <stdarg.h>
-
-#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;
- const uint8_t *ptr;
- const uint8_t *end;
-};
-
-struct _LV2_OSC_Item {
- int32_t size;
- const uint8_t *body;
-
- uint64_t timetag;
- const uint8_t *end;
-};
-
-struct _LV2_OSC_Arg {
- const char *type;
- int32_t size;
- union {
- int32_t i;
- float f;
- const char *s;
- const uint8_t *b;
-
- int64_t h;
- double d;
- uint64_t t;
-
- const uint8_t *m;
- const char *S;
- char c;
- struct {
- uint8_t R;
- uint8_t G;
- uint8_t B;
- uint8_t A;
- }; // anonymous RGBA struct
- };
-
- const char *path;
- const uint8_t *end;
-};
-
-static inline void
-lv2_osc_reader_initialize(LV2_OSC_Reader *reader, const uint8_t *buf, size_t size)
-{
- reader->buf = buf;
- reader->ptr = buf;
- reader->end = buf + size;
-}
-
-static inline bool
-lv2_osc_reader_overflow(LV2_OSC_Reader *reader, size_t size)
-{
- return reader->ptr + size > reader->end;
-}
-
-static inline bool
-lv2_osc_reader_be32toh(LV2_OSC_Reader *reader, union swap32_t *s32)
-{
- if(lv2_osc_reader_overflow(reader, 4))
- return false;
-
- s32->u = *(const uint32_t *)reader->ptr;
- s32->u = be32toh(s32->u);
- reader->ptr += 4;
-
- return true;
-}
-
-static inline bool
-lv2_osc_reader_be64toh(LV2_OSC_Reader *reader, union swap64_t *s64)
-{
- if(lv2_osc_reader_overflow(reader, 8))
- return false;
-
- s64->u = *(const uint64_t *)reader->ptr;
- s64->u = be64toh(s64->u);
- reader->ptr += 8;
-
- return true;
-}
-
-static inline bool
-lv2_osc_reader_get_int32(LV2_OSC_Reader *reader, int32_t *i)
-{
- union swap32_t s32;
- if(!lv2_osc_reader_be32toh(reader, &s32))
- return false;
-
- *i = s32.i;
-
- return true;
-}
-
-static inline bool
-lv2_osc_reader_get_float(LV2_OSC_Reader *reader, float *f)
-{
- union swap32_t s32;
- if(!lv2_osc_reader_be32toh(reader, &s32))
- return false;
-
- *f = s32.f;
-
- return true;
-}
-
-static inline bool
-lv2_osc_reader_get_int64(LV2_OSC_Reader *reader, int64_t *h)
-{
- union swap64_t s64;
- if(!lv2_osc_reader_be64toh(reader, &s64))
- return false;
-
- *h = s64.h;
-
- return true;
-}
-
-static inline bool
-lv2_osc_reader_get_timetag(LV2_OSC_Reader *reader, uint64_t *t)
-{
- union swap64_t s64;
- if(!lv2_osc_reader_be64toh(reader, &s64))
- return false;
-
- *t = s64.u;
-
- return true;
-}
-
-static inline bool
-lv2_osc_reader_get_double(LV2_OSC_Reader *reader, double *d)
-{
- union swap64_t s64;
- if(!lv2_osc_reader_be64toh(reader, &s64))
- return false;
-
- *d = s64.d;
-
- return true;
-}
-
-static inline bool
-lv2_osc_reader_get_string(LV2_OSC_Reader *reader, const char **s)
-{
- const char *str = (const char *)reader->ptr;
- const size_t padded = LV2_OSC_PADDED_SIZE(strlen(str) + 1);
- if(lv2_osc_reader_overflow(reader, padded ))
- return false;
-
- *s = str;
- reader->ptr += padded;
-
- return true;
-}
-
-static inline bool
-lv2_osc_reader_get_symbol(LV2_OSC_Reader *reader, const char **S)
-{
- return lv2_osc_reader_get_string(reader, S);
-}
-
-static inline bool
-lv2_osc_reader_get_midi(LV2_OSC_Reader *reader, const uint8_t **m)
-{
- if(lv2_osc_reader_overflow(reader, 4))
- return false;
-
- *m = reader->ptr;
- reader->ptr += 4;
-
- return true;
-}
-
-static inline bool
-lv2_osc_reader_get_blob(LV2_OSC_Reader *reader, int32_t *len, const uint8_t **body)
-{
- if(!lv2_osc_reader_get_int32(reader, len))
- return false;
-
- const size_t padded = LV2_OSC_PADDED_SIZE(*len);
- if(lv2_osc_reader_overflow(reader, padded))
- return false;
-
- *body = reader->ptr;
- reader->ptr += padded;
-
- return true;
-}
-
-static inline bool
-lv2_osc_reader_get_rgba(LV2_OSC_Reader *reader, uint8_t *r, uint8_t *g, uint8_t *b, uint8_t *a)
-{
- if(lv2_osc_reader_overflow(reader, 4))
- return false;
-
- *r = reader->ptr[0];
- *g = reader->ptr[1];
- *b = reader->ptr[2];
- *a = reader->ptr[3];
- reader->ptr += 4;
-
- return true;
-}
-
-static inline bool
-lv2_osc_reader_get_char(LV2_OSC_Reader *reader, char *c)
-{
- int32_t i;
- if(!lv2_osc_reader_get_int32(reader, &i))
- return false;
-
- *c = i;
-
- return true;
-}
-
-static inline LV2_OSC_Item *
-lv2_osc_reader_item_raw(LV2_OSC_Reader *reader, LV2_OSC_Item *itm)
-{
- if(!lv2_osc_reader_get_int32(reader, &itm->size))
- return NULL;
-
- if(lv2_osc_reader_overflow(reader, itm->size))
- return NULL;
-
- itm->body = reader->ptr;
-
- return itm;
-}
-
-static inline LV2_OSC_Item *
-lv2_osc_reader_item_begin(LV2_OSC_Reader *reader, LV2_OSC_Item *itm, size_t len)
-{
- if(lv2_osc_reader_overflow(reader, len))
- return NULL;
-
- itm->end = reader->ptr + len;
-
- if(lv2_osc_reader_overflow(reader, 16))
- return NULL;
-
- if(strncmp((const char *)reader->ptr, "#bundle", 8))
- return NULL;
- reader->ptr += 8;
-
- if(!lv2_osc_reader_get_timetag(reader, &itm->timetag))
- return NULL;
-
- return lv2_osc_reader_item_raw(reader, itm);
-}
-
-static inline bool
-lv2_osc_reader_item_is_end(LV2_OSC_Reader *reader, LV2_OSC_Item *itm)
-{
- return reader->ptr > itm->end;
-}
-
-static inline LV2_OSC_Item *
-lv2_osc_reader_item_next(LV2_OSC_Reader *reader, LV2_OSC_Item *itm)
-{
- reader->ptr += itm->size;
-
- return lv2_osc_reader_item_raw(reader, itm);
-}
-
-#define OSC_READER_BUNDLE_BEGIN(reader, len) \
- lv2_osc_reader_item_begin( \
- (reader), \
- &(LV2_OSC_Item){ .size = 0, .body = NULL, .timetag = 1ULL, .end = NULL }, \
- len)
-
-#define OSC_READER_BUNDLE_ITERATE(reader, itm) \
- for(itm = itm; \
- itm && !lv2_osc_reader_item_is_end((reader), (itm)); \
- itm = lv2_osc_reader_item_next((reader), (itm)))
-
-#define OSC_READER_BUNDLE_FOREACH(reader, itm, len) \
- for(LV2_OSC_Item *(itm) = OSC_READER_BUNDLE_BEGIN((reader), (len)); \
- itm && !lv2_osc_reader_item_is_end((reader), (itm)); \
- itm = lv2_osc_reader_item_next((reader), (itm)))
-
-static inline LV2_OSC_Arg *
-lv2_osc_reader_arg_raw(LV2_OSC_Reader *reader, LV2_OSC_Arg *arg)
-{
- switch( (LV2_OSC_Type)*arg->type)
- {
- case LV2_OSC_INT32:
- {
- if(!lv2_osc_reader_get_int32(reader, &arg->i))
- return NULL;
- arg->size = 4;
-
- break;
- }
- case LV2_OSC_FLOAT:
- {
- if(!lv2_osc_reader_get_float(reader, &arg->f))
- return NULL;
- arg->size = 4;
-
- break;
- }
- case LV2_OSC_STRING:
- {
- if(!lv2_osc_reader_get_string(reader, &arg->s))
- return NULL;
- arg->size = strlen(arg->s) + 1;
-
- break;
- }
- case LV2_OSC_BLOB:
- {
- if(!lv2_osc_reader_get_blob(reader, &arg->size, &arg->b))
- return NULL;
- //arg->size = arg->size;
-
- break;
- }
-
- case LV2_OSC_TRUE:
- case LV2_OSC_FALSE:
- case LV2_OSC_NIL:
- case LV2_OSC_IMPULSE:
- break;
-
- case LV2_OSC_INT64:
- {
- if(!lv2_osc_reader_get_int64(reader, &arg->h))
- return NULL;
- arg->size = 8;
-
- break;
- }
- case LV2_OSC_DOUBLE:
- {
- if(!lv2_osc_reader_get_double(reader, &arg->d))
- return NULL;
- arg->size = 8;
-
- break;
- }
- case LV2_OSC_TIMETAG:
- {
- if(!lv2_osc_reader_get_timetag(reader, &arg->t))
- return NULL;
- arg->size = 8;
-
- break;
- }
-
- case LV2_OSC_MIDI:
- {
- if(!lv2_osc_reader_get_midi(reader, &arg->m))
- return NULL;
- arg->size = 4;
-
- break;
- }
- case LV2_OSC_SYMBOL:
- {
- if(!lv2_osc_reader_get_symbol(reader, &arg->S))
- return NULL;
- arg->size = strlen(arg->S) + 1;
-
- break;
- }
- case LV2_OSC_CHAR:
- {
- if(!lv2_osc_reader_get_char(reader, &arg->c))
- return NULL;
- arg->size = 4;
-
- break;
- }
- case LV2_OSC_RGBA:
- {
- if(!lv2_osc_reader_get_rgba(reader, &arg->R, &arg->G, &arg->B, &arg->A))
- return NULL;
- arg->size = 4;
-
- break;
- }
- }
-
- return arg;
-}
-
-static inline LV2_OSC_Arg *
-lv2_osc_reader_arg_begin(LV2_OSC_Reader *reader, LV2_OSC_Arg *arg, size_t len)
-{
- if(lv2_osc_reader_overflow(reader, len))
- return NULL;
-
- arg->end = reader->ptr + len;
-
- if(!lv2_osc_reader_get_string(reader, &arg->path)) //TODO check for validity
- return NULL;
-
- if(!lv2_osc_reader_get_string(reader, &arg->type)) //TODO check for validity
- return NULL;
-
- if(*arg->type != ',')
- return NULL;
-
- arg->type++; // skip ','
-
- return lv2_osc_reader_arg_raw(reader, arg);
-}
-
-static inline bool
-lv2_osc_reader_arg_is_end(LV2_OSC_Reader *reader, LV2_OSC_Arg *arg)
-{
- return (*arg->type == '\0') || (reader->ptr > arg->end);
-}
-
-static inline LV2_OSC_Arg *
-lv2_osc_reader_arg_next(LV2_OSC_Reader *reader, LV2_OSC_Arg *arg)
-{
- arg->type++;
-
- return lv2_osc_reader_arg_raw(reader, arg);
-}
-
-#define OSC_READER_MESSAGE_BEGIN(reader, len) \
- lv2_osc_reader_arg_begin( \
- (reader), \
- &(LV2_OSC_Arg){ .type = NULL, .size = 0, .path = NULL, .end = NULL }, \
- len)
-
-#define OSC_READER_MESSAGE_ITERATE(reader, arg) \
- for(arg = arg; \
- arg && !lv2_osc_reader_arg_is_end((reader), (arg)); \
- arg = lv2_osc_reader_arg_next((reader), (arg)))
-
-#define OSC_READER_MESSAGE_FOREACH(reader, arg, len) \
- for(LV2_OSC_Arg *(arg) = OSC_READER_MESSAGE_BEGIN((reader), (len)); \
- arg && !lv2_osc_reader_arg_is_end((reader), (arg)); \
- arg = lv2_osc_reader_arg_next((reader), (arg)))
-
-static inline bool
-lv2_osc_reader_arg_varlist(LV2_OSC_Reader *reader, const char *fmt, va_list args)
-{
- for(const char *type = fmt; *type; type++)
- {
- switch( (LV2_OSC_Type)*type)
- {
- case LV2_OSC_INT32:
- if(!lv2_osc_reader_get_int32(reader, va_arg(args, int32_t *)))
- return false;
- break;
- case LV2_OSC_FLOAT:
- if(!lv2_osc_reader_get_float(reader, va_arg(args, float *)))
- return false;
- break;
- case LV2_OSC_STRING:
- if(!lv2_osc_reader_get_string(reader, va_arg(args, const char **)))
- return false;
- break;
- case LV2_OSC_BLOB:
- if(!lv2_osc_reader_get_blob(reader, va_arg(args, int32_t *), va_arg(args, const uint8_t **)))
- return false;
- break;
-
- case LV2_OSC_TRUE:
- case LV2_OSC_FALSE:
- case LV2_OSC_NIL:
- case LV2_OSC_IMPULSE:
- break;
-
- case LV2_OSC_INT64:
- if(!lv2_osc_reader_get_int64(reader, va_arg(args, int64_t *)))
- return false;
- break;
- case LV2_OSC_DOUBLE:
- if(!lv2_osc_reader_get_double(reader, va_arg(args, double *)))
- return false;
- break;
- case LV2_OSC_TIMETAG:
- if(!lv2_osc_reader_get_timetag(reader, va_arg(args, uint64_t *)))
- return false;
- break;
-
- case LV2_OSC_MIDI:
- if(!lv2_osc_reader_get_midi(reader, va_arg(args, const uint8_t **)))
- return false;
- break;
- case LV2_OSC_SYMBOL:
- if(!lv2_osc_reader_get_symbol(reader, va_arg(args, const char **)))
- return false;
- break;
- case LV2_OSC_CHAR:
- if(!lv2_osc_reader_get_char(reader, va_arg(args, char *)))
- return false;
- break;
- case LV2_OSC_RGBA:
- if(!lv2_osc_reader_get_rgba(reader, va_arg(args, uint8_t *), va_arg(args, uint8_t *),
- va_arg(args, uint8_t *), va_arg(args, uint8_t *)))
- return false;
- break;
- }
- }
-
- return true;
-}
-
-static inline bool
-lv2_osc_reader_arg_vararg(LV2_OSC_Reader *reader, const char *fmt, ...)
-{
- va_list args;
- va_start(args, fmt);
-
- const bool res = lv2_osc_reader_arg_varlist(reader, fmt, args);
-
- va_end(args);
-
- return res;
-}
-
-static inline bool
-lv2_osc_reader_is_bundle(LV2_OSC_Reader *reader)
-{
- return strncmp((const char *)reader->ptr, "#bundle", 8) == 0;
-}
-
-static inline bool
-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
-
-#endif // LV2_OSC_READER_H
D osc.lv2/osc.lv2/stream.h => osc.lv2/osc.lv2/stream.h +0 -1433
@@ 1,1433 0,0 @@
-/*
- * Copyright (c) 2015-2016 Hanspeter Portner (dev@open-music-kontrollers.ch)
- *
- * This is free software: you can redistribute it and/or modify
- * it under the terms of the Artistic License 2.0 as published by
- * The Perl Foundation.
- *
- * This source 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
- * Artistic License 2.0 for more details.
- *
- * You should have received a copy of the Artistic License 2.0
- * along the source as a COPYING file. If not, obtain it from
- * http://www.perlfoundation.org/artistic_license_2_0.
- */
-
-#ifndef LV2_OSC_STREAM_H
-#define LV2_OSC_STREAM_H
-
-#include <stdbool.h>
-#include <stdlib.h>
-#include <string.h>
-#if !defined(_WIN32)
-# include <arpa/inet.h>
-# include <sys/socket.h>
-# include <net/if.h>
-# include <netinet/tcp.h>
-# include <netinet/in.h>
-# include <netdb.h>
-# include <termios.h>
-# include <limits.h>
-#endif
-#include <sys/types.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <unistd.h>
-#include <poll.h>
-
-#include <osc.lv2/osc.h>
-
-#if !defined(LV2_OSC_STREAM_SNDBUF)
-# define LV2_OSC_STREAM_SNDBUF 0x100000 // 1 M
-#endif
-
-#if !defined(LV2_OSC_STREAM_RCVBUF)
-# define LV2_OSC_STREAM_RCVBUF 0x100000 // 1 M
-#endif
-
-#if !defined(LV2_OSC_STREAM_REQBUF)
-# define LV2_OSC_STREAM_REQBUF 1024
-#endif
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-typedef void *
-(*LV2_OSC_Stream_Write_Request)(void *data, size_t minimum, size_t *maximum);
-
-typedef void
-(*LV2_OSC_Stream_Write_Advance)(void *data, size_t written);
-
-typedef const void *
-(*LV2_OSC_Stream_Read_Request)(void *data, size_t *toread);
-
-typedef void
-(*LV2_OSC_Stream_Read_Advance)(void *data);
-
-typedef struct _LV2_OSC_Address LV2_OSC_Address;
-typedef struct _LV2_OSC_Driver LV2_OSC_Driver;
-typedef struct _LV2_OSC_Stream LV2_OSC_Stream;
-
-struct _LV2_OSC_Address {
- socklen_t len;
- union {
- struct sockaddr_in in4;
- struct sockaddr_in6 in6;
- };
-};
-
-struct _LV2_OSC_Driver {
- LV2_OSC_Stream_Write_Request write_req;
- LV2_OSC_Stream_Write_Advance write_adv;
- LV2_OSC_Stream_Read_Request read_req;
- LV2_OSC_Stream_Read_Advance read_adv;
-};
-
-struct _LV2_OSC_Stream {
- int socket_family;
- int socket_type;
- int protocol;
- bool server;
- bool slip;
- bool serial;
- bool connected;
- int sock;
- int fd;
- LV2_OSC_Address self;
- LV2_OSC_Address peer;
- const LV2_OSC_Driver *driv;
- void *data;
- uint8_t tx_buf [0x4000];
- uint8_t rx_buf [0x4000];
- size_t rx_off;
- char url [PATH_MAX];
-};
-
-typedef enum _LV2_OSC_Enum {
- LV2_OSC_NONE = 0x000000,
-
- LV2_OSC_SEND = 0x800000,
- LV2_OSC_RECV = 0x400000,
- LV2_OSC_CONN = 0x200000,
-
- LV2_OSC_ERR = 0x00ffff
-} LV2_OSC_Enum;
-
-static const char *udp_prefix = "osc.udp://";
-static const char *tcp_prefix = "osc.tcp://";
-static const char *tcp_slip_prefix = "osc.slip.tcp://";
-static const char *tcp_prefix_prefix = "osc.prefix.tcp://";
-static const char *ser_prefix = "osc.serial://";
-//FIXME serial
-
-
-static inline int
-_lv2_osc_stream_interface_attribs(int fd, int speed)
-{
- struct termios tty;
-
- if(tcgetattr(fd, &tty) < 0)
- {
- return -1;
- }
-
- cfsetospeed(&tty, (speed_t)speed);
- cfsetispeed(&tty, (speed_t)speed);
-
- tty.c_cflag |= (CLOCAL | CREAD); /* ignore modem controls */
- tty.c_cflag &= ~CSIZE;
- tty.c_cflag |= CS8; /* 8-bit characters */
- tty.c_cflag &= ~PARENB; /* no parity bit */
- tty.c_cflag &= ~CSTOPB; /* only need 1 stop bit */
- tty.c_cflag &= ~CRTSCTS; /* no hardware flowcontrol */
-
- /* setup for non-canonical mode */
- tty.c_iflag &= ~(IGNCR | ONLCR | IXON);
- tty.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
- tty.c_oflag &= ~OPOST;
-
- /* fetch bytes as they become available */
- tty.c_cc[VMIN] = 0;
- tty.c_cc[VTIME] = 0;
-
- if(tcsetattr(fd, TCSANOW, &tty) != 0)
- {
- return -1;
- }
-
- return 0;
-}
-
-#define LV2_OSC_STREAM_ERRNO(EV, ERRNO) ( (EV & (~LV2_OSC_ERR)) | (ERRNO) )
-
-static inline void
-_close_socket(int *fd)
-{
- if(fd)
- {
- if(*fd >= 0)
- {
- close(*fd);
- }
-
- *fd = -1;
- }
-}
-
-static inline int
-lv2_osc_stream_deinit(LV2_OSC_Stream *stream)
-{
- _close_socket(&stream->fd);
- _close_socket(&stream->sock);
-
- return 0;
-}
-
-static inline int
-_lv2_osc_stream_reinit(LV2_OSC_Stream *stream)
-{
- LV2_OSC_Enum ev = LV2_OSC_NONE;
- lv2_osc_stream_deinit(stream);
-
- char *dup = strdup(stream->url);
- if(!dup)
- {
- ev = LV2_OSC_STREAM_ERRNO(ev, ENOMEM);
- goto fail;
- }
-
- char *ptr = dup;
- char *tmp;
-
- if(strncmp(ptr, udp_prefix, strlen(udp_prefix)) == 0)
- {
- stream->slip = false;
- stream->socket_family = AF_INET;
- stream->socket_type = SOCK_DGRAM;
- stream->protocol = IPPROTO_UDP;
- ptr += strlen(udp_prefix);
- }
- else if(strncmp(ptr, tcp_prefix, strlen(tcp_prefix)) == 0)
- {
- stream->slip = true;
- stream->socket_family = AF_INET;
- stream->socket_type = SOCK_STREAM;
- stream->protocol = IPPROTO_TCP;
- ptr += strlen(tcp_prefix);
- }
- else if(strncmp(ptr, tcp_slip_prefix, strlen(tcp_slip_prefix)) == 0)
- {
- stream->slip = true;
- stream->socket_family = AF_INET;
- stream->socket_type = SOCK_STREAM;
- stream->protocol = IPPROTO_TCP;
- ptr += strlen(tcp_slip_prefix);
- }
- else if(strncmp(ptr, tcp_prefix_prefix, strlen(tcp_prefix_prefix)) == 0)
- {
- stream->slip = false;
- stream->socket_family = AF_INET;
- stream->socket_type = SOCK_STREAM;
- stream->protocol = IPPROTO_TCP;
- ptr += strlen(tcp_prefix_prefix);
- }
- else if(strncmp(ptr, ser_prefix, strlen(ser_prefix)) == 0)
- {
- stream->slip = true;
- stream->serial = true;
- ptr += strlen(ser_prefix);
- }
- else
- {
- ev = LV2_OSC_STREAM_ERRNO(ev, ENOPROTOOPT);
- goto fail;
- }
-
- if(ptr[0] == '\0')
- {
- ev = LV2_OSC_STREAM_ERRNO(ev, EDESTADDRREQ);
- goto fail;
- }
-
- if(stream->serial)
- {
- stream->sock = open(ptr, O_RDWR | O_NOCTTY | O_NDELAY);
- if(stream->sock < 0)
- {
- ev = LV2_OSC_STREAM_ERRNO(ev, errno);
- goto fail;
- }
-
- if(fcntl(stream->sock, F_SETFL, FNDELAY) == -1) //FIXME
- {
- ev = LV2_OSC_STREAM_ERRNO(ev, errno);
- goto fail;
- }
-
- if(_lv2_osc_stream_interface_attribs(stream->sock, B115200) == -1)
- {
- ev = LV2_OSC_STREAM_ERRNO(ev, errno);
- goto fail;
- }
-
- stream->connected = true;
- }
- else // !stream->serial
- {
- const char *node = NULL;
- const char *iface = NULL;
- const char *service = NULL;
-
- // optional IPv6
- if(ptr[0] == '[')
- {
- stream->socket_family = AF_INET6;
- ++ptr;
- }
-
- node = ptr;
-
- // optional IPv6
- if( (tmp = strchr(ptr, '%')) )
- {
- if(stream->socket_family != AF_INET6)
- {
- ev = LV2_OSC_STREAM_ERRNO(ev, EPROTOTYPE);
- goto fail;
- }
-
- ptr = tmp;
- ptr[0] = '\0';
- iface = ++ptr;
- }
-
- // optional IPv6
- if( (tmp = strchr(ptr, ']')) )
- if(ptr)
- {
- if(stream->socket_family != AF_INET6)
- {
- ev = LV2_OSC_STREAM_ERRNO(ev, EDESTADDRREQ);
- goto fail;
- }
-
- ptr = tmp;
- ptr[0] = '\0';
- ++ptr;
- }
-
- // mandatory IPv4/6
- ptr = strchr(ptr, ':');
- if(!ptr)
- {
- ev = LV2_OSC_STREAM_ERRNO(ev, EDESTADDRREQ);
- goto fail;
- }
-
- ptr[0] = '\0';
-
- service = ++ptr;
-
- if(strlen(node) == 0)
- {
- node = NULL;
- stream->server = true;
- }
-
- stream->sock = socket(stream->socket_family, stream->socket_type,
- stream->protocol);
-
- if(stream->sock < 0)
- {
- ev = LV2_OSC_STREAM_ERRNO(ev, errno);
- goto fail;
- }
-
- if(fcntl(stream->sock, F_SETFL, O_NONBLOCK) == -1)
- {
- ev = LV2_OSC_STREAM_ERRNO(ev, errno);
- goto fail;
- }
-
- const int sendbuff = LV2_OSC_STREAM_SNDBUF;
- const int recvbuff = LV2_OSC_STREAM_RCVBUF;
- const int reuseaddr = 1;
-
- if(setsockopt(stream->sock, SOL_SOCKET,
- SO_SNDBUF, &sendbuff, sizeof(sendbuff)) == -1)
- {
- ev = LV2_OSC_STREAM_ERRNO(ev, errno);
- goto fail;
- }
-
- if(setsockopt(stream->sock, SOL_SOCKET,
- SO_RCVBUF, &recvbuff, sizeof(recvbuff)) == -1)
- {
- ev = LV2_OSC_STREAM_ERRNO(ev, errno);
- goto fail;
- }
-
- if(setsockopt(stream->sock, SOL_SOCKET,
- SO_REUSEADDR, &reuseaddr, sizeof(reuseaddr)) == -1)
- {
- ev = LV2_OSC_STREAM_ERRNO(ev, errno);
- goto fail;
- }
-
- if(stream->socket_family == AF_INET) // IPv4
- {
- if(stream->server)
- {
- // resolve self address
- struct addrinfo hints;
- memset(&hints, 0x0, sizeof(struct addrinfo));
- hints.ai_family = stream->socket_family;
- hints.ai_socktype = stream->socket_type;
- hints.ai_protocol = stream->protocol;
-
- struct addrinfo *res;
- if(getaddrinfo(node, service, &hints, &res) != 0)
- {
- ev = LV2_OSC_STREAM_ERRNO(ev, errno);
- goto fail;
- }
- if(res->ai_addrlen != sizeof(stream->peer.in4))
- {
- ev = LV2_OSC_STREAM_ERRNO(ev, EPROTOTYPE);
- goto fail;
- }
-
- stream->self.len = res->ai_addrlen;
- memcpy(&stream->self.in4, res->ai_addr, res->ai_addrlen);
- stream->self.in4.sin_addr.s_addr = htonl(INADDR_ANY);
-
- freeaddrinfo(res);
-
- if(bind(stream->sock, (struct sockaddr *)&stream->self.in4,
- stream->self.len) != 0)
- {
- ev = LV2_OSC_STREAM_ERRNO(ev, errno);
- goto fail;
- }
- }
- else // client
- {
- stream->self.len = sizeof(stream->self.in4);
- stream->self.in4.sin_family = stream->socket_family;
- stream->self.in4.sin_port = htons(0);
- stream->self.in4.sin_addr.s_addr = htonl(INADDR_ANY);
-
- if(bind(stream->sock, (struct sockaddr *)&stream->self.in4,
- stream->self.len) != 0)
- {
- ev = LV2_OSC_STREAM_ERRNO(ev, errno);
- goto fail;
- }
-
- // resolve peer address
- struct addrinfo hints;
- memset(&hints, 0x0, sizeof(struct addrinfo));
- hints.ai_family = stream->socket_family;
- hints.ai_socktype = stream->socket_type;
- hints.ai_protocol = stream->protocol;
-
- struct addrinfo *res;
- if(getaddrinfo(node, service, &hints, &res) != 0)
- {
- ev = LV2_OSC_STREAM_ERRNO(ev, errno);
- goto fail;
- }
- if(res->ai_addrlen != sizeof(stream->peer.in4))
- {
- ev = LV2_OSC_STREAM_ERRNO(ev, EPROTOTYPE);
- goto fail;
- }
-
- stream->peer.len = res->ai_addrlen;
- memcpy(&stream->peer.in4, res->ai_addr, res->ai_addrlen);
-
- freeaddrinfo(res);
- }
-
- if(stream->socket_type == SOCK_DGRAM)
- {
- const int broadcast = 1;
-
- if(setsockopt(stream->sock, SOL_SOCKET, SO_BROADCAST,
- &broadcast, sizeof(broadcast)) != 0)
- {
- ev = LV2_OSC_STREAM_ERRNO(ev, errno);
- goto fail;
- }
-
- //FIXME handle multicast
- }
- else if(stream->socket_type == SOCK_STREAM)
- {
- const int flag = 1;
-
- if(setsockopt(stream->sock, stream->protocol,
- TCP_NODELAY, &flag, sizeof(flag)) != 0)
- {
- ev = LV2_OSC_STREAM_ERRNO(ev, errno);
- goto fail;
- }
-
- if(setsockopt(stream->sock, SOL_SOCKET,
- SO_KEEPALIVE, &flag, sizeof(flag)) != 0)
- {
- ev = LV2_OSC_STREAM_ERRNO(ev, errno);
- goto fail;
- }
-
- if(stream->server)
- {
- if(listen(stream->sock, 1) != 0)
- {
- ev = LV2_OSC_STREAM_ERRNO(ev, errno);
- goto fail;
- }
- }
- else // client
- {
- if(connect(stream->sock, (struct sockaddr *)&stream->peer.in4,
- stream->peer.len) == 0)
- {
- stream->connected = true;
- }
- }
- }
- else
- {
- ev = LV2_OSC_STREAM_ERRNO(ev, EPROTOTYPE);
- goto fail;
- }
- }
- else if(stream->socket_family == AF_INET6) // IPv6
- {
- if(stream->server)
- {
- // resolve self address
- struct addrinfo hints;
- memset(&hints, 0x0, sizeof(struct addrinfo));
- hints.ai_family = stream->socket_family;
- hints.ai_socktype = stream->socket_type;
- hints.ai_protocol = stream->protocol;
-
- struct addrinfo *res;
- if(getaddrinfo(node, service, &hints, &res) != 0)
- {
- ev = LV2_OSC_STREAM_ERRNO(ev, errno);
- goto fail;
- }
- if(res->ai_addrlen != sizeof(stream->peer.in6))
- {
- ev = LV2_OSC_STREAM_ERRNO(ev, EPROTOTYPE);
- goto fail;
- }
-
- stream->self.len = res->ai_addrlen;
- memcpy(&stream->self.in6, res->ai_addr, res->ai_addrlen);
- stream->self.in6.sin6_addr = in6addr_any;
- if(iface)
- {
- stream->self.in6.sin6_scope_id = if_nametoindex(iface);
- }
-
- freeaddrinfo(res);
-
- if(bind(stream->sock, (struct sockaddr *)&stream->self.in6,
- stream->self.len) != 0)
- {
- ev = LV2_OSC_STREAM_ERRNO(ev, errno);
- goto fail;
- }
- }
- else // client
- {
- stream->self.len = sizeof(stream->self.in6);
- stream->self.in6.sin6_family = stream->socket_family;
- stream->self.in6.sin6_port = htons(0);
- stream->self.in6.sin6_addr = in6addr_any;
- if(iface)
- {
- stream->self.in6.sin6_scope_id = if_nametoindex(iface);
- }
-
- if(bind(stream->sock, (struct sockaddr *)&stream->self.in6,
- stream->self.len) != 0)
- {
- ev = LV2_OSC_STREAM_ERRNO(ev, errno);
- goto fail;
- }
-
- // resolve peer address
- struct addrinfo hints;
- memset(&hints, 0x0, sizeof(struct addrinfo));
- hints.ai_family = stream->socket_family;
- hints.ai_socktype = stream->socket_type;
- hints.ai_protocol = stream->protocol;
-
- struct addrinfo *res;
- if(getaddrinfo(node, service, &hints, &res) != 0)
- {
- ev = LV2_OSC_STREAM_ERRNO(ev, errno);
- goto fail;
- }
- if(res->ai_addrlen != sizeof(stream->peer.in6))
- {
- ev = LV2_OSC_STREAM_ERRNO(ev, EPROTOTYPE);
- goto fail;
- }
-
- stream->peer.len = res->ai_addrlen;
- memcpy(&stream->peer.in6, res->ai_addr, res->ai_addrlen);
-
- if(iface)
- {
- stream->peer.in6.sin6_scope_id = if_nametoindex(iface);
- }
-
- freeaddrinfo(res);
- }
-
- if(stream->socket_type == SOCK_DGRAM)
- {
- // nothing to do
- }
- else if(stream->socket_type == SOCK_STREAM)
- {
- const int flag = 1;
-
- if(setsockopt(stream->sock, stream->protocol,
- TCP_NODELAY, &flag, sizeof(flag)) != 0)
- {
- ev = LV2_OSC_STREAM_ERRNO(ev, errno);
- goto fail;
- }
-
- if(setsockopt(stream->sock, SOL_SOCKET,
- SO_KEEPALIVE, &flag, sizeof(flag)) != 0)
- {
- ev = LV2_OSC_STREAM_ERRNO(ev, errno);
- goto fail;
- }
-
- if(stream->server)
- {
- if(listen(stream->sock, 1) != 0)
- {
- ev = LV2_OSC_STREAM_ERRNO(ev, errno);
- goto fail;
- }
- }
- else // client
- {
- if(connect(stream->sock, (struct sockaddr *)&stream->peer.in6,
- stream->peer.len) == 0)
- {
- stream->connected = true;
- }
- }
- }
- else
- {
- ev = LV2_OSC_STREAM_ERRNO(ev, EPROTOTYPE);
- goto fail;
- }
- }
- else
- {
- ev = LV2_OSC_STREAM_ERRNO(ev, EPROTOTYPE);
- goto fail;
- }
- }
-
- free(dup);
-
- return ev;
-
-fail:
- if(dup)
- {
- free(dup);
- }
-
- _close_socket(&stream->sock);
-
- return ev;
-}
-
-static inline int
-lv2_osc_stream_init(LV2_OSC_Stream *stream, const char *url,
- const LV2_OSC_Driver *driv, void *data)
-{
- memset(stream, 0x0, sizeof(LV2_OSC_Stream));
-
- strncpy(stream->url, url, sizeof(stream->url) - 1);
- stream->driv = driv;
- stream->data = data;
- stream->sock = -1;
- stream->fd = -1;
-
- return _lv2_osc_stream_reinit(stream);
-}
-
-#define SLIP_END 0300 // 0xC0, 192, indicates end of packet
-#define SLIP_ESC 0333 // 0xDB, 219, indicates byte stuffing
-#define SLIP_END_REPLACE 0334 // 0xDC, 220, ESC ESC_END means END data byte
-#define SLIP_ESC_REPLACE 0335 // 0xDD, 221, ESC ESC_ESC means ESC data byte
-
-// SLIP encoding
-static inline size_t
-lv2_osc_slip_encode_inline(uint8_t *dst, size_t len)
-{
- if(len == 0)
- return 0;
-
- const uint8_t *end = dst + len;
-
- // estimate new size
- size_t size = 2; // double ended SLIP
- for(const uint8_t *from=dst; from<end; from++, size++)
- {
- if( (*from == SLIP_END) || (*from == SLIP_ESC))
- size ++;
- }
-
- // fast track if no escaping needed
- if(size == len + 2)
- {
- memmove(dst+1, dst, len);
- dst[0] = SLIP_END;
- dst[size-1] = SLIP_END;
-
- return size;
- }
-
- // slow track if some escaping needed
- uint8_t *to = dst + size - 1;
- *to-- = SLIP_END;
- for(const uint8_t *from=end-1; from>=dst; from--)
- {
- if(*from == SLIP_END)
- {
- *to-- = SLIP_END_REPLACE;
- *to-- = SLIP_ESC;
- }
- else if(*from == SLIP_ESC)
- {
- *to-- = SLIP_ESC_REPLACE;
- *to-- = SLIP_ESC;
- }
- else
- *to-- = *from;
- }
- *to-- = SLIP_END;
-
- return size;
-}
-
-// SLIP decoding
-static inline size_t
-lv2_osc_slip_decode_inline(uint8_t *dst, size_t len, size_t *size)
-{
- const uint8_t *src = dst;
- const uint8_t *end = dst + len;
- uint8_t *ptr = dst;
-
- bool whole = false;
-
- if( (src < end) && (*src == SLIP_END) )
- {
- whole = true;
- src++;
- }
-
- while(src < end)
- {
- if(*src == SLIP_ESC)
- {
- if(src == end-1)
- break;
-
- src++;
- if(*src == SLIP_END_REPLACE)
- *ptr++ = SLIP_END;
- else if(*src == SLIP_ESC_REPLACE)
- *ptr++ = SLIP_ESC;
- src++;
- }
- else if(*src == SLIP_END)
- {
- src++;
-
- *size = whole ? ptr - dst : 0;
- return src - dst;
- }
- else
- {
- *ptr++ = *src++;
- }
- }
-
- *size = 0;
- return 0;
-}
-
-static inline LV2_OSC_Enum
-_lv2_osc_stream_run_udp(LV2_OSC_Stream *stream)
-{
- LV2_OSC_Enum ev = LV2_OSC_NONE;
-
- // send everything
- if(stream->peer.len) // has a peer
- {
- const uint8_t *buf;
- size_t tosend;
-
- while( (buf = stream->driv->read_req(stream->data, &tosend)) )
- {
- const ssize_t sent = sendto(stream->sock, buf, tosend, 0,
- (struct sockaddr *)&stream->peer.in6, stream->peer.len);
-
- if(sent == -1)
- {
- if( (errno == EAGAIN) || (errno == EWOULDBLOCK) )
- {
- // full queue
- break;
- }
-
- ev = LV2_OSC_STREAM_ERRNO(ev, errno);
- break;
- }
- else if(sent != (ssize_t)tosend)
- {
- ev = LV2_OSC_STREAM_ERRNO(ev, EIO);
- break;
- }
-
- stream->driv->read_adv(stream->data);
- ev |= LV2_OSC_SEND;
- }
- }
-
- // recv everything
- {
- uint8_t *buf;
- size_t max_len;
-
- while( (buf = stream->driv->write_req(stream->data,
- LV2_OSC_STREAM_REQBUF, &max_len)) )
- {
- struct sockaddr_in6 in;
- socklen_t in_len = sizeof(in);
-
- memset(&in, 0, in_len);
- const ssize_t recvd = recvfrom(stream->sock, buf, max_len, 0,
- (struct sockaddr *)&in, &in_len);
-
- if(recvd == -1)
- {
- if( (errno == EAGAIN) || (errno == EWOULDBLOCK) )
- {
- // empty queue
- break;
- }
-
- ev = LV2_OSC_STREAM_ERRNO(ev, errno);
- break;
- }
- else if(recvd == 0)
- {
- // peer has shut down
- break;
- }
-
- stream->peer.len = in_len;
- memcpy(&stream->peer.in6, &in, in_len);
-
- stream->driv->write_adv(stream->data, recvd);
- ev |= LV2_OSC_RECV;
- }
- }
-
- return ev;
-}
-
-static inline LV2_OSC_Enum
-_lv2_osc_stream_run_tcp(LV2_OSC_Stream *stream)
-{
- LV2_OSC_Enum ev = LV2_OSC_NONE;
-
- // handle connections
- if(!stream->connected) // no peer
- {
- if(stream->server)
- {
- stream->peer.len = sizeof(stream->peer.in6);
- stream->fd = accept(stream->sock, (struct sockaddr *)&stream->peer.in6,
- &stream->peer.len);
-
- if(stream->fd >= 0)
- {
- const int flag = 1;
- const int sendbuff = LV2_OSC_STREAM_SNDBUF;
- const int recvbuff = LV2_OSC_STREAM_RCVBUF;
-
- if(fcntl(stream->fd, F_SETFL, O_NONBLOCK) == -1)
- {
- ev = LV2_OSC_STREAM_ERRNO(ev, errno);
- }
-
- if(setsockopt(stream->fd, stream->protocol,
- TCP_NODELAY, &flag, sizeof(flag)) != 0)
- {
- ev = LV2_OSC_STREAM_ERRNO(ev, errno);
- }
-
- if(setsockopt(stream->sock, SOL_SOCKET,
- SO_KEEPALIVE, &flag, sizeof(flag)) != 0)
- {
- ev = LV2_OSC_STREAM_ERRNO(ev, errno);
- }
-
- if(setsockopt(stream->fd, SOL_SOCKET,
- SO_SNDBUF, &sendbuff, sizeof(sendbuff)) == -1)
- {
- ev = LV2_OSC_STREAM_ERRNO(ev, errno);
- }
-
- if(setsockopt(stream->fd, SOL_SOCKET,
- SO_RCVBUF, &recvbuff, sizeof(recvbuff)) == -1)
- {
- ev = LV2_OSC_STREAM_ERRNO(ev, errno);
- }
-
- stream->connected = true; // orderly accept
- }
- else
- {
- //ev = LV2_OSC_STREAM_ERRNO(ev, errno);
- }
- }
- else
- {
- if(stream->sock < 0)
- {
- ev = _lv2_osc_stream_reinit(stream);
- }
-
- if(connect(stream->sock, (struct sockaddr *)&stream->peer.in6,
- stream->peer.len) == 0)
- {
- stream->connected = true; // orderly (re)connect
- }
- else
- {
- //if(errno == EISCONN)
- //{
- // _close_socket(&stream->sock);
- //}
-
- //ev = LV2_OSC_STREAM_ERRNO(ev, errno);
- }
- }
- }
-
- // send everything
- if(stream->connected)
- {
- int *fd = stream->server
- ? &stream->fd
- : &stream->sock;
-
- if(*fd >= 0)
- {
- const uint8_t *buf;
- size_t tosend;
-
- while( (buf = stream->driv->read_req(stream->data, &tosend)) )
- {
- if(stream->slip) // SLIP framed
- {
- if(tosend <= sizeof(stream->tx_buf)) // check if there is enough memory
- {
- memcpy(stream->tx_buf, buf, tosend);
- tosend = lv2_osc_slip_encode_inline(stream->tx_buf, tosend);
- }
- else
- {
- tosend = 0;
- }
- }
- else // uint32_t prefix frames
- {
- const size_t nsize = tosend + sizeof(uint32_t);
-
- if(nsize <= sizeof(stream->tx_buf)) // check if there is enough memory
- {
- const uint32_t prefix = htonl(tosend);
-
- memcpy(stream->tx_buf, &prefix, sizeof(uint32_t));
- memcpy(stream->tx_buf + sizeof(uint32_t), buf, tosend);
- tosend = nsize;
- }
- else
- {
- tosend = 0;
- }
- }
-
- const ssize_t sent = tosend
- ? send(*fd, stream->tx_buf, tosend, 0)
- : 0;
-
- if(sent == -1)
- {
- if( (errno == EAGAIN) || (errno == EWOULDBLOCK) )
- {
- // empty queue
- break;
- }
-
- _close_socket(fd);
- stream->connected = false;
- ev = LV2_OSC_STREAM_ERRNO(ev, errno);
- break;
- }
- else if(sent != (ssize_t)tosend)
- {
- ev = LV2_OSC_STREAM_ERRNO(ev, EIO);
- break;
- }
-
- stream->driv->read_adv(stream->data);
- ev |= LV2_OSC_SEND;
- }
- }
- }
-
- // recv everything
- if(stream->connected)
- {
- int *fd = stream->server
- ? &stream->fd
- : &stream->sock;
-
- if(*fd >= 0)
- {
- if(stream->slip) // SLIP framed
- {
- while(true)
- {
- ssize_t recvd = recv(*fd, stream->rx_buf + stream->rx_off,
- sizeof(stream->rx_buf) - stream->rx_off, 0);
-
- if(recvd == -1)
- {
- if( (errno == EAGAIN) || (errno == EWOULDBLOCK) )
- {
- // empty queue
- break;
- }
-
- _close_socket(fd);
- stream->connected = false;
- ev = LV2_OSC_STREAM_ERRNO(ev, errno);
- break;
- }
- else if(recvd == 0)
- {
- _close_socket(fd);
- stream->connected = false; // orderly shutdown
- break;
- }
-
- uint8_t *ptr = stream->rx_buf;
- recvd += stream->rx_off;
-
- while(recvd > 0)
- {
- size_t size;
- size_t parsed = lv2_osc_slip_decode_inline(ptr, recvd, &size);
-
- if(size) // dispatch
- {
- uint8_t *buf;
-
- if( (buf = stream->driv->write_req(stream->data, size, NULL)) )
- {
- memcpy(buf, ptr, size);
-
- stream->driv->write_adv(stream->data, size);
- ev |= LV2_OSC_RECV;
- }
- else
- {
- parsed = 0;
- ev = LV2_OSC_STREAM_ERRNO(ev, ENOMEM);
- }
- }
-
- if(parsed)
- {
- ptr += parsed;
- recvd -= parsed;
- }
- else
- {
- break;
- }
- }
-
- if(recvd > 0) // is there remaining chunk for next call?
- {
- memmove(stream->rx_buf, ptr, recvd);
- stream->rx_off = recvd;
- }
- else
- {
- stream->rx_off = 0;
- }
-
- break;
- }
- }
- else // uint32_t prefix frames
- {
- uint8_t *buf;
-
- while( (buf = stream->driv->write_req(stream->data,
- LV2_OSC_STREAM_REQBUF, NULL)) )
- {
- uint32_t prefix;
-
- ssize_t recvd = recv(*fd, &prefix, sizeof(uint32_t), 0);
- if(recvd == sizeof(uint32_t))
- {
- prefix = ntohl(prefix); //FIXME check prefix <= max_len
- recvd = recv(*fd, buf, prefix, 0);
- }
- else if(recvd == -1)
- {
- if( (errno == EAGAIN) || (errno == EWOULDBLOCK) )
- {
- // empty queue
- break;
- }
-
- _close_socket(fd);
- stream->connected = false;
- ev = LV2_OSC_STREAM_ERRNO(ev, errno);
- break;
- }
- else if(recvd == 0)
- {
- _close_socket(fd);
- stream->connected = false; // orderly shutdown
- break;
- }
-
- stream->driv->write_adv(stream->data, recvd);
- ev |= LV2_OSC_RECV;
- }
- }
- }
- }
-
- if(stream->connected)
- {
- ev |= LV2_OSC_CONN;
- }
-
- return ev;
-}
-
-static inline LV2_OSC_Enum
-_lv2_osc_stream_run_ser(LV2_OSC_Stream *stream)
-{
- LV2_OSC_Enum ev = LV2_OSC_NONE;
-
- // send everything
- {
- const int fd = stream->sock;
-
- if(fd >= 0)
- {
- const uint8_t *buf;
- size_t tosend;
-
- while( (buf = stream->driv->read_req(stream->data, &tosend)) )
- {
- if(stream->slip) // SLIP framed
- {
- if(tosend <= sizeof(stream->tx_buf)) // check if there is enough memory
- {
- memcpy(stream->tx_buf, buf, tosend);
- tosend = lv2_osc_slip_encode_inline(stream->tx_buf, tosend);
- }
- else
- {
- tosend = 0;
- }
- }
- else // uint32_t prefix frames
- {
- const size_t nsize = tosend + sizeof(uint32_t);
-
- if(nsize <= sizeof(stream->tx_buf)) // check if there is enough memory
- {
- const uint32_t prefix = htonl(tosend);
-
- memcpy(stream->tx_buf, &prefix, sizeof(uint32_t));
- memcpy(stream->tx_buf + sizeof(uint32_t), buf, tosend);
- tosend = nsize;
- }
- else
- {
- tosend = 0;
- }
- }
-
- const ssize_t sent = tosend
- ? write(fd, stream->tx_buf, tosend)
- : 0;
-
- if(sent == -1)
- {
- if( (errno == EAGAIN) || (errno == EWOULDBLOCK) )
- {
- // empty queue
- break;
- }
-
- ev = LV2_OSC_STREAM_ERRNO(ev, errno);
- break;
- }
- else if(sent != (ssize_t)tosend)
- {
- ev = LV2_OSC_STREAM_ERRNO(ev, EIO);
- break;
- }
-
- stream->driv->read_adv(stream->data);
- ev |= LV2_OSC_SEND;
- }
- }
- }
-
- // recv everything
- {
- const int fd = stream->sock;
-
- if(fd >= 0)
- {
- if(stream->slip) // SLIP framed
- {
- while(true)
- {
- ssize_t recvd = read(fd, stream->rx_buf + stream->rx_off,
- sizeof(stream->rx_buf) - stream->rx_off);
-
- if(recvd == -1)
- {
- if( (errno == EAGAIN) || (errno == EWOULDBLOCK) )
- {
- // empty queue
- break;
- }
-
- stream->connected = false;
- ev = LV2_OSC_STREAM_ERRNO(ev, errno);
- break;
- }
- else if(recvd == 0)
- {
- // orderly shutdown
- break;
- }
-
- uint8_t *ptr = stream->rx_buf;
- recvd += stream->rx_off;
-
- while(recvd > 0)
- {
- size_t size;
- size_t parsed = lv2_osc_slip_decode_inline(ptr, recvd, &size);
-
- if(size) // dispatch
- {
- uint8_t *buf;
-
- if( (buf = stream->driv->write_req(stream->data, size, NULL)) )
- {
- memcpy(buf, ptr, size);
-
- stream->driv->write_adv(stream->data, size);
- ev |= LV2_OSC_RECV;
- }
- else
- {
- parsed = 0;
- ev = LV2_OSC_STREAM_ERRNO(ev, ENOMEM);
- }
- }
-
- if(parsed)
- {
- ptr += parsed;
- recvd -= parsed;
- }
- else
- {
- break;
- }
- }
-
- if(recvd > 0) // is there remaining chunk for next call?
- {
- memmove(stream->rx_buf, ptr, recvd);
- stream->rx_off = recvd;
- }
- else
- {
- stream->rx_off = 0;
- }
-
- break;
- }
- }
- else // uint32_t prefix frames
- {
- uint8_t *buf;
-
- while( (buf = stream->driv->write_req(stream->data,
- LV2_OSC_STREAM_REQBUF, NULL)) )
- {
- uint32_t prefix;
-
- ssize_t recvd = read(fd, &prefix, sizeof(uint32_t));
- if(recvd == sizeof(uint32_t))
- {
- prefix = ntohl(prefix); //FIXME check prefix <= max_len
- recvd = read(fd, buf, prefix);
- }
- else if(recvd == -1)
- {
- if( (errno == EAGAIN) || (errno == EWOULDBLOCK) )
- {
- // empty queue
- break;
- }
-
- stream->connected = false;
- ev = LV2_OSC_STREAM_ERRNO(ev, errno);
- break;
- }
- else if(recvd == 0)
- {
- // orderly shutdown
- break;
- }
-
- stream->driv->write_adv(stream->data, recvd);
- ev |= LV2_OSC_RECV;
- }
- }
- }
- }
-
- if(stream->connected)
- {
- ev |= LV2_OSC_CONN;
- }
-
- return ev;
-}
-
-static inline LV2_OSC_Enum
-lv2_osc_stream_run(LV2_OSC_Stream *stream)
-{
- LV2_OSC_Enum ev = LV2_OSC_NONE;
-
- switch(stream->socket_type)
- {
- case SOCK_DGRAM:
- {
- ev |= _lv2_osc_stream_run_udp(stream);
- } break;
- case SOCK_STREAM:
- {
- ev |= _lv2_osc_stream_run_tcp(stream);
- } break;
- default:
- {
- ev |= _lv2_osc_stream_run_ser(stream);
- } break;
- }
-
- return ev;
-}
-
-static inline 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 inline 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
-
-#endif // LV2_OSC_STREAM_H
D osc.lv2/osc.lv2/util.h => osc.lv2/osc.lv2/util.h +0 -631
@@ 1,631 0,0 @@
-/*
- * Copyright (c) 2015-2016 Hanspeter Portner (dev@open-music-kontrollers.ch)
- *
- * This is free software: you can redistribute it and/or modify
- * it under the terms of the Artistic License 2.0 as published by
- * The Perl Foundation.
- *
- * This source 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
- * Artistic License 2.0 for more details.
- *
- * You should have received a copy of the Artistic License 2.0
- * along the source as a COPYING file. If not, obtain it from
- * http://www.perlfoundation.org/artistic_license_2_0.
- */
-
-#ifndef LV2_OSC_UTIL_H
-#define LV2_OSC_UTIL_H
-
-#include <assert.h>
-#include <ctype.h>
-#include <inttypes.h>
-#include <stdio.h>
-#include <stdlib.h>
-#if !defined(_WIN32)
-# include <fnmatch.h>
-#endif
-
-#include <osc.lv2/osc.h>
-
-#include <lv2/lv2plug.in/ns/ext/atom/util.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#ifndef __unused
-# define __unused __attribute__((unused))
-#endif
-
-#undef LV2_ATOM_TUPLE_FOREACH // there is a bug in LV2 1.10.0
-#define LV2_ATOM_TUPLE_FOREACH(tuple, iter) \
- for (LV2_Atom* (iter) = lv2_atom_tuple_begin(tuple); \
- !lv2_atom_tuple_is_end(LV2_ATOM_BODY(tuple), (tuple)->atom.size, (iter)); \
- (iter) = lv2_atom_tuple_next(iter))
-
-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 [] = {
- ' ', '#',
- '\0'
-};
-
-// allowed characters in OSC format string
-static const char valid_format_chars [] = {
- LV2_OSC_INT32, LV2_OSC_FLOAT, LV2_OSC_STRING, LV2_OSC_BLOB,
- LV2_OSC_TRUE, LV2_OSC_FALSE, LV2_OSC_NIL, LV2_OSC_IMPULSE,
- LV2_OSC_INT64, LV2_OSC_DOUBLE, LV2_OSC_TIMETAG,
- LV2_OSC_SYMBOL, LV2_OSC_MIDI,
- '\0'
-};
-
-static inline 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 inline 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 inline 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
-*/
-static inline bool
-lv2_osc_check_path(const char *path)
-{
- assert(path);
-
- if(path[0] != '/')
- return false;
-
- for(const char *ptr=path+1; *ptr!='\0'; ptr++)
- if( (isprint(*ptr) == 0) || (strchr(invalid_path_chars, *ptr) != NULL) )
- return false;
-
- return true;
-}
-
-/**
- TODO
-*/
-static inline bool
-lv2_osc_check_fmt(const char *format, int offset)
-{
- assert(format);
-
- if(offset && (format[0] != ',') )
- return false;
-
- for(const char *ptr=format+offset; *ptr!='\0'; ptr++)
- if(strchr(valid_format_chars, *ptr) == NULL)
- return false;
-
- return true;
-}
-
-/**
- TODO
-*/
-static inline uint64_t
-lv2_osc_timetag_parse(const LV2_OSC_Timetag *timetag)
-{
- return ((uint64_t)timetag->integral << 32) | timetag->fraction;
-}
-
-/**
- TODO
-*/
-static inline LV2_OSC_Timetag *
-lv2_osc_timetag_create(LV2_OSC_Timetag *timetag, uint64_t tt)
-{
- timetag->integral = tt >> 32;
- timetag->fraction = tt & 0xffffffff;
-
- return timetag;
-}
-
-#define LV2_OSC_TIMETAG_CREATE(tt) \
- lv2_osc_timetag_create(&(LV2_OSC_Timetag){.integral = 0, .fraction = 0}, (tt))
-
-/**
- TODO
-*/
-static inline bool
-lv2_osc_is_packet_type(LV2_OSC_URID *osc_urid, LV2_URID type)
-{
- return type == osc_urid->OSC_Packet;
-}
-
-/**
- TODO
-*/
-static inline bool
-lv2_osc_is_bundle_type(LV2_OSC_URID *osc_urid, LV2_URID type)
-{
- return type == osc_urid->OSC_Bundle;
-}
-
-/**
- TODO
-*/
-static inline bool
-lv2_osc_is_message_type(LV2_OSC_URID *osc_urid, LV2_URID type)
-{
- return type == osc_urid->OSC_Message;
-}
-
-/**
- TODO
-*/
-static inline bool
-lv2_osc_is_message_or_bundle_type(LV2_OSC_URID *osc_urid, LV2_URID type)
-{
- return lv2_osc_is_message_type(osc_urid, type)
- || lv2_osc_is_bundle_type(osc_urid, type);
-}
-
-static inline LV2_OSC_Type
-lv2_osc_argument_type(LV2_OSC_URID *osc_urid, const LV2_Atom *atom)
-{
- const LV2_Atom_Object *obj = (const LV2_Atom_Object *)atom;
-
- if(atom->type == osc_urid->ATOM_Int)
- return LV2_OSC_INT32;
- else if(atom->type == osc_urid->ATOM_Float)
- return LV2_OSC_FLOAT;
- else if(atom->type == osc_urid->ATOM_String)
- return LV2_OSC_STRING;
- else if(atom->type == osc_urid->ATOM_Chunk)
- return LV2_OSC_BLOB;
-
- else if(atom->type == osc_urid->ATOM_Long)
- return LV2_OSC_INT64;
- else if(atom->type == osc_urid->ATOM_Double)
- return LV2_OSC_DOUBLE;
- else if( (atom->type == osc_urid->ATOM_Object) && (obj->body.otype == osc_urid->OSC_Timetag) )
- return LV2_OSC_TIMETAG;
-
- else if(atom->type == osc_urid->ATOM_Bool)
- {
- if(((const LV2_Atom_Bool *)atom)->body)
- return LV2_OSC_TRUE;
- else
- return LV2_OSC_FALSE;
- }
- else if(atom->type == osc_urid->ATOM_Literal)
- {
- const LV2_Atom_Literal *lit = (const LV2_Atom_Literal *)atom;
- if(lit->body.datatype == osc_urid->OSC_Nil)
- return LV2_OSC_NIL;
- else if(lit->body.datatype == osc_urid->OSC_Impulse)
- return LV2_OSC_IMPULSE;
- else if(lit->body.datatype == osc_urid->OSC_Char)
- return LV2_OSC_CHAR;
- else if(lit->body.datatype == osc_urid->OSC_RGBA)
- return LV2_OSC_RGBA;
- }
-
- else if(atom->type == osc_urid->ATOM_URID)
- return LV2_OSC_SYMBOL;
- else if(atom->type == osc_urid->MIDI_MidiEvent)
- return LV2_OSC_MIDI;
-
- return '\0';
-}
-
-static inline const LV2_Atom *
-lv2_osc_int32_get(LV2_OSC_URID *osc_urid __unused, const LV2_Atom *atom,
- int32_t *i)
-{
- assert(i);
- *i = ((const LV2_Atom_Int *)atom)->body;
-
- return lv2_atom_tuple_next(atom);
-}
-
-static inline const LV2_Atom *
-lv2_osc_float_get(LV2_OSC_URID *osc_urid __unused, const LV2_Atom *atom,
- float *f)
-{
- assert(f);
- *f = ((const LV2_Atom_Float *)atom)->body;
-
- return lv2_atom_tuple_next(atom);
-}
-
-static inline const LV2_Atom *
-lv2_osc_string_get(LV2_OSC_URID *osc_urid __unused, const LV2_Atom *atom,
- const char **s)
-{
- assert(s);
- *s = LV2_ATOM_BODY_CONST(atom);
-
- return lv2_atom_tuple_next(atom);
-}
-
-static inline const LV2_Atom *
-lv2_osc_blob_get(LV2_OSC_URID *osc_urid __unused, const LV2_Atom *atom,
- uint32_t *size, const uint8_t **b)
-{
- assert(size && b);
- *size = atom->size;
- *b = LV2_ATOM_BODY_CONST(atom);
-
- return lv2_atom_tuple_next(atom);
-}
-
-static inline const LV2_Atom *
-lv2_osc_int64_get(LV2_OSC_URID *osc_urid __unused, const LV2_Atom *atom,
- int64_t *h)
-{
- assert(h);
- *h = ((const LV2_Atom_Long *)atom)->body;
-
- return lv2_atom_tuple_next(atom);
-}
-
-static inline const LV2_Atom *
-lv2_osc_double_get(LV2_OSC_URID *osc_urid __unused, const LV2_Atom *atom,
- double *d)
-{
- assert(d);
- *d = ((const LV2_Atom_Double *)atom)->body;
-
- return lv2_atom_tuple_next(atom);
-}
-
-static inline const LV2_Atom *
-lv2_osc_timetag_get(LV2_OSC_URID *osc_urid, const LV2_Atom *atom,
- LV2_OSC_Timetag *timetag)
-{
- assert(timetag);
-
- const LV2_Atom_Long *integral = NULL;
- const LV2_Atom_Long *fraction = NULL;
-
- lv2_atom_object_get((const LV2_Atom_Object *)atom,
- osc_urid->OSC_timetagIntegral, &integral,
- osc_urid->OSC_timetagFraction, &fraction,
- 0);
-
- if( integral && (integral->atom.type == osc_urid->ATOM_Long)
- && fraction && (fraction->atom.type == osc_urid->ATOM_Long) )
- {
- timetag->integral = integral->body;
- timetag->fraction = fraction->body;
- }
- else
- {
- // set to immediate
- timetag->integral = 0;
- timetag->fraction = 1;
- }
-
- return lv2_atom_tuple_next(atom);
-}
-
-static inline const LV2_Atom *
-lv2_osc_true_get(LV2_OSC_URID *osc_urid __unused, const LV2_Atom *atom)
-{
- return lv2_atom_tuple_next(atom);
-}
-
-static inline const LV2_Atom *
-lv2_osc_false_get(LV2_OSC_URID *osc_urid __unused, const LV2_Atom *atom)
-{
- return lv2_atom_tuple_next(atom);
-}
-
-static inline const LV2_Atom *
-lv2_osc_nil_get(LV2_OSC_URID *osc_urid __unused, const LV2_Atom *atom)
-{
- return lv2_atom_tuple_next(atom);
-}
-
-static inline const LV2_Atom *
-lv2_osc_impulse_get(LV2_OSC_URID *osc_urid __unused, const LV2_Atom *atom)
-{
- return lv2_atom_tuple_next(atom);
-}
-
-static inline const LV2_Atom *
-lv2_osc_symbol_get(LV2_OSC_URID *osc_urid __unused, const LV2_Atom *atom,
- LV2_URID *S)
-{
- assert(S);
- *S = ((const LV2_Atom_URID *)atom)->body;
-
- return lv2_atom_tuple_next(atom);
-}
-
-static inline const LV2_Atom *
-lv2_osc_midi_get(LV2_OSC_URID *osc_urid __unused, const LV2_Atom *atom,
- uint32_t *size, const uint8_t **m)
-{
- assert(size && m);
- *size = atom->size;
- *m = LV2_ATOM_BODY_CONST(atom);
-
- return lv2_atom_tuple_next(atom);
-}
-
-static inline const LV2_Atom *
-lv2_osc_char_get(LV2_OSC_URID *osc_urid __unused, const LV2_Atom *atom, char *c)
-{
- assert(c);
- const char *str = LV2_ATOM_CONTENTS_CONST(LV2_Atom_Literal, atom);
- *c = str[0];
-
- return lv2_atom_tuple_next(atom);
-}
-
-static inline const LV2_Atom *
-lv2_osc_rgba_get(LV2_OSC_URID *osc_urid __unused, const LV2_Atom *atom,
- uint8_t *r, uint8_t *g, uint8_t *b, uint8_t *a)
-{
- assert(r && g && b && a);
- const char *str = LV2_ATOM_CONTENTS_CONST(LV2_Atom_Literal, atom);
-
- uint8_t *key [4] = {
- r, g, b, a
- };
-
- const char *pos = str;
- char *endptr;
-
- for(unsigned count = 0; count < 4; count++, pos += 2)
- {
- char buf [5] = {'0', 'x', pos[0], pos[1], '\0'};
-
- *key[count] = strtol(buf, &endptr, 16);
- }
-
- return lv2_atom_tuple_next(atom);
-}
-
-/**
- TODO
-*/
-static inline bool
-lv2_osc_bundle_body_get(LV2_OSC_URID *osc_urid, uint32_t size, const LV2_Atom_Object_Body *body,
- const LV2_Atom_Object **timetag, const LV2_Atom_Tuple **items)
-{
- assert(timetag && items);
-
- *timetag = NULL;
- *items = NULL;
-
- lv2_atom_object_body_get(size, body,
- osc_urid->OSC_bundleTimetag, timetag,
- osc_urid->OSC_bundleItems, items,
- 0);
-
- if(!*timetag || ((*timetag)->atom.type != osc_urid->ATOM_Object) || ((*timetag)->body.otype != osc_urid->OSC_Timetag))
- return false;
- if(!*items || ((*items)->atom.type != osc_urid->ATOM_Tuple))
- return false;
-
- return true;
-}
-
-/**
- TODO
-*/
-static inline bool
-lv2_osc_bundle_get(LV2_OSC_URID *osc_urid, const LV2_Atom_Object *obj,
- const LV2_Atom_Object **timetag, const LV2_Atom_Tuple **items)
-{
- return lv2_osc_bundle_body_get(osc_urid, obj->atom.size, &obj->body,
- timetag, items);
-}
-
-/**
- TODO
-*/
-static inline bool
-lv2_osc_message_body_get(LV2_OSC_URID *osc_urid, uint32_t size, const LV2_Atom_Object_Body *body,
- const LV2_Atom_String **path, const LV2_Atom_Tuple **arguments)
-{
- assert(path && arguments);
-
- *path = NULL;
- *arguments = NULL;
-
- lv2_atom_object_body_get(size, body,
- osc_urid->OSC_messagePath, path,
- osc_urid->OSC_messageArguments, arguments,
- 0);
-
- if(!*path || ((*path)->atom.type != osc_urid->ATOM_String))
- return false;
- // message without arguments is valid
- if( *arguments && ((*arguments)->atom.type != osc_urid->ATOM_Tuple))
- return false;
-
- return true;
-}
-
-/**
- TODO
-*/
-static inline bool
-lv2_osc_message_get(LV2_OSC_URID *osc_urid, const LV2_Atom_Object *obj,
- const LV2_Atom_String **path, const LV2_Atom_Tuple **arguments)
-{
- return lv2_osc_message_body_get(osc_urid, obj->atom.size, &obj->body,
- path, arguments);
-}
-
-static inline bool
-lv2_osc_body_unroll(LV2_OSC_URID *osc_urid, uint32_t size, const LV2_Atom_Object_Body *body,
- LV2_OSC_Method method, void *data)
-{
- if(body->otype == osc_urid->OSC_Bundle)
- {
- const LV2_Atom_Object *timetag = NULL;
- const LV2_Atom_Tuple *items = NULL;
-
- if(!lv2_osc_bundle_body_get(osc_urid, size, body, &timetag, &items))
- return false;
-
- LV2_OSC_Timetag tt;
- lv2_osc_timetag_get(osc_urid, &timetag->atom, &tt);
-
- LV2_ATOM_TUPLE_FOREACH(items, atom)
- {
- const LV2_Atom_Object *obj= (const LV2_Atom_Object *)atom;
-
- if(!lv2_osc_body_unroll(osc_urid, obj->atom.size, &obj->body, method, data))
- return false;
- }
-
- return true;
- }
- else if(body->otype == osc_urid->OSC_Message)
- {
- const LV2_Atom_String *path = NULL;
- const LV2_Atom_Tuple *arguments = NULL;
-
- if(!lv2_osc_message_body_get(osc_urid, size, body, &path, &arguments))
- return false;
-
- if(method)
- method(LV2_ATOM_BODY_CONST(path), arguments, data);
-
- return true;
- }
-
- return false;
-}
-
-static inline bool
-lv2_osc_unroll(LV2_OSC_URID *osc_urid, const LV2_Atom_Object *obj,
- LV2_OSC_Method method, void *data)
-{
- return lv2_osc_body_unroll(osc_urid, obj->atom.size, &obj->body, method, data);
-}
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
-
-#endif // LV2_OSC_UTIL_H
D osc.lv2/osc.lv2/writer.h => osc.lv2/osc.lv2/writer.h +0 -579
@@ 1,579 0,0 @@
-/*
- * Copyright (c) 2015-2016 Hanspeter Portner (dev@open-music-kontrollers.ch)
- *
- * This is free software: you can redistribute it and/or modify
- * it under the terms of the Artistic License 2.0 as published by
- * The Perl Foundation.
- *
- * This source 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
- * Artistic License 2.0 for more details.
- *
- * You should have received a copy of the Artistic License 2.0
- * along the source as a COPYING file. If not, obtain it from
- * http://www.perlfoundation.org/artistic_license_2_0.
- */
-
-#ifndef LV2_OSC_WRITER_H
-#define LV2_OSC_WRITER_H
-
-#include <stdbool.h>
-#include <string.h>
-
-#include <osc.lv2/osc.h>
-#include <osc.lv2/util.h>
-#include <osc.lv2/endian.h>
-
-#include <lv2/lv2plug.in/ns/ext/atom/util.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#undef LV2_ATOM_TUPLE_FOREACH // there is a bug in LV2 1.10.0
-#define LV2_ATOM_TUPLE_FOREACH(tuple, iter) \
- for (LV2_Atom* (iter) = lv2_atom_tuple_begin(tuple); \
- !lv2_atom_tuple_is_end(LV2_ATOM_BODY(tuple), (tuple)->atom.size, (iter)); \
- (iter) = lv2_atom_tuple_next(iter))
-
-typedef struct _LV2_OSC_Writer LV2_OSC_Writer;
-typedef struct _LV2_OSC_Writer_Frame LV2_OSC_Writer_Frame;
-
-struct _LV2_OSC_Writer {
- uint8_t *buf;
- uint8_t *ptr;
- const uint8_t *end;
-};
-
-struct _LV2_OSC_Writer_Frame {
- uint8_t *ref;
-};
-
-static inline void
-lv2_osc_writer_initialize(LV2_OSC_Writer *writer, uint8_t *buf, size_t size)
-{
- writer->buf = buf;
- writer->ptr = buf;
- writer->end = buf + size;
-}
-
-static inline size_t
-lv2_osc_writer_get_size(LV2_OSC_Writer *writer)
-{
- if(writer->ptr > writer->buf)
- return writer->ptr - writer->buf;
-
- return 0;
-}
-
-static inline uint8_t *
-lv2_osc_writer_finalize(LV2_OSC_Writer *writer, size_t *size)
-{
- *size = lv2_osc_writer_get_size(writer);
-
- if(*size)
- return writer->buf;
-
- return NULL;
-}
-
-static inline bool
-lv2_osc_writer_overflow(LV2_OSC_Writer *writer, size_t size)
-{
- return writer->ptr + size >= writer->end;
-}
-
-static inline bool
-lv2_osc_writer_htobe32(LV2_OSC_Writer *writer, union swap32_t *s32)
-{
- if(lv2_osc_writer_overflow(writer, 4))
- return false;
-
- s32->u = htobe32(s32->u);
- *(uint32_t *)writer->ptr = s32->u;
- writer->ptr += 4;
-
- return true;
-}
-
-static inline bool
-lv2_osc_writer_htobe64(LV2_OSC_Writer *writer, union swap64_t *s64)
-{
- if(lv2_osc_writer_overflow(writer, 8))
- return false;
-
- s64->u = htobe64(s64->u);
- *(uint64_t *)writer->ptr = s64->u;
- writer->ptr += 8;
-
- return true;
-}
-
-static inline bool
-lv2_osc_writer_add_int32(LV2_OSC_Writer *writer, int32_t i)
-{
- return lv2_osc_writer_htobe32(writer, &(union swap32_t){ .i = i });
-}
-
-static inline bool
-lv2_osc_writer_add_float(LV2_OSC_Writer *writer, float f)
-{
- return lv2_osc_writer_htobe32(writer, &(union swap32_t){ .f = f });
-}
-
-static inline bool
-lv2_osc_writer_add_string(LV2_OSC_Writer *writer, const char *s)
-{
- const size_t rawlen = strlen(s) + 1;
- const size_t padded = LV2_OSC_PADDED_SIZE(rawlen);
- if(lv2_osc_writer_overflow(writer, padded))
- return false;
-
- const uint32_t blank = 0;
- memcpy(writer->ptr + padded - sizeof(uint32_t), &blank, sizeof(uint32_t));
- memcpy(writer->ptr, s, rawlen);
- writer->ptr += padded;
-
- return true;
-}
-
-static inline bool
-lv2_osc_writer_add_symbol(LV2_OSC_Writer *writer, const char *S)
-{
- return lv2_osc_writer_add_string(writer, S);
-}
-
-static inline bool
-lv2_osc_writer_add_int64(LV2_OSC_Writer *writer, int64_t h)
-{
- return lv2_osc_writer_htobe64(writer, &(union swap64_t){ .h = h });
-}
-
-static inline bool
-lv2_osc_writer_add_double(LV2_OSC_Writer *writer, double d)
-{
- return lv2_osc_writer_htobe64(writer, &(union swap64_t){ .d = d });
-}
-
-static inline bool
-lv2_osc_writer_add_timetag(LV2_OSC_Writer *writer, uint64_t u)
-{
- return lv2_osc_writer_htobe64(writer, &(union swap64_t){ .u = u });
-}
-
-static inline bool
-lv2_osc_writer_add_blob_inline(LV2_OSC_Writer *writer, int32_t len, uint8_t **body)
-{
- const size_t len_padded = LV2_OSC_PADDED_SIZE(len);
- const size_t size = 4 + len_padded;
- if(lv2_osc_writer_overflow(writer, size))
- return false;
-
- if(!lv2_osc_writer_add_int32(writer, len))
- return false;
-
- *body = writer->ptr;
- //memset(&writer->ptr[len], 0x0, len_padded - len);
- writer->ptr += len_padded;
-
- return true;
-}
-
-static inline bool
-lv2_osc_writer_add_blob(LV2_OSC_Writer *writer, int32_t len, const uint8_t *body)
-{
- uint8_t *dst;
- if(!lv2_osc_writer_add_blob_inline(writer, len, &dst))
- return false;
-
- memcpy(dst, body, len);
-
- return true;
-}
-
-static inline bool
-lv2_osc_writer_add_midi_inline(LV2_OSC_Writer *writer, int32_t len, uint8_t **m)
-{
- if( (len > 4) || lv2_osc_writer_overflow(writer, 4))
- return false;
-
- *m = writer->ptr;
- //memset(&writer->ptr[len], 0x0, 4 - len);
- writer->ptr += 4;
-
- return true;
-}
-
-static inline bool
-lv2_osc_writer_add_midi(LV2_OSC_Writer *writer, int32_t len, const uint8_t *m)
-{
- uint8_t *dst;
- if(!lv2_osc_writer_add_midi_inline(writer, len, &dst))
- return false;
-
- memcpy(dst, m, len);
-
- return true;
-}
-
-static inline bool
-lv2_osc_writer_add_rgba(LV2_OSC_Writer *writer, uint8_t r, uint8_t g, uint8_t b, uint8_t a)
-{
- if(lv2_osc_writer_overflow(writer, 4))
- return false;
-
- writer->ptr[0] = r;
- writer->ptr[1] = g;
- writer->ptr[2] = b;
- writer->ptr[3] = a;
- writer->ptr += 4;
-
- return true;
-}
-
-static inline bool
-lv2_osc_writer_add_char(LV2_OSC_Writer *writer, char c)
-{
- return lv2_osc_writer_add_int32(writer, (int32_t)c);
-}
-
-static inline bool
-lv2_osc_writer_push_bundle(LV2_OSC_Writer *writer, LV2_OSC_Writer_Frame *frame, uint64_t t)
-{
- if(lv2_osc_writer_overflow(writer, 16))
- return false;
-
- frame->ref = writer->ptr;
-
- strncpy((char *)writer->ptr, "#bundle", 8);
- writer->ptr += 8;
-
- return lv2_osc_writer_add_timetag(writer, t);
-}
-
-static inline bool
-lv2_osc_writer_pop_bundle(LV2_OSC_Writer *writer, LV2_OSC_Writer_Frame *frame)
-{
- union swap32_t s32 = { .i = writer->ptr - frame->ref - 16};
-
- if(s32.i <= 0)
- {
- writer->ptr = frame->ref;
- return false;
- }
-
- return true;
-}
-
-static inline bool
-lv2_osc_writer_push_item(LV2_OSC_Writer *writer, LV2_OSC_Writer_Frame *frame)
-{
- if(lv2_osc_writer_overflow(writer, 4))
- return false;
-
- frame->ref = writer->ptr;
- writer->ptr += 4;
-
- return true;
-}
-
-static inline bool
-lv2_osc_writer_pop_item(LV2_OSC_Writer *writer, LV2_OSC_Writer_Frame *frame)
-{
- union swap32_t s32 = { .i = writer->ptr - frame->ref - 4};
-
- if(s32.i <= 0)
- {
- writer->ptr = frame->ref;
- return false;
- }
-
- s32.u = htobe32(s32.u);
- *(uint32_t *)frame->ref = s32.u;
-
- return true;
-}
-
-static inline bool
-lv2_osc_writer_add_path(LV2_OSC_Writer *writer, const char *path)
-{
- return lv2_osc_writer_add_string(writer, path);
-}
-
-static inline bool
-lv2_osc_writer_add_format(LV2_OSC_Writer *writer, const char *fmt)
-{
- const size_t rawlen = strlen(fmt) + 1;
- const size_t padded = LV2_OSC_PADDED_SIZE(rawlen + 1);
- if(lv2_osc_writer_overflow(writer, padded))
- return false;
-
- const uint32_t blank = 0;
- memcpy(writer->ptr + padded - sizeof(uint32_t), &blank, sizeof(uint32_t));
- *writer->ptr++ = ',';
- memcpy(writer->ptr, fmt, rawlen);
- writer->ptr += padded - 1;
-
- return true;
-}
-
-static inline bool
-lv2_osc_writer_arg_varlist(LV2_OSC_Writer *writer, const char *fmt, va_list args)
-{
- for(const char *type = fmt; *type; type++)
- {
- switch( (LV2_OSC_Type)*type)
- {
- case LV2_OSC_INT32:
- if(!lv2_osc_writer_add_int32(writer, va_arg(args, int32_t)))
- return false;
- break;
- case LV2_OSC_FLOAT:
- if(!lv2_osc_writer_add_float(writer, (float)va_arg(args, double)))
- return false;
- break;
- case LV2_OSC_STRING:
- if(!lv2_osc_writer_add_string(writer, va_arg(args, const char *)))
- return false;
- break;
- case LV2_OSC_BLOB:
- {
- const int32_t len = va_arg(args, int32_t);
- if(!lv2_osc_writer_add_blob(writer, len, va_arg(args, const uint8_t *)))
- return false;
- } break;
-
- case LV2_OSC_TRUE:
- case LV2_OSC_FALSE:
- case LV2_OSC_NIL:
- case LV2_OSC_IMPULSE:
- break;
-
- case LV2_OSC_INT64:
- if(!lv2_osc_writer_add_int64(writer, va_arg(args, int64_t)))
- return false;
- break;
- case LV2_OSC_DOUBLE:
- if(!lv2_osc_writer_add_double(writer, va_arg(args, double)))
- return false;
- break;
- case LV2_OSC_TIMETAG:
- if(!lv2_osc_writer_add_timetag(writer, va_arg(args, uint64_t)))
- return false;
- break;
-
- case LV2_OSC_MIDI:
- {
- const int32_t len = va_arg(args, int32_t);
- if(!lv2_osc_writer_add_midi(writer, len, va_arg(args, const uint8_t *)))
- return false;
- } break;
- case LV2_OSC_SYMBOL:
- if(!lv2_osc_writer_add_symbol(writer, va_arg(args, const char *)))
- return false;
- break;
- case LV2_OSC_CHAR:
- if(!lv2_osc_writer_add_char(writer, va_arg(args, int)))
- return false;
- break;
- case LV2_OSC_RGBA:
- {
- const uint8_t r = va_arg(args, unsigned);
- const uint8_t g = va_arg(args, unsigned);
- const uint8_t b = va_arg(args, unsigned);
- const uint8_t a = va_arg(args, unsigned);
- if(!lv2_osc_writer_add_rgba(writer, r, g, b, a))
- return false;
- } break;
- }
- }
-
- return true;
-}
-
-static inline bool
-lv2_osc_writer_arg_vararg(LV2_OSC_Writer *writer, const char *fmt, ...)
-{
- va_list args;
- va_start(args, fmt);
-
- const bool res = lv2_osc_writer_arg_varlist(writer, fmt, args);
-
- va_end(args);
-
- return res;
-}
-
-static inline bool
-lv2_osc_writer_message_varlist(LV2_OSC_Writer *writer, const char *path, const char *fmt, va_list args)
-{
- if(!lv2_osc_writer_add_path(writer, path))
- return false;
-
- if(!lv2_osc_writer_add_format(writer, fmt))
- return false;
-
- return lv2_osc_writer_arg_varlist(writer, fmt, args);
-}
-
-static inline bool
-lv2_osc_writer_message_vararg(LV2_OSC_Writer *writer, const char *path, const char *fmt, ...)
-{
- va_list args;
- va_start(args, fmt);
-
- const bool res = lv2_osc_writer_message_varlist(writer, path, fmt, args);
-
- va_end(args);
-
- return res;
-}
-
-static inline bool
-lv2_osc_writer_packet(LV2_OSC_Writer *writer, LV2_OSC_URID *osc_urid,
- LV2_URID_Unmap *unmap, uint32_t size, const LV2_Atom_Object_Body *body)
-{
- if(body->otype == osc_urid->OSC_Bundle)
- {
- const LV2_Atom_Object *timetag = NULL;
- const LV2_Atom_Tuple *items = NULL;
-
- if(!lv2_osc_bundle_body_get(osc_urid, size, body, &timetag, &items))
- return false;
-
- LV2_OSC_Timetag tt;
- LV2_OSC_Writer_Frame bndl = { .ref = 0 };
-
- lv2_osc_timetag_get(osc_urid, &timetag->atom, &tt);
- if(!lv2_osc_writer_push_bundle(writer, &bndl, lv2_osc_timetag_parse(&tt)))
- return false;
-
- LV2_ATOM_TUPLE_FOREACH(items, atom)
- {
- const LV2_Atom_Object *obj= (const LV2_Atom_Object *)atom;
- LV2_OSC_Writer_Frame itm = { .ref = 0 };
-
- if( !lv2_osc_writer_push_item(writer, &itm)
- || !lv2_osc_writer_packet(writer, osc_urid, unmap, obj->atom.size, &obj->body)
- || !lv2_osc_writer_pop_item(writer, &itm) )
- {
- return false;
- }
- }
-
- return lv2_osc_writer_pop_bundle(writer, &bndl);
- }
- else if(body->otype == osc_urid->OSC_Message)
- {
- const LV2_Atom_String *path = NULL;
- const LV2_Atom_Tuple *arguments = NULL;
-
- if(lv2_osc_message_body_get(osc_urid, size, body, &path, &arguments))
- {
- if(!lv2_osc_writer_add_path(writer, LV2_ATOM_BODY_CONST(path)))
- return false;
-
- char fmt [128]; //TODO how big?
- char *ptr = fmt;
- LV2_ATOM_TUPLE_FOREACH(arguments, atom)
- {
- *ptr++ = lv2_osc_argument_type(osc_urid, atom);
- }
- *ptr = '\0';
- if(!lv2_osc_writer_add_format(writer, fmt))
- return false;
-
- LV2_ATOM_TUPLE_FOREACH(arguments, atom)
- {
- const LV2_Atom_Object *obj= (const LV2_Atom_Object *)atom;
-
- if(atom->type == osc_urid->ATOM_Int)
- {
- if(!lv2_osc_writer_add_int32(writer, ((const LV2_Atom_Int *)atom)->body))
- return false;
- }
- else if(atom->type == osc_urid->ATOM_Float)
- {
- if(!lv2_osc_writer_add_float(writer, ((const LV2_Atom_Float *)atom)->body))
- return false;
- }
- else if(atom->type == osc_urid->ATOM_String)
- {
- if(!lv2_osc_writer_add_string(writer, LV2_ATOM_BODY_CONST(atom)))
- return false;
- }
- else if(atom->type == osc_urid->ATOM_Chunk)
- {
- if(!lv2_osc_writer_add_blob(writer, atom->size, LV2_ATOM_BODY_CONST(atom)))
- return false;
- }
-
- else if(atom->type == osc_urid->ATOM_Long)
- {
- if(!lv2_osc_writer_add_int64(writer, ((const LV2_Atom_Long *)atom)->body))
- return false;
- }
- else if(atom->type == osc_urid->ATOM_Double)
- {
- if(!lv2_osc_writer_add_double(writer, ((const LV2_Atom_Double *)atom)->body))
- return false;
- }
- else if( (atom->type == osc_urid->ATOM_Object) && (obj->body.otype == osc_urid->OSC_Timetag) )
- {
- LV2_OSC_Timetag tt;
- lv2_osc_timetag_get(osc_urid, &obj->atom, &tt);
- if(!lv2_osc_writer_add_timetag(writer, lv2_osc_timetag_parse(&tt)))
- return false;
- }
-
- // there is nothing to do for: true, false, nil, impulse
-
- else if(atom->type == osc_urid->ATOM_URID)
- {
- const char *symbol = unmap->unmap(unmap->handle, ((const LV2_Atom_URID *)atom)->body);
- if(!symbol || !lv2_osc_writer_add_symbol(writer, symbol))
- return false;
- }
- else if(atom->type == osc_urid->MIDI_MidiEvent)
- {
- uint8_t *m = NULL;
- if(!lv2_osc_writer_add_midi_inline(writer, atom->size + 1, &m))
- return false;
- m[0] = 0x0; // port
- memcpy(&m[1], LV2_ATOM_BODY_CONST(atom), atom->size);
- }
- else if(atom->type == osc_urid->ATOM_Literal)
- {
- const LV2_Atom_Literal *lit = (LV2_Atom_Literal *)atom;
-
- if(lit->body.datatype == osc_urid->OSC_Char)
- {
- const char c = *(const char *)LV2_ATOM_CONTENTS_CONST(LV2_Atom_Literal, lit);
- if(!lv2_osc_writer_add_char(writer, c))
- return false;
- }
- else if(lit->body.datatype == osc_urid->OSC_RGBA)
- {
- const char *rgba = LV2_ATOM_CONTENTS_CONST(LV2_Atom_Literal, atom);
- uint8_t r, g, b, a;
- if(sscanf(rgba, "%02"SCNx8"%02"SCNx8"%02"SCNx8"%02"SCNx8, &r, &g, &b, &a) != 4)
- return false;
- if(!lv2_osc_writer_add_rgba(writer, r, g, b, a))
- return false;
- }
- }
- }
- }
-
- return true;
- }
-
- return false;
-}
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
-
-#endif // LV2_OSC_WRITER_H
D osc.lv2/osc.ttl => osc.lv2/osc.ttl +0 -42
@@ 1,42 0,0 @@
-# Copyright (c) 2015-2016 Hanspeter Portner (dev@open-music-kontrollers.ch)
-#
-# This is free software: you can redistribute it and/or modify
-# it under the terms of the Artistic License 2.0 as published by
-# The Perl Foundation.
-#
-# This source 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
-# Artistic License 2.0 for more details.
-#
-# You should have received a copy of the Artistic License 2.0
-# along the source as a COPYING file. If not, obtain it from
-# http://www.perlfoundation.org/artistic_license_2_0.
-
-@prefix owl: <http://www.w3.org/2002/07/owl#> .
-@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
-@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
-@prefix lv2: <http://lv2plug.in/ns/lv2core#> .
-@prefix atom: <http://lv2plug.in/ns/ext/atom#> .
-@prefix osc: <http://open-music-kontrollers.ch/lv2/osc#> .
-
-<http://open-music-kontrollers.ch/lv2/osc>
- a owl:Ontology ;
- rdfs:seeAlso <lv2_osc.h> ,
- <lv2-osc.doap.ttl> ;
- lv2:documentation """
- <p>This specification defines event data types for OSC bundles and message.
- To signal support for OSC events on an atom:AtomPort with an atom:bufferType
- of atom:Sequence, plugin authors should add atom:supports osc:Event to
- the plugin specification.</p>
- """ .
-
-osc:schedule
- a lv2:Feature .
-
-osc:Event
- a rdfs:Class ,
- rdfs:Datatype ;
- rdfs:subClassOf atom:Atom ;
- owl:onDatatype xsd:hexBinary ;
- rdfs:label "OSC Event (Bundle or Message)" .
D osc.lv2/test/osc_test.c => osc.lv2/test/osc_test.c +0 -1373
@@ 1,1373 0,0 @@
-#include <assert.h>
-#include <string.h>
-#include <stdio.h>
-#include <pthread.h>
-#include <time.h>
-
-#include <osc.lv2/osc.h>
-#include <osc.lv2/reader.h>
-#include <osc.lv2/writer.h>
-#include <osc.lv2/forge.h>
-#if !defined(_WIN32)
-# include <osc.lv2/stream.h>
-#endif
-
-#define BUF_SIZE 0x100000
-#define MAX_URIDS 512
-
-typedef void (*test_t)(LV2_OSC_Writer *writer);
-typedef struct _urid_t urid_t;
-typedef struct _app_t app_t;
-
-struct _urid_t {
- LV2_URID urid;
- char *uri;
-};
-
-struct _app_t {
- urid_t urids [MAX_URIDS];
- LV2_URID urid;
-};
-
-static app_t __app;
-static uint8_t buf0 [BUF_SIZE];
-static uint8_t buf1 [BUF_SIZE];
-static uint8_t buf2 [BUF_SIZE];
-static const LV2_Atom_Object *obj2= (const LV2_Atom_Object *)buf2;
-
-const uint8_t raw_0 [] = {
- '/', 0x0, 0x0, 0x0,
- ',', 0x0, 0x0, 0x0
-};
-
-const uint8_t raw_1 [] = {
- '/', 'p', 'i', 'n',
- 'g', 0x0, 0x0, 0x0,
- ',', 'i', 'f', 's',
- 0x0, 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0, 0xc,
- 0x40, 0x59, 0x99, 0x9a,
- 'w', 'o', 'r', 'l',
- 'd', 0x0, 0x0, 0x0
-};
-
-const uint8_t raw_2 [] = {
- '/', 'p', 'i', 'n',
- 'g', 0x0, 0x0, 0x0,
- ',', 'h', 'd', 'S',
- 0x0, 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0, 0xc,
- 0x40, 0x0b, 0x33, 0x33,
- 0x33, 0x33, 0x33, 0x33,
- 'h', 't', 't', 'p',
- ':', '/', '/', 'e',
- 'x', 'a', 'm', 'p',
- 'l', 'e', '.', 'c',
- 'o', 'm', 0x0, 0x0
-};
-
-const uint8_t raw_3 [] = {
- '/', 'p', 'i', 'n',
- 'g', 0x0, 0x0, 0x0,
- ',', 'T', 'F', 'N',
- 'I', 0x0, 0x0, 0x0
-};
-
-const uint8_t raw_4 [] = {
- '/', 'm', 'i', 'd',
- 'i', 0x0, 0x0, 0x0,
- ',', 'm', 0x0, 0x0,
- 0x0, 0x90, 24, 0x7f
-};
-
-const uint8_t raw_5 [] = {
- '/', 'b', 'l', 'o',
- 'b', 0x0, 0x0, 0x0,
- ',', 'b', 0x0, 0x0,
- 0x0, 0x0, 0x0, 0x6,
- 0x1, 0x2, 0x3, 0x4,
- 0x5, 0x6, 0x0, 0x0
-};
-
-const uint8_t raw_6 [] = {
- '#', 'b', 'u', 'n',
- 'd', 'l', 'e', 0x0,
- 0x0, 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0, 0x1,
-
- 0x0, 0x0, 0x0, 0x8,
- '/', 0x0, 0x0, 0x0,
- ',', 0x0, 0x0, 0x0
-};
-
-const uint8_t raw_7 [] = {
- '#', 'b', 'u', 'n',
- 'd', 'l', 'e', 0x0,
- 0x0, 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0, 0x1,
-
- 0x0, 0x0, 0x0, 0x1c,
- '#', 'b', 'u', 'n',
- 'd', 'l', 'e', 0x0,
- 0x0, 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0, 0x1,
-
- 0x0, 0x0, 0x0, 0x8,
- '/', 0x0, 0x0, 0x0,
- ',', 0x0, 0x0, 0x0,
-
- 0x0, 0x0, 0x0, 0x8,
- '/', 0x0, 0x0, 0x0,
- ',', 0x0, 0x0, 0x0
-};
-
-const uint8_t raw_8 [] = {
- '/', 'p', 'i', 'n',
- 'g', 0x0, 0x0, 0x0,
- ',', 't', 'c', 'r',
- 0x0, 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0, 0x1,
- 0x0, 0x0, 0x0, 'o',
- 0x1, 0x2, 0x3, 0x4
-};
-
-static LV2_URID
-_map(LV2_URID_Map_Handle instance, const char *uri)
-{
- app_t *app = instance;
-
- urid_t *itm;
- for(itm=app->urids; itm->urid; itm++)
- {
- if(!strcmp(itm->uri, uri))
- return itm->urid;
- }
-
- assert(app->urid + 1 < MAX_URIDS);
-
- // create new
- itm->urid = ++app->urid;
- itm->uri = strdup(uri);
-
- return itm->urid;
-}
-
-static const char *
-_unmap(LV2_URID_Unmap_Handle instance, LV2_URID urid)
-{
- app_t *app = instance;
-
- urid_t *itm;
- for(itm=app->urids; itm->urid; itm++)
- {
- if(itm->urid == urid)
- return itm->uri;
- }
-
- // not found
- return NULL;
-}
-
-static LV2_URID_Map map = {
- .handle = &__app,
- .map = _map
-};
-
-static LV2_URID_Unmap unmap = {
- .handle = &__app,
- .unmap = _unmap
-};
-
-//#define DUMP
-#if defined(DUMP)
-static void
-_dump(const uint8_t *src, const uint8_t *dst, size_t size)
-{
- for(size_t i = 0; i < size; i++)
- printf("%zu %02x %02x\n", i, src[i], dst[i]);
- printf("\n");
-}
-#endif
-
-static void
-_clone(LV2_OSC_Reader *reader, LV2_OSC_Writer *writer, size_t size)
-{
- if(lv2_osc_reader_is_bundle(reader))
- {
- LV2_OSC_Item *itm = OSC_READER_BUNDLE_BEGIN(reader, size);
- assert(itm);
-
- LV2_OSC_Writer_Frame frame_bndl = { .ref = 0 };
- assert(lv2_osc_writer_push_bundle(writer, &frame_bndl, itm->timetag));
-
- OSC_READER_BUNDLE_ITERATE(reader, itm)
- {
- LV2_OSC_Reader reader2;
- lv2_osc_reader_initialize(&reader2, itm->body, itm->size);
-
- LV2_OSC_Writer_Frame frame_itm = { .ref = 0 };
- assert(lv2_osc_writer_push_item(writer, &frame_itm));
- _clone(&reader2, writer, itm->size);
- assert(lv2_osc_writer_pop_item(writer, &frame_itm));
- }
-
- assert(lv2_osc_writer_pop_bundle(writer, &frame_bndl));
- }
- else if(lv2_osc_reader_is_message(reader))
- {
- LV2_OSC_Arg *arg = OSC_READER_MESSAGE_BEGIN(reader, size);
- assert(arg);
-
- assert(lv2_osc_writer_add_path(writer, arg->path));
- assert(lv2_osc_writer_add_format(writer, arg->type));
-
- OSC_READER_MESSAGE_ITERATE(reader, arg)
- {
- switch((LV2_OSC_Type)*arg->type)
- {
- case LV2_OSC_INT32:
- assert(lv2_osc_writer_add_int32(writer, arg->i));
- break;
- case LV2_OSC_FLOAT:
- assert(lv2_osc_writer_add_float(writer, arg->f));
- break;
- case LV2_OSC_STRING:
- assert(lv2_osc_writer_add_string(writer, arg->s));
- break;
- case LV2_OSC_BLOB:
- assert(lv2_osc_writer_add_blob(writer, arg->size, arg->b));
- break;
-
- case LV2_OSC_INT64:
- assert(lv2_osc_writer_add_int64(writer, arg->h));
- break;
- case LV2_OSC_DOUBLE:
- assert(lv2_osc_writer_add_double(writer, arg->d));
- break;
- case LV2_OSC_TIMETAG:
- assert(lv2_osc_writer_add_timetag(writer, arg->t));
- break;
-
- case LV2_OSC_TRUE:
- case LV2_OSC_FALSE:
- case LV2_OSC_NIL:
- case LV2_OSC_IMPULSE:
- break;
-
- case LV2_OSC_MIDI:
- assert(lv2_osc_writer_add_midi(writer, arg->size, arg->m));
- break;
- case LV2_OSC_SYMBOL:
- assert(lv2_osc_writer_add_symbol(writer, arg->S));
- break;
- case LV2_OSC_CHAR:
- assert(lv2_osc_writer_add_char(writer, arg->c));
- break;
- case LV2_OSC_RGBA:
- assert(lv2_osc_writer_add_rgba(writer, arg->R, arg->G, arg->B, arg->A));
- break;
- }
- }
- }
-}
-
-static void
-_test_a(LV2_OSC_Writer *writer, const uint8_t *raw, size_t size)
-{
- LV2_OSC_URID osc_urid;
- lv2_osc_urid_init(&osc_urid, &map);
-
- // check writer against raw bytes
- size_t len;
- assert(lv2_osc_writer_finalize(writer, &len) == buf0);
- assert(len == size);
-#if defined(DUMP)
- if(memcmp(raw, buf0, size) != 0)
- _dump(raw, buf0, size);
-#endif
- assert(memcmp(raw, buf0, size) == 0);
-
- // check reader & writer
- LV2_OSC_Reader reader;
- lv2_osc_reader_initialize(&reader, buf0, size);
- lv2_osc_writer_initialize(writer, buf1, BUF_SIZE);
- _clone(&reader, writer, size);
-
- // check cloned against raw bytes
- assert(lv2_osc_writer_finalize(writer, &len) == buf1);
- assert(len == size);
-#if defined(DUMP)
- if(memcmp(raw, buf1, size) != 0)
- _dump(raw, buf1, size);
-#endif
- assert(memcmp(raw, buf1, size) == 0);
-
- // check forge
- LV2_Atom_Forge forge;
- lv2_atom_forge_init(&forge, &map);
- lv2_atom_forge_set_buffer(&forge, buf2, BUF_SIZE);
- assert(lv2_osc_forge_packet(&forge, &osc_urid, &map, buf0, size));
-
- // check deforge
- lv2_osc_writer_initialize(writer, buf1, BUF_SIZE);
- assert(lv2_osc_writer_packet(writer, &osc_urid, &unmap, obj2->atom.size, &obj2->body));
-
- // check deforged against raw bytes
- assert(lv2_osc_writer_finalize(writer, &len) == buf1);
- assert(len == size);
-#if defined(DUMP)
- if(memcmp(raw, buf1, size) != 0)
- _dump(raw, buf1, size);
-#endif
- assert(memcmp(raw, buf1, size) == 0);
-}
-
-static void
-test_0_a(LV2_OSC_Writer *writer)
-{
- assert(lv2_osc_writer_message_vararg(writer, "/", ""));
- _test_a(writer, raw_0, sizeof(raw_0));
-}
-
-static void
-test_1_a(LV2_OSC_Writer *writer)
-{
- assert(lv2_osc_writer_message_vararg(writer, "/ping", "ifs",
- 12, 3.4f, "world"));
- _test_a(writer, raw_1, sizeof(raw_1));
-}
-
-static void
-test_2_a(LV2_OSC_Writer *writer)
-{
- assert(lv2_osc_writer_message_vararg(writer, "/ping", "hdS",
- (int64_t)12, (double)3.4, "http://example.com"));
- _test_a(writer, raw_2, sizeof(raw_2));
-}
-
-static void
-test_3_a(LV2_OSC_Writer *writer)
-{
- assert(lv2_osc_writer_message_vararg(writer, "/ping", "TFNI"));
- _test_a(writer, raw_3, sizeof(raw_3));
-}
-
-static void
-test_4_a(LV2_OSC_Writer *writer)
-{
- const uint8_t m [] = {0x00, 0x90, 24, 0x7f};
- const int32_t len = sizeof(m);
- assert(lv2_osc_writer_message_vararg(writer, "/midi", "m", len, m));
- _test_a(writer, raw_4, sizeof(raw_4));
-}
-
-static void
-test_5_a(LV2_OSC_Writer *writer)
-{
- const uint8_t b [] = {0x1, 0x2, 0x3, 0x4, 0x5, 0x6};
- const int32_t len = sizeof(b);
- assert(lv2_osc_writer_message_vararg(writer, "/blob", "b", len, b));
- _test_a(writer, raw_5, sizeof(raw_5));
-}
-
-static void
-test_6_a(LV2_OSC_Writer *writer)
-{
- LV2_OSC_Writer_Frame frame_bndl = { .ref = 0 };
- LV2_OSC_Writer_Frame frame_itm = { .ref = 0 };
-
- assert(lv2_osc_writer_push_bundle(writer, &frame_bndl, LV2_OSC_IMMEDIATE));
- {
- assert(lv2_osc_writer_push_item(writer, &frame_itm));
- {
- assert(lv2_osc_writer_message_vararg(writer, "/", ""));
- }
- assert(lv2_osc_writer_pop_item(writer, &frame_itm));
- }
- assert(lv2_osc_writer_pop_bundle(writer, &frame_bndl));
-
- _test_a(writer, raw_6, sizeof(raw_6));
-}
-
-static void
-test_7_a(LV2_OSC_Writer *writer)
-{
- LV2_OSC_Writer_Frame frame_bndl[2] = { { .ref = 0 }, { .ref = 0 } };
- LV2_OSC_Writer_Frame frame_itm[2] = { { .ref = 0 }, { .ref = 0 } };;
-
- assert(lv2_osc_writer_push_bundle(writer, &frame_bndl[0], LV2_OSC_IMMEDIATE));
- {
- assert(lv2_osc_writer_push_item(writer, &frame_itm[0]));
- {
- assert(lv2_osc_writer_push_bundle(writer, &frame_bndl[1], LV2_OSC_IMMEDIATE));
- {
- assert(lv2_osc_writer_push_item(writer, &frame_itm[1]));
- {
- assert(lv2_osc_writer_message_vararg(writer, "/", ""));
- }
- assert(lv2_osc_writer_pop_item(writer, &frame_itm[1]));
- }
- assert(lv2_osc_writer_pop_bundle(writer, &frame_bndl[1]));
- }
- assert(lv2_osc_writer_pop_item(writer, &frame_itm[0]));
-
- assert(lv2_osc_writer_push_item(writer, &frame_itm[0]));
- {
- assert(lv2_osc_writer_message_vararg(writer, "/", ""));
- }
- assert(lv2_osc_writer_pop_item(writer, &frame_itm[0]));
- }
- assert(lv2_osc_writer_pop_bundle(writer, &frame_bndl[0]));
-
- _test_a(writer, raw_7, sizeof(raw_7));
-}
-
-static void
-test_8_a(LV2_OSC_Writer *writer)
-{
- assert(lv2_osc_writer_message_vararg(writer, "/ping", "tcr",
- 1ULL,
- 'o',
- 0x1, 0x2, 0x3, 0x4));
- _test_a(writer, raw_8, sizeof(raw_8));
-}
-
-static test_t tests [] = {
- test_0_a,
- test_1_a,
- test_2_a,
- test_3_a,
- test_4_a,
- test_5_a,
- test_6_a,
- test_7_a,
- test_8_a,
-
- NULL
-}
-;
-static int
-_run_tests()
-{
- LV2_OSC_Writer writer;
-
- for(test_t *test=tests; *test; test++)
- {
- test_t cb = *test;
-
- memset(buf0, 0x0, BUF_SIZE);
- memset(buf1, 0x0, BUF_SIZE);
-
- lv2_osc_writer_initialize(&writer, buf0, BUF_SIZE);
-
- cb(&writer);
- }
-
- assert(unmap.unmap(unmap.handle, 0)== NULL);
-
- return 0;
-}
-
-#if !defined(_WIN32)
-typedef struct _item_t item_t;
-typedef struct _stash_t stash_t;
-
-struct _item_t {
- size_t size;
- uint8_t buf [];
-};
-
-struct _stash_t {
- size_t size;
- item_t **items;
- item_t *rsvd;
-};
-
-static uint8_t *
-_stash_write_req(stash_t *stash, size_t minimum, size_t *maximum)
-{
- if(!stash->rsvd || (stash->rsvd->size < minimum))
- {
- const size_t sz = sizeof(item_t) + minimum;
- stash->rsvd = realloc(stash->rsvd, sz);
- assert(stash->rsvd);
- stash->rsvd->size = minimum;
- }
-
- if(maximum)
- {
- *maximum = stash->rsvd->size;
- }
-
- return stash->rsvd->buf;
-}
-
-static void
-_stash_write_adv(stash_t *stash, size_t written)
-{
- assert(stash->rsvd);
- assert(stash->rsvd->size >= written);
- stash->rsvd->size = written;
- stash->size += 1;
- stash->items = realloc(stash->items, sizeof(item_t *) * stash->size);
- stash->items[stash->size - 1] = stash->rsvd;
- stash->rsvd = NULL;
-}
-
-static const uint8_t *
-_stash_read_req(stash_t *stash, size_t *size)
-{
- if(stash->size == 0)
- {
- if(size)
- {
- *size = 0;
- }
-
- return NULL;
- }
-
- item_t *item = stash->items[0];
-
- if(size)
- {
- *size = item->size;
- }
-
- return item->buf;
-}
-
-static void
-_stash_read_adv(stash_t *stash)
-{
- assert(stash->size);
-
- free(stash->items[0]);
- stash->size -= 1;
-
- for(unsigned i = 0; i < stash->size; i++)
- {
- stash->items[i] = stash->items[i+1];
- }
-
- stash->items = realloc(stash->items, sizeof(item_t *) * stash->size);
-}
-
-static void *
-_write_req(void *data, size_t minimum, size_t *maximum)
-{
- stash_t *stash = data;
-
- return _stash_write_req(&stash[0], minimum, maximum);
-}
-
-static void
-_write_adv(void *data, size_t written)
-{
- stash_t *stash = data;
-
- _stash_write_adv(&stash[0], written);
-}
-
-static const void *
-_read_req(void *data, size_t *toread)
-{
- stash_t *stash = data;
-
- return _stash_read_req(&stash[1], toread);
-}
-
-static void
-_read_adv(void *data)
-{
- stash_t *stash = data;
-
- _stash_read_adv(&stash[1]);
-}
-
-static const LV2_OSC_Driver driv = {
- .write_req = _write_req,
- .write_adv = _write_adv,
- .read_req = _read_req,
- .read_adv = _read_adv
-};
-
-#define COUNT 128
-
-typedef struct _pair_t pair_t;
-
-struct _pair_t {
- const char *server;
- const char *client;
- bool lossy;
-};
-
-static void *
-_thread_1(void *data)
-{
- const pair_t *pair = data;
- const char *uri = pair->server;
-
- LV2_OSC_Stream stream;
- stash_t stash [2];
- uint8_t check [COUNT];
-
- memset(&stream, 0x0, sizeof(stream));
- memset(stash, 0x0, sizeof(stash));
- memset(check, 0x0, sizeof(check));
-
- assert(lv2_osc_stream_init(&stream, uri, &driv, stash) == 0);
-
- time_t t0 = time(NULL);
- unsigned count = 0;
- while(true)
- {
- const time_t t1 = time(NULL);
- const LV2_OSC_Enum ev = lv2_osc_stream_run(&stream);
-
- if(ev & LV2_OSC_ERR)
- {
- fprintf(stderr, "%s: %s\n", __func__, strerror(ev & LV2_OSC_ERR));
- }
-
- if(ev & LV2_OSC_RECV)
- {
- const uint8_t *buf_rx;
- size_t reat;
-
- while( (buf_rx = _stash_read_req(&stash[0], &reat)) )
- {
- LV2_OSC_Reader reader;
-
- lv2_osc_reader_initialize(&reader, buf_rx, reat);
- assert(lv2_osc_reader_is_message(&reader));
-
- OSC_READER_MESSAGE_FOREACH(&reader, arg, reat)
- {
- assert(strcmp(arg->path, "/trip") == 0);
- assert(*arg->type == 'i');
- assert(arg->size == sizeof(int32_t));
- assert(check[arg->i] == 0);
- check[arg->i] = 1;
- }
-
- count++;
-
- while(true)
- {
- // send back
- uint8_t *buf_tx;
- if( (buf_tx = _stash_write_req(&stash[1], reat, NULL)) )
- {
- memcpy(buf_tx, buf_rx, reat);
-
- _stash_write_adv(&stash[1], reat);
- break;
- }
- }
-
- _stash_read_adv(&stash[0]);
- }
-
- t0 = t1;
- }
-
- if(count >= COUNT)
- {
- break;
- }
- else if(pair->lossy && (difftime(t1, t0) >= 1.0) )
- {
- fprintf(stderr, "%s: timeout: %i\n", __func__, count);
- break;
- }
- }
-
- LV2_OSC_Enum ev;
- do
- {
- ev = lv2_osc_stream_run(&stream);
-
- if(ev & LV2_OSC_ERR)
- {
- fprintf(stderr, "%s: %s\n", __func__, strerror(ev & LV2_OSC_ERR));
- }
- } while( (ev & LV2_OSC_SEND) || (ev & LV2_OSC_CONN) );
-
- assert(pair->lossy || (count == COUNT) );
-
- assert(lv2_osc_stream_deinit(&stream) == 0);
-
- free(stash[0].rsvd);
- while(stash[0].size)
- {
- _stash_read_adv(&stash[0]);
- }
- free(stash[0].items);
-
- free(stash[1].rsvd);
- while(stash[1].size)
- {
- _stash_read_adv(&stash[1]);
- }
- free(stash[1].items);
-
- return NULL;
-}
-
-static void *
-_thread_2(void *data)
-{
- const pair_t *pair = data;
- const char *uri = pair->client;
-
- LV2_OSC_Stream stream;
- stash_t stash [2];
- uint8_t check [COUNT];
-
- memset(&stream, 0x0, sizeof(stream));
- memset(stash, 0x0, sizeof(stash));
- memset(check, 0x0, sizeof(check));
-
- assert(lv2_osc_stream_init(&stream, uri, &driv, stash) == 0);
-
- unsigned count = 0;
- for(int32_t i = 0; i < COUNT; i++)
- {
- LV2_OSC_Writer writer;
-
- while(true)
- {
- uint8_t *buf_tx;
- size_t max;
- if( (buf_tx = _stash_write_req(&stash[1], 1024, &max)) )
- {
- size_t writ;
- lv2_osc_writer_initialize(&writer, buf_tx, max);
- assert(lv2_osc_writer_message_vararg(&writer, "/trip", "i", i));
- assert(lv2_osc_writer_finalize(&writer, &writ) == buf_tx);
- assert(writ == 16);
- assert(check[i] == 0);
- check[i] = 1;
-
- _stash_write_adv(&stash[1], writ);
- break;
- }
- }
-
- const LV2_OSC_Enum ev = lv2_osc_stream_run(&stream);
-
- if(ev & LV2_OSC_ERR)
- {
- fprintf(stderr, "%s: %s\n", __func__, strerror(ev & LV2_OSC_ERR));
- }
-
- if(ev & LV2_OSC_RECV)
- {
- const uint8_t *buf_rx;
- size_t reat;
-
- while( (buf_rx = _stash_read_req(&stash[0], &reat)) )
- {
- LV2_OSC_Reader reader;
-
- lv2_osc_reader_initialize(&reader, buf_rx, reat);
- assert(lv2_osc_reader_is_message(&reader));
-
- OSC_READER_MESSAGE_FOREACH(&reader, arg, reat)
- {
- assert(strcmp(arg->path, "/trip") == 0);
- assert(*arg->type == 'i');
- assert(arg->size == sizeof(int32_t));
- assert(check[arg->i] == 1);
- check[arg->i] = 2;
- }
-
- count++;
-
- _stash_read_adv(&stash[0]);
- }
- }
- }
-
- time_t t0 = time(NULL);
- while(true)
- {
- const time_t t1 = time(NULL);
- const LV2_OSC_Enum ev = lv2_osc_stream_run(&stream);
-
- if(ev & LV2_OSC_ERR)
- {
- fprintf(stderr, "%s: %s\n", __func__, strerror(ev & LV2_OSC_ERR));
- }
-
- if(ev & LV2_OSC_RECV)
- {
- const uint8_t *buf_rx;
- size_t reat;
-
- while( (buf_rx = _stash_read_req(&stash[0], &reat)) )
- {
- LV2_OSC_Reader reader;
-
- lv2_osc_reader_initialize(&reader, buf_rx, reat);
- assert(lv2_osc_reader_is_message(&reader));
-
- OSC_READER_MESSAGE_FOREACH(&reader, arg, reat)
- {
- assert(strcmp(arg->path, "/trip") == 0);
- assert(*arg->type == 'i');
- assert(arg->size == sizeof(int32_t));
- assert(check[arg->i] == 1);
- check[arg->i] = 2;
- }
-
- count++;
-
- _stash_read_adv(&stash[0]);
- }
-
- t0 = t1;
- }
-
- if(count >= COUNT)
- {
- break;
- }
- else if(pair->lossy && (difftime(t1, t0) >= 1.0) )
- {
- fprintf(stderr, "%s: timeout: %i\n", __func__, count);
- break;
- }
- }
-
- assert(pair->lossy || (count == COUNT) );
-
- assert(lv2_osc_stream_deinit(&stream) == 0);
-
- free(stash[0].rsvd);
- while(stash[0].size)
- {
- _stash_read_adv(&stash[0]);
- }
- free(stash[0].items);
-
- free(stash[1].rsvd);
- while(stash[1].size)
- {
- _stash_read_adv(&stash[1]);
- }
- free(stash[1].items);
-
- return NULL;
-}
-
-static const pair_t pairs [] = {
- {
- .server = "osc.udp://:2222",
- .client = "osc.udp://localhost:2222",
- .lossy = true
- },
- {
- .server = "osc.udp://[]:3333",
- .client = "osc.udp://[::1]:3333",
- .lossy = true
- },
-
- {
- .server = "osc.udp://:3344",
- .client = "osc.udp://255.255.255.255:3344",
- .lossy = true
- },
-
- {
- .server = "osc.tcp://:4444",
- .client = "osc.tcp://localhost:4444",
- .lossy = false
- },
- {
- .server = "osc.tcp://[]:5555",
- .client = "osc.tcp://[::1]:5555",
- .lossy = false
- },
-
- {
- .server = "osc.slip.tcp://:6666",
- .client = "osc.slip.tcp://localhost:6666",
- .lossy = false
- },
- {
- .server = "osc.slip.tcp://[]:7777",
- .client = "osc.slip.tcp://[::1]:7777",
- .lossy = false
- },
-
- {
- .server = "osc.prefix.tcp://:8888",
- .client = "osc.prefix.tcp://localhost:8888",
- .lossy = false
- },
- {
- .server = "osc.prefix.tcp://[%lo]:9999",
- .client = "osc.prefix.tcp://[::1%lo]:9999",
- .lossy = false
- },
-
-#if 0
- {
- .server = "osc.serial:///dev/pts/4", //FIXME baudrate
- .client = "osc.serial:///dev/pts/5",
- .lossy = false
- },
-#endif
-
- {
- .server = NULL,
- .client = NULL,
- .lossy = false
- }
-};
-#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 __attribute__((unused)), char **argv __attribute__((unused)))
-{
-#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;
- pthread_t thread_2;
-
- fprintf(stdout, "running stream test: <%s> <%s> %i\n",
- pair->server, pair->client, pair->lossy);
-
- assert(pthread_create(&thread_1, NULL, _thread_1, (void *)pair) == 0);
- assert(pthread_create(&thread_2, NULL, _thread_2, (void *)pair) == 0);
-
- assert(pthread_join(thread_1, NULL) == 0);
- assert(pthread_join(thread_2, NULL) == 0);
- }
-#endif
-
- for(unsigned i=0; i<__app.urid; i++)
- {
- urid_t *itm = &__app.urids[i];
-
- free(itm->uri);
- }
-
- return 0;
-}