Commit graph

4311 commits

Author SHA1 Message Date
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
25c8579695 Job-Planning: new draft - organise the overall planning process
- introduce a new entity: RenderDrive
- it supersedes the CalcPlanCalculation, but is managed by CalcStream
- moreover, the RenderDrive will house a IterTreeExplorer-Pipeline
- define the concerns and relationships more clearly (see Drawing)
- prerequisite to disentangle the Job-planning "mechanics"
2023-04-17 04:51:38 +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
bc330f0525 MERGE: Join completed GUI developments (closes: #1230)
All preceding integration work (#1014 and #1099) completed.
Ready to start on the [ticket:1221 »Playback Vertical Slice«]...
2023-03-22 23:56:08 +01: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
5b64507560 Timeline: remove visual debugging and add timeline style
for sake of developement of the timeline body drawing code,
several tweaks were added to make the impact of the styling stand
out clearly. This changeset removes all those tweaks and restors
the code to intended neutral behaviour

Moreover, the cursom drawing of the timeline now requires some
basic aids to be present in the stylesheet, otherwise the track structure
will not be visible. Thus add some minimalistic styling to the
"light-theme-complement"-stylesheet, mostly based on the usual
predefined theme colours and some box-shadow settings.

This is by no means an adequate graphical solution,
yet it should be enough to get on with coding....
2023-03-19 14:32:11 +01:00
28331f9f8a Timeline: complete the rework of UI backbone and Timeline (closes: #1014)
check private notes and mindmap and fix some remaining minor inconsistencies,
notably the calculations in the overlay renderer in the `BodyCanvasWidget`.
2023-03-18 00:58:55 +01:00
8fec337f60 Timeline: investigate setup of initial canvas widthin pixels
Not sure if the initial window width is used properly for calibration
of ZoomWindow "pixel width" base setting.


Follow-up to the layout logic established with this commit:
09714cfe28
2023-03-15 02:05:34 +01:00
d564ce429a Timeline: remove diagnostic functions (closes #1201)
An extended round of rebuilding and reworking the global UI structures
can be concluded now. A flexible recursive structure of Tracks has
been implemented for the new Timeline-UI, allowing to contro all
relevant aspects of structure composition by **Diff Messages** sent
up from the Steam-Layer into the UI.

Moreover, the ability to control the custom drawing code through regular
**CSS style rules** has been demonstrated, allowing for seamless integration
of Lumiera UI elements with the existing desktop theme.
2023-03-10 17:23:17 +01:00
fc0fcad4d6 Timeline: implement structure connections for sub-Tracks (closes: #1018)
This completes the initial implementation round for the TrackHead.
- arrangement and layout for nested sub-Tracks is now settled
- a graphical representation of scope nesting was implemented

Postponed for later...
- still some minor discrepancies on synchronisation of vertical space
  between TrackHead and custom drawing in the body (off-by-one?)
- Expanding / Collapsing of Tracks
- Implement actual Controls to influence the Scope, e.g. Volume, Mix-Mode
- Dynamically indicate selection and Muting on the structure display
2023-03-06 01:51:35 +01:00
caffcef559 Timeline: Bugfix - can not assume scale factor one
While by default the Cairo Context is scaled to device units,
we must not assume that the given Context is unscaled; rather
it might have been deliberately scaled...

A notable example is the Gtk Inspector, which offers a "Magnifier" feature
2023-03-05 17:20:24 +01:00
fc74fbcd4f Timeline: complete integration of bracket drawing into the Layout
- pick up all relevant values from CSS
- also control the width of the StaveBracket
- observe the given overall height

Moreover, complete documentation drawing in Inkscape
and add a page to the TiddlyWiki, describing the principles
underlying this design and construction.
2023-03-05 04:00:49 +01:00
47108fa2d8 Timeline: expand and document system of marker style classes
.timeline__head : The complete header container on the left side
.timeline__navi : navigation control at top
.timeline__pbay : container holding the patchbay on the left side
.fork__head     : each individual TrackHeadWidget (possibly nested)
.fork__control  : container for the control components for each track scope
.fork__bracket  : the StaveBracket drawing to indicate the nesting structure
2023-03-03 18:36:33 +01:00
c234ab733b Timeline: Bugfix in drawing code
...the gap at the lower end of the line was caused
by an unintended conversion from double to int, prior to scaling
2023-03-02 17:59:54 +01:00
6108fdb738 Timeline: now able to implement placement and complete drawing
The tricky part is to derive the anchor point for the upper
and the lower cap of the bracket, taking into account possible padding.
There seems to be a bug hidden somewhere in this logic, since the
line turns out too short at the lower end....?
2023-03-02 02:06:56 +01:00
2565856f2e Timeline: investigation how to retrieve font size
According to the documentation, we should be able to get a Pango
font description from the CSS style context, and from there we should
be able to retrieve a font-size specification (and a DPI for the display)

Running this experimental code yields a font-size value of 9pt,
leading to a scale factor of about ~6, which seems plausible.
2023-03-01 01:43:57 +01:00
d66949a70a Timeline: setup for layout control of scope brackets
after weighting in the pro, and cons,
I decided to follow the standard path and pick up values
for each StaveBracket instance individually from Gtk::StyleContext,
assuming that the GTK framework will care for caching and performance
2023-02-27 02:04:56 +01:00
b7ea68e285 Timeline: draft Cairo drawing code to implement this shape
...this settles the most tricky part: how to get the curved end caps
defined and placed precisely; the solution approach is thereby confirmed.
2023-02-26 16:58:07 +01:00
171c3e30d7 Timeline: fix horizontal allocation on leaf-tracks
...as it turned out, it suffices just to state desired behaviour explicitly
- make the StaveBracket expand=false
- declare the HeadControl expand=true

The reason lies in the fact that on leaf-tracks there are just two
adjacent cells in a single row, lacking any exterior source of layout guidance.
2023-02-11 04:30:26 +01:00
4444e2b0ec Timeline: setup framework for custom drawing for the track structure
...just drawing a marker cross for now to indicate allocated size;
speaking of size -- GTK sometimes expands allocation horizontally,
while we'd prefer an absolutely fixed size for the purpose at hand.
2023-02-10 17:51:02 +01:00
70b8b86182 Timeline: determine remaining work to wrap-up
Intention is to shift focus of development work down towards Player and Scheduler soon.
However, since the timeline display saw substantial improvement it seems prudent
to finish work on some open ends, notably

- the track head structure
- the drawing and styling code

While content rendering for Clip widgets can safely be postponed, regarding the TrackHeadWidget,
where custom drawing is planned to display a structural outline of the nested scopes, some
ground work should be completed to make those plannings explicit.
2023-02-09 01:30:32 +01:00
37543024fd Timeline: use ElementBoxWidget to display the track header
This both demonstrates the layout of the `TrackHeadWidget`
and puts `ElementBoxWidget` into intended use to indicate
the scope of a track and to provide a placement icon and
an expander/collapser button.

see #1018
see #1219
2023-02-03 04:38:56 +01:00
25be54ecbe Timeline: remove diagnostic code (closes: #1211)
Layout calculation and balancing between body and track header
now works reasonably well, labels are placed properly and the
calculated layout remains stable when changing window size,
connected panes and scrollbars behave as expected now.

Quite a feat!
2023-01-25 01:42:40 +01:00
e0e0192938 Timeline: fix height calculation
...to properly account for
- the "prelude" padding above the root track
- overview rulers located into a fixed separate canvas at top
- slope-down and slope-up borders around nested tracks.

After testing, results seem now to be accurate up to ± 1px

Finally (sigh)
2023-01-23 23:44:55 +01:00
9bfae3cee1 Timeline: control alignment to sub-tracks through additional padding
...a huge improvement;
however, it becomes obiouvs now that we'll have to deal specifically
with the root track ruler canvas and "prelude" padding...
2023-01-22 00:50:34 +01:00
b38481fa89 Timeline: solve basic layout issue by properly calculating the height
As it turns out, we need to take the actual allocation of the cells
within the grid explicitly into account: combined cells will report
their extension for each of the underlying cells, thus leading to
excessively overestimated measurements.

So we now calculate the overall height based on the actual structure
- first row holds the label
- left column below used as expander
- right column holds individual content

Remaining problems:
- height of ruler canvas at top not taken into account (11px in this example)
- start of sub-track headers not synchronised with start of sub-tracks
  in the body area
2023-01-20 23:57:21 +01:00
4887194589 Timeline: investigate vertical space allocation on nested tracks
...seemingly the allocation of grid cells in the `TrackHeadWidget`
is not quite correct yet: even when there are nested sub-tracks,
we always need another row to hold the controls corresponding to
the track itself and the whole scope. And this row is also what
should be adjusted to match the vertical extension of the content
area.

As it turns out, the whole topic how to handle collapsed tracks
was not even considered yet; the calculation of the "track profile"
would need to be reworked to accommodate collapsed tracks, see: #1265
2023-01-19 23:58:42 +01:00
a04d2b01c6 Timeline: hunt down and fix a numeric-wrap problem
Sometimes, fractional seconds in the ZoomWindow metric can build up
to numerator and denominator values in the 64-bit integer domain.
Thus the division and truncation of the Window pixel with value
must be done in int64_t, while the result value is then
guaranteed to be a small integer < 100000

This caused the canvas to flicker and jump in size and the
resulting scrollbar change caused various cascading effects
on the further layout calculations...
2023-01-17 02:16:30 +01:00
2fb182e7ff Timeline: analyse and fix re-entrance problem in DisplayEvaluation
Note: the actual root cause, why this re-entrance happens,
is due to another obvious numerics bug not yet solved.
Here, the canvas width was suddenly set to zero, causing
the scrollbar position to change and thus the ZoomWindow
to re-fire the structure change signal.

However, such invalidation of previously established baseline
values can never be totally excluded in advanced layout calculations,
and thus the evaluation mechanism must be prepared and re-triggered
to start over, until a stable layout is achieved.
2023-01-16 00:07:05 +01:00
0a99e5dfc8 Timeline: reorganise additional padding in TrackHeadWidget
- rearrange cell content and disable auto-expand to prevent
  the content area from becoming oversized initially

- fix autocompletion error in signal binding,
  causing segfault when moving the scrollbar
2023-01-15 02:51:00 +01:00
61f0e2f6a7 Timeline: further (unsuccessful) efforts towards layout sync
attempting to get the vertical space allocation in header and content area
synchronised; previously we conflated the content size and additional
padding, but even after distinguishing both, we still get a cyclic
dependency, leading to progressive increasing of allocated size...
2023-01-10 04:02:26 +01:00
832dc72652 fix indentation 2023-01-10 02:48:45 +01:00
09714cfe28 Timeline: draft solution to interconnect ZoomWindow and scrollbar
After quite some tinkering, instead of extending the DisplayManager interface,
I now prefer to treat this connection rather as an intricate implementation detail:

The TimelineLayout implementatino now provides two translation functions,
which are directly wired as slots from the Signals emitted by moving the
hand of the scrollbar; the idea is that these functions mutate the ZoomWindow,
which then triggers a DisplayEvaltuation, which in turn causes the
drawing code to pick up and translate back the new metric and position.

Results look promising, insofar the DisplayEvaluation is now triggered
repeatedly, and the actual window width in pixel is propagated;
however, the response of the layout code is seemingly random at times,
the allocated height grows monontonously and the code Segfaults when
moving the scrollbar...
2023-01-06 03:09:28 +01:00
941d3088d5 Timeline: rearrange ruler canvas into a slave scrolled pane
this makes the arrangement more symmetric and natural
and also makes the overview ruler scroll alongside the content pane,
thereby creating the (intended) impression of one uniform layout space
2023-01-05 02:45:11 +01:00
f3098daeb4 Timeline: investigate problem with horizontal scrollbar
As it turns out, this happens as side-effect from the workaround 2019-08-22

fc5eaf857c

Obviously, just set_size() on the canvas is not sufficient for
GTK actually to establish a size-request (seemingly the canvas counts
as /empty/ and only real widgets would make a difference).
However, since the ruler canvas is directly placed into the box,
and not adapted by a ScrolledWindow, explicitly set_size_request()
also causes the enclosing Box to "inherit" this minimal required size,
thereby also spreading out the BodyCanvasWidget beyond the size
actually available. GTK handles this situation by hard-clipping
on the right side, which causes the vertical scrollbar to disappear
and keeps the horizontal scrollbar disabled (since nominally it still
spans the whole size available, even while this size is then clipped
subsequently).

This changeset adds a lot of debug printing and demonstrates this
behaviour by setting only a minimal horizontal size_request, so that
the window is no longer expanded and clipped.
2023-01-04 23:55:21 +01:00
c22bbe5f93 Timeline: Refactor DisplayEvaluation to integrate zoom calibration
This does not really change the logic of the DisplayEvaluation mechanism,
but makes it much more flexible: instead of having two hard wired components,
the DisplayEvaluation visitor now holds a collection of LayoutElement pointers.
This way, the Layout manager itself (on behalf of the ZoomWindow) can
participate in the process, and on activation will now establish the
window width in pixel.

This works now insofar the drawing on the canvas is adapted coherently;
however something with the setup of the Scrollbar is still not quite right;
some time ago I recall the scrollbar worked, but now it is blocked
and the canvas just clips to the right side.
2023-01-04 03:36:12 +01:00
061b70c96f Timeline: integrate ZoomWindow change listener
- connect to TimelineLayout::signalStructureChange
 - this causes the trackProfile to be reset
 - next draw() call will then triger display-evaluation
2023-01-03 02:23:22 +01:00
62bad8720a Timeline: decide upon handling of the canvas origin
It is now tied to the start of ZoomWindow::overallSpan(),
thereby defining the (technical) pixel coordinates within the window
and for drawing on the canvas to be always positive. Whenever ZoomWindow
re-calibrates, it's change signal will trigger, causing the
TimelineLayout to perform a new DisplayEvaluationPass,
which in turn prompts all embedded widgets to readjust
their positions accordingly.
2023-01-03 00:20:09 +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