1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-10-10 16:43:33 +02:00

Adding new libraries for LV2 support.

lilv-0.16.0
lv2-1.6.0
serd-0.18.2
sord-0.12.0
sratom-0.4.2
This commit is contained in:
lllucius
2013-10-27 08:56:51 +00:00
parent 52afa22aaf
commit bc5e7ffce8
588 changed files with 170918 additions and 0 deletions

View File

@@ -0,0 +1,13 @@
Copyright 2012 David Robillard <http://drobilla.net>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

25
lib-src/lv2/sratom/NEWS Normal file
View File

@@ -0,0 +1,25 @@
sratom (0.4.2) stable;
* Fix serialisation of nested tuples
* Fix memory leaks
* Use new sord API to clean up and shrink code
* Disable timestamps in HTML documentation for reproducible build
* Update to waf 1.7.9 and autowaf r90 (install docs to versioned directory)
-- David Robillard <d@drobilla.net> Mon, 18 Feb 2013 11:17:01 -0500
sratom (0.4.0) stable;
* Correctly read objects with several rdf:type properties
* Support writing Object Atoms as top level descriptions if subject and
predicate are not given.
* Fix various hyper-strict warnings
* Upgrade to waf 1.7.2
-- David Robillard <d@drobilla.net> Thu, 23 Aug 2012 01:11:07 -0400
sratom (0.2.0) stable;
* Initial release
-- David Robillard <d@drobilla.net> Wed, 18 Apr 2012 15:14:11 -0400

11
lib-src/lv2/sratom/README Normal file
View File

@@ -0,0 +1,11 @@
Sratom
------
Sratom is a library for serialising LV2 atoms to/from RDF, particularly the
Turtle syntax.
More information about LV2 atoms can be found at <http://lv2plug.in/ns/ext/atom>
More information about Sratom can be found at <http://drobilla.net/software/sratom>
-- David Robillard <d@drobilla.net>

View File

