Commit graph

2663 commits

Author SHA1 Message Date
2c3b85a122 Dispatcher-Pipeline: allocate JobTicket in Segment
PROBLEM: can not implement Spec-generation, since
 - we must use a λ for internal allocation of JobTickets
 - but recursive type inference is not possible

Will thus need to abandon the Spec-Tuple and relocate this
traversal-and-generation code into JobTicket itself
2023-06-09 02:48:38 +02:00
c246c21e41 Dispatcher-Pipeline: remould Segment for on-demand JobTicket generation
Use another unit-test (FixtureSegment_test) to guide and cover
the transition from the existing fake-implementation to the
actual implementation, where the JobTicket will be generated
on-demand, from a NodeGraphAttachment
2023-06-08 03:21:43 +02:00
0c57a61545 Dispatcher-Pipeline: implement Generation of fake-ExitNodes
...similar to the Generation of complete JobTickets in the initial implementation
2023-06-08 00:28:44 +02:00
f6af4c6a16 Dispatcher-Pipeline: prepare test for the new NodeGraphAttachment
It turns out that the real (not mocked) implementation of JobTicket creation
is already required now for this planned (mock)Dispatcher setup;
moreover, this real implementation turns out to be almost identical
to the mock implementation written recently -- just nested structure
of prerequiste JobTickets need to be changed into a similar structur
of ExitNodes

-- as an aside: rearrange various tests to be more in-line
   with the envisioned architecture of playback and engine
2023-06-07 04:03:00 +02:00
3b2e5db7b4 Dispatcher-Pipeline: consider how to access render nodes from job
...this opens up yet another difficult question and a host of new problems
- how are prerequisites detected or arranged by the Builder
- how are prerequisites represented?
- what is an ExitNode in terms of implementation? A subclass of ProcNode?
- how will the actual implementation of JobTicket creation (on-demand) work?
- how to adapt the Mock implementation, while retaining the Specification
  for Segments and prerequisites?
2023-06-06 04:25:12 +02:00
7d5c32e6b6 Dispatcher-Pipeline: draft test for JobTicket access 2023-06-05 18:09:42 +02:00
4601c6350e Dispatcher-Pipeline: arrangement of builder types
...it turns out that we actually do not need to wrap TreeExplorer
on the builder types, because basically there is only a single active
builder type, and the complete processing pipeline can be assembled
in a single terminal function.

The type rebinding problem can thus be solved just by a simple
marker struct, which inherits from a template parameter
2023-06-04 02:01:07 +02:00
71ea10bf21 Dispatcher-Pipeline: implement the frame-tick core
splitting into a sequence of builder types seems to have done the trick
2023-06-03 18:38:37 +02:00
81ee9a2e67 Dispatcher-Pipeline: builder type rebinding problems
...hard to tackle...
The idea is to wrap the TreeExplorer builder, so that our specific
builder functions can delegated to the (inherited) generic builder functions
and would just need to supply some cleverly bound lambdas. However,
resulting types are recursive, which does not play nice with type inference,
and working around that problem leads to capturing a self reference,
which at time of invocation is already invalidated (due to moving the
whole pipeline into the final storage)
2023-06-03 03:44:22 +02:00
94fe4a4bec Dispatcher-Pipeline: draft builder-API
...which leads to the next daunting problems:
- we need some mocked ModelPort and DataSink placeholders
- we need a way how to inherit from a partial TreeExplorer pipeline
2023-06-02 05:32:15 +02:00
dda37365cc Dispatcher-Pipeline: direct implementation of frame-tick
start with demonstration of base technique in test setup
2023-06-01 18:09:26 +02:00
ad173540d9 Library: allow for a stop condition in iterator pipeline
...introduced in preparation for building the Dispatcher pipeline,
which at its core means to iterate over a sequence of frame positions;
thus we need a way to stop rendering at a predetermined point...
2023-06-01 16:48:27 +02:00
fbfbd2a078 Dispatcher+Scheduler: decision to dispose of the TimeAnchor
several years ago, it seemed like a good idea to incorporate
the link between nominal time and wall-clock time into a dedicated
anchor point, which also regulates the continued frame planning.

But it turned out that such a design mixes up several concepts
and introduces confusion regarding the meaning of "real time"
- latency can not be reasonably defined for a whole planning chunk
- skipping or sliding due to missed deadlines can not reasonably handled
  within such an abstract entity; it must be handled rather at the
  level of a playback process
- linking the frame grid generation directly to a planning chunk
  undercuts the possible abstraction of a planning pipeline
2023-05-31 03:27:13 +02:00
87f40c8169 Dispatcher+Scheduler: Requirement analysis and planning work 2023-05-29 04:43:10 +02:00
b4c0ffab25 Job-Planning: Analysis for the next step
...which is build a »Job planning pipeline« step by step
in a test setup, and then factor that out as RenderDrive,
to supersede the existing CalcPlanContinuation and get
rid of the Monads this way...

