40 files changed, 1 insertions(+), 6315 deletions(-)
M VERSION
D netatom.lv2/.gitlab-ci.yml
D netatom.lv2/COPYING
D netatom.lv2/README.md
D netatom.lv2/VERSION
D netatom.lv2/gitlab-ci/generic.yml
D netatom.lv2/meson.build
D netatom.lv2/netatom.lv2/endian.h
D netatom.lv2/netatom.lv2/netatom.h
D netatom.lv2/test/netatom_test.c
D props.lv2/.gitlab-ci.yml
D props.lv2/COPYING
D props.lv2/README.md
D props.lv2/VERSION
D props.lv2/gitlab-ci/generic.yml
D props.lv2/meson.build
D props.lv2/props.h
D props.lv2/test/chunk.bin
D props.lv2/test/manifest.ttl.in
D props.lv2/test/props.c
D props.lv2/test/props.ttl
D props.lv2/test/props_test.c
D timely.lv2/.gitlab-ci.yml
D timely.lv2/COPYING
D timely.lv2/README.md
D timely.lv2/VERSION
D timely.lv2/gitlab-ci/generic.yml
D timely.lv2/meson.build
D timely.lv2/test/manifest.ttl.in
D timely.lv2/test/timely.c
D timely.lv2/test/timely.ttl
D timely.lv2/timely.h
D varchunk/.gitlab-ci.yml
D varchunk/COPYING
D varchunk/README.md
D varchunk/VERSION
D varchunk/gitlab-ci/generic.yml
D varchunk/meson.build
D varchunk/test_varchunk.c
D varchunk/varchunk.h
M VERSION => VERSION +1 -1
@@ 1,1 1,1 @@
-0.1.675
+0.1.679
D netatom.lv2/.gitlab-ci.yml => netatom.lv2/.gitlab-ci.yml +0 -2
@@ 1,2 0,0 @@
-include:
- - local: 'gitlab-ci/generic.yml'
D netatom.lv2/COPYING => netatom.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 netatom.lv2/README.md => netatom.lv2/README.md +0 -33
@@ 1,33 0,0 @@
-# netatom.lv2
-
-## Utility header for (de)serializing LV2 atoms in binary form
-
-### Build Status
-
-[![build status](https://gitlab.com/OpenMusicKontrollers/netatom.lv2/badges/master/build.svg)](https://gitlab.com/OpenMusicKontrollers/netatom.lv2/commits/master)
-
-### Build / test
-
- git clone https://git.open-music-kontrollers.ch/lv2/netatom.lv2
- cd netatom.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 netatom.lv2/VERSION => netatom.lv2/VERSION +0 -1
D netatom.lv2/gitlab-ci/generic.yml => netatom.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 netatom.lv2/meson.build => netatom.lv2/meson.build +0 -38
@@ 1,38 0,0 @@
-project('netatom.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')
-sratom_dep = dependency('sratom-0',
- static : meson.is_cross_build() and false) #FIXME
-deps = [lv2_dep, sratom_dep]
-
-if host_machine.system() == 'windows'
- deps += cc.find_library('ws2_32')
-endif
-
-c_args = []
-
-if cc.has_argument('-Wno-error=format=')
- c_args += '-Wno-error=format='
-endif
-
-netatom_test = executable('netatom_test',
- join_paths('test', 'netatom_test.c'),
- c_args : c_args,
- dependencies : deps,
- install : false)
-
-test('Test', netatom_test,
- args : ['1000'],
- timeout : 240)
D netatom.lv2/netatom.lv2/endian.h => netatom.lv2/netatom.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 netatom.lv2/netatom.lv2/netatom.h => netatom.lv2/netatom.lv2/netatom.h +0 -535
@@ 1,535 0,0 @@
-/*
- * 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.
- */
-
-#ifndef _NETATOM_H
-#define _NETATOM_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <netatom.lv2/endian.h>
-
-#include <lv2/lv2plug.in/ns/ext/atom/atom.h>
-#include <lv2/lv2plug.in/ns/ext/atom/forge.h>
-#include <lv2/lv2plug.in/ns/ext/urid/urid.h>
-#include <lv2/lv2plug.in/ns/ext/midi/midi.h>
-
-#ifndef NETATOM_API
-# define NETATOM_API static
-#endif
-
-typedef struct _netatom_t netatom_t;
-
-NETATOM_API uint8_t *
-netatom_serialize(netatom_t *netatom, LV2_Atom *atom, size_t size_rx,
- size_t *size_tx);
-
-NETATOM_API const LV2_Atom *
-netatom_deserialize(netatom_t *netatom, uint8_t *buf_tx, size_t size_tx);
-
-NETATOM_API netatom_t *
-netatom_new(LV2_URID_Map *map, LV2_URID_Unmap *unmap, bool swap);
-
-NETATOM_API void
-netatom_free(netatom_t *netatom);
-
-#ifdef NETATOM_IMPLEMENTATION
-
-typedef union _netatom_union_t netatom_union_t;
-
-union _netatom_union_t {
- LV2_Atom *atom;
- uint8_t *buf;
-};
-
-struct _netatom_t {
- bool swap;
- LV2_URID_Unmap *unmap;
- LV2_URID_Map *map;
- LV2_Atom_Forge forge;
- struct {
- uint8_t *buf;
- const uint8_t *cur;
- const uint8_t *end;
- } dict;
- uint32_t MIDI_MidiEvent;
- bool overflow;
-};
-
-static inline void
-_netatom_ser_uri(netatom_t *netatom, uint32_t *urid, const char *uri)
-{
- if(*urid == 0)
- return; // ignore untyped atoms
-
- // look for matching URID in dictionary
- uint32_t match = 0;
-
- for(netatom_union_t ptr = { .buf = netatom->dict.buf };
- ptr.buf < netatom->dict.cur;
- ptr.buf += lv2_atom_pad_size(lv2_atom_total_size(ptr.atom)))
- {
- if(ptr.atom->type == *urid)
- {
- match = ptr.buf - netatom->dict.buf + 1;
- break;
- }
- }
-
- if(match) // use already matched URI in dictionary
- {
- *urid = match;
- }
- else // add new URI to dictionary
- {
- if(!uri)
- uri = netatom->unmap->unmap(netatom->unmap->handle, *urid);
-
- if(!uri) // invalid urid
- {
- *urid = 0;
- }
- else
- {
- const uint32_t size = strlen(uri) + 1;
- const uint32_t tot_size = sizeof(LV2_Atom) + lv2_atom_pad_size(size);
- const uint32_t ref = netatom->dict.cur - netatom->dict.buf + 1;
-
- if(netatom->dict.cur + tot_size <= netatom->dict.end)
- {
- LV2_Atom *atom = (LV2_Atom *)netatom->dict.cur;
- atom->size = size;
- atom->type = *urid;
- strncpy(LV2_ATOM_BODY(atom), uri, tot_size); // automatic padding
-
- *urid = ref;
- netatom->dict.cur += tot_size;
- }
- else // dict buffer overflow
- {
- *urid = 0;
- netatom->overflow = true;
- }
- }
- }
-
- if(netatom->swap)
- *urid = htobe32(*urid);
-}
-
-static inline void
-_netatom_ser_dict(netatom_t *netatom)
-{
- LV2_Atom *body = NULL;
- for(netatom_union_t ptr = { .buf = netatom->dict.buf };
- ptr.buf < netatom->dict.cur;
- ptr.buf += lv2_atom_pad_size(lv2_atom_total_size(ptr.atom)))
- {
- if( netatom->swap && body)
- body->size = htobe32(body->size);
- body = ptr.atom;
- ptr.atom->type = 0; // clear key
- }
- if(netatom->swap && body)
- body->size = htobe32(body->size);
-}
-
-static inline void
-_netatom_deser_uri(netatom_t *netatom, uint32_t *urid)
-{
- if(*urid == 0)
- return; // ignore untyped atoms
-
- const uint32_t ref = netatom->swap
- ? be32toh(*urid)
- : *urid;
-
- const LV2_Atom *atom = (const LV2_Atom *)&netatom->dict.buf[ref - 1];
- *urid = atom->type;
-}
-
-static inline void
-_netatom_deser_dict(netatom_t *netatom)
-{
- for(netatom_union_t ptr = { .buf = netatom->dict.buf};
- ptr.buf < netatom->dict.cur;
- ptr.buf += lv2_atom_pad_size(lv2_atom_total_size(ptr.atom)))
- {
- if(netatom->swap)
- ptr.atom->size = be32toh(ptr.atom->size);
- const char *uri = LV2_ATOM_BODY_CONST(ptr.atom);
- ptr.atom->type = netatom->map->map(netatom->map->handle, uri);
- }
-}
-
-static void
-_netatom_ser_atom(netatom_t *netatom, LV2_Atom *atom)
-{
- LV2_Atom_Forge *forge = &netatom->forge;
- const char *uri = NULL;
-
- if(atom->type == forge->Bool)
- {
- if(netatom->swap)
- {
- uint32_t *u = LV2_ATOM_BODY(atom);
- *u = htobe32(*u);
- }
- uri = LV2_ATOM__Bool;
- }
- else if(atom->type == forge->Int)
- {
- if(netatom->swap)
- {
- uint32_t *u = LV2_ATOM_BODY(atom);
- *u = htobe32(*u);
- }
- uri = LV2_ATOM__Int;
- }
- else if(atom->type == forge->Float)
- {
- if(netatom->swap)
- {
- uint32_t *u = LV2_ATOM_BODY(atom);
- *u = htobe32(*u);
- }
- uri = LV2_ATOM__Float;
- }
- else if(atom->type == forge->Long)
- {
- if(netatom->swap)
- {
- uint64_t *u = LV2_ATOM_BODY(atom);
- *u = htobe64(*u);
- }
- uri = LV2_ATOM__Long;
- }
- else if(atom->type == forge->Double)
- {
- if(netatom->swap)
- {
- uint64_t *u = LV2_ATOM_BODY(atom);
- *u = htobe64(*u);
- }
- uri = LV2_ATOM__Double;
- }
- else if(atom->type == forge->URID)
- {
- uint32_t *u = LV2_ATOM_BODY(atom);
- _netatom_ser_uri(netatom, u, NULL);
- uri = LV2_ATOM__URID;
- }
- else if(atom->type == forge->String)
- {
- uri = LV2_ATOM__String;
- }
- else if(atom->type == forge->Chunk)
- {
- uri = LV2_ATOM__Chunk;
- }
- else if(atom->type == netatom->MIDI_MidiEvent)
- {
- uri = LV2_MIDI__MidiEvent;
- }
- else if(atom->type == forge->Literal)
- {
- LV2_Atom_Literal *lit = (LV2_Atom_Literal *)atom;
- _netatom_ser_uri(netatom, &lit->body.datatype, NULL);
- _netatom_ser_uri(netatom, &lit->body.lang, NULL);
- uri = LV2_ATOM__Literal;
- }
- else if(atom->type == forge->Object)
- {
- LV2_Atom_Object *obj = (LV2_Atom_Object *)atom;
- LV2_Atom *body = NULL;
- LV2_ATOM_OBJECT_FOREACH(obj, prop)
- {
- if(body)
- _netatom_ser_atom(netatom, body);
- body = &prop->value;
- _netatom_ser_uri(netatom, &prop->key, NULL);
- _netatom_ser_uri(netatom, &prop->context, NULL);
- }
- if(body)
- _netatom_ser_atom(netatom, body);
- _netatom_ser_uri(netatom, &obj->body.id, NULL);
- _netatom_ser_uri(netatom, &obj->body.otype, NULL);
- uri = LV2_ATOM__Object;
- }
- else if(atom->type == forge->Tuple)
- {
- LV2_Atom_Tuple *tup = (LV2_Atom_Tuple *)atom;
- LV2_Atom *body = NULL;
- LV2_ATOM_TUPLE_FOREACH(tup, item)
- {
- if(body)
- _netatom_ser_atom(netatom, body);
- body = item;
- }
- if(body)
- _netatom_ser_atom(netatom, body);
- uri = LV2_ATOM__Tuple;
- }
- else if(atom->type == forge->Sequence)
- {
- LV2_Atom_Sequence *seq = (LV2_Atom_Sequence *)atom;
- LV2_Atom *body = NULL;
- LV2_ATOM_SEQUENCE_FOREACH(seq, ev)
- {
- if(body)
- _netatom_ser_atom(netatom, body);
- body = &ev->body;
- if(netatom->swap)
- ev->time.frames = htobe64(ev->time.frames);
- }
- if(body)
- _netatom_ser_atom(netatom, body);
- _netatom_ser_uri(netatom, &seq->body.unit, NULL);
- if(netatom->swap)
- seq->body.pad = htobe32(seq->body.pad);
- uri = LV2_ATOM__Sequence;
- }
- else if(atom->type == forge->Vector)
- {
- LV2_Atom_Vector *vec = (LV2_Atom_Vector *)atom;
- if(netatom->swap)
- {
- if(vec->body.child_size == 4)
- {
- const unsigned n = (vec->atom.size - sizeof(LV2_Atom_Vector_Body)) / 4;
- uint32_t *u = LV2_ATOM_CONTENTS(LV2_Atom_Vector, atom);
- for(unsigned i = 0; i < n; i++)
- u[i] = htobe32(u[i]);
- }
- else if(vec->body.child_size == 8)
- {
- const unsigned n = (vec->atom.size - sizeof(LV2_Atom_Vector_Body)) / 8;
- uint64_t *u = LV2_ATOM_CONTENTS(LV2_Atom_Vector, atom);
- for(unsigned i = 0; i < n; i++)
- u[i] = htobe64(u[i]);
- }
- vec->body.child_size = htobe32(vec->body.child_size);
- }
- _netatom_ser_uri(netatom, &vec->body.child_type, NULL); //TODO set uri
- uri = LV2_ATOM__Vector;
- }
- else if(atom->type == forge->Path)
- {
- uri = LV2_ATOM__Path;
- }
- else if(atom->type == forge->URI)
- {
- uri = LV2_ATOM__URI;
- }
-
- if(netatom->swap)
- atom->size = htobe32(atom->size);
- _netatom_ser_uri(netatom, &atom->type, uri);
-}
-
-static void
-_netatom_deser_atom(netatom_t *netatom, LV2_Atom *atom)
-{
- LV2_Atom_Forge *forge = &netatom->forge;
-
- if(netatom->swap)
- atom->size = be32toh(atom->size);
- _netatom_deser_uri(netatom, &atom->type);
-
- if( (atom->type == forge->Bool)
- || (atom->type == forge->Int)
- || (atom->type == forge->Float) )
- {
- if(netatom->swap)
- {
- uint32_t *u = LV2_ATOM_BODY(atom);
- *u = be32toh(*u);
- }
- }
- else if( (atom->type == forge->Long)
- || (atom->type == forge->Double) )
- {
- if(netatom->swap)
- {
- uint64_t *u = LV2_ATOM_BODY(atom);
- *u = be64toh(*u);
- }
- }
- else if(atom->type == forge->URID)
- {
- uint32_t *u = LV2_ATOM_BODY(atom);
- _netatom_deser_uri(netatom, u);
- }
- else if(atom->type == forge->Literal)
- {
- LV2_Atom_Literal *lit = (LV2_Atom_Literal *)atom;
- _netatom_deser_uri(netatom, &lit->body.datatype);
- _netatom_deser_uri(netatom, &lit->body.lang);
- }
- else if(atom->type == forge->Object)
- {
- LV2_Atom_Object *obj = (LV2_Atom_Object *)atom;
- _netatom_deser_uri(netatom, &obj->body.id);
- _netatom_deser_uri(netatom, &obj->body.otype);
- LV2_ATOM_OBJECT_FOREACH(obj, prop)
- {
- _netatom_deser_uri(netatom, &prop->key);
- _netatom_deser_uri(netatom, &prop->context);
- _netatom_deser_atom(netatom, &prop->value);
- }
- }
- else if(atom->type == forge->Tuple)
- {
- LV2_Atom_Tuple *tup = (LV2_Atom_Tuple *)atom;
- LV2_ATOM_TUPLE_FOREACH(tup, item)
- {
- _netatom_deser_atom(netatom, item);
- }
- }
- else if(atom->type == forge->Sequence)
- {
- LV2_Atom_Sequence *seq = (LV2_Atom_Sequence *)atom;
- _netatom_deser_uri(netatom, &seq->body.unit);
- if(netatom->swap)
- seq->body.pad = be32toh(seq->body.pad);
- LV2_ATOM_SEQUENCE_FOREACH(seq, ev)
- {
- _netatom_deser_atom(netatom, &ev->body);
- if(netatom->swap)
- ev->time.frames = be64toh(ev->time.frames);
- }
- }
- else if(atom->type == forge->Vector)
- {
- LV2_Atom_Vector *vec = (LV2_Atom_Vector *)atom;
- _netatom_deser_uri(netatom, &vec->body.child_type);
- if(netatom->swap)
- {
- vec->body.child_size = be32toh(vec->body.child_size);
- if(vec->body.child_size == 4)
- {
- const unsigned n = (vec->atom.size - sizeof(LV2_Atom_Vector_Body)) / 4;
- uint32_t *u = LV2_ATOM_CONTENTS(LV2_Atom_Vector, atom);
- for(unsigned i = 0; i < n; i++)
- u[i] = be32toh(u[i]);
- }
- else if(vec->body.child_size == 8)
- {
- const unsigned n = (vec->atom.size - sizeof(LV2_Atom_Vector_Body)) / 8;
- uint64_t *u = LV2_ATOM_CONTENTS(LV2_Atom_Vector, atom);
- for(unsigned i = 0; i < n; i++)
- u[i] = be64toh(u[i]);
- }
- }
- }
-}
-
-NETATOM_API uint8_t *
-netatom_serialize(netatom_t *netatom, LV2_Atom *atom, size_t size_rx,
- size_t *size_tx)
-{
- if(!netatom || !atom)
- return NULL;
-
- uint8_t *buf_rx = (uint8_t *)atom;
- const uint32_t tot_size = lv2_atom_pad_size(lv2_atom_total_size(atom));
-
- netatom->dict.buf = buf_rx + tot_size;
- netatom->dict.cur = netatom->dict.buf;
- netatom->dict.end = buf_rx + size_rx;
-
- netatom->overflow = false;
-
- _netatom_ser_atom(netatom, atom);
- _netatom_ser_dict(netatom);
-
- if(netatom->overflow)
- return NULL;
-
- const size_t size_dict = netatom->dict.cur - netatom->dict.buf;
- const size_t written = tot_size + size_dict;
-
- if(size_tx)
- *size_tx = written;
-
- return buf_rx;
-}
-
-NETATOM_API const LV2_Atom *
-netatom_deserialize(netatom_t *netatom, uint8_t *buf_tx, size_t size_tx)
-{
- if(!netatom || !buf_tx)
- return NULL;
-
- LV2_Atom *atom = (LV2_Atom *)buf_tx;
- const uint32_t size = netatom->swap
- ? be32toh(atom->size)
- : atom->size;
-
- const uint32_t tot_size = lv2_atom_pad_size(sizeof(LV2_Atom) + size);
-
- const uint32_t dict_size = size_tx - tot_size;
- netatom->dict.buf = buf_tx + tot_size;
- netatom->dict.cur = netatom->dict.buf + dict_size;
- netatom->dict.end = buf_tx + size_tx;
-
- netatom->overflow = false;
-
- _netatom_deser_dict(netatom);
- _netatom_deser_atom(netatom, atom);
-
- return atom;
-}
-
-NETATOM_API netatom_t *
-netatom_new(LV2_URID_Map *map, LV2_URID_Unmap *unmap, bool swap)
-{
- netatom_t *netatom = calloc(1, sizeof(netatom_t));
- if(!netatom)
- return NULL;
-
- netatom->swap = swap;
- netatom->map = map;
- netatom->unmap = unmap;
-
- lv2_atom_forge_init(&netatom->forge, map);
-
- netatom->MIDI_MidiEvent = map->map(map->handle, LV2_MIDI__MidiEvent);
-
- return netatom;
-}
-
-NETATOM_API void
-netatom_free(netatom_t *netatom)
-{
- if(!netatom)
- return;
-
- free(netatom);
-}
-
-#endif // NETATOM_IMPLEMENTATION
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif // _NETATOM_H
D netatom.lv2/test/netatom_test.c => netatom.lv2/test/netatom_test.c +0 -289
@@ 1,289 0,0 @@
-/*
- * 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.
- */
-
-#include <time.h>
-#include <sratom/sratom.h>
-
-#define NETATOM_IMPLEMENTATION
-#include <netatom.lv2/netatom.h>
-
-#define MAX_URIDS 2048
-#define MAX_BUF 4092
-
-typedef struct _urid_t urid_t;
-typedef struct _store_t store_t;
-
-struct _urid_t {
- LV2_URID urid;
- char *uri;
-};
-
-struct _store_t {
- urid_t urids [MAX_URIDS];
- LV2_URID urid;
-};
-
-static LV2_URID
-_map(LV2_URID_Map_Handle instance, const char *uri)
-{
- store_t *handle = instance;
-
- urid_t *itm;
- for(itm=handle->urids; itm->urid; itm++)
- {
- if(!strcmp(itm->uri, uri))
- return itm->urid;
- }
-
- assert(handle->urid + 1 < MAX_URIDS);
-
- // create new
- itm->urid = ++handle->urid;
- itm->uri = strdup(uri);
-
- return itm->urid;
-}
-
-static const char *
-_unmap(LV2_URID_Unmap_Handle instance, LV2_URID urid)
-{
- store_t *handle = instance;
-
- for(urid_t *itm=handle->urids; itm->urid; itm++)
- {
- if(itm->urid == urid)
- return itm->uri;
- }
-
- // not found
- return NULL;
-}
-
-static void
-_freemap(store_t *handle)
-{
- for(urid_t *itm = handle->urids; itm->urid; itm++)
- free(itm->uri);
-}
-
-static void
-_netatom_test(LV2_URID_Map *map, LV2_URID_Unmap *unmap, bool swap,
- const LV2_Atom *atom, unsigned iterations)
-{
- static uint8_t buf [MAX_BUF];
- netatom_t *netatom = netatom_new(map, unmap, swap);
- assert(netatom);
-
- for(unsigned i = 0; i < iterations; i++)
- {
- memcpy(buf, atom, lv2_atom_total_size(atom));
-
- size_t size_tx = 0;
- uint8_t *buf_tx = netatom_serialize(netatom, (LV2_Atom *)buf, MAX_BUF, &size_tx);
- assert(buf_tx);
-
- if(iterations == 1)
- {
- fwrite(buf_tx, size_tx, 1, stdout);
-
-#if !defined(_WIN32)
- const size_t tot_size = lv2_atom_total_size(atom);
- fprintf(stderr, "%zu, %zu, %lf\n", tot_size, size_tx,
- (double)size_tx / lv2_atom_total_size(atom));
-#endif
- }
-
- const LV2_Atom *atom_rx = netatom_deserialize(netatom, buf_tx, size_tx);
- assert(atom_rx);
-
- const uint32_t size_rx = lv2_atom_total_size(atom_rx);
-
- assert(size_rx == lv2_atom_total_size(atom));
- assert(memcmp(atom, atom_rx, size_rx) == 0);
- }
-
- netatom_free(netatom);
-}
-
-static void
-_sratom_test(LV2_URID_Map *map, LV2_URID_Unmap *unmap, bool pretty,
- const LV2_Atom *atom, unsigned iterations)
-{
- Sratom *sratom = sratom_new(map);
- assert(sratom);
- sratom_set_pretty_numbers(sratom, pretty);
- const char *base_uri = "file:///tmp/base";
- const SerdNode subject = serd_node_from_string(SERD_URI, (const uint8_t *)(""));
- const SerdNode predicate = serd_node_from_string(SERD_URI, (const uint8_t *)(LV2_ATOM__atomTransfer));
-
- for(unsigned i = 0; i < iterations; i++)
- {
- char *ttl = sratom_to_turtle(sratom, unmap, base_uri, &subject, &predicate,
- atom->type, atom->size, LV2_ATOM_BODY_CONST(atom));
- assert(ttl);
-
- LV2_Atom *clone = sratom_from_turtle(sratom, base_uri, &subject, &predicate, ttl);
- assert(clone);
-
- assert(atom->size == clone->size);
- assert(atom->type == clone->type);
- //assert(memcmp(LV2_ATOM_BODY_CONST(atom), LV2_ATOM_BODY_CONST(clone), atom->size) == 0);
-
- free(clone);
- free(ttl);
- }
-
- sratom_free(sratom);
-}
-
-#define MAP(O) map.map(map.handle, "urn:netatom:test#"O)
-
-int
-main(int argc, char **argv)
-{
- static store_t handle;
-
- if(argc < 2)
- return -1;
- const unsigned iterations = atoi(argv[1]);
-
- LV2_URID_Map map = {
- .handle = &handle,
- .map = _map
- };
-
- LV2_URID_Unmap unmap = {
- .handle = &handle,
- .unmap = _unmap
- };
-
- LV2_Atom_Forge forge;
- lv2_atom_forge_init(&forge, &map);
-
- union {
- LV2_Atom atom;
- uint8_t buf [2048];
- } un;
-
- lv2_atom_forge_set_buffer(&forge, un.buf, 2048);
-
- LV2_Atom_Forge_Frame obj_frame;
- lv2_atom_forge_object(&forge, &obj_frame, 0, MAP("otype"));
- {
- lv2_atom_forge_key(&forge, forge.Int);
- lv2_atom_forge_int(&forge, 12);
-
- lv2_atom_forge_key(&forge, forge.Bool);
- lv2_atom_forge_bool(&forge, 1);
-
- lv2_atom_forge_key(&forge, forge.Long);
- lv2_atom_forge_long(&forge, 14);
-
- lv2_atom_forge_key(&forge, forge.Float);
- lv2_atom_forge_float(&forge, 1.5);
-
- lv2_atom_forge_key(&forge, forge.Double);
- lv2_atom_forge_double(&forge, 4.5);
-
- lv2_atom_forge_key(&forge, forge.String);
- lv2_atom_forge_string(&forge, "hello", 5);
-
- lv2_atom_forge_key(&forge, forge.Path);
- lv2_atom_forge_path(&forge, "/tmp", 4);
-
- lv2_atom_forge_key(&forge, forge.Literal);
- lv2_atom_forge_literal(&forge, "hello", 5, MAP("dtype"), MAP("lang"));
-
- /*
- lv2_atom_forge_key(&forge, forge.URI);
- lv2_atom_forge_uri(&forge, LV2_URID__map, strlen(LV2_URID__map));
- */
-
- lv2_atom_forge_key(&forge, forge.URID);
- lv2_atom_forge_urid(&forge, MAP("key"));
-
- const uint8_t m [3] = {0x90, 0x2f, 0x7f};
- lv2_atom_forge_key(&forge, map.map(map.handle, LV2_MIDI__MidiEvent));
- lv2_atom_forge_atom(&forge, 3, map.map(map.handle, LV2_MIDI__MidiEvent));
- lv2_atom_forge_write(&forge, m, 3);
-
- const uint8_t b [8] = {0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7};
- lv2_atom_forge_key(&forge, forge.Chunk);
- lv2_atom_forge_atom(&forge, 8, forge.Chunk);
- lv2_atom_forge_write(&forge, b, 8);
-
- LV2_Atom_Forge_Frame tup_frame;
- lv2_atom_forge_key(&forge, forge.Tuple);
- lv2_atom_forge_tuple(&forge, &tup_frame);
- {
- for(unsigned i = 0; i < 16; i++)
- lv2_atom_forge_int(&forge, i);
- }
- lv2_atom_forge_pop(&forge, &tup_frame);
-
- LV2_Atom_Forge_Frame vec_frame;
- lv2_atom_forge_key(&forge, forge.Vector);
- lv2_atom_forge_vector_head(&forge, &vec_frame, sizeof(int32_t), forge.Int);
- {
- for(unsigned i = 0; i < 16; i++)
- lv2_atom_forge_int(&forge, i);
- }
- lv2_atom_forge_pop(&forge, &vec_frame);
-
- LV2_Atom_Forge_Frame seq_frame;
- lv2_atom_forge_key(&forge, forge.Sequence);
- lv2_atom_forge_sequence_head(&forge, &seq_frame, MAP(LV2_ATOM__frameTime));
- {
- for(unsigned i = 0; i < 16; i++)
- {
- lv2_atom_forge_frame_time(&forge, i);
- lv2_atom_forge_int(&forge, i);
- }
- }
- lv2_atom_forge_pop(&forge, &seq_frame);
- }
- lv2_atom_forge_pop(&forge, &obj_frame);
-
- // add some dummy URI to hash map
- char tmp [32];
- for(int i=0; i<1024; i++)
- {
- snprintf(tmp, 32, "urn:dummy:%i", i);
- map.map(map.handle, tmp);
- }
-
-#if !defined(__APPLE__) && !defined(_WIN32)
- struct timespec t0, t1, t2;
- clock_gettime(CLOCK_MONOTONIC, &t0);
-#endif
- _netatom_test(&map, &unmap, true, &un.atom, iterations);
-#if !defined(__APPLE__) && !defined(_WIN32)
- clock_gettime(CLOCK_MONOTONIC, &t1);
-#endif
- _sratom_test(&map, &unmap, false, &un.atom, iterations);
-#if !defined(__APPLE__) && !defined(_WIN32)
- clock_gettime(CLOCK_MONOTONIC, &t2);
-
- const double d1 = (t1.tv_sec - t0.tv_sec) + (t1.tv_nsec - t0.tv_nsec) * 1e-9;
- const double d2 = (t2.tv_sec - t1.tv_sec) + (t2.tv_nsec - t1.tv_nsec) * 1e-9;
- fprintf(stderr, "%lf s, %lf s, x %lf\n", d1, d2, d2/d1);
-#endif
-
- _freemap(&handle);
-
- return 0;
-}
D props.lv2/.gitlab-ci.yml => props.lv2/.gitlab-ci.yml +0 -2
@@ 1,2 0,0 @@
-include:
- - local: 'gitlab-ci/generic.yml'
D props.lv2/COPYING => props.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 props.lv2/README.md => props.lv2/README.md +0 -20
@@ 1,20 0,0 @@
-# Props.lv2
-
-## Utility header for property based LV2 plugins
-
-### License
-
-Copyright (c) 2015 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 props.lv2/VERSION => props.lv2/VERSION +0 -1
D props.lv2/gitlab-ci/generic.yml => props.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 props.lv2/meson.build => props.lv2/meson.build +0 -82
@@ 1,82 0,0 @@
-project('props.lv2', 'c', default_options : [
- 'buildtype=release',
- 'warning_level=3',
- 'werror=false',
- 'b_lto=false',
- 'c_std=c11'])
-
-add_project_arguments('-D_GNU_SOURCE', language : 'c')
-
-conf_data = configuration_data()
-cc = meson.get_compiler('c')
-
-cp = find_program('cp')
-lv2_validate = find_program('lv2_validate', native : true, required : false)
-sord_validate = find_program('sord_validate', native : true, required : false)
-lv2lint = find_program('lv2lint', required : false)
-clone = [cp, '@INPUT@', '@OUTPUT@']
-
-m_dep = cc.find_library('m')
-lv2_dep = dependency('lv2', version : '>=1.14.0')
-
-inc_dir = []
-
-inst_dir = join_paths(get_option('libdir'), 'lv2', meson.project_name())
-
-dsp_srcs = [join_paths('test', 'props.c')]
-
-c_args = ['-fvisibility=hidden',
- '-ffast-math']
-
-mod = shared_module('props', dsp_srcs,
- c_args : c_args,
- include_directories : inc_dir,
- name_prefix : '',
- dependencies : [m_dep, lv2_dep],
- install : true,
- install_dir : inst_dir)
-
-version = run_command('cat', 'VERSION').stdout().strip().split('.')
-conf_data.set('MAJOR_VERSION', version[0])
-conf_data.set('MINOR_VERSION', version[1])
-conf_data.set('MICRO_VERSION', version[2])
-
-suffix = mod.full_path().strip().split('.')[-1]
-conf_data.set('MODULE_SUFFIX', '.' + suffix)
-
-manifest_ttl = configure_file(
- input : join_paths('test', 'manifest.ttl.in'), output : 'manifest.ttl',
- configuration : conf_data,
- install : true,
- install_dir : inst_dir)
-dsp_ttl = custom_target('props_ttl',
- input : join_paths('test', 'props.ttl'),
- output : 'props.ttl',
- command : clone,
- install : true,
- install_dir : inst_dir)
-custom_target('chunk_bin',
- input : join_paths('test', 'chunk.bin'),
- output : 'chunk.bin',
- command : clone,
- install : true,
- install_dir : inst_dir)
-
-props_test = executable('props_test',
- join_paths('test', 'props_test.c'),
- c_args : c_args,
- install : false)
-
-test('Test', props_test,
- timeout : 240)
-
-if lv2_validate.found() and sord_validate.found()
- test('LV2 validate', lv2_validate,
- args : [manifest_ttl, dsp_ttl])
-endif
-
-if lv2lint.found()
- test('LV2 lint', lv2lint,
- args : ['-Ewarn',
- 'http://open-music-kontrollers.ch/lv2/props#test'])
-endif
D props.lv2/props.h => props.lv2/props.h +0 -1226
@@ 1,1226 0,0 @@
-/*
- * Copyright (c) 2015 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_PROPS_H_
-#define _LV2_PROPS_H_
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <stdlib.h>
-#include <stdatomic.h>
-#include <stdio.h>
-
-#include <lv2/lv2plug.in/ns/lv2core/lv2.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/atom/forge.h>
-#include <lv2/lv2plug.in/ns/ext/patch/patch.h>
-#include <lv2/lv2plug.in/ns/ext/state/state.h>
-
-/*****************************************************************************
- * API START
- *****************************************************************************/
-
-// structures
-typedef struct _props_def_t props_def_t;
-typedef struct _props_impl_t props_impl_t;
-typedef struct _props_dyn_t props_dyn_t;
-typedef struct _props_t props_t;
-
-typedef enum _props_dyn_ev_t {
- PROPS_DYN_EV_ADD,
- PROPS_DYN_EV_REM,
- PROPS_DYN_EV_SET
-} props_dyn_ev_t;
-
-// function callbacks
-typedef void (*props_event_cb_t)(
- void *data,
- int64_t frames,
- props_impl_t *impl);
-
-typedef void (*props_dyn_prop_cb_t)(
- void *data,
- props_dyn_ev_t ev,
- LV2_URID subj,
- LV2_URID prop,
- const LV2_Atom *body);
-
-struct _props_def_t {
- const char *property;
- const char *type;
- const char *access;
- size_t offset;
- bool hidden;
-
- uint32_t max_size;
- props_event_cb_t event_cb;
-};
-
-struct _props_impl_t {
- LV2_URID property;
- LV2_URID type;
- LV2_URID access;
-
- struct {
- uint32_t size;
- void *body;
- } value;
- struct {
- uint32_t size;
- void *body;
- } stash;
-
- const props_def_t *def;
-
- atomic_int state;
- bool stashing;
-};
-
-struct _props_dyn_t {
- props_dyn_prop_cb_t prop;
-};
-
-struct _props_t {
- struct {
- LV2_URID subject;
-
- LV2_URID patch_get;
- LV2_URID patch_set;
- LV2_URID patch_put;
- LV2_URID patch_patch;
- LV2_URID patch_wildcard;
- LV2_URID patch_add;
- LV2_URID patch_remove;
- LV2_URID patch_subject;
- LV2_URID patch_body;
- LV2_URID patch_property;
- LV2_URID patch_value;
- LV2_URID patch_writable;
- LV2_URID patch_readable;
- LV2_URID patch_sequence;
- LV2_URID patch_error;
- LV2_URID patch_ack;
-
- LV2_URID atom_int;
- LV2_URID atom_long;
- LV2_URID atom_float;
- LV2_URID atom_double;
- LV2_URID atom_bool;
- LV2_URID atom_urid;
- LV2_URID atom_path;
- LV2_URID atom_literal;
- LV2_URID atom_vector;
- LV2_URID atom_object;
- LV2_URID atom_sequence;
-
- LV2_URID state_StateChanged;
- } urid;
-
- void *data;
-
- bool stashing;
- atomic_bool restoring;
-
- uint32_t max_size;
-
- const props_dyn_t *dyn;
-
- unsigned nimpls;
- props_impl_t impls [1];
-};
-
-#define PROPS_T(PROPS, MAX_NIMPLS) \
- props_t (PROPS); \
- props_impl_t _impls [MAX_NIMPLS]
-
-// rt-safe
-static inline int
-props_init(props_t *props, const char *subject,
- const props_def_t *defs, int nimpls,
- void *value_base, void *stash_base,
- LV2_URID_Map *map, void *data);
-
-// rt-safe
-static inline void
-props_dyn(props_t *props, const props_dyn_t *dyn);
-
-// rt-safe
-static inline void
-props_idle(props_t *props, LV2_Atom_Forge *forge, uint32_t frames,
- LV2_Atom_Forge_Ref *ref);
-
-// rt-safe
-static inline int
-props_advance(props_t *props, LV2_Atom_Forge *forge, uint32_t frames,
- const LV2_Atom_Object *obj, LV2_Atom_Forge_Ref *ref);
-
-// rt-safe
-static inline void
-props_set(props_t *props, LV2_Atom_Forge *forge, uint32_t frames,
- LV2_URID property, LV2_Atom_Forge_Ref *ref);
-
-// rt-safe
-static inline void
-props_get(props_t *props, LV2_Atom_Forge *forge, uint32_t frames,
- LV2_URID property, LV2_Atom_Forge_Ref *ref);
-
-// rt-safe
-static inline void
-props_stash(props_t *props, LV2_URID property);
-
-// rt-safe
-static inline LV2_URID
-props_map(props_t *props, const char *property);
-
-// rt-safe
-static inline const char *
-props_unmap(props_t *props, LV2_URID property);
-
-// non-rt
-static inline LV2_State_Status
-props_save(props_t *props, LV2_State_Store_Function store,
- LV2_State_Handle state, uint32_t flags, const LV2_Feature *const *features);
-
-// non-rt
-static inline LV2_State_Status
-props_restore(props_t *props, LV2_State_Retrieve_Function retrieve,
- LV2_State_Handle state, uint32_t flags, const LV2_Feature *const *features);
-
-/*****************************************************************************
- * API END
- *****************************************************************************/
-
-// enumerations
-typedef enum _props_state_t {
- PROP_STATE_NONE = 0,
- PROP_STATE_LOCK = 1,
- PROP_STATE_RESTORE = 2
-} props_state_t;
-
-static inline void
-_props_impl_spin_lock(props_impl_t *impl, int from, int to)
-{
- int expected = from;
- const int desired = to;
-
- while(!atomic_compare_exchange_strong_explicit(&impl->state, &expected, desired,
- memory_order_acquire, memory_order_acquire))
- {
- // spin
- }
-}
-
-static inline bool
-_props_impl_try_lock(props_impl_t *impl, int from, int to)
-{
- int expected = from;
- const int desired = to;
-
- return atomic_compare_exchange_strong_explicit(&impl->state, &expected, desired,
- memory_order_acquire, memory_order_acquire);
-}
-
-static inline void
-_props_impl_unlock(props_impl_t *impl, int to)
-{
- atomic_store_explicit(&impl->state, to, memory_order_release);
-}
-
-static inline bool
-_props_restoring_get(props_t *props)
-{
- return atomic_exchange_explicit(&props->restoring, false, memory_order_acquire);
-}
-
-static inline void
-_props_restoring_set(props_t *props)
-{
- atomic_store_explicit(&props->restoring, true, memory_order_release);
-}
-
-static inline void
-_props_qsort(props_impl_t *A, int n)
-{
- if(n < 2)
- return;
-
- const props_impl_t *p = A;
-
- int i = -1;
- int j = n;
-
- while(true)
- {
- do {
- i += 1;
- } while(A[i].property < p->property);
-
- do {
- j -= 1;
- } while(A[j].property > p->property);
-
- if(i >= j)
- break;
-
- const props_impl_t tmp = A[i];
- A[i] = A[j];
- A[j] = tmp;
- }
-
- _props_qsort(A, j + 1);
- _props_qsort(A + j + 1, n - j - 1);
-}
-
-static inline props_impl_t *
-_props_impl_get(props_t *props, LV2_URID property)
-{
- props_impl_t *base = props->impls;
-
- for(int N = props->nimpls, half; N > 1; N -= half)
- {
- half = N/2;
- props_impl_t *dst = &base[half];
- base = (dst->property > property) ? base : dst;
- }
-
- return (base->property == property) ? base : NULL;
-}
-
-static inline LV2_Atom_Forge_Ref
-_props_patch_set(props_t *props, LV2_Atom_Forge *forge, uint32_t frames,
- props_impl_t *impl, int32_t sequence_num)
-{
- LV2_Atom_Forge_Frame obj_frame;
-
- LV2_Atom_Forge_Ref ref = lv2_atom_forge_frame_time(forge, frames);
-
- if(ref)
- ref = lv2_atom_forge_object(forge, &obj_frame, 0, props->urid.patch_set);
- {
- if(props->urid.subject) // is optional
- {
- if(ref)
- ref = lv2_atom_forge_key(forge, props->urid.patch_subject);
- if(ref)
- ref = lv2_atom_forge_urid(forge, props->urid.subject);
- }
-
- if(sequence_num) // is optional
- {
- if(ref)
- ref = lv2_atom_forge_key(forge, props->urid.patch_sequence);
- if(ref)
- ref = lv2_atom_forge_int(forge, sequence_num);
- }
-
- if(ref)
- ref = lv2_atom_forge_key(forge, props->urid.patch_property);
- if(ref)
- ref = lv2_atom_forge_urid(forge, impl->property);
-
- if(ref)
- lv2_atom_forge_key(forge, props->urid.patch_value);
- if(ref)
- ref = lv2_atom_forge_atom(forge, impl->value.size, impl->type);
- if(ref)
- ref = lv2_atom_forge_write(forge, impl->value.body, impl->value.size);
- }
- if(ref)
- lv2_atom_forge_pop(forge, &obj_frame);
-
- if(ref)
- ref = lv2_atom_forge_frame_time(forge, frames);
- if(ref)
- ref = lv2_atom_forge_object(forge, &obj_frame, 0, props->urid.state_StateChanged);
- if(ref)
- lv2_atom_forge_pop(forge, &obj_frame);
-
- return ref;
-}
-
-static inline LV2_Atom_Forge_Ref
-_props_patch_get(props_t *props, LV2_Atom_Forge *forge, uint32_t frames,
- props_impl_t *impl, int32_t sequence_num)
-{
- LV2_Atom_Forge_Frame obj_frame;
-
- LV2_Atom_Forge_Ref ref = lv2_atom_forge_frame_time(forge, frames);
-
- if(ref)
- ref = lv2_atom_forge_object(forge, &obj_frame, 0, props->urid.patch_get);
- {
- if(props->urid.subject) // is optional
- {
- if(ref)
- ref = lv2_atom_forge_key(forge, props->urid.patch_subject);
- if(ref)
- ref = lv2_atom_forge_urid(forge, props->urid.subject);
- }
-
- if(sequence_num) // is optional
- {
- if(ref)
- ref = lv2_atom_forge_key(forge, props->urid.patch_sequence);
- if(ref)
- ref = lv2_atom_forge_int(forge, sequence_num);
- }
-
- if(ref)
- ref = lv2_atom_forge_key(forge, props->urid.patch_property);
- if(ref)
- ref = lv2_atom_forge_urid(forge, impl->property);
- }
- if(ref)
- lv2_atom_forge_pop(forge, &obj_frame);
-
- return ref;
-}
-
-static inline LV2_Atom_Forge_Ref
-_props_patch_error(props_t *props, LV2_Atom_Forge *forge, uint32_t frames,
- int32_t sequence_num)
-{
- LV2_Atom_Forge_Frame obj_frame;
-
- LV2_Atom_Forge_Ref ref = lv2_atom_forge_frame_time(forge, frames);
-
- if(ref)
- ref = lv2_atom_forge_object(forge, &obj_frame, 0, props->urid.patch_error);
- {
- if(ref)
- ref = lv2_atom_forge_key(forge, props->urid.patch_sequence);
- if(ref)
- ref = lv2_atom_forge_int(forge, sequence_num);
- }
- if(ref)
- lv2_atom_forge_pop(forge, &obj_frame);
-
- return ref;
-}
-
-static inline LV2_Atom_Forge_Ref
-_props_patch_ack(props_t *props, LV2_Atom_Forge *forge, uint32_t frames,
- int32_t sequence_num)
-{
- LV2_Atom_Forge_Frame obj_frame;
-
- LV2_Atom_Forge_Ref ref = lv2_atom_forge_frame_time(forge, frames);
-
- if(ref)
- ref = lv2_atom_forge_object(forge, &obj_frame, 0, props->urid.patch_ack);
- {
- if(ref)
- ref = lv2_atom_forge_key(forge, props->urid.patch_sequence);
- if(ref)
- ref = lv2_atom_forge_int(forge, sequence_num);
- }
- if(ref)
- lv2_atom_forge_pop(forge, &obj_frame);
-
- return ref;
-}
-
-static inline void
-_props_impl_stash(props_t *props, props_impl_t *impl)
-{
- if(_props_impl_try_lock(impl, PROP_STATE_NONE, PROP_STATE_LOCK))
- {
- impl->stashing = false;
- impl->stash.size = impl->value.size;
- memcpy(impl->stash.body, impl->value.body, impl->value.size);
-
- _props_impl_unlock(impl, PROP_STATE_NONE);
- }
- else
- {
- impl->stashing = true; // try again later
- props->stashing = true;
- }
-}
-
-static inline void
-_props_impl_restore(props_t *props, LV2_Atom_Forge *forge, uint32_t frames,
- props_impl_t *impl, LV2_Atom_Forge_Ref *ref)
-{
- if(_props_impl_try_lock(impl, PROP_STATE_RESTORE, PROP_STATE_LOCK))
- {
- impl->stashing = false; // makes no sense to stash a recently restored value
- impl->value.size = impl->stash.size;
- memcpy(impl->value.body, impl->stash.body, impl->stash.size);
-
- _props_impl_unlock(impl, PROP_STATE_NONE);
-
- if(*ref && !impl->def->hidden)
- *ref = _props_patch_set(props, forge, frames, impl, 0);
-
- const props_def_t *def = impl->def;
- if(def->event_cb)
- def->event_cb(props->data, 0, impl);
- }
-}
-
-static inline void
-_props_impl_set(props_t *props, props_impl_t *impl, LV2_URID type,
- uint32_t size, const void *body)
-{
- if( (impl->type == type)
- && ( (impl->def->max_size == 0) || (size <= impl->def->max_size)) )
- {
- impl->value.size = size;
- memcpy(impl->value.body, body, size);
-
- _props_impl_stash(props, impl);
- }
-}
-
-static inline int
-_props_impl_init(props_t *props, props_impl_t *impl, const props_def_t *def,
- void *value_base, void *stash_base, LV2_URID_Map *map)
-{
- if(!def->property || !def->type)
- return 0;
-
- const LV2_URID type = map->map(map->handle, def->type);
- const LV2_URID property = map->map(map->handle, def->property);
- const LV2_URID access = def->access
- ? map->map(map->handle, def->access)
- : map->map(map->handle, LV2_PATCH__writable);
-
- if(!type || !property || !access)
- return 0;
-
- impl->property = property;
- impl->access = access;
- impl->def = def;
- impl->value.body = (uint8_t *)value_base + def->offset;
- impl->stash.body = (uint8_t *)stash_base + def->offset;
-
- uint32_t size;
- if( (type == props->urid.atom_int)
- || (type == props->urid.atom_float)
- || (type == props->urid.atom_bool)
- || (type == props->urid.atom_urid) )
- {
- size = 4;
- }
- else if((type == props->urid.atom_long)
- || (type == props->urid.atom_double) )
- {
- size = 8;
- }
- else if(type == props->urid.atom_literal)
- {
- size = sizeof(LV2_Atom_Literal_Body);
- }
- else if(type == props->urid.atom_vector)
- {
- size = sizeof(LV2_Atom_Vector_Body);
- }
- else if(type == props->urid.atom_object)
- {
- size = sizeof(LV2_Atom_Object_Body);
- }
- else if(type == props->urid.atom_sequence)
- {
- size = sizeof(LV2_Atom_Sequence_Body);
- }
- else
- {
- size = 0; // assume everything else as having size 0
- }
-
- impl->type = type;
- impl->value.size = size;
- impl->stash.size = size;
-
- atomic_init(&impl->state, PROP_STATE_NONE);
-
- // update maximal value size
- const uint32_t max_size = def->max_size
- ? def->max_size
- : size;
-
- if(max_size > props->max_size)
- {
- props->max_size = max_size;
- }
-
- return 1;
-}
-
-static inline int
-props_init(props_t *props, const char *subject,
- const props_def_t *defs, int nimpls,
- void *value_base, void *stash_base,
- LV2_URID_Map *map, void *data)
-{
- if(!props || !defs || !value_base || !stash_base || !map)
- return 0;
-
- props->nimpls = nimpls;
- props->data = data;
-
- props->urid.subject = subject ? map->map(map->handle, subject) : 0;
-
- props->urid.patch_get = map->map(map->handle, LV2_PATCH__Get);
- props->urid.patch_set = map->map(map->handle, LV2_PATCH__Set);
- props->urid.patch_put = map->map(map->handle, LV2_PATCH__Put);
- props->urid.patch_patch = map->map(map->handle, LV2_PATCH__Patch);
- props->urid.patch_wildcard = map->map(map->handle, LV2_PATCH__wildcard);
- props->urid.patch_add = map->map(map->handle, LV2_PATCH__add);
- props->urid.patch_remove = map->map(map->handle, LV2_PATCH__remove);
- props->urid.patch_subject = map->map(map->handle, LV2_PATCH__subject);
- props->urid.patch_body = map->map(map->handle, LV2_PATCH__body);
- props->urid.patch_property = map->map(map->handle, LV2_PATCH__property);
- props->urid.patch_value = map->map(map->handle, LV2_PATCH__value);
- props->urid.patch_writable = map->map(map->handle, LV2_PATCH__writable);
- props->urid.patch_readable = map->map(map->handle, LV2_PATCH__readable);
- props->urid.patch_sequence = map->map(map->handle, LV2_PATCH__sequenceNumber);
- props->urid.patch_ack = map->map(map->handle, LV2_PATCH__Ack);
- props->urid.patch_error = map->map(map->handle, LV2_PATCH__Error);
-
- props->urid.atom_int = map->map(map->handle, LV2_ATOM__Int);
- props->urid.atom_long = map->map(map->handle, LV2_ATOM__Long);
- props->urid.atom_float = map->map(map->handle, LV2_ATOM__Float);
- props->urid.atom_double = map->map(map->handle, LV2_ATOM__Double);
- props->urid.atom_bool = map->map(map->handle, LV2_ATOM__Bool);
- props->urid.atom_urid = map->map(map->handle, LV2_ATOM__URID);
- props->urid.atom_path = map->map(map->handle, LV2_ATOM__Path);
- props->urid.atom_literal = map->map(map->handle, LV2_ATOM__Literal);
- props->urid.atom_vector = map->map(map->handle, LV2_ATOM__Vector);
- props->urid.atom_object = map->map(map->handle, LV2_ATOM__Object);
- props->urid.atom_sequence = map->map(map->handle, LV2_ATOM__Sequence);
-
- props->urid.state_StateChanged = map->map(map->handle, LV2_STATE__StateChanged);
-
- atomic_init(&props->restoring, false);
-
- int status = 1;
- for(unsigned i = 0; i < props->nimpls; i++)
- {
- props_impl_t *impl = &props->impls[i];
-
- status = status
- && _props_impl_init(props, impl, &defs[i], value_base, stash_base, map);
- }
-
- _props_qsort(props->impls, props->nimpls);
-
- return status;
-}
-
-static inline void
-props_dyn(props_t *props, const props_dyn_t *dyn)
-{
- props->dyn = dyn;
-}
-
-static inline void
-props_idle(props_t *props, LV2_Atom_Forge *forge, uint32_t frames,
- LV2_Atom_Forge_Ref *ref)
-{
- if(_props_restoring_get(props))
- {
- for(unsigned i = 0; i < props->nimpls; i++)
- {
- props_impl_t *impl = &props->impls[i];
-
- _props_impl_restore(props, forge, frames, impl, ref);
- }
- }
-
- if(props->stashing)
- {
- props->stashing = false;
-
- for(unsigned i = 0; i < props->nimpls; i++)
- {
- props_impl_t *impl = &props->impls[i];
-
- if(impl->stashing)
- _props_impl_stash(props, impl);
- }
- }
-}
-
-static inline int
-props_advance(props_t *props, LV2_Atom_Forge *forge, uint32_t frames,
- const LV2_Atom_Object *obj, LV2_Atom_Forge_Ref *ref)
-{
- if(!lv2_atom_forge_is_object_type(forge, obj->atom.type))
- {
- return 0;
- }
-
- if(obj->body.otype == props->urid.patch_get)
- {
- const LV2_Atom_URID *subject = NULL;
- const LV2_Atom_URID *property = NULL;
- const LV2_Atom_Int *sequence = NULL;
-
- lv2_atom_object_get(obj,
- props->urid.patch_subject, &subject,
- props->urid.patch_property, &property,
- props->urid.patch_sequence, &sequence,
- 0);
-
- // check for a matching optional subject
- if( (subject && props->urid.subject)
- && ( (subject->atom.type != props->urid.atom_urid)
- || (subject->body != props->urid.subject) ) )
- {
- return 0;
- }
-
- int32_t sequence_num = 0;
- if(sequence && (sequence->atom.type == props->urid.atom_int))
- {
- sequence_num = sequence->body;
- }
-
- if(!property)
- {
- for(unsigned i = 0; i < props->nimpls; i++)
- {
- props_impl_t *impl = &props->impls[i];
-
- if(*ref && !impl->def->hidden)
- *ref = _props_patch_set(props, forge, frames, impl, sequence_num);
- }
-
- return 1;
- }
- else if(property->atom.type == props->urid.atom_urid)
- {
- props_impl_t *impl = _props_impl_get(props, property->body);
-
- if(impl)
- {
- if(*ref && !impl->def->hidden)
- *ref = _props_patch_set(props, forge, frames, impl, sequence_num);
-
- return 1;
- }
- else if(sequence_num)
- {
- if(*ref)
- *ref = _props_patch_error(props, forge, frames, sequence_num);
- }
- }
- else if(sequence_num)
- {
- if(*ref)
- *ref = _props_patch_error(props, forge, frames, sequence_num);
- }
- }
- else if(obj->body.otype == props->urid.patch_set)
- {
- const LV2_Atom_URID *subject = NULL;
- const LV2_Atom_URID *property = NULL;
- const LV2_Atom_Int *sequence = NULL;
- const LV2_Atom *value = NULL;
-
- lv2_atom_object_get(obj,
- props->urid.patch_subject, &subject,
- props->urid.patch_property, &property,
- props->urid.patch_sequence, &sequence,
- props->urid.patch_value, &value,
- 0);
-
- // check for a matching optional subject
- if( (subject && props->urid.subject)
- && ( (subject->atom.type != props->urid.atom_urid)
- || (subject->body != props->urid.subject) ) )
- {
- return 0;
- }
-
- int32_t sequence_num = 0;
- if(sequence && (sequence->atom.type == props->urid.atom_int))
- {
- sequence_num = sequence->body;
- }
-
- if(!property || (property->atom.type != props->urid.atom_urid) || !value)
- {
- if(sequence_num)
- {
- if(ref)
- *ref = _props_patch_error(props, forge, frames, sequence_num);
- }
-
- return 0;
- }
-
- props_impl_t *impl = _props_impl_get(props, property->body);
- if(impl)
- {
- _props_impl_set(props, impl, value->type, value->size,
- LV2_ATOM_BODY_CONST(value));
-
- // send on (e.g. to UI)
- if(*ref && !impl->def->hidden)
- *ref = _props_patch_set(props, forge, frames, impl, sequence_num);
-
- const props_def_t *def = impl->def;
- if(def->event_cb)
- def->event_cb(props->data, frames, impl);
-
- if(sequence_num)
- {
- if(*ref)
- *ref = _props_patch_ack(props, forge, frames, sequence_num);
- }
-
- return 1;
- }
- else if(props->dyn && props->dyn->prop)
- {
- const LV2_URID subj = subject ? subject->body : 0;
-
- props->dyn->prop(props->data, PROPS_DYN_EV_SET, subj, property->body, value);
-
- //TODO send ack
- }
- else if(sequence_num)
- {
- if(*ref)
- *ref = _props_patch_error(props, forge, frames, sequence_num);
- }
- }
- else if(obj->body.otype == props->urid.patch_put)
- {
- const LV2_Atom_URID *subject = NULL;
- const LV2_Atom_Int *sequence = NULL;
- const LV2_Atom_Object *body = NULL;
-
- lv2_atom_object_get(obj,
- props->urid.patch_subject, &subject,
- props->urid.patch_sequence, &sequence,
- props->urid.patch_body, &body,
- 0);
-
- // check for a matching optional subject
- if( (subject && props->urid.subject)
- && ( (subject->atom.type != props->urid.atom_urid)
- || (subject->body != props->urid.subject) ) )
- {
- return 0;
- }
-
- int32_t sequence_num = 0;
- if(sequence && (sequence->atom.type == props->urid.atom_int))
- {
- sequence_num = sequence->body;
- }
-
- if(!body || !lv2_atom_forge_is_object_type(forge, body->atom.type))
- {
- if(sequence_num)
- {
- if(*ref)
- *ref = _props_patch_error(props, forge, frames, sequence_num);
- }
-
- return 0;
- }
-
- LV2_ATOM_OBJECT_FOREACH(body, prop)
- {
- const LV2_URID property = prop->key;
- const LV2_Atom *value = &prop->value;
-
- props_impl_t *impl = _props_impl_get(props, property);
- if(impl)
- {
- _props_impl_set(props, impl, value->type, value->size,
- LV2_ATOM_BODY_CONST(value));
-
- // send on (e.g. to UI)
- if(*ref && !impl->def->hidden)
- *ref = _props_patch_set(props, forge, frames, impl, sequence_num);
-
- const props_def_t *def = impl->def;
- if(def->event_cb)
- def->event_cb(props->data, frames, impl);
- }
- else if(props->dyn && props->dyn->prop)
- {
- const LV2_URID subj = subject ? subject->body : 0;
-
- props->dyn->prop(props->data, PROPS_DYN_EV_SET, subj, property, value);
-
- //TODO send ack
- }
- }
-
- if(sequence_num)
- {
- if(*ref)
- *ref = _props_patch_ack(props, forge, frames, sequence_num);
- }
-
- return 1;
- }
- else if(obj->body.otype == props->urid.patch_patch)
- {
- const LV2_Atom_URID *subject = NULL;
- const LV2_Atom_Int *sequence = NULL;
- const LV2_Atom_Object *add = NULL;
- const LV2_Atom_Object *rem = NULL;
-
- lv2_atom_object_get(obj,
- props->urid.patch_subject, &subject,
- props->urid.patch_sequence, &sequence,
- props->urid.patch_add, &add,
- props->urid.patch_remove, &rem,
- 0);
-
- LV2_URID subj = 0;
- if(subject && (subject->atom.type == props->urid.atom_urid))
- {
- subj = subject->body;
- }
-
- int32_t sequence_num = 0;
- if(sequence && (sequence->atom.type == props->urid.atom_int))
- {
- sequence_num = sequence->body;
- }
-
- if(rem && lv2_atom_forge_is_object_type(forge, rem->atom.type))
- {
- LV2_ATOM_OBJECT_FOREACH(rem, prop)
- {
- const LV2_URID property = prop->key;
- const LV2_Atom *value = &prop->value;
-
- if(props->dyn && props->dyn->prop)
- {
- props->dyn->prop(props->data, PROPS_DYN_EV_REM, subj, property, value);
- }
- }
- }
-
- if(add && lv2_atom_forge_is_object_type(forge, add->atom.type))
- {
- LV2_ATOM_OBJECT_FOREACH(add, prop)
- {
- const LV2_URID property = prop->key;
- const LV2_Atom *value = &prop->value;
-
- if(props->dyn && props->dyn->prop)
- {
- props->dyn->prop(props->data, PROPS_DYN_EV_ADD, subj, property, value);
- }
- }
- }
-
- if(sequence_num && *ref)
- {
- *ref = _props_patch_ack(props, forge, frames, sequence_num);
- }
-
- return 1;
- }
-
- return 0; // did not handle a patch event
-}
-
-static inline void
-props_set(props_t *props, LV2_Atom_Forge *forge, uint32_t frames,
- LV2_URID property, LV2_Atom_Forge_Ref *ref)
-{
- props_impl_t *impl = _props_impl_get(props, property);
-
- if(impl)
- {
- _props_impl_stash(props, impl);
-
- if(*ref && !impl->def->hidden) //TODO use patch:sequenceNumber
- *ref = _props_patch_set(props, forge, frames, impl, 0);
- }
-}
-
-static inline void
-props_get(props_t *props, LV2_Atom_Forge *forge, uint32_t frames,
- LV2_URID property, LV2_Atom_Forge_Ref *ref)
-{
- props_impl_t *impl = _props_impl_get(props, property);
-
- if(impl)
- {
- if(*ref && !impl->def->hidden) //TODO use patch:sequenceNumber
- *ref = _props_patch_get(props, forge, frames, impl, 0);
- }
-}
-
-static inline void
-props_stash(props_t *props, LV2_URID property)
-{
- props_impl_t *impl = _props_impl_get(props, property);
-
- if(impl)
- _props_impl_stash(props, impl);
-}
-
-static inline LV2_URID
-props_map(props_t *props, const char *uri)
-{
- for(unsigned i = 0; i < props->nimpls; i++)
- {
- props_impl_t *impl = &props->impls[i];
-
- if(!strcmp(impl->def->property, uri))
- return impl->property;
- }
-
- return 0;
-}
-
-static inline const char *
-props_unmap(props_t *props, LV2_URID property)
-{
- props_impl_t *impl = _props_impl_get(props, property);
-
- if(impl)
- return impl->def->property;
-
- return NULL;
-}
-
-static inline int
-_copy_file(const char *to, const char *from)
-{
- FILE *dst = NULL;
- FILE *src = NULL;
- int ch;
-
- dst = fopen(to, "wb");
- if(!dst)
- {
- return 1;
- }
-
- src = fopen(from, "rb");
- if(!src)
- {
- fclose(dst);
-
- return 1;
- }
-
- while( (ch = fgetc(src)) != EOF)
- {
- fputc(ch, dst);
- }
-
- fclose(dst);
- fclose(src);
-
- return 0;
-}
-
-static inline void
-_free_path(const LV2_State_Free_Path *free_path, char *path)
-{
- if(free_path && free_path->free_path)
- {
- free_path->free_path(free_path->handle, path);
- }
- else
- {
- free(path);
- }
-}
-
-static inline LV2_State_Status
-props_save(props_t *props, LV2_State_Store_Function store,
- LV2_State_Handle state, uint32_t flags, const LV2_Feature *const *features)
-{
- const LV2_State_Map_Path *map_path = NULL;
- const LV2_State_Make_Path *make_path = NULL;
- const LV2_State_Free_Path *free_path = NULL;
-
- // set POD flag if not already set by host
- flags |= LV2_STATE_IS_POD;
-
- for(unsigned i = 0; features[i]; i++)
- {
- if(!strcmp(features[i]->URI, LV2_STATE__mapPath))
- {
- map_path = features[i]->data;
- }
- else if(!strcmp(features[i]->URI, LV2_STATE__makePath))
- {
- make_path = features[i]->data;
- }
- else if(!strcmp(features[i]->URI, LV2_STATE__freePath))
- {
- free_path = features[i]->data;
- }
- }
-
- void *body = malloc(props->max_size); // create memory to store widest value
- if(body)
- {
- for(unsigned i = 0; i < props->nimpls; i++)
- {
- props_impl_t *impl = &props->impls[i];
-
- if(impl->access == props->urid.patch_readable)
- continue; // skip read-only, as it makes no sense to restore them
-
- // always clear memory
- memset(body, 0x0, props->max_size);
-
- _props_impl_spin_lock(impl, PROP_STATE_NONE, PROP_STATE_LOCK);
-
- // create temporary copy of value, store() may well be blocking
- const uint32_t size = impl->stash.size;
- memcpy(body, impl->stash.body, size);
-
- _props_impl_unlock(impl, PROP_STATE_NONE);
-
- if( map_path && map_path->abstract_path
- && (impl->type == props->urid.atom_path) )
- {
- const char *path = strstr(body, "file://") == body
- ? (char *)body + 7 // skip "file://"
- : (char *)body;
-
- char *abstract = NULL;
-
- if( make_path && make_path->path
- && (strstr(path, "/tmp") == path) )
- {
- char *absolute = make_path->path(make_path->handle, basename(path));
-
- if(absolute)
- {
- if(_copy_file(absolute, path) == 0)
- {
- abstract = map_path->abstract_path(map_path->handle, absolute);
- }
-
- _free_path(free_path, absolute);
- }
- }
- else
- {
- abstract = map_path->abstract_path(map_path->handle, path);
- }
-
- if(abstract)
- {
- const uint32_t sz = strlen(abstract) + 1;
- store(state, impl->property, abstract, sz, impl->type, flags);
-
- _free_path(free_path, abstract);
- }
- }
- else // !Path
- {
- store(state, impl->property, body, size, impl->type, flags);
- }
- }
-
- free(body);
- }
-
- return LV2_STATE_SUCCESS;
-}
-
-static inline LV2_State_Status
-props_restore(props_t *props, LV2_State_Retrieve_Function retrieve,
- LV2_State_Handle state, uint32_t flags __attribute__((unused)),
- const LV2_Feature *const *features)
-{
- const LV2_State_Map_Path *map_path = NULL;
- const LV2_State_Free_Path *free_path = NULL;
-
- for(unsigned i = 0; features[i]; i++)
- {
- if(!strcmp(features[i]->URI, LV2_STATE__mapPath))
- {
- map_path = features[i]->data;
- }
- if(!strcmp(features[i]->URI, LV2_STATE__freePath))
- {
- free_path = features[i]->data;
- }
- }
-
- for(unsigned i = 0; i < props->nimpls; i++)
- {
- props_impl_t *impl = &props->impls[i];
-
- if(impl->access == props->urid.patch_readable)
- continue; // skip read-only, as it makes no sense to restore them
-
- size_t size;
- uint32_t type;
- uint32_t _flags;
- const void *body = retrieve(state, impl->property, &size, &type, &_flags);
-
- if( body
- && (type == impl->type)
- && ( (impl->def->max_size == 0) || (size <= impl->def->max_size) ) )
- {
- if( map_path && map_path->absolute_path
- && (type == props->urid.atom_path) )
- {
- char *absolute = map_path->absolute_path(map_path->handle, body);
- if(absolute)
- {
- const uint32_t sz = strlen(absolute) + 1;
-
- _props_impl_spin_lock(impl, PROP_STATE_NONE, PROP_STATE_LOCK);
-
- impl->stash.size = sz;
- memcpy(impl->stash.body, absolute, sz);
-
- _props_impl_unlock(impl, PROP_STATE_RESTORE);
-
- _free_path(free_path, absolute);
- }
- }
- else // !Path
- {
- _props_impl_spin_lock(impl, PROP_STATE_NONE, PROP_STATE_LOCK);
-
- impl->stash.size = size;
- memcpy(impl->stash.body, body, size);
-
- _props_impl_unlock(impl, PROP_STATE_RESTORE);
- }
- }
- }
-
- _props_restoring_set(props);
-
- return LV2_STATE_SUCCESS;
-}
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif // _LV2_PROPS_H_
D props.lv2/test/chunk.bin => props.lv2/test/chunk.bin +0 -0
D props.lv2/test/manifest.ttl.in => props.lv2/test/manifest.ttl.in +0 -28
@@ 1,28 0,0 @@
-# Copyright (c) 2015 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 owl: <http://www.w3.org/2002/07/owl#> .
-@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
-
-@prefix props: <http://open-music-kontrollers.ch/lv2/props#> .
-
-# Orbit Looper
-props:test
- a lv2:Plugin ;
- lv2:minorVersion @MINOR_VERSION@ ;
- lv2:microVersion @MICRO_VERSION@ ;
- lv2:binary <props@MODULE_SUFFIX@> ;
- rdfs:seeAlso <props.ttl> .
D props.lv2/test/props.c => props.lv2/test/props.c +0 -323
@@ 1,323 0,0 @@
-/*
- * Copyright (c) 2015 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.
- */
-
-#include <stdio.h>
-
-#include <props.h>
-
-#include <lv2/lv2plug.in/ns/ext/log/log.h>
-#include <lv2/lv2plug.in/ns/ext/log/logger.h>
-
-#define PROPS_PREFIX "http://open-music-kontrollers.ch/lv2/props#"
-#define PROPS_TEST_URI PROPS_PREFIX"test"
-
-#define MAX_NPROPS 7
-#define MAX_STRLEN 256
-
-typedef struct _plugstate_t plugstate_t;
-typedef struct _plughandle_t plughandle_t;
-
-struct _plugstate_t {
- int32_t val1;
- int64_t val2;
- float val3;
- double val4;
- char val5 [MAX_STRLEN];
- char val6 [MAX_STRLEN];
- uint8_t val7 [MAX_STRLEN];
-};
-
-struct _plughandle_t {
- LV2_URID_Map *map;
- LV2_Log_Log *log;
- LV2_Log_Logger logger;
- LV2_Atom_Forge forge;
- LV2_Atom_Forge_Ref ref;
-
- PROPS_T(props, MAX_NPROPS);
- plugstate_t state;
- plugstate_t stash;
-
- struct {
- LV2_URID val2;
- LV2_URID val4;
- } urid;
-
- const LV2_Atom_Sequence *event_in;
- LV2_Atom_Sequence *event_out;
-};
-
-static void
-_intercept(void *data, int64_t frames __attribute__((unused)), props_impl_t *impl)
-{
- plughandle_t *handle = data;
-
- lv2_log_trace(&handle->logger, "SET : %s\n", impl->def->property);
-}
-
-static void
-_intercept_stat1(void *data, int64_t frames, props_impl_t *impl)
-{
- plughandle_t *handle = data;
-
- _intercept(data, frames, impl);
-
- handle->state.val2 = handle->state.val1 * 2;
-
- props_set(&handle->props, &handle->forge, frames, handle->urid.val2, &handle->ref);
-}
-
-static void
-_intercept_stat3(void *data, int64_t frames, props_impl_t *impl)
-{
- plughandle_t *handle = data;
-
- _intercept(data, frames, impl);
-
- handle->state.val4 = handle->state.val3 * 2;
-
- props_set(&handle->props, &handle->forge, frames, handle->urid.val4, &handle->ref);
-}
-
-static void
-_intercept_stat6(void *data, int64_t frames, props_impl_t *impl)
-{
- plughandle_t *handle = data;
-
- _intercept(data, frames, impl);
-
- const char *path = strstr(handle->state.val6, "file://")
- ? handle->state.val6 + 7 // skip "file://"
- : handle->state.val6;
- FILE *f = fopen(path, "wb"); // create empty file
- if(f)
- fclose(f);
-}
-
-static const props_def_t defs [MAX_NPROPS] = {
- {
- .property = PROPS_PREFIX"statInt",
- .offset = offsetof(plugstate_t, val1),
- .type = LV2_ATOM__Int,
- .event_cb = _intercept_stat1,
- },
- {
- .property = PROPS_PREFIX"statLong",
- .access = LV2_PATCH__readable,
- .offset = offsetof(plugstate_t, val2),
- .type = LV2_ATOM__Long,
- .event_cb = _intercept,
- },
- {
- .property = PROPS_PREFIX"statFloat",
- .offset = offsetof(plugstate_t, val3),
- .type = LV2_ATOM__Float,
- .event_cb = _intercept_stat3,
- },
- {
- .property = PROPS_PREFIX"statDouble",
- .access = LV2_PATCH__readable,
- .offset = offsetof(plugstate_t, val4),
- .type = LV2_ATOM__Double,
- .event_cb = _intercept,
- },
- {
- .property = PROPS_PREFIX"statString",
- .offset = offsetof(plugstate_t, val5),
- .type = LV2_ATOM__String,
- .event_cb = _intercept,
- .max_size = MAX_STRLEN // strlen
- },
- {
- .property = PROPS_PREFIX"statPath",
- .offset = offsetof(plugstate_t, val6),
- .type = LV2_ATOM__Path,
- .event_cb = _intercept_stat6,
- .max_size = MAX_STRLEN // strlen
- },
- {
- .property = PROPS_PREFIX"statChunk",
- .offset = offsetof(plugstate_t, val7),
- .type = LV2_ATOM__Chunk,
- .event_cb = _intercept,
- .max_size = MAX_STRLEN // strlen
- }
-};
-
-static LV2_Handle
-instantiate(const LV2_Descriptor* descriptor,
- double rate __attribute__((unused)),
- const char *bundle_path __attribute__((unused)),
- const LV2_Feature *const *features)
-{
- plughandle_t *handle = calloc(1, sizeof(plughandle_t));
- if(!handle)
- return NULL;
-
- for(unsigned i=0; features[i]; i++)
- {
- if(!strcmp(features[i]->URI, LV2_URID__map))
- handle->map = features[i]->data;
- else if(!strcmp(features[i]->URI, LV2_LOG__log))
- handle->log = features[i]->data;
- }
-
- if(!handle->map)
- {
- fprintf(stderr,
- "%s: Host does not support urid:map\n", descriptor->URI);
- free(handle);
- return NULL;
- }
- if(!handle->log)
- {
- fprintf(stderr,
- "%s: Host does not support log:log\n", descriptor->URI);
- free(handle);
- return NULL;
- }
-
- lv2_log_logger_init(&handle->logger, handle->map, handle->log);
- lv2_atom_forge_init(&handle->forge, handle->map);
-
- if(!props_init(&handle->props, descriptor->URI,
- defs, MAX_NPROPS, &handle->state, &handle->stash,
- handle->map, handle))
- {
- lv2_log_error(&handle->logger, "failed to initialize property structure\n");
- free(handle);
- return NULL;
- }
-
- handle->urid.val2 = props_map(&handle->props, PROPS_PREFIX"statLong");
- handle->urid.val4 = props_map(&handle->props, PROPS_PREFIX"statDouble");
-
- return handle;
-}
-
-static void
-connect_port(LV2_Handle instance, uint32_t port, void *data)
-{
- plughandle_t *handle = (plughandle_t *)instance;
-
- switch(port)
- {
- case 0:
- handle->event_in = (const LV2_Atom_Sequence *)data;
- break;
- case 1:
- handle->event_out = (LV2_Atom_Sequence *)data;
- break;
- default:
- break;
- }
-}
-
-static void
-run(LV2_Handle instance, uint32_t nsamples __attribute__((unused)))
-{
- plughandle_t *handle = instance;
-
- uint32_t capacity = handle->event_out->atom.size;
- LV2_Atom_Forge_Frame frame;
- lv2_atom_forge_set_buffer(&handle->forge, (uint8_t *)handle->event_out, capacity);
- handle->ref = lv2_atom_forge_sequence_head(&handle->forge, &frame, 0);
-
- props_idle(&handle->props, &handle->forge, 0, &handle->ref);
-
- LV2_ATOM_SEQUENCE_FOREACH(handle->event_in, ev)
- {
- const LV2_Atom_Object *obj = (const LV2_Atom_Object *)&ev->body;
-
- if(handle->ref)
- props_advance(&handle->props, &handle->forge, ev->time.frames, obj, &handle->ref);
- }
-
- if(handle->ref)
- lv2_atom_forge_pop(&handle->forge, &frame);
- else
- lv2_atom_sequence_clear(handle->event_out);
-}
-
-static void
-cleanup(LV2_Handle instance)
-{
- plughandle_t *handle = instance;
-
- free(handle);
-}
-
-static LV2_State_Status
-_state_save(LV2_Handle instance, LV2_State_Store_Function store,
- LV2_State_Handle state, uint32_t flags,
- const LV2_Feature *const *features)
-{
- plughandle_t *handle = (plughandle_t *)instance;
-
- return props_save(&handle->props, store, state, flags, features);
-}
-
-static LV2_State_Status
-_state_restore(LV2_Handle instance, LV2_State_Retrieve_Function retrieve,
- LV2_State_Handle state, uint32_t flags,
- const LV2_Feature *const *features)
-{
- plughandle_t *handle = (plughandle_t *)instance;
-
- return props_restore(&handle->props, retrieve, state, flags, features);
-}
-
-LV2_State_Interface state_iface = {
- .save = _state_save,
- .restore = _state_restore
-};
-
-static const void *
-extension_data(const char *uri)
-{
- if(!strcmp(uri, LV2_STATE__interface))
- return &state_iface;
- return NULL;
-}
-
-const LV2_Descriptor props_test = {
- .URI = PROPS_TEST_URI,
- .instantiate = instantiate,
- .connect_port = connect_port,
- .activate = NULL,
- .run = run,
- .deactivate = NULL,
- .cleanup = cleanup,
- .extension_data = extension_data
-};
-
-#ifdef _WIN32
-__declspec(dllexport)
-#else
-__attribute__((visibility("default")))
-#endif
-const LV2_Descriptor*
-lv2_descriptor(uint32_t index)
-{
- switch(index)
- {
- case 0:
- return &props_test;
- default:
- return NULL;
- }
-}
D props.lv2/test/props.ttl => props.lv2/test/props.ttl +0 -151
@@ 1,151 0,0 @@
-# Copyright (c) 2015 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 foaf: <http://xmlns.com/foaf/0.1/> .
-@prefix doap: <http://usefulinc.com/ns/doap#> .
-@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
-@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
-@prefix lv2: <http://lv2plug.in/ns/lv2core#> .
-@prefix atom: <http://lv2plug.in/ns/ext/atom#> .
-@prefix urid: <http://lv2plug.in/ns/ext/urid#> .
-@prefix state: <http://lv2plug.in/ns/ext/state#> .
-@prefix patch: <http://lv2plug.in/ns/ext/patch#> .
-@prefix log: <http://lv2plug.in/ns/ext/log#> .
-@prefix units: <http://lv2plug.in/ns/extensions/units#> .
-@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
-
-@prefix omk: <http://open-music-kontrollers.ch/ventosus#> .
-@prefix proj: <http://open-music-kontrollers.ch/lv2/> .
-@prefix props: <http://open-music-kontrollers.ch/lv2/props#> .
-
-# Maintainer
-omk:me
- a foaf:Person ;
- foaf:name "Hanspeter Portner" ;
- foaf:mbox <mailto:dev@open-music-kontrollers.ch> ;
- foaf:homepage <http://open-music-kontrollers.ch> .
-
-# Project
-proj:props
- a doap:Project ;
- doap:maintainer omk:me ;
- doap:name "Props Bundle" .
-
-props:statInt
- a lv2:Parameter ;
- rdfs:range atom:Int ;
- rdfs:label "statInt" ;
- rdfs:comment "This is a 32-bit integer" ;
- units:unit units:hz ;
- lv2:minimum 0 ;
- lv2:maximum 10 .
-
-props:statLong
- a lv2:Parameter ;
- rdfs:range atom:Long ;
- rdfs:label "statLong" ;
- rdfs:comment "This is a 64-bit integer" ;
- units:unit units:khz ;
- lv2:minimum 0 ;
- lv2:maximum 20 .
-
-props:statFloat
- a lv2:Parameter ;
- rdfs:range atom:Float ;
- rdfs:label "statFloat" ;
- rdfs:comment "This is a 32-bit float" ;
- units:unit units:mhz ;
- lv2:minimum -0.5 ;
- lv2:maximum 0.5 .
-
-props:statDouble
- a lv2:Parameter ;
- rdfs:range atom:Double ;
- rdfs:label "statDouble" ;
- rdfs:comment "This is a 64-bit double" ;
- units:unit units:db ;
- lv2:minimum -1.0 ;
- lv2:maximum 1.0 .
-
-props:statString
- a lv2:Parameter ;
- rdfs:range atom:String ;
- rdfs:label "statString" ;
- rdfs:comment "This is a string" .
-
-props:statPath
- a lv2:Parameter ;
- rdfs:range atom:Path ;
- rdfs:label "statPath" ;
- rdfs:comment "This is a path" .
-
-props:statChunk
- a lv2:Parameter ;
- rdfs:range atom:Chunk;
- rdfs:label "statChunk" ;
- rdfs:comment "This is a chunk" .
-
-# Looper Test
-props:test
- a lv2:Plugin ,
- lv2:ConverterPlugin ;
- doap:name "Props Test" ;
- doap:license <https://spdx.org/licenses/Artistic-2.0> ;
- lv2:project proj:props ;
- lv2:requiredFeature urid:map, log:log, state:loadDefaultState ;
- lv2:optionalFeature lv2:isLive, lv2:hardRTCapable, state:threadSafeRestore ;
- lv2:extensionData state:interface ;
-
- lv2:port [
- # sink event port
- a lv2:InputPort ,
- atom:AtomPort ;
- atom:bufferType atom:Sequence ;
- atom:supports patch:Message ;
- lv2:index 0 ;
- lv2:symbol "event_in" ;
- lv2:name "Event Input" ;
- lv2:designation lv2:control ;
- ] , [
- # source event port
- a lv2:OutputPort ,
- atom:AtomPort ;
- atom:bufferType atom:Sequence ;
- atom:supports patch:Message ;
- lv2:index 1 ;
- lv2:symbol "event_out" ;
- lv2:name "Event Output" ;
- lv2:designation lv2:control ;
- ] ;
-
- patch:writable
- props:statInt ,
- props:statFloat ,
- props:statString ,
- props:statPath ,
- props:statChunk ;
-
- patch:readable
- props:statLong ,
- props:statDouble ;
-
- state:state [
- props:statInt 4 ;
- props:statFloat "0.4"^^xsd:float ;
- props:statString "Hello world" ;
- props:statPath <> ;
- props:statChunk "AQIDBAUGBw=="^^xsd:base64Binary ;
- ] .
D props.lv2/test/props_test.c => props.lv2/test/props_test.c +0 -647
@@ 1,647 0,0 @@
-/*
- * Copyright (c) 2015 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.
- */
-
-#include <assert.h>
-
-#include <props.h>
-
-#define MAX_URIDS 512
-#define STR_SIZE 32
-#define CHUNK_SIZE 16
-#define VEC_SIZE 13
-
-#define PROPS_PREFIX "http://open-music-kontrollers.ch/lv2/props#"
-#define PROPS_TEST_URI PROPS_PREFIX"test"
-
-typedef struct _plugstate_t plugstate_t;
-typedef struct _urid_t urid_t;
-typedef struct _handle_t handle_t;
-typedef void (*test_t)(handle_t *handle);
-typedef void *(*ser_atom_realloc_t)(void *data, void *buf, size_t size);
-typedef void (*ser_atom_free_t)(void *data, void *buf);
-
-typedef struct _ser_atom_t ser_atom_t;
-
-struct _plugstate_t {
- int32_t b32;
- int32_t i32;
- int64_t i64;
- float f32;
- double f64;
- uint32_t urid;
- char str [STR_SIZE];
- char uri [STR_SIZE];
- char path [STR_SIZE];
- uint8_t chunk [CHUNK_SIZE];
- LV2_Atom_Literal_Body lit;
- char lit_body [STR_SIZE];
- LV2_Atom_Vector_Body vec;
- int32_t vec_body [VEC_SIZE];
- LV2_Atom_Object_Body obj; //FIXME
- LV2_Atom_Sequence_Body seq; //FIXME
-};
-
-struct _urid_t {
- LV2_URID urid;
- char *uri;
-};
-
-enum {
- PROP_b32 = 0,
- PROP_i32,
- PROP_i64,
- PROP_f32,
- PROP_f64,
- PROP_urid,
- PROP_str,
- PROP_uri,
- PROP_path,
- PROP_chunk,
- PROP_lit,
- PROP_vec,
- PROP_obj,
- PROP_seq,
-
- MAX_NPROPS
-};
-
-struct _handle_t {
- PROPS_T(props, MAX_NPROPS);
- plugstate_t state;
- plugstate_t stash;
-
- LV2_URID_Map map;
-
- urid_t urids [MAX_URIDS];
- LV2_URID urid;
-};
-
-struct _ser_atom_t {
- ser_atom_realloc_t realloc;
- ser_atom_free_t free;
- void *data;
-
- size_t size;
- size_t offset;
- union {
- uint8_t *buf;
- LV2_Atom *atom;
- };
-};
-
-static LV2_Atom_Forge_Ref
-_ser_atom_sink(LV2_Atom_Forge_Sink_Handle handle, const void *buf,
- uint32_t size)
-{
- ser_atom_t *ser = handle;
- const size_t needed = ser->offset + size;
-
- while(needed > ser->size)
- {
- const size_t augmented = ser->size
- ? ser->size << 1
- : 1024;
- uint8_t *grown = ser->realloc(ser->data, ser->buf, augmented);
- if(!grown) // out-of-memory
- {
- return 0;
- }
-
- ser->buf = grown;
- ser->size = augmented;
- }
-
- const LV2_Atom_Forge_Ref ref = ser->offset + 1;
- memcpy(&ser->buf[ser->offset], buf, size);
- ser->offset += size;
-
- return ref;
-}
-
-static LV2_Atom *
-_ser_atom_deref(LV2_Atom_Forge_Sink_Handle handle, LV2_Atom_Forge_Ref ref)
-{
- ser_atom_t *ser = handle;
-
- if(!ref) // invalid reference
- {
- return NULL;
- }
-
- const size_t offset = ref - 1;
- return (LV2_Atom *)&ser->buf[offset];
-}
-
-static void *
-_ser_atom_realloc(void *data, void *buf, size_t size)
-{
- (void)data;
-
- return realloc(buf, size);
-}
-
-static void
-_ser_atom_free(void *data, void *buf)
-{
- (void)data;
-
- free(buf);
-}
-
-static int
-ser_atom_deinit(ser_atom_t *ser)
-{
- if(!ser)
- {
- return -1;
- }
-
- if(ser->buf)
- {
- ser->free(ser->data, ser->buf);
- }
-
- ser->size = 0;
- ser->offset = 0;
- ser->buf = NULL;
-
- return 0;
-}
-
-static int
-ser_atom_funcs(ser_atom_t *ser, ser_atom_realloc_t realloc,
- ser_atom_free_t free, void *data)
-{
- if(!ser || !realloc || !free || ser_atom_deinit(ser))
- {
- return -1;
- }
-
- ser->realloc = realloc;
- ser->free = free;
- ser->data = data;
-
- return 0;
-}
-
-static int
-ser_atom_init(ser_atom_t *ser)
-{
- if(!ser)
- {
- return -1;
- }
-
- ser->size = 0;
- ser->offset = 0;
- ser->buf = NULL;
-
- return ser_atom_funcs(ser, _ser_atom_realloc, _ser_atom_free, NULL);
-}
-
-#if 0
-static int
-ser_atom_reset(ser_atom_t *ser, LV2_Atom_Forge *forge)
-{
- if(!ser || !forge)
- {
- return -1;
- }
-
- lv2_atom_forge_set_sink(forge, _ser_atom_sink, _ser_atom_deref, ser);
-
- ser->offset = 0;
-
- return 0;
-}
-#endif
-
-static LV2_Atom *
-ser_atom_get(ser_atom_t *ser)
-{
- if(!ser)
- {
- return NULL;
- }
-
- return ser->atom;
-}
-
-static LV2_URID
-_map(LV2_URID_Map_Handle instance, const char *uri)
-{
- handle_t *handle = instance;
-
- urid_t *itm;
- for(itm=handle->urids; itm->urid; itm++)
- {
- if(!strcmp(itm->uri, uri))
- return itm->urid;
- }
-
- assert(handle->urid + 1 < MAX_URIDS);
-
- // create new
- itm->urid = ++handle->urid;
- itm->uri = strdup(uri);
-
- return itm->urid;
-}
-
-static const props_def_t defs [MAX_NPROPS] = {
- [PROP_b32] = {
- .property = PROPS_PREFIX"b32",
- .offset = offsetof(plugstate_t, b32),
- .type = LV2_ATOM__Bool
- },
- [PROP_i32] = {
- .property = PROPS_PREFIX"i32",
- .offset = offsetof(plugstate_t, i32),
- .type = LV2_ATOM__Int
- },
- [PROP_i64] = {
- .property = PROPS_PREFIX"i64",
- .offset = offsetof(plugstate_t, i64),
- .type = LV2_ATOM__Long
- },
- [PROP_f32] = {
- .property = PROPS_PREFIX"f32",
- .offset = offsetof(plugstate_t, f32),
- .type = LV2_ATOM__Float
- },
- [PROP_f64] = {
- .property = PROPS_PREFIX"f64",
- .offset = offsetof(plugstate_t, f64),
- .type = LV2_ATOM__Double
- },
- [PROP_urid] = {
- .property = PROPS_PREFIX"urid",
- .offset = offsetof(plugstate_t, urid),
- .type = LV2_ATOM__URID
- },
- [PROP_str] = {
- .property = PROPS_PREFIX"str",
- .offset = offsetof(plugstate_t, str),
- .type = LV2_ATOM__String,
- .max_size = STR_SIZE
- },
- [PROP_uri] = {
- .property = PROPS_PREFIX"uri",
- .offset = offsetof(plugstate_t, uri),
- .type = LV2_ATOM__URI,
- .max_size = STR_SIZE
- },
- [PROP_path] = {
- .property = PROPS_PREFIX"path",
- .offset = offsetof(plugstate_t, path),
- .type = LV2_ATOM__Path,
- .max_size = STR_SIZE
- },
- [PROP_chunk] = {
- .property = PROPS_PREFIX"chunk",
- .offset = offsetof(plugstate_t, chunk),
- .type = LV2_ATOM__Chunk,
- .max_size = CHUNK_SIZE
- },
- [PROP_lit] = {
- .property = PROPS_PREFIX"lit",
- .offset = offsetof(plugstate_t, lit),
- .type = LV2_ATOM__Literal,
- .max_size = sizeof(LV2_Atom_Literal_Body) + STR_SIZE
- },
- [PROP_vec] = {
- .property = PROPS_PREFIX"vec",
- .offset = offsetof(plugstate_t, vec),
- .type = LV2_ATOM__Literal,
- .max_size = sizeof(LV2_Atom_Vector_Body) + VEC_SIZE*sizeof(int32_t)
- },
- [PROP_obj] = {
- .property = PROPS_PREFIX"obj",
- .offset = offsetof(plugstate_t, obj),
- .type = LV2_ATOM__Object,
- .max_size = sizeof(LV2_Atom_Object_Body) + 0 //FIXME
- },
- [PROP_seq] = {
- .property = PROPS_PREFIX"seq",
- .offset = offsetof(plugstate_t, seq),
- .type = LV2_ATOM__Sequence,
- .max_size = sizeof(LV2_Atom_Sequence_Body) + 0 //FIXME
- }
-};
-
-static void
-_test_1(handle_t *handle)
-{
- assert(handle);
-
- props_t *props = &handle->props;
- plugstate_t *state = &handle->state;
- plugstate_t *stash = &handle->stash;
- LV2_URID_Map *map = &handle->map;
-
- for(unsigned i = 0; i < MAX_NPROPS; i++)
- {
- const props_def_t *def = &defs[i];
-
- const LV2_URID property = props_map(props, def->property);
- assert(property != 0);
- assert(property == map->map(map->handle, def->property));
-
- assert(strcmp(props_unmap(props, property), def->property) == 0);
-
- props_impl_t *impl = _props_impl_get(props, property);
- assert(impl);
-
- const LV2_URID type = map->map(map->handle, def->type);
- const LV2_URID access = map->map(map->handle, def->access
- ? def->access : LV2_PATCH__writable);
-
- assert(impl->property == property);
- assert(impl->type == type);
- assert(impl->access == access);
-
- assert(impl->def == def);
-
- assert(atomic_load(&impl->state) == PROP_STATE_NONE);
- assert(impl->stashing == false);
-
- switch(i)
- {
- case PROP_b32:
- {
- assert(impl->value.size == sizeof(state->b32));
- assert(impl->value.body == &state->b32);
-
- assert(impl->stash.size == sizeof(stash->b32));
- assert(impl->stash.body == &stash->b32);
- } break;
- case PROP_i32:
- {
- assert(impl->value.size == sizeof(state->i32));
- assert(impl->value.body == &state->i32);
-
- assert(impl->stash.size == sizeof(stash->i32));
- assert(impl->stash.body == &stash->i32);
- } break;
- case PROP_i64:
- {
- assert(impl->value.size == sizeof(state->i64));
- assert(impl->value.body == &state->i64);
-
- assert(impl->stash.size == sizeof(stash->i64));
- assert(impl->stash.body == &stash->i64);
- } break;
- case PROP_f32:
- {
- assert(impl->value.size == sizeof(state->f32));
- assert(impl->value.body == &state->f32);
-
- assert(impl->stash.size == sizeof(stash->f32));
- assert(impl->stash.body == &stash->f32);
- } break;
- case PROP_f64:
- {
- assert(impl->value.size == sizeof(state->f64));
- assert(impl->value.body == &state->f64);
-
- assert(impl->stash.size == sizeof(stash->f64));
- assert(impl->stash.body == &stash->f64);
- } break;
- case PROP_urid:
- {
- assert(impl->value.size == sizeof(state->urid));
- assert(impl->value.body == &state->urid);
-
- assert(impl->stash.size == sizeof(stash->urid));
- assert(impl->stash.body == &stash->urid);
- } break;
- case PROP_str:
- {
- assert(impl->value.size == 0);
- assert(impl->value.body == &state->str);
-
- assert(impl->stash.size == 0);
- assert(impl->stash.body == &stash->str);
- } break;
- case PROP_uri:
- {
- assert(impl->value.size == 0);
- assert(impl->value.body == &state->uri);
-
- assert(impl->stash.size == 0);
- assert(impl->stash.body == &stash->uri);
- } break;
- case PROP_path:
- {
- assert(impl->value.size == 0);
- assert(impl->value.body == &state->path);
-
- assert(impl->stash.size == 0);
- assert(impl->stash.body == &stash->path);
- } break;
- case PROP_chunk:
- {
- assert(impl->value.size == 0);
- assert(impl->value.body == &state->chunk);
-
- assert(impl->stash.size == 0);
- assert(impl->stash.body == &stash->chunk);
- } break;
- case PROP_lit:
- {
- assert(impl->value.size == sizeof(state->lit));
- assert(impl->value.body == &state->lit);
-
- assert(impl->stash.size == sizeof(stash->lit));
- assert(impl->stash.body == &stash->lit);
- } break;
- case PROP_vec:
- {
- assert(impl->value.size == sizeof(state->vec));
- assert(impl->value.body == &state->vec);
-
- assert(impl->stash.size == sizeof(stash->vec));
- assert(impl->stash.body == &stash->vec);
- } break;
- case PROP_obj:
- {
- assert(impl->value.size == sizeof(state->obj));
- assert(impl->value.body == &state->obj);
-
- assert(impl->stash.size == sizeof(stash->obj));
- assert(impl->stash.body == &stash->obj);
- } break;
- case PROP_seq:
- {
- assert(impl->value.size == sizeof(state->seq));
- assert(impl->value.body == &state->seq);
-
- assert(impl->stash.size == sizeof(stash->seq));
- assert(impl->stash.body == &stash->seq);
- } break;
- default:
- {
- assert(false);
- } break;
- }
- }
-}
-
-static void
-_test_2(handle_t *handle)
-{
- assert(handle);
-
- props_t *props = &handle->props;
- plugstate_t *state = &handle->state;
- plugstate_t *stash = &handle->stash;
- LV2_URID_Map *map = &handle->map;
-
- LV2_Atom_Forge forge;
- LV2_Atom_Forge_Frame frame;
- LV2_Atom_Forge_Ref ref;
- ser_atom_t ser;
-
- lv2_atom_forge_init(&forge, map);
- assert(ser_atom_init(&ser) == 0);
-
- lv2_atom_forge_set_sink(&forge, _ser_atom_sink, _ser_atom_deref, &ser);
-
- ref = lv2_atom_forge_sequence_head(&forge, &frame, 0);
- assert(ref);
-
- props_idle(props, &forge, 0, &ref);
- assert(ref);
-
- const LV2_URID property = props_map(props, defs[0].property);
- assert(property);
-
- state->b32 = true;
-
- props_set(props, &forge, 1, property, &ref);
- assert(ref);
-
- state->b32 = false;
-
- lv2_atom_forge_pop(&forge, &frame);
-
- const LV2_Atom_Sequence *seq = (const LV2_Atom_Sequence *)ser_atom_get(&ser);
- assert(seq);
-
- unsigned nevs = 0;
- LV2_ATOM_SEQUENCE_FOREACH(seq, ev)
- {
- const LV2_Atom *atom = &ev->body;
-
- assert(ev->time.frames == 1);
- assert(atom->type == forge.Object);
-
- const LV2_Atom_Object *obj = (const LV2_Atom_Object *)atom;
- assert(obj->body.id == 0);
-
- if(obj->body.otype == props->urid.state_StateChanged)
- {
- continue;
- }
-
- assert(obj->body.otype == props->urid.patch_set);
-
- unsigned nprops = 0;
- LV2_ATOM_OBJECT_FOREACH(obj, prop)
- {
- assert(prop->context == 0);
-
- if(prop->key == props->urid.patch_subject)
- {
- const LV2_Atom_URID *val = (const LV2_Atom_URID *)&prop->value;
-
- assert(val->atom.type == forge.URID);
- assert(val->atom.size == sizeof(uint32_t));
- assert(val->body == props->urid.subject);
-
- nprops |= 0x1;
- }
- else if(prop->key == props->urid.patch_property)
- {
- const LV2_Atom_URID *val = (const LV2_Atom_URID *)&prop->value;
-
- assert(val->atom.type == forge.URID);
- assert(val->atom.size == sizeof(uint32_t));
- assert(val->body == property);
-
- nprops |= 0x2;
- }
- else if(prop->key == props->urid.patch_value)
- {
- const LV2_Atom_Bool *val = (const LV2_Atom_Bool *)&prop->value;
-
- assert(val->atom.type == forge.Bool);
- assert(val->atom.size == sizeof(int32_t));
- assert(val->body == true);
-
- nprops |= 0x4;
- }
- else
- {
- assert(false);
- }
- }
- assert(nprops == 0x7);
-
- assert(props_advance(props, &forge, ev->time.frames, obj, &ref) == 1);
-
- assert(state->b32 == true);
- assert(stash->b32 == true);
-
- nevs |= 0x1;
- }
- assert(nevs == 0x1);
-
- assert(ser_atom_deinit(&ser) == 0);
-}
-
-static const test_t tests [] = {
- _test_1,
- _test_2,
- NULL
-};
-
-int
-main(int argc __attribute__((unused)), char **argv __attribute__((unused)))
-{
- static handle_t handle;
-
- for(const test_t *test = tests; *test; test++)
- {
- memset(&handle, 0, sizeof(handle));
-
- handle.map.handle = &handle;
- handle.map.map = _map;
-
- assert(props_init(&handle.props, PROPS_PREFIX"subj", defs, MAX_NPROPS,
- &handle.state, &handle.stash, &handle.map, NULL) == 1);
-
- (*test)(&handle);
- }
-
- for(urid_t *itm=handle.urids; itm->urid; itm++)
- {
- free(itm->uri);
- }
-
- return 0;
-}
D timely.lv2/.gitlab-ci.yml => timely.lv2/.gitlab-ci.yml +0 -2
@@ 1,2 0,0 @@
-include:
- - local: 'gitlab-ci/generic.yml'
D timely.lv2/COPYING => timely.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 timely.lv2/README.md => timely.lv2/README.md +0 -20
@@ 1,20 0,0 @@
-# Timely.lv2
-
-## Utility header for time-based LV2 plugins
-
-### License
-
-Copyright (c) 2015 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 timely.lv2/VERSION => timely.lv2/VERSION +0 -1
D timely.lv2/gitlab-ci/generic.yml => timely.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 timely.lv2/meson.build => timely.lv2/meson.build +0 -67
@@ 1,67 0,0 @@
-project('timely.lv2', 'c', default_options : [
- 'buildtype=release',
- 'warning_level=3',
- 'werror=false',
- 'b_lto=false',
- 'c_std=c11'])
-
-add_project_arguments('-D_GNU_SOURCE', language : 'c')
-
-conf_data = configuration_data()
-cc = meson.get_compiler('c')
-
-cp = find_program('cp')
-lv2_validate = find_program('lv2_validate', native : true, required : false)
-sord_validate = find_program('sord_validate', native : true, required : false)
-lv2lint = find_program('lv2lint', required : false)
-clone = [cp, '@INPUT@', '@OUTPUT@']
-
-m_dep = cc.find_library('m')
-lv2_dep = dependency('lv2', version : '>=1.14.0')
-
-inc_dir = []
-
-inst_dir = join_paths(get_option('libdir'), 'lv2', meson.project_name())
-
-dsp_srcs = [join_paths('test', 'timely.c')]
-
-c_args = ['-fvisibility=hidden',
- '-ffast-math']
-
-mod = shared_module('timely', dsp_srcs,
- c_args : c_args,
- include_directories : inc_dir,
- name_prefix : '',
- dependencies : [m_dep, lv2_dep],
- install : true,
- install_dir : inst_dir)
-
-version = run_command('cat', 'VERSION').stdout().strip().split('.')
-conf_data.set('MAJOR_VERSION', version[0])
-conf_data.set('MINOR_VERSION', version[1])
-conf_data.set('MICRO_VERSION', version[2])
-
-suffix = mod.full_path().strip().split('.')[-1]
-conf_data.set('MODULE_SUFFIX', '.' + suffix)
-
-manifest_ttl = configure_file(input : join_paths('test', 'manifest.ttl.in'), output : 'manifest.ttl',
- configuration : conf_data,
- install : true,
- install_dir : inst_dir)
-dsp_ttl = custom_target('timely_ttl',
- input : join_paths('test', 'timely.ttl'),
- output : 'timely.ttl',
- command : clone,
- install : true,
- install_dir : inst_dir)
-
-if lv2_validate.found() and sord_validate.found()
- test('LV2 validate', lv2_validate,
- args : [manifest_ttl, dsp_ttl])
-endif
-
-if lv2lint.found()
- test('LV2 lint', lv2lint,
- args : ['-Ewarn',
- 'http://open-music-kontrollers.ch/lv2/timely#test'])
-endif
D timely.lv2/test/manifest.ttl.in => timely.lv2/test/manifest.ttl.in +0 -28
@@ 1,28 0,0 @@
-# Copyright (c) 2015 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 owl: <http://www.w3.org/2002/07/owl#> .
-@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
-
-@prefix timely: <http://open-music-kontrollers.ch/lv2/timely#> .
-
-# Orbit Looper
-timely:test
- a lv2:Plugin ;
- lv2:minorVersion @MINOR_VERSION@ ;
- lv2:microVersion @MICRO_VERSION@ ;
- lv2:binary <timely@MODULE_SUFFIX@> ;
- rdfs:seeAlso <timely.ttl> .
D timely.lv2/test/timely.c => timely.lv2/test/timely.c +0 -218
@@ 1,218 0,0 @@
-/*
- * Copyright (c) 2015 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.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <inttypes.h>
-
-#include <timely.h>
-
-#include <lv2/lv2plug.in/ns/ext/log/log.h>
-#include <lv2/lv2plug.in/ns/ext/log/logger.h>
-
-#define TIMELY_PREFIX "http://open-music-kontrollers.ch/lv2/timely#"
-#define TIMELY_TEST_URI TIMELY_PREFIX"test"
-
-typedef struct _plughandle_t plughandle_t;
-
-struct _plughandle_t {
- LV2_URID_Map *map;
- LV2_Log_Log *log;
- LV2_Log_Logger logger;
- timely_t timely;
-
-
- const LV2_Atom_Sequence *event_in;
-};
-
-static void
-_timely_cb(timely_t *timely, int64_t frames, LV2_URID type, void *data)
-{
- plughandle_t *handle = data;
-
- const int64_t frame = TIMELY_FRAME(timely);
-
- if(type == TIMELY_URI_BAR_BEAT(timely))
- {
- const float bar_beat = TIMELY_BAR_BEAT_RAW(timely);
- lv2_log_trace(&handle->logger, "0x%08"PRIx64" %4"PRIi64" time:barBeat %f\n",
- frame, frames, bar_beat);
- }
- else if(type == TIMELY_URI_BAR(timely))
- {
- const int64_t bar = TIMELY_BAR(timely);
- lv2_log_trace(&handle->logger, "0x%08"PRIx64" %4"PRIi64" time:bar %"PRIi64"\n",
- frame, frames, bar);
- }
- else if(type == TIMELY_URI_BEAT_UNIT(timely))
- {
- const int32_t beat_unit = TIMELY_BEAT_UNIT(timely);
- lv2_log_trace(&handle->logger, "0x%08"PRIx64" %4"PRIi64" time:beatUnit %"PRIi32"\n",
- frame, frames, beat_unit);
- }
- else if(type == TIMELY_URI_BEATS_PER_BAR(timely))
- {
- const float bpb = TIMELY_BEATS_PER_BAR(timely);
- lv2_log_trace(&handle->logger, "0x%08"PRIx64" %4"PRIi64" time:beatsPerBar %f\n",
- frame, frames, bpb);
- }
- else if(type == TIMELY_URI_BEATS_PER_MINUTE(timely))
- {
- const float bpm = TIMELY_BEATS_PER_MINUTE(timely);
- lv2_log_trace(&handle->logger, "0x%08"PRIx64" %4"PRIi64" time:beatsPerMinute %f\n",
- frame, frames, bpm);
- }
- else if(type == TIMELY_URI_FRAME(timely))
- {
- /*
- lv2_log_trace(&handle->logger, "0x%08"PRIx64" %4"PRIi64" time:frame %"PRIi64"\n",
- frame, frames, frame);
- */
- }
- else if(type == TIMELY_URI_FRAMES_PER_SECOND(timely))
- {
- const float fps = TIMELY_FRAMES_PER_SECOND(timely);
- lv2_log_trace(&handle->logger, "0x%08"PRIx64" %4"PRIi64" time:framesPerSecond %f\n",
- frame, frames, fps);
- }
- else if(type == TIMELY_URI_SPEED(timely))
- {
- const float speed = TIMELY_SPEED(timely);
- lv2_log_trace(&handle->logger, "0x%08"PRIx64" %4"PRIi64" time:speed %f\n",
- frame, frames, speed);
- }
-}
-
-static LV2_Handle
-instantiate(const LV2_Descriptor* descriptor, double rate,
- const char *bundle_path __attribute__((unused)),
- const LV2_Feature *const *features)
-{
- plughandle_t *handle = calloc(1, sizeof(plughandle_t));
- if(!handle)
- return NULL;
-
- for(unsigned i=0; features[i]; i++)
- {
- if(!strcmp(features[i]->URI, LV2_URID__map))
- handle->map = features[i]->data;
- else if(!strcmp(features[i]->URI, LV2_LOG__log))
- handle->log = features[i]->data;
- }
-
- if(!handle->map)
- {
- fprintf(stderr,
- "%s: Host does not support urid:map\n", descriptor->URI);
- free(handle);
- return NULL;
- }
- if(!handle->log)
- {
- fprintf(stderr,
- "%s: Host does not support log:log\n", descriptor->URI);
- free(handle);
- return NULL;
- }
-
- lv2_log_logger_init(&handle->logger, handle->map, handle->log);
-
- timely_mask_t mask = TIMELY_MASK_BAR_BEAT
- | TIMELY_MASK_BAR
- | TIMELY_MASK_BEAT_UNIT
- | TIMELY_MASK_BEATS_PER_BAR
- | TIMELY_MASK_BEATS_PER_MINUTE
- //| TIMELY_MASK_FRAME
- | TIMELY_MASK_FRAMES_PER_SECOND
- | TIMELY_MASK_SPEED
- | TIMELY_MASK_BAR_BEAT_WHOLE
- | TIMELY_MASK_BAR_WHOLE;
- timely_init(&handle->timely, handle->map, rate, mask, _timely_cb, handle);
- timely_set_multiplier(&handle->timely, 1.f);
-
- return handle;
-}
-
-static void
-connect_port(LV2_Handle instance, uint32_t port, void *data)
-{
- plughandle_t *handle = (plughandle_t *)instance;
-
- switch(port)
- {
- case 0:
- handle->event_in = (const LV2_Atom_Sequence *)data;
- break;
- default:
- break;
- }
-}
-
-static void
-run(LV2_Handle instance, uint32_t nsamples)
-{
- plughandle_t *handle = instance;
- int64_t from = 0;
-
- LV2_ATOM_SEQUENCE_FOREACH(handle->event_in, ev)
- {
- const int64_t to = ev->time.frames;
- const LV2_Atom_Object *obj = (const LV2_Atom_Object *)&ev->body;
-
- const int handled = timely_advance(&handle->timely, obj, from, to);
- (void)handled;
- from = to;
- }
-
- timely_advance(&handle->timely, NULL, from, nsamples);
-}
-
-static void
-cleanup(LV2_Handle instance)
-{
- plughandle_t *handle = instance;
-
- free(handle);
-}
-
-const LV2_Descriptor timely_test = {
- .URI = TIMELY_TEST_URI,
- .instantiate = instantiate,
- .connect_port = connect_port,
- .activate = NULL,
- .run = run,
- .deactivate = NULL,
- .cleanup = cleanup,
- .extension_data = NULL
-};
-
-#ifdef _WIN32
-__declspec(dllexport)
-#else
-__attribute__((visibility("default")))
-#endif
-const LV2_Descriptor*
-lv2_descriptor(uint32_t index)
-{
- switch(index)
- {
- case 0:
- return &timely_test;
- default:
- return NULL;
- }
-}
D timely.lv2/test/timely.ttl => timely.lv2/test/timely.ttl +0 -65
@@ 1,65 0,0 @@
-# Copyright (c) 2015 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 foaf: <http://xmlns.com/foaf/0.1/> .
-@prefix doap: <http://usefulinc.com/ns/doap#> .
-@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
-@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
-@prefix lv2: <http://lv2plug.in/ns/lv2core#> .
-@prefix atom: <http://lv2plug.in/ns/ext/atom#> .
-@prefix urid: <http://lv2plug.in/ns/ext/urid#> .
-@prefix time: <http://lv2plug.in/ns/ext/time#> .
-@prefix log: <http://lv2plug.in/ns/ext/log#> .
-
-@prefix lic: <http://opensource.org/licenses/> .
-@prefix omk: <http://open-music-kontrollers.ch/ventosus#> .
-@prefix proj: <http://open-music-kontrollers.ch/lv2/> .
-@prefix timely: <http://open-music-kontrollers.ch/lv2/timely#> .
-
-# Maintainer
-omk:me
- a foaf:Person ;
- foaf:name "Hanspeter Portner" ;
- foaf:mbox <mailto:dev@open-music-kontrollers.ch> ;
- foaf:homepage <http://open-music-kontrollers.ch> .
-
-# Project
-proj:timely
- a doap:Project ;
- doap:maintainer omk:me ;
- doap:name "Timely Bundle" .
-
-# Looper Test
-timely:test
- a lv2:Plugin ,
- lv2:ConverterPlugin ;
- doap:name "Timely Test" ;
- doap:license lic:Artistic-2.0 ;
- lv2:project proj:timely ;
- lv2:requiredFeature urid:map, log:log ;
- lv2:optionalFeature lv2:isLive, lv2:hardRTCapable ;
-
- lv2:port [
- # sink event port
- a lv2:InputPort ,
- atom:AtomPort ;
- atom:bufferType atom:Sequence ;
- atom:supports time:Position ;
- lv2:index 0 ;
- lv2:symbol "event_in" ;
- lv2:name "Event Input" ;
- lv2:designation lv2:control ;
- ] .
D timely.lv2/timely.h => timely.lv2/timely.h +0 -404
@@ 1,404 0,0 @@
-/*
- * Copyright (c) 2015 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_TIMELY_H_
-#define _LV2_TIMELY_H_
-
-#include <math.h>
-
-#include <lv2/lv2plug.in/ns/lv2core/lv2.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/atom/forge.h>
-#include <lv2/lv2plug.in/ns/ext/time/time.h>
-
-typedef struct _timely_t timely_t;
-typedef void (*timely_cb_t)(timely_t *timely, int64_t frames, LV2_URID type,
- void *data);
-
-typedef enum _timely_mask_t {
- TIMELY_MASK_BAR_BEAT = (1 << 0),
- TIMELY_MASK_BAR = (1 << 1),
- TIMELY_MASK_BEAT_UNIT = (1 << 2),
- TIMELY_MASK_BEATS_PER_BAR = (1 << 3),
- TIMELY_MASK_BEATS_PER_MINUTE = (1 << 4),
- TIMELY_MASK_FRAME = (1 << 5),
- TIMELY_MASK_FRAMES_PER_SECOND = (1 << 6),
- TIMELY_MASK_SPEED = (1 << 7),
- TIMELY_MASK_BAR_BEAT_WHOLE = (1 << 8),
- TIMELY_MASK_BAR_WHOLE = (1 << 9)
-} timely_mask_t;
-
-struct _timely_t {
- struct {
- LV2_URID atom_object;
- LV2_URID atom_blank;
- LV2_URID atom_resource;
-
- LV2_URID time_position;
- LV2_URID time_barBeat;
- LV2_URID time_bar;
- LV2_URID time_beatUnit;
- LV2_URID time_beatsPerBar;
- LV2_URID time_beatsPerMinute;
- LV2_URID time_frame;
- LV2_URID time_framesPerSecond;
- LV2_URID time_speed;
- } urid;
-
- struct {
- float bar_beat;
- int64_t bar;
-
- int32_t beat_unit;
- float beats_per_bar;
- float beats_per_minute;
-
- int64_t frame;
- float frames_per_second;
-
- float speed;
- } pos;
-
- float multiplier;
-
- double frames_per_beat;
- double frames_per_bar;
-
- struct {
- double beat;
- double bar;
- } offset;
-
- bool first;
- timely_mask_t mask;
- timely_cb_t cb;
- void *data;
-};
-
-#define TIMELY_URI_BAR_BEAT(timely) ((timely)->urid.time_barBeat)
-#define TIMELY_URI_BAR(timely) ((timely)->urid.time_bar)
-#define TIMELY_URI_BEAT_UNIT(timely) ((timely)->urid.time_beatUnit)
-#define TIMELY_URI_BEATS_PER_BAR(timely) ((timely)->urid.time_beatsPerBar)
-#define TIMELY_URI_BEATS_PER_MINUTE(timely) ((timely)->urid.time_beatsPerMinute)
-#define TIMELY_URI_FRAME(timely) ((timely)->urid.time_frame)
-#define TIMELY_URI_FRAMES_PER_SECOND(timely) ((timely)->urid.time_framesPerSecond)
-#define TIMELY_URI_SPEED(timely) ((timely)->urid.time_speed)
-
-#define TIMELY_BAR_BEAT_RAW(timely) ((timely)->pos.bar_beat)
-#define TIMELY_BAR_BEAT(timely) (floor((timely)->pos.bar_beat) \
- + (timely)->offset.beat / (timely)->frames_per_beat)
-#define TIMELY_BAR(timely) ((timely)->pos.bar)
-#define TIMELY_BEAT_UNIT(timely) ((timely)->pos.beat_unit)
-#define TIMELY_BEATS_PER_BAR(timely) ((timely)->pos.beats_per_bar)
-#define TIMELY_BEATS_PER_MINUTE(timely) ((timely)->pos.beats_per_minute)
-#define TIMELY_FRAME(timely) ((timely)->pos.frame)
-#define TIMELY_FRAMES_PER_SECOND(timely) ((timely)->pos.frames_per_second)
-#define TIMELY_SPEED(timely) ((timely)->pos.speed)
-
-#define TIMELY_FRAMES_PER_BEAT(timely) ((timely)->frames_per_beat)
-#define TIMELY_FRAMES_PER_BAR(timely) ((timely)->frames_per_bar)
-
-static inline void
-_timely_deatomize_body(timely_t *timely, int64_t frames, uint32_t size,
- const LV2_Atom_Object_Body *body)
-{
- const LV2_Atom_Float *bar_beat = NULL;
- const LV2_Atom_Long *bar = NULL;
- const LV2_Atom_Int *beat_unit = NULL;
- const LV2_Atom_Float *beats_per_bar = NULL;
- const LV2_Atom_Float *beats_per_minute = NULL;
- const LV2_Atom_Long *frame = NULL;
- const LV2_Atom_Float *frames_per_second = NULL;
- const LV2_Atom_Float *speed = NULL;
-
- lv2_atom_object_body_get(size, body,
- timely->urid.time_barBeat, &bar_beat,
- timely->urid.time_bar, &bar,
- timely->urid.time_beatUnit, &beat_unit,
- timely->urid.time_beatsPerBar, &beats_per_bar,
- timely->urid.time_beatsPerMinute, &beats_per_minute,
- timely->urid.time_frame, &frame,
- timely->urid.time_framesPerSecond, &frames_per_second,
- timely->urid.time_speed, &speed,
- 0);
-
- // send speed first upon transport stop
- if(speed && (speed->body != timely->pos.speed) && (speed->body == 0.f) )
- {
- timely->pos.speed = speed->body;
- if(timely->mask & TIMELY_MASK_SPEED)
- timely->cb(timely, frames, timely->urid.time_speed, timely->data);
- }
-
- if(beat_unit)
- {
- const int32_t _beat_unit = beat_unit->body * timely->multiplier;
- if(_beat_unit != timely->pos.beat_unit)
- {
- timely->pos.beat_unit = _beat_unit;
- if(timely->mask & TIMELY_MASK_BEAT_UNIT)
- timely->cb(timely, frames, timely->urid.time_beatUnit, timely->data);
- }
- }
-
- if(beats_per_bar)
- {
- const float _beats_per_bar = beats_per_bar->body * timely->multiplier;
- if(_beats_per_bar != timely->pos.beats_per_bar)
- {
- timely->pos.beats_per_bar = _beats_per_bar;
- if(timely->mask & TIMELY_MASK_BEATS_PER_BAR)
- timely->cb(timely, frames, timely->urid.time_beatsPerBar, timely->data);
- }
- }
-
- if(beats_per_minute && (beats_per_minute->body != timely->pos.beats_per_minute) )
- {
- timely->pos.beats_per_minute = beats_per_minute->body;
- if(timely->mask & TIMELY_MASK_BEATS_PER_MINUTE)
- timely->cb(timely, frames, timely->urid.time_beatsPerMinute, timely->data);
- }
-
- if(frame && (frame->body != timely->pos.frame) )
- {
- timely->pos.frame = frame->body;
- if(timely->mask & TIMELY_MASK_FRAME)
- timely->cb(timely, frames, timely->urid.time_frame, timely->data);
- }
-
- if(frames_per_second && (frames_per_second->body != timely->pos.frames_per_second) )
- {
- timely->pos.frames_per_second = frames_per_second->body;
- if(timely->mask & TIMELY_MASK_FRAMES_PER_SECOND)
- timely->cb(timely, frames, timely->urid.time_framesPerSecond, timely->data);
- }
-
- if(bar && (bar->body != timely->pos.bar) )
- {
- timely->pos.bar = bar->body;
- if(timely->mask & TIMELY_MASK_BAR)
- timely->cb(timely, frames, timely->urid.time_bar, timely->data);
- }
-
- if(bar_beat)
- {
- const float _bar_beat = bar_beat->body * timely->multiplier;
- if(_bar_beat != timely->pos.bar_beat)
- {
- timely->pos.bar_beat = _bar_beat;
- if(timely->mask & TIMELY_MASK_BAR_BEAT)
- timely->cb(timely, frames, timely->urid.time_barBeat, timely->data);
- }
- }
-
- // send speed last upon transport start
- if(speed && (speed->body != timely->pos.speed) && (speed->body != 0.f) )
- {
- timely->pos.speed = speed->body;
- if(timely->mask & TIMELY_MASK_SPEED)
- timely->cb(timely, frames, timely->urid.time_speed, timely->data);
- }
-}
-
-static inline void
-_timely_refresh(timely_t *timely)
-{
- const float speed = (timely->pos.speed != 0.f)
- ? timely->pos.speed
- : 1.f; // prevent divisions through zero later on
-
- timely->frames_per_beat = 240.0 * timely->pos.frames_per_second
- / (timely->pos.beats_per_minute * timely->pos.beat_unit * speed);
- timely->frames_per_bar = timely->frames_per_beat * timely->pos.beats_per_bar;
-
- // bar
- timely->offset.bar = timely->pos.bar_beat * timely->frames_per_beat;
-
- // beat
- double integral;
- double beat_beat = modf(timely->pos.bar_beat, &integral);
- (void)integral;
- timely->offset.beat = beat_beat * timely->frames_per_beat;
-}
-
-static inline void
-timely_init(timely_t *timely, LV2_URID_Map *map, double rate,
- timely_mask_t mask, timely_cb_t cb, void *data)
-{
- assert(cb != NULL);
-
- timely->mask = mask;
- timely->cb = cb;
- timely->data = data;
-
- timely->urid.atom_object = map->map(map->handle, LV2_ATOM__Object);
- timely->urid.atom_blank = map->map(map->handle, LV2_ATOM__Blank);
- timely->urid.atom_resource = map->map(map->handle, LV2_ATOM__Resource);
- timely->urid.time_position = map->map(map->handle, LV2_TIME__Position);
- timely->urid.time_barBeat = map->map(map->handle, LV2_TIME__barBeat);
- timely->urid.time_bar = map->map(map->handle, LV2_TIME__bar);
- timely->urid.time_beatUnit = map->map(map->handle, LV2_TIME__beatUnit);
- timely->urid.time_beatsPerBar = map->map(map->handle, LV2_TIME__beatsPerBar);
- timely->urid.time_beatsPerMinute = map->map(map->handle, LV2_TIME__beatsPerMinute);
- timely->urid.time_frame = map->map(map->handle, LV2_TIME__frame);
- timely->urid.time_framesPerSecond = map->map(map->handle, LV2_TIME__framesPerSecond);
- timely->urid.time_speed = map->map(map->handle, LV2_TIME__speed);
-
- timely->multiplier = 1.f;
-
- timely->pos.speed = 0.f;
- timely->pos.bar_beat = 0.f;
- timely->pos.bar = 0;
- timely->pos.beat_unit = 4;
- timely->pos.beats_per_bar = 4.f;
- timely->pos.beats_per_minute = 120.f;
- timely->pos.frame = 0;
- timely->pos.frames_per_second = rate;
-
- _timely_refresh(timely);
-
- timely->first = true;
-}
-
-static inline void
-timely_set_multiplier(timely_t *timely, float multiplier)
-{
- const float mul = multiplier / timely->multiplier;
-
- timely->pos.bar_beat *= mul;
- timely->pos.beat_unit *= mul;
- timely->pos.beats_per_bar *= mul;
-
- timely->multiplier = multiplier;
-
- _timely_refresh(timely);
-
- timely->first = true;
-}
-
-static inline int
-timely_advance_body(timely_t *timely, uint32_t size, uint32_t type,
- const LV2_Atom_Object_Body *body, uint32_t from, uint32_t to)
-{
- if(timely->first)
- {
- timely->first = false;
-
- // send initial values
- if(timely->mask & TIMELY_MASK_SPEED)
- timely->cb(timely, 0, timely->urid.time_speed, timely->data);
-
- if(timely->mask & TIMELY_MASK_BEAT_UNIT)
- timely->cb(timely, 0, timely->urid.time_beatUnit, timely->data);
-
- if(timely->mask & TIMELY_MASK_BEATS_PER_BAR)
- timely->cb(timely, 0, timely->urid.time_beatsPerBar, timely->data);
-
- if(timely->mask & TIMELY_MASK_BEATS_PER_MINUTE)
- timely->cb(timely, 0, timely->urid.time_beatsPerMinute, timely->data);
-
- if(timely->mask & TIMELY_MASK_FRAME)
- timely->cb(timely, 0, timely->urid.time_frame, timely->data);
-
- if(timely->mask & TIMELY_MASK_FRAMES_PER_SECOND)
- timely->cb(timely, 0, timely->urid.time_framesPerSecond, timely->data);
-
- if(timely->mask & TIMELY_MASK_BAR)
- timely->cb(timely, 0, timely->urid.time_bar, timely->data);
-
- if(timely->mask & TIMELY_MASK_BAR_BEAT)
- timely->cb(timely, 0, timely->urid.time_barBeat, timely->data);
- }
-
- // are we rolling?
- if(timely->pos.speed != 0.f)
- {
- if( (timely->offset.bar == 0) && (timely->pos.bar == 0) )
- {
- if(timely->mask & (TIMELY_MASK_BAR | TIMELY_MASK_BAR_WHOLE) )
- timely->cb(timely, from, timely->urid.time_bar, timely->data);
- }
-
- if( (timely->offset.beat == 0) && (timely->pos.bar_beat == 0) )
- {
- if(timely->mask & (TIMELY_MASK_BAR_BEAT | TIMELY_MASK_BAR_BEAT_WHOLE) )
- timely->cb(timely, from, timely->urid.time_barBeat, timely->data);
- }
-
- unsigned update_frame = to;
- for(unsigned i=from; i<to; i++)
- {
- if(timely->offset.bar >= timely->frames_per_bar)
- {
- timely->pos.bar += 1;
- timely->offset.bar -= timely->frames_per_bar;
-
- if(timely->mask & TIMELY_MASK_FRAME)
- timely->cb(timely, (update_frame = i), timely->urid.time_frame, timely->data);
-
- if(timely->mask & TIMELY_MASK_BAR_WHOLE)
- timely->cb(timely, i, timely->urid.time_bar, timely->data);
- }
-
- if( (timely->offset.beat >= timely->frames_per_beat) )
- {
- timely->pos.bar_beat = floor(timely->pos.bar_beat) + 1;
- timely->offset.beat -= timely->frames_per_beat;
-
- if(timely->pos.bar_beat >= timely->pos.beats_per_bar)
- timely->pos.bar_beat -= timely->pos.beats_per_bar;
-
- if( (timely->mask & TIMELY_MASK_FRAME) && (update_frame != i) )
- timely->cb(timely, (update_frame = i), timely->urid.time_frame, timely->data);
-
- if(timely->mask & TIMELY_MASK_BAR_BEAT_WHOLE)
- timely->cb(timely, i, timely->urid.time_barBeat, timely->data);
- }
-
- timely->offset.bar += 1;
- timely->offset.beat += 1;
- timely->pos.frame += 1;
- }
- }
-
- // is this a time position event?
- if( ( (type == timely->urid.atom_object)
- || (type == timely->urid.atom_blank)
- || (type == timely->urid.atom_resource) )
- && body && (body->otype == timely->urid.time_position) )
- {
- _timely_deatomize_body(timely, to, size, body);
- _timely_refresh(timely);
-
- return 1; // handled a time position event
- }
-
- return 0; // did not handle a time position event
-}
-
-static inline int
-timely_advance(timely_t *timely, const LV2_Atom_Object *obj,
- uint32_t from, uint32_t to)
-{
- if(obj)
- return timely_advance_body(timely, obj->atom.size, obj->atom.type, &obj->body, from, to);
-
- return timely_advance_body(timely, 0, 0, NULL, from, to);
-}
-
-#endif // _LV2_TIMELY_H_
D varchunk/.gitlab-ci.yml => varchunk/.gitlab-ci.yml +0 -2
@@ 1,2 0,0 @@
-include:
- - local: 'gitlab-ci/generic.yml'
D varchunk/COPYING => varchunk/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 varchunk/README.md => varchunk/README.md +0 -112
@@ 1,112 0,0 @@
-# Varchunk
-
-## Ringbuffer optimized for realtime event handling
-
-### Properties
-
-* Is realtime-safe
-* Is lock-free
-* Supports variably sized chunks
-* Supports contiguous memory chunks
-* Supports zero copy operation
-* Uses a simplistic API
-
-### Build Status
-
-[![build status](https://gitlab.com/OpenMusicKontrollers/varchunk/badges/master/build.svg)](https://gitlab.com/OpenMusicKontrollers/varchunk/commits/master)
-
-### Build / test
-
- git clone https://git.open-music-kontrollers.ch/lad/varchunk
- cd varchunk
- meson build
- cd build
- ninja -j4
- ninja test
-
-### Usage
-
- #include <pthread.h>
- #include <varchunk.h>
-
- static void *
- producer_main(void *arg)
- {
- varchunk_t *varchunk = arg;
- void *ptr;
- const size_t towrite = sizeof(uint32_t);
- uint32_t counter = 0;
-
- while(counter <= 1000000)
- {
- if( (ptr = varchunk_write_request(varchunk, towrite)) )
- {
- // write 'towrite' bytes to 'ptr'
- *(uint32_t *)ptr = counter++;
- varchunk_write_advance(varchunk, towrite);
- }
- }
-
- return NULL;
- }
-
- static void *
- consumer_main(void *arg)
- {
- varchunk_t *varchunk = arg;
- const void *ptr;
- size_t toread;
-
- while(1)
- {
- if( (ptr = varchunk_read_request(varchunk, &toread)) )
- {
- // read 'toread' bytes from 'ptr'
- if(*(uint32_t *)ptr >= 1000000)
- break;
- varchunk_read_advance(varchunk);
- }
- }
-
- return NULL;
- }
-
- int
- main(int argc, char **argv)
- {
- if(!varchunk_is_lock_free())
- return -1;
-
- pthread_t producer;
- pthread_t consumer;
- varchunk_t *varchunk = varchunk_new(8192, true);
- if(!varchunk)
- return -1;
-
- pthread_create(&consumer, NULL, consumer_main, varchunk);
- pthread_create(&producer, NULL, producer_main, varchunk);
-
- pthread_join(producer, NULL);
- pthread_join(consumer, NULL);
-
- varchunk_free(varchunk);
-
- return 0;
- }
-
-### License
-
-Copyright (c) 2015-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 varchunk/VERSION => varchunk/VERSION +0 -1
D varchunk/gitlab-ci/generic.yml => varchunk/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 varchunk/meson.build => varchunk/meson.build +0 -30
@@ 1,30 0,0 @@
-project('varchunk', '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')
-
-thread_dep = dependency('threads')
-deps = [thread_dep]
-
-if host_machine.system() == 'linux'
- rt_dep = cc.find_library('rt')
- deps += rt_dep
-endif
-
-test_varchunk = executable('test_varchunk',
- 'test_varchunk.c',
- dependencies : deps,
- install : false)
-
-test('Test', test_varchunk,
- args : ['100000'],
- timeout : 360) # seconds
D varchunk/test_varchunk.c => varchunk/test_varchunk.c +0 -254
@@ 1,254 0,0 @@
-/*
- * Copyright (c) 2015-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.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <inttypes.h>
-#include <pthread.h>
-#include <unistd.h>
-#include <assert.h>
-
-#include <varchunk.h>
-
-#if !defined(_WIN32)
-# include <sys/mman.h>
-# include <sys/stat.h>
-# include <fcntl.h>
-# include <string.h>
-# define VARCHUNK_USE_SHARED_MEM
-
-static const struct timespec req = {
- .tv_sec = 0,
- .tv_nsec = 1
-};
-#endif
-
-static uint64_t iterations = 10000000;
-#define THRESHOLD (RAND_MAX / 256)
-#define PAD(SIZE) ( ( (size_t)(SIZE) + 7U ) & ( ~7U ) )
-
-static void *
-producer_main(void *arg)
-{
- varchunk_t *varchunk = arg;
- uint8_t *ptr;
- const uint8_t *end;
- size_t written;
- uint64_t cnt = 0;
-
- while(cnt < iterations)
- {
-#if !defined(_WIN32)
- if(rand() < THRESHOLD)
- {
- nanosleep(&req, NULL);
- }
-#endif
-
- written = PAD(rand() * 1024.f / RAND_MAX);
-
- size_t maximum;
- if( (ptr = varchunk_write_request_max(varchunk, written, &maximum)) )
- {
- assert(maximum >= written);
- end = ptr + written;
- for(uint8_t *src=ptr; src<end; src+=sizeof(uint64_t))
- {
- *(uint64_t *)src = cnt;
- assert(*(uint64_t *)src == cnt);
- }
- varchunk_write_advance(varchunk, written);
- cnt++;
- }
- else
- {
- // buffer full
- }
- }
-
- return NULL;
-}
-
-static void *
-consumer_main(void *arg)
-{
- varchunk_t *varchunk = arg;
- const uint8_t *ptr;
- const uint8_t *end;
- size_t toread;
- uint64_t cnt = 0;
-
- while(cnt < iterations)
- {
-#if !defined(_WIN32)
- if(rand() < THRESHOLD)
- {
- nanosleep(&req, NULL);
- }
-#endif
-
- if( (ptr = varchunk_read_request(varchunk, &toread)) )
- {
- end = ptr + toread;
- for(const uint8_t *src=ptr; src<end; src+=sizeof(uint64_t))
- {
- assert(*(const uint64_t *)src == cnt);
- }
- varchunk_read_advance(varchunk);
- cnt++;
- }
- else
- {
- // buffer empty
- }
- }
-
- return NULL;
-}
-
-static void
-test_threaded()
-{
- pthread_t producer;
- pthread_t consumer;
- varchunk_t *varchunk = varchunk_new(8192, true);
- assert(varchunk);
-
- pthread_create(&consumer, NULL, consumer_main, varchunk);
- pthread_create(&producer, NULL, producer_main, varchunk);
-
- pthread_join(producer, NULL);
- pthread_join(consumer, NULL);
-
- varchunk_free(varchunk);
-}
-
-#if defined(VARCHUNK_USE_SHARED_MEM)
-typedef struct _varchunk_shm_t varchunk_shm_t;
-
-struct _varchunk_shm_t {
- char *name;
- int fd;
- varchunk_t *varchunk;
-};
-
-static int
-varchunk_shm_init(varchunk_shm_t *varchunk_shm, const char *name, size_t minimum, bool release_and_acquire)
-{
- const size_t body_size = varchunk_body_size(minimum);
- const size_t total_size = sizeof(varchunk_t) + body_size;
-
- varchunk_shm->name = strdup(name);
- if(!varchunk_shm->name)
- {
- return -1;
- }
-
- bool is_first = true;
- varchunk_shm->fd = shm_open(varchunk_shm->name, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
- if(varchunk_shm->fd == -1)
- {
- is_first = false;
- varchunk_shm->fd = shm_open(varchunk_shm->name, O_RDWR , S_IRUSR | S_IWUSR);
- }
- if(varchunk_shm->fd == -1)
- {
- free(varchunk_shm->name);
- return -1;
- }
-
- if( (ftruncate(varchunk_shm->fd, total_size) == -1)
- || ((varchunk_shm->varchunk = mmap(NULL, total_size, PROT_READ | PROT_WRITE,
- MAP_SHARED, varchunk_shm->fd, 0)) == MAP_FAILED) )
- {
- shm_unlink(varchunk_shm->name);
- close(varchunk_shm->fd);
- free(varchunk_shm->name);
- return -1;
- }
-
- if(is_first)
- {
- varchunk_init(varchunk_shm->varchunk, body_size, release_and_acquire);
- }
-
- return 0;
-}
-
-static void
-varchunk_shm_deinit(varchunk_shm_t *varchunk_shm)
-{
- const size_t total_size = sizeof(varchunk_t) + varchunk_shm->varchunk->size;
-
- munmap(varchunk_shm->varchunk, total_size);
- shm_unlink(varchunk_shm->name);
- close(varchunk_shm->fd);
- free(varchunk_shm->name);
-}
-
-static void
-test_shared()
-{
- const char *name = "/varchunk_shm_test";
- pid_t pid = fork();
-
- assert(pid != -1);
-
- if(pid == 0) // child
- {
- varchunk_shm_t varchunk_shm;
- assert(varchunk_shm_init(&varchunk_shm, name, 8192, true) == 0);
-
- consumer_main(varchunk_shm.varchunk);
-
- varchunk_shm_deinit(&varchunk_shm);
- }
- else // parent
- {
- varchunk_shm_t varchunk_shm;
- assert(varchunk_shm_init(&varchunk_shm, name, 8192, true) == 0);
-
- producer_main(varchunk_shm.varchunk);
-
- varchunk_shm_deinit(&varchunk_shm);
- }
-}
-#endif
-
-int
-main(int argc, char **argv)
-{
-#if !defined(_WIN32)
- const int seed = time(NULL);
- srand(seed);
-#endif
-
- if(argc >= 2)
- {
- iterations = atoi(argv[1]);
- }
-
- assert(varchunk_is_lock_free());
-
- test_threaded();
-
-#if defined(VARCHUNK_USE_SHARED_MEM)
- test_shared();
-#endif
-
- return 0;
-}
D varchunk/varchunk.h => varchunk/varchunk.h +0 -384
@@ 1,384 0,0 @@
-/*
- * Copyright (c) 2015-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.
- */
-
-#ifndef _VARCHUNK_H
-#define _VARCHUNK_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <stdlib.h>
-#include <stdint.h>
-#include <stdatomic.h>
-#include <stdbool.h>
-#include <assert.h>
-
-#if !defined(_WIN32)
-# include <sys/mman.h> // mlock
-#endif
-
-/*****************************************************************************
- * API START
- *****************************************************************************/
-
-typedef struct _varchunk_t varchunk_t;
-
-static inline bool
-varchunk_is_lock_free(void);
-
-static inline size_t
-varchunk_body_size(size_t minimum);
-
-static inline varchunk_t *
-varchunk_new(size_t minimum, bool release_and_acquire);
-
-static inline void
-varchunk_free(varchunk_t *varchunk);
-
-static inline void
-varchunk_init(varchunk_t *varchunk, size_t body_size, bool release_and_acquire);
-
-static inline void *
-varchunk_write_request_max(varchunk_t *varchunk, size_t minimum, size_t *maximum);
-
-static inline void *
-varchunk_write_request(varchunk_t *varchunk, size_t minimum);
-
-static inline void
-varchunk_write_advance(varchunk_t *varchunk, size_t written);
-
-static inline const void *
-varchunk_read_request(varchunk_t *varchunk, size_t *toread);
-
-static inline void
-varchunk_read_advance(varchunk_t *varchunk);
-
-/*****************************************************************************
- * API END
- *****************************************************************************/
-
-#define VARCHUNK_PAD(SIZE) ( ( (size_t)(SIZE) + 7U ) & ( ~7U ) )
-
-typedef struct _varchunk_elmnt_t varchunk_elmnt_t;
-
-struct _varchunk_elmnt_t {
- uint32_t size;
- uint32_t gap;
-};
-
-struct _varchunk_t {
- size_t size;
- size_t mask;
- size_t rsvd;
- size_t gapd;
-
- memory_order acquire;
- memory_order release;
-
- atomic_size_t head;
- atomic_size_t tail;
-
- uint8_t buf [] __attribute__((aligned(sizeof(varchunk_elmnt_t))));
-};
-
-static inline bool
-varchunk_is_lock_free(void)
-{
- varchunk_t varchunk;
-
- return atomic_is_lock_free(&varchunk.head)
- && atomic_is_lock_free(&varchunk.tail);
-}
-
-static inline size_t
-varchunk_body_size(size_t minimum)
-{
- size_t size = 1;
- while(size < minimum)
- size <<= 1; // assure size to be a power of 2
- return size;
-}
-
-static inline void
-varchunk_init(varchunk_t *varchunk, size_t body_size, bool release_and_acquire)
-{
- varchunk->acquire = release_and_acquire
- ? memory_order_acquire
- : memory_order_relaxed;
- varchunk->release = release_and_acquire
- ? memory_order_release
- : memory_order_relaxed;
-
- atomic_init(&varchunk->head, 0);
- atomic_init(&varchunk->tail, 0);
-
- varchunk->size = body_size;
- varchunk->mask = varchunk->size - 1;
-}
-
-static inline varchunk_t *
-varchunk_new(size_t minimum, bool release_and_acquire)
-{
- varchunk_t *varchunk = NULL;
-
- const size_t body_size = varchunk_body_size(minimum);
- const size_t total_size = sizeof(varchunk_t) + body_size;
-
-#if defined(_WIN32)
- varchunk = _aligned_malloc(total_size, sizeof(varchunk_elmnt_t));
-#else
- posix_memalign((void **)&varchunk, sizeof(varchunk_elmnt_t), total_size);
- mlock(varchunk, total_size); // prevent memory from being flushed to disk
-#endif
-
- if(varchunk)
- varchunk_init(varchunk, body_size, release_and_acquire);
-
- return varchunk;
-}
-
-static inline void
-varchunk_free(varchunk_t *varchunk)
-{
- if(varchunk)
- {
-#if !defined(_WIN32)
- munlock(varchunk->buf, varchunk->size);
-#endif
- free(varchunk);
- }
-}
-
-static inline void
-_varchunk_write_advance_raw(varchunk_t *varchunk, size_t head, size_t written)
-{
- // only producer is allowed to advance write head
- const size_t new_head = (head + written) & varchunk->mask;
- atomic_store_explicit(&varchunk->head, new_head, varchunk->release);
-}
-
-static inline void *
-varchunk_write_request_max(varchunk_t *varchunk, size_t minimum, size_t *maximum)
-{
- assert(varchunk);
-
- size_t space; // size of writable buffer
- size_t end; // virtual end of writable buffer
- const size_t head = atomic_load_explicit(&varchunk->head, memory_order_relaxed); // read head
- const size_t tail = atomic_load_explicit(&varchunk->tail, varchunk->acquire); // read tail (consumer modifies it any time)
- const size_t padded = 2*sizeof(varchunk_elmnt_t) + VARCHUNK_PAD(minimum);
-
- // calculate writable space
- if(head > tail)
- space = ((tail - head + varchunk->size) & varchunk->mask) - 1;
- else if(head < tail)
- space = (tail - head) - 1;
- else // head == tail
- space = varchunk->size - 1;
- end = head + space;
-
- if(end > varchunk->size) // available region wraps over at end of buffer
- {
- // get first part of available buffer
- uint8_t *buf1 = varchunk->buf + head;
- const size_t len1 = varchunk->size - head;
-
- if(len1 < padded) // not enough space left on first part of buffer
- {
- // get second part of available buffer
- uint8_t *buf2 = varchunk->buf;
- const size_t len2 = end & varchunk->mask;
-
- if(len2 < padded) // not enough space left on second buffer, either
- {
- varchunk->rsvd = 0;
- varchunk->gapd = 0;
- if(maximum)
- *maximum = varchunk->rsvd;
- return NULL;
- }
- else // enough space left on second buffer, use it!
- {
- varchunk->rsvd = len2;
- varchunk->gapd = len1;
- if(maximum)
- *maximum = varchunk->rsvd;
- return buf2 + sizeof(varchunk_elmnt_t);
- }
- }
- else // enough space left on first part of buffer, use it!
- {
- varchunk->rsvd = len1;
- varchunk->gapd = 0;
- if(maximum)
- *maximum = varchunk->rsvd;
- return buf1 + sizeof(varchunk_elmnt_t);
- }
- }
- else // available region is contiguous
- {
- uint8_t *buf = varchunk->buf + head;
-
- if(space < padded) // no space left on contiguous buffer
- {
- varchunk->rsvd = 0;
- varchunk->gapd = 0;
- if(maximum)
- *maximum = varchunk->rsvd;
- return NULL;
- }
- else // enough space left on contiguous buffer, use it!
- {
- varchunk->rsvd = space;
- varchunk->gapd = 0;
- if(maximum)
- *maximum = varchunk->rsvd;
- return buf + sizeof(varchunk_elmnt_t);
- }
- }
-}
-
-static inline void *
-varchunk_write_request(varchunk_t *varchunk, size_t minimum)
-{
- return varchunk_write_request_max(varchunk, minimum, NULL);
-}
-
-static inline void
-varchunk_write_advance(varchunk_t *varchunk, size_t written)
-{
- assert(varchunk);
- // fail miserably if stupid programmer tries to write more than rsvd
- assert(written <= varchunk->rsvd);
-
- // write elmnt header at head
- const size_t head = atomic_load_explicit(&varchunk->head, memory_order_relaxed);
- if(varchunk->gapd > 0)
- {
- // fill end of first buffer with gap
- varchunk_elmnt_t *elmnt = (varchunk_elmnt_t *)(varchunk->buf + head);
- elmnt->size = varchunk->gapd - sizeof(varchunk_elmnt_t);
- elmnt->gap = 1;
-
- // fill written element header
- elmnt = (void *)varchunk->buf;
- elmnt->size = written;
- elmnt->gap = 0;
- }
- else // varchunk->gapd == 0
- {
- // fill written element header
- varchunk_elmnt_t *elmnt = (varchunk_elmnt_t *)(varchunk->buf + head);
- elmnt->size = written;
- elmnt->gap = 0;
- }
-
- // advance write head
- _varchunk_write_advance_raw(varchunk, head,
- varchunk->gapd + sizeof(varchunk_elmnt_t) + VARCHUNK_PAD(written));
-}
-
-static inline void
-_varchunk_read_advance_raw(varchunk_t *varchunk, size_t tail, size_t read)
-{
- // only consumer is allowed to advance read tail
- const size_t new_tail = (tail + read) & varchunk->mask;
- atomic_store_explicit(&varchunk->tail, new_tail, varchunk->release);
-}
-
-static inline const void *
-varchunk_read_request(varchunk_t *varchunk, size_t *toread)
-{
- assert(varchunk);
- size_t space; // size of available buffer
- const size_t tail = atomic_load_explicit(&varchunk->tail, memory_order_relaxed); // read tail
- const size_t head = atomic_load_explicit(&varchunk->head, varchunk->acquire); // read head (producer modifies it any time)
-
- // calculate readable space
- if(head > tail)
- space = head - tail;
- else
- space = (head - tail + varchunk->size) & varchunk->mask;
-
- if(space > 0) // there may be chunks available for reading
- {
- const size_t end = tail + space; // virtual end of available buffer
-
- if(end > varchunk->size) // available buffer wraps around at end
- {
- // first part of available buffer
- const uint8_t *buf1 = varchunk->buf + tail;
- const size_t len1 = varchunk->size - tail;
- const varchunk_elmnt_t *elmnt = (const varchunk_elmnt_t *)buf1;
-
- if(elmnt->gap) // gap elmnt?
- {
- // skip gap
- _varchunk_read_advance_raw(varchunk, tail, len1);
-
- // second part of available buffer
- const uint8_t *buf2 = varchunk->buf;
- // there will always be at least on element after a gap
- elmnt = (const varchunk_elmnt_t *)buf2;
-
- *toread = elmnt->size;
- return buf2 + sizeof(varchunk_elmnt_t);
- }
- else // valid chunk, use it!
- {
- *toread = elmnt->size;
- return buf1 + sizeof(varchunk_elmnt_t);
- }
- }
- else // available buffer is contiguous
- {
- // get buffer
- const uint8_t *buf = varchunk->buf + tail;
- const varchunk_elmnt_t *elmnt = (const varchunk_elmnt_t *)buf;
-
- *toread = elmnt->size;
- return buf + sizeof(varchunk_elmnt_t);
- }
- }
- else // no chunks available aka empty buffer
- {
- *toread = 0;
- return NULL;
- }
-}
-
-static inline void
-varchunk_read_advance(varchunk_t *varchunk)
-{
- assert(varchunk);
- // get elmnt header from tail (for size)
- const size_t tail = atomic_load_explicit(&varchunk->tail, memory_order_relaxed);
- const varchunk_elmnt_t *elmnt = (const varchunk_elmnt_t *)(varchunk->buf + tail);
-
- // advance read tail
- _varchunk_read_advance_raw(varchunk, tail,
- sizeof(varchunk_elmnt_t) + VARCHUNK_PAD(elmnt->size));
-}
-
-#undef VARCHUNK_PAD
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif //_VARCHUNK_H