diff options
author | David Robillard <d@drobilla.net> | 2021-04-01 14:14:32 -0400 |
---|---|---|
committer | David Robillard <d@drobilla.net> | 2021-04-01 14:14:32 -0400 |
commit | ec134d2c5f2c44a602ede280f9ce7dffd64caf41 (patch) | |
tree | 873f615a95280a860ae6f15254381bb3c7a920b6 | |
parent | 91945867cfee9e92df50149311d98eda41b16a60 (diff) | |
download | sratom-ec134d2c5f2c44a602ede280f9ce7dffd64caf41.tar.gz sratom-ec134d2c5f2c44a602ede280f9ce7dffd64caf41.tar.bz2 sratom-ec134d2c5f2c44a602ede280f9ce7dffd64caf41.zip |
WIP
-rw-r--r-- | bindings/cpp/meson.build | 8 | ||||
-rw-r--r-- | doc/c/overview.rst | 263 | ||||
-rw-r--r-- | doc/c/xml/meson.build | 8 | ||||
-rw-r--r-- | doc/meson.build | 2 | ||||
-rw-r--r-- | meson.build | 11 |
5 files changed, 278 insertions, 14 deletions
diff --git a/bindings/cpp/meson.build b/bindings/cpp/meson.build index 02f4d53..ea6d336 100644 --- a/bindings/cpp/meson.build +++ b/bindings/cpp/meson.build @@ -17,6 +17,7 @@ if get_option('strict') '-Wno-inline', '-Wno-multiple-inheritance', '-Wno-padded', + '-Wno-parentheses', '-Wno-suggest-attribute=pure', '-Wno-switch-default', '-Wno-unused-const-variable', @@ -39,6 +40,10 @@ else cpp_suppressions += [ '-Wno-nullability-extension', ] + elif cpp.get_id() == 'gcc' + cpp_suppressions += [ + '-Wno-parentheses', + ] endif endif @@ -49,7 +54,8 @@ cpp_headers = [ ] serdpp_dep = dependency('serdxx-1', - version: '>= 1.0.0') + version: '>= 1.0.0', + fallback: ['serd', 'serdxx_dep']) sratompp_dep = declare_dependency( include_directories: include_directories(['include']), diff --git a/doc/c/overview.rst b/doc/c/overview.rst index b5d75c1..2ffcfd1 100644 --- a/doc/c/overview.rst +++ b/doc/c/overview.rst @@ -1,12 +1,267 @@ -######## -Overview -######## +############ +Using Sratom +############ .. default-domain:: c .. highlight:: c -The entire API is declared in ``sratom.h``: +The sratom API is declared in ``sratom.h``: .. code-block:: c #include <sratom/sratom.h> + +Sratom supports two operations: +writing atoms to a model or string, called "dumping", +and reading atoms from a model or string, called "loading". +Each is supported by a separate object. + +************* +Dumping Atoms +************* + +Dumping atoms is supported by :struct:`SratomDumper`. +A new dumper can be allocated with :func:`sratom_dumper_new`. +It requires a :struct:`SerdWorld`, +and both a URID map (to map vocabulary during setup), +and URID unmap (for expanding URIDs in the output). +For example, assuming these are already set up appropriately in the application: + +.. code-block:: c + + SerdWorld* world = my_world(); + LV2_URID_Map* map = my_urid_map(); + LV2_URID_Unmap* unmap = my_urid_map(); + SratomDumper* dumper = sratom_dumper_new(world, map, unmap); + +Dumping Strings +=============== + +Once a dumper is allocated it can be used to write any number of atoms. +The simplest function to use is :func:`sratom_to_string`, +which takes an environment and an atom, +and returns a newly allocated string representation of the atom. + +The environment can be used to set up the base URI and any namespace prefixes for the output. +The base URI is used to convert relative paths to URIs, +and prefixes will be used to abbreviate the output. +Typically, the base URI is a file URI that points to a directory that file paths are relative to, +and prefixes are set for commonly used vocabularies. +For example: + +.. code-block:: c + + SerdStringView base = SERD_STATIC_STRING("file:///tmp/state/"); + SerdEnv* env = serd_env_new(base); + + serd_env_set_prefix( + env, + SERD_STATIC_STRING("atom"), + SERD_STATIC_STRING("http://lv2plug.in/ns/ext/atom#")); + +With the environment configured, +:func:`sratom_to_string` can be used to convert atoms to strings: + +.. code-block:: c + + LV2_Atom* atom = my_atom(); + char* string = sratom_to_string(dumper, env, atom, 0); + + fprintf(stderr, "Atom: %s\n", string); + + sratom_free(string); + +Dumping to a Statement Sink +=========================== + +More advanced use cases are supported by the more fundamental functions :func:`sratom_dump` and :func:`sratom_dump_atom`. +These write a series of statements that describe the atom to a :struct:`SerdSink`, +which can be configured to write anywhere, such as a file or model. +A subject and predicate should be provided for the main resulting statement. +For example, when writing a value for some control, +the subject might identify the device, +and the predicate the parameter: + +.. code-block:: c + + SerdModel* model = my_model(); + LV2_URID subject = urid_map("http://example.org/amp"); + LV2_URID predicate = urid_map("http://example.org/gain"); + const SerdSink* sink = serd_inserter_new(model, NULL); + + const float value = 42.0f; + + sratom_dump(dumper, + env, + sink, + subject, + predicate, + urid_map(LV2_ATOM__Float), + sizeof(float), + &value, + 0); + +Which would produce output like: + +.. code-block:: text + + eg:amp eg:gain 42.0 . + +More complex atoms might produce several statements, +for example an object may itself have several properties: + +.. code-block:: text + + eg:mixer eg:pan [ + eg:left 1.0 ; + eg:front 0.5 ; + ] . + +Representation +============== + +If no subject and predicate are given, +either explicitly with :func:`sratom_dump` or by using :func:`sratom_to_string`, +then the atom will be written as the subject. +Literals (which are not enough to form a statement) are written as the sole element of a list. +This ensures that the representation can be transmitted, stored, or transformed without loss. +For example, here is the terse string format (which is Turtle) of various atom types: + +.. code-block:: turtle + + ( "hello" ) . + + ( true ) . + + ( 1 ) . + + ( 3.0 ) . + + ( <file:///absolute/path> ) . + + ( <relative/path> ) . + + ( eg:thing ) . + + [] + a atom:Tuple ; + rdf:value ( "foo" true ) . + + [] + a atom:Vector ; + atom:childType atom:Int ; + rdf:value ( 1 2 3 4 5 ) . + + [] + a atom:Sequence ; + rdf:value ( + [ + atom:frameTime 1 ; + rdf:value "901A01"^^midi:MidiEvent + ] + [ + atom:frameTime 3 ; + rdf:value "902B02"^^midi:MidiEvent + ] + ) . + +Cleaning Up +=========== + +When finished, a dumper must be destroyed by :func:`sratom_dumper_free`: + +.. code-block:: c + + sratom_dumper_free(dumper); + +Any newly-allocated strings returned by :func:`sratom_to_string` are independent, +and may outlive the dumper that created them. +These must be individually destroyed with :func:`sratom_free`. + +************* +Loading Atoms +************* + +:struct:`SratomLoader` can construct atoms from descriptions written by a dumper. +This is typically used to load saved atoms from a file, socket, or data model. +A new loader can be allocated with :func:`sratom_loader_new`: + +.. code-block:: c + + SerdWorld* world = my_world(); + LV2_URID_Map* map = my_urid_map(); + SratomLoader* loader = sratom_loader_new(world, map); + +Once a loader is allocated it can be used to read any number of atoms. + +Loading Strings +=============== + +:func:`sratom_from_string` can be used to load atoms from strings created by :func:`sratom_to_string`: + +.. code-block:: c + + const char* string = "( 42.0 ) ."; + + LV2_Atom* atom = sratom_from_string(loader, env, string); + + do_something_with(atom); + +The environment should match the one used when dumping the string, +so that namespace prefixes can be parsed correctly. +The returned atom is newly allocated and owned by the caller, +who must eventually destroy it with :func:`sratom_free`: + +.. code-block:: c + + sratom_free(atom); + +Loading from a Model +==================== + +:func:`sratom_from_model` and the lower-level :func:`sratom_load` can be used to load atoms from a data model. +A model contains statements, +so this can be used to load atoms that were saved with :func:`sratom_dump`. +The node that represents the atom must be given to specify where in the model to find the atom. +Typically, +this is the object of a statement with the subject and predicate passed to :func:`sratom_dump`. + +For example, +given some model and node in an application, +a new atom can be allocated from its representation in the model: + +.. code-block:: c + + const SerdModel* model = my_model(); + const SerdNode* value_node = get_value(model); + + Atom* atom = sratom_from_model(loader, + base, + model, + value_node); + +The lower-level :func:`sratom_load` can be used with a :struct:`LV2_Atom_Forge` instead, +which allows writing the atom directly to an existing buffer: + +.. code-block:: c + + LV2_Atom_Forge* forge = my_buffer_writing_forge(); + + sratom_load(loader, + base, + forge, + model, + value_node); + +Cleaning Up +=========== + +When finished, a loader must be destroyed by :func:`sratom_loader_free`: + +.. code-block:: c + + sratom_loader_free(loader); + +Any newly-allocated atoms returned by :func:`sratom_from_model` are independent, +and may outlive the loader that created them. +These must be individually destroyed with :func:`sratom_free`. diff --git a/doc/c/xml/meson.build b/doc/c/xml/meson.build index fdb55cc..42fbd93 100644 --- a/doc/c/xml/meson.build +++ b/doc/c/xml/meson.build @@ -1,9 +1,9 @@ doxygen = find_program('doxygen') c_doxygen_input = [] -foreach h : c_headers - c_doxygen_input += ['..' / h] -endforeach +# foreach h : sratom_c_headers +# c_doxygen_input += ['..' / h] +# endforeach config = configuration_data() config.set('SRATOM_SRCDIR', sratom_src_root) @@ -15,5 +15,5 @@ c_doxyfile = configure_file(configuration: config, c_index_xml = custom_target('sratom-c-index.xml', command: [doxygen, '@INPUT0@'], - input: [c_doxyfile] + c_header_files, + input: [c_doxyfile] + sratom_c_header_files, output: 'index.xml') diff --git a/doc/meson.build b/doc/meson.build index 81457b9..e9f7749 100644 --- a/doc/meson.build +++ b/doc/meson.build @@ -10,7 +10,7 @@ if build_docs subdir('c') endif -if meson.version().version_compare('>=0.53.0') +if not meson.is_subproject() and meson.version().version_compare('>=0.53.0') summary('Documentation', build_docs, bool_yn: true) endif diff --git a/meson.build b/meson.build index c85b966..57498a2 100644 --- a/meson.build +++ b/meson.build @@ -53,6 +53,9 @@ if get_option('strict') '-Wno-suggest-attribute=pure', '-Wno-unsuffixed-float-constants', '-Wno-unused-const-variable', + + # FIXME: Just for tests + '-Wno-parentheses', ] elif cc.get_id() == 'msvc' c_warnings += [ @@ -84,8 +87,8 @@ if cc.get_id() == 'msvc' add_project_arguments(msvc_args, language: ['c']) endif -c_headers = ['include/sratom/sratom.h'] -c_header_files = files(c_headers) +sratom_c_headers = ['include/sratom/sratom.h'] +sratom_c_header_files = files(sratom_c_headers) sources = [ 'src/dumper.c', @@ -150,7 +153,7 @@ pkg.generate( description: 'A library for serializing LV2 atoms') # Install header to a versioned include directory -install_headers(c_headers, subdir: versioned_name / 'sratom') +install_headers(sratom_c_header_files, subdir: versioned_name / 'sratom') if not get_option('docs').disabled() subdir('doc') @@ -165,7 +168,7 @@ if is_variable('cpp') subdir('bindings/cpp') endif -if meson.version().version_compare('>=0.53.0') +if not meson.is_subproject() and meson.version().version_compare('>=0.53.0') summary('Tests', get_option('tests'), bool_yn: true) summary('Install prefix', get_option('prefix')) |