kew developer docs
Work in progress. Please tell me what to add here.
How songs are created
Songs are created by calling loadsong. In it a thread called songdatareaderthread() is created. In that the songdata is created and assigned a slot A or B in the loader. For instance, if a track is loaded in slot A, and we are loading the next track, the track is assigned to slot B. The decoder is also set as next in preparenext_decoder so that miniaudio can play it gaplessly. Kew alternates between showing metadata from songs in slot A or slot B, but miniaudio is playing a chained set of decoders, and we are adding one link to the chain at a time.
The current song SongData is cloned (songdataclone()) whenever getcurrentsongdata() is called, if the current song has changed since getcurrentsong_data() was last called.
Whenever the user changes what the next song is going to be, nextSongNeedsRebuilding should be set to 1.
How the UI works
kew implements a stateless rendering pattern called model-view-update. This means data in the model is changed in the update() function and more complex behavior is done by executing an UpdateResult and sending it to run_command(). The rendering does not modify the model, it can however return data in a message inside the UpdateResult if it has made a change. Then the update() function can read the data in that message and apply it to the model if needed.
Rendering
The rendering is done in renderui.c in layoutrenderdirty() by calling the correct component method for the components that are in the Layout. Only dirty areas are re-rendered. To mark an area as dirty, you can call setdirty() with DIRTYALL or with DIRTYLIBRARY, or DIRTY_FOOTER or whatever are you want to set dirty.
The component method will take a region and will render the cells for that region according to what’s in the model to the DrawBuffer.
Finally, what’s in the DrawBuffer is rendered to the screen in terminalbackendcommit.
Rendering Style
The struct that handles styling is called CellStyle. You can use the current theme to set the correct cell style, like so:
CellStyle querystyle = cellstylefromtheme(ui->theme.search_query);
Then pass it to the draw_buffer function:
drawbuffersetstringtruncated(buf, region.row, region.col, text, textwidth, querystyle);
Layout and Components
Component configuration is read from current.layout that’s in ~/.config/kew/layouts/.
For instance, the error_row and footer is defined like this:
[footer_pane]
row
height=fixed:1
col=0
pane
component=error_row
dirty=footer
width=auto
row
height=fixed:1
col=0
pane
component=footer
dirty=footer
width=auto
It says that these two components should be marked dirty by DIRTY_FOOTER.
A function is matched with every component name in a registry in settings.c:
static const ComponentEntry component_registry[]
For instance:
{“footer”, component_footer}
This component is the one that renders the footer area, which is defind above by starting at col 0 and being 1 row high, and width auto, which means maximum width of the region it’s in.