Challenges
- there is a inconsistency with channel usage
- need to establish a way how to transport the output-Sink into the JobFunctor
- need a way to propagate the current frame number to the next planning chunk
2023-05-26 04:20:12 +02:00
e33689e5d6 Job-Planning: verify and complete the build-up of mock structures (see #1294)
The prototypical setup of data structures and test support components
is largely complete by now — with the exception of the `MockDispatcher`,
which will be completed while moving to the next steps pertaining the
setup of a frame dispatch pipeline.

 * the existing `DummyJob` was augmented to allow verification of
   association between Job and `JobTicket`
 * the existing implementation of `JobTicket` was verified and augmented
   to allow coverage of the whole usage cycle
 * a `MockJobTicket` was implemented on top, which can be generated
   from a symbolical test specification (rather than from the real
   Fixture data structure)
 * a complete `MockSegmentation` was developed, allowing to establish
   all the aforementioned data structures without an actual backing
   Render Engine. Moreover, `MockSegmentation` can be generated
   from the aforementioned symbolic test specification.
 * as part of this work, an algorithm to split an existing Segmentation
   and to splice in new segments was developed and verified
2023-05-24 03:38:12 +02:00
4f37b0412c Job-Planning: finally complete the MockSegmentation tests
Last testcase: add deeply nested Prerequisites.
Turns out that the allocator must be able to handle
re-entrant allocations, which std::deque can not fulfil.
Thus using std::list here for the Mock implementation.

In the end, the real allocations will be done by our custom
allocator (AllocationCluster), which can be arranged easily
to support re-entrant allocation calls (since the whole point
is to just place those objects into a pre-allocated large block
and only de-allocate them later in one sway. Thus the allocator
does not need to wait for the object constructor to finish, which
trivially allows for re-entrant calls)
2023-05-23 06:40:18 +02:00
94cec423d0 Job-Planning: switch to processing references
...which uncovers further deeply nested problems,
especially when referring to non-copyable types.

Thus need to construct a common type that can be used
both to refer to the source elements and the expanded elements,
and use this common type as result type and also attempt to
produce better diagnostic messages on type mismatch....
2023-05-23 01:08:05 +02:00
bf6951afcf Job-Planning: verify pipeline can now be constructed (after bugfix)
verify by in-depth investigation that all nested typedefs are now properly constructed
2023-05-23 01:07:53 +02:00
0df0fd001e Library: fix follow-up problems with const correctness
...the improved const correctness on STL iterators uncovered another
latent problem with out diagnositc format helper, which provide
consistently rounded float and double output, but failed to take
CV-qualifiaction into account
2023-05-23 01:07:53 +02:00
e176e54004 Library: adjust and fix semantics of nested 'value_type' binding
This is a subtle and far reaching fix, which hopefully removes
a roadblock regarding a Dispatcher pipeline: Our type rebinding
template used to pick up nested type definitions, especially
'value_type' and 'reference' from iterators and containers,
took an overly simplistic approach, which was then fixed
at various places driven by individual problems.

Now:
 - value_type is conceptually the "thing" exposed by the iterator
 - and pointers are treated as simple values, and no longer linked
   to their pointee type; rather we handle the twist regarding
   STL const_iterator direcly (it defines a non const value_type,
   which is sensible from the STL point of view, but breaks our
   generic iterator wrapping mechanism)
2023-05-23 01:07:53 +02:00
67468f15d5 Job-Planning: Attempt to build a prerequisite-Pipeline failed -- investigate why
To complete the mock setup, the next step would be to extend the GenNode-based spec langage
to allow defining prerequisite Mock-JobTickets. Setting this up seems rather straight forward --

however, defining a simple testcase to cover this extension runs into surprisingly tricky problems..
- for one, the singleValIterator from Itertools has serious difficulties handling references
- but even more surprising, it seems impossible to make the "prerequisites iterator"
  fit into the Tree-Explorer framework (which I intend to use as replacement
  for the monadic approach)

after some extended analysis of generic types and template instances,
it seems that not TreeExplorer as such is the primary problem, but rather
there is a conceptual mismatch somewhere deep down in Itertools or Iter-Adapter
2023-05-23 01:07:07 +02:00
27a8e91fa2 Job-Ticket: consider how to deal with channels and prerequisites
By reasoning and analysis I conclude that the differentiation into
multiple channels is likely misplaced in JobTicket; it belongs ratther
into the Segment and should provide a suitable JobTicket for each ModelPort

Handling of prerequisites also needs to be reshaped entirely after
switching to a pipeline builder for the Job-planning pipeline; as
preliminary access point, just add an iterator over the immediate
prerequisites, thereby shifting the exploration mechanism entirely
out of the JobTicket implementation
2023-05-11 22:47:56 +02:00
db87de3c92 Segmentation: complete implementation of mock / test stub setup
We are now able to build and refine a segmentation
and to get distinct MockJobs from these segments
and to verify invocation of a specific job
2023-05-10 15:00:10 +02:00
a940cd25bc Library: extract helper for unloading a sequence into a tuple 2023-05-10 14:49:51 +02:00
566f73de2a Segmentation: verify standard cases..
Testcase: A simple Sementation with a single and bounded Segment


As aside, figured out how to unpack an iterator such as to
tie a fixed number of references through a structural binding:

auto const& [s1,s2,s3] = seqTuple<3> (mockSegs.eachSeg());
2023-05-10 03:59:46 +02:00
e5cdb86ac3 Segmentation: integrate SplitSplice and build mock-segmentation
...now able to build a mock segmentation which issues dummy jobs,
and is wired such as to verify the right job is invoked for each segment.

And this allows to build and verify the Dispatcher,
without being able to invoke actual render jobs yet.
2023-05-05 03:46:42 +02:00
256045f91d Segmentation: add test case to cover instance management
- only the parts actually touched by the algo will be re-allocated
- when a segment is split, the clone copies carry on all data


Library: add function to check for a bare address (without type info)
2023-05-05 01:34:41 +02:00
52dad70753 Segmentation: Split-Splice algorithm implementation complete
...and verified including corner cases...
2023-05-04 15:59:17 +02:00
3f2f3db568 Segmentation: verify Split-Splice standard cases
Algorithm seems to work basically...
There was a copy-n-paste error in the treatment of the Successor,
leading to spurious duplication in some cases
2023-05-04 14:43:40 +02:00
c8f879ff3f Segmentation: extract invocation for test
typically you'd write an custom adaptor function
to define all the λ-bindings for the Algorithm
2023-05-04 12:01:25 +02:00
f9a4d6134c Segmentation: setup for simple demo test case works
due to having extracted the Algo implementation as template,
we can now instantiate it for isolated tests with simple integer intervals
2023-05-04 02:07:38 +02:00
00ca84a2aa test-helper for comparison with expected (string) result
...this is something I should have done since YEARS, really...

Whenever working with symbolically represented data, tests
typically involve checking *hundreds* of expected results,
and thus it can be really hard to find out where the
failure actually happens; it is better for readability
to have the expected result string immediately in the
test code; now this expected result can be marked
with a user-defined literal, and then on mismatch
the expected and the real value will be printed.
2023-05-04 00:48:29 +02:00
476c0f6493 Segmentation: build test-setup for Split-Splice-Algo
use simple intervals over integer numbers as test setup
- detect possible memory leaks
- detect corrupted Segmentation sequences
2023-05-03 15:27:46 +02:00
b582c35c9f Segmentation: structure analysis for splitSplice operation
There are 12 distinct cases regarding the orientation of two intervals;
The Segmentation::splitSplice() operation shall insert a new Segment
and adjust / truncate / expand / split / delete existing segments
such as to retain the *Invariant* (seamless segmentation covering
the complete time axis)
2023-05-02 04:29:34 +02:00
a807705185 Segmentation: draft simple mock-based setup for tests
- how to pass-in a specification given as GenNode
- now this might be translated into a MockJobTicket allocated in the MockSegmentation

Unimplemented: actually build the Segment with suitable start/end time
2023-05-01 17:02:11 +02:00
56405b2e2d Job-Planning: simulate backing by specific JobTicket
right now we're lacking a complete working implementation of render node invocation,
and thus the Dispatcher implementation can only be verified with the help
of mocked jobs. However, at least a preliminary implementation of tagging the
invocation instance is available, and thus we're able to verify that
a given job instance indeed belongs to and is "backed" by a specific JobTicket.

This is prerequisite for building up a (likewise mocked) Fixture datastructure,
and this in turn was meant to form the basis for attacking an actual Scheduler
implementation, followed by a real render node invocation.
2023-05-01 14:07:21 +02:00
f6fbc15e5f Job-Planning: provide stub implementation for NOP job (see #1296)
- can now create a Job from JobTicket::NIL
- on invocation this Job will to nothing

Only when the first real output backend is implemented,
we can decide if this simplistic implementation is enough,
or if an empty output must be explicitly generated...
2023-05-01 01:48:36 +02:00
fef0c05b64 Job-Planning: base implementation of job instance creation
* using a simplified preliminary implementation of hash chaining (see #1293)
 * simplistic implementation of hashing for time values (half-rotation)
 * for now just hashing the time into the upper part of the LUID

Maybe we can even live with that implementation for some time,
depending on how important uniform distribution of hash values is
for proper usage of the frame cache.

Needless to say, various further fine points need more consideration,
especially questions of portability (32bit anyone?). Moreover, since
frame times are typically quantised, the search space for the hashed
time values is drastically reduced; conceivably we should rather
research and implement a good hash function for 128bit and then combine
all information into a single hash key....
2023-04-30 22:33:42 +02:00
8aa0c258ba Job-Planning: investigate invocation of jobs
...using the MockJobTicket setup as point of reference,
since the actual invocation of render nodes will only be drafted
later in this "Vertical Slice" integration effort...
2023-04-30 02:18:56 +02:00
685b5beba6 Segmentation: simple implementation of time-based access
- introduce a JobTicket::NOP (null-object pattern)
- assuming that the function splitSplice() will retain complete coverage allways

Remark:
`Fixture::getPlaylistForRender()` is a leftover from the very early implementation drafts.
This function was more or less based on the way Cinelerra works; it is clear by now
that Lumiera can not possibly work this way, given that we'll build a low-level model
and dispatch precompiled render jobs....
2023-04-27 22:30:49 +02:00
d73b316ead Segmentation: consider preliminary data structure
...and consider how that can be extended later into the full
structure, which has to support a transactional switch
2023-04-27 19:38:37 +02:00
d58174db4d Segmentation: reorganise namespaces
The Fixture and the low-level model backbone deserve a distinct namespace on their own.
Since it's built by the Builder from the Session contents, and also used by the frame dispatch,
we can expect dependence on some types from Steam-Layer, and thus this namespace
needs to reside in Steam-Layer rather, while the actual low-level Model
might become part of Vault-Layer, creating a hierarchy of data structures.

(Remark: likely also the session related namespaces will need a reorganisation)
2023-04-25 18:27:16 +02:00
90593776f6 Segmentation: a plan to bootstrap into the required structure
The idea is to escape a "design deadlock" by using a test-driven prototype
implementation of the data structure to back a further development
of the Dispatcher and Scheduler implementation, which then can be used
to gradually elaborate and switch over to an actual implementation
data structure
2023-04-25 13:40:20 +02:00
b93a9a7985 Job-Planning: elaborate mock setup for render job 2023-04-21 05:29:10 +02:00
305eb825af Job-Planning: first testcase - empty JobTicket
...requires a first attempt towards defining a `JobTiket`.
This turns out quite tricky, due to using those `LinkedElements`
(intrusive single linked list), which requires all added records
actually to live elsewhere. Since we want to use a custom allocator
later (the `AllocationCluster`), this boils down to allocating those
records only when about to construct the `JobTicket` itself.

What makes matters even worse: at the moment we use a separate spec
per Media channel (maybe these specs can be collapsed later non).
And thus we need to pass a collection -- or better an iterator
with raw specs, which in turn must reveal yet another nested
sequence for the prerequisite `JobTickets`.

Anyhow, now we're able at least to create an empty `JobTicket`,
backed by a dummy `JobFunctor`....
2023-04-20 23:55:02 +02:00
856d8a3b51 Library: allow to reverse intrusive single linked list
Looks like we'll actually retain and use this low-level solution
in cases where we just can not afford heap allocations but need
to keep polymorphic objects close to one another in memory.

Since single linked lists are filled by prepending, it is rather
common to need the reversed order of elements for traversal,
which can be achieved in linear time.

And while we're here, we can modernise the templated emplacement functions
2023-04-20 18:53:17 +02:00
d341f003ca Job-Planning: attempt to stake claims
desperately trying to move forward and define a minimal first test case...
2023-04-18 20:02:36 +02:00
1dd1ec0e79 Job-Planning: decision how to rework bottom-up and test driven
- build the reworked Job-planning pipeline more or less from scratch
- back that with mocked `Dispatcher` and `JobTicket`
- then transfer this into a `RenderDrive`, which can be tested as well
- could continue then to a `CalcStream` integration test....
2023-04-17 17:10:53 +02:00
bcd2b3d632 PlaybackVerticalSlice: design analysis for Frame Dispatcher and Scheduler
- decision: the Monad-style iteration framework will be abandoned
- the job-planning will be recast in terms of the iter-tree-explorer
- job-planning and frame dispatch will be disentangled
- the Scheduler will deliberately offer a high-level interface
- on this high-level, Scheduler will support dependency management
- the low-level implementation of the Scheduler will be based on Activity verbs
2023-04-14 04:43:39 +02:00
dfcb17b890 GUI: close out rework of top-level and timeline
This finishes a long lasting effort to rework the top-level of the Lumiera GTK UI,
to adapt to GTK-3 and the new asynchronous message based architecture.

Special credits and thanks to
 * Joel Holdsworth
 * Stefan Kangas

Without their relentless foundational work, the Lumiera UI could
never be where it is now. Even if some code was rewritten and several
parts of the old GTK-2 implementation are now obsolete, numerous ideas
solutions and inspirations were drawn from those early contributions
and live on as part of the reworked GUI.
2023-03-22 02:58:04 +01:00
52d3231226 Timeline: finish ZoomWindow implementation and boundrary tests 2022-12-18 03:47:40 +01:00
e436023ef9 Timeline: properly handling maximal zoom-in and alignment to µ-ticks 2022-12-17 17:47:10 +01:00
b1514f6632 Timeline: properly handling extreme scroll-steps 2022-12-17 01:15:34 +01:00
3893968502 Timeline: improve handling of window size changes at extreme positions
...again and again surprising how much inconsitencies can hide in just some lines of code...
2022-12-16 19:59:47 +01:00
77bb156615 Timeline: verify handling of extreme time offsets 2022-12-16 02:23:20 +01:00
5e595c57ca Timeline: automatically orient and shift into allowed time domain
Note: changing behaviour of TimeSpan to possibly flip start and end,
and also to use Offset as Offset and then re-orient,
since this seems the least surprising behaviour.

These changes carry over into changed default and limiting
on ZoomWindow constructor and various mutators, and most
notably shifting the time span always into allowed domain.
2022-12-14 03:00:07 +01:00
777024ee40 Timeline: resolve yet another insidious corner case at maximum zoom
...the implementation was way too naive; in some cases we could go
into an infinite loop. In the end, using Newton approximation was not
necessary (and thus there is no loop anymore), but it helped me get
at a much better solution with very small error margin on average case.

All these corner cases are obviously "academic" to some degree,
but it turns out there is no clear-cut point where you'd be able
just so set a limit and be sure that fractional integer arithmetic
works flawless in all cases.

Thus the choice is
 - give up (fractional) integers and work with floats and have to
   deal with error accumulation
 - or do something as chosen here, namely add a boundary zone, where
   fractional integer arithmetic can be kept under control, while admitting
   small errors, and in turn get the absolutely precise integers in all
   everyday standard cases
2022-12-13 01:21:18 +01:00
c31522c236 Timeline: define better internal zoom-out limit
The value used previously was too conservative, and prevented ZommWindow
from zooming out to the complete Time domain. This was due to missing the
Time::SCALE denominator, which increaded the limit by factor 1e6

In fact the code is able to handle even this extremely reduced limit,
but doing so seems over the top, since now detox() kicks in on several
calculations, leading to rather coarse grained errors.

Thus I decided to use a compromise: lower the limit only by factor 1000;
with typical screen pixel widths, we can reach the full time domain,
while most scaling and zoom calculations can be performed precisely,
without detox() kicking in. Obviously this change requires adjusting
a lot of the test case expectations, since we can now zoom out maximally.
2022-12-10 04:26:22 +01:00
40f003a962 Timeline: stress-test with excessive zoom-out reveals further weakness
As it turns out, the calculation path initially choosen for the mutateScale(Rat)
was needlessly indirect, and also duplicated several of the safeguards,
meanwhile implemented way better in conformWindowToMetric(Rat)

Thus, instead of relatively re-scaling the window, now we just
limit the given zoomFactor and pass it to conformWindowToMetric()
2022-12-09 23:13:27 +01:00
ce3713d872 Timeline: now able to increase to maximum pixel count
There is a built-in limitation, which now is even
lowered to 100000 pixels horizontally.

With the techniques introduced in this changeset, it seems possible
to support more -- yet this would be a case of unnecessary genricity;
handling such large numbers will drive more computations into the
danger zone, and doing so incurs cost in terms of testing and debugging.

Placing that into context, contemporary displays are not even 4K on
average, and it does not look likely even for cinema display to go
way beyond 8k -- so yes, I want display hardware with 100000 pixels!!


The key takeaway of this changeset:
 - can calculate px = trunc(zoomFactor * duration) step wise,
   even when the direct calculation would lead to wrap-around
 - can safely adjust and fix the zoomFactor using Newton approximation
2022-12-09 19:37:35 +01:00
068549dace Timeline: now able to handle maximal zoom-out
...even zooming out to span the complete time domain (~19000 years).
But only under the condition that the display window is sufficiently
large in terms of pixels, so we can handle the computation without
glitches.

This should not be a relevant limitation in practice, since a window
size of some 100 pixels is enough to handle Duration::MAX. Needless to add
that it's hard to imagine a media timeline of such tremendous size...
building on these Library changes, plus the safe-add function
developed some days ago, it is now possible to mark a large displacement
as `time::Offset`, and apply this to yield any valid time position,
even extreme negative values
2022-12-08 18:06:37 +01:00
006758f349 Library/Timeline: now able to scroll to extreme positions (closes #1263)
...building on these Library changes, plus the safe-add function
developed some days ago, it is now possible to mark a large displacement
as `time::Offset`, and apply this to yield any valid time position,
even extreme negative values
2022-12-05 03:34:04 +01:00
13adc56f34 Library: rectify confusingly named function on the Grid API
The APIs for time quantisation were drafted in an early stage of the project
and then never followed-up. Especially Grid::gridAlign has no
real-world usage yet, and is only massaged in some tests.

When looking at QuantiserBasics_test, I was puzzled and led astray,
since this function suggests to materialise a continuous time into
a quantised time -- which it doesn't (there is another dedicated
function Quantiser::materialise() to that end); so, without engaging
into the discussion if this function is of any use, I'll hereby
choose a name better reflecting what it does.
2022-12-05 01:05:23 +01:00
50c602ec3f Library: rectify clipping of time::Duration (see #1263)
This is a deep refactoring to allow to represent the distance
between all valid time points as a time::Offset or time::Duration.

By design this is possible, since Time::MAX was defined as 1/30 of
the maximum value technically representable as int64_t. However,
introducing a different limiter for offsets and durations turns
out difficult, due to the inconsistencies in the exiting hierarchy
of temporal entities. Which in turn seems to stem from the unfortunate
decision to make time entities immutable, see #1261

Since the limiter is hard wired into the `time::TimeValue` constructor,
we are forced to create a "backdoor" of sorts, to pass up values
with different limiting from child classes. This would not be so
much of a problem if calculations weren't forced to go through `TimeVar`,
which does not distinguish between time points and time durations.

This solution rearranges all checks to be performed now by time::Offset,
while time::Duration will only take the absolute value at construction,
based on the fact that there is no valid construction path to yield
a duration which does not go through an offset first.

Later, when we're ready to sort out the implementation base of time values
(see #1258), this design issue should be revisited
- either we'll allow derived classes explicitly to invoke the limiter functions
- or we may be able to have an automatic conversion path from clearly
  marked base implementation types, in which case we wouldn't use the
  buildRaw_() and _raw() "backdoor" functions any more...
2022-12-05 00:58:32 +01:00
4d79bdce5f Timeline: sophisticated helper function to resolve problems with numeric precision
While the calculation was already basically under control, I just was not content
with the achieved numeric precision -- and the fact that the test case in fact
misses the bar, making it difficult do demonstrate that the calculation
is not derailed. I just had the gut feeling that it must be somehow possible
to achieve an absolute error level, not just a relative error level of 1e-6

Thus I reworked this part into a generic helper function, see #1262

The end result is:
 * partial failure. we can only ''guarantee'' the relative error margin of 1e-6
 * but in most cases not out to the most extreme numbers, the sophisticated
   solution achieves much better results way below the absolute error level of 1µ-Tick

Thus with using rational numbers, we have now a solution that is absolutely precise
in the regular case, and gradually introduces errors at the domain bound
but with an guaranteed relative error margin of 1e-6 (== Time::SCALE)
2022-12-02 22:23:14 +01:00
289f92da7e Timeline: safely calculate sum/difference of large fractional times
...in a similar vein as done for the product calculation.
In this case, we need to check the dimensions carefully and pick
the best calculation path, but as long as the overall result can
be represented, it should be possible to carry out the calculation
with fractional values, albeit introducing a small error.

As a follow-up, I have now also refactored the re-quantisation
functions, to be usable for general requantisation to another grid,
and I used these to replace the *naive* implementation of the
conversion FSecs -> µ-Grid, which caused a lot of integer-wrap-around

However, while the test now works basically without glitch or wrap,
the window position is still numerically of by 1e-6, which becomes
quite noticeably here due to the large overall span used for the test.
2022-12-01 23:23:50 +01:00
7007101357 Timeline: safely calculate the fraction of a very large timespan
...using a requantisation trick to cancel out some factors in the
product of two rational numbers, allowing to calculate the product
without actual multiplication of (dangerously large) numbers.

with these additional safeguards, the anchorWindowAtPosition()
succeeds without Integer-wrap, but the result is not fully correct
(some further calculation error hidden somewhere??)
2022-11-29 02:00:41 +01:00
b898f1514b Timeline: safeguard agains injecting a poisonous metric factor 2022-11-26 19:45:10 +01:00
90aba4df09 Timeline: demonstrate safeguards against reversed and toxic input 2022-11-18 02:55:28 +01:00
cfe3a6618f Lib: cover re-quantisation helper
...which I intend to use for sanitising poisonous rational numbers,
as prerequisite for handling divisor based time scales in the ZoomWindow
2022-11-15 02:13:57 +01:00
ce1220ee72 Lib: test coverage for rational-int corner cases and integer-log
- detailed documentation of known problematic behaviour
  when working with rational fractions
- demonstrate the heuristic predicate to detect dangerous numbers

- add extensive coverage and microbenchmarks for the integer-logarithm
  implementation, based on an example on Stackoverflow. Surprising result:
  The std::ilog(double) function is of comparable speed, at least for
  GCC-8 on Debian-Buster.
2022-11-14 05:20:37 +01:00
8ab0e1acb5 Lib: consider method to sanitise a poisonous rational
Especially rational numbers with large denominator can be insidious,
since they might cause numeric overflow on seemingly harmless operations,
like adding a small number.

A solution might be to *requantise* the number into a different,
way smaller denominator. Obviously this is a lossy operation;
yet a small and controlled numeric error is always better than
an uncontrolled numeric wrap-around.
2022-11-13 16:52:12 +01:00
d3fc6fd4de Timeline: Analysis of possibly toxic input values
- protection against negative numbers seems adequate
- a possible concern are handling of very large time spans
- definitively have to guard against "poisonous" fractions
  (e.g. n / INT_MAX)
2022-11-12 17:35:47 +01:00
cc16953fd8 Timeline: implement and verify ZoomWindow change notification 2022-11-11 16:30:27 +01:00
3f396ef3b2 Timeline: ZoomWindow now passes all tests according to spec
- some test definitions were simply numerically wrong
- changed some aspects of the specified behaviour, to be more consistent
  + scrolling is more liberal and always allows to extend canvas
  + setting window to a given duration expands around anchor point
2022-11-11 03:06:33 +01:00
93de063ae5 Timeline: fix next ZoomWindow_test failure 2022-11-10 21:00:00 +01:00
fa4fbe5225 Timeline: clarify or fix further ZoomWindow_test failures
- forgot the bias towards the next larger grid aligned size
- implement safeguard against empty window
2022-11-09 03:25:35 +01:00
a9df13f078 Timeline: define basic ZoomWindow setters on top of the normalisation
Rearrange the internal mutator functions to follow a common scheme,
so that most of the setters can be implemented by simple forwarding.
Move the change-listener triggering up into the actual setters.

This makes further test cases pass
 - verify_setup
 - verify_calibration
...implying that the pixel width is now retained
and basic behaviour matches expectations
2022-11-07 03:24:04 +01:00
292be817b7 Timeline: investigate problem with numeric overflow in fractional arithmetic
Extensive tests with corner cases soon highlighted this problem
inherent to integer calculations with fractional numbers: it is
possible to derail the calculation by numeric overflow with values
not excessively large, but using large numbers as denominator.
This problem is typically triggered by addition and subtraction,
where you'd naively not expect any problems.

Thus changed the approach in the normalisation function, relying
on an explicitly coded test rather, and performing the adjustment
only after conversion back to simple integral micro-tick scale.
2022-11-07 00:19:28 +01:00
5ed5905d7f Timeline: work out a scheme of Invariants and Normalisation for the ZoomWindow
Getting all those requirements translated into code turns out to be a challenging task;
and the usual ascent to handle such a situation is to define **Invariants**
in conjunction with a normalisation scheme; each manipulation will then be
translated into invocation of one of the three fundamental mutators,
and these in turn always lead into the common normalisation sequence.

__Invariants__
- oriented and non-empty windows
- never alter given pxWidth
- zoom metric factor < max zoom
- visibleWindow ⊂ Canvas
2022-11-06 02:46:11 +01:00
f2ef893adb Timeline: complete specification of ZoomWindow expected behaviour
Writing this specification unveiled a limitation of our internal
time base implementation, which is a 64bit microsecond grid.
As it turns out, any grid based time representation will always
be not precise enough to handle some relevant time specifications,
which are defined by a divisor. Most notably this affects the precise
display of frame duration in the GUI, and even more relevant,
the sample accurate editing of sound in the timeline.

Thus I decided to perform the internal computation in ZoomWindow
as rational numbers, based on boost::rational

Note: implementation stubbed only, test fails
2022-11-04 03:40:36 +01:00
f1b3f4e666 Timeline: reconsider time handling and Stage/Steam integration
This ZoomWindow_test highlights again the question about the intended usage
of the Lumiera time entities. In which way do we want to perform time calculations,
and under which circumstances is it adequate to perform arithmetic on
raw time values?

These questions made me think about rather far reaching concerns regarding
subsidiarity and implicit or explicit usage context. Basically I could
reconfirm the design choices taken some years ago -- while I must admit
that the project is headed towards a way larger scale and more loose
coupling of the parts, than I could imagine several years ago, at the
time when the design started...

As a side note: we can not avoid that some knowledge about the time implementation
leaks out from the support lib; time codes themselves are tightly coupled
to the usage scenario within the session and can not be used as means
for implementing UI concerns. And the more generic time frameworks,
like std::chrono (as much as it is desirable to have some integration here)
will not be of any help for most of our specific usage patterns.
The reason is, for film editing we do not have a global time scale,
rather the truth is when the film starts....
2022-10-30 23:12:34 +01:00
7145d0d9ce Timeline: ZoomWindow implementation draft
implement the first test case: nudge the zoom factor
⟹ scale factor doubled
⟹ visible window reduced to half size
⟹ visible window placed in the middle of the overall range
2022-10-30 01:31:25 +02:00
b3fe6e16c6 Timeline: requirement analysis to define the ZoomWindow (see #1196) 2022-10-29 01:59:42 +02:00
f393780845 Lib: fix a bug with diagnostic output
The header "format-cout.hpp" offers a convenience function
to print pretty much any object or data in human readable form.
However, the formatter for pointers used within this framework
switched std::cout into hexadecimal display of numbers and failed
to clean-up this state.

Since the "stickyness" of IOS stream manipulators is generally a problem,
we now provide a RAII helper to capture the previous stream state and
automatically restore it when leaving the scope.
2022-09-27 01:51:21 +02:00
ed7e3b4b32 ElementBox: extract builder qualifier support as library implementation
Complete the investigation and turn the solution into a generic
mix-in-template, which can be used in flexible ways to support
this qualifier notation.

Moreover, recapitulate requirements for the ElementBoxWidget
2022-08-28 23:36:27 +02:00
e15e893a01 Util: use case-insensitive matching for parsing bool values 2021-08-20 14:33:59 +02:00
4caf790339 Library: verify PlantingHandle's extended capabilities
- move construct into the buffer
- directly invoke the payload constructor through PlantingHandle
- reconsider type signature and size constraint
- extend the unit test
- document a corner case of c++ "perfect forwarding",
  which caused me some grief here
2021-05-07 22:50:13 +02:00
5a37bce855 Lib/Diff: extend PlantingHandle to allow for placment-new
...this extension was spurred by the previeous refactoring.
Since 'emplace' now clearly denotes an operation to move-embed an existing object,
we could as well offer a separate 'create' API, which would take forwarding
arguments as usual and just delegates to the placement-new operation 'create'
already available in the InPlaceBuffer class.

Such would be a convenience shortcut and is not strictly necessary,
since move-construction is typically optimised away; yet it would also
allow to support strictly non-copyable payload types.

This refactoring also highlights a fuzziness in the existing design,
where we just passed the interface type, while being sloppy about the
DEFAULT type. In fact this *is* relevant, since any kind of construction
might fail, necessitating to default-construct a placeholder, since
InPlaceBuffer was intended for zero-overhead usage and thus has in itself
no means to know about the state of its buffer's contents. Thus the
only sane contract is that there is always a valid object emplaced
into the buffer, which in turn forces us to provide a loophole for
class hierarchies with an abstract base class -- in such a case the
user has to provide a fallback type explicitly.
2021-05-02 19:40:11 +02:00
5aa41accfc Lib/Diff: prefer the name "emplace" over "build"
...for the operation on a PlantingHandle, which allows
to implant a sub type instance into the opaque buffer.

 * "create" should be used for a constructor invocation
 * "emplace" takes an existing object and move-constructs
2021-05-02 18:31:47 +02:00
73740a24e3 Clip-Drag: refactor into sub-component of TimelineLayout
this allows to avoid multi-step indirection
when translating mouse dragging pixel coordinates
into a time offset for the dragged clip widget.

Moreover this also improves the design,
since the handling of canvas metric is pretty much
a self contained, separate concern
2021-04-30 19:46:32 +02:00
db3a525d6e Clip-Drag: get the gesture logic to work
some bugfixes,
but also a notable change: detect the completion of the gesture
directly when the button is released; this is necessary, because
seemingly we do not get motion_events when no button is pressed,
at least not in this test setup based on a Gtk::Button widget.
2021-04-17 22:32:26 +02:00
b5cf8b2303 Clip-Drag: draft the dragging controller logic
direct implementation with state flags in-class
Intention is to refactor this into a state machine eventually
2021-04-17 19:43:29 +02:00
453ee08803 Clip: investigate how to enforce a fixed horizontal extension
GTK doesn't expose a first-class API for this,
since -- by design -- the extension of a widget is negotiated.
Thus I'm looking for some kind of workaround for our specific use-case,
where a clip widget must be rendered with a well defined horizontal size,
corresponding to its length.

Thus far, we're only able to increase the size of the Button widget
used as placeholder, but we can not forcibly shrink that button,
probably because the embedded Gtk::Lable requires additional extension.
2021-02-05 00:21:08 +01:00
2e4cd56f4f Relative-Hook: rectify the design
Partially as a leftover from the way more ambitious initial design,
we ended up with CanvasHook as an elaboration/specialisation of the
ViewHook abstraction. However, as it stands, this design is tilted,
since CanvasHook is not just an elaboration, but rather a variation
of the same basic idea.

And this is now more like a building pattern and less of a generic
framework, it seems adequate to separate these two variations completely,
even if this incurs a small amount of code duplication.


Actually this refactoring is necessary to resolve a bug, where
we ended up with the same Clip widgets attached two times to the
same Canvas control, one time through the ViewHook baseclass,
and a second time by the ctor of the "derived" CanvasHook
2021-01-30 13:29:50 +01:00
acb674a9d2 Project: update and clean-up Doxygen configuration
...in an attempt to clarify why numerous cross links are not generated.
In the end, this attempt was not very successful, yet I could find some breadcrumbs...

- file comments generally seem to have a problem with auto link generation;
  only fully qualified names seem to work reliably

- cross links to entities within a namespace do not work,
  if the corresponding namespace is not documented in Doxygen

- documentation for entities within anonymous namespaces
  must be explicitly enabled. Of course this makes only sense
  for detailed documentation (but we do generate detailed
  documentation here, including implementation notes)

- and the notorious problem: each file needs a valid @file comment

- the hierarchy of Markdown headings must be consistent within each
  documentation section. This entails also to individual documented
  entities. Basically, there must be a level-one heading (prefix "#"),
  otherwise all headings will just disappear...

- sometimes the doc/devel/doxygen-warnings.txt gives further clues
2021-01-24 19:35:45 +01:00
06dbb9fad5 DiffFramework: simplify existing bindings
...by relying on the newly implemented automatic standard binding
Looks like a significant improvement for me, now the actual bindings
only details aspects, which are related to the target, and no longer
such technicalitis like how to place a Child-Mutator into a buffer handle
2021-01-23 12:55:10 +01:00
05b5ee9a7e Diff-Framework: investigate simplification for the most common case
After this long break during the "Covid Year 2020",
I pick this clean-up task as a means to fresh up my knowledge about the code base

The point to note is, when looking at all the existing diff bindings,
seemingly there is a lot of redundancy on some technical details,
which do not cary much meaining or relevance at the usage site:

- the most prominent case is binding to a collection of DiffMutables hold by smart-ptr
- all these objects expose an object identity (getID() function), which can be used as »Matcher«
- and all these objects can just delegate to the child's buildMutator() function
  for entering a recursive mutation.
2021-01-22 12:38:45 +01:00
657b94a4e3 ++ a strange year passed by ++
read the code, documentation and mindmap to find out
at what point I was when this story unfolded
2021-01-20 08:05:30 +01:00
e33eae729b Relative-Hook: complete refactoring down to tracks and clips (see #1213)
...and the result was very much worth the effort,
leading to more focused and cleaner code.

 - all the concerns of moving widgets and translating coordinates
   are now confined to the second abstraction layer (CanvasHook)

 - while the ViewHook now deals exclusively with attachment, detachment
   and reordering of attachment sequence
2020-03-23 04:16:10 +01:00
f956f27ff4 Relative-Hook: build CanvasHook abstraction based on ViewHook
this refactoring was expedient, as the code becomes
way more legible within each of the two levels of abstraction
2020-03-23 02:02:06 +01:00
dd016667ad Diff-Listener: add a variant to trigger also on value assignment (see #1206)
As it turned out, it is rather easy to extend the existing listener
for structural changes to detect also value assignments. Actually
it seems we'd need both flavours, so be it.
2020-03-15 23:11:14 +01:00
0f6f09180e Lib: simplified optional access to nested record attributes
Yeah, C++17, finally!

...not totally sure if we want to go that route.
However, the noise reduction in terms of code size at call site looks compelling
2020-03-14 23:52:04 +01:00
c7d157e295 Library: integrate generic min/max function
...built while investigating type deduction problems on PtrDerefIter
...also allow PtrDerefIter to work with std::unique_ptr
2020-03-08 02:05:39 +01:00
0837498cc0 Relative-Hook: proof-of-concept based on ViewHook (see #1207)
this draft commit reshifts the (meanwhile broken) test code from:
03c358fe86

Now the marker Buttons are injected again, but without any detailed
positioning code at call site. This demonstrates the viability of the
Structure-Change / ViewHook refactoring.

To make this change viable, it was necessary to remove the ViewHooked<>
marker template from the rehook() callback. As it turns out, this was
added rather for logical reasons, and is in fact not necessary in
any of the existing ViewHook implementations (and I don't expect any
other implementations to come)

BUT the actual positioning coordinates are still wrong (which seems
to re related to other conceptual problems in coordinate offset handling)
2020-02-27 21:03:46 +01:00
b2b5cf0f6d MERGE: upgrade to Debian/Buster and to C++17 2020-02-22 02:16:25 +01:00
421a2ed49a C++17: some related clean-up 2020-02-21 23:55:09 +01:00
00c9ecb659 C++17: fix detector for function signatures
failure was likewise caused by `noexcept` being part of the signature type now
2020-02-21 20:16:59 +01:00
8c12e88fd3 C++17: fix detector for STL container iterability
the reason for the failure, as it turned out,
is that 'noexcept' is part of the function signature since C++17

And, since typically a STL container has const and non-const variants
of the begin() and end() function, the match to a member function pointer
became ambuguous, when probing with a signature without 'noexcept'

However, we deliberately want to support "any STL container like" types,
and this IMHO should include types with a possibly throwing iterator.
The rationale is, sometimes we want to expose some element *generator*
behind a container-like interface.

At this point I did an investigation if we can emulate something
in the way of a Concept -- i.e. rather than checking for the presence
of some functions on the interface, better try to cover the necessary
behaviour, like in a type class.

Unfortunately, while doable, this turns out to become quite technical;
and this highlights why the C++20 concepts are such an important addition
to the language.

So for the time being, we'll amend the existing solution
and look ahead to C++20
2020-02-21 18:57:49 +01:00
577592c66e C++17: isolate problematic code segments (see Ticket #1138)
as it turns out, "almost" the whole codebase compiles in C++17 mode.

with the exception of two metaprogramming-related problems:

 - our "duck detector" for STL containers does not trigger anymore
 - the Metafunction to dissect Function sigantures (meta::_Fun) flounders
2020-02-18 04:16:03 +01:00
3cfe5a13b1 fix failing test - boost::format is getting better
"%broken" is not broken anymore, but renders a boolean,
and we configured the formatter not to complain on missing values.

Fortunately "%madness" is still broken ;-)
2020-02-17 03:32:43 +01:00
38837da65e Timehandling: choose safer representation for fractional seconds (closes #939)
When drafting the time handling framework some years ago,
I foresaw the possible danger of mixing up numbers relating
to fractional seconds, with other plain numbers intended as
frame counts or as micro ticks. Thus I deliberately picked
an incompatible integer type for FSecs = boost::rational<long>

However, using long is problematic in itself, since its actual
bit length is not fixed, and especially on 32bit platforms long
is quite surprisingly defined to be the same as int.

However, meanwhile, using the new C++ features, I have blocked
pretty much any possible implicit conversion path, requiring
explicit conversions in the relevant ctor invocations. So,
after weighting in the alternatives, FSecs is now defined
as boost::rational<int64_t>.
2020-02-17 03:13:36 +01:00
cef7917d8e Diff-Listener: finished and unit test pass (closes: #1206) 2019-12-15 21:40:09 +01:00
d8b20ae497 Diff-Listener: fill in implementation
...basically just need to intercept three TreeMutator-operations
2019-12-15 04:04:25 +01:00
a33e236630 Diff-Listener: define API 2019-12-14 23:35:16 +01:00
806d569e06 Diff-Framework: resolve lurking problems with specific STL containers
basically the solution was a bit too naive and assumed everything is similar to a vector.
It is not, and this leads to some insidious problems with std::map, which hereby
are resolved by introducing ContainerTraits
2019-12-14 01:29:21 +01:00
8a5f1bc8d7 Diff-Listener: add a similar simplistic demo for opaque binding
based on a TreeMutator binding to a STL vector

...because this is probably the most frequently used case
2019-12-13 01:05:04 +01:00
3321e5bc6b Diff-Listener: need a really basic test
All of the existing "simple" tests for the »Diff Framework« are way to much low-level;
they might indeed be elementary, but not introductory and simple to grasp.
We need a very simplistic example to show off the idea of mutation by diff,
and this simple example can then be used to build further usage test cases.

My actual goal for #1206 to have such a very basic usage demonstration and then
to attach a listener to this setup, and verify it is actually triggered.

PS: the name "GenNodeBasic_test" is somewhat pathetic, this test covers a lot
of ground and is anything but "basic". GenNode in fact became a widely used
fundamental data structure within Lumiera, and -- admittedly -- the existing
implementation might be somewhat simplistic, while the whole concept as such
is demanding, and we should accept that as the state of affairs
2019-12-12 23:41:26 +01:00
c86f914915 Structure-Change: re-order entity naming
ViewHookable -> ViewHook
ViewHook -> ViewHooked
2019-12-12 17:02:24 +01:00
c501a38590 Structure-Change: fix test after refactoring / add lifecycle warning
now the lifecycle of widget and hook are tightly interwoven.
Indeed the test uncovered a situation where a call into the
already destroyed Canvas might halt the application.
2019-12-09 01:24:51 +01:00
0a20d18242 Structure-Change: implement the changed API and memory layout
NOTE: 2 test failures
2019-12-08 23:57:43 +01:00
99e367f33b Structure-Change: draft other API for hooking up widgets
...basically it occurred to me that in practice we will never have to deal
with isolated ViewHooks, rather with widgets-combinded-with-a-hook.
So the idea is to combine both into a template ViewHooked<W>
2019-12-08 21:09:25 +01:00
ffcac2ea1e Structure-Change: implement a simplistic implementation of re-ordering
...verified by the rather conceptual unit test
2019-12-06 23:19:09 +01:00
305ff8e6cc Structure-Change: draft API for re-ordering attached widgets
basically this attempts to work around an "impedance mismatch" caused by relying on Lumiera's Diff framework.
Applying a diff might alter the structural order of components, without those componets
being aware of the change. If especially those components are attached into some
UI layout, or otherwise delegate to display widgets, we need a dedicated mechanism
to reestablish those display elements in proper order after applying the change.

The typical examples is a sequence of sub-Tracks, which might have been reordert due
to applying rules down in the Steam Layer. The resulting diff will propagate the
new order of sub-Tracks up into the UI, yet now all of the elaborate layout and
space allocation done in the presentation code needs to be adjusted or even
recomputed to accomodate the change.
2019-12-06 21:53:43 +01:00
37d2e52c1e ClipDisplay: also verify invocation of widget relocation via ViewHook
...obviously this is just a dummy implementation and serves only to verify the design
2019-11-08 21:37:09 +01:00
bdf3351f55 ClipDisplay: basic implementation of ViewHook helper 2019-11-08 20:49:37 +01:00
f9d8f6eb55 ClipDisplay: draft desired properties of the ViewHook helper
...which serves to solve the problem with Canvas access.
Basically we do not want each and every Clip widget to be aware of the concrete canvas implementation widget;
and in addition, automated removal of widgets from the Canvas seems desirable
2019-09-30 02:49:02 +02:00
ec50407167 Timeline: start implementing some bits of the drawing code
Use a "catchy" style definition with lime background to make the drawing visible
2019-07-14 17:53:21 +02:00
6b4bf0a6ea Library: allow to check if Advice was explicitly given
For context: The »Advice System« was coined a long time ago, in 2010,
based on the vague impression that it might be useful for that kind of application
we are about to build here. And, as can be expected, none of the usage situations
envisioned at that time was brought to bear. Non the less, the facility came in
handy at times, precisely because it is cross-cutting and allows to pass
information without imposing any systematic relationship between the
communication partners.

And now we've got again such a situation.
The global style manager in the UI has to build a virtual CSS path,
which is needed by drawing code somewhere deep down, and we absolutely
do not want to pass a reference to the style manager over 20 recursive calls.

The alternatives would be
 (1) to turn the style manager into a public service
 (2) to have a static access function somewhere
 (3) to use a global variable.
For rationale, (1) would be overblown, because we do not actually request
a service to do work for us, rather we need some global piece of information.
(2) would be equivalent to (1), just more confusing. And (3) is basically
what the Advice system does, with the added benefit of a clear-cut service
access point and a well defined lifecycle.

This changeset adds the ability to check if actual Advice has been published,
which allows us to invoke the (possibly expensive) GTK path building and
style context building code only once.
2019-07-13 17:00:23 +02:00
8ffab2f002 Dependencies: get rid of boost-regexp (see #995)
Mostly, std::regexp can be used as a drop-in replacement.

Note: unfortunately ECMA regexps do not support lookbehind assertions.
This lookbehind is necesary here because we want to allow parsing values
from strings with additional content, which means we need explicitly to
exclude mismatches due to invalid syntax.

We can work around that issue like "either line start, or *not* one of these characters.


Alternatively we could consider to make the match more rigid,
i.e we would require the string to conain *only* the timecode spec to be parsed.
2019-06-24 02:41:02 +02:00
ab90d9c71d Functions-Commands: discard the ability to compare functors for equivalence (closes #294)
evil hack R.I.P
2019-06-23 19:45:30 +02:00
94edb5de86 BufferMetadata: likewise abandon use of function comparison for buffer handlers
The existing implementation created a Buffer-Type based on various traits,
including the constructor and destructor functions for the buffer content.
However, this necessitates calculating the hash_value of a std::function,
which (see #294) is generally not possible to implement.

So with this changeset we now store an additional identity hash value
right into the TypeHandler, based on the target type placed into the buffer
2019-06-23 18:57:21 +02:00
d57770ca89 Commands: disable equivalence-test on command equality
This was prompted by a test failing under Boost-1.65 (--> see #294)
When reviewed now, the whole idea of testing Steam-Layer Commands for
equivalence feels a bit sketchy.

Just the comparison for the command ''identity'' alone seems sufficient,
i.e. the test if a command-ID is associated with the same backend-handle
and thus the same functor binding.
2019-06-23 17:35:21 +02:00
f6e5886348 Library: complete test coverage of VerbPack 2019-06-11 02:40:20 +02:00
3d5a67ed14 Library: finish and clean-up the solution for VerbPack dispatch 2019-06-10 16:08:50 +02:00
8f43c2591e Library: investigate malfunction in metaprogramming
the template lib::PolymorphicValue seemingly picked the wrong
implementation strategy for "virtual copy support": In fact it is possible
to use the optimal strategy here, since our interface inherits from CloneSupport,
yet the metaprogramming logic picked the mix-in-adapter (which requires one additional "slot"
of storage plus a dynamic_cast at runtime).

The reason for this malfunction was the fact that we used META_DETECT_FUNCTION
to detect the presence of a clone-support-function. This is not correct, since
it can only detect a function in the *same* class, not an inherited function.

Thus, switching to META_DETECT_FUNCTION_NAME solves this problem
Well, this solution has some downsides, but since I intend to rewrite the
whole virtual copy support (#1197) anyway, I'll deem this acceptable for now


TODO / WIP: still some diagnostics code to clean up, plus a better solution for the EmptyBase
2019-05-10 02:19:01 +02:00
23c9da7c62 Library: solve the dilemma by inheriting from VerbToken
...which, in the end, can even be considered the more logical design choice,
since the "verb visitor" is a more elaborated and sophisiticated Verb-Token,
adding the special twist of embedded storage for variable function arguments
2019-05-09 23:40:47 +02:00
a530665769 Library: fix some reference passing errors
...but bad news on the main issue:
the workaround consumes the tuple and thus is not tenable!

And what is even worse: the textbook implementation of std::apply is
equivalent to our workaround and also consumes the argument tuple
2019-04-22 16:54:22 +02:00
e28635a11a Library: investigate copy behaviour in forwarding calls 2019-04-21 03:52:34 +02:00
5191073558 Library: continue Investigation with workaround, inconclusive yet
A simple yet weird workaround (and basically equivalent to our helper function)
is to wrap the argument tuple itself into std::forward<Args> -- which has the
effect of exposing RValue references to the forwarding function, thus silencing
the compiler.

I am not happy with this result, since it contradicts the notion of perfect forwarding.

As an asside, the ressearch has sorted out some secondary suspicions..
- it is *not* the Varargs argument pack as such
- it is *not* the VerbToken type as such

The problem clearly is related to exposing tuple elements to a forwarding function.
2019-04-20 17:27:47 +02:00
6fbd1021ba Library: first attempt to get the flexible VerbToken to work
...still not decided yet if this whole apporach is sound...
2019-04-17 18:32:21 +02:00
9b5fdd39b8 Library: draft for a visitor-like VerbToken
this is a generalisation of what we use in the diff framework;
typically you'd package the VerbToken into some kind of container,
together with the concrete invocation argument.

However, the specific twist here is that we want *variable arguments*,
depending on the actual operation called on the interpreter interface.
2019-04-16 18:21:51 +02:00
ec9b2388da Timeline: consider how to integrate the drawing code
...which leads to a specific twist here; while in the simple version
we still could hope to get away with a simple uniform uint argument,
the situation has changed altogether now. The canvas has turned into
some generic component, since it is instantiated two times, onece for
the time ruler and once for the actual body content. Thus all of the
specifics of the drawing code need to be pushed into a new, dedicated
renderer component. And this more or less forces us to pass all the
actual presentation variations through the invocation arguments of
the visitor.

So we're now off again for a digression, we need a more generalised visitor
2019-04-14 15:38:57 +02:00
116600b20a Timeline: draft a concept to attack the custom layout
the core question is: how to translate time into pixel coordinates
2018-12-10 00:12:52 +01:00
7b7ec310b3 Dispatcher: rename in accordance to the layer
so now we've got a "SteamDispatcher" ... cute ;-)
2018-12-10 00:12:52 +01:00
2ea89fcb54 Dispatcher: rework loop control logic
- we got occasional hangups when waiting for disabled state
- the builder was not triggered properly, sometimes redundant, sometimes without timeout

As it turned out, the loop control logic is more like a state machine,
and the state variables need to be separated from the external influenced variables.

As a consequence, the inChange_ variable was not calculated properly when disabled in a race,
and then the loop went into infinite wait state, without propagating this to
the externally waiting client, which caused the deadlock
2018-12-10 00:12:52 +01:00
48a829d544 Library: clarify usage of the basic time scale
effectively we rely in the micro tick timescale promoted by libGAVL,
but it seems indicated to introduce our own constant definition.
And also clarify some comments and tests.

(this changeset does not change any values or functionality)
2018-12-10 00:12:52 +01:00
b68d0f24cb Library: settle long standing confusion regarding time border conditions
basically we can pick just any convention here, and so we should pick the convention in a way
that makes most sense informally, for a *human reader*. But what we previously did, was to pick
the condition such as to make it simple in some situations for the programmer....

With the predictable result: even with the disappointingly small number of usages we have up to now,
we got that condition backwards several times.

OK, so from now on!!!

Time::NEVER == Time::MAX, because "never" is as far as possible into the future
2018-12-10 00:12:43 +01:00
d3d7ea35ad Global-Layer-Renaming: fix remaining textual usages and IDs in the code
- most notably the NOBUG logging flags have been renamed now
 - but for the configuration, I'll stick to "GUI" for now,
   since "Stage" would be bewildering for an occasional user
 - in a similar vein, most documentation continues to refer to the GUI
2018-12-10 00:09:56 +01:00
480104b945 Global-Layer-Renaming: adapt the build system to the new layer names
...with one exception: I'll retain the name "gui" for the final product to be built.
2018-11-16 15:25:28 +01:00
02c5809707 Global-Layer-Renaming: adjust namespace qualification 2018-11-15 23:59:23 +01:00
555ca0bff9 Global-Layer-Renaming: rename namespaces 2018-11-15 23:55:13 +01:00
72b15b8e45 Global-Layer-Renaming: transform header include guards
btw... we could change to #pragma once
2018-11-15 23:52:02 +01:00
2d5ebcd5fa Global-Layer-Renaming: adjust header includes 2018-11-15 23:42:43 +01:00
6261779531 Global-Layer-Renaming: rearrange directories
backend -> vault
proc -> steam
gui -> stage
2018-11-15 23:28:03 +01:00
9e951e1eeb Global-Layer-Renaming: adapt lots of documentation 2018-11-15 21:13:52 +01:00
8432420726 Library: fix unwanted implicit conversion
...it should have been explicit from start, since there is no point
in converting an EntryID into a plain flat string without further notice

this became evident, when the compiler picked the string overload on

MakeRec().genNode(specialID)

...which is in compliance to the rules, since string is a direct match,
while BareEntryID would be an (slicing) upcast. However, obviously we
want the BareEntryID here, and not an implicit string conversion,
thereby discarding the special hash value hidden within the ID
2018-11-09 23:09:28 +01:00
1bbe903202 GenNode: revert -- better not handle this problem on ETD level
...rather extend the "object builder" DSL notation to allow passing in a given EntryID literally.
Rationale is, we should handle the problem of unique IDs on the level of the domain model.
If we attempt to "fix" this within GenNode, the price would be to make the ETD creation stateful
2018-11-09 22:50:48 +01:00
572bd38fec DummySessionConnection: produce a simple population diff message
seems to work surprisingly well...
the diff application poceeds in the GUI up to the point
where the TrackPresenter need to be inserted into a two-fold display context
2018-10-15 02:54:42 +02:00
a77ecb6d5d change util::sanitise to filter out '
Only reatain chars, numbers and -_.+$()@
Allowing the appostroph seems entirely random and unjustified here
2018-10-12 23:45:49 +02:00
fa6ba76f85 investigate insidious ill-guided conversion
As it turns out, using the functional-notation form conversion
with *parentheses* will fall back on a C-style (wild, re-interpret) cast
when the target type is *not* a class. As in the case in question here, where
it is a const& to a class. To the contrary, using *curly braces* will always
attempt to go through a constructor, and thus fail as expected, when there is
no conversion path available.

I wasn't aware of that pitfall. I noticed it since the recently introduced
class TimelineGui lacked a conversion operator to BareEntryID const& and just
happily used the TimelineGui object itself and did a reinterpret_cast into BareEntryID
2018-10-12 23:42:56 +02:00
e81b0592d3 TreeMutator: combine no-op layer with selective other diff binding
...and complete unit test coverage.
This is complex stuff and we'd better be careful it actually works
2018-10-12 02:05:11 +02:00
fb93e349da TreeMutator: conjure up a black hole mutator
...which is a somewhat involved version of /dev/null
2018-10-11 23:56:33 +02:00
9894542bf9 Introduce predefined constants for magic IDs in UI communication
...these magical strings are already spreading dangerously throughout the code base


PS: also fixup for c6b8811af0  (broken whitespace in test definition)
2018-10-08 05:00:06 +02:00
12344ae9d8 NotificationDisplay: add an Error-State and implement signal to trigger on change
this is more or less gratitious functionality for now,
yet I consider it a proof-of-concept
2018-10-05 15:59:21 +02:00
c6b8811af0 Library: utility to interpret a text as bool value (yes/no)
...also fixes the problem with the "expand" mark in DemoGuiRoundtrip
2018-10-03 04:43:16 +02:00
4e94dfd4d9 FailureHandling: improved ZombieCheck
now capturing the Zombie's ID

==> surprise, its ClassLock<gui::interact::LocationQuery>
2018-10-01 05:51:21 +02:00
5a7a5a5720 DOC: fix syntax of some doxygen links
seemingly we really need the \ref in the link target expression
2018-09-21 14:33:12 +02:00
121d78e13b EventLog: now able to write the condition to verify doRevealYourself (#1162)
this initially (on 1.9.18) triggered this extended digression;
The initial naive implementation (without backtracking) did not allow
to express such a simple thing like "function XXX" not invoked (again) after "function XXX"
2018-09-19 03:27:48 +02:00
03a1d58198 EventLog: verify and complete the TestEventLog_test
can now cover all the cases as initially intended,
including backtracking
2018-09-19 02:52:38 +02:00
1683439b32 ChainSearch: backtracking verified -- finished 2018-09-16 01:08:49 +02:00
84399aa407 ChainSearch: verify proper interplay of two dynamic search conditions 2018-09-16 01:08:49 +02:00
38a1aad897 ChainSearch: bugfixes on reworked construction
...seems basically sane now.
Just we still need to wrap it one more time into IterableDecorator;
which means the overall scheme how to build and package the whole pipeline
is not correct yet.

Maybe it is not possible to get it packaged all into one single class?
2018-09-16 01:08:48 +02:00
05e6e7f316 ChainSearch: remould construction to get the logic correct
on closer investigation it turned out that the logic of the
first design attempt was broken altogether. It did not properly
support backtracking (which was the reason to start this whole
exercise) and it caused dangling references within the lambda
closure once the produced iterator pipeline was moved out
into the target location.

Reasoning from first principles then indicated that the only sane
way to build such a search evaluation component is to use *two*
closely collaborating layers. The actual filter configuration
and evaluation logic can not reside and work from within the
expander. Rather, it must sit in a layer on top and work in
a conventional, imperative way (with a while loop).

Sometimes, functional programming is *not* the natural way
of doing things, and we should then stop attempting to force
matters against their nature.
2018-09-16 01:08:45 +02:00
767156e912 TreeExplorer: unit test coverage for injected custom layer 2018-09-16 01:07:23 +02:00
8aae789b82 ChainSearch: test case to scrutinise chained filter reconfiguration
...and TADAA ... there we get an insidious bug:

we capture *this by reference into the expansion functor,
and then we move *this away, out from the builder into the target....
2018-09-14 21:06:15 +02:00
29d2c151b3 ChainSearch: add builder function just to replace the filter
Up to now, we had a very simplistic configuration option just
to search for a match, and we had the complete full-blown reconfiguration
builder option, which accepts a functor to work on and reconfigure the
embedded Filter chain.

It occurred to me that in many cases you'd rather want some intermediary
level of flexibility: you want to replace the filter predicate entirely
by some explicitly given functor, yet you don't need the full ability
to re-shape the Filter chain as a whole. In fact the intended use case
for IterChainSearch (which is the EventLog I am about to augment with
backtracking capabilities) will only ever need that intermediate level.


Thus wer're adding this intermediary level of configurability now.

The only twist is that doing so requires us to pass an "arbitrary function like thing"
(captured by universal reference) through a "layer of lambdas". Which means,
we have to capture an "arbitrary thingie" by value.

Fortunately, as I just found out today, C++14 allows something which comes
close to that requirement: the value capture of a lambda is allowe to have
an intialiser. Which means, we can std::forward into the value captured
by the intermediary lambda. I just hope I never need to know or understand
the actual type this captured "value" takes on.... :-)
2018-09-14 21:06:15 +02:00
10f21f77f8 ChainSearch: resolve the problems and get basic functionality to work
with the augmented TreeExplorer, we're now able to get rid of the
spurious base layer, and we're able to discard the filter and
continue with the unfiltered sequence starting from current position.
2018-09-14 21:06:15 +02:00
df7a9492b7 TreeExplorer: helper function so support ChainSearch::clearFilter()
build a special feature into the Explorer component of TreeExplorer,
causing it to "lock into" the current child sequence and discard
all previous sequences from the stack of child explorations
2018-09-14 21:06:15 +02:00
7cdd680e78 TreeExplorer: clean-up after refactoring
So we have now a reworked version of the internals of TreeExplorer in place.
It should be easier to debug template instantation traces now, since most
of the redundancy on the type parameters could be remove. Moreover, existing
pipelines can now be re-assigned with similarily built pipelines in many cases,
since the concrete type of the functor is now erased.

The price tag for this refactoring is that we have now to perform a call
through a function pointer on each functor invocation (due to the type erasure).
And seemingly the bloat in the debugging information has been increased slightly
(this overhead is removed by stripping the binary)
2018-09-14 21:06:15 +02:00
36d79be8b2 TreeExplorer: refactor Filter in a similar way 2018-09-14 21:06:15 +02:00
1e657acbff TreeExplorer: refactor Transformer to employ the improved wrapping style
...step by step switch over to the new usage pattern.
Transformer should be the blueprint for all other functor usages.


The reworked solutions behaves as expected;
we see two functor invocations; the outer functor, which does
the argument adaptation, is allocated in heap memory
2018-09-14 21:06:15 +02:00
e3ca8548a4 TreeExplorer: allow for a disabled filter
...considered as one of the building blocks to resolve Problems in the Design of ChainSearch
2018-09-14 21:06:15 +02:00
34b78fc47e ChainSearch: identify some possible problems
- as implemented now, we will finally backtrack into the unfiltered base iterator
- it is not possible to implement a clearFilter() operation
2018-09-14 21:06:15 +02:00
d923138d1c ChainSearch: configure the core of the chained search mechanism
...based on a monadic tree expansion: we define a single step,
which takes the current filter configuration and builds the next
filter configuration, based on a stored chain of configuration functions

The actual exhausting depth-first results just by the greedy application pattern,
and uses the stack embedded in the "Explorer" layer of TreeExplorer
2018-09-14 21:06:14 +02:00
d398177a71 ChainSearch: now actually build the processing pipeline in the ctor
..this resolves the most challenging part of the construction work;
we use the static helper functions to infer a type and construct a suitable
processing pipeline and we invoke the same helper to initialise the base class
in the ctor.

Incidentally... we can now drop all the placeholder stubs,
since we now inherit the full iterator and child explorer API.
The test now starts actually to work... we get spam and sausage!

TODO: now actually fill in the expand functor such as to pick the
concrete filter step in the chain from a sequence of preconfigured
filter bindings
2018-09-14 21:06:14 +02:00
9b0937bc63 ChainSearch: move into namespace iter
...seems to be a not-so-commonly used helper
2018-09-14 21:06:14 +02:00
a52ed91de0 ChainSearch: draft a solution how to construct the Expand functor type
...now matters start to get really nasty,
since we have to pick up an infered type from a partially built pipeline
and use it to construct the signature for a functor to bind into the more elaborate complete pipeline
2018-09-14 21:06:14 +02:00
6834c26470 ChainSearch: draft a solution how to construct the pipeline builder base type
this is a tricky undertaking, since our treeExplore() helper constructs
a complex wrapped type, depending on the actual builder expressions used.

Solution is to use decltype on the result of a helper function,
and let the _DecoratorTraits from TreeExplorer do the necessary type adaptations
2018-09-14 21:06:14 +02:00
4988153e15 Library: prevent implicit bool conversion on iterator-like objects
...it should have been this way all the time.
Generic code might otherwise be ill guided to assume a conversion
from the Iterator to its value type, while in fact an explicit dereferentiation is necessary
2018-09-14 21:06:14 +02:00
433543a2c7 DOC: some doxygen fixes 2018-09-14 21:06:14 +02:00
ec8d0557e8 ChainSearch: draft interface and possible implementation approach
The intention is to augment the iterator based (linear) search
used in EventLog to allow for real backtracking, based on a evaluation tree.
This should be rather staight forward to implement, relying on the
exploreChildren() functionality of TreeExplorer. The trick is to package
the chained search step as a monadic flatMap operation
2018-09-14 21:06:14 +02:00
604ffbf73c TreeExplorer: fix a bug and finish the feature
we did an unnecessary copy of the argument, which was uncovered
by the test case manipulating the state core.


Whew.
Now we have a beautiful new overengineered solution
2018-09-14 21:06:14 +02:00
be7f47d5b7 TreeExplorer: rework the solution to allow for arbitrary functor types
outift the Filter base class with the most generic form of the Functor
wrapper, and rather wrap each functor argument individually. This allows
then to combine various kinds of functors
2018-09-14 21:06:14 +02:00
90c0f43cfd TreeExplorer: code all the combination cases
...this solution works, but has a shortcoming:
the type of the passed lambdas is effectively pinned to conform
with the signature of the first lambda used initially when building the filter.

Well, this is the standard use case, but it kind of turns all the
tricky warpping and re-binding into a nonsense excercise; in this form
the filter can only be used in the monadic case (value -> bool).

Especially this rules out all the advanced usages, where the filter
collaborates with the internals of the source.
2018-09-14 21:06:14 +02:00
e29d9ae19e TreeExplorer: better package this very specific code as subclass
while this is basically just code code cosmetics,
at least it marks this as a very distinct special case,
and keeps the API for the standard Filter layer clean.
2018-09-14 21:06:14 +02:00
8f70b4e902 TreeExplorer: prototype for the extracted boilerplate helper
a quite convoluted construct built from several nested generic lambdas.
When investigated in the debugger, the observed addresses and the
invoked code looks sane and as expected.
2018-09-14 21:06:14 +02:00
94da0f627f TreeExplorer: draft ability to remould the filter
The intention is to switch from the itertools-based filter
to the filter available in the TreeExplorer framework.
Thus "basically" we just need to copy the solution over,
since both are conceptually equivalent.

However...... :-(
The TreeExplorer framework is designed to be way more generic
and accepts basically everything as argument and tries to adapt apropriately.

This means we have to use a lot of intricate boilerplate code,
just to get the same effect that was possible in Itertools with
a simple and elegant in-place lambda assignment
2018-09-14 21:06:14 +02:00
757258fb3a TreeExplorer: fix bug in Filter layer
Fillter needs to be re-evaluated, when an downstream entity requests
expandChildren() onto an upstream source. And obviously the ordering
of the chained calls was wrong here.

As it turns out, I had discovered that necessity to re-evaluate with
the Transformer layer. There is a dedicated test case for that, but
I cut short on verifying the filter in that situation as well, so
that piece of broken copy-n-paste code went through undetected.

This is in fact a rather esoteric corner case, because it is only
triggered when the expandChildren() call is passed through the filter.
When otoh the filter sits /after/ the entity generating the expandChildren()
calls, everything works as intended. And the latter is the typical standard
usage situation of an recursive evalutation algorithm: the filter is here
used as final part to drive the evaluation ahead and pick the solutions.
2018-09-14 21:06:14 +02:00
3fc5a94b87 TreeExplorer: investigate the backtracking abilities
There is a bug or shortcoming in the existing ErrorLog matcher implementation.
It is not really difficult to fix, however doing so would require us to intersperse
yet another helper facility into the log matcher. And it occurred to me, that
this helper would effectively re-implement the stack based backtracking ability,
which is already present in TreeExplorer (and was created precisely to support
this kind of recursive evaluation strategies).

Thus I intend to switch the implementation of the EventLog matcher from the
old IterTool framework to the newer TreeExplorer framework. And this intention
made me re-read the code, fixing several comments and re-thinking the design
2018-09-14 21:06:14 +02:00
2520ee82d1 EventLog: investigate failed match in EventLog
seemingly my quick-n-dirty implementation was to naiive.
We need real backtracking, if we want to support switches
in the search direction (match("y").after("x").before("z")

Up to now, I have cheated myself around this obvious problem :-/
2018-09-14 21:06:13 +02:00
1ab42b298d UiElement: add unit test to cover the doRevealYourself functionality
...which is now kind-of specified and we're providing a default implementation,
so it should be documented in AbstractTangible_test
2018-09-14 21:06:13 +02:00
026049a13c UiElement: likewise integrate the Revealer functor (#1162) 2018-09-14 21:06:13 +02:00
3f327b335a UiElement: switch MockElement to rely on the new functor based default impl
...which is implicit verified through AbstractTangible_test::markState()
2018-09-14 21:06:13 +02:00
a74dc596ce WLink: finished incl. exception handling guarantees and documentation 2018-09-14 21:06:12 +02:00
ae26012bf5 WLink: implement copy operations
swap-based implementation
not sure if attachTo() should be noexcept
2018-09-14 21:06:12 +02:00
baa3d2bff0 WLink: define expected copy behaviour 2018-09-14 21:06:12 +02:00
a15951b036 WLink: implement connecting / reconnecting 2018-09-14 21:06:12 +02:00
c47e3d0210 WLink: draft basic behaviour 2018-09-14 21:06:12 +02:00
e829a74edf NotificationDisplay: draft idea of managed link-to-widget
a smart-reference based on sigc::trackable
2018-09-14 21:06:12 +02:00
36abe4567e NotificationDisplay: define the actual controller behaviour to be implemented
this is specification work; for now the stubs are marked UNIMPLEMENTED
2018-09-14 21:06:12 +02:00
53c47a6fcc Assets: verify creation of ErrorLog meta-Asset 2018-09-14 21:06:12 +02:00
f872e22216 Assets: draft how the global ErrorLog asset could be created 2018-09-14 21:06:12 +02:00
928b4372e0 Assets: investigating the unclear distinction between asset::Struct and asset::Meta (#1156)
including a kind-of Bugfix: the ctor of TimeGrid erroneously categorised it as asset::Kind STRUCT
2018-09-14 21:06:12 +02:00
3b8965c0b6 Heisenbug hunt.... Segfault related to regular expression (#1158)
not yet able to reproduce these seemingly random segfaults
2018-09-14 21:04:25 +02:00
c5bdb89b5b BusTerm_test: obvious performance improvement on RegExp search
Greedy wildcard match .+ is unnecessary, since in case of a positive match,
the next given expression always follows immediately. We just want to skip
over some "syntactic noise"

This change makes the matching time linear in the size of the log.

But unfortunately, I still occasionally see an Segmentation Fault.
It seems to arise when compiling the regular expresions

e.g. the following RegExps cashed (right in the middle of the test)

after.+?_ATTRIBS_.+?ins.+?53 of 57 ≺358.gen010≻.+?mut.+?53 of 57 ≺358.gen010≻.+?ins.+?borgID.+?358.+?emu.+?53 of 57 ≺358.gen010≻
after.+?_ATTRIBS_.+?ins.+?53 of 63 ≺178.gen028≻.+?mut.+?53 of 63 ≺178.gen028≻.+?ins.+?borgID.+?178.+?emu.+?53 of 63 ≺178.gen028≻
after.+?_ATTRIBS_.+?ins.+?53 of 59 ≺498.gen038≻.+?mut.+?53 of 59 ≺498.gen038≻.+?ins.+?borgID.+?498.+?emu.+?53 of 59 ≺498.gen038≻
after.+?_ATTRIBS_.+?ins.+?53 of 60 ≺223.gen003≻.+?mut.+?53 of 60 ≺223.gen003≻.+?ins.+?borgID.+?223.+?emu.+?53 of 60 ≺223.gen003≻
after.+?_ATTRIBS_.+?ins.+?53 of 78 ≺121.gen015≻.+?mut.+?53 of 78 ≺121.gen015≻.+?ins.+?borgID.+?121.+?emu.+?53 of 78 ≺121.gen015≻
2018-09-14 21:04:09 +02:00
8097485dbf ViewSpec: integrate the simple View access case (Unit test PASS)
This finishes the first round of design drafts in this area.
Right now it seems difficult to get any further, since most of
the actual view creation and management in the UI is not yet coded.
2018-06-15 18:02:08 +02:00
800fc5915a ViewSpec: recast the ElementAccess API to work around the design problem
...it is not really solved, rather postponed.
But who knows. Maybe it's already good enough...
2018-06-15 16:42:51 +02:00
f55a8f606b ...one month later: pick up after the LAC.18 Berlin
...happened to be completely absorbed by the preparations
for my workshop about Yoshimi and musical presets
2018-06-14 17:02:34 +02:00
f64e01a20c GCC-7: minor adjustments to make the testsuite PASS again
The boost::hash documentation does not mention a significant change in that area,
yet the frequent collisions on identifiers with number suffix do not occur anymore
in Boost 1.65
2018-04-29 03:15:57 +02:00
f06038828c GCC-7: integrate recent clean-up and refactoring work (lib::Depend)
# Conflicts:
#	src/lib/error-exception.cpp
#	src/lib/error.hpp
#	src/lib/opaque-holder.hpp
#	src/lib/wrapper.hpp
#	src/proc/mobject/session/sess-manager-impl.hpp
2018-04-27 02:23:20 +02:00
3296148dad pre-C++17: remove remaining old-style (dynamic) exception specifications 2018-04-26 12:07:08 +02:00
5f0af2495b Test-Fix: possible race in test setup
On rare occasions, the test thread itself consumes faster than the producer threads feed new test data.
Make sure the test does not hangin such a situation
2018-04-26 10:54:13 +02:00
d0538a55ff ViewSpec: implement the generic access function in ViewLocator
still missing: internal wiring from the allocation token(s) of the DSL
into the ElementAccess service designed last week.
2018-04-15 03:07:54 +02:00
ba3d9e57b5 ViewSpec: draft a way to code an integration test for ViewLocator (#1129)
The original goal for #1129 (ViewSpecDSL_test) is impossible to accomplish,
at least within our existing test framework. Thus I'll limit myself to coding
a clean-room integration test with purely synthetic DSL definitions and mock widgets
2018-04-15 01:39:46 +02:00
86b1aac721 ElementAccess: somewhat improve the mock implementation to cover the standard case
...still quite braindead, but well....
2018-04-14 03:58:02 +02:00
4205511405 ElementAccess: change the way of mock element creation
...still quite braindead, but allows at least to cover the standard case as well.

A better mock element access service would at least traverse a GenNode-Tree,
and thus emulate the behaviour of the real service; yet both seems way beyond
scope right now, and all I need is some basic coverage of the Interface
2018-04-14 03:14:19 +02:00
a565fc3321 ElementAccess: rearrange files according to namespace 2018-04-14 02:06:31 +02:00
4071a58454 ElementAccess: fix first unit test case
ouch, the typedef Base /is/ already a pointer...
2018-04-14 01:59:41 +02:00
4c273d902c ElementAccess: add very simplistic mock implementation 2018-04-14 01:37:56 +02:00
22f50b1b00 ElementAccess: streamline error cases
My understanding is that in the standard use case, we precisely know what to expect
and just go ahead and perform the conversion. Thus it is pointless to introduce
fine grained distinctions. When the access fails, this always indicates some broken
application logic, and just raises an error.
2018-04-13 03:29:08 +02:00
ac4f0bc6db ElementAccess: possibly working solution based on lib::variant
With this solution, somewhere deep down within the implementation
the knowledge about the actual result type would be encoded into
the embedded VTable within a lib::variant. At interface level,
ther will be a double dispatch based on that result type
and the desired result type, leading either to a successful
access or an error response.
2018-04-13 02:39:46 +02:00
91b83f5ede ElementAccess: (WIP) unsuccessful attempt to solve the typing problem
the intention was to return disparate result types, just depending on the
actual position in the UI-Coordinates. The client knows what to expect
2018-04-09 01:14:12 +02:00
c245098d45 ElementAccess: (WIP) first draft for internal accessor function
...but can not work this way.
Since void* has not RTTI, no secure access with downcast is possible
2018-04-09 00:51:24 +02:00
20ecc3f0d0 DI: allow to trigger the lazy instantiation of a mock service instance directly
Basically the mocking mechanism just switches the configuration
and then waits for the service to be accessed in order to cause acutual
instantiation of the mock service implementation. But sometimes we want
to prepare and rig the mock instance prior to the first invocation;
in such cases it can be handy just to trigger the lazy creating process
2018-04-08 18:43:27 +02:00
e99ad7a3e6 ElementAccess: draft simple lookup interface 2018-04-08 18:43:27 +02:00
09359cf92a ElementAccess: initial brainstorming about the interface mechanics 2018-04-07 02:28:29 +02:00
dc97ab5546 ElementAccess: consider helper to encapsulte access to actual GTK structures (#1134) 2018-04-07 01:00:25 +02:00
2f899a921c ViewSpec: draft next steps to address
...should implement the generic invocation in ViewLocator,
without actually implementing the backing UI element allocation logic
2018-04-05 19:43:10 +02:00
18a552002d ViewSpec: use mocked LocationSolver to verify operation of the DSL 2018-04-05 01:09:13 +02:00
71bb2b48b6 ViewSpec: pick up with dependency-injection into the DSL tokens (#1126)
Attempt to find my way back to the point
where the digression regarding dependency-injection started.

As it turns out, this was a valuable digression, since we can rid ourselves
from lots of ad-hoc functionality, which basically does in a shitty way
what DependencyFactory now provides as standard solution


FIRST STEP is to expose the Navigator as generic "LocationQuery" service
through lib::Depend<LocationQuery>
2018-04-04 03:29:26 +02:00
4e0d99e928 Demote the Play-Facade to a in-language (C++) Interface to get rid of InterfaceFacadeLink
I am fully aware this change has some far reaching ramifications.
Effectively I am hereby abandoning the goal of a highly modularised Lumiera,
where every major component is mapped over the Interface-System. This was
always a goal I accepted only reluctantly, and my now years of experience
confirm my reservation: it will cost us lots of efforts just for the
sake of being "sexy".
2018-04-03 02:14:45 +02:00
be789bea59 Fix funny problem with C header stdbool.h
...which is so kind as to redefine bool, true and false as macros. Yessss!
2018-04-02 03:27:07 +02:00
89d93a13e4 Modernise Unknown Exception handler and Exception messages 2018-04-02 01:48:51 +02:00
21e47e014a Modernise Lumiera Error baseclass 2018-04-01 23:45:00 +02:00
bfbcc5de43 simplify ClassLock by use of Meyer's Singleton with zombie check
...and package the ZombieCheck as helper object.
Also rewrite the SyncClassLock_test to perform an
multithreaded contended test to prove the lock is shared and effective
2018-04-01 06:09:01 +02:00
992056ea69 reduce include dependencies of DelStash
...get rid of some further Boost includes and remove unnecessary disable_if
2018-04-01 00:37:58 +02:00
fc546f71b4 Reorganise some tests
Dependency-Injection rather fits into the "fundamentals" section.
It is more than a mere library facility
2018-03-31 17:12:45 +02:00
fe10ab92dc DI: adjust codebase to the new DependInject configuration API 2018-03-31 01:06:10 +02:00
80207ea224 DI: (WIP) switch to totally rewritten new implementation of lib::Depend (#1086)
- state-of-the-art implementation of access with Double Checked Locking + Atomics
- improved design for configuration of dependencies. Now at the provider, not the consumer
- support for exposing services with a lifecycle through the lib::Depend<SRV> front-end
2018-03-31 01:06:06 +02:00
5d0c2b6d2c DI: special solution for singletons with private default ctor
...which declare DependencyFactory as friend.
Yes, we want to encourrage that usage pattern.

Problem is, std::is_constructible<X> gives a misleading result in that case.
We need to do the instantiation check within the scope of DependencyFactory
2018-03-30 06:48:34 +02:00
b3d18c1a74 DI: rework dependency-injection configuration in terms of the new DependencyFactory
why is this so damn hard to get right?
2018-03-30 05:56:53 +02:00
5fc85df385 DI: inline into lib::Depend to obsolete InstanceHolder
but now we've got two factory functors.
So there is yet more potential for simplification & refactoring
2018-03-29 16:57:55 +02:00
c3e149028f DI: draft towards unified use of the singleton holder
ideally we want
 - just a plain unique_ptr
 - but with custom deleter delegating to lib::Depend
 - Depend can be made fried to support private ctor/dtor
 - reset the instance-ptr on deletion
 - always kill any instance
2018-03-28 03:27:05 +02:00
d6786870f3 DI: port the old Singleton unit tests
all these tests are ported by drop-in replacement
and should work afterwards exactly as before (and they do indeed)

A minor twist was spotted though (nice to have more unit tests indeed!):
Sometimes we want to pass a custom constructor *not* as modern-style lambda,
but rather as direct function reference, function pointer or even member
function pointer. However, we can not store those types into the closure
for later lazy invocation. This is basically the same twist I run into
yesterday, when modernising the thread-wrapper. And the solution is
similar. Our traits class _Fun<FUN> has a new typedef Functor
with a suitable functor type to be instantiated and copied. In case of
the Lambda this is the (anonymous) lamda class itself, but in case of
a function reference or pointer it is a std::function.
2018-03-26 07:54:16 +02:00
4d783770d0 Bugfix: CallQueue_test initialisation was not threadsafe (see also #1131)
...which showed up under high system load.
The initialisation of the member variables for the check sum
could be delayed while the corresponding thread was already running
2018-03-26 04:40:54 +02:00
685a9b84ee Library: replace boost::noncopyable by our own library solution
Benefits
 - get rid of yet another pervasive Boost dependency
 - define additional more fine grained policies (move only, clonable)
2018-03-24 05:35:13 +01:00
d9af3abb0f DI: implement creating singleton from arbitrary (user provided) closure/functor/lambda
this is quite an ugly feature, but I couldn't come up with
any convincing argument *not* to implement it (and its low hanging fruit)
2018-03-22 06:53:56 +01:00
5c39498929 DI: clean-up and document the TDD test
...written as byproduct from the reimplementation draft.

NOTE there is a quite similar test from 2013, DependencyFactory_test
For now I prefer to retain both, since the old one should just continue
to work with minor API adjustments (and thus prove this rewrite is a
drop-in replacement).

On the long run those two tests could be merged eventually...
2018-03-19 05:34:27 +01:00
957e7ff54c DI: extract testcode into new unit test 2018-03-19 03:46:43 +01:00
41b8d12b66 ViewSpec: reconsider how to build and structure the DSL (#1126)
...in the light of all the foundation components and frameworks created meanwhile
2018-02-23 05:07:39 +01:00
b6360b2e9c LocationSolver: automatically inject persp(UIC_ELIDED) (closes #1128)
decided to add a very specific preprocessing here, to make the DSL notation more natural.
My guess is that most people won't spot the presence of this tiny bit of magic,
and it would be way more surprising to have rules like

UICoord::currentWindow().panel("viewer").create()

fail in most cases, simply because there is a wildcard on the perspective
and the panel viewer does not (yet) exist. In such a case, we now turn the
perspective into a "existential quantified" wildcard, which is treated as if
the actually existing element was written explicitly into the pattern.
2018-02-17 05:11:34 +01:00
0f26f1e0f4 LocationSolver: Documentation and clean-up (#1127) 2018-02-17 03:45:07 +01:00
da8fd6a031 LocationSolver: use the "elided" marker for realistic create rules
...actually just more test coverage,
the feature is already implemented.

What *could* be done though is to inject that UIC_ELIDED marker
on missing perspective specs in create clauses automatically...
2018-02-16 07:34:48 +01:00
983c490644 LocationSolver: test coverage for existentially quantified elements (#1128)
...and again spotted some really insidious bugs
2018-02-16 06:37:43 +01:00
6665fb68d6 LocationSolver: decide not to implement match based on context (#1130)
This looks like YAGNI, and it would be non trivial to implement.
But since the feature looks important for slick UI behaviour,
I've made a new ticket and leave it for now
2018-02-16 03:24:37 +01:00
f3791297d6 LocationSolver: cover most standard usage situations
with the exception of some special situations,
which require additional features from the engine,
especially binding-on-context

Not sure though if I'll implement these or say YAGNI
2018-02-16 01:59:51 +01:00
60d40a6a6e LocationSolver: concept for standard usage situation test coverage
...using a fixed set of rules this time,
while injecting a different (simulated) UI tree for each testcase
2018-02-14 04:42:19 +01:00
98cab32a08 LocationSolver: several rule match test cases 2018-02-14 03:02:44 +01:00
9249c513a9 LocationSolver: wildcard match test cases 2018-02-13 03:13:53 +01:00
92bf317d29 LocationSolver: long explicit path test cases
...and here a bug was hiding. gotcha
2018-02-13 02:46:43 +01:00
9fe314ad04 LocationSolver: testcases regarding perspective
TODO support for existentially quantified perspective to match against
"just the" perspectice, disregarding the actual value
2018-02-13 02:26:03 +01:00
c11e557b45 LocationSolver: smallest possible query test cases
querying on window level (=root level)
2018-02-11 04:36:11 +01:00
e04f61fe0d LocationSolver: length discriminating test cases 2018-02-11 04:16:58 +01:00
820abe2bef LocationSolver: provide DSL notation to write "create clauses" 2018-02-11 04:00:59 +01:00
7a167c4c3a LocationSolver: draft pattern for writing those test cases
...which shows: we also need a DSL mechanism for writing "create clauses"
2018-02-11 02:34:56 +01:00
65a86bc426 LocationSolver: define extensive test coverage to be written (#1127) 2018-02-10 02:03:09 +01:00
6d0e8a35a6 LocationSolver: simple unit test PASS 2018-02-10 00:34:24 +01:00
66bbf146a6 LocationSolver: implement this additional resolving flavour
coverPartially() now computes coverage solution and moves
that solution into place, while retaining the extraneous, uncovered part
2018-02-09 03:30:45 +01:00
c88a68a2a0 LocationSolver: need yet another flavour of the coordinate resolving mechanism
...this happens when you design a subsystem bottom-up
You build five items just to find out that in fact you need only a sixth item....
2018-02-08 03:00:38 +01:00
6022a8afb1 LocationSolver: draft outline of the solving loop 2018-02-08 02:50:48 +01:00
bf314482da LocationSolver: draft the simple usage scenario (unit test) (#1127) 2018-02-08 00:37:02 +01:00
10d2cafba9 LocationSolver: draft entities involved in location solving (#1127)
basically this will be built on top of the path matching / resolving mechanism coded thus far.
but we'll need some additional flags and some DSL magic
2018-02-07 04:03:39 +01:00
136e78d023 DockAccess: decide on next steps towards integration (#1126) 2018-02-01 23:08:43 +01:00
22e823fad5 DockAccess: finish setup of allocation specifications within the DSL 2018-01-15 03:56:23 +01:00
ef74527f6b DOC: eliminate spurious mentions of tr1:: 2018-01-12 03:03:25 +01:00
7dd69003b5 Navigator: finish path matching resolver for UI coordinates (closes #1107) 2018-01-10 04:42:49 +01:00
722c49e5ff Navigator: finish coverage of path extension 2018-01-10 04:21:42 +01:00
2d66293c32 Navigator: test for path extension now basically working as intended 2018-01-09 02:12:00 +01:00
f10263c469 Navigator: fix insidious nesting error in test definition 2018-01-09 01:52:49 +01:00
55c196e5a2 Navigator: define test cases for path extension after coverage 2018-01-08 23:49:24 +01:00
d5209bfe1d Navigator: get the anchor() cases to work as intended 2018-01-07 07:20:41 +01:00
837aa81fc5 Navigator: cook up some interesting test cases for anchor mutation
...and yes,
even writing seemingly superfluous test cases will uncover yet another bug
2018-01-07 03:17:15 +01:00
2665ad5bf3 Navigator: supply another mutation operation to make anchorage explicit
...basically just a re-use of existing functionality.
Needs some test coverage though
2018-01-07 02:24:33 +01:00
c88747dc99 Navigator: cover selection from several possible solutions 2018-01-06 04:36:18 +01:00
e7ce82d17e Navigator: fix covering of an explicit UI-Coordinate
...especially to make the anchorage explicit
2018-01-06 03:32:42 +01:00
0ea5583b62 Navigator: explicitly reject solutions that did not bind all wildcards
...this makes most of the remaining test cases pass

only a plain anchor is not yet properly interpolated
2018-01-05 03:57:27 +01:00
d9db5f3917 Navigator: further unit tests for boundrary cases
NOTE not working yet; trailing wildcards not rejected
2018-01-05 02:14:22 +01:00
f4648c393f Navigator: unit test simple cases of coverage 2018-01-04 04:52:09 +01:00