@@ -0,0 +1,187 @@
<doxygenlayout version="1.0">
<!-- Navigation index tabs for HTML output -->
<navindex>
<tab type="mainpage" visible="yes" title=""/>
<tab type="pages" visible="yes" title="" intro=""/>
<tab type="modules" visible="yes" title="" intro=""/>
<tab type="namespaces" visible="yes" title="">
<tab type="namespacelist" visible="yes" title="" intro=""/>
<tab type="namespacemembers" visible="yes" title="" intro=""/>
</tab>
<tab type="classes" visible="yes" title="">
<tab type="classlist" visible="yes" title="" intro=""/>
<tab type="classindex" visible="$ALPHABETICAL_INDEX" title=""/>
<tab type="hierarchy" visible="yes" title="" intro=""/>
<tab type="classmembers" visible="yes" title="" intro=""/>
</tab>
<tab type="files" visible="yes" title="">
<tab type="filelist" visible="yes" title="" intro=""/>
<tab type="globals" visible="yes" title="" intro=""/>
</tab>
<tab type="examples" visible="yes" title="" intro=""/>
</navindex>
<!-- Layout definition for a class page -->
<class>
<briefdescription visible="yes"/>
<includes visible="$SHOW_INCLUDE_FILES"/>
<inheritancegraph visible="$CLASS_GRAPH"/>
<collaborationgraph visible="$COLLABORATION_GRAPH"/>
<allmemberslink visible="yes"/>
<memberdecl>
<nestedclasses visible="yes" title=""/>
<publictypes title=""/>
<publicslots title=""/>
<signals title=""/>
<publicmethods title=""/>
<publicstaticmethods title=""/>
<publicattributes title=""/>
<publicstaticattributes title=""/>
<protectedtypes title=""/>
<protectedslots title=""/>
<protectedmethods title=""/>
<protectedstaticmethods title=""/>
<protectedattributes title=""/>
<protectedstaticattributes title=""/>
<packagetypes title=""/>
<packagemethods title=""/>
<packagestaticmethods title=""/>
<packageattributes title=""/>
<packagestaticattributes title=""/>
<properties title=""/>
<events title=""/>
<privatetypes title=""/>
<privateslots title=""/>
<privatemethods title=""/>
<privatestaticmethods title=""/>
<privateattributes title=""/>
<privatestaticattributes title=""/>
<friends title=""/>
<related title="" subtitle=""/>
<membergroups visible="yes"/>
</memberdecl>
<detaileddescription title=""/>
<memberdef>
<inlineclasses title=""/>
<typedefs title=""/>
<enums title=""/>
<constructors title=""/>
<functions title=""/>
<related title=""/>
<variables title=""/>
<properties title=""/>
<events title=""/>
</memberdef>
<usedfiles visible="$SHOW_USED_FILES"/>
<authorsection visible="yes"/>
</class>
<!-- Layout definition for a namespace page -->
<namespace>
<briefdescription visible="yes"/>
<memberdecl>
<nestednamespaces visible="yes" title=""/>
<classes visible="yes" title=""/>
<typedefs title=""/>
<enums title=""/>
<functions title=""/>
<variables title=""/>
<membergroups visible="yes"/>
</memberdecl>
<detaileddescription title=""/>
<memberdef>
<inlineclasses title=""/>
<typedefs title=""/>
<enums title=""/>
<functions title=""/>
<variables title=""/>
</memberdef>
<authorsection visible="yes"/>
</namespace>
<!-- Layout definition for a file page -->
<file>
<briefdescription visible="yes"/>
<includes visible="$SHOW_INCLUDE_FILES"/>
<includegraph visible="$INCLUDE_GRAPH"/>
<includedbygraph visible="$INCLUDED_BY_GRAPH"/>
<sourcelink visible="yes"/>
<memberdecl>
<classes visible="yes" title=""/>
<namespaces visible="yes" title=""/>
<defines title=""/>
<typedefs title=""/>
<enums title=""/>
<functions title=""/>
<variables title=""/>
<membergroups visible="yes"/>
</memberdecl>
<detaileddescription title=""/>
<memberdef>
<inlineclasses title=""/>
<defines title=""/>
<typedefs title=""/>
<enums title=""/>
<functions title=""/>
<variables title=""/>
</memberdef>
<authorsection/>
</file>
<!-- Layout definition for a group page -->
<group>
<briefdescription visible="no"/>
<groupgraph visible="$GROUP_GRAPHS"/>
<detaileddescription title=""/>
<memberdecl>
<nestedgroups visible="yes" title=""/>
<dirs visible="yes" title=""/>
<files visible="yes" title=""/>
<namespaces visible="yes" title=""/>
<classes visible="yes" title=""/>
<defines title=""/>
<typedefs title=""/>
<enums title=""/>
<enumvalues title=""/>
<functions title=""/>
<variables title=""/>
<signals title=""/>
<publicslots title=""/>
<protectedslots title=""/>
<privateslots title=""/>
<events title=""/>
<properties title=""/>
<friends title=""/>
<membergroups visible="yes"/>
</memberdecl>
<memberdef>
<pagedocs/>
<inlineclasses title=""/>
<defines title=""/>
<typedefs title=""/>
<enums title=""/>
<enumvalues title=""/>
<functions title=""/>
<variables title=""/>
<signals title=""/>
<publicslots title=""/>
<protectedslots title=""/>
<privateslots title=""/>
<events title=""/>
<properties title=""/>
<friends title=""/>
</memberdef>
<authorsection visible="yes"/>
</group>
<!-- Layout definition for a directory page -->
<directory>
<briefdescription visible="yes"/>
<directorygraph visible="yes"/>
<memberdecl>
<dirs visible="yes"/>
<files visible="yes"/>
</memberdecl>
<detaileddescription title=""/>
</directory>
</doxygenlayout>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,563 @@
body {
font-size: medium;
font-family: sans-serif;
}
#top {
background-color: #F3F3F3;
margin: 0;
padding: 0;
border-bottom: 1px solid #DDD;
margin-bottom: 1ex;
font-size: xx-large;
font-weight: bold;
}
div.header {
display: none;
}
.tabs {
display: none;
}
h1 h2 h3 h4 h5 h6 {
font-weight: bold;
}
h1 {
font-size: 164%;
}
h2 {
font-size: 132%;
}
h3 {
font-size: 124%;
}
h4 {
font-size: 116%;
}
h5 {
font-size: 108%;
}
h6 {
font-size: 100%;
}
p {
margin: 0 0 1ex 0;
}
br {
display: none;
}
dt {
font-weight: 700;
}
div.multicol {
}
p.startli,p.startdd,p.starttd {
margin-top: 2px;
}
p.endli {
margin-bottom: 0;
}
p.enddd {
margin-bottom: 4px;
}
p.endtd {
margin-bottom: 2px;
}
caption {
font-weight: 700;
}
span.legend {
font-size: 70%;
text-align: center;
}
h3.version {
font-size: 90%;
text-align: center;
}
div.qindex,div.navtab {
background-color: #EBEFF6;
border: 1px solid #A3B4D7;
text-align: center;
margin: 2px;
padding: 2px;
}
div.qindex,div.navpath {
width: 100%;
line-height: 140%;
}
div.navtab {
margin-right: 15px;
}
/* @group Link Styling */
a {
color: #3D8C57;
text-decoration: none;
}
.contents a:visited {
color: #50755E;
}
a:hover {
text-decoration: underline;
}
a.qindexHL {
background-color: #9CAFD4;
color: #FFF;
border: 1px double #869DCA;
}
a.code {
color: #4665A2;
}
a.codeRef {
color: #4665A2;
}
/* @end */
dl.el {
margin-left: -1cm;
}
.fragment {
font-family: monospace, fixed;
font-size: 105%;
}
pre.fragment {
border: 1px solid #C4C4C4;
background-color: #F9F9F9;
padding: 4px 6px;
margin: 4px 8px 4px 2px;
overflow: auto;
font-size: 9pt;
line-height: 125%;
}
div.ah {
background-color: #000;
font-weight: 700;
color: #FFF;
margin-bottom: 3px;
margin-top: 3px;
padding: .2em;
border: thin solid #333;
}
div.groupHeader {
margin-left: 16px;
margin-top: 12px;
margin-bottom: 6px;
font-weight: 700;
}
div.groupText {
margin-left: 16px;
font-style: italic;
}
body {
background: #FFF;
color: #000;
margin: 0;
}
div.contents {
margin-top: 10px;
margin-left: 10px;
margin-right: 10px;
}
td.indexkey {
background-color: #EBEFF6;
font-weight: 700;
border: 1px solid #C4CFE5;
margin: 2px 0;
padding: 2px 10px;
}
td.indexvalue {
background-color: #EBEFF6;
border: 1px solid #C4CFE5;
padding: 2px 10px;
margin: 2px 0;
}
tr.memlist {
background-color: #EEF1F7;
}
p.formulaDsp {
text-align: center;
}
img.formulaDsp {
}
img.formulaInl {
vertical-align: middle;
}
div.center {
text-align: center;
margin-top: 0;
margin-bottom: 0;
padding: 0;
}
div.center img {
border: 0;
}
address.footer {
text-align: right;
padding: 0 0.25em 0.25em 0;
}
img.footer {
border: 0;
vertical-align: middle;
}
/* @group Code Colorization */
span.keyword {
color: green;
}
span.keywordtype {
color: #604020;
}
span.keywordflow {
color: #e08000;
}
span.comment {
color: maroon;
}
span.preprocessor {
color: #806020;
}
span.stringliteral {
color: #002080;
}
span.charliteral {
color: teal;
}
span.vhdldigit {
color: #F0F;
}
span.vhdlkeyword {
color: #700070;
}
span.vhdllogic {
color: red;
}
/* @end */
td.tiny {
font-size: 75%;
}
.dirtab {
padding: 4px;
border-collapse: collapse;
border: 1px solid #A3B4D7;
}
th.dirtab {
background: #EBEFF6;
font-weight: 700;
}
hr {
height: 0;
border: none;
border-top: 1px solid #DDD;
margin: 2em 0 1em;
}
hr.footer {
height: 1px;
}
/* @group Member Descriptions */
table.memberdecls {
border-spacing: 0;
font-size: small;
}
.mdescLeft,.mdescRight,.memItemLeft,.memItemRight,.memTemplItemLeft,.memTemplItemRight,.memTemplParams {
background-color: #FBFBFB;
margin: 0;
padding: 0.25ex;
}
.mdescLeft,.mdescRight {
color: #555;
}
.memItemLeft,.memItemRight,.memTemplParams {
border-top: 1px solid #DDD;
}
.memItemLeft,.memTemplItemLeft {
white-space: nowrap;
padding-left: 2em;
}
.memTemplParams {
color: #464646;
white-space: nowrap;
}
/* @end */
/* @group Member Details */
/* Styles for detailed member documentation */
.memtemplate {
font-size: 80%;
color: #4665A2;
font-weight: bold;
}
.memnav {
background-color: #EBEFF6;
border: 1px solid #A3B4D7;
text-align: center;
margin: 2px;
margin-right: 15px;
padding: 2px;
}
.memitem {
padding: 0;
margin: 1ex 0 2ex 0;
border: 1px solid #CCC;
}
.memname {
white-space: nowrap;
font-weight: bold;
}
.memproto {
border-bottom: 1px solid #DDD;
padding: 0.5ex;
font-weight: bold;
background-color: #F3F3F3;
}
.memdoc {
padding: 1ex;
background-color: #FBFBFB;
border-top-width: 0;
}
.paramkey {
text-align: right;
}
.paramtype {
white-space: nowrap;
}
.paramname {
color: #602020;
white-space: nowrap;
}
.paramname em {
font-style: normal;
}
/* @end */
/* @group Directory (tree) */
/* for the tree view */
.ftvtree {
font-family: sans-serif;
margin: 0;
}
/* these are for tree view when used as main index */
.directory {
font-size: 9pt;
font-weight: bold;
margin: 5px;
}
.directory h3 {
margin: 0;
margin-top: 1em;
font-size: 11pt;
}
.directory > h3 {
margin-top: 0;
}
.directory p {
margin: 0;
white-space: nowrap;
}
.directory div {
display: none;
margin: 0;
}
.directory img {
vertical-align: -30%;
}
/* these are for tree view when not used as main index */
.directory-alt {
font-size: 100%;
font-weight: bold;
}
.directory-alt h3 {
margin: 0;
margin-top: 1em;
font-size: 11pt;
}
.directory-alt > h3 {
margin-top: 0;
}
.directory-alt p {
margin: 0;
white-space: nowrap;
}
.directory-alt div {
display: none;
margin: 0;
}
.directory-alt img {
vertical-align: -30%;
}
/* @end */
div.dynheader {
margin-top: 8px;
}
address {
font-style: normal;
color: #2A3D61;
}
table.doxtable {
border-collapse: collapse;
margin: 0.5ex;
}
table.doxtable td,table.doxtable th {
border: 1px solid #DDD;
padding: 3px 7px 2px;
}
table.doxtable th {
background-color: #F3F3F3;
color: #000;
padding-bottom: 4px;
padding-top: 5px;
text-align: left;
font-weight: bold;
}
.tabsearch {
top: 0;
left: 10px;
height: 36px;
z-index: 101;
overflow: hidden;
font-size: 13px;
}
.navpath ul {
font-size: 11px;
height: 30px;
line-height: 30px;
color: #8AA0CC;
border: 1px solid #C2CDE4;
overflow: hidden;
margin: 0;
padding: 0;
}
.navpath li {
list-style-type: none;
float: left;
padding-left: 10px;
padding-right: 15px;
color: #364D7C;
}
.navpath a {
height: 32px;
display: block;
text-decoration: none;
outline: none;
}
.navpath a:hover {
color: #6884BD;
}
div.summary {
float: right;
font-size: 8pt;
padding-right: 5px;
width: 50%;
text-align: right;
}
div.summary a {
white-space: nowrap;
}
div.header {
background-color: #F3F3F3;
margin: 0;
border-bottom: 1px solid #DDD;
}
div.headertitle {
padding: 5px 5px 5px 10px;
font-size: 180%;
font-weight: bold;
}

View File

@@ -0,0 +1,11 @@
prefix=@PREFIX@
exec_prefix=@EXEC_PREFIX@
libdir=@LIBDIR@
includedir=@INCLUDEDIR@
Name: Sratom
Version: @SRATOM_VERSION@
Description: LV2 Atom RDF serialisation library
Requires: lv2 @PKG_serd_0@ @PKG_sord_0@
Libs: -L${libdir} -l@LIB_SRATOM@
Cflags: -I${includedir}/sratom-@SRATOM_MAJOR_VERSION@

View File

