diff --git a/README b/README
index 2ebbe23df..f8f4236ce 100644
--- a/README
+++ b/README
@@ -61,8 +61,8 @@ For building Lumiera, you'll need:
* https://gtkmm.gnome.org/en/[gtkmm]
* https://cgit.freedesktop.org/xorg/lib/libXv[libXv]
* https://wiki.gnome.org/Projects/LibRsvg[lib rSVG]
- * https://git.lumiera.org/?p=debian/gdl;a=summary[lib GDL]
- * https://git.lumiera.org/?p=debian/gdlmm;a=summary[GDL-mm bindings]
+ * https://git.lumiera.org/gitweb?p=debian/gdl;a=summary[lib GDL]
+ * https://git.lumiera.org/gitweb?p=debian/gdlmm;a=summary[GDL-mm bindings]
Further information:
diff --git a/admin/scons/Platform.py b/admin/scons/Platform.py
index ea11fd9c3..fc308a45e 100644
--- a/admin/scons/Platform.py
+++ b/admin/scons/Platform.py
@@ -97,6 +97,8 @@ def configure(env):
problems.append('We need boost::lexical_cast')
if not conf.CheckCXXHeader('boost/format.hpp'):
problems.append('We need boost::format (header).')
+ if not conf.CheckCXXHeader('boost/lockfree/queue.hpp'):
+ problems.append('We need boost::lockfree (header).')
if not conf.CheckLibWithHeader('boost_program_options','boost/program_options.hpp','C++'):
problems.append('We need boost::program_options (including binary lib for linking).')
diff --git a/doc/design/application/ApplicationStart.txt b/doc/design/application/ApplicationStart.txt
index a460039e4..56d625ec4 100644
--- a/doc/design/application/ApplicationStart.txt
+++ b/doc/design/application/ApplicationStart.txt
@@ -1,42 +1,47 @@
-The Application : Start-up and Subsystems
-=========================================
+Application : Start-up and Subsystems
+=====================================
:Date: 2009
:Author: Ichthyo
//MENU: label Start-up
.the purpose of »Application-main«
-Lumiera is envisioned as a heavyweight yet coherent »**Application**« -- not so much
-as platform, framework or operating system. And, in accordance with this focus, we
-place no emphasis on possible configuration changes and state transitions within
-the running application _as a whole._ And, while in fact it is possible to close
-and load a new Session, most of the time we assume the application just to be
-``up and running'' -- all required services to be available and interfaces to
-be accessible. Without doubt, these are simplifications, but serve us well
-to cut down complexity -- yet still there needs to be one dedicated realm
-to deal with these specific concerns of configuration, dependency and lifecyle.
+Lumiera is envisaged as a heavyweight yet coherent »**Application**« -- which implies
+it is not so much seen as ``a platform'', framework or operating system. And, in line
+with this understanding, we place no emphasis on possible configuration changes and state
+transitions within the running application _as a whole._ The ability to react ``life'' to
+some global setting changes can be limited to relevant special cases. And, while it is
+indeed possible to close and load a new Session from a running application instance, in
+most parts of the code base we assume the application just to be ``up and running'' -- all
+required services are assumed to be available and interfaces to be accessible. If some of
+these assumptions break, an exception is raised and the application unwinds.
+Without doubt, these decisions represent a forcible simplification, and might be limiting
+at times, yet serve us well to cut down complexity in large parts of the code base --
+however, there needs to be _one dedicated realm_ to deal with all these specific concerns
+related to configuration, interdependency and lifecyle.
-The Application Realm
----------------------
-So we treat all these concerns within a small and self contained structure, clearly
-set apart from all the other layers, services and subsystems. This dedicated
-_Application Realm_ is organised around the ``Application main object''.footnote:[
-This is the singleton `lumiera::AppState`, which is triggered by the `main` function
-of the Lumiera Application. The sourcecode is kept in a separate folder 'src/common'
-and linked into the shared library 'liblumieracommon.so']
-It serves the purpose of pulling up and tearing down the application in a controlled
-fashion. And additionally, it provides the Interface and Config core services.
-The act of building or tearing down this core realm and main object is what creates
-the *Lifecycle* of the application. This is a succession of ``lifecycle phases'' --
-and almost all activities happen within the _operational phase,_ when everything
-is ``up and running'' or ``just available''.
+The Vessel
+----------
+So we treat all these concerns within a focused and self contained structure, called
+the »**Vessel**«, and clearly set apart from all the other layers, services and subsystems.
+This dedicated _Application Realm_ is organised around the ``Application main object''.footnote:[
+ This is the singleton `vessel::Voyage`, which is triggered by the `main` function
+ of the Lumiera Application. The sourcecode is kept in a separate folder 'src/vessel'
+ and linked into the shared library 'liblumieravessel.so']
+Its purpose is to bootstrap and tear-down the application in a controlled way,
+which includes to provide the backbone services, evaluate the start-up parameters
+and to connect and start the necessary core components. The beginning and end of
+this vessel's voyage therefore marks the *Lifecycle* of the application, as a
+succession of ``lifecycle phases'' -- where almost any activity happens within
+the _operational phase,_ when everything is considered ``up and running''.
Subsystems
~~~~~~~~~~
-However, initially the application needs to be brought up, and at the end, all
-parts need to be unwound cleanly. To organise this process, we identify a limited
-number of *Subsystems* within the Application, which are more or less independent.
+However, before becoming operational, the application must be bootstrapped, and at the end,
+all parts need to be unwound cleanly. To organise this process, we identify a limited number
+of *Subsystems* within the Application, which are self-sufficient and operate independently,
+at least to some degree.
Each link:{ldoc}/design/architecture/Subsystems.html[Subsystem] is self contained
and groups some other parts and services, which typically work together and may
be mutually dependent. These subsystems represent a grouping, applied for the purpose
@@ -61,7 +66,7 @@ the startup phase. It is the responsibility of the _Application main object_ to
pull up required functionality, which in turn might result in pulling up
further subsystems as dependencies.
-Subsystems are defined by implementing the interface `lumiera::Subsys`, which acts
+Subsystems are defined by implementing the interface `vessel::Subsys`, which acts
as façade to conduct the lifecycle, find out about dependencies and shut down
the subsystem in the end. So this interface, together with the _Subsystem Runner,_
define a lifecycle protocol; each subsystem is free to implement this as it
@@ -97,20 +102,21 @@ within the engine independently, relying on worker jobs and a thread pool.
Initialisation and Lifecycle
----------------------------
-After some discussion,footnote:[See the
-link:{rfc}/GlobalInitialization.html[GlobalInitialisation] RfC
-from spring 2008. In the beginning, we all agreed to ``keep matters simple''
-and build an `init()` function within one central piece of code everyone knows
-and hooks into. However, while the outline of the application emerged, there
-was a tension between the concern about _over-engineering_ versus the concern
-about _tangled and unmanageable complexity._ At some point, an alternative
-implementation based on lifecycle callbacks was elaborated, which then turned
-into the solution described here. Lumiera then ceased to be the typical UI
-application started by GTK, and the existing GTK code was retrofitted to
-launch from within a plug-in.]
+After some discussion,footnote:[
+ See the link:{rfc}/GlobalInitialization.html[GlobalInitialisation] RfC
+ from spring 2008. In the beginning, we all agreed to ``keep matters simple''
+ and build an `init()` function within one central piece of code everyone knows
+ and hooks into. However, while the outline of the application emerged, there
+ was a tension between the concern about _over-engineering_ versus the concern
+ about _tangled and unmanageable complexity._ At some point, an alternative
+ implementation based on lifecycle callbacks was elaborated, which then turned
+ into the solution described here. At that point, Lumiera ceased to be the
+ typical UI based application started-up by GTK-main, and the existing GTK
+ code was retrofitted to be launched from within a plug-in.
+]
the design leaned toward loosely coupled parts and a formal lifecycle; which
saves us from investigating and coding up the various interdependencies
-explicitly. Rather, the parts of the application have to comply to
+explicitly. Rather, all parts of the application have to comply to
link:{ldoc}/design/architecture/Subsystems.html#lifecycle[Lifecycle Phases],
and each part has to care for its own state transitions, invoked through
_lifecycle callbacks._ We can distinguish two distinct models how to deal
@@ -128,9 +134,9 @@ Application Start
~~~~~~~~~~~~~~~~~
* some fundamental language-level facilities will be prepared during
_static initialisation._ At some point, execution enters `main(argc,arvv)`.
- * `AppState::init()` brings up the plugin loader and opens the config-interface.
+ * `Voyage::init()` brings up the plugin loader and opens the config-interface.
* ...followed by triggering *ON_GLOBAL_INIT*
- * the main thread then pulls up the subsystems (`AppState::maybeStart(subsystem)`),
+ * the main thread then pulls up the subsystems (`Voyage::maybeStart(subsystem)`),
according to the command line options.
* within each subsystem, façade interfaces will be opened through the
interface/plug-in system.
@@ -142,7 +148,7 @@ Application Start
the main window.
* there is an *ON_GLOBAL_SHUTDOWN* event, which can be used for normal cleanup;
In case of an emergency exit, the *ON_EMERGENCY_EXIT* event is triggered alternatively.
- * the AppState destructor tears down the core systems (config-interface and pluginloader).
+ * the Voyage destructor tears down the core systems (config-interface and pluginloader).
* we establish a policy to _prohibit any non-local and non-trivial activities_ during the
tear-down phase after leaving the `main()` function.
diff --git a/doc/design/application/Config.txt b/doc/design/application/Config.txt
index dec73272b..631c2362c 100644
--- a/doc/design/application/Config.txt
+++ b/doc/design/application/Config.txt
@@ -1,15 +1,71 @@
-Lumiera Design: Application and Session Configuration
-=====================================================
+Application and Session Configuration
+=====================================
-*TODO* : 'write design document'
+.After initial discussion, this topic was postponed.
+[CAUTION]
+In its current form, as of 2026, the Lumiera application is headed towards a first
+integration of the parts developed thus far. A simple configuration file, 'setup.ini'
+is used to supply some minimal parameters for bootstrap of the application; all further
+settings are defined as local constants in the source code.
-The Lumiera application uses two quite different sources for configuration
+**Configuration and Parametrisation** of software describe a state of setting, that lies
+between the fixed structure embodied into the code and the transient work state of the
+application. It encompasses all settings and options that determine how a software system
+behaves in a specific environment, without changing its underlying source code.
-- individual __settings values__ can be loaded from an application- and user configuration in the conventional way
-- various facilities, especially in the Steam-Layer, base the actual behavour on __queries__, which are
- to be resolve employing a rules based system '(planned)'. Configuration rules will be provided by the
- application (defaults), a session template and rules stored in the actual session.
+The purpose of configuration
+----------------------------
+For a video editing application, the scope of ``configuration'' can be far reaching.
+Not only are there numerous parameters in the engine, that must be fine-tuned for optimal
+performance, but also several patterns of behaviour are available that can not be decided by
+first principle alone and must thus be left open for the user to configure to their preference.
+Some of these are linked to the actual user, some to the setup in the system, and some to the
+current project.
+Furthermore, many of these ``settings'' turn out, upon closer inspection, to be a form of
+rule-based knowledge. In a project with the scale of a movie, it is essential for a fluid
+and intuitive working style to handle some default setup and configuration of connections
+and conversions automatically, while the user can have very valid reasons to prohibit
+some other specific class of automatic conversions to be applied without explicit confirmation.
--> see also the link:rfc/ConfigLoaderDraft2008.html[Config Loader brainstorming from 2008] (implementation details)
+After some initial, prototyping for a ``config loader'', it was deemed too risky to engage
+into any kind of preliminary design without knowing the possible ramifications. +
+-> link:/x/rfc/ConfigLoaderDraft2008.html[Config Loader brainstorming from 2008]
+The following preliminary measures have now been established for the ongoing development:
+- whenever a _tweaking parameter_ is discovered, it will be extracted and marked
+ with a **language constant** in the setup or integration header of the software component.
+- whenever a _decision point_ is encountered, that can not be related to technical dependencies,
+ it is marked as a **query call** -- with a corresponding, hard-wired _faked configuration rule_.
+
+The integration of some kind of configuration rule language is considered part of the primary agenda.
+
+Requirements
+------------
+To track any insights gained regarding the requirements for configuration,
+https://issues.lumiera.org/ticket/1224[Ticket #1224 (»Layered Configuration«)]
+was added to the list of medium-term
+https://issues.lumiera.org/report/17[»Focus Topics«]
+
+The following requirements have been identified to date (2026)
+
+- It is pointless to build one huge flat global "configuration file";
+ rather, groups of configuration settings are scoped and closely related to a _local context_
+- the degree of _consistency checking_ must be tied to such a local context, where the
+ situation is reasonably clear: the consumer of specific configuration usually has
+ clear-cut requirements to demand some configuration to be mandatory, while other
+ configuration is optional. Misspelled or misplaced configuration that does not
+ fit in such a category must be flagged as error.
+- such a locally defined set of expected and optional configuration might become
+ subject to versioning (forward- / backward compatibility)
+- Configuration must be assembled from several configuration sources,
+ with clearly defined precedence and shadowing. Notably we have default configuration,
+ system-wide configuration, user specific configuration and project related configuration.
+- a _preferences UI_ must be able to alter configuration settings, thereby intelligently
+ routing the changes into the appropriate configuration source or create a suitable overlay
+- when configuration causes a decision from a rule to flip, this fact must be recorded
+ permanently in the session; the reason for this mechanism is that configuration might
+ change later, and the application must be able then to point out all places
+ affected by the change.
+- Any detected configuration change must be captured and logged as Event and thus
+ be un-doable cleanly, with all possible ripple effects.
diff --git a/doc/design/application/index.txt b/doc/design/application/index.txt
index 11b8b02d5..1bfe09a51 100644
--- a/doc/design/application/index.txt
+++ b/doc/design/application/index.txt
@@ -1,10 +1,48 @@
-Design Documents: Application Framework
-=======================================
+The Application Realm
+=====================
// Menu : prepend child ApplicationStart
- * link:Config.html[Configuration]
- * link:plugin_loader.html[Plugin Loader]
- * link:ApplicationStart.html[Application Subsystems and Lifecycle]
+Shaping the outside world through software requires a variety of effective mechanisms
+that capture, represent, and transform elements of reality. A well-designed part is
+focused on a single aspect, is coherent and cohesive in itself, with links to other
+parts based on concepts and abstraction rather then on shared technology. Yet this
+structural perspective must be complemented by a meaningful overall arrangement that
+supports the desired workflow and can be adapted to circumstances.
+In software systems, such coherency does not emerge spontaneously. It must be supported
+by definition work to establish suitable terms and interfaces, components must be
+interconnected and configured, and the overall state needs coordination.
+An application is therefore more than just a collection of software components.
+In the Lumiera Architecture, this application realm is embodied into a structure
+called the »**Vessel**«:
+
+- it is built as a library with only basic linkage to the support library
+- it can be invoked from a `main()` function, with an argument parser
+- at source code level, it provides all the types and definitions
+ required to express the _binding_ between components
+- _conceptually,_ all layers are encased in the _application vessel_
+- and while the Vessel can not just ``control'' the configuration of parts
+ on upper layers, it has to bootstrap their ability to adapt to circumstances.
+
+--
+
+--
+
+Dependencies::
+ While the code base is organised into _three layers,_ the actual implementation
+ structures are arranged into **Subsystems** that _depend_ on each other and
+ can be _started and shut down_
++
+-> link:ApplicationStart.html[Subsystems and Lifecycle]
+
+Configuration::
+ As a means to adapt to the environment and enable flexibility,
+ this topic is surprisingly intricate and development has barely scratched
+ the surface: while the effective configuration is assembled from several
+ layered sources, the meaning (and documentation) of individual settings
+ is scoped, and users can expect the ability to override some settings
+ from within the application.
++
+-> link:Config.html[Configuration]
diff --git a/doc/design/application/plugin_loader.txt b/doc/design/application/plugin_loader.txt
deleted file mode 100644
index a0e2d9a1a..000000000
--- a/doc/design/application/plugin_loader.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-Lumiera Design: Plugin system
-=============================
-
-Eventually, this will have design documentation for the Plugin system.
-
diff --git a/doc/design/architecture/Subsystems.txt b/doc/design/architecture/Subsystems.txt
index 67406f860..74e276d25 100644
--- a/doc/design/architecture/Subsystems.txt
+++ b/doc/design/architecture/Subsystems.txt
@@ -237,7 +237,7 @@ Lifecycle Events
The Application as a whole conducts a well defined lifecycle; whenever transitioning to the next phase,
a _Lifecycle Event_ is issued. Components may register a notification hook with the central _Lifecycle Manager_
(see 'include/lifecycle.h') to be invoked whenever a specific event is emitted. The process of registration
-can be simplified by planting a static variable of type `lumiera::LifecycleHook`.
+can be simplified by planting a static variable of type `vessel::LifecycleHook`.
WARNING: A callback enrolled this way needs to be callable at the respective point in the lifecycle,
otherwise the application will crash.
@@ -246,7 +246,7 @@ WARNING: A callback enrolled this way needs to be callable at the respective poi
Invoked as early as possible, somewhere in the static initialisation phase prior to entering `main()`.
In order to install a callback hook for this event, the client must plant a static variable somewhere.
-`AppState`::
+`Voyage`::
This is the Lumiera »Application Object«. It is a singleton, and should be used by `main()` solely.
While not a lifecycle event in itself, it serves to bring up some very fundamental application services:
+
@@ -255,7 +255,7 @@ WARNING: A callback enrolled this way needs to be callable at the respective poi
- the application configuration
--
+
-After starting those services within the `AppState::init()` function,
+After starting those services within the `Voyage::init()` function,
the event `ON_GLOBAL_INIT` is emitted.
`ON_GLOBAL_INIT`::
diff --git a/doc/design/plugins/PluginBrainstorm.txt b/doc/design/extension/PluginBrainstorm.txt
similarity index 100%
rename from doc/design/plugins/PluginBrainstorm.txt
rename to doc/design/extension/PluginBrainstorm.txt
diff --git a/doc/design/plugins/PluginVersioning.txt b/doc/design/extension/PluginVersioning.txt
similarity index 100%
rename from doc/design/plugins/PluginVersioning.txt
rename to doc/design/extension/PluginVersioning.txt
diff --git a/doc/design/extension/index.txt b/doc/design/extension/index.txt
new file mode 100644
index 000000000..4291329a8
--- /dev/null
+++ b/doc/design/extension/index.txt
@@ -0,0 +1,19 @@
+Extending the Application
+=========================
+
+During the inception phase, the link:/x/rfc/AllPluginInterfacesAreC.html[idea was commended]
+to bootstrap the application as a multi-lingual compound of plug-ins, for maximum flexibility
+and ease of contribution. Although this approach garnered much support initially, the ensuing
+discussions questioned its viability, with well-known plugin-based systems and frameworks
+cited as cautionary example.
+
+A prototype implementation
+(-> link:PluginBrainstorm.html[draft for the plugin interface])
+was nevertheless developed, but it proved problematic in practical use.
+The goal of a flexibly expandable application is still maintained,
+but the path to achieving it should be based on actual requirements.
+
+Development of an https://issues.lumiera.org/ticket/1212[Extension Concept #1212]
+was thus placed on the list of medium-term
+https://issues.lumiera.org/report/17[»Focus Topics«]
+
diff --git a/doc/design/index.txt b/doc/design/index.txt
index 9e3d27811..80e513f4a 100644
--- a/doc/design/index.txt
+++ b/doc/design/index.txt
@@ -7,22 +7,23 @@ Lumiera Design Documents
// Menu : prepend child design/gui
// Menu : prepend child architecture
-// Menu : append child plugins
+// Menu : append child extension
// Menu : append child workflow
// Menu : append child governance
-Lumiera is to be a professional tool for video editing on
+Lumiera aspires to be a professional tool for video editing on
GNU/Linux systems. The vision of the development team defines a modern design
for the core of a Non-Linear Editing software. A key aspect of Lumiera
is the strong separation between the user interface and the processing core.
-We are developing Lumiera with a GTK GUI but that will in no way be exclusive;
-other GUIs can be written, as well as scripts to drive the core.
+We are developing Lumiera with a general purpose GTK UI -- which is loaded as
+an optional component, so that the core can also be invoked from scripts to
+use the editing and processing capabilities of the engine.
This becomes possible by an ongoing effort to decrease coupling. Each major
component in the application strives to be open to extensions, but closed
against external modification. The presentation, the model and the ``performing''
-of the model are separate and self-contained parts of the application. Lumiera
-as a processing core will be able to perform any conceivable
-task on video and audio, maybe even tasks entirely unrelated to video editing.
+of the model are separate and self-contained parts of the application.
+Lumiera as a processing core will be able to perform any conceivable task
+on video and audio, maybe even tasks entirely unrelated to video editing.
.Workflow
*****************
@@ -52,7 +53,8 @@ specialised GUIs. The interface is the component that is closest to the user. I
provides purely visual interaction with the user. Within this work environment, the user
manipulates, organizes, loads, configures all sorts of data, especially MObjects (media
objects) and Assets. These elements are contained within a structure called the Session. +
--> link:gui/index.html[GUI/Stage-Layer design documents]
+-> link:gui/index.html[GUI/Stage-Layer design documents] +
+-> link:{ldoc}/technical/stage/index.html[GUI technical documentation]
Steam: the Transformation Layer
@@ -87,24 +89,23 @@ the screen or to external output. +
Extra Components
----------------
-The Application
-~~~~~~~~~~~~~~~
-
-The application controls the initialization and shutdown procedures as well as
-loading external elements such as plug-ins, which are widely used throughout
-Lumiera. It acts as the framework which supports core component operations. This
-framework is complemented by a library of commonly used components, algorithms and data structures. +
--> link:application/index.html[Application framework]
+The Vessel
+~~~~~~~~~~
+A structure that is anchored below all layers, yet contains everything, conceptually.
+Definitions for building common interfaces are located here, as is the mechanism for initialisation
+and shutdown of the application, the loading of bootstrap configuration and optional components.
+It encloses and coordinates all parts to work together as a coherent whole.
+This -> link:application/index.html[Application framework] is complemented by
+a link:{ldoc}/technical/library/index.html[Support-Lbrary] with commonly used components,
+algorithms and data structures.
-link:plugins/index.html[Plugins]
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Plug-ins play an important role within Lumiera since the application relies
-heavily on current FLOSS implementations and external libraries. Moreover, the
-application will be configurable and can be extended in various
-ways; whenever some extension isn't permanent or will be used only on demand, it
-is packaged as a separate module into a plug-in. For example, the GUI of Lumiera
-is a plugin. +
--> design documents regarding the link:plugins/index.html[Plugins]
+Extensions
+~~~~~~~~~~
+Lumiera uses proven and field-tested implementations for the actual media processing,
+which are available as FLOSS or open-source libraries. To avoid extensive external dependencies
+on the main application however, such libraries need to be loaded through _adaptor plug-ins._
+Furthermore, the application will be configurable and it is conceivable that external
+extensions will be created. Designing and building a future-proof framework for configuration
+and extension is an important medium-term goal for further development.
diff --git a/doc/design/lowlevel/index.txt b/doc/design/lowlevel/index.txt
index e4bf2de20..431e0f3ab 100644
--- a/doc/design/lowlevel/index.txt
+++ b/doc/design/lowlevel/index.txt
@@ -1,14 +1,30 @@
-Design Documents: Vault
-=======================
+Low-level Services
+==================
-What follows is a summary of Lumiera's *Data Handling Backend*
+Towards the _upper side_ of the Lumiera core, in »Steam Layer«,
+several components and subsystems work together to provide functionality
+that is close to the requirements of the _problem domain_ -- editing and
+rendering of media. The implementation of these features however requires
+a foundation of generic, technical services: Memory needs to be allocated,
+working buffers must be provided and managed, work tasks coordinated.
+It is hard to associate these responsibilities directly to
+some specific domain, other than just _data processing._
-This is the foundation layer responsible for any high performance or high volume
-data access. Within Lumiera, there are two main kinds of data handling:
+A common trait of all those special aspects of processing is that they
+require special care and attention to achieve the necessary level of
+performance, while they are _technical_ in nature and do not directly
+reflect and model structures of the real world.
+
+Data Handling
+-------------
+The task of editing video and processing media requires to read and write
+a significant amount of data, while using the capabilities of the hardware
+to the best degree possible. Lumiera thus needs a foundation layer for
+high volume data access; two kinds of data handling can be distinguished:
* The Session and the object models manipulated through the GUI are kept in memory.
- They are backed by a _storage backend,_ which provides database-like storage and
- especially logging, replaying and ``Undo'' of all ongoing modifications..
+ They will be backed by a _storage backend,_ which provides database-like storage
+ and especially logging, and controlled execution of _mutating actions._
* Media data is handled _frame wise_ -- prefetching data asynchronously.
The goal is to optimize CPU utilization; large scale data IO will be performed
diff --git a/doc/design/plugins/index.txt b/doc/design/plugins/index.txt
deleted file mode 100644
index 6ad7e6138..000000000
--- a/doc/design/plugins/index.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-Design Documents: Plug-In
-=========================
-
- * link:PluginBrainstorm.html[early draft for the plugin interface]
diff --git a/doc/design/workflow/Verwijlen/WorkflowProposals.txt b/doc/design/workflow/Verwijlen/WorkflowProposals.txt
index cfe579ef4..cd778d74d 100644
--- a/doc/design/workflow/Verwijlen/WorkflowProposals.txt
+++ b/doc/design/workflow/Verwijlen/WorkflowProposals.txt
@@ -1,16 +1,15 @@
Lumiera Workflow Proposals
==========================
:Author: Wouter Verwijlen
-:Date: 19 August 2025
+:Date: 16 March 2026
:TOC:
-I would like to share a first version of a collection of workflow ideas for Lumiera. These ideas come
-from having cut hundreds (or possibly thousands) of videos over the past 20 years as a professional
-editor, working in Avid Media Composer, Adobe Premiere Pro (from before it was called "Pro"),
-Lightworks and DaVinci Resolve.
+I would like to share a collection of workflow ideas for Lumiera. These ideas come from
+having cut hundreds (or possibly thousands) of videos over the past 20 years as a professional
+editor, working in Avid Media Composer, Adobe Premiere, Lightworks and DaVinci Resolve.
-This document focuses on analysing the behaviour of Non-linear Editors (NLE's), in other words
-software in which a user can edit films and videos, in order to discuss possible solutions for the
+This document focuses on analysing the behaviour of Non-linear Editors (NLE's): software
+in which a user can edit films and videos, in order to discuss possible solutions for the
design of Lumiera.
The main ideas behind these proposals are:
@@ -178,14 +177,354 @@ specific project in order to select the parts needed for the final edit. I will
which different NLE's handle this and will propose possible directions for Lumiera to support
certain workflows.
-[red]#To be written:#
+Project creation
+~~~~~~~~~~~~~~~~
+When starting a new project, a user often needs to set the project resolution and framerate. Adobe
+Premiere (optionally) shows an import panel immediately after this. The first time you drop a clip
+on a timeline, Resolve and Premiere will ask if you want to change your project settings to match
+the clip settings, when these are different.
+
+.Premiere's import panel
+image::{imgg}/wouter/v4-01-importPanel.jpg[width="100%", alt="Premiere's import panel"]
+
+Projects themselves exist within an application's database (Resolve), or as a file/folder on local or
+shared storage (Avid, Premiere, Lightworks, FCP).
+
+One of the first things that needs to be setup is the organisational structure of the project, in other
+words: the structure that's going to house all of the project's contents. Most applications use bins for
+this, a bin being simply a container for items like video clips. In a sense they are similar to folders
+on a computer's storage, except bins usually only exist within the project in your NLE. Avid's bins
+also exist as folders on local or shared storage, but this is an exception.
+
+For top level organisation, bins can either be placed in other bins (Premiere, Resolve) or in
+groups/folders (Avid, Lightworks).
+
+As we'll see throughout this document, Final Cut Pro is usually the only application that takes a
+different approach. Projects are called ``libraries'' and FCP sorts footage based on events (top level
+containers of timelines, footage and keyword collections), keywords (tags) and collections, instead
+of bins (timelines are confusingly called ``projects''). Footage, when imported, is placed in an event
+and from there all emphasis is on the metadata, in how you rate and tag (parts of) the footage. This
+also serves as a replacement of the subclips feature found in other NLE's.
+
+.Final Cut Pro's Keywords dialog. +
+image::{imgg}/wouter/v4-02-keywords.jpg[width="100%", alt="Final Cut Pro's Keywords dialog"]
+^↑``Travel part 1'' and ``Travel part 2'' on the left are events.^
+
+
+In any case, when working in a professional environment, you will probably want to start with a
+template that defines your top level structure, instead of having to recreate your entire bin setup
+for every project. Surprisingly, at the time of writing only Adobe Premiere has introduced a project
+template feature (in version 2024). In other apps you will need to manually create your own template project
+and duplicate that, or even literally copy and paste bins from a template project in a file browser (Avid).
+
+Importing footage
+~~~~~~~~~~~~~~~~~
+Every application works with clips: virtual representations of (parts of) the video files that exist on
+your preferred type of storage. Getting footage into your project (``ingest'') will create these clips in
+your project. Most apps will offer several options to do this:
+
+. Creating links to the original video files, wherever these may reside (on your computer,
+external storage, network storage or in the cloud).
+. Copying your files to a dedicated folder managed by the application (this could again be on
+local or network storage). Importing to a dedicated application folder is very useful for
+feature film editing and TV production, but is less common elsewhere in the media industry.
+Its strong point is that when your media is managed by the application, you won't have to
+re-link files when moving to a different editing station.
+. Optionally, files can be transcoded during import. New media files will be created in either
+the app's dedicated folder or to a user specified location. The transcoded files will be much
+more optimised for editing, resulting in better playback performance.
+
+The latter is part of what is known as the *offline-online* workflow, in which you work with
+optimised files, and once an edit is finished (``picture lock''), the clips on the timeline
+will be exchanged with clips that link to the original camera files. Often, after colour grading
+in an external application, all colour graded shots are rendered with their colour corrections
+and placed back onto the timeline in the NLE.
+
+A specific type of offline-online workflow is the *proxy workflow*, that allows switching
+on-the-fly between the proxy files and the original camera files and will ensure that exports
+of your video will use these original camera files when rendering. When using a proxy workflow,
+you can either create optimised files inside the application itself (or in Premiere's case, via
+Adobe Media Encoder) or attach existing proxy files that were created by a third party application
+or by the camera during recording.
+
+After importing media and possibly creating/attaching proxies, clip attributes might need altering.
+You might need to change incorrectly determined frame rates or, more commonly, change the audio
+channel mapping of your clips (e.g. setup clips with two audio channels as dual mono instead of
+stereo).
+
+Clip types
+^^^^^^^^^^
+We usually find the following types of clips in NLE's:
+
+Source clips:: they represent media files (containing video and/or audio streams) to its full
+extent, and for other types of media (most notably still images) -- these usually get a default
+duration upon import.
+Subclips:: they represent a portion of a video or audio file.
+Timeline clips:: duplicates of source clips that only exist within a timeline. Properties of
+these clips can often be altered without altering the same properties of the source clip.
+Compound clips/nested sequences:: these are in fact (sub)timelines that can contain any
+number of tracks and clips.
+Multicam clips:: (group clips in Avid), these are compound clips, in which multiple clips are
+synchronised and combined into one. This compound contains clips with different camera angles
+(for video) or audio recordings for the same event.
+Filler (Avid), FX clips (Lightworks) or Adjustment Clips (Premiere, Resolve):: these special clips
+can hold effects that are applied to all clips on lower tracks of a timeline, directly underneath.
+
+Bin types
+^^^^^^^^^
+Often there are two types of bins in which these clips sit
+
+. ``Normal'' bins.
+. Search bins (Premiere) / filters (Lightworks) / smart bins (Resolve) / smart collections
+(FCP): for these you setup certain rules based on clip names or metadata. All clips to which
+these rules apply are automatically added to these bins. This means that the same clip can
+simultaneously exist in a regular bin and a search bin, in contrast to normal bins, where each
+clip will only exist in a single bin and you'd have to duplicate this clip for it to be also
+placed in another bin (Lightworks being the exception here).
+
+.Filter options in Lightworks
+image::{imgg}/wouter/v4-03-filterOptions.jpg[alt="Filter options in Lightworks"]
+
+
+Resolve adds a third kind of bins, known as ``Power bins'': these are bins that are accessible by all projects.
+
+Bin views
+^^^^^^^^^
+Bins offer several views to see its contents. These include:
+
+* List View / Text View: all items in the bin are listed vertically. Multiple columns will show
+different kinds of metadata -- the user can choose which fields are displayed and can
+rearrange their order.
+
+* Icon View (Premiere) / Frame View (Avid) / Thumbnail View (Resolve) / Tile View
+(Lightworks): this will show a small frame from each clip in a raster. In general you're able
+to change which frame is displayed if you wish to see another.
+
+* Freeform View (Premiere): same as Icon View, but you can freely position the clips
+wherever you want. Note that Avid and Lightworks allow you to do this within Icon/Frame
+View itself.
+
+* Script View (Avid): similar to Text View, but with a frame being displayed for each clip and
+a large field for entering comments. In Script View, the vertical order of clips can be
+rearranged, in contrast to Text View, which only supports automatic sorting.
+
+* Metadata View (Resolve): similar to Avid's Script View, except you can't reorder clips.
+
+* Filmstrip View (Final Cut Pro): similar to Icon View, but [red]#TODO: missing text??#
+
+Avid is famous for allowing you to save your Text or Script View configuration as a preset that can
+be quickly recalled. Premiere allows this through its Metadata Display window, Final Cut Pro by
+Control+left clicking any column header and Lightworks via the Columns > Presets menu, but these
+methods are less straightforward than Avid's. Another neat feature that Avid has is a bin map: an
+overview of bin contents that can be toggled when in Frame View.
+
+.Creating a custom view preset in Avid Media Composer, which can be selected from the drop-down menu in the top bar.
+image::{imgg}/wouter/v4-04-customView.jpg[width="120%", alt="Creating a custom view preset"]
+
+
+Note that all apps offer a search/filter box (or button) on top of each bin view. Final Cut Pro and
+Resolve allow skimming clips from the bin view, simply by hovering the mouse on top of the
+thumbnail and moving it from left to right.
+
+
+Organising footage
+~~~~~~~~~~~~~~~~~~
+Once your footage is represented by clips in bins, organisation can begin. Wildly different methods
+exist for this. In the simplest version you will just drop your footage in one or several bins and be
+done with it. In professional environments there are often strict bin structures and naming
+conventions, and additional methods for organising are being used:
+
+* First and foremost: with multi-camera shoots and/or when audio has been recorded
+separately, now is the time to synchronise these. Create multicam clips and/or synchronise
+sound, either in the NLE itself, or in an external application. I personally create source reels
+first (see further down this list), export these to another application for syncing, import the
+synced reel back, and in case of a multicam shoot, split this reel into multiple reels and
+convert each to a multicam clip (Premiere and Resolve both support this).
+
+* Metadata. This is a very powerful way to search for or filter specific types of content and it
+could be a chapter on its own. Metadata is often created by the camera during recording,
+added during offloading by a DIT (digital imaging technician) or applied after ingest by
+assistant editors. Nowadays metadata is also added by AI/machine learning algorithms to
+help identify the contents of a clip, create transcriptions from audio, etc. Avid provides the
+option to (automatically or manually) connect clips to lines in a script (ScriptSync).
+
+* The aforementioned subclips are often used to extract sections out of a longer clip.
+
+* Sequence/timeline markers to mark points in time, or sections (so-called ranged or spanned
+markers; terminology is different per app).
++
+.Plenty of marker options in Adobe Premiere
+image::{imgg}/wouter/v4-05-markerOptions.png[width="70%", alt="Marker options in Premiere"]
++
+
+* Timeline clip notes (Avid): these can be added to a timeline clip, and will stay connected to
+this clip. You can't trim them off and they will automatically move whenever a clip moves.
+They can be burned into a render upon export. Premiere and Resolve offer clip markers
+instead -- these are similar to sequence markers, but are attached to clips.
+
+* Tagging or rating (parts of) clips (FCP and to a lesser extent Resolve). FCP's rating only
+goes as far as letting you mark clips or sections as ``favourite'' or reject clips entirely,
+but its keyword system (as described later in this chapter) is much more elaborate and useful.
+Resolve has an option to add keywords, but its workflow is quite clunky when trying to
+apply this to a section within a clip.
+
+* Clip colours. Often there exist multiple levels at which a clip can get a colour. Colours can be
+applied based on source clip (usually different colours for different media types), timeline
+clip, timeline track, offline footage, different framerates, and more. Avid has the most
+options in this field and lets you choose exactly which types of colours to display on the
+timeline. Manually set clip colours are a very useful organisational tool, e.g. to differentiate
+between several cameras, interviewed persons in a documentary or different locations.
++
+.Avid has many options for choosing how clips are coloured in the timeline
+image::{imgg}/wouter/v4-06-clipColor.png[width="50%", alt="Coosing clip colours in Avid"]
++
+
+* Flags (Resolve). Similar to markers, but these apply to entire (source) clips, while markers
+apply to a single point in time or a time range within a clip. Multiple flags can be added to
+each source clip.
+
+* Reels: source footage is divided over one or multiple timelines to be able to quickly navigate
+many clips without having to load individual clips in the source viewer. These are called
+``source reels''. A special kind of source reel is a ``sync map'', which contains all footage
+of a day of shooting from multiple cameras synced and laid out chronologically.
+FCP doesn't quite support source reels and instead offers continuous playback from the
+browser window. Resolve has a ``source tape'' option that works in a similar way.
+
+
+.Simple example of a source reel (top), converted to a sync map (bottom)
+image::{imgg}/wouter/v4-07-syncMap.png[width="100%", alt="Example of a sync map", link="{imgg}/wouter/v4-07-syncMap.png"]
+
+Viewing footage
+^^^^^^^^^^^^^^^
+Once basic organisation is in place, the editor can start watching and adding further notes/comments
+to narrow down large amounts of footage and seek out options of useful content for the edit. Most
+apps offer two types of monitors for video playback: source and record/program monitors. FCP has
+only a single monitor that switches between these two functions. Some others (Avid, Resolve) give
+users the choice between single or multi viewer modes. Lightworks and Avid support an unlimited
+amount of floating viewers.
+
+.You can open (and position) as many viewers as you like in Lightworks
+image::{imgg}/wouter/v4-08-multiViewer.jpg[width="120%", alt="Multiple viewers in Lightworks", link="{imgg}/wouter/v4-08-multiViewer.jpg"]
+
+Viewers are usually coupled with timecode display and have a ton of settings.
+I won't go into details about these.
+
+In most applications you can also watch your source footage from the bin when in Frame/Icon
+View. You'll be able to use JKL shortcuts for playback, mark in and out points and add it to the
+timeline, similar as to when the clip is loaded in the source viewer. Final Cut Pro lets you click and
+drag in-out regions in the thumbnail.
+
+Selects
+^^^^^^^
+Time to create a selection of material to consider for the rough cut. One way to do this, as
+previously described, is by creating subclips or by tagging. Drop the subclips in a bin in
+Icon / Frame View and you have a good visual overview of selected shots. This is great for selecting
+B-roll material, or for projects that require a very visual approach, f.e. trailers, music videos
+or aftermovies (not hoping to ever cut one of those again though, but that's a different story 😉).
+
+Another way to select footage is to cut selections from source clips or source reels to one or more
+selects reels: these are timelines that hold your selections and are only used for that purpose. Selects
+reels can then be loaded again as if they were a source clip, in order for an another selection to be
+made. This is called *reel-to-reel editing*. Many apps allow seeing the source timeline, either in their
+own panel (Premiere) or window (Lightworks), or by switching the timeline panel between a source
+and record mode (Avid, Resolve). A method known as _pancake timeline editing_ works when an
+application supports viewing multiple timelines simultaneously. By stacking timelines above each
+other you can easily drag selections from one timeline to another. This is possible in Premiere,
+Lightworks and Resolve.
+
+.Pancake timeline editing in Lightworks
+image::{imgg}/wouter/v4-09-pancake.png[width="110%", alt="Example of a sync map", link="{imgg}/wouter/v4-09-pancake.png"]
+
+Reels can be further managed by using markers to describe certain points in time or sections, and
+these markers can be viewed as a list in their own panel. When selecting a marker in this panel, the
+playhead of the corresponding monitor will jump to the (start) frame of this marker. Markers can
+have multiple input fields and a colour. They are one of the most important tools to be able to make
+notes and navigate large amounts of footage over extended periods of time. As an aside: Lightworks
+has an option to turn ranged markers into subclips, quite useful, as it allows you to use markers
+to make your selection.
+
+Some NLE's have a ``ripple markers'' option for timeline markers. This means markers will move
+when clips in the timeline are shortened or extended.
+
+FCP has ``todo markers'' that can be checked. And when tagging clips with keywords in FCP,
+keyword collections are automatically created in which all sections of clips with the same keyword
+can be found. It's also possible to manually create keyword collections and drag and drop clips or
+tagged sections (``content ranges'') there.
+
+Back to the reels: one advantage of reel-to-reel editing is that it's very useful to see the audio
+waveforms of your source clips on an actual timeline: this way you can freely zoom and scroll.
+Final Cut Pro will only display a clip's waveform at the bottom of the clip preview in the browser,
+but when an interview is an hour or longer, this waveform will be squeezed in a way that's of little
+use.
+
+Another advantage of reel-to-reel editing is a sense of space: you get an idea of where certain
+footage can be found (more to the left, in the middle, or at the end of a reel). Combined with
+markers, clip colours and gaps between sections, this makes it easier to find things back later. A third
+advantage is that it's easy to filter in rounds: you can narrow down your footage in multiple reel-to-reel
+selection passes.
+
+I personally often use a variation of reel-to-reel editing, in which I lift sections in my source reel.
+I then duplicate this reel, remove the first video and audio track(s) and keep the lifted parts to create
+my selects reel. The advantage here is that I can rate sections as _not useful_ (V1), _possibly useful_
+(V2), _quite useful_ (V3) or _highly useful_ (V4) by lifting the video clip one, two or three tracks up --
+see it as a 4-star rating system. I have seen other editors use this method for selecting footage,
+although in all fairness I'm not sure how widespread this technique is.
+
+.Lifting selections; also note the use of clip colours, gaps and markers for organising the selects reel.
+image::{imgg}/wouter/v4-10-selectsReel.png[width="100%", alt="Example of a sync map", link="{imgg}/wouter/v4-10-selectsReel.png"]
+
+
+In FCP you can create your own rating system by using keywords (as shown in the screenshot at the
+start of this chapter) and then having everything filtered through keyword collections, as described
+in this https://blog.frame.io/2016/10/18/make-fcp-x-log-better-1/[blog post at Frame.io].
+Quite handy as well!
+
+Proposals
+~~~~~~~~~
+* Which system(s) of organising a project and selecting footage should Lumiera support? I
+would say: most. They don't interfere with each other, so let the user choose. Definitely
+support source timelines and let people rate, tag and mark all they want. Subclips might not
+be necessary when a tagging/keyword system is present, as Final Cut has proven.
+
+* Metadata-based organising, searching and filtering of content are _must-haves_.
+
+* I would include a native rating system (1 to 5 stars should suffice) that works both on clip
+sections and entire clips, rather than FCP's favourite/reject system, as it's more granular.
+
+* As for bins-in-bins vs bins-in-folders: the first one is more flexible (bins can contain both
+media files and other bins, while folders can only contain bins) and more closely resembles
+how folders work on a PC, so my preference would be to go that route, although there's also
+something to be said for the strict division of function that folders+bins have.
+
+* I would like to propose an option to automatically create source reels based on rules you can
+set, for example: one source reel for every day of shooting. These automatic source reels
+could have a filter function to select which clips are being displayed on the timeline. This
+way it becomes easy to say something like ``show me all clips from the second day of the
+shoot from camera A''.
+
+* A versioning system for timelines is something that only Resolve has recently picked up
+with its Create (and Restore) Timeline Backup feature, and honestly I've been amazed by
+how this hasn't been a core feature in NLE's for decades now, as it makes so much sense to
+have. Let users make snapshots and perhaps make one automatically every day, without the
+need to manually duplicate and rename timelines and putting them in some sort of archive
+bin.
+
+* Importing: auto-import based on watch folders could be very useful during certain stages of
+an edit. Setup which folders to watch and whenever a new file is dropped in that folder it
+will be imported into a bin of choice. Especially handy when working with sound effects.
+However, we might not want to be scanning folders all the time.
+
+* About sound effects: there's a free application called Metadigger that let's you quickly filter
+your sound collection by metadata and then copy sound files to your project folder with a
+keyboard shortcut. Something like this, built-in, would be quite handy for those of us with
+local sound effect libraries.
+
+* A small one: I'd like each project to remember the last location you imported from. I often
+switch between projects and each time I want to import something in current NLE's, the file
+dialog points to the last used directory, which is often the wrong one.
+Not a big deal, but not ideal either.
+
-- Asset organisation: bins vs metadata-based structures (+ search bins/filters)
-- Viewing footage: single clips vs source reels; continuous playback from browser
-- Source monitor + program monitor vs a single monitor
-- Creating selects: selects reels, subclips and keyword collections
-- On markers and notes
-- From selects to editing in the timeline: Timelines in the source viewer: reel to reel editing
Chapter 2: the timeline
-----------------------
@@ -283,7 +622,7 @@ Editors often proudly share screenshots of their timelines on social media, and
impressive, but these are in fact pretty fragile structures.
.One of my own timelines, which is relatively simple by comparison to those of many Hollywood movies
-image::{imgg}/wouter/01-timeline.jpg[width="110%", alt="Screenshot of a timeline", link="{imgg}/wouter/01-timeline.jpg"]
+image::{imgg}/wouter/v3-01-timeline.jpg[width="110%", alt="Screenshot of a timeline", link="{imgg}/wouter/v3-01-timeline.jpg"]
So naturally, a question would be: what will happen if we would let go of the track paradigm? This
is what Final Cut Pro has done, starting from the rewrite of Final Cut Pro X. At the time, a
@@ -300,10 +639,10 @@ primary storyline, and all connected clips automatically move with it. With a mo
ignore clip connections, so that you can also easily move a primary clip elsewhere without its
connected siblings coming along.
-image::{imgg}/wouter/02-trim-magnetic-1.jpg[width="100%", alt="(before trim)"]
+image::{imgg}/wouter/v3-02-trim-magnetic-1.jpg[width="100%", alt="(before trim)"]
.Extending one clip will automatically move all connected clips in order to keep sync
-image::{imgg}/wouter/02-trim-magnetic-2.jpg[width="100%", alt="(after trim)"]
+image::{imgg}/wouter/v3-02-trim-magnetic-2.jpg[width="100%", alt="(after trim)"]
_Sounds good._ Why not just copy this? One reason is that FCP assumes that all clips that are not on
the primary storyline should be connected to this primary storyline. This might work well for fiction
@@ -318,7 +657,7 @@ How else could we group clips together that ought to be connected? +
We could create groups that are directly editable, like so:
.Compound clips
-image::{imgg}/wouter/03-grouped-1.png[width="100%", alt="Timeline with compound clips"]
+image::{imgg}/wouter/v3-03-grouped-1.png[width="100%", alt="Timeline with compound clips"]
However, there are a few problems with this: we expect rendering to happen from top to bottom, in
which case the b-roll would cover the subtitles. On top of that, it's hard to see at which points video
@@ -327,7 +666,7 @@ clips overlap. Last but not least: it looks rather unorganised.
Can we restructure this? Perhaps like this:
.Overlapping compound clips
-image::{imgg}/wouter/03-grouped-2.png[width="100%", alt="Timeline with stacked overlapping compound clips"]
+image::{imgg}/wouter/v3-03-grouped-2.png[width="100%", alt="Timeline with stacked overlapping compound clips"]
But how exactly would a user interact with a timeline like this? I will leave the answer to that
question for an actual design document, as for now I just wanted to show the concept of grouping so
@@ -354,7 +693,7 @@ FCP's precision editor. It doesn't change the working of keyboard shortcuts or t
alters the timeline via animations in a very fluid way.
.Final Cut Pro's precision editor
-image::{imgg}/wouter/04-fcp-precision-editor.jpg[precision editor]
+image::{imgg}/wouter/v3-04-fcp-precision-editor.jpg[precision editor]
Another example is the Trim View in DaVinci Resolve: whenever you perform a trimming
operation, the program monitor displays a trim view (showing the frames left and right of the cut
@@ -386,7 +725,7 @@ the use of a _contextual bar_ that appears over the bottom part of the timeline
mode is active.
.Contextual bar with options for the mode/tool
-image::{imgg}/wouter/05-contextual-bar.png[width="100%", alt="contextual bar"]
+image::{imgg}/wouter/v3-05-contextual-bar.png[width="100%", alt="contextual bar"]
Currently I'm thinking of using this bar on two or three occasions:
@@ -467,10 +806,10 @@ One last thing I would like to address is the destruction that an insert operati
this can be prevented by proper track management, but you can wonder why you would ever want
an insert action to cause the following:
-image::{imgg}/wouter/06-sync-insert-1.png[height=110, alt="sync insert"]
+image::{imgg}/wouter/v3-06-sync-insert-1.png[height=110, alt="sync insert"]
.Inserting a clip with sync locks enabled for V2 might split a clip in Avid Media Composer.
-image::{imgg}/wouter/06-sync-insert-2.png[height=110, alt="sync insert"]
+image::{imgg}/wouter/v3-06-sync-insert-2.png[height=110, alt="sync insert"]
In this case, if you'd like the clips on V2 to stay in sync, the overlapping clip will be split in two.
If you don't want this to happen you would have to move the overlapping clip to another track
@@ -622,7 +961,7 @@ will move both the viewport and playhead. Clicking the left mouse button will ac
position and close the widget.
+
.Skim widget
-image::{imgg}/wouter/07-1-skim.png[width="100%", alt="A skim widget rendered as overlay"]
+image::{imgg}/wouter/v3-07-1-skim.png[width="100%", alt="A skim widget rendered as overlay"]
Autoscroll widget:: when the user moves the mouse cursor slightly left or right, it will enter zones
@@ -631,14 +970,14 @@ When the user moves the mouse farther away from the initial starting point, the
increase. This will also work vertically. The playhead will move along as well.
+
.Autoscroll widget
-image::{imgg}/wouter/07-2-autoscroll.png[width="100%", alt="A widget for auto-scrolling"]
+image::{imgg}/wouter/v3-07-2-autoscroll.png[width="100%", alt="A widget for auto-scrolling"]
Zoom widget:: moving the mouse left or right from the centre will zoom horizontally, up and
down will zoom vertically.
+
.Zoom widget
-image::{imgg}/wouter/07-3-zoom.png[width="100%", alt="An overlay widget to control zooming"]
+image::{imgg}/wouter/v3-07-3-zoom.png[width="100%", alt="An overlay widget to control zooming"]
Mouse-only navigation:
@@ -648,7 +987,7 @@ mouse button. When released, it will commit to the new location/view. If a user
immediately releases the button, a regular context menu will appear.
+
.Combined skim, zoom and scroll widget
-image::{imgg}/wouter/07-4-combined.png[width="100%", alt="Overlay widget to combin skim, zoom and autoscrol function"]
+image::{imgg}/wouter/v3-07-4-combined.png[width="100%", alt="Overlay widget to combin skim, zoom and autoscrol function"]
Why popup widgets?
@@ -708,7 +1047,7 @@ what any other NLE does at the moment, but enabling multi-clip selection by keyb
good reason to go in this direction.
.Selection mockup: selected clips are highlighted in yellow, the cursor is a white dot.
-image::{imgg}/wouter/08-selection.png[width="100%", alt="selecting clips"]
+image::{imgg}/wouter/v3-08-selection.png[width="100%", alt="selecting clips"]
For selecting, we can introduce an ``add to selection'' key which adds the highlighted clip to the
current selection (apart from the convention of using Ctrl+mouse click). We could also think of
@@ -723,10 +1062,10 @@ Most NLE's have functions for selecting many clips at once, called ``select forw
backward''. In Adobe Premiere these are tools: click and you select all clips to either the left or right
of the mouse cursor, and using Shift will toggle between selecting all clips on a single track or on
all tracks (it doesn't respect track activation status though, which it should). Other NLE's (Resolve,
-Avid, Lightworks) only have keyboard shortcuts for these functions, which do only affect activated
-tracks. This is a bit faster: in Premiere you need to switch to the Select Forward/Backward Tool,
-make your selection, then switch back to your previous tool. With a keyboard shortcut you only
-have to press a single key (if your track selection is correct).
+Avid, Lightworks) have keyboard shortcuts for these functions (in Avid you can place a button in the
+GUI as well), which do affect activated tracks only. This is a bit faster: in Premiere you need to
+switch to the Select Forward/Backward Tool, make your selection, then switch back to your previous
+tool. With a keyboard shortcut you only have to press a single key (if your track selection is correct).
Arranging clips
~~~~~~~~~~~~~~~
@@ -789,7 +1128,7 @@ entering trim mode.
* Lightworks has a trim mode that defaults to ripple trimming, unless you specifically use the
“drag to black” feature by Control-clicking trim edges when entering trim mode. When
using the keyboard, one needs to mark a section and use the Remove command (similar to
-Avid''s ``lift'') to create a gap.
+Avid's ``lift'') to create a gap.
Next to ripple/non-ripple trimming there are three other edit operations closely related to trimming
that need to be mentioned:
@@ -816,10 +1155,10 @@ tracks automatically stay in sync. This means (manually) enabling or disabling t
track. Once set, trimming a single clip can be enough to have all tracks move along, although you
might still need to manually select trim sides for overlapping clips to get the desired result.
-image::{imgg}/wouter/09-sync-trim-1.png[height=140, alt="trimming with sync-lock(before)"]
+image::{imgg}/wouter/v3-09-sync-trim-1.png[height=140, alt="trimming with sync-lock(before)"]
.Avid's sync locks will split longer clips by default, in order to keep sync. Such destructive behaviour should be avoided in Lumiera.
-image::{imgg}/wouter/09-sync-trim-2.png[height=140, alt="trimming with sync-lock(after)"]
+image::{imgg}/wouter/v3-09-sync-trim-2.png[height=140, alt="trimming with sync-lock(after)"]
Without sync locks you will have to select trim sides on every track that needs to stay in sync,
although, as we'll see, even that can be accomplished by a single keystroke. FCP is the exception
@@ -850,7 +1189,7 @@ These commands can be combined: when pressing multiple keys, new trim sides are
selection. This allows for quickly selecting many trim sides on many tracks.
.One keystroke led to the selection of these four trim sides in Lightworks
-image::{imgg}/wouter/10-trim-side.png["select trim side"]
+image::{imgg}/wouter/v3-10-trim-side.png["select trim side"]
Another feature that was already mentioned in a previous chapter, is FCP's precision editor, which
can be triggered by double clicking a cut or by keyboard shortcut. This shows how much footage
@@ -937,7 +1276,7 @@ exited automatically whenever the user clicks in an empty spot of the timeline o
mode key (T). This key can also be used to return to the last-used trim configuration.
.Mockup of the trim mode. The striped area marks the pre- and post-roll that will be previewed.
-image::{imgg}/wouter/11-trim-mode.png[width="100%", alt="using trim mode"]
+image::{imgg}/wouter/v3-11-trim-mode.png[width="100%", alt="using trim mode"]
Splitting and merging clips
@@ -973,7 +1312,7 @@ I would like to propose the ability to divide a timeline into multiple sections.
will have a header in the ruler that can be edited, to give each section a name (similar to how
duration markers in Premiere are displayed).
-image::{imgg}/wouter/12-sections.png[width="100%", alt="Timeline with sections"]
+image::{imgg}/wouter/v3-12-sections.png[width="100%", alt="Timeline with sections"]
The benefits of sections:
@@ -1030,7 +1369,7 @@ transition from a clip's start or end to the position of the playhead.
* Avid has a configuration panel for adding transitions:
-image::{imgg}/wouter/13-transition.png[align="center", alt="transition properties"]
+image::{imgg}/wouter/v3-13-transition.png[align="center", alt="transition properties"]
* Some apps allow adding transitions to every cut in the in-out range (Avid, Lightworks). Avid
gives you the option to skip cuts that already have a transition. Very useful for adding short
@@ -1100,6 +1439,12 @@ Chapter 3: finishing
--------------------
[red]#To be written.#
+- Nodes vs Layers
+- Audio mixing
+- Color grading
+- Visual effects compositing
+- Titling
+
Chapter 4: a broader GUI concept
--------------------------------
[red]#To be written.#
diff --git a/doc/devel/Status.txt b/doc/devel/Status.txt
index ea1389ec1..d35493187 100644
--- a/doc/devel/Status.txt
+++ b/doc/devel/Status.txt
@@ -51,7 +51,7 @@ Current Release
[red]#Lumiera is not usable yet#.
- A »Preview Release« was
- https://git.lumiera.org/?p=LUMIERA;a=tag;h=refs/tags/v0.pre.04[published at Dec 2, 2025]
+ https://git.lumiera.org/gitweb?p=LUMIERA;a=tag;h=refs/tags/v0.pre.04[published at Dec 2, 2025]
- link:/debian[DEB packages]
were built for »Trixie« and »Noble«
diff --git a/doc/devel/meeting_summary/2008-10-10.txt b/doc/devel/meeting_summary/2008-10-10.txt
index 0f33162ed..f5ea10590 100644
--- a/doc/devel/meeting_summary/2008-10-10.txt
+++ b/doc/devel/meeting_summary/2008-10-10.txt
@@ -214,7 +214,7 @@ Interface Definition Language
-----------------------------
In his work on the plugin loader, _Cehteh_ created a first draft how to export an interface, and calls for review.
An example can be found in
-https://git.lumiera.org/?p=LUMIERA;a=blob;f=tests/backend/test-interfaces.c;h=09fa25afa3cb57b79a2717d0bf3a8253afeba000;hb=ebcc5c7fd2d8700f3375e3309b724ac2517a0f40[tests/backend/test-interfaces.c]
+https://git.lumiera.org/gitweb?p=LUMIERA;a=blob;f=tests/backend/test-interfaces.c;h=09fa25afa3cb57b79a2717d0bf3a8253afeba000;hb=ebcc5c7fd2d8700f3375e3309b724ac2517a0f40[tests/backend/test-interfaces.c]
An interface is a list of »slots« mapping functions. The interface descriptor is itself realised as interface,
and thus can be versioned, extended and specialised.
diff --git a/doc/devel/meeting_summary/2009-01-14.txt b/doc/devel/meeting_summary/2009-01-14.txt
index 4531e2702..ab0b52f45 100644
--- a/doc/devel/meeting_summary/2009-01-14.txt
+++ b/doc/devel/meeting_summary/2009-01-14.txt
@@ -95,7 +95,7 @@ For now the focus is on getting a single frame into the gui and there will be ti
The devs agreed to meet up on Saturday to get the latest version up and running.
-NOTE: Demonstration in https://git.lumiera.org/?p=LUMIERA;a=blob;f=src/common/guifacade.cpp;h=60a16d0f67bd95b43e44662daa9c0525235e14f5;hb=5f10e65852de2c51364c2e2a5a1cf29cae81c6b2#l64[guifacade.cpp]
+NOTE: Demonstration in https://git.lumiera.org/gitweb?p=LUMIERA;a=blob;f=src/common/guifacade.cpp;h=60a16d0f67bd95b43e44662daa9c0525235e14f5;hb=5f10e65852de2c51364c2e2a5a1cf29cae81c6b2#l64[guifacade.cpp]
(The thread shall be forked from within the GUI code not from the facade)
This was discussed and ichthyo has already pushed a new cleaned up state and resolved most of the dependency problems with the liblumiera. It raised the question: do we prefer a UI facade to a GUI facade or do we want an extra script facade someday?
diff --git a/doc/devel/rfc/ApplicationStructure.txt b/doc/devel/rfc/ApplicationStructure.txt
index f08c94c3e..1732b466e 100644
--- a/doc/devel/rfc/ApplicationStructure.txt
+++ b/doc/devel/rfc/ApplicationStructure.txt
@@ -191,7 +191,7 @@ don't think we get much program options, maybe something to set a GUI skin.
Moreover, I've written last year a thin wrapper around the commandline and
integrated it with the boost options parser such that user code can receive the
remaining options as a vector of `std::string`s. Please have a look at
-https://git.lumiera.org/?p=LUMIERA;a=blob;f=tests/common/mainsuite.cpp;h=455bfd98effd0b7dbe6597f712a1bdfa35232308;hb=80e1e382f42512ebf2e10a802f77e50327b8fb73[the test class runner main]
+https://git.lumiera.org/gitweb?p=LUMIERA;a=blob;f=tests/common/mainsuite.cpp;h=455bfd98effd0b7dbe6597f712a1bdfa35232308;hb=80e1e382f42512ebf2e10a802f77e50327b8fb73[the test class runner main]
for an usage example. I really want our Lumiera main to be clean and expressive
in the way showed there. Probably the most important part of the startup is
pulling up the session core; because of that I think most of the startup
diff --git a/doc/devel/rfc/ArchitectureOverview.txt b/doc/devel/rfc/ArchitectureOverview.txt
index 625060e25..ac4390c45 100644
--- a/doc/devel/rfc/ArchitectureOverview.txt
+++ b/doc/devel/rfc/ArchitectureOverview.txt
@@ -15,8 +15,8 @@ This proposal intends to capture envisioned Architecture of the Application.
image:{ldoc}/devel/draw/rendered/Lumi.Architecture-1.png[Overview of Lumiera Architecture]
^The SVG source of this drawing is
-https://git.lumiera.org/?p=LUMIERA;a=blob_plain;f=doc/devel/draw/Lumi.Architecture-1.svg;hb=HEAD[maintained in GIT(2008)]·
-https://git.lumiera.org/?p=LUMIERA;a=blob_plain;f=doc/devel/draw/Lumi.Architecture-2.svg;hb=HEAD[(current: 2022)]^
+https://git.lumiera.org/gitweb?p=LUMIERA;a=blob_plain;f=doc/devel/draw/Lumi.Architecture-1.svg;hb=HEAD[maintained in GIT(2008)]·
+https://git.lumiera.org/gitweb?p=LUMIERA;a=blob_plain;f=doc/devel/draw/Lumi.Architecture-2.svg;hb=HEAD[(current: 2022)]^
Description
@@ -75,7 +75,7 @@ Conclusion
----------
Accepted. The drawing was moved into the GIT tree. +
It was upgraded and reworked
-https://git.lumiera.org/?p=LUMIERA;a=blob_plain;f=doc/devel/draw/Lumi.Architecture-2.svg;hb=0b9f2e2c3139cad542013caac593cb5972a2e3f6[in 2022]
+https://git.lumiera.org/gitweb?p=LUMIERA;a=blob_plain;f=doc/devel/draw/Lumi.Architecture-2.svg;hb=0b9f2e2c3139cad542013caac593cb5972a2e3f6[in 2022]
Back to link:/x/DesignProcess.html[Lumiera Design Process overview]
diff --git a/doc/devel/rfc/DesignRenderNodesInterface.txt b/doc/devel/rfc/DesignRenderNodesInterface.txt
index 0dc00a399..7c716f071 100644
--- a/doc/devel/rfc/DesignRenderNodesInterface.txt
+++ b/doc/devel/rfc/DesignRenderNodesInterface.txt
@@ -106,7 +106,7 @@ details of carrying out the operations are much more involved.
Please see the
link/wiki/renderengine.html#Rendering[Development internal doc (TiddlyWiki)]
and the
-https://git.lumiera.org/?p=LUMIERA;a=blob;f=src/proc/engine/procnode.hpp;h=9cf3a2ea8c33091d0ee992ec0fc8f37bb5874d34;hb=f9452f654cf39a4abbbeecfd81bef51aa347b321[Draft: ProcNode (src)]
+https://git.lumiera.org/gitweb?p=LUMIERA;a=blob;f=src/proc/engine/procnode.hpp;h=9cf3a2ea8c33091d0ee992ec0fc8f37bb5874d34;hb=f9452f654cf39a4abbbeecfd81bef51aa347b321[Draft: ProcNode (src)]
for details
(and/or contact Ichthyo for in-depth discussion of those technical details)
diff --git a/doc/devel/rfc/DevelopmentFramework.txt b/doc/devel/rfc/DevelopmentFramework.txt
index 0a430d65e..8a4000f53 100644
--- a/doc/devel/rfc/DevelopmentFramework.txt
+++ b/doc/devel/rfc/DevelopmentFramework.txt
@@ -149,7 +149,7 @@ We soon settled upon the following toolchain, which is used up to today:
history is consolidated eventually into the
link:{rfc}/MasterRepositorySetup.html#historical_remark[»official Lumiera repository«],
which is made accessible at
- https://git.lumiera.org/?p=LUMIERA;a=summary[`git://git.lumiera.org/LUMIERA`]
+ https://git.lumiera.org/gitweb?p=LUMIERA;a=summary[`git://git.lumiera.org/LUMIERA`]
- We never used link:{rfc}/GitSubmoduleTransistion.html#_comments[Git submodules]...
- https://www.scons.org/[SCons] became the primary buildsystem soon,
with Autotools discontinued in 2011
@@ -158,14 +158,14 @@ We soon settled upon the following toolchain, which is used up to today:
- Website and documentation pages are generated by
https://asciidoc-py.github.io/[Asciidoc], with source files for
documentation maintained
- https://git.lumiera.org/?p=LUMIERA;a=blob;f=doc/index.txt;h=9bc0f11e6fb67588388e7616320b695841571278;hb=20f3252892d5b53a05ecd8aeb571122806baba17[in-tree],
+ https://git.lumiera.org/gitweb?p=LUMIERA;a=blob;f=doc/index.txt;h=9bc0f11e6fb67588388e7616320b695841571278;hb=20f3252892d5b53a05ecd8aeb571122806baba17[in-tree],
published
- https://git.lumiera.org/?p=website;a=blob;f=build_website.sh;h=60b90e18d5732d66566baf2c20a217212a5dcece;hb=aefc91e13a95a3c742dc8143c374ec982e0aa56b[automatically on push].
+ https://git.lumiera.org/gitweb?p=website;a=blob;f=build_website.sh;h=60b90e18d5732d66566baf2c20a217212a5dcece;hb=aefc91e13a95a3c742dc8143c374ec982e0aa56b[automatically on push].
- A https://classic.tiddlywiki.com/[TiddlyWiki] is used for development notes
- for Unit-Tests, we use our own minimalist
- https://git.lumiera.org/?p=LUMIERA;a=blob;f=src/lib/test/run.hpp;h=035633af9bde7a8053bcd304baffc21693dcf031;hb=20f3252892d5b53a05ecd8aeb571122806baba17[Test-runner].
+ https://git.lumiera.org/gitweb?p=LUMIERA;a=blob;f=src/lib/test/run.hpp;h=035633af9bde7a8053bcd304baffc21693dcf031;hb=20f3252892d5b53a05ecd8aeb571122806baba17[Test-runner].
and a
- https://git.lumiera.org/?p=LUMIERA;a=blob;f=tests/test.sh;h=8c13810eb475bbacd97c528607e6750f47bb145e;hb=20f3252892d5b53a05ecd8aeb571122806baba17[shell script]
+ https://git.lumiera.org/gitweb?p=LUMIERA;a=blob;f=tests/test.sh;h=8c13810eb475bbacd97c528607e6750f47bb145e;hb=20f3252892d5b53a05ecd8aeb571122806baba17[shell script]
to support definition of test collections.
- A Debian package is maintained with
https://wiki.debian.org/PackagingWithGit[git-buildpackage] and published
diff --git a/doc/devel/rfc/DistributedDevelopmentFramework.txt b/doc/devel/rfc/DistributedDevelopmentFramework.txt
index 9f8e50592..e2d43d7cc 100644
--- a/doc/devel/rfc/DistributedDevelopmentFramework.txt
+++ b/doc/devel/rfc/DistributedDevelopmentFramework.txt
@@ -68,9 +68,9 @@ rather -- a task no one was willing to take on.
Yet the Lumiera project succeeded in building a web presence based on
https://asciidoc-py.github.io/[Asciidoc] sources
-https://git.lumiera.org/?p=website;a=summary[checked into Git],
+https://git.lumiera.org/gitweb?p=website;a=summary[checked into Git],
with a lightweight
-https://git.lumiera.org/?p=website;a=blob;f=build_website.sh;h=60b90e18d5732d66566baf2c20a217212a5dcece;hb=aefc91e13a95a3c742dc8143c374ec982e0aa56b[commit-hook script]
+https://git.lumiera.org/gitweb?p=website;a=blob;f=build_website.sh;h=60b90e18d5732d66566baf2c20a217212a5dcece;hb=aefc91e13a95a3c742dc8143c374ec982e0aa56b[commit-hook script]
to automatically publish any changes on git-push -- a scheme
which comes close to the gist of this RfC.
diff --git a/doc/devel/rfc/MasterRepositorySetup.txt b/doc/devel/rfc/MasterRepositorySetup.txt
index 81d092acc..86f499f76 100644
--- a/doc/devel/rfc/MasterRepositorySetup.txt
+++ b/doc/devel/rfc/MasterRepositorySetup.txt
@@ -16,7 +16,7 @@ This describes how the shared MASTER is set up and syncronized.
Description
~~~~~~~~~~~
We have now a shared master repository in
-https://git.lumiera.org/?p=LUMIERA;a=summary[/git/LUMIERA].
+https://git.lumiera.org/gitweb?p=LUMIERA;a=summary[/git/LUMIERA].
- The public/anonymous git url is [yellow-background]#`git://git.lumiera.org/LUMIERA`#
- for people with ssh access it is pushable at [purple]#`UID@git.lumiera.org:/git/LUMIERA`#.
@@ -71,10 +71,10 @@ That being said -- the shared master at [yellow-background]#`git://git.lumiera.o
still contains the _official_ state of the Lumiera codebase, while
actual development is published first in a repository per developer
(so effectively in
-https://git.lumiera.org/?p=lumiera/ichthyo;a=summary[the Ichthyo repository]
+https://git.lumiera.org/gitweb?p=lumiera/ichthyo;a=summary[the Ichthyo repository]
for the time being);
development is consolidated intermittently into the
-https://git.lumiera.org/?p=LUMIERA;a=summary[LUMIERA Git].
+https://git.lumiera.org/gitweb?p=LUMIERA;a=summary[LUMIERA Git].
''''
diff --git a/doc/devel/rfc/NoBugFlags.txt b/doc/devel/rfc/NoBugFlags.txt
index e6b4ad19d..0d2afdbfc 100644
--- a/doc/devel/rfc/NoBugFlags.txt
+++ b/doc/devel/rfc/NoBugFlags.txt
@@ -18,7 +18,7 @@ Propose a documentation/planning about the setup.
Description
~~~~~~~~~~~
Take a look at my draft at:
-https://git.lumiera.org/?p=LUMIERA;a=blob;f=doc/devel/nobug_flags.txt;h=325141acb52a7be7f75425359b6057c74ed30253;hb=a03e3c5e73a4c0be2264ac4e4e0f02eb8749837b[nobug_flags.txt]
+https://git.lumiera.org/gitweb?p=LUMIERA;a=blob;f=doc/devel/nobug_flags.txt;h=325141acb52a7be7f75425359b6057c74ed30253;hb=a03e3c5e73a4c0be2264ac4e4e0f02eb8749837b[nobug_flags.txt]
I've added the things I planning for the backend, others might add their own
plans there too. So far this is an early draft, comments welcome.
diff --git a/doc/devel/rfc/SchedulerRequirements.txt b/doc/devel/rfc/SchedulerRequirements.txt
index e3a90503d..bfc3c1cc0 100644
--- a/doc/devel/rfc/SchedulerRequirements.txt
+++ b/doc/devel/rfc/SchedulerRequirements.txt
@@ -210,7 +210,7 @@ during this effort leads to the following refinements:
- Workers manage their capacity through a statistical distribution of _sleep times._
In this form, the proposal can be considered as implemented. +
-^(see -> https://git.lumiera.org/?p=LUMIERA;a=commit;h=d71eb37[d71eb37]
+^(see -> https://git.lumiera.org/gitweb?p=LUMIERA;a=commit;h=d71eb37[d71eb37]
and https://issues.lumiera.org/ticket/1344[#1344])^
Ichthyostega:: '2024-04-20 01:55 CEST'
diff --git a/doc/devel/uml/BoUML-diagrams.txt b/doc/devel/uml/BoUML-diagrams.txt
index 72ea556da..869c4195b 100644
--- a/doc/devel/uml/BoUML-diagrams.txt
+++ b/doc/devel/uml/BoUML-diagrams.txt
@@ -49,6 +49,4 @@ On occasion, we'll replace them by drawings from our current UML model.
128517: classdiagram 142725 "Time flavours"
133637: classdiagram 143877 "Player Entities"
133637: objectdiagram 144005 "Play Process Structure"
-133637: sequencediagram 145157 "output data exchange"
-133637: classdiagram 151685 "Player Output"
128773: classdiagram 158213 "UIBus"
diff --git a/doc/devel/uml/OutputSlot_components.svg b/doc/devel/uml/OutputSlot_components.svg
new file mode 100644
index 000000000..98dca4bee
--- /dev/null
+++ b/doc/devel/uml/OutputSlot_components.svg
@@ -0,0 +1,8639 @@
+
+
diff --git a/doc/devel/uml/OutputSlot_sequence.svg b/doc/devel/uml/OutputSlot_sequence.svg
new file mode 100644
index 000000000..5a70461b5
--- /dev/null
+++ b/doc/devel/uml/OutputSlot_sequence.svg
@@ -0,0 +1,1672 @@
+
+
diff --git a/doc/devel/uml/fig145157.png b/doc/devel/uml/fig145157.png
deleted file mode 100644
index dac8e23cb..000000000
Binary files a/doc/devel/uml/fig145157.png and /dev/null differ
diff --git a/doc/devel/uml/fig151685.png b/doc/devel/uml/fig151685.png
deleted file mode 100644
index 77b41e446..000000000
Binary files a/doc/devel/uml/fig151685.png and /dev/null differ
diff --git a/doc/index.txt b/doc/index.txt
index 676804e85..0439abeb2 100644
--- a/doc/index.txt
+++ b/doc/index.txt
@@ -1,7 +1,7 @@
Documentation
=============
-This documentation section contains documentation for both users and developers.
+This documentation section contains documentation for users and developers alike.
== User ==
@@ -60,8 +60,8 @@ deeper documentation dungeons.
At the second layer, the reader must make the first major decision on which
router to pursue: documentation with a heavy code based leaning; or more descriptive
-documentation on the design of Lumiera which avoids a code narrative. This
-section has two main sections:
+documentation on the design of Lumiera, which omits most technical details of the implementation.
+Consequently, the documentation is divided into two main parts:
* link:design/index.html[Lumiera Developer Design Documents]
* link:technical/index.html[Lumiera Developer Technical Documents]
@@ -75,14 +75,14 @@ section has two main sections:
[width="90%",frame="topbot",options="header",cols="^,2<"]
|================================================================================================
-|Sub-System|Remarks
+|Section|Remarks
|link:design/architecture/[Architecture]|Structure of Lumiera
|link:design/gui/[GUI]|The Lumiera ⟷ user interaction layer
|link:design/model/[Model]|Low-level and high-level models
|link:design/engine/[Engine]|Renderer, output generation, ...
|link:design/lowlevel/[Low-level]|Low-level and system services
|link:design/application/[Application]|Application framework
-|link:design/plugins/[Plugins]|Dynamically loaded Extensions
+|link:design/extension/[Extension]|Dynamically loaded Extensions
|link:design/workflow/[Workflow]|Workflow and Interaction Design
|link:design/governance/[Governance]|Meta project concerns
|================================================================================================
@@ -93,12 +93,12 @@ section has two main sections:
[width="90%",frame="topbot",options="header",cols="^,2<"]
|================================================================================================
-|Sub-System|Remarks
+|Section|Remarks
|link:technical/build/[Build System]|Build, Packaging and CI
|link:technical/stage/[Stage]|GUI (technical aspects)
|link:technical/steam/[Steam]|Session and processing coordination
|link:technical/vault/[Vault]|Low-level operations
-|link:technical/library/[Support lib]|Interface and support libraries
+|link:technical/library/[Library]|Utilities and custom frameworks
|link:technical/code/[Code base]|Code management, organisation, ...
|link:technical/infra/[Infrastructure]|Website and developer tooling ...
|link:technical/howto/[Developer HowTos]|Instructions and guides for developers
diff --git a/doc/technical/build/BuildDependencies.txt b/doc/technical/build/BuildDependencies.txt
index f841c1583..29a1851d6 100644
--- a/doc/technical/build/BuildDependencies.txt
+++ b/doc/technical/build/BuildDependencies.txt
@@ -40,7 +40,7 @@ Lumiera expects a ``standard'' desktop installation running a XServer.footnote:[
Wayland is ``just around the corner'' since 10 years now. Well, recently it
seems it is _really_ just around the corner. We are aware of the necessary
changes, which are not very complicated to implement (since we are using
- GTK-3). However, as long as Wayland simply crashes or hands in our
+ GTK-3). However, as long as Wayland simply crashes or hangs in our
everyday work setup with XFCE, we will not consider this topic
a priority. In the meantime, please report any problems
you encounter with Lumiera running on XWayland.
@@ -97,7 +97,8 @@ Languages and Tools
* BOOST (listed below are the Debian package names)
- libboost-dev (at least *1.83*)
- - libboost-program-options-dev
+ - notably including `boost::lockfree`
+ - libboost-program-options-dev (link dependency)
* Script languages
- Python (*3.10*) required for building (->SCons)
@@ -123,7 +124,7 @@ Build Tools
* pkg-config
* Doxygen (optional)
* Asciidoc (optional)
-* Git -> https://git.lumiera.org/?p=LUMIERA;a=summary[git://git.lumiera.org/LUMIERA]
+* Git -> https://git.lumiera.org/gitweb?p=LUMIERA;a=summary[git://git.lumiera.org/LUMIERA]
footnote:[
_Ichthyo_ maintains a repo at https://github.com/Ichthyostega/Lumiera/[Github ^~Ichthyostega/Lumiera^]
]
@@ -160,9 +161,9 @@ Libraries
which is possible, but would require some considerable effort. As of 2025, GDL is still usable,
but no longer available through the standard distribution channels. +
We provide a Git repository at our Website for
- https://git.lumiera.org/?p=debian/gdl;a=summary[libGDL (3.40) +git://git.lumiera.org/debian/gdl+]
+ https://git.lumiera.org/gitweb?p=debian/gdl;a=summary[libGDL (3.40) +git://git.lumiera.org/debian/gdl+]
and the
- https://git.lumiera.org/?p=debian/gdlmm;a=summary[GDL C++ bindings (3.7.3) +git://git.lumiera.org/debian/gdlmm+]
+ https://git.lumiera.org/gitweb?p=debian/gdlmm;a=summary[GDL C++ bindings (3.7.3) +git://git.lumiera.org/debian/gdlmm+]
and we maintain custom Debian packages for both in our
link:/debian/[Debian DEB depot].
]
diff --git a/doc/technical/build/LumieraDebianPackage.txt b/doc/technical/build/LumieraDebianPackage.txt
index 9d374613f..f94617aed 100644
--- a/doc/technical/build/LumieraDebianPackage.txt
+++ b/doc/technical/build/LumieraDebianPackage.txt
@@ -79,8 +79,8 @@ How the Lumiera Debian package works
Since we maintain both the Debian package and our build system, we can always try to do
_the heavy lifting_ in our link:{ldoc}/technical/build/SCons.html[SCons build system],
as this helps to keep the Debian packaging as simple as possible. Please have a look at the
--> https://git.lumiera.org/?p=debian/lumiera;a=blob;hb=refs/heads/deb;f=debian/control[control file]
-· https://git.lumiera.org/?p=debian/lumiera;a=blob;hb=refs/heads/deb;f=debian/rules[debian/rules]
+-> https://git.lumiera.org/gitweb?p=debian/lumiera;a=blob;hb=refs/heads/deb;f=debian/control[control file]
+· https://git.lumiera.org/gitweb?p=debian/lumiera;a=blob;hb=refs/heads/deb;f=debian/rules[debian/rules]
- we rely on the _Debhelper Sequencer_ "`dh_*`" in our 'debian/rules' +
-> https://manpages.debian.org/trixie/debhelper/dh.1.en.html[Manpage]
@@ -106,7 +106,7 @@ into `master` and marked with a tag there.
For the actual packaging, we use these release tags as _upstream tag_ and perform a merge
from that tag into the **debian branch**.footnote:[
This _debian branch_ is called `deb` by convention. As mentioned above, it is published through
- a separate https://git.lumiera.org/?p=debian/lumiera;a=summary[Git repository `git://git.lumiera.org/debian/lumiera`],
+ a separate https://git.lumiera.org/gitweb?p=debian/lumiera;a=summary[Git repository `git://git.lumiera.org/debian/lumiera`],
which is kept separate, since packaging is considered a ``downstream process''.
]
This branch carries only the additions and tweaks done for debian packaging. Yet still, this `deb`
@@ -115,7 +115,7 @@ repository as the `master` branch. When the packaging process is complete, the p
DEB version is marked with a tag `debian/`
Note however that there is another branch in the aforementioned `debian/lumiera` repository,
-which is called https://git.lumiera.org/?p=debian/lumiera;a=shortlog;h=refs/heads/depot[depot]
+which is called https://git.lumiera.org/gitweb?p=debian/lumiera;a=shortlog;h=refs/heads/depot[depot]
and is related to our link:/debian[DEB package depot] on Lumiera.org. This branch carries a completely
different directory structure, since it is used with the
https://wiki.debian.org/DebianRepository/SetupWithReprepro[»reprepro« tool from Debian]
diff --git a/doc/technical/build/SCons.txt b/doc/technical/build/SCons.txt
index cd4acb7e2..b5e24e1b3 100644
--- a/doc/technical/build/SCons.txt
+++ b/doc/technical/build/SCons.txt
@@ -352,6 +352,6 @@ shared object (dynamic library), which is then again a SCons target
and can be passed to other executable builders as library dependency
for compilation and linking. Look into 'src/SConscript' or 'test/SConscript'
to see examples of that technique -- which we also use to define that
-global compound target variables like `core`, `app_lib`, `core_lib`,
+global compound target variables like `core`, `vessel_lib`, `core_lib`,
`vault_lib`, and `support_lib`. These in turn are essential for
building the layered dependency hierarchy in our code.
diff --git a/doc/technical/code/LinkingStructure.txt b/doc/technical/code/LinkingStructure.txt
index c1ab3700a..4618afe19 100644
--- a/doc/technical/code/LinkingStructure.txt
+++ b/doc/technical/code/LinkingStructure.txt
@@ -322,8 +322,8 @@ actively step by step
modules of the application will be placed by default
. after the core application has been loaded and all direct dependencies are resolved,
- but still before entering `main()`, the class `lumiera::AppState` will be initialised,
- which in turn holds a member of type `lumiera::BasicSetup`. The latter will figure out
+ but still before entering `main()`, the class `vessel::Voyage` will be initialised,
+ which in turn holds a member of type `vessel::BasicSetup`. The latter will figure out
the location of the executable footnote:[this is a Linux-only trick, using `/proc/self/exe`]
and require a 'setup.ini' file in the same directory. This setup file is mandatory.
diff --git a/doc/technical/howto/crackNuts.txt b/doc/technical/howto/crackNuts.txt
index d5741c03e..d92ac46f2 100644
--- a/doc/technical/howto/crackNuts.txt
+++ b/doc/technical/howto/crackNuts.txt
@@ -88,6 +88,33 @@ test with random numbers::
several threads; each thread should use its own generator then (yet this can be handled sloppy if
the _quality_ of the random number actually does not matter!)
+special test setup::
+ It can be very helpful to use _policy based design_ for some complex evaluation or algorithm,
+ even in cases where it is clear that the actual usage will only ever involve one specific data type
+ and configuration. Not only does such a structured approach help with clarifying the design itself,
+ since the core of the evaluation logic can be abstracted from data representation, but only the
+ testing and verification of correctness is simplified, as the test can be written to use simple,
+ human-readable data (strings, symbols), and, furthermore, many kinds of instrumentation can be
+ included into the test data to gain detailed insight what is happening in the test subject.
+
+verify behaviour sequence::
+ Use the `lib::EventLog`:
++
+- within the test, notable points are marked into the log, possibly with arguments
+- after the test, the Event Log can be verified with a search-sequence
+- this way it is possible to ensure that some events did happen, and happened
+ in a very specific order, or that some event did _not_ happen after another event
+- the `test::Tracker` defined in 'src/test/tracking-dummy.hpp' will mark all constructor,
+ destructor and copy events into an embedded Event Log instance. By inheriting or mix-in
+ from that type, the allocation and instance behaviour of some service can be scrutinised.
+
+verify incidences and concurrency::
+ Aside from using some generic tracing utility, sometimes it is much easier to setup
+ a _specifically tailored instrumentation_. This can be achieved with 'incidence-count.hpp'
++
+- for instrumentation, the `markEnter()` and `markLeave()` functions need to be invoked
+- after the test run, various statistics can be computed and evaluated, including
+ cumulated time and concurrency for the "cases" marked with enter / leave.
Common Tasks
@@ -109,6 +136,12 @@ structured data::
- also useful as output format, both for debugging and because it can be matched against
an expected structure, which is generated with the DSL notation.
- [yellow-background]#(planned)# will be able to map this from/to JSON easily.
+scoped collection::
+ unique-ownership collection that holds a sequence of objects in a preallocated fixed
+ storage block. Notably even non-copyable objects can be managed (which is not possible
+ with a `std::vector`), and type-erased instances of subclasses can be mixed. Furthermore
+ there is a constructor variant that allows to populate a `ScopedCollection` in RAII-style.
+ This can e.g. be used to fire-off a set of Threads or open a set of wrapped connections.
Iterating
~~~~~~~~~
@@ -134,6 +167,26 @@ IterSource::
even the production-state can be hooked up into the IterSource instance (with a smart-ptr).
This allows e.g. to send a Diff to the UI through the UI-Bus, while the actual generation
and application both happen demand-driven or _lazy..._
+State Core::
+ When some algorithm involves a statefull evaluation, it might be helpful to package that into
+ a _State Core_ container. This is a class that is expected to expose three operations, which
+ allow to build an iteration on top. The header 'iter-adapter.hpp' provides several adapters
+ and wrappers, notable `lib::IterStateWrapper` wraps any _state core_ and provides a
+ Lumiera Iterator interface; likewise, `IterExplorer` heavily relies on that concept and
+ is able to accept and iterate any state core in a pipeline.
+special iterators::
+ Some additional adaptors are provided as building block so that specific evaluations
+ can be made to conform with the »Lumiera Iterator« concept
++
+- several given iterators can be combined into a iteration over tuples with 'lib/iter-zip.hpp'
+- there is also a variation 'lib::izip' that adds a running index into the _zipping operation_
+- IterExplorer provides a `flatten()` operation, that can be used to join an iterator-of-iterators
+ into a single seamless iteration lazily.
+- when a STL container also supports _backwards iteration_, then a lumiera iterator can be
+ created that can _switch direction_ dynamically, with the help of 'iter-cursor.hpp'
+- a STL »deque« container can be used both as a stack and a queue; the header 'iter-stack.hpp'
+ provides an iteration adapter for both usage schemes, so that either the stack or the queue
+ can be _"discharged"_ as a Lumiera Iterator (possibly with an IterExplorer pipeline)
Formatting
@@ -155,6 +208,25 @@ Formatting
because there are way more capable solutions _out there_ ☺)
+Setup and wiring
+~~~~~~~~~~~~~~~~
+Generally speaking, we prefer _constructor wiring_ whenever possible, to avoid creating
+unnecessary statefulness (as would be the case when connecting dependencies through setters).
+This design also favours decomposition into self-contained components with a single purpose,
+and simplifies error handling with the help of the RAII pattern.
+
+However, sometimes a piece of code depends on some remote and even global service; in these
+cases, the `lib::Depend` framework can be used to access that service via type name. The
+actual service can either be created on-demand as a singleton, or it can be installed
+explicitly as a service instance. Furthermore, it is possible to "push aside" the
+current service instance temporarily and replace it by a _test mock_.
+
+One point to note is that `lib::Depend` is a _monostate_, and not a _singleton_.
+The actual service should be written as a free-standing class, that can be instantiated
+directly for the purpose of testing.
+
+
+
Language constructs
-------------------
Templates
@@ -235,4 +307,14 @@ unpack iterator into tuple::
- see tuple-record-init-test.cpp
- used in 'command-simple-closure.hpp' to receive parameter values sent via UI-Bus and package them
into a tuple for invocation of a Steam-Layer command.
++
+index and iterate over tuple elements::
+ This is another example of bridging the compile-time / runtime barrier, using a trampoline.
+ Obviously such a solution requires that it is somehow possible to define a generic functor / λ that
+ can accept any of the tuple elements. And, in order to build a runtime index access, we additionally
+ need to convert each of the tuple elements into a _common reconciled type_.
++
+- If such a type exists, can be figured out with the help of the `meta::CommonReturn` _metafunction_
+- `lib::meta::TupleIdxAdaptor` provides the necessary machinery to define a subscript `operator[]`
+- see `TupleIdxAdaptor_test` for some usage examples, including a runtime iteration...
diff --git a/doc/technical/index.txt b/doc/technical/index.txt
index f3ace95bd..9fcd9007e 100644
--- a/doc/technical/index.txt
+++ b/doc/technical/index.txt
@@ -9,34 +9,34 @@ Technical Documentation
// Menu : prepend child overview
-This documentation section contains technical documentation about Lumiera. To
-get an *overview* of all the internals and components, you might want to read
+This documentation section contains technical documentation about Lumiera. +
+To get an *overview* of all the internals and components, you might want to read
link:overview.html[Lumiera the Inner Core]
== Three Layers
-The technical documentation is split in three parts, one for each of the three
-main layers of Lumiera. You may want to read the
-link:{ldoc}/design/index.html[Design Documents] first to get an overview of all the
-components.
+The technical documentation is divided into three main parts and some supplements,
+corresponding to the code organisation in three layers. The information here can be
+very detailed and technical at times, and the topics are organised by individual components.
* link:stage/index.html[*Stage Layer*] : Documents related to the GTK based Lumiera GUI
-
-* link:steam/index.html[*Steam Layer*] : Documents regarding Session, models and the engine structure
-
+* link:steam/index.html[*Steam Layer*] : Documents regarding Session, the models and the engine
* link:vault/index.html[*Vault Layer*] : Documents about the data and processing backend
+To better understand the underlying concepts, it might be helpful to also consult the
+link:{ldoc}/design/index.html[Design Documents].
+
== Tools
.Development
-* link:/doxy/[*Doxygen* generated documentation] : API documentation of the Lumiera code.
+* link:/doxy/[*Doxygen*] : API documentation of the Lumiera code.
* organisation of the link:code/index.html[Code Base] in general
* link:/x/CodingGuidelines.html[Coding Style] and further guidelines
.Building
-* link:build/index.html[Buildsystem] : Installation & compilation tools, dependencies and packaging.
+* link:build/index.html[Buildsystem] : Installation and compilation tools, dependencies and packaging.
.HOWTO
-* link:/x/DevHowto.html[Developer *HOWTOs*] : Collection of instructions, recipes, hints and similar
- materials intended for developers
+* link:/x/DevHowto.html[Developer *HOWTOs*] : Collection of instructions, recipes, hints, misdeeds
+ and confessions and similar helpful resources for developers
diff --git a/doc/technical/infra/TestSupport.txt b/doc/technical/infra/TestSupport.txt
index ca5146c76..59d134cbf 100644
--- a/doc/technical/infra/TestSupport.txt
+++ b/doc/technical/infra/TestSupport.txt
@@ -8,30 +8,32 @@ NOTE: This page holds content copied from the old "main" TiddlyWiki +
It needs to be reworked, formatted and generally brought into line
********************************************
-.Lumiera relies on *test-driven development*
+.Lumiera employs test-driven development
This page discusses the overall organisation
of test code, and the tools used for
running test cases
********************************************
-Tests are the only form of documentation, known to provides some resilience against
-becoming outdated. Tests help to focus on the usage, instead of engaging in spurious
+Tests are the only known form of documentation that offers some resilience against
+getting outdated. Tests help to focus on the usage, instead of engaging in spurious
implementation details. Developers are highly encouraged to write the tests _before_
the actual implementation, or at least alongside and interleaved with expanding the
feature set of the actual code.
+
There may be exceptions to this rule. Not every single bit needs to be covered by tests.
Some features are highly cross-cutting and exceptionally difficult to cover with tests.
-And sometimes, just an abstract specification is a better choice.
+Test code must not duplicate the logic of implementation code, it should represent an
+abstracted, outside, logical view of the matter at hand. And sometimes it is the better
+choice to simply write an abstract specification in understandable language.
As a rule of thumb, consider to write test code which is easy to read and understand,
_like a narration_ to show off the relevant properties of the test subject.
+
Test Structure
--------------
-- a *test case* is an executable, expected to run without failure, and optionally producing
- some verifiable output
-- simple test cases may be written as stand-alone application, while the more tightly
- integrated test cases can be written as classes within the Lumiera application framework.
+- a *test case* is an executable, expected to run without failure; test code not only invokes
+ a _subject under test_ -- the important part is to _verify_ its behaviour.
- test cases should use the +CHECK+ macro of NoBug to verify test results, since the normal
assertions may be de-configured for optimised release builds.
- our test runner script 'test.sh' provides mechanisms to check for expected output
@@ -41,15 +43,13 @@ several functions within the same test fixture. This allows to create a ``narrat
in the code: first do this, than do that, and now that, and now this should happen...
Generally speaking, it is up to the individual test to take care or isolate himself
from any _dependencies_. Test code and application code uses the same mechanisms
-for accessing other components within the application. Up to now (2014), there
-was no need for any kind of _dependency injection_, nor did we face any
-difficulties with tainted state.
+for accessing other components within the application.
Test classes are organised into a tree closely mirroring the main application source
code tree. Large sections of this test tree are linked together into *test libraries*.
Some of these are linked against a specific (sub)scope of the application, like e.g.
only against the support library, the application framework or the vault. Since we
-use _strict dependencies_, this linking step will spot code not being placed at the
+use _strict dependencies_, this linking step will also spot code not placed at the
correct scope within the whole system. As a final step, the build system creates a
*test runner* application (`target/test-suite`), which links dynamically against _all_
the test libraries and thus against all application dependencies.
@@ -81,9 +81,9 @@ to help with automating the build and test execution, test code should adhere to
- test classes should be placed into a sub namespace +...::test+
- specific definitions for a single test case may rely on global variables,
but these should live within an anonymous namespace
-- all test executables should be named according to the pattern +test-*+
+- free standing test executables should be named according to the pattern `test-*`
- all test source code is within the 'tests' subtree
-- immediately within the 'tests/' directory are the test collection definitions +*.tests+,
+- immediately within the 'tests/' directory are the test collection definitions `*.tests`,
ordered by number prefixes
- below are the directories with test cases, to be grouped into the aforementioned test-executables.
- we distinguish two ways to write and link tests: _standalone_ and _suite_
@@ -107,7 +107,7 @@ See the following
.hello-world-test example
[source,C]
----------------------------------------------------------------
-#include "lib/test/run.hpp"
+#include "test/run.hpp"
#include
using std::cout;
diff --git a/doc/technical/infra/debianDepot.txt b/doc/technical/infra/debianDepot.txt
index 12f5cb32f..3fad649bc 100644
--- a/doc/technical/infra/debianDepot.txt
+++ b/doc/technical/infra/debianDepot.txt
@@ -109,7 +109,7 @@ Configuration
~~~~~~~~~~~~~
All the current configuration and the state of the Debian depot index files is tracked
in the aforementioned ``debian/lumiera'' Git repository, on a separate branch called
-https://git.lumiera.org/?p=debian/lumiera;a=shortlog;h=refs/heads/depot[`depot']
+https://git.lumiera.org/gitweb?p=debian/lumiera;a=shortlog;h=refs/heads/depot[`depot']
TIP: this is a slightly unconventional setup, insofar the `depot' branch carries
a directory tree that is completely separate from the main Lumiera source tree, which
diff --git a/doc/technical/library/index.txt b/doc/technical/library/index.txt
index 67e0a7946..f15c65b9f 100644
--- a/doc/technical/library/index.txt
+++ b/doc/technical/library/index.txt
@@ -1,41 +1,70 @@
Library documentation
=====================
-//Menu: label Support Lib
-Alongside with the core Lumiera Application, we're also creating several *Libraries*. +
-This section holds pages with in-depth technical documentation regarding those. Please don't
-expect a coherent or complete coverage for the time being -- library functionality is typically
-``discovered'' while in the middle of the implementation, then factored out, reused and remoulded
-over time.
+Alongside with the core Lumiera Application, and as part of ongoing development work,
+a lot of *Library code* is written. Many of this happens on occasion. Library solutions
+are frequently ``discovered'', while in the middle of the implementation, driven by the
+desire to re-use some code structure that was built just recently and in a similar way.
+
+
+Support Library
+---------------
+Over time, a huge and growing number of generic building blocks has been collected.
+Hoever, not all parts of this collection are equally well maintained and presentable.
+It happened time and again that some pattern extracted into the library turned out
+to be rather some kind or ephemeral habit -- maybe even a bad habit in hindsight --
+and turned into a dead-end eventually. Furthermore, a lot of our library code has
+been superseded by very similar features of newer language standards.footnote:[
+ It seems like developers working on similar problems tend to have similar ideas
+ to improve productivity. Unfortunately, the solutions resulting from this convergence
+ of ideas have a tendency not to ``converge'' so well in practical terms.
+ For example, Lumiera had a tuple type a long time before a mature tuple implementation
+ was available in the Boost libraries, yet in the end, we could retrofit most of our
+ tuple-handling library. However, other cases did not play out so well: we evolved
+ the idea of ``iterators'' to become a lazy processing pipeline, but unfortunately
+ our design leans more into the direction of functional programming and is much
+ more expressive and powerful as abbreviation than the »Range-TS« from C++20.
+]
+The entrance barrier for something to be added to our _Support Library_ is rather low:
+
+- extracting it as a library function _must make the client code clearer_
+- it must be possible to describe its purpose and its usage in _generic terms_ --
+ without referring to data types and definitions from our domain models.
+- it must be _essentially stateless_ and self-contained
+- it must be easy to document with an unit-test.
+
+Over time, parts of the Support Library have evolved into some kind of a framework:
+Notably the link:{ldoc}/design/architecture/time/index.html[time and timecode] handling,
+our link:Dependencies.html[dependency and service handling],
+the link:DiffFramework.html[»Diff framework«], together with the recursive property trees
+used for link:{ldoc}/design/architecture/ETD.html[»External Tree Description«], the
+link:iterator.html[iterator pipeline builders], the metaprogramming helpers for transforming
+function signatures and generic sequences, and our collection of string conversion, parsing
+and rendering functions. These all turned into distinguishing traits of the Lumiera code base.
+
+The link:{ldoc}/technical/overview.html#_library[»Library« section of the »Overview« document]
+contains a long list of short descriptions for relevant features of the Support Library.
+
+
+.how to crack nuts...
+[NOTE]
+In the how-to section, there is a page with a loose collection of
+link:{ldoc}/technical/howto/crackNuts.html[successful solution patterns],
+many of which rely on unique features of our Support Lib.
+
Interface Library
-----------------
The Lumiera Application is designed deliberately in a way to be controllable by scripts. All of
the Session, the models and the vault are fully operational without the GUI. Any significant
-functionality can be addressed through the primary Façade Interfaces.
+functionality shall be usable through the primary Façade Interfaces alone. Yet in order to create
+such an open and extensible application as envisioned, we also need to build up an _interface layer._
+Eventually, this should evolve into a binding library for using Lumiera -- however, none of this
+interface building work has been accomplished yet, as of 2026. We do not even have a complete
+picture how _event sourcing_ meshes together with our UI commands and the configuration rules.
-But, in order to make such an open and extensible application a reality, we need to build up
-an 'interface layer' -- provided as library for client code and script adapters to link against.
-This library allows to access the primary external interfaces and exposes everything needed to
-work with the specifics of the application.
-
-[,yellow]#TODO as of 1/2012:# _this is just a nebulous plan for now._ Nothing of the work required
-really to address facilities from the outside has been done. All we've managed to achieve is actually
-to use clean interfaces and decouple the parts of the application appropriately.
-
-- we still need to identify those core concepts which need to be exposed
+- we still need to identify those select core concepts which need to be exposed
- we need to refactor the corresponding data types to resolve cross dependencies to the implementation
-- then we could think about moving those data types into an _official Lumiera interface_
-
-Support Library
----------------
-There is a huge collection of generic building blocks, re-used more or less frequently.
-The're written in a generic way, but in accordance to the rest of the source base, relying only
-on the general error handling and logging framework used within Lumiera. (Some facilities may depend
-on other parts of the Application; this can be qualified as a bug -- please complain when you've found
-something of that sort).
-
-
-
+- only then we could think about moving those data types into an _official Lumiera interface_
diff --git a/doc/technical/overview.txt b/doc/technical/overview.txt
index a37f5d649..9565c6f9e 100644
--- a/doc/technical/overview.txt
+++ b/doc/technical/overview.txt
@@ -1,7 +1,7 @@
Lumiera: The Inner Core
=======================
:Author: Lumiera_Core_Developers
-:Date: 2012 / 2025
+:Date: 2012 / 2026
:toc:
[abstract]
@@ -30,7 +30,7 @@ This three Layers are:
The Steam Layer::
Keeps the Session, generates the rendering graphs for sequences,
- arranges what to do when and how.
+ prearranges elements and decides what to do when and how.
The Vault Layer::
Manages worker pools, schedules jobs, does the memory management for the
@@ -39,13 +39,11 @@ This three Layers are:
The extra components are:
- Lumiera::
- The main program itself, which starts all Subsystems and controls the
- overall lifecycle.
-
- Common::
- Vital components and common services which must be available for pulling up
- any part of the system.
+ The Vessel::
+ This is the »backbone« of the application, it is rooted below the three
+ layers and encompasses everything. It defines the periphery, starts all
+ Subsystems, controls the overall lifecycle and provides vital services
+ which must be available for engaging any part of the system.
Library::
A lot of (largely) stateless helper functionality used throughout the code.
@@ -55,9 +53,9 @@ Coding Style
~~~~~~~~~~~~
The Lumiera team agreed on using GNU coding style with slight adaptations.
-Generally speaking, we strive to keep the code base consistent and stick to
-widely accepted guidelines and best practices. See our separate
-link:{ldoc}/technical/code/codingGuidelines.html[Coding Guidelines] page.
+In general, we strive to maintain source code consistency and adhere to widely
+accepted guidelines and practices of good craftsmanship. See our separate
+link:{ldoc}/technical/code/CodingGuidelines.html[Coding Guidelines] page.
@@ -148,7 +146,7 @@ contained within the Session, which belongs to the _steam layer_ below.
User interfaces are implemented as plug-ins and are pulled up on demand,
they won't contain any relevant persistent state beyond presentation.
-_As of 2023, the one and only interface under active development is
+_As of 2026, the one and only interface under active development is
the Lumiera GTK GUI,_ based on GTK-3 / gtkmm. The sources are in tree
(directory 'src/stage') and it is integrated into the standard build and
installation process. By default, running the 'lumiera' executable will
@@ -250,7 +248,7 @@ for each output channel is required.
The player service
^^^^^^^^^^^^^^^^^^
-Client code accesses the player (subsystem) through the play-facade (`lumiera::Play`).
+Client code accesses the player (subsystem) through the play-facade (`Play`).
The exposed service allows to _set up an output connection for playback or rendering,_
resulting in a play-controller object.
@@ -285,11 +283,6 @@ performance critical.
- the OutputSlot exposed by the output manager is responsible for accepting timed frame delivery
-
-
-Vault Layer
------------
-
Engine Interface
~~~~~~~~~~~~~~~~
While on itself just a thin interface and adaptation layer forwarding calls to
@@ -318,16 +311,21 @@ the job ticket acts as blueprint for the actual jobs to be enqueued
with the _Scheduler._
+
+Vault Layer
+-----------
Scheduler
~~~~~~~~~
The Scheduler serves as the central hub in the implementation of the RenderEngine
and coordinates the processing resources of the application. Its purpose is to
invoke and control the dependency and time based execution of the _Render Jobs._
-Regarding architecture, the Scheduler is located in the Vault-Layer and running the Scheduler
-is equivalent to activating the »Vault Subsystem«. An EngineFaçade acts as entrance point,
-providing high-level render services to other parts of the application: render jobs can be
-activated under various timing and dependency constraints, which can be grouped
+As far as architecture is concerned, the Scheduler is located in the Vault-Layer and
+is a _passive service_ -- like most components in the vault it needs to be put into
+use by some coordinating and integrating facility. An EngineFaçade, itself located
+above, in the »Steam« layer, acts as entrance point, to provide the high-level
+render services to other parts of the application: render jobs can be activated
+under various timing and dependency constraints, which can be grouped
into three basic modes of control:
Deadline::
@@ -362,6 +360,29 @@ The scheduler is able to observe and maintain dependencies between render jobs,
to break down an extended calculation into a chain of small steps.
+The Work Force
+~~~~~~~~~~~~~~
+Since the typical work job dimensions can be expected to lie in the range of _some milliseconds,_
+the Lumiera engine can adopt a statistical model of capacity distribution. This is notably
+different to an _operating system scheduler_ where the response times are measured in
+microseconds and the coordination of work approaches hardware limits. These observations
+lead to the (maybe slightly surprising approach) to rely on an _actively pulling_ work force
+combined with a _passive scheduling service._
+
+The _Work Force_ is a **pool of worker threads** with a size typically matching the nominal
+number of independent CPU cores in the system. Spinning up the Work Force is equivalent to
+activating the »Vault Subsystem«. Deliberately, there is no dedicated ``engine'' or
+``manager'' thread. All workers participate in the coordination work on equal footing.
+An idle worker enters the (passive) scheduling code, and thereby performs management
+work up to the point where the next render job is determined. The worker then leaves
+the management realm and continues with performing this job. However, the scheduling
+code preloads each worker with some random sleep delay in order to distribute the
+``incidence'' of idle workers and to avoid contention. This way, the available
+computing capacity is distributed stochastically into that time window where
+demand is foreseeable, based on the next job's starting time, the currently
+dispatched jobs and the observed load factor.
+
+
Resource Management
~~~~~~~~~~~~~~~~~~~
@@ -378,12 +399,12 @@ the system and current circumstances.
-Common Services
----------------
+Vessel: Common Services
+-----------------------
Subsystem runner
~~~~~~~~~~~~~~~~
-Conceptually, the application is structured into layers. However, as actual runtime
+Conceptually, the application is structured into layers. However, as the actual runtime
entities we rely on a small number of link:{ldoc}/design/architecture/Subsystems.html[Subsystems],
which can be started and stopped and have well defined dependencies:
@@ -418,17 +439,14 @@ link:{ldoc}/design/architecture/Subsystems.html#_lifecycle[documentation]
[small]#(likewise incomplete, but we're getting there, eventually [yellow-background]##2018##)#
-Plugin loader
-~~~~~~~~~~~~~
-_tbw_
Advice framework
~~~~~~~~~~~~~~~~
This is a ``whiteboard'' system, allowing implementation-level services to _publish_
some piece of information as _advice_, while other parts of the system may pick up
this advice just by a name token, without requiring a direct knowledge of the
-original _advisor._ The _Advice System_ is a singleton service maintaining a
-lookup and registration data structure. Individual _piece of advice_ elements
+original _advisor._ The _Advice System_ is a singleton service that maintains
+a lookup and registration data structure. Individual _piece of advice_ elements
are stored _as value copy_. Publishing new advice requires locking, but accessing
advice is lock-free (actually there needs to be a memory barrier ``somewhere'',
otherwise the advice requesting client might not see new advice)
@@ -458,13 +476,27 @@ Library
-------
The Lumiera support library contains lots of helper functionality
-factored out from the internals and re-used. It is extended as we go.
+factored out from the internals and re-used. Some parts evolved into
+basic frameworks, that are used pervasively throughout the code base.
+
+ - link:{ldoc}/design/architecture/time/index.html[time and timecode]
+ (-> xref:_time[below])
+ - link:Dependencies.html[dependency and service handling]
+ (-> xref:_singletons_and_dependencies[below]),
+ - the link:DiffFramework.html[»Diff framework«]
+ - property trees for link:{ldoc}/design/architecture/ETD.html[»External Tree Description«]
+ (-> xref:_external_tree_description[below])
+ - the link:iterator.html[iterator pipeline builders]
+ (-> xref:_iterators[below])
+ - various metaprogramming helpers (function signatures and generic sequences)
+ - string conversion, parsing and rendering functions
+
practical shortcuts
~~~~~~~~~~~~~~~~~~~
-The header 'lib/util.hpp' defines some shortcuts heavily used throughout
-the code base. The idea is to highlight a common semantic meaning, while
-hide differentiation on the technical details.
+The header 'lib/util.hpp' defines some shortcuts that are used almost
+everywhere in the code base. The general idea is to highlight a common semantic meaning,
+while hide the differentiation related to the technical details.
isnil:: indicate a _missing value_, irrespective if this is a NULL pointer,
an empty string or an empty container. Several of our custom wrappers also
@@ -473,8 +505,29 @@ isnil:: indicate a _missing value_, irrespective if this is a NULL pointer,
contains:: indicate that a value is _somehow contained_ within a collection,
irrespective if this is a set, a map, a vector or string (substring test)
-sanitise:: make any string usable as identifier.
+limited:: to bracket some value.
+unConst:: a functional notation to cast away `const`, which is used typically
+ at the barrier between a type safe front-end and a low-level back-end,
+ and to avoid needless duplication of accessor code implementation
+ for sake of providing `const` information functions.
+
+isSameObject:: identity test based on bare memory location,
+ which is used a lot in assertions and unit tests
+
+string shorthands::
+ trim, startsWith, endsWith, boolVal, sanitise (turn arbitrary string into an identifier)
+
+
+Literals and Symbols
+~~~~~~~~~~~~~~~~~~~~
+Besides the well-known C++ strings (and `string_view`), Lumiera introduces
+two marker types for string tokens
+
+Literal:: a C-string literal directly given in the Source code
+
+Symbol:: an _interned_ token stored in a Symbol table, so that its
+ address hash can be used as unique identity
Locking
@@ -892,6 +945,17 @@ and assignment incur the cost of an additional virtual call,
assuming the target objects cooperate by mixing in a
copy management interface.
+.uninitialised storage
+A cornerstone of the C++ language is the deterministic and reliable invocation
+of constructors and destructors. However, when building low-level storage schemes,
+a frequent requirement is to cover the precise storage of an object collection,
+_without_ actually invoking any constructor or destructor. The `UninitialisedStorage`
+template is a building block to support this task. It is parametrised with a type
+and an element count, and provides a force-casted array-like access to the storage cells.
+This can be used either to placement-construct some elements on-demand, or to ``project''
+an object-like view over existing data in the storage.
+
+
Unique Identifiers
~~~~~~~~~~~~~~~~~~
diff --git a/doc/technical/stage/index.txt b/doc/technical/stage/index.txt
index ad34a0085..a7252f702 100644
--- a/doc/technical/stage/index.txt
+++ b/doc/technical/stage/index.txt
@@ -1,5 +1,5 @@
Technical Documentation: Stage Layer
====================================
-Eventually, this will have technical documentation for the GUI.
+This section offers a loose collection with detailed information regarding the GUI implementation.
diff --git a/doc/technical/steam/index.txt b/doc/technical/steam/index.txt
index 56c69524b..c48e8741f 100644
--- a/doc/technical/steam/index.txt
+++ b/doc/technical/steam/index.txt
@@ -1,27 +1,36 @@
Technical Documentation: Steam-Layer
====================================
-Eventually, this section will hold technical documentation for the Steam-Layer.
+As implementation progresses, this section will gradually compile
+the technical documentation for the Steam layer.
Development Scrapbook TiddlyWiki
--------------------------------
-Hermann Voßeler, core developer of the Steam-Layer uses an separate embedded wiki
-for his day-to-day design sketches, notes and also for the more persistent planning.
-This *TiddlyWiki* is a nifty JavaScript wiki embedded in a single HTML page; as such
-it lives right within the source tree, where it can be worked on alongside with the
-code. Besides the actual planning and descriptions, this wiki also links to the
-UML diagrams created with *BOUML* during the ongoing planning and design.
+It is sometimes difficult to write complete documentation while a system is still under construction.
+For taking work notes and formulating new ideas while working, _Ichthyostega_ frequently uses the
+https://classic.tiddlywiki.com/[TiddlyWiki] -- which is a nifty JavaScript wiki embedded within a
+single HTML page; as such it lives right within the source tree, where it can be worked on alongside
+with the code. Notes and sketches for the planning often evolve into detailed descriptions, complete
+with test data and UML diagrams to document the structure. Material drafted in the TiddlyWiki
+will be moved gradually into this documentation section, as time permits.
-This setup started as a temporary solution -- but as uWiki is not expected to come
-to life soon, the current website can't serve as replacement for a real wiki, an
-we'll stick to that situation for the time being. As the content in the TiddlyWiki
-becomes more mature and stable, it will be moved over into this section here.
+This arrangement started as a temporary solution at a time where we did not have a suitable website
+for permanent documentation -- and it was kept ever since, as the TiddlyWiki is very convenient
+to work with, once you are accustomed to its quirks.footnote:[
+ It is quite fluid and inspiring to work with indeed. The content is an unordered collection
+ of small notepad pages, called ``Tiddlers'', which can be opened and closed conveniently.
+ Any "CamelCaseWord" becomes a new Tiddler, recent changes appear in a timeline, and Tiddlers
+ can be organised with tags. The only point to be careful is that you need to _save_
+ your work, which can be achieved with the `save' action in the menu to overwrite
+ the old version in the Git tree. Sometimes this might produce Git conflicts,
+ which are easy to resolve, since the content is plain text.
+]
+Additions to the TiddlyWiki are usually made during coding, and are deliberately committed always
+together with the corresponding code. As such, these additions will propagate to Lumiera/Master eventually;
+yet to make the newest development notes easier to access, we have put up a `rsync`ed version of the
+TiddlyWiki online for direct access over the internet (which then is of course read-only).
-While additions to the TiddlyWiki generally propagate to Lumiera/Master through
-the normal merges, we've put up a rsynced version of the TiddlyWiki online for
-direct access (of course read-only).
-
--> access the Proy-Layer link:/wiki/renderengine.html[TiddlyWiki online here]
+-> access the link:/wiki/renderengine.html[TiddlyWiki online here]
diff --git a/doc/user/intro/intro.txt b/doc/user/intro/intro.txt
index 3f34822d2..2e49a6c27 100755
--- a/doc/user/intro/intro.txt
+++ b/doc/user/intro/intro.txt
@@ -113,8 +113,11 @@ each have a distinct _type_ which explicitly identifies the possible connections
modules. Within these constraints, any combination is possible without
hidden restrictions.
-Lumiera is not a set of Lego bricks, nor is it a business application
-driven by finite usage stories.
+However, the application strives for a certain degree of internal coherence. +
+Lumiera is not a set of Lego bricks allowing you to build ``just anything''
+(in a clumsy way) -- nor is it the next universal programming platform or
+application framework driven by pre-canned success stories, where you
+``just push the button'' and magic does the rest.
Medium Level Abstraction and Project Specific Conventions
@@ -131,9 +134,8 @@ details such as header format conversion or access to individual channels.
To complement this approach, Lumiera does _not_ rely on hard-wired, global
conventions -- rather we allow the building up of project specific conventions and
rules xref:rules[<-] to fit a given requirement and preferred working style.
-
-Lumiera will be supplied with a conventional template and a default
-configuration to ease the learning curve for new users.
+However, in its default configuration, Lumiera will be supplied with a conventional
+UI template and key bindings to ease the learning curve for new users.
[[graphs]]
@@ -218,16 +220,15 @@ Lumiera consists of three major parts:
In this section, we discuss the user's perspective when working with the GUI.
-Although Lumiera will initially ship with a standard, default GUI, we do not presume that this GUI will be suitable for all uses.
-We expect there to be multiple, different GUIs, each designed for different
-kinds of tasks. We expect that some of these will be written by users, and the
-steam-layer is designed to facilitate this easily.
+Although Lumiera ships with a conventional desktop UI by default, we do not presume
+that this GUI will be suitable for all uses. We expect there to be several specialised
+UIs eventually, designed to handle very specific kinds of tasks.
Indeed, Lumiera can even work
satisfactorily without a GUI, for example, for special purposes
(e.g. as headless render-node xref:rendernode[<-] or frameserver
-xref:frameserver[<-]). Scripts will eventually be written
-to facilitate automated processing.
+xref:frameserver[<-]). A script interface will be added at some
+point to facilitate automated processing.
Now it is time to take a look at the preliminary Lumiera GUI:
@@ -505,21 +506,19 @@ A Plug-in is a kind of generalisation of a library.
All applications use, to varying degrees of intensity, libraries. A programmer
will not reinvent the wheel each time he sits down to programme an
application. A programmer will typically borrow and use features and
-functionality from other programmers---or even borrow from himself, stuff
+functionality from other programmers -- or even borrow from himself, stuff
written long ago in the past. Such features are collected together in
libraries.
-A library is used in an application by _linking_ the library into the
-application. (There are other things to be done, but we'll call these 'details',
-which wont concern us here.) There are different ways to _link_ a library
-into an application: linking statically and linking dynamically.
+A library is used in an application by _linking_ the library into the application.
+However, there are different ways to _link_ a library: linking statically and
+linking dynamically.
_Static Linking_ is done while the application is being built, or
compiled. It is performed by the linker, which executes as the last step
-of the compilation process. The linker can perform some sanity checks
-(mostly checks regarding formally correct function invocation) and warn the user
-hat some particular feature is being used incorrectly. The user can then correct
-the offending code, and recompile. +
+of the compilation process. The linker can perform some sanity checks and
+some optimisation. In the end, the functionality of the library is ``baked into''
+the resulting executable. +
There are a number of disadvantages associated with static linking. Features and
libraries are being constantly improved. If the application wants to use new
features, it will have to be recompiled with the new library which provides the
@@ -532,15 +531,14 @@ features can be used by the application. The features provided by a dynamic
library are loaded when the application starts to run.
However both methods exhibit a number of shortcomings. Wouldn't it be better if
-all features could be loaded only when needed? If features could be loaded only
-when needed, then they could also be unloaded when not required, thus saving
-memory and possibly increasing performance. This scheme of making features
-available to an application is known as run-time linking, aka plug-ins.
+all features could be loaded only when needed? This scheme of making features
+available to an application on-demand is known as run-time linking. A component
+intended to be added this way, at run time, by the user, is known as a Plug-in.
Plug-ins offer other benefits: the application can continue to use both the old
features and the new features together, side-by-side, by using the version
-number associated with the plug-in. This saves the application from the havoc
-of library incompatibility that is
-associated with other linking methods.
+number associated with the plug-in. Furthermore, Plug-ins can load other Plug-ins
+and thus extend the application in creative ways, beyond anything the original
+developers of the application had planned.
Most modern applications use plug-ins, some are heavily dependent on plug-ins
and only provide limited functionality without any plug-ins.
diff --git a/doc/user/tutorials/building.txt b/doc/user/tutorials/building.txt
index 3638e73b1..3ce26088b 100644
--- a/doc/user/tutorials/building.txt
+++ b/doc/user/tutorials/building.txt
@@ -54,7 +54,7 @@ in addition to the following tools and libraries:
* https://www.boost.org/[Boost libraries]
* https://github.com/bplaum/gavl[GAVL library]
* https://nobug.pipapo.org/[NoBug] ~([purple]#⚠ see below#)~
- * Lumiera https://git.lumiera.org/?p=LUMIERA;a=summary[source code]
+ * Lumiera https://git.lumiera.org/gitweb?p=LUMIERA;a=summary[source code]
The GUI depends on the following:
diff --git a/doc/user/tutorials/contributing.txt b/doc/user/tutorials/contributing.txt
index aa53825db..6fe451999 100644
--- a/doc/user/tutorials/contributing.txt
+++ b/doc/user/tutorials/contributing.txt
@@ -115,9 +115,9 @@ sudo make install
but was orphaned in 2021. Since it is currently a prerequisite for building Lumiera,
we maintain a clone of the original repository and a Debian package on Lumiera.org.
This is relevant both for
- https://git.lumiera.org/?p=debian/gdl;a=summary[libGDL (3.40) +git://git.lumiera.org/debian/gdl+]
+ https://git.lumiera.org/gitweb?p=debian/gdl;a=summary[libGDL (3.40) +git://git.lumiera.org/debian/gdl+]
and the
- https://git.lumiera.org/?p=debian/gdlmm;a=summary[GDL C++ bindings (3.7.3) +git://git.lumiera.org/debian/gdlmm+].
+ https://git.lumiera.org/gitweb?p=debian/gdlmm;a=summary[GDL C++ bindings (3.7.3) +git://git.lumiera.org/debian/gdlmm+].
]
* first you have to build libGTL itself...
diff --git a/research/try.cpp b/research/try.cpp
index b6e9d0a82..972451b90 100644
--- a/research/try.cpp
+++ b/research/try.cpp
@@ -1,6 +1,7 @@
/* try.cpp - to try out and experiment with new features....
* scons will create the binary bin/try
*/
+// 03/26 - runtime index access and iteration over tuple-likes
// 06/25 - provide a concept to accept _tuple-like_ objects
// 06/25 - investigate function type detection of std::bind Binders
// 12/24 - investigate problem when perfect-forwarding into a binder
@@ -10,22 +11,28 @@
/** @file try.cpp
- * Develop a concept to detect _tuple-like_ classes, based on the requirements
- * of the »tuple protocol«. Using some ideas from [Stackoverflow] as starting point.
- * However, we model both a _friend function_ `get` and a similar member function
- * as alternatives for element access, and we break down the checks into sub-concepts.
- * [Stackoverflow]: https://stackoverflow.com/q/68443804/444796
+ * Work out a construction scheme to build an efficient element-accessor to data
+ * in a tuple-like with run-time indexing. As an extension, run-time pulled iteration
+ * can be established, using the IterExplorer framework.
+ * @see lib::meta::FunTrampoline
+ * @see lib::meta::TupleIdxAdaptor
*/
#include "lib/format-cout.hpp"
-#include "lib/test/test-helper.hpp"
-#include "lib/test/diagnostic-output.hpp"
+#include "lib/format-util.hpp"
+#include "test/test-helper.hpp"
+#include "test/diagnostic-output.hpp"
+#include "lib/meta/common-result.hpp"
+#include "lib/meta/tuple-concept.hpp"
#include "lib/meta/tuple-helper.hpp"
+#include "lib/meta/function.hpp"
+#include "lib/iter-adapter.hpp"
#include "lib/hetero-data.hpp"
+#include "lib/meta/trait.hpp"
#include "lib/util.hpp"
-#include
+#include
using std::string;
@@ -41,14 +48,263 @@ template
void
show()
{
- cout << "Tup!! "<< lib::test::showType() <() < ([](auto i)
{
using Elm = std::tuple_element_t;
- cout <<" "<() <() <`
+ */
+ template
+ concept typeseq = requires (TSEQ seq)
+ {
+ // TSEQ can invoke a function with a Types subclass
+ [](Types&){/*placeholder*/}(seq);
+ };
+#endif ///////////////////////////////////////////////////////////////////////////////////////////////////(End) : new generic library functions
+
+
+ template class BUILD, typeseq TSEQ>
+ class FunTrampoline
+ {
+ using AllElm = ElmTypes;
+ using Indices = AllElm::Idx;
+ using Builder = BUILD;
+ using Functor = Builder::Functor;
+ using Table = std::array;
+
+ template
+ static constexpr Table
+ buildFunctors (std::index_sequence)
+ {
+ return {Builder().template build()...};
+ }
+
+ static constexpr Table functors = buildFunctors (Indices{});
+
+ public:
+ static constexpr size_t size() { return functors.size(); }
+ static constexpr size_t memSiz() { return sizeof(functors); }
+
+ static Functor const&
+ dispatch (size_t idx)
+ {
+ ENSURE (idx < functors.size());
+ return functors[idx];
+ }
+
+ using ResType = _Fun::Ret;
+ };
+
+
+#if false ///////////////////////////////////////////////////////////////////////////////////////////////////TODO : new generic library functions
+ template
+ using isConst = std::is_const>;
+ template
+ using isLRef = std::is_lvalue_reference;
+
+
+ template
+ using Any_Const = ElmTypes::template OrAll;
+
+ template
+ using All_LRef = ElmTypes::template AndAll;
+
+ template
+ static constexpr bool Any_Const_v = Any_Const::value;
+
+ template
+ static constexpr bool All_LRef_v = All_LRef::value;
+
+
+
+
+ template
+ struct ProbeCommonType
+ {
+
+ template
+ using Reconciled = decltype(true ? std::declval() : std::declval());
+
+
+ template
+ struct FoundResult
+ : std::true_type
+ {
+ using Type = RES;
+ };
+ struct NoResultFound
+ : std::false_type
+ { };
+
+ template>
+ static FoundResult>
+ check(int);
+
+ template
+ static NoResultFound
+ check(...);
+
+ using FirstResult = decltype(check(0));
+
+ template
+ struct Join
+ {
+ using Result = FirstResult;
+ };
+
+ template
+ struct Join
+ {
+ //wenn RES erfolgreich
+ using CT = FirstResult::Type;
+ using Result = ProbeCommonType::Result;
+ };
+
+ using Result = Join::Result;
+ };
+
+
+
+ template
+ struct CommonResult
+ : ProbeCommonType::Result
+ { };
+
+ template
+ struct CommonResult
+ : CommonResult
+ { };
+
+ template<>
+ struct CommonResult<>
+ : std::false_type
+ { };
+
+ template
+ struct CommonResult>
+ : CommonResult
+ { };
+
+ template
+ using CommonResult_t = CommonResult::Type;
+
+ template
+ static constexpr bool has_CommonResult_v = CommonResult::value;
+
+
+ template
+ concept reconcilable = requires
+ {
+ typename CommonResult::Type;
+ };
+
+ template
+ concept reconcilable_ref = reconcilable
+ and isLRef_v>;
+
+ template
+ struct CommonResultTraits
+ {
+ static_assert (reconcilable, "unable to reconcile these types");
+
+ using CommonVal = std::common_type_t;
+ using ResType = CommonResult_t;
+ //NOTE: std::common_type decays (strips CV and ref)
+ static constexpr bool makeConst = isConst_v;
+ static constexpr bool exposeRef = isLRef_v;
+ };
+#endif ///////////////////////////////////////////////////////////////////////////////////////////////////(End) : new generic library functions
+
+
+
+ template
+ class TupleIndexAdaptor
+ : public TUP
+ {
+ template
+ struct SubscriptBuilder
+ {
+ using Tuple = RefTraits::value_type;
+ using AddRefs = ElmTypes::template Apply;
+ using ResType = CommonResult_t;
+ using Functor = ResType(*)(Tuple&);
+
+ template
+ constexpr auto
+ build()
+ {
+ return [](Tuple& tuple) -> ResType
+ {
+ return getElm (tuple);
+ };
+ }
+ };
+
+ using TypeSeq = ElmTypes::Seq;
+ using Accessor = FunTrampoline;
+ public:
+ using ResType = Accessor::ResType;
+ using reference = ResType;
+ using value_Type = RefTraits::value_type;
+
+ template
+ TupleIndexAdaptor(T&& dataSrc)
+ : TUP{forward (dataSrc)}
+ { }
+
+ using TUP::TUP;
+
+ static constexpr size_t size() { return Accessor::size(); }
+
+ ResType
+ operator[] (size_t idx)
+ {
+ return Accessor::dispatch(idx)(*this);
+ }
+ };
+
+ template
+ TupleIndexAdaptor(TUP) -> TupleIndexAdaptor>;
+}}
+
+using namespace lib::meta;
+
+template
+struct Stringify
+ {
+ using Tuple = ElmTypes::Tup;
+ using Functor = string(*)(Tuple const&);
+
+ template
+ constexpr auto
+ build()
+ {
+ using ElmT = std::tuple_element_t;
+
+ return [](Tuple const& tuple)
+ {
+ return util::toString (getElm (tuple));
+ };
+ }
+
+ };
+
+
+struct Uber { };
+struct Untr : Uber { };
+struct Unta : Uber { };
+
int
main (int, char**)
@@ -57,20 +313,10 @@ main (int, char**)
using Arr = std::array;
using Hetero = lib::HeteroData::Chain::ChainExtent::ChainType;
- SHOW_EXPR((lib::meta::tuple_sized ))
- SHOW_EXPR((lib::meta::tuple_sized ))
- SHOW_EXPR((lib::meta::tuple_sized ))
- SHOW_EXPR((lib::meta::tuple_sized ))
-
- SHOW_EXPR((lib::meta::tuple_element_accessible))
-// SHOW_EXPR((lib::meta::tuple_element_accessible))
- SHOW_EXPR((lib::meta::tuple_element_accessible))
- SHOW_EXPR((lib::meta::tuple_accessible))
- SHOW_EXPR((lib::meta::tuple_accessible))
-
SHOW_EXPR((lib::meta::tuple_like ))
SHOW_EXPR((lib::meta::tuple_like ))
SHOW_EXPR((lib::meta::tuple_like ))
+ SHOW_EXPR((lib::meta::tuple_like ))
SHOW_EXPR((lib::meta::tuple_like ))
show();
@@ -78,25 +324,112 @@ main (int, char**)
show();
show();
- SHOW_EXPR((std::tuple_size_v))
- using Elm1 = std::tuple_element_t<1, const Tup>;
- SHOW_TYPE(Elm1)
- using TupConstSeq = lib::meta::ElmTypes::Seq;
- SHOW_TYPE(TupConstSeq)
+ using TupStringy = FunTrampoline::Seq>;
+SHOW_EXPR(TupStringy::size())
- using T1 = decltype(lib::meta::getElm<0> (std::declval()));
- SHOW_TYPE(T1)
- using T2 = decltype(lib::meta::getElm<0> (std::declval()));
- SHOW_TYPE(T2)
- using T3 = decltype(lib::meta::getElm<0> (std::declval()));
- SHOW_TYPE(T3)
-
- using H1 = decltype(lib::meta::getElm<4> (std::declval()));
- SHOW_TYPE(H1)
- using H2 = decltype(lib::meta::getElm<4> (std::declval()));
- SHOW_TYPE(H2)
- using H3 = decltype(lib::meta::getElm<4> (std::declval()));
- SHOW_TYPE(H3)
+ Tup tup23{2,3};
+ Tup tup42{4,2};
+SHOW_TYPE(decltype(std::get<1>(tup42)))
+SHOW_EXPR(std::get<1>(tup42))
+SHOW_EXPR(TupStringy::dispatch(0)(tup23))
+SHOW_EXPR(TupStringy::dispatch(0)(tup42))
+SHOW_EXPR(TupStringy::dispatch(1)(tup23))
+SHOW_EXPR(TupStringy::dispatch(1)(tup42))
+
+ using T1 = Types;
+ using T2 = Types;
+ using T3 = Types;
+SHOW_EXPR((has_CommonResult_v))
+SHOW_EXPR((has_CommonResult_v))
+SHOW_EXPR((has_CommonResult_v))
+SHOW_EXPR((has_CommonResult_v<>))
+SHOW_EXPR((has_CommonResult_v))
+SHOW_EXPR((has_CommonResult_v))
+
+SHOW_TYPE(CommonResult_t)
+SHOW_TYPE(CommonResult_t)
+SHOW_TYPE(CommonResult_t)
+using CoTx = CommonResult_t;
+SHOW_TYPE(CoTx)
+
+
+ TupleIndexAdaptor idxAdapt{tup42};
+SHOW_EXPR(sizeof(tup42))
+SHOW_EXPR(sizeof(idxAdapt))
+SHOW_TYPE(TupleIndexAdaptor::ResType)
+SHOW_EXPR(idxAdapt.size())
+SHOW_EXPR(idxAdapt[0])
+SHOW_EXPR(idxAdapt[1])
+SHOW_EXPR(getElm<0>(static_cast (idxAdapt)))
+SHOW_EXPR(getElm<1>(static_cast (idxAdapt)))
+SHOW_TYPE(decltype(idxAdapt[1]))
+
+ using Tup2 = std::tuple;
+ int ii{23};
+ Tup2 tup21{-1,ii,55};
+ TupleIndexAdaptor idxApt2{tup21};
+SHOW_TYPE(decltype(tup21))
+ using IdxApt2 = decltype(idxApt2);
+SHOW_TYPE(IdxApt2)
+SHOW_TYPE(IdxApt2::ResType)
+SHOW_EXPR(idxApt2[0])
+SHOW_EXPR(idxApt2[1])
+SHOW_EXPR(idxApt2[2])
+SHOW_EXPR(++idxApt2[0])
+SHOW_EXPR(idxApt2[1]++)
+SHOW_EXPR(++++idxApt2[2])
+SHOW_EXPR(tup21)
+SHOW_EXPR(Tup2(idxApt2))
+SHOW_EXPR(ii)
+
+ using TupIt = lib::IterableDecorator>;
+ TupIt tupIt{move(idxApt2)};
+SHOW_EXPR( bool(tupIt) )
+SHOW_EXPR( *tupIt )
+SHOW_TYPE(decltype(*tupIt))
+ ++*tupIt;
+ --ii;
+SHOW_EXPR( *tupIt )
+SHOW_EXPR(util::join(tupIt, "▶▶"))
+
+SHOW_EXPR(( reconcilable ))
+SHOW_EXPR(( reconcilable ))
+SHOW_EXPR(( reconcilable ))
+SHOW_EXPR(( reconcilable ))
+SHOW_EXPR(( reconcilable_ref ))
+SHOW_EXPR(( reconcilable_ref ))
+SHOW_EXPR(( reconcilable_ref ))
+SHOW_EXPR(( reconcilable_ref ))
+ using TX = CommonResult_t;
+SHOW_TYPE(TX)
+SHOW_EXPR(( reconcilable ))
+SHOW_EXPR(( reconcilable ))
+SHOW_EXPR(( reconcilable ))
+ using TX2 = CommonResult_t;
+SHOW_TYPE(TX2)
+SHOW_EXPR(( reconcilable ))
+SHOW_EXPR(( reconcilable ))
+SHOW_EXPR(( reconcilable ))
+SHOW_EXPR(( reconcilable ))
+SHOW_EXPR(( reconcilable_ref ))
+SHOW_EXPR(( reconcilable_ref ))
+SHOW_EXPR(( reconcilable ))
+SHOW_EXPR(( reconcilable ))
+ using TX3 = CommonResult_t;
+SHOW_TYPE(TX3)
+ using TX4 = CommonResult_t;
+SHOW_TYPE(TX4)
+SHOW_EXPR(( reconcilable ))
+ using TX5 = CommonResult_t;
+SHOW_TYPE(TX5)
+ using TX6 = CommonResult_t;
+SHOW_TYPE(TX6)
+SHOW_EXPR(( CommonResult::value ))
+SHOW_EXPR(( CommonResult::value ))
+SHOW_EXPR(( CommonResult::value ))
+SHOW_EXPR(( reconcilable ))
+SHOW_EXPR(( reconcilable ))
+SHOW_EXPR(( reconcilable ))
cout << "\n.gulp." <
@@ -11,32 +11,30 @@
*/
-/** @file lifecycle.h
+/** @file lifecycle.hpp
** Installing and invoking of application lifecycle event callbacks.
- ** This service is a facade for and implemented by the lumiera::LifecycleRegistry.
+ ** This service is a facade for and implemented by the vessel::LifecycleRegistry.
** By placing a static LifecycleHook variable or by calling LifecycleHook::add,
** a callback can be registered to be executed on a specific application lifecycle
** event. Examples being #ON_BASIC_INIT, #ON_GLOBAL_INIT. Other subsystems may
** register additional events for more specific purpose.
**
** @note the implementation resides in lib/lifecycle.cpp and gets linked into liblumiera.so
- ** @see lumiera::AppState
+ ** @see vessel::Voyage
** @see main.cpp
*/
-#ifndef LUMIERA_LIFECYCLE_H
-#define LUMIERA_LIFECYCLE_H
+#ifndef VESSEL_LIFECYCLE_H
+#define VESSEL_LIFECYCLE_H
-#ifdef __cplusplus
-
#include "lib/symbol.hpp"
#include "lib/nocopy.hpp"
-namespace lumiera {
+namespace vessel {
using lib::Symbol;
@@ -81,21 +79,5 @@ namespace lumiera {
-} // namespace lumiera
-
-
-
-#else /* =========== C interface ====================== */
-
-
-//defined in liblumiera.so
-extern const char * lumiera_ON_BASIC_INIT;
-extern const char * lumiera_ON_GLOBAL_INIT;
-extern const char * lumiera_ON_GLOBAL_SHUTDOWN;
-
-
-void lumiera_LifecycleHook_add (const char* eventLabel, void callbackFun(void));
-void lumiera_Lifecycle_trigger (const char* eventLabel);
-
-#endif
-#endif
+} // namespace vessel
+#endif /*VESSEL_LIFECYCLE_H*/
diff --git a/src/include/session-command-facade.h b/src/include/session-command-facade.h
index a23dbf593..6851ca146 100644
--- a/src/include/session-command-facade.h
+++ b/src/include/session-command-facade.h
@@ -116,7 +116,7 @@ extern "C" {
#endif /* =========================== CL Interface ===================== */
-#include "common/interface.h"
+#include "vessel/interface.h"
LUMIERA_INTERFACE_DECLARE (lumieraorg_SessionCommand, 0,
LUMIERA_INTERFACE_SLOT (const char*, cycle, (const char*, const char*)),
diff --git a/src/lib/allocator-handle.hpp b/src/lib/allocator-handle.hpp
index d7c0477f3..4676bef02 100644
--- a/src/lib/allocator-handle.hpp
+++ b/src/lib/allocator-handle.hpp
@@ -51,6 +51,7 @@
#include
#include
+#include
#include
diff --git a/src/lib/builder-qualifier-support.hpp b/src/lib/builder-qualifier-support.hpp
index 5513f7cc8..3f9e32cdc 100644
--- a/src/lib/builder-qualifier-support.hpp
+++ b/src/lib/builder-qualifier-support.hpp
@@ -31,7 +31,7 @@
** @warning since these qualifiers manipulate by side-effect, it is up to the user to ensure
** consistent settings and behaviour (typically within a terminal `build()` function).
** @note the `qualify()` function accepts the qualifier functors by-reference; thus it is up
- ** to the user to either pass them by-value, by reverence or even by perfect forwarding.
+ ** to the user to either pass them by-value, by reference or even by perfect forwarding.
**
** @see BuilderQualifierSupport_test
** @see ElementBoxWidget as usage example
diff --git a/src/lib/depend-inject.hpp b/src/lib/depend-inject.hpp
index 6a3edebd6..c68009d56 100644
--- a/src/lib/depend-inject.hpp
+++ b/src/lib/depend-inject.hpp
@@ -376,7 +376,7 @@ namespace lib {
using ResultVal = meta::_Fun::Ret;
using Subclass = meta::Strip::TypePlain;
- static_assert (std::is_pointer::value,
+ static_assert (std::is_pointer_v,
"Function must yield a pointer to a heap allocated instance");
};
diff --git a/src/lib/diff/gen-node.cpp b/src/lib/diff/gen-node.cpp
index 69cc70ca7..ed0b18c7a 100644
--- a/src/lib/diff/gen-node.cpp
+++ b/src/lib/diff/gen-node.cpp
@@ -44,7 +44,7 @@
using util::join;
using boost::lexical_cast;
using lib::time::TimeValue;
-using lib::transformIterator;
+using lib::transformIter;
using util::almostEqual;
using lib::hash::LuidH;
@@ -297,9 +297,9 @@ namespace diff{
return (Rec::TYPE_NIL==rec.getType()? "" : rec.getType())
+ "{"
- + join (transformIterator (rec.attribs(), renderAttrib))
+ + join (transformIter (rec.attribs(), renderAttrib))
+ (isnil(rec.scope())? "" : "|")
- + join (transformIterator (rec.scope() , renderChild))
+ + join (transformIter (rec.scope() , renderChild))
+ "}"
;
}
diff --git a/src/lib/diff/gen-node.hpp b/src/lib/diff/gen-node.hpp
index 5a794743a..9f21f9d15 100644
--- a/src/lib/diff/gen-node.hpp
+++ b/src/lib/diff/gen-node.hpp
@@ -375,8 +375,6 @@ namespace diff{
iterator end() const;
- using ChildDataIter = TransformIter;
-
/** visit the _data_ of nested child elements
* @return an iterator over the DataCap elements of all children,
* in case this GenNode actually holds a Record.
@@ -384,26 +382,26 @@ namespace diff{
* @note this iterator visits _only_ the children, which are
* by definition unnamed. It does _not_ visit attributes.
*/
- friend ChildDataIter
+ friend auto
childData (GenNode const& n)
{
- return ChildDataIter{ n.data.childIter()
- , [](GenNode const& child) ->DataCap const&
+ return transformIter(n.data.childIter()
+ ,[](GenNode const& child) ->DataCap const&
{
return child.data;
}
- };
+ );
}
- friend ChildDataIter
+ friend auto
childData (Rec::scopeIter&& scopeIter)
{
- return ChildDataIter{ std::forward(scopeIter)
- , [](GenNode const& child) ->DataCap const&
+ return transformIter(std::forward(scopeIter)
+ ,[](GenNode const& child) ->DataCap const&
{
return child.data;
}
- };
+ );
}
@@ -776,7 +774,7 @@ namespace diff{
inline std::optional
DataCap::retrieveAttribute (string key) const
{
- static_assert (not std::is_reference_v
+ static_assert (not meta::isRef_v
,"optional access only possible by value");
Rec* nested = unConst(this)->maybeAccessNestedRec();
diff --git a/src/lib/diff/mutation-message.hpp b/src/lib/diff/mutation-message.hpp
index 735c6ca07..b4ae1a1bc 100644
--- a/src/lib/diff/mutation-message.hpp
+++ b/src/lib/diff/mutation-message.hpp
@@ -100,7 +100,7 @@ namespace diff{
using std::__and_;
using std::__not_;
using lib::meta::enable_if;
- using lib::meta::can_IterForEach;
+ using lib::meta::can_LumieraIter;
using lib::meta::can_STL_ForEach;
using DiffStep = TreeDiffLanguage::DiffStep;
@@ -168,7 +168,7 @@ namespace diff{
* @note source iterator is copied into a heap allocated IterSource
*/
template
- MutationMessage(IT&& ii, enable_if< can_IterForEach, void*> =nullptr)
+ MutationMessage(IT&& ii, enable_if< can_LumieraIter, void*> =nullptr)
: _FrontEnd{iter_source::wrapIter (std::forward(ii))}
{ }
@@ -179,7 +179,7 @@ namespace diff{
*/
template
MutationMessage(CON& container, enable_if< __and_< can_STL_ForEach
- ,__not_>>, void*> =nullptr)
+ ,__not_>>, void*> =nullptr)
: _FrontEnd{iter_source::eachEntry(container)}
{ }
diff --git a/src/lib/diff/record.hpp b/src/lib/diff/record.hpp
index 89c9f7637..e5da73aba 100644
--- a/src/lib/diff/record.hpp
+++ b/src/lib/diff/record.hpp
@@ -308,18 +308,16 @@ namespace diff{
using iterator = IterAdapter;
using scopeIter = iter_stl::_SeqT::Range;
- using keyIter = TransformIter;
- using valIter = TransformIter;
/** default iteration exposes all data within this "object", starting with the attributes */
iterator begin () const { return iterator(this, attribs_.empty()? children_.begin() : attribs_.begin()); }
iterator end () const { return iterator(); }
- scopeIter attribs() const { return iter_stl::eachElm(attribs_); }
- scopeIter scope() const { return iter_stl::eachElm(children_); }
+ scopeIter attribs() const { return iter_stl::eachElm (attribs_); }
+ scopeIter scope() const { return iter_stl::eachElm (children_); }
- keyIter keys() const { return transformIterator(attribs(), extractKey); }
- valIter vals() const { return transformIterator(attribs(), extractVal); }
+ auto keys() const { return transformIter (attribs(), extractKey); }
+ auto vals() const { return transformIter (attribs(), extractVal); }
protected: /* ==== API for the IterAdapter ==== */
@@ -792,11 +790,11 @@ namespace diff{
Record::operator std::string() const
{
using util::join;
- using lib::transformIterator;
+ using lib::transformIter;
return "Rec("
+ (TYPE_NIL==type_? "" : type_)
- + (isnil(this->attribs())? "" : "| "+join (transformIterator (this->attribs(), renderAttribute))+" ")
+ + (isnil(this->attribs())? "" : "| "+join (transformIter (this->attribs(), renderAttribute))+" ")
+ (isnil(this->scope())? "" : "|{"+join (this->scope())+"}")
+ ")"
;
diff --git a/src/lib/diff/test-mutation-target.hpp b/src/lib/diff/test-mutation-target.hpp
index 713fe23b6..7a308ed73 100644
--- a/src/lib/diff/test-mutation-target.hpp
+++ b/src/lib/diff/test-mutation-target.hpp
@@ -43,7 +43,7 @@
#include "lib/idi/genfunc.hpp"
#include "lib/format-string.hpp"
#include "lib/format-util.hpp"
-#include "lib/test/event-log.hpp"
+#include "test/event-log.hpp"
#include "lib/nocopy.hpp"
#include "lib/util.hpp"
@@ -58,8 +58,8 @@ namespace diff{
namespace error = lumiera::error;
using lib::Literal;
- using lib::test::EventLog;
- using lib::test::EventMatch;
+ using test::EventLog;
+ using test::EventMatch;
using iter_stl::eachElm;
using util::unConst;
using util::isnil;
@@ -110,12 +110,12 @@ namespace diff{
renderRecord (Rec const& record)
{
using util::join;
- using lib::transformIterator;
+ using lib::transformIter;
return "Rec("
+ (Rec::TYPE_NIL==record.getType()? "" : record.getType())
- + (isnil(record.attribs())? "" : "| "+join (transformIterator (record.attribs(), renderAttribute))+" ")
- + (isnil(record.scope())? "" : "|{"+join (transformIterator (record.scope(), renderChild))+"}")
+ + (isnil(record.attribs())? "" : "| "+join (transformIter (record.attribs(), renderAttribute))+" ")
+ + (isnil(record.scope())? "" : "|{"+join (transformIter (record.scope(), renderChild))+"}")
+ ")"
;
}
@@ -289,14 +289,14 @@ namespace diff{
string
showContent () const
{
- return join (transformIterator (begin(), renderNode));
+ return join (transformIter (begin(), renderNode));
}
/** render elements waiting in source buffer to be accepted */
string
showSrcBuffer () const
{
- return join (transformIterator (eachElm(prev_content_), renderNode));
+ return join (transformIter (eachElm(prev_content_), renderNode));
}
EventMatch
diff --git a/src/lib/diff/tree-mutator-collection-binding.hpp b/src/lib/diff/tree-mutator-collection-binding.hpp
index ef237a583..fc36284d4 100644
--- a/src/lib/diff/tree-mutator-collection-binding.hpp
+++ b/src/lib/diff/tree-mutator-collection-binding.hpp
@@ -76,6 +76,7 @@
#include "lib/error.hpp"
#include "lib/nocopy.hpp"
#include "lib/meta/trait.hpp"
+#include "lib/meta/function.hpp"
#include "lib/diff/gen-node.hpp"
#include "lib/diff/tree-mutator.hpp"
#include "lib/iter-adapter-stl.hpp"
diff --git a/src/lib/error-exception.cpp b/src/lib/error-exception.cpp
index 74669ddfe..36191a7e5 100644
--- a/src/lib/error-exception.cpp
+++ b/src/lib/error-exception.cpp
@@ -24,7 +24,7 @@
#include "lib/error.hpp"
-#include "include/lifecycle.h"
+#include "include/lifecycle.hpp"
#include "lib/meta/util.hpp"
#include "lib/util.hpp"
@@ -154,6 +154,9 @@ namespace lumiera {
namespace error {
namespace {
+ using vessel::LifecycleHook;
+ using vessel::ON_BASIC_INIT;
+
void install_unexpectedException_handler ()
{
std::set_terminate (lumiera_unexpectedException);
diff --git a/src/lib/format-obj.cpp b/src/lib/format-obj.cpp
index 57dc1191c..676a4713f 100644
--- a/src/lib/format-obj.cpp
+++ b/src/lib/format-obj.cpp
@@ -197,14 +197,15 @@ apologies for that."
"|(\\w+::)+\\(anonymous namespace\\)::"
"|lib::meta::"
"|lib::time::"
- "|lib::test::"
"|lib::diff::"
"|lib::"
"|util::"
+ "|\\btest::"
"|steam::(asset::|mobject::(session::)?|play::)?"
"|stage::model"
"|stage::ctrl"
"|lumiera::"
+ "|vessel::"
, regex::ECMAScript | regex::optimize};
static regex lolong {"long long"
diff --git a/src/lib/format-obj.hpp b/src/lib/format-obj.hpp
index 85f65a2b1..842a26ff6 100644
--- a/src/lib/format-obj.hpp
+++ b/src/lib/format-obj.hpp
@@ -100,6 +100,119 @@ namespace util {
+
+ namespace { // helper for printing type diagnostics
+
+ template
+ struct TypeDiagnostics
+ {
+ using Type = X;
+ static constexpr auto prefix = "";
+ static constexpr auto postfix = "";
+ };
+ template
+ struct TypeDiagnostics
+ {
+ using Type = X;
+ static constexpr auto prefix = "const ";
+ static constexpr auto postfix = "";
+ };
+ template
+ struct TypeDiagnostics
+ {
+ using Type = X;
+ static constexpr auto prefix = "";
+ static constexpr auto postfix = "&";
+ };
+ template
+ struct TypeDiagnostics
+ {
+ using Type = X;
+ static constexpr auto prefix = "";
+ static constexpr auto postfix = " &&";
+ };
+ template
+ struct TypeDiagnostics
+ {
+ using Type = X;
+ static constexpr auto prefix = "";
+ static constexpr auto postfix = " const&";
+ };
+ template
+ struct TypeDiagnostics
+ {
+ using Type = X;
+ static constexpr auto prefix = "const ";
+ static constexpr auto postfix = " &&";
+ };
+ template
+ struct TypeDiagnostics
+ {
+ using Type = X;
+ static constexpr auto prefix = "";
+ static constexpr auto postfix = " *";
+ };
+ template
+ struct TypeDiagnostics
+ {
+ using Type = X;
+ static constexpr auto prefix = "const ";
+ static constexpr auto postfix = " *";
+ };
+ template
+ struct TypeDiagnostics
+ {
+ using Type = X;
+ static constexpr auto prefix = "const ";
+ static constexpr auto postfix = " * const";
+ };
+ template
+ struct TypeDiagnostics
+ {
+ using Type = X;
+ static constexpr auto prefix = "";
+ static constexpr auto postfix = " * const";
+ };
+ template
+ struct TypeDiagnostics
+ {
+ using Type = X;
+ static constexpr auto prefix = "";
+ static constexpr auto postfix = " * const *";
+ };
+ }//(End)decoration helper
+
+ /** diagnostic type output, including const and similar adornments
+ * @warning operates after-the-fact and relies on mangled type names
+ * plus several heuristics. Output might thus not be entirely correct,
+ * especially when several levels of const, pointer and references are involved.
+ * If in doubt, place the test::TypeDebugger to reveal the type as the compiler sees it.
+ * @remarks the function lib::meta::typeStr was deliberately written such as to remove type adornments
+ * and does not work on all kinds of reference. This helper complements this and
+ * attempts to preserve const-ness, pointer and reference decoration.
+ */
+ template
+ inline std::string
+ showType()
+ {
+ using Case = TypeDiagnostics;
+ using Type = Case::Type;
+
+ return Case::prefix
+ + lib::meta::humanReadableTypeID (typeid(Type).name())
+ + Case::postfix;
+ }
+
+ template
+ inline std::string
+ showTypes()
+ {
+ return "<| " + ((showType()+", ") + ... + "|>");
+ }
+
+
+
+
namespace {
/** toggle to prefer specialisation with direct lexical conversion */
template
diff --git a/src/lib/format-util.hpp b/src/lib/format-util.hpp
index 01e7c8616..80d044666 100644
--- a/src/lib/format-util.hpp
+++ b/src/lib/format-util.hpp
@@ -46,7 +46,7 @@
namespace util {
- using lib::meta::can_IterForEach;
+ using lib::meta::lum_iter;
using std::string;
using std::forward;
using std::move;
@@ -135,13 +135,13 @@ namespace util {
{
using Val = lib::meta::ValueTypeBinding::value_type;
- return lib::transformIterator(forward(src), util::toString);
+ return lib::transformIter (forward(src), util::toString);
}
namespace { // helper to build range iterator on demand
- template
+ template
struct _RangeIter
{
using StlIter = CON::const_iterator;
@@ -153,8 +153,8 @@ namespace util {
{ }
};
- template
- struct _RangeIter> >
+ template
+ struct _RangeIter
{
IT iter;
diff --git a/src/lib/hash-standard.hpp b/src/lib/hash-standard.hpp
index b603c8e6f..2703a14b8 100644
--- a/src/lib/hash-standard.hpp
+++ b/src/lib/hash-standard.hpp
@@ -44,9 +44,11 @@
** Please ensure it is always included _before_ the latter. Failing to do so will result
** in mysterious failures.
**
- ** @todo 4/2014 doesn't work as expected. My suspicion is that in the actual use case (PlacementIndex),
- ** the type providing the hasher is mixed in through inheritance, and the template specialisation
- ** for this base type is not considered on lookup. ///////TICKET #722
+ ** @todo 4/2026 this shady trickery works without problems since many years now,
+ ** while it is not clear if we actually need to do these horrible things any more.
+ ** Even while we may retain that automatic bridge to boost-functional hash, doing so
+ ** should be possible with the current STDLIB without having to patch and rewire
+ ** the library implementation. //////////////////////////////////////////////////////////////////////TICKET #1422 : re-assess the situation !
**
** @see HashIndexed
** @see LUID
@@ -106,10 +108,6 @@ namespace std {
{
static_assert (sizeof(TY) < 0, "No hash implementation found. "
"Either specialise std::hash or provide a boost-style hash_value via ADL.");
-
- // the default provides *no* hash implementation
- // and adds a marker type for metaprogramming
- typedef int NotHashable;
};
/**
@@ -129,8 +127,8 @@ namespace std {
/**
* Primary class template for std::hash.
- * We provide no default implementation, but a marker type
- * to allow detection of custom implementation through metaprogramming
+ * We provide no default implementation, but bridge automatically
+ * when a boost-style hash function can be picked up via ADL.
*
* @note this definition has been \em hijacked by Lumiera
* to add an automatic bridge to use boost::hash functions
@@ -140,12 +138,14 @@ namespace std {
: public _HashImplementationSelector
{ };
-}
+}// namespace std
-/* ==== Evil Evil ==== */
+
+
+/* ==== Evil Evil ==== */ ////////////////////////////////////////////////////////////////TICKET #1422 : very likely we do not need this manipulation any more !!!
#define hash hash_HIDDEN
#define _Hash_impl _Hash_impl_HIDDEN
@@ -204,6 +204,12 @@ namespace std {
STD_HASH_IMPL (long double)
#undef STD_HASH_IMPL
-}
+
+ /** rewire the partial specialisation for pointer types */
+ template
+ struct hash : public hash_HIDDEN { };
+
+
+}// namespace std
#endif /*LIB_HASH_STANDARD_H*/
diff --git a/src/lib/index-iter.hpp b/src/lib/index-iter.hpp
index b8bb7915f..be709bff2 100644
--- a/src/lib/index-iter.hpp
+++ b/src/lib/index-iter.hpp
@@ -50,8 +50,8 @@ namespace lib {
using ResVal = decltype(data_->operator[](0));
- using value_type = meta::RefTraits::Value;
- using reference = meta::RefTraits::Reference;
+ using value_type = meta::RefTraits::value_type;
+ using reference = meta::RefTraits::reference;
bool
checkPoint() const
diff --git a/src/lib/item-wrapper.hpp b/src/lib/item-wrapper.hpp
index bd45621ed..aca3fbc78 100644
--- a/src/lib/item-wrapper.hpp
+++ b/src/lib/item-wrapper.hpp
@@ -31,7 +31,7 @@
** this to the pattern of _type erasure_, where we discard specific
** knowledge after construction; for _such_ cases, opaque-holder.hpp
** might be a better fit.
- ** @see lib::TransformIter
+ ** @see lib::iter::Transform
** @see lib::explore
**
*/
diff --git a/src/lib/iter-adapter-ptr-deref.hpp b/src/lib/iter-adapter-ptr-deref.hpp
index 3458efe80..22d89658f 100644
--- a/src/lib/iter-adapter-ptr-deref.hpp
+++ b/src/lib/iter-adapter-ptr-deref.hpp
@@ -61,7 +61,7 @@ namespace lib {
public:
/** this iterator adapter is meant to wrap an iterator yielding pointer values */
using pointer = meta::ValueTypeBinding::value_type;
- static_assert(std::is_pointer_v);
+ static_assert(is_pointer_v);
using value_type = std::remove_pointer_t;
using reference = value_type&;
@@ -74,8 +74,8 @@ namespace lib {
using ValueTypeBase = std::remove_const_t