@@ -0,0 +1,217 @@
/*
Copyright 2012 David Robillard <http://drobilla.net>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/**
@file sratom.h API for Sratom, an LV2 Atom RDF serialisation library.
*/
#ifndef SRATOM_SRATOM_H
#define SRATOM_SRATOM_H
#include <stdint.h>
#include "lv2/lv2plug.in/ns/ext/urid/urid.h"
#include "lv2/lv2plug.in/ns/ext/atom/atom.h"
#include "lv2/lv2plug.in/ns/ext/atom/forge.h"
#include "serd/serd.h"
#include "sord/sord.h"
#ifdef SRATOM_SHARED
# ifdef _WIN32
# define SRATOM_LIB_IMPORT __declspec(dllimport)
# define SRATOM_LIB_EXPORT __declspec(dllexport)
# else
# define SRATOM_LIB_IMPORT __attribute__((visibility("default")))
# define SRATOM_LIB_EXPORT __attribute__((visibility("default")))
# endif
# ifdef SRATOM_INTERNAL
# define SRATOM_API SRATOM_LIB_EXPORT
# else
# define SRATOM_API SRATOM_LIB_IMPORT
# endif
#else
# define SRATOM_API
#endif
#ifdef __cplusplus
extern "C" {
#endif
/**
@defgroup sratom Sratom
An LV2 Atom RDF serialisation library.
@{
*/
/**
Atom serialiser.
*/
typedef struct SratomImpl Sratom;
/**
Mode for reading resources to LV2 Objects.
This affects how resources (which are either blank nodes or have URIs) are
read by sratom_read(), since they may be read as simple references (a URI or
blank node ID) or a complete description (an atom "Object").
Currently, blank nodes are always read as Objects, but support for reading
blank node IDs may be added in the future.
*/
typedef enum {
/**
Read blank nodes as Objects, and named resources as URIs.
*/
SRATOM_OBJECT_MODE_BLANK,
/**
Read blank nodes and the main subject as Objects, and any other named
resources as URIs. The "main subject" is the subject parameter passed
to sratom_read(); if this is a resource it will be read as an Object,
but all other named resources encountered will be read as URIs.
*/
SRATOM_OBJECT_MODE_BLANK_SUBJECT,
} SratomObjectMode;
/**
Create a new Atom serialiser.
*/
SRATOM_API
Sratom*
sratom_new(LV2_URID_Map* map);
/**
Free an Atom serialisation.
*/
SRATOM_API
void
sratom_free(Sratom* sratom);
/**
Set the sink(s) where sratom will write its output.
This must be called before calling sratom_write().
*/
SRATOM_API
void
sratom_set_sink(Sratom* sratom,
const char* base_uri,
SerdStatementSink sink,
SerdEndSink end_sink,
void* handle);
/**
Write pretty numeric literals.
If @p pretty_numbers is true, numbers will be written as pretty Turtle
literals, rather than string literals with precise types. The cost of this
is that the types might get fudged on a round-trip to RDF and back.
*/
SRATOM_API
void
sratom_set_pretty_numbers(Sratom* sratom,
bool pretty_numbers);
/**
Configure how resources will be read to form LV2 Objects.
*/
SRATOM_API
void
sratom_set_object_mode(Sratom* sratom,
SratomObjectMode object_mode);
/**
Write an Atom to RDF.
The serialised atom is written to the sink set by sratom_set_sink().
@return 0 on success, or a non-zero error code otherwise.
*/
SRATOM_API
int
sratom_write(Sratom* sratom,
LV2_URID_Unmap* unmap,
uint32_t flags,
const SerdNode* subject,
const SerdNode* predicate,
uint32_t type,
uint32_t size,
const void* body);
/**
Read an Atom from RDF.
The resulting atom will be written to @p forge.
*/
SRATOM_API
void
sratom_read(Sratom* sratom,
LV2_Atom_Forge* forge,
SordWorld* world,
SordModel* model,
const SordNode* subject);
/**
Serialise an Atom to a Turtle string.
The returned string must be free()'d by the caller.
*/
SRATOM_API
char*
sratom_to_turtle(Sratom* sratom,
LV2_URID_Unmap* unmap,
const char* base_uri,
const SerdNode* subject,
const SerdNode* predicate,
uint32_t type,
uint32_t size,
const void* body);
/**
Read an Atom from a Turtle string.
The returned atom must be free()'d by the caller.
*/
SRATOM_API
LV2_Atom*
sratom_from_turtle(Sratom* sratom,
const char* base_uri,
const SerdNode* subject,
const SerdNode* predicate,
const char* str);
/**
A convenient resizing sink for LV2_Atom_Forge.
The handle must point to an initialized SerdChunk.
*/
SRATOM_API
LV2_Atom_Forge_Ref
sratom_forge_sink(LV2_Atom_Forge_Sink_Handle handle,
const void* buf,
uint32_t size);
/**
The corresponding deref function for sratom_forge_sink.
*/
SRATOM_API
LV2_Atom*
sratom_forge_deref(LV2_Atom_Forge_Sink_Handle handle,
LV2_Atom_Forge_Ref ref);
/**
@}
*/
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* SRATOM_SRATOM_H */

View File

@@ -0,0 +1,788 @@
/*
Copyright 2012 David Robillard <http://drobilla.net>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#define __STDC_LIMIT_MACROS 1
#include <assert.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "lv2/lv2plug.in/ns/ext/atom/forge.h"
#include "lv2/lv2plug.in/ns/ext/atom/util.h"
#include "lv2/lv2plug.in/ns/ext/midi/midi.h"
#include "sratom/sratom.h"
#define NS_RDF (const uint8_t*)"http://www.w3.org/1999/02/22-rdf-syntax-ns#"
#define NS_XSD (const uint8_t*)"http://www.w3.org/2001/XMLSchema#"
#define USTR(str) ((const uint8_t*)(str))
typedef enum {
MODE_SUBJECT,
MODE_BODY,
MODE_SEQUENCE,
} ReadMode;
struct SratomImpl {
LV2_URID_Map* map;
LV2_Atom_Forge forge;
LV2_URID atom_Event;
LV2_URID midi_MidiEvent;
unsigned next_id;
SerdNode base_uri;
SerdStatementSink write_statement;
SerdEndSink end_anon;
void* handle;
SratomObjectMode object_mode;
bool pretty_numbers;
struct {
SordNode* atom_childType;
SordNode* atom_frameTime;
SordNode* rdf_first;
SordNode* rdf_rest;
SordNode* rdf_type;
SordNode* rdf_value;
SordNode* xsd_base64Binary;
} nodes;
};
static void
read_node(Sratom* sratom,
LV2_Atom_Forge* forge,
SordWorld* world,
SordModel* model,
const SordNode* node,
ReadMode mode);
SRATOM_API
Sratom*
sratom_new(LV2_URID_Map* map)
{
Sratom* sratom = (Sratom*)malloc(sizeof(Sratom));
sratom->map = map;
sratom->atom_Event = map->map(map->handle, LV2_ATOM__Event);
sratom->midi_MidiEvent = map->map(map->handle, LV2_MIDI__MidiEvent);
sratom->next_id = 0;
sratom->base_uri = SERD_NODE_NULL;
sratom->object_mode = SRATOM_OBJECT_MODE_BLANK;
sratom->pretty_numbers = false;
memset(&sratom->nodes, 0, sizeof(sratom->nodes));
lv2_atom_forge_init(&sratom->forge, map);
return sratom;
}
SRATOM_API
void
sratom_free(Sratom* sratom)
{
serd_node_free(&sratom->base_uri);
free(sratom);
}
SRATOM_API
void
sratom_set_sink(Sratom* sratom,
const char* base_uri,
SerdStatementSink write_statement,
SerdEndSink end_anon,
void* handle)
{
if (base_uri) {
serd_node_free(&sratom->base_uri);
sratom->base_uri = serd_node_new_uri_from_string(
USTR(base_uri), NULL, NULL);
}
sratom->write_statement = write_statement;
sratom->end_anon = end_anon;
sratom->handle = handle;
}
SRATOM_API
void
sratom_set_pretty_numbers(Sratom* sratom,
bool pretty_numbers)
{
sratom->pretty_numbers = pretty_numbers;
}
SRATOM_API
void
sratom_set_object_mode(Sratom* sratom,
SratomObjectMode object_mode)
{
sratom->object_mode = object_mode;
}
static void
gensym(SerdNode* out, char c, unsigned num)
{
out->n_bytes = out->n_chars = snprintf(
(char*)out->buf, 10, "%c%u", c, num);
}
static void
list_append(Sratom* sratom,
LV2_URID_Unmap* unmap,
unsigned* flags,
SerdNode* s,
SerdNode* p,
SerdNode* node,
uint32_t size,
uint32_t type,
const void* body)
{
// Generate a list node
gensym(node, 'l', sratom->next_id);
sratom->write_statement(sratom->handle, *flags, NULL,
s, p, node, NULL, NULL);
// _:node rdf:first value
*flags = SERD_LIST_CONT;
*p = serd_node_from_string(SERD_URI, NS_RDF "first");
sratom_write(sratom, unmap, *flags, node, p, type, size, body);
// Set subject to node and predicate to rdf:rest for next time
gensym(node, 'l', ++sratom->next_id);
*s = *node;
*p = serd_node_from_string(SERD_URI, NS_RDF "rest");
}
static void
list_end(SerdStatementSink sink,
void* handle,
unsigned* flags,
SerdNode* s,
SerdNode* p)
{
// _:node rdf:rest rdf:nil
const SerdNode nil = serd_node_from_string(SERD_URI, NS_RDF "nil");
sink(handle, *flags, NULL, s, p, &nil, NULL, NULL);
}
static void
start_object(Sratom* sratom,
uint32_t* flags,
const SerdNode* subject,
const SerdNode* predicate,
const SerdNode* node,
const char* type)
{
if (subject && predicate) {
sratom->write_statement(sratom->handle, *flags|SERD_ANON_O_BEGIN, NULL,
subject, predicate, node, NULL, NULL);
// Start abbreviating object properties
*flags |= SERD_ANON_CONT;
// Object is in a list, stop list abbreviating if necessary
*flags &= ~SERD_LIST_CONT;
}
if (type) {
SerdNode p = serd_node_from_string(SERD_URI, NS_RDF "type");
SerdNode o = serd_node_from_string(SERD_URI, USTR(type));
sratom->write_statement(sratom->handle, *flags, NULL,
node, &p, &o, NULL, NULL);
}
}
static bool
path_is_absolute(const char* path)
{
return (path[0] == '/'
|| (isalpha(path[0]) && path[1] == ':'
&& (path[2] == '/' || path[2] == '\\')));
}
SRATOM_API
int
sratom_write(Sratom* sratom,
LV2_URID_Unmap* unmap,
uint32_t flags,
const SerdNode* subject,
const SerdNode* predicate,
uint32_t type_urid,
uint32_t size,
const void* body)
{
const char* const type = unmap->unmap(unmap->handle, type_urid);
uint8_t idbuf[12] = "b0000000000";
SerdNode id = serd_node_from_string(SERD_BLANK, idbuf);
uint8_t nodebuf[12] = "b0000000000";
SerdNode node = serd_node_from_string(SERD_BLANK, nodebuf);
SerdNode object = SERD_NODE_NULL;
SerdNode datatype = SERD_NODE_NULL;
SerdNode language = SERD_NODE_NULL;
bool new_node = false;
if (type_urid == 0 && size == 0) {
object = serd_node_from_string(SERD_URI, USTR(NS_RDF "nil"));
} else if (type_urid == sratom->forge.String) {
object = serd_node_from_string(SERD_LITERAL, (const uint8_t*)body);
} else if (type_urid == sratom->forge.Chunk) {
datatype = serd_node_from_string(SERD_URI, NS_XSD "base64Binary");
object = serd_node_new_blob(body, size, true);
new_node = true;
} else if (type_urid == sratom->forge.Literal) {
const LV2_Atom_Literal_Body* lit = (const LV2_Atom_Literal_Body*)body;
const uint8_t* str = USTR(lit + 1);
object = serd_node_from_string(SERD_LITERAL, str);
if (lit->datatype) {
datatype = serd_node_from_string(
SERD_URI, USTR(unmap->unmap(unmap->handle, lit->datatype)));
} else if (lit->lang) {
const char* lang = unmap->unmap(unmap->handle, lit->lang);
const char* prefix = "http://lexvo.org/id/iso639-3/";
const size_t prefix_len = strlen(prefix);
if (lang && !strncmp(lang, prefix, prefix_len)) {
language = serd_node_from_string(
SERD_LITERAL, USTR(lang + prefix_len));
} else {
fprintf(stderr, "Unknown language URID %d\n", lit->lang);
}
}
} else if (type_urid == sratom->forge.URID) {
const uint32_t urid = *(const uint32_t*)body;
const uint8_t* str = USTR(unmap->unmap(unmap->handle, urid));
object = serd_node_from_string(SERD_URI, str);
} else if (type_urid == sratom->forge.Path) {
const uint8_t* str = USTR(body);
if (path_is_absolute((const char*)str)) {
new_node = true;
object = serd_node_new_file_uri(str, NULL, NULL, false);
} else {
SerdURI base_uri = SERD_URI_NULL;
if (!sratom->base_uri.buf ||
strncmp((const char*)sratom->base_uri.buf, "file://", 7)) {
fprintf(stderr, "warning: Relative path but base is not a file URI.\n");
fprintf(stderr, "warning: Writing ambiguous atom:Path literal.\n");
object = serd_node_from_string(SERD_LITERAL, str);
datatype = serd_node_from_string(SERD_URI, USTR(LV2_ATOM__Path));
} else {
if (sratom->base_uri.buf) {
serd_uri_parse(sratom->base_uri.buf, &base_uri);
}
new_node = true;
SerdNode rel = serd_node_new_file_uri(str, NULL, NULL, false);
object = serd_node_new_uri_from_node(&rel, &base_uri, NULL);
serd_node_free(&rel);
}
}
} else if (type_urid == sratom->forge.URI) {
const uint8_t* str = USTR(body);
object = serd_node_from_string(SERD_URI, str);
} else if (type_urid == sratom->forge.Int) {
new_node = true;
object = serd_node_new_integer(*(const int32_t*)body);
datatype = serd_node_from_string(SERD_URI, (sratom->pretty_numbers)
? NS_XSD "integer" : NS_XSD "int");
} else if (type_urid == sratom->forge.Long) {
new_node = true;
object = serd_node_new_integer(*(const int64_t*)body);
datatype = serd_node_from_string(SERD_URI, (sratom->pretty_numbers)
? NS_XSD "integer" : NS_XSD "long");
} else if (type_urid == sratom->forge.Float) {
new_node = true;
object = serd_node_new_decimal(*(const float*)body, 8);
datatype = serd_node_from_string(SERD_URI, (sratom->pretty_numbers)
? NS_XSD "decimal" : NS_XSD "float");
} else if (type_urid == sratom->forge.Double) {
new_node = true;
object = serd_node_new_decimal(*(const double*)body, 16);
datatype = serd_node_from_string(SERD_URI, (sratom->pretty_numbers)
? NS_XSD "decimal" : NS_XSD "double");
} else if (type_urid == sratom->forge.Bool) {
const int32_t val = *(const int32_t*)body;
datatype = serd_node_from_string(SERD_URI, NS_XSD "boolean");
object = serd_node_from_string(SERD_LITERAL,
USTR(val ? "true" : "false"));
} else if (type_urid == sratom->midi_MidiEvent) {
new_node = true;
datatype = serd_node_from_string(SERD_URI, USTR(LV2_MIDI__MidiEvent));
uint8_t* str = (uint8_t*)calloc(size * 2 + 1, 1);
for (uint32_t i = 0; i < size; ++i) {
snprintf((char*)str + (2 * i), size * 2 + 1, "%02X",
(unsigned)(uint8_t)*((const uint8_t*)body + i));
}
object = serd_node_from_string(SERD_LITERAL, USTR(str));
} else if (type_urid == sratom->atom_Event) {
const LV2_Atom_Event* ev = (const LV2_Atom_Event*)body;
gensym(&id, 'e', sratom->next_id++);
start_object(sratom, &flags, subject, predicate, &id, NULL);
// TODO: beat time
SerdNode time = serd_node_new_integer(ev->time.frames);
SerdNode p = serd_node_from_string(SERD_URI,
USTR(LV2_ATOM__frameTime));
datatype = serd_node_from_string(SERD_URI, NS_XSD "decimal");
sratom->write_statement(sratom->handle, SERD_ANON_CONT, NULL,
&id, &p, &time, &datatype, &language);
serd_node_free(&time);
p = serd_node_from_string(SERD_URI, NS_RDF "value");
sratom_write(sratom, unmap, SERD_ANON_CONT, &id, &p,
ev->body.type, ev->body.size, LV2_ATOM_BODY(&ev->body));
if (sratom->end_anon) {
sratom->end_anon(sratom->handle, &id);
}
} else if (type_urid == sratom->forge.Tuple) {
gensym(&id, 't', sratom->next_id++);
start_object(sratom, &flags, subject, predicate, &id, type);
SerdNode p = serd_node_from_string(SERD_URI, NS_RDF "value");
flags |= SERD_LIST_O_BEGIN;
LV2_ATOM_TUPLE_BODY_FOREACH(body, size, i) {
list_append(sratom, unmap, &flags, &id, &p, &node,
i->size, i->type, LV2_ATOM_BODY(i));
}
list_end(sratom->write_statement, sratom->handle, &flags, &id, &p);
if (sratom->end_anon) {
sratom->end_anon(sratom->handle, &id);
}
} else if (type_urid == sratom->forge.Vector) {
const LV2_Atom_Vector_Body* vec = (const LV2_Atom_Vector_Body*)body;
gensym(&id, 'v', sratom->next_id++);
start_object(sratom, &flags, subject, predicate, &id, type);
SerdNode p = serd_node_from_string(SERD_URI, (const uint8_t*)LV2_ATOM__childType);
SerdNode child_type = serd_node_from_string(
SERD_URI, (const uint8_t*)unmap->unmap(unmap->handle, vec->child_type));
sratom->write_statement(sratom->handle, flags, NULL, &id, &p, &child_type, NULL, NULL);
p = serd_node_from_string(SERD_URI, NS_RDF "value");
flags |= SERD_LIST_O_BEGIN;
for (const char* i = (const char*)(vec + 1);
i < (const char*)vec + size;
i += vec->child_size) {
list_append(sratom, unmap, &flags, &id, &p, &node,
vec->child_size, vec->child_type, i);
}
list_end(sratom->write_statement, sratom->handle, &flags, &id, &p);
if (sratom->end_anon) {
sratom->end_anon(sratom->handle, &id);
}
} else if (type_urid == sratom->forge.Blank ||
type_urid == sratom->forge.Resource) {
const LV2_Atom_Object_Body* obj = (const LV2_Atom_Object_Body*)body;
const char* otype = unmap->unmap(unmap->handle,
obj->otype);
if (type_urid == sratom->forge.Blank) {
gensym(&id, 'b', sratom->next_id++);
start_object(sratom, &flags, subject, predicate, &id, otype);
} else {
id = serd_node_from_string(
SERD_URI, (const uint8_t*)unmap->unmap(unmap->handle, obj->id));
flags = 0;
start_object(sratom, &flags, NULL, NULL, &id, otype);
}
LV2_ATOM_OBJECT_BODY_FOREACH(obj, size, prop) {
const char* const key = unmap->unmap(unmap->handle, prop->key);
SerdNode pred = serd_node_from_string(SERD_URI, USTR(key));
sratom_write(sratom, unmap, flags, &id, &pred,
prop->value.type, prop->value.size,
LV2_ATOM_BODY(&prop->value));
}
if (sratom->end_anon && (flags & SERD_ANON_CONT)) {
sratom->end_anon(sratom->handle, &id);
}
} else if (type_urid == sratom->forge.Sequence) {
const LV2_Atom_Sequence_Body* seq = (const LV2_Atom_Sequence_Body*)body;
gensym(&id, 'v', sratom->next_id++);
start_object(sratom, &flags, subject, predicate, &id, type);
SerdNode p = serd_node_from_string(SERD_URI, NS_RDF "value");
flags |= SERD_LIST_O_BEGIN;
LV2_ATOM_SEQUENCE_BODY_FOREACH(seq, size, ev) {
list_append(sratom, unmap, &flags, &id, &p, &node,
sizeof(LV2_Atom_Event) + ev->body.size,
sratom->atom_Event,
ev);
}
list_end(sratom->write_statement, sratom->handle, &flags, &id, &p);
if (sratom->end_anon && subject && predicate) {
sratom->end_anon(sratom->handle, &id);
}
} else {
gensym(&id, 'b', sratom->next_id++);
start_object(sratom, &flags, subject, predicate, &id, type);
SerdNode p = serd_node_from_string(SERD_URI, NS_RDF "value");
SerdNode o = serd_node_new_blob(body, size, true);
datatype = serd_node_from_string(SERD_URI, NS_XSD "base64Binary");
sratom->write_statement(sratom->handle, flags, NULL, &id, &p, &o, &datatype, NULL);
if (sratom->end_anon && subject && predicate) {
sratom->end_anon(sratom->handle, &id);
}
serd_node_free(&o);
}
if (object.buf) {
sratom->write_statement(sratom->handle, flags, NULL,
subject, predicate, &object, &datatype, &language);
}
if (new_node) {
serd_node_free(&object);
}
return 0;
}
SRATOM_API
char*
sratom_to_turtle(Sratom* sratom,
LV2_URID_Unmap* unmap,
const char* base_uri,
const SerdNode* subject,
const SerdNode* predicate,
uint32_t type,
uint32_t size,
const void* body)
{
SerdURI buri = SERD_URI_NULL;
SerdNode base = serd_node_new_uri_from_string(USTR(base_uri), NULL, &buri);
SerdEnv* env = serd_env_new(&base);
SerdChunk str = { NULL, 0 };
serd_env_set_prefix_from_strings(env, USTR("midi"),
USTR(LV2_MIDI_PREFIX));
serd_env_set_prefix_from_strings(env, USTR("atom"),
USTR(LV2_ATOM_URI "#"));
serd_env_set_prefix_from_strings(env, USTR("rdf"), NS_RDF);
serd_env_set_prefix_from_strings(env, USTR("xsd"), NS_XSD);
serd_env_set_prefix_from_strings(env, USTR("eg"),
USTR("http://example.org/"));
SerdWriter* writer = serd_writer_new(
SERD_TURTLE,
(SerdStyle)(SERD_STYLE_ABBREVIATED |
SERD_STYLE_RESOLVED |
SERD_STYLE_CURIED),
env, &buri, serd_chunk_sink, &str);
// Write @prefix directives
serd_env_foreach(env,
(SerdPrefixSink)serd_writer_set_prefix,
writer);
sratom_set_sink(sratom, base_uri,
(SerdStatementSink)serd_writer_write_statement,
(SerdEndSink)serd_writer_end_anon,
writer);
sratom_write(sratom, unmap, SERD_EMPTY_S,
subject, predicate, type, size, body);
serd_writer_finish(writer);
serd_writer_free(writer);
serd_env_free(env);
serd_node_free(&base);
return (char*)serd_chunk_sink_finish(&str);
}
static void
read_list_value(Sratom* sratom,
LV2_Atom_Forge* forge,
SordWorld* world,
SordModel* model,
const SordNode* node,
ReadMode mode)
{
SordNode* fst = sord_get(model, node, sratom->nodes.rdf_first, NULL, NULL);
SordNode* rst = sord_get(model, node, sratom->nodes.rdf_rest, NULL, NULL);
if (fst && rst) {
read_node(sratom, forge, world, model, fst, mode);
read_list_value(sratom, forge, world, model, rst, mode);
}
sord_node_free(world, rst);
sord_node_free(world, fst);
}
static void
read_resource(Sratom* sratom,
LV2_Atom_Forge* forge,
SordWorld* world,
SordModel* model,
const SordNode* node,
LV2_URID otype)
{
LV2_URID_Map* map = sratom->map;
SordQuad q = { node, NULL, NULL, NULL };
SordIter* i = sord_find(model, q);
SordQuad match;
for (; !sord_iter_end(i); sord_iter_next(i)) {
sord_iter_get(i, match);
const SordNode* p = match[SORD_PREDICATE];
const SordNode* o = match[SORD_OBJECT];
const char* p_uri = (const char*)sord_node_get_string(p);
uint32_t p_urid = map->map(map->handle, p_uri);
if (!(sord_node_equals(p, sratom->nodes.rdf_type) &&
sord_node_get_type(o) == SORD_URI &&
map->map(map->handle, (const char*)sord_node_get_string(o)) == otype)) {
lv2_atom_forge_property_head(forge, p_urid, 0);
read_node(sratom, forge, world, model, o, MODE_BODY);
}
}
sord_iter_free(i);
}
static uint32_t
atom_size(Sratom* sratom, uint32_t type_urid)
{
if (type_urid == sratom->forge.Int) {
return sizeof(int32_t);
} else if (type_urid == sratom->forge.Long) {
return sizeof(int64_t);
} else if (type_urid == sratom->forge.Float) {
return sizeof(float);
} else if (type_urid == sratom->forge.Double) {
return sizeof(double);
} else if (type_urid == sratom->forge.Bool) {
return sizeof(int32_t);
} else if (type_urid == sratom->forge.URID) {
return sizeof(uint32_t);
} else {
return 0;
}
}
static void
read_node(Sratom* sratom,
LV2_Atom_Forge* forge,
SordWorld* world,
SordModel* model,
const SordNode* node,
ReadMode mode)
{
LV2_URID_Map* map = sratom->map;
size_t len = 0;
const char* str = (const char*)sord_node_get_string_counted(node, &len);
if (sord_node_get_type(node) == SORD_LITERAL) {
char* endptr;
SordNode* datatype = sord_node_get_datatype(node);
const char* language = sord_node_get_language(node);
if (datatype) {
const char* type_uri = (const char*)sord_node_get_string(datatype);
if (!strcmp(type_uri, (const char*)NS_XSD "int") ||
!strcmp(type_uri, (const char*)NS_XSD "integer")) {
lv2_atom_forge_int(forge, strtol(str, &endptr, 10));
} else if (!strcmp(type_uri, (const char*)NS_XSD "long")) {
lv2_atom_forge_long(forge, strtol(str, &endptr, 10));
} else if (!strcmp(type_uri, (const char*)NS_XSD "float") ||
!strcmp(type_uri, (const char*)NS_XSD "decimal")) {
lv2_atom_forge_float(forge, serd_strtod(str, &endptr));
} else if (!strcmp(type_uri, (const char*)NS_XSD "double")) {
lv2_atom_forge_double(forge, serd_strtod(str, &endptr));
} else if (!strcmp(type_uri, (const char*)NS_XSD "boolean")) {
lv2_atom_forge_bool(forge, !strcmp(str, "true"));
} else if (!strcmp(type_uri, (const char*)NS_XSD "base64Binary")) {
size_t size = 0;
void* body = serd_base64_decode(USTR(str), len, &size);
lv2_atom_forge_atom(forge, size, forge->Chunk);
lv2_atom_forge_write(forge, body, size);
free(body);
} else if (!strcmp(type_uri, LV2_ATOM__Path)) {
lv2_atom_forge_path(forge, str, len);
} else if (!strcmp(type_uri, LV2_MIDI__MidiEvent)) {
lv2_atom_forge_atom(forge, len / 2, sratom->midi_MidiEvent);
for (const char* s = str; s < str + len; s += 2) {
unsigned num;
sscanf(s, "%2X", &num);
assert(num < UINT8_MAX);
const uint8_t c = num;
lv2_atom_forge_raw(forge, &c, 1);
}
lv2_atom_forge_pad(forge, len / 2);
} else {
lv2_atom_forge_literal(
forge, str, len,
sratom->map->map(sratom->map->handle, type_uri),
0);
}
} else if (language) {
const char* prefix = "http://lexvo.org/id/iso639-3/";
const size_t lang_len = strlen(prefix) + strlen(language);
char* lang_uri = (char*)calloc(lang_len + 1, 1);
snprintf(lang_uri, lang_len + 1, "%s%s", prefix, language);
lv2_atom_forge_literal(
forge, str, len, 0,
sratom->map->map(sratom->map->handle, lang_uri));
free(lang_uri);
} else {
lv2_atom_forge_string(forge, str, len);
}
} else if (sord_node_get_type(node) == SORD_URI &&
!(sratom->object_mode == SRATOM_OBJECT_MODE_BLANK_SUBJECT
&& mode == MODE_SUBJECT)) {
if (!strcmp(str, (const char*)NS_RDF "nil")) {
lv2_atom_forge_atom(forge, 0, 0);
} else if (!strncmp(str, "file://", 7)) {
uint8_t* path = serd_file_uri_parse((const uint8_t*)str, NULL);
lv2_atom_forge_path(forge, (const char*)path, strlen((const char*)path));
free(path);
} else {
lv2_atom_forge_urid(forge, map->map(map->handle, str));
}
} else {
SordNode* type = sord_get(
model, node, sratom->nodes.rdf_type, NULL, NULL);
SordNode* value = sord_get(
model, node, sratom->nodes.rdf_value, NULL, NULL);
const uint8_t* type_uri = NULL;
uint32_t type_urid = 0;
if (type) {
type_uri = sord_node_get_string(type);
type_urid = map->map(map->handle, (const char*)type_uri);
}
LV2_Atom_Forge_Frame frame = { 0, 0 };
if (mode == MODE_SEQUENCE) {
SordNode* frame_time = sord_get(
model, node, sratom->nodes.atom_frameTime, NULL, NULL);
const char* frame_time_str = frame_time
? (const char*)sord_node_get_string(frame_time)
: "";
lv2_atom_forge_frame_time(forge, serd_strtod(frame_time_str, NULL));
read_node(sratom, forge, world, model, value, MODE_BODY);
sord_node_free(world, frame_time);
} else if (type_urid == sratom->forge.Tuple) {
lv2_atom_forge_tuple(forge, &frame);
read_list_value(sratom, forge, world, model, value, MODE_BODY);
} else if (type_urid == sratom->forge.Sequence) {
lv2_atom_forge_sequence_head(forge, &frame, 0);
read_list_value(sratom, forge, world, model, value, MODE_SEQUENCE);
} else if (type_urid == sratom->forge.Vector) {
SordNode* child_type_node = sord_get(
model, node, sratom->nodes.atom_childType, NULL, NULL);
uint32_t child_type = map->map(
map->handle, (const char*)sord_node_get_string(child_type_node));
uint32_t child_size = atom_size(sratom, child_type);
if (child_size > 0) {
lv2_atom_forge_vector_head(forge, &frame, child_size, child_type);
read_list_value(sratom, forge, world, model, value, MODE_BODY);
}
sord_node_free(world, child_type_node);
} else if (value && sord_node_equals(sord_node_get_datatype(value),
sratom->nodes.xsd_base64Binary)) {
size_t vlen = 0;
const uint8_t* vstr = sord_node_get_string_counted(value, &vlen);
size_t size = 0;
void* body = serd_base64_decode(vstr, vlen, &size);
lv2_atom_forge_atom(forge, size, type_urid);
lv2_atom_forge_write(forge, body, size);
free(body);
} else if (sord_node_get_type(node) == SORD_URI) {
lv2_atom_forge_resource(
forge, &frame, map->map(map->handle, str), type_urid);
read_resource(sratom, forge, world, model, node, type_urid);
} else {
lv2_atom_forge_blank(forge, &frame, sratom->next_id++, type_urid);
read_resource(sratom, forge, world, model, node, type_urid);
}
if (frame.ref) {
lv2_atom_forge_pop(forge, &frame);
}
sord_node_free(world, value);
sord_node_free(world, type);
}
}
SRATOM_API
void
sratom_read(Sratom* sratom,
LV2_Atom_Forge* forge,
SordWorld* world,
SordModel* model,
const SordNode* node)
{
sratom->nodes.atom_childType = sord_new_uri(world, USTR(LV2_ATOM__childType));
sratom->nodes.atom_frameTime = sord_new_uri(world, USTR(LV2_ATOM__frameTime));
sratom->nodes.rdf_first = sord_new_uri(world, NS_RDF "first");
sratom->nodes.rdf_rest = sord_new_uri(world, NS_RDF "rest");
sratom->nodes.rdf_type = sord_new_uri(world, NS_RDF "type");
sratom->nodes.rdf_value = sord_new_uri(world, NS_RDF "value");
sratom->nodes.xsd_base64Binary = sord_new_uri(world, NS_XSD "base64Binary");
sratom->next_id = 1;
read_node(sratom, forge, world, model, node, MODE_SUBJECT);
sord_node_free(world, sratom->nodes.xsd_base64Binary);
sord_node_free(world, sratom->nodes.rdf_value);
sord_node_free(world, sratom->nodes.rdf_type);
sord_node_free(world, sratom->nodes.rdf_rest);
sord_node_free(world, sratom->nodes.rdf_first);
sord_node_free(world, sratom->nodes.atom_frameTime);
sord_node_free(world, sratom->nodes.atom_childType);
memset(&sratom->nodes, 0, sizeof(sratom->nodes));
}
SRATOM_API
LV2_Atom_Forge_Ref
sratom_forge_sink(LV2_Atom_Forge_Sink_Handle handle,
const void* buf,
uint32_t size)
{
SerdChunk* chunk = (SerdChunk*)handle;
const LV2_Atom_Forge_Ref ref = chunk->len + 1;
serd_chunk_sink(buf, size, chunk);
return ref;
}
SRATOM_API
LV2_Atom*
sratom_forge_deref(LV2_Atom_Forge_Sink_Handle handle, LV2_Atom_Forge_Ref ref)
{
SerdChunk* chunk = (SerdChunk*)handle;
return (LV2_Atom*)(chunk->buf + ref - 1);
}
SRATOM_API
LV2_Atom*
sratom_from_turtle(Sratom* sratom,
const char* base_uri,
const SerdNode* subject,
const SerdNode* predicate,
const char* str)
{
SerdChunk out = { NULL, 0 };
SerdNode base = serd_node_new_uri_from_string(USTR(base_uri), NULL, NULL);
SordWorld* world = sord_world_new();
SordModel* model = sord_new(world, SORD_SPO, false);
SerdEnv* env = serd_env_new(&base);
SerdReader* reader = sord_new_reader(model, env, SERD_TURTLE, NULL);
if (!serd_reader_read_string(reader, (const uint8_t*)str)) {
SordNode* s = sord_node_from_serd_node(world, env, subject, 0, 0);
lv2_atom_forge_set_sink(
&sratom->forge, sratom_forge_sink, sratom_forge_deref, &out);
if (subject && predicate) {
SordNode* p = sord_node_from_serd_node(world, env, predicate, 0, 0);
SordNode* o = sord_get(model, s, p, NULL, NULL);
if (o) {
sratom_read(sratom, &sratom->forge, world, model, o);
sord_node_free(world, o);
} else {
fprintf(stderr, "Failed to find node\n");
}
} else {
sratom_read(sratom, &sratom->forge, world, model, s);
}
} else {
fprintf(stderr, "Failed to read Turtle\n");
}
serd_reader_free(reader);
serd_env_free(env);
sord_free(model);
sord_world_free(world);
serd_node_free(&base);
return (LV2_Atom*)out.buf;
}

View File

@@ -0,0 +1,306 @@
/*
Copyright 2012 David Robillard <http://drobilla.net>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <ctype.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include "lv2/lv2plug.in/ns/ext/atom/forge.h"
#include "lv2/lv2plug.in/ns/ext/atom/util.h"
#include "lv2/lv2plug.in/ns/ext/midi/midi.h"
#include "sratom/sratom.h"
#define NS_RDF "http://www.w3.org/1999/02/22-rdf-syntax-ns#"
#define USTR(s) ((const uint8_t*)(s))
static char** uris = NULL;
static size_t n_uris = 0;
static char*
copy_string(const char* str)
{
const size_t len = strlen(str);
char* dup = (char*)malloc(len + 1);
memcpy(dup, str, len + 1);
return dup;
}
static LV2_URID
urid_map(LV2_URID_Map_Handle handle, const char* uri)
{
for (size_t i = 0; i < n_uris; ++i) {
if (!strcmp(uris[i], uri)) {
return i + 1;
}
}
uris = (char**)realloc(uris, ++n_uris * sizeof(char*));
uris[n_uris - 1] = copy_string(uri);
return n_uris;
}
static const char*
urid_unmap(LV2_URID_Unmap_Handle handle,
LV2_URID urid)
{
if (urid > 0 && urid <= n_uris) {
return uris[urid - 1];
}
return NULL;
}
static int
test_fail(const char* fmt, ...)
{
va_list args;
va_start(args, fmt);
fprintf(stderr, "error: ");
vfprintf(stderr, fmt, args);
va_end(args);
return 1;
}
static int
test(bool top_level)
{
LV2_URID_Map map = { NULL, urid_map };
LV2_URID_Unmap unmap = { NULL, urid_unmap };
LV2_Atom_Forge forge;
lv2_atom_forge_init(&forge, &map);
Sratom* sratom = sratom_new(&map);
sratom_set_object_mode(
sratom,
top_level ? SRATOM_OBJECT_MODE_BLANK_SUBJECT : SRATOM_OBJECT_MODE_BLANK);
LV2_URID eg_Object = urid_map(NULL, "http://example.org/Object");
LV2_URID eg_one = urid_map(NULL, "http://example.org/a-one");
LV2_URID eg_two = urid_map(NULL, "http://example.org/b-two");
LV2_URID eg_three = urid_map(NULL, "http://example.org/c-three");
LV2_URID eg_four = urid_map(NULL, "http://example.org/d-four");
LV2_URID eg_true = urid_map(NULL, "http://example.org/e-true");
LV2_URID eg_false = urid_map(NULL, "http://example.org/f-false");
LV2_URID eg_path = urid_map(NULL, "http://example.org/g-path");
LV2_URID eg_urid = urid_map(NULL, "http://example.org/h-urid");
LV2_URID eg_string = urid_map(NULL, "http://example.org/i-string");
LV2_URID eg_langlit = urid_map(NULL, "http://example.org/j-langlit");
LV2_URID eg_typelit = urid_map(NULL, "http://example.org/k-typelit");
LV2_URID eg_null = urid_map(NULL, "http://example.org/l-null");
LV2_URID eg_chunk = urid_map(NULL, "http://example.org/m-chunk");
LV2_URID eg_blob = urid_map(NULL, "http://example.org/n-blob");
LV2_URID eg_blank = urid_map(NULL, "http://example.org/o-blank");
LV2_URID eg_tuple = urid_map(NULL, "http://example.org/p-tuple");
LV2_URID eg_rectup = urid_map(NULL, "http://example.org/q-rectup");
LV2_URID eg_vector = urid_map(NULL, "http://example.org/r-vector");
LV2_URID eg_seq = urid_map(NULL, "http://example.org/s-seq");
uint8_t buf[1024];
lv2_atom_forge_set_buffer(&forge, buf, sizeof(buf));
const char* obj_uri = "http://example.org/obj";
LV2_URID obj_id = urid_map(NULL, obj_uri);
LV2_Atom_Forge_Frame obj_frame;
if (top_level) {
lv2_atom_forge_resource(&forge, &obj_frame, obj_id, eg_Object);
} else {
lv2_atom_forge_blank(&forge, &obj_frame, 1, eg_Object);
}
LV2_Atom* obj = lv2_atom_forge_deref(&forge, obj_frame.ref);
// eg_one = (Int32)1
lv2_atom_forge_property_head(&forge, eg_one, 0);
lv2_atom_forge_int(&forge, 1);
// eg_two = (Int64)2
lv2_atom_forge_property_head(&forge, eg_two, 0);
lv2_atom_forge_long(&forge, 2);
// eg_three = (Float)3.0
lv2_atom_forge_property_head(&forge, eg_three, 0);
lv2_atom_forge_float(&forge, 3.0f);
// eg_four = (Double)4.0
lv2_atom_forge_property_head(&forge, eg_four, 0);
lv2_atom_forge_double(&forge, 4.0);
// eg_true = (Bool)1
lv2_atom_forge_property_head(&forge, eg_true, 0);
lv2_atom_forge_bool(&forge, true);
// eg_false = (Bool)0
lv2_atom_forge_property_head(&forge, eg_false, 0);
lv2_atom_forge_bool(&forge, false);
// eg_path = (Path)"/absolute/path"
const char* pstr = "/absolute/path";
const size_t pstr_len = strlen(pstr);
lv2_atom_forge_property_head(&forge, eg_path, 0);
lv2_atom_forge_path(&forge, pstr, pstr_len);
// eg_urid = (URID)"http://example.org/value"
LV2_URID eg_value = urid_map(NULL, "http://example.org/value");
lv2_atom_forge_property_head(&forge, eg_urid, 0);
lv2_atom_forge_urid(&forge, eg_value);
// eg_string = (String)"hello"
lv2_atom_forge_property_head(&forge, eg_string, 0);
lv2_atom_forge_string(&forge, "hello", strlen("hello"));
// eg_langlit = (Literal)"bonjour"@fr
lv2_atom_forge_property_head(&forge, eg_langlit, 0);
lv2_atom_forge_literal(
&forge, "bonjour", strlen("bonjour"),
0, urid_map(NULL, "http://lexvo.org/id/iso639-3/fra"));
// eg_typelit = (Literal)"bonjour"@fr
lv2_atom_forge_property_head(&forge, eg_typelit, 0);
lv2_atom_forge_literal(
&forge, "value", strlen("value"),
urid_map(NULL, "http://example.org/Type"), 0);
// eg_null = null
lv2_atom_forge_property_head(&forge, eg_null, 0);
lv2_atom_forge_atom(&forge, 0, 0);
// eg_chunk = 0xBEEFDEAD
uint8_t chunk_buf[] = { 0xBE, 0xEF, 0xDE, 0xAD };
lv2_atom_forge_property_head(&forge, eg_chunk, 0);
lv2_atom_forge_atom(&forge, sizeof(chunk_buf), forge.Chunk);
lv2_atom_forge_write(&forge, chunk_buf, sizeof(chunk_buf));
// eg_blob = 0xDEADBEEF
uint32_t blob_type = map.map(map.handle, "http://example.org/Blob");
uint8_t blob_buf[] = { 0xDE, 0xAD, 0xBE, 0xEF };
lv2_atom_forge_property_head(&forge, eg_blob, 0);
lv2_atom_forge_atom(&forge, sizeof(blob_buf), blob_type);
lv2_atom_forge_write(&forge, blob_buf, sizeof(blob_buf));
// eg_blank = [ a <http://example.org/Object> ]
lv2_atom_forge_property_head(&forge, eg_blank, 0);
LV2_Atom_Forge_Frame blank_frame;
lv2_atom_forge_blank(&forge, &blank_frame, top_level ? 1 : 2, eg_Object);
lv2_atom_forge_pop(&forge, &blank_frame);
// eg_tuple = "foo",true
lv2_atom_forge_property_head(&forge, eg_tuple, 0);
LV2_Atom_Forge_Frame tuple_frame;
lv2_atom_forge_tuple(&forge, &tuple_frame);
lv2_atom_forge_string(&forge, "foo", strlen("foo"));
lv2_atom_forge_bool(&forge, true);
lv2_atom_forge_pop(&forge, &tuple_frame);
// eg_rectup = "foo",true,("bar",false)
lv2_atom_forge_property_head(&forge, eg_rectup, 0);
LV2_Atom_Forge_Frame rectup_frame;
lv2_atom_forge_tuple(&forge, &rectup_frame);
lv2_atom_forge_string(&forge, "foo", strlen("foo"));
lv2_atom_forge_bool(&forge, true);
LV2_Atom_Forge_Frame subrectup_frame;
lv2_atom_forge_tuple(&forge, &subrectup_frame);
lv2_atom_forge_string(&forge, "bar", strlen("bar"));
lv2_atom_forge_bool(&forge, false);
lv2_atom_forge_pop(&forge, &subrectup_frame);
lv2_atom_forge_pop(&forge, &rectup_frame);
// eg_vector = (Vector<Int32>)1,2,3,4
lv2_atom_forge_property_head(&forge, eg_vector, 0);
int32_t elems[] = { 1, 2, 3, 4 };
lv2_atom_forge_vector(&forge, 4, forge.Int, sizeof(int32_t), elems);
// eg_seq = (Sequence)1, 2
LV2_URID midi_midiEvent = map.map(map.handle, LV2_MIDI__MidiEvent);
lv2_atom_forge_property_head(&forge, eg_seq, 0);
LV2_Atom_Forge_Frame seq_frame;
lv2_atom_forge_sequence_head(&forge, &seq_frame, 0);
const uint8_t ev1[3] = { 0x90, 0x1A, 0x1 };
lv2_atom_forge_frame_time(&forge, 1);
lv2_atom_forge_atom(&forge, sizeof(ev1), midi_midiEvent);
lv2_atom_forge_raw(&forge, ev1, sizeof(ev1));
lv2_atom_forge_pad(&forge, sizeof(ev1));
const uint8_t ev2[3] = { 0x90, 0x2B, 0x2 };
lv2_atom_forge_frame_time(&forge, 3);
lv2_atom_forge_atom(&forge, sizeof(ev2), midi_midiEvent);
lv2_atom_forge_raw(&forge, ev2, sizeof(ev2));
lv2_atom_forge_pad(&forge, sizeof(ev2));
lv2_atom_forge_pop(&forge, &seq_frame);
lv2_atom_forge_pop(&forge, &obj_frame);
const char* base_uri = "file:///tmp/base/";
SerdNode s = serd_node_from_string(SERD_URI, USTR("http://example.org/obj"));
SerdNode p = serd_node_from_string(SERD_URI, USTR(NS_RDF "value"));
SerdNode* subj = top_level ? NULL : &s;
SerdNode* pred = top_level ? NULL : &p;
char* outstr = sratom_to_turtle(
sratom, &unmap, base_uri, subj, pred,
obj->type, obj->size, LV2_ATOM_BODY(obj));
printf("# Atom => Turtle\n\n%s", outstr);
LV2_Atom* parsed = NULL;
if (top_level) {
SerdNode o= serd_node_from_string(SERD_URI, (const uint8_t*)obj_uri);
parsed = sratom_from_turtle(sratom, base_uri, &o, NULL, outstr);
} else {
parsed = sratom_from_turtle(sratom, base_uri, subj, pred, outstr);
}
if (!lv2_atom_equals(obj, parsed)) {
return test_fail("Parsed atom does not match original\n");
}
char* instr = sratom_to_turtle(
sratom, &unmap, base_uri, subj, pred,
parsed->type, parsed->size, LV2_ATOM_BODY(parsed));
printf("# Turtle => Atom\n\n%s", instr);
if (strcmp(outstr, instr)) {
return test_fail("Re-serialised string differs from original\n");
}
printf("All tests passed.\n");
free(parsed);
free(instr);
free(outstr);
sratom_free(sratom);
for (uint32_t i = 0; i < n_uris; ++i) {
free(uris[i]);
}
free(uris);
uris = NULL;
n_uris = 0;
return 0;
}
int
main(void)
{
if (test(false)) {
return 1;
} else if (test(true)) {
return 1;
}
return 0;
}

BIN
lib-src/lv2/sratom/waf vendored Executable file

Binary file not shown.

163
lib-src/lv2/sratom/wscript Normal file
View File

@@ -0,0 +1,163 @@
#!/usr/bin/env python
import os
import subprocess
import waflib.Options as Options
import waflib.extras.autowaf as autowaf
# Library and package version (UNIX style major, minor, micro)
# major increment <=> incompatible changes
# minor increment <=> compatible changes (additions)
# micro increment <=> no interface changes
SRATOM_VERSION = '0.4.2'
SRATOM_MAJOR_VERSION = '0'
# Mandatory waf variables
APPNAME = 'sratom' # Package name for waf dist
VERSION = SRATOM_VERSION # Package version for waf dist
top = '.' # Source directory
out = 'build' # Build directory
def options(opt):
opt.load('compiler_c')
autowaf.set_options(opt)
opt.add_option('--test', action='store_true', dest='build_tests',
help="Build unit tests")
opt.add_option('--static', action='store_true', dest='static',
help="Build static library")
opt.add_option('--no-shared', action='store_true', dest='no_shared',
help='Do not build shared library')
def configure(conf):
conf.load('compiler_c')
autowaf.configure(conf)
autowaf.set_c99_mode(conf)
autowaf.display_header('Sratom Configuration')
conf.env.BUILD_TESTS = Options.options.build_tests
conf.env.BUILD_SHARED = not Options.options.no_shared
conf.env.BUILD_STATIC = Options.options.static
if not conf.env.BUILD_SHARED and not conf.env.BUILD_STATIC:
conf.fatal('Neither a shared nor a static build requested')
# Check for gcov library (for test coverage)
if conf.env.BUILD_TESTS:
conf.check_cc(lib='gcov',
define_name='HAVE_GCOV',
mandatory=False)
autowaf.check_pkg(conf, 'lv2', uselib_store='LV2',
atleast_version='1.0.0', mandatory=True)
autowaf.check_pkg(conf, 'serd-0', uselib_store='SERD',
atleast_version='0.14.0', mandatory=True)
autowaf.check_pkg(conf, 'sord-0', uselib_store='SORD',
atleast_version='0.12.0', mandatory=True)
autowaf.define(conf, 'SRATOM_VERSION', SRATOM_VERSION)
autowaf.set_lib_env(conf, 'sratom', SRATOM_VERSION)
conf.write_config_header('sratom_config.h', remove=False)
autowaf.display_msg(conf, "Unit tests", str(conf.env.BUILD_TESTS))
print('')
lib_source = ['src/sratom.c']
def build(bld):
# C Headers
includedir = '${INCLUDEDIR}/sratom-%s/sratom' % SRATOM_MAJOR_VERSION
bld.install_files(includedir, bld.path.ant_glob('sratom/*.h'))
# Pkgconfig file
autowaf.build_pc(bld, 'SRATOM', SRATOM_VERSION, SRATOM_MAJOR_VERSION,
['SERD', 'SORD', 'LV2'],
{'SRATOM_MAJOR_VERSION' : SRATOM_MAJOR_VERSION})
libflags = ['-fvisibility=hidden']
libs = ['m']
defines = []
if bld.env.MSVC_COMPILER:
libflags = []
libs = []
defines = ['snprintf=_snprintf']
# Shared Library
if bld.env.BUILD_SHARED:
obj = bld(features = 'c cshlib',
export_includes = ['.'],
source = lib_source,
includes = ['.', './src'],
lib = libs,
name = 'libsratom',
target = 'sratom-%s' % SRATOM_MAJOR_VERSION,
vnum = SRATOM_VERSION,
install_path = '${LIBDIR}',
defines = defines + ['SRATOM_SHARED', 'SRATOM_INTERNAL'],
cflags = libflags)
autowaf.use_lib(bld, obj, 'SERD SORD LV2')
# Static library
if bld.env.BUILD_STATIC:
obj = bld(features = 'c cstlib',
export_includes = ['.'],
source = lib_source,
includes = ['.', './src'],
lib = libs,
name = 'libsratom_static',
target = 'sratom-%s' % SRATOM_MAJOR_VERSION,
vnum = SRATOM_VERSION,
install_path = '${LIBDIR}',
defines = defines + ['SRATOM_INTERNAL'])
autowaf.use_lib(bld, obj, 'SERD SORD LV2')
if bld.env.BUILD_TESTS:
test_libs = libs
test_cflags = ['']
if bld.is_defined('HAVE_GCOV'):
test_libs += ['gcov']
test_cflags += ['-fprofile-arcs', '-ftest-coverage']
# Static library (for unit test code coverage)
obj = bld(features = 'c cstlib',
source = lib_source,
includes = ['.', './src'],
lib = test_libs,
name = 'libsratom_profiled',
target = 'sratom_profiled',
install_path = '',
defines = defines + ['SRATOM_INTERNAL'],
cflags = test_cflags)
autowaf.use_lib(bld, obj, 'SERD SORD LV2')
# Unit test program
obj = bld(features = 'c cprogram',
source = 'tests/sratom_test.c',
includes = ['.', './src'],
use = 'libsratom_profiled',
lib = test_libs,
target = 'sratom_test',
install_path = '',
defines = defines,
cflags = test_cflags)
# Documentation
autowaf.build_dox(bld, 'SRATOM', SRATOM_VERSION, top, out)
bld.add_post_fun(autowaf.run_ldconfig)
if bld.env.DOCS:
bld.add_post_fun(fix_docs)
def test(ctx):
autowaf.pre_test(ctx, APPNAME)
os.environ['PATH'] = '.' + os.pathsep + os.getenv('PATH')
autowaf.run_tests(ctx, APPNAME, ['sratom_test'], dirs=['./src','./tests'])
autowaf.post_test(ctx, APPNAME)
def lint(ctx):
subprocess.call('cpplint.py --filter=+whitespace/comments,-whitespace/tab,-whitespace/braces,-whitespace/labels,-build/header_guard,-readability/casting,-readability/todo,-build/include src/* sratom/*', shell=True)
def fix_docs(ctx):
if ctx.cmd == 'build':
autowaf.make_simple_dox(APPNAME)
def upload_docs(ctx):
os.system("rsync -ravz --delete -e ssh build/doc/html/ drobilla@drobilla.net:~/drobilla.net/docs/sratom/")