Releases: oernster/Stellody
Release list
Stellody v0.6.0
Release notes
Rate what you are listening to
Any track takes a rating out of five stars, from a rectangle at the right of the
position bar. The stars are about whichever track you have picked out rather
than whichever one is playing, so a track you have never heard can be rated; so can one you
point at while something else plays. Pressing the star a track
already sits on takes the rating back, since nought is the absence of a rating
rather than a sixth one.
An album carries a rating of its own, set from the stars in its own header under
the artist's name. A caption says which rating it is, because the two controls
look alike and sit inches apart. Neither is worked out from the other: a record
with one poor track on it is not a poor record.
Neither ever reaches your music files. Both are kept in Stellody's own store
against the album's identity rather than against a path, so renaming a folder
loses nothing.
Play counts, where they can actually be read
Reaching the end of a track is what counts as a play, so skipping through an
album counts nothing.
The count first sat beside the stars on the position row. That row is about one
track and moves on the moment that track ends, which is the moment the count
becomes worth reading, so in practice it showed nothing. It now sits on the
track's own row in the album's list, beside the rest of its detail, which lets a
record be read down for the tracks you keep coming back to. A track that has
never played out says nothing there rather than nought: a column of noughts says
only that the library is new.
The album pane's header
The play and close buttons sat beside the album's name, so the name stopped
short of the edge to leave room for two small pictures. They sit under it now,
at the end of the rating row, at twice the size they were. The name runs the
whole width.
The play button also stopped disagreeing with the one on the toolbar. It offered
to start the open album whatever was already going; it wears the pause face
while something plays now and pauses on a press, which is what the toolbar's
button has always done. Both are told what is playing from the same place, so
they cannot drift apart.
The album header reads properly
The name, the artist and the album rating caption each sat with the first
letter against the corner of a hard box. Every widget carries its own fill, so
a label in that header reads as a rectangle whether or not it was meant to.
Those three now hold their text off the edges and carry rounded corners: the
title and the artist round on the outside of the pair, since they read as one
block and rounding each in full would pinch the join between them.
A cross rather than a slash
The mark that says a switch is off is new artwork: a red cross. It reads the
same way in both places it is used, over the muted speaker and on the button
that rolls an open album back up.
Help, plus knowing when there is a newer Stellody
The About button at the right of the top tray is a Help button now. Its tooltip
says Help and it drops a menu carrying About and Check for updates. The menu
bar's Help menu carries both as well.
Stellody can now tell you when a newer version has been published. About three
seconds after the window opens, then once a day after that, it asks GitHub
whether there is one. It says nothing at all unless there is: no "you are up to
date" you did not ask for. When there is, it offers the file for your own
machine, a way to skip that version for good, else Later. Asked outright from
the Help menu it answers whichever way it turns out, including that it could not
reach GitHub.
That request carries nothing whatever about you or your machine, not even which
version you are running: it reads one small public document about Stellody and
the comparison happens here. Scanning a library and playing it still open no
connection at all.
This is the second thing in Stellody that can open a connection, the cover
chooser being the first, so the structural test that has always held the
local-first promise now names two modules instead of one and says what each is
for. Going from one to two was an edit somebody had to make and defend, which is
the point of counting them.
Waving the close question away decides nothing
Pressing the cross on the prompt that asks what the close button should mean
used to minimise the window to the tray. The prompt reported the offered
default whether or not anybody had chosen it, so being dismissed looked exactly
like choosing Minimise to tray.
It decides nothing now. The cross on it, like Escape, takes the whole press back:
the window neither leaves nor hides. Nothing is remembered either, which
matters because the same fault had a quieter half: dismissing the prompt with
the remember box ticked wrote that non-answer down as the standing behaviour,
so the question never came back.
Stellody has a site
At stellody.co.uk, with a home page, a features
page, a page on why it is built this way and a download page. It carries
screenshots of both views and states the things Stellody deliberately does not
do as plainly as the things it does.
The same pages answer at stellody.com, which now reaches the product rather
than the placeholder that stood there before. stellody.co.uk is the address
worth linking to; every page says so in its own markup, so a search engine is
never left to choose between the two.
Stellody v0.5.0
Release notes
Search the library
Type into the box in the top tray and the library narrows to what you are
looking for: album titles, artists and track titles, as you type. The box opens
and closes from the magnifier beside it; closing it clears the phrase, so a
narrowed library can never be left behind a box nobody can see.
An album that matches keeps all of its tracks, so it reads exactly as it always
does rather than turning into a shorter album. The track the phrase actually
hit is highlighted as though it were about to play and its row flashes a couple
of times, which gives the eye somewhere to go without the album being taken
apart. In the grid of sleeves that means the album opens underneath with the
hit already chosen; in the list it means the disc and the album above the track
are opened so the row can be seen.
Pressing Return asks the same phrase again. That is the way back to what a
search found for anyone who has since moved off it, since the box already holds
the phrase they want and asking again would otherwise mean clearing it and
typing it out.
Whatever was open under the sleeves stays open while a search narrows around
it, through a keystroke, through clearing the box, through inverting the album
order and through a rescan. It shuts only where that album has gone from the
grid altogether.
There is no search index. The whole library is read on every keystroke, which
is measured at under half a millisecond over 485 albums of 6,877 tracks; an
index would have held the wrong text besides.
Volume sits beside mute
The volume button has moved from the strip along the bottom up into the tray at
the top, immediately left of the mute switch. The two are one thought, how loud
and then whether at all, so doing half of it no longer means crossing the
window. The slider it opens now comes up below the button rather than above it.
The mute switch says what a press would do
It showed the state before: a plain speaker while the sound was on. Every other
picture in that tray shows the action instead, so it now carries the slash while
the sound is on, because that press is the one that silences it. The bottom
strip is unchanged: shuffle and repeat still light up to show their own state.
Tooltips arrive almost immediately
Qt held a tooltip back for the better part of a second. On a strip of buttons
that carry only a picture that wait means guessing at what each one does, so
the wait is now short enough to read as the button answering.
Fixes
- An album opened by a search showed no sleeve at all. Every keystroke was
throwing away the covers that had already been read, so the pane opened on a
placeholder painted in its own colour. Covers now survive a narrowing; the
pane also picks up a sleeve that arrives after it opened. - A search that replaced every row could leave the pane under the sleeves
listing the whole library down both of its columns.
Stellody v0.4.0
Release notes
The cover chooser a listener can see
Right clicking an album offers "Find cover art online...", which opens a grid
of every picture MusicBrainz and the Cover Art Archive hold for it. Picking one
keeps it. That is the whole of the outward reach: a window is given the service
or it is not, so one built without it carries no such entry at all.
It opens on a wait rather than on a result, because there is one. The archive
allows a request a second and a release has to be asked about before there is a
picture, so the dialog says what it is doing, then draws each tile as its own
thumbnail lands rather than making you wait for the last of them.
Closing it lets go. A request already sent runs to its own timeout, since
nothing can reach into a socket and stop it; what closing promises is narrower
and is the part that matters: whatever comes back afterwards is dropped rather
than drawn into a window that has moved on. A test holds a search open, closes
it, releases it and watches nothing arrive.
A picture that is kept is kept the way a local cover is, against the album's
identity rather than a path, so it survives a folder rename. It is marked as
chosen, which means it is checked against no file and outlives a rescan. As
ever, nothing is written into the music folder.
A refused archive is not an album without art
The chooser came back empty for everything. The archive was not saying the
album has no pictures; it was declining to answer at all, so a decline was
being read as an answer.
Measured: MusicBrainz refused 6 of 10 asks for one release at the one request a
second its own terms ask for; two asks five seconds apart were refused while a
third was answered. Three different user agents made no difference and the Cover
Art Archive answered 4 of 4 in the same minute, so it is that one host
declining a share of requests rather than the network, the rate or this
machine.
So a refused search is now asked again, up to five times with a growing pause
between them. Three live searches after the change came back with 10, 31 and 10
pictures, in 9 to 15 seconds each.
What still will not answer is said plainly. A search that is refused every time
now says the archive would not answer and to try again in a moment, rather than
reporting that nothing came back for the album. The two are different claims
and only one of them was ever true.
The chooser shows that it is working
A search takes 10 to 15 seconds against the real archive, which is long enough
that a dialog saying so in words alone reads as one that has hung. There is now
an indicator under the message, following the same pattern the scan uses: it
runs indeterminate while the releases are being looked for, since there is
nothing to count yet, then becomes a real fraction of the pictures as their
thumbnails arrive.
The button beside it says Cancel for exactly as long as there is something to
cancel, then Close. Pressing it does the same thing either way; only the word
changes, so nothing is ever left unable to be stopped. Keeping a chosen picture
is a fetch of its own, so it draws its own wait too.
The picture you picked says so
A picked tile now wears a ring, in the green the rest of the application rings a
chosen thing with. The tint behind the label was doing that job alone and was
too quiet to read against a wall of sleeves. The colour is stated once in the
palette rather than painted in the dialog; the ring is scoped to the chooser,
since the library's own views are choosing nothing.
Picking a picture no longer washes its colour out. Qt draws a selected icon in
its own Selected mode, so the one tile being compared against the others was
the one that could no longer be seen properly; measured, a picked tile rendered
grey where its picture was brown. The same picture is now registered for every
mode, which leaves the ring to say what is picked.
A track shows its shape before it plays
The waveform used to be measured just after a press, so a track nobody had
played yet drew a flat line: nothing at all about the track somebody was
deciding whether to play. With nothing loaded, the bar now follows the
highlight and draws that track's shape.
What is loaded still wins. The line crossing the shape belongs to the track
that is playing, so browsing the library during playback leaves the picture
under it alone; the highlight only supplies the shape when there is no playhead
to contradict.
Measuring starts the moment the highlight lands on a track. It was made to
settle for a fraction of a second first, on the reasoning that a decode per row
passed over would be wasteful; measured, that reasoning had the wrong culprit.
The cost was not the decodes: it was letting go of one, which blocked the whole
interface for two seconds a step, because asking a thread to quit does nothing
to a decode already running.
Both halves are now fixed where they belong. A measurement is told to give up
and stops at the next block it reads, keeping nothing, since half a file is not
a shape. Letting go of one never waits. Measured on the reference library:
stepping through rows mid decode cost 2.00 seconds a step before and 0.2
milliseconds after; shutting down mid decode now takes 0.01 seconds. A
track already measured costs no decode at all and comes back in 0.6
milliseconds, which is the ordinary case for anything played before.
The shape half of the window moved into a module of its own while this was
done, along the seam between what the transport buttons do and which track the
bar is drawing.
The shape draws itself as it is read
A track that had never been played still showed a flat line for a second or
more, a cue-sheet album for a good deal longer, because the whole file had
to be read before there was anything to draw. Now the reading offers what it
has every five seconds of the music and the picture builds from the left.
Measured cold, from the disk rather than from a cache: an ordinary 28 megabyte
track puts its first picture up in 0.02 seconds and finishes in 0.49; a 272
megabyte album FLAC puts one up in 0.01 and fills in over 8.17. A track visited
again is instant, since the finished measurement is kept.
The reading itself also got four times faster, with the same answer bit for
bit. Finding which bucket a frame belonged to was being done one frame at a
time in Python, which turned out to be most of the time rather than the
decoding: a 60 megabyte track folded in 3.2 seconds that way and 0.84 done in
one pass by numpy, while a 390 megabyte album FLAC went from 21.8 seconds to
5.3.
Only the finished measurement is kept. A part of one written down would be
wrong on every redraw afterwards without ever looking wrong enough for anybody
to notice.
A chosen cover comes back after a restart
A cover picked from the chooser was kept correctly and drawn at once, then the
album showed a placeholder again on the next start. The picture was on disk
the whole time; nothing ever asked for it.
Drawing an album asks for its cover. That ask used to answer nothing
without consulting the store at all whenever the album had no file beside the
music and no picture inside the audio. It was a saving: opening nothing is
cheaper than asking a decoder to open nothing. An album with nowhere local to
look is the only kind the chooser is ever offered for, though; a chosen
picture has no file beside the music to be found by, so the saving cost every
chosen cover its next restart.
The store is now asked whatever the candidates say, since it is the thing that
knows whether a cover is kept. The property that saving read was removed with
it, because leaving it there invites the saving back.
Stellody v0.3.0
Release notes
Since the last release.
Album covers in the library
Each album now shows its cover. Stellody looks first for a file next to the
music, choosing by the names a ripper is likeliest to have written, then for a
picture inside the audio itself. Measured over a real library, four folders in
five carry a file beside the music while another fifth carry only an embedded
picture, so both are main paths rather than one being a fallback.
Reading a cover means going to disk and decoding an image, so it happens on a
thread of its own and only for albums a row has actually asked to draw. A
library of several hundred albums therefore costs a dozen reads to show a
dozen rows rather than several hundred to show any. Until an answer arrives an
album draws a plain square; an album carrying no picture anywhere keeps
that square rather than leaving a gap where every other row has a sleeve.
What is read is kept, scaled down, against the album's identity rather than
its path, so renaming a folder reuses the picture instead of reading it again.
What it was read from is recorded beside it and checked against that file's
size and modification time, so a cover replaced on disk is read afresh while a
rescan that changed nothing reuses what is already there.
Nothing about this reaches the network and nothing is written into the music
folder. The picture is read out of the file and Stellody's own copy is kept
where Stellody's own state lives.
A grid of covers, with the album opened underneath
The library can now be shown as a wall of sleeves rather than a list, with a
toggle at the left of the bottom strip between the two. That toggle was drawn
and disabled from the start; it now works, naming the view it would move
to rather than the one on show, since a button naming the current state reads
as a label and gets pressed to confirm it. Which view was last used is
remembered between sessions, as the appearance and the sort order already were.
Both views are the same library rather than two copies of it, so neither can
disagree with the other about what is there or the order it is in. Switching
keeps the order because there is only one of it; one cover serves both:
kept at the size the grid draws it and scaled down for a row, so moving between
the views reads nothing from disk a second time.
Picking a sleeve opens that album in a pane beneath the grid rather than
replacing the grid, so the sleeves stay where they were. The pane carries the
cover, the album's title and artist, a control that plays it from the first
track and one that shuts the pane again, with the album's tracks listed under
it. Those tracks are the same library rooted at that album, so their durations
and both ways of starting a track are the ones the list already had.
The sleeves are drawn as tiles
A grid of covers is not a list with pictures in it, so a tile is drawn rather
than left to the item view. Every tile is the same size whatever the length of
the names on it, the sleeve is centred rather than pushed against an edge, the
title sits over the artist and a name too long for its tile is cut with an
ellipsis rather than running into its neighbour.
The album whose pane is open wears the accent ring the rest of the application
uses to say where attention is, so the wall says which sleeve was picked
without a second device having to be invented for it. The pane itself is now a
panel of its own rather than more window; its heading carries the year.
The open album runs down two columns
An album opened under the sleeves lists its tracks in two columns rather than
one, the way the back of a sleeve does, so an album of a dozen tracks is read
without the pane growing to the height of a dozen rows.
Both columns are the one library rooted at the one album. Each hides the rows
belonging to the other rather than holding a copy of them, so the two cannot
disagree about the order or about what is on the album; no track can go
missing between the foot of one column and the head of the next. Nothing is
built out of widgets by hand, so the arrows still walk a column and the ring
still lands on real rows. An odd number of tracks leaves the longer run on the
left, where a reader starts. An album with a single track draws one column
rather than an empty panel beside a full one.
Opening an album leaves a track ready to play
Picking a sleeve now highlights that album's first track, so the play button at
the top has something to start. On a multi-disc album the highlight goes to the
first track on the first disc rather than to the disc itself.
The play button reads the view that is ON SHOW rather than always reading the
list. While the sleeves are up it starts what is highlighted in the open album,
which is what somebody looking at the sleeves is pointing at. One highlight is
shared between the two columns, so moving it into the second column takes it
out of the first.
The transport menu belongs to the sleeves too
Right clicking a sleeve offers the same Play, Pause, Stop, Previous and Next
the list has always carried, as does right clicking a track in the open album.
Play over anything naming an album means that album from its first track,
whether it is a sleeve in the grid or an album row in the list. It used to do
nothing at all on an album row, on the reading that such a row carries no
track of its own; a sleeve carries none either and pressing Play on one plainly
means play this. Over the album already loaded it means carry on, exactly as it
does over the track already loaded: starting a long piece over is what next and
previous are for.
The list gives a track row the height of a track row
A cover is drawn in the list at the size a row can carry rather than at the
size the grid keeps it. One pixmap serves both views; the list was taking the
grid's, which made every row as tall as a sleeve. Asking the view for a smaller
icon does not fix that, since the size is read off the pixmap and the view is
never consulted for one, so the size is now stated where it is read.
Rows are no longer held to a single height either, because only an album row
carries a picture. Measured on one album with its tracks showing: an album row
went from 166 pixels to 46 and a track row from 166 to 16.
The play button starts what is picked
Picking a second album and pressing play started the FIRST one again. Anything
loaded turned the press into a resume, whatever had been chosen since. Play now
means the highlighted track wherever that is not the track already loaded,
which is the rule the right click menu has always followed.
While something is playing the button is a pause button, so it still pauses
with another album picked: a press there is asking to stop rather than to go
somewhere else. The press after it starts what was picked.
Three sizes of sleeve in the grid
The grid draws its sleeves at one of three sizes, medium, large or extra large,
stepped through by a button in the bottom strip beside the view toggle. It
names the size it would move to rather than the one on show, as that toggle
does; it is dead over the list, where the size means nothing. The choice
outlasts the session, as the view and the sort order already did.
The tiles and the grid grow together, since a view keeps the spacing it was
given and would otherwise overlap them. Measured across the three: a 160 pixel
sleeve in a 192 pixel cell, then 240 in 272, then 320 in 352. The names under a
sleeve get the same room at every size, because a title is the same title
however large the picture above it.
Changing the size reads the covers again rather than stretching what is
already held. Reading comes out of Stellody's own store, which keeps a cover at
512 pixels, so none of the three asks for more than was kept and nothing
touches the music folder or the network. Holding one size at a time is also
what keeps the memory to the size chosen rather than to the largest on offer.
Repair moves up beside rescan
The repair control, which is still not built, sat on the bottom strip beside
the view toggle: among the settings that outlast a track rather than beside the
control it follows from. It now sits under the menus to the right of rescan,
since repair is the answer to what a rescan finds.
Its wording has one home, which moved with it, so the button and the one in the
library health report cannot come to say different things about the same
unbuilt feature. It stays disabled and stays named in the focus ring, so the
ring picks it up on the day it works without the order being revisited.
A bonus disc joins the album it belongs to
A folder such as "Ether Song (Bonus Disc)" sitting beside "Ether Song" showed
as a second album of the same name and artist, one above the other in the
library. The folder marker the grouping recognised needed a digit and this one
has none, so nothing joined them.
A bonus disc is now a disc even where its folder names no number. Which disc it
is comes from the tags where they say so; where they say nothing, the tracks go
on the disc after everything else the album holds, since a bonus disc is never
the first one and leaving it there would collide with the album proper track
for track.
The word CD, Disc or Disk is still required, because a bonus EDITION is not a
bonus disc. Measured across the reference library of 984 folders: three pairs
fold, "Ether Song", "Come Away With Me" and "The Ecleftic", each becoming one
album of two discs with no new issues reported. The folders naming an edition,
"[Bonus Track]", "(Bonus Track Version)", "[Bonus DVD]" and "[UK Bonus
Edition]", stay their own albums as before.
One older fault went with it. A folder named "Ether Song (Bonus Disc 2)" used
to be read as an album called "Ether Song (Bonus", the opening bracket left
behind; it ...
Stellody v0.2.0
Release notes
Since the last release.
The track's own waveform, with the playhead crossing it
The bar along the bottom of the window no longer fills up. It draws the
track's own amplitude, mirrored about the middle, with the part already played
in the accent colour and the rest dimmed; a line marks where playback has
reached. A bar says how far into a track playback has got. A waveform says
that as well as what is coming: where the quiet passage sits, where the piece
opens out, whether the thing about to arrive is a drum or a breath.
The shape covers a whole file rather than one track, because a cue sheet album
is one file holding many tracks and measuring it once serves all of them. Each
track then takes the part of that measurement belonging to it. A track too
short to fill a single bucket still gets a shape rather than nothing, coarse
though that shape is.
Measuring means decoding the file, which is far too slow to do while the
interface waits, so it happens on a thread of its own and the answer is kept.
A file already measured draws the moment the track starts; one that is not
draws a flat line until its shape arrives. Skipping quickly through an album
decodes nothing it passes over; an answer that arrives after the listener has
moved on is dropped rather than drawn over the track now playing.
What is kept lives in Stellody's own directory, named by a digest of the
file's path rather than by the path itself, since a music folder's names are
arbitrary where a filesystem's are not. Each record is checked against the
file's size and modification time, so a file replaced under the same name is
measured again rather than drawn from a record that no longer describes it.
Peaks are held to four places, which is finer than any display can show and
keeps a whole file's record to a few kilobytes.
Nothing about this reaches the music folder. The measurement is Stellody's own
state, written where Stellody's own state lives, which the read-only guard
proves rather than promises.
Where a track has reached, plus a way to move within it
The bar shows how far into the track playback has got, with the time either
side of it. Clicking anywhere along it moves there, rather than nudging
forward a page at a time as a slider otherwise would: clicking three quarters
of the way along a track means three quarters of the way along. It is
reachable from the keyboard like everything else.
The figure it shows is corrected. The audio engine reports what it has
DECODED, which runs a buffer ahead of what is leaving the speakers, so a
display fed from it raw would sit ahead of the music and a track would appear
to finish before it had. The engine now states how far ahead it is running and
the transport subtracts it. Seeking is corrected the same way in reverse, so
asking for a point lands on that point rather than a buffer short of it.
Stellody v0.1.1
Release notes
The guard that matters says only what it means
The structural test proving that nothing outside Stellody's own state may
write to disk carried permission for two modules that had never been written:
an artwork cache and a settings store. Permission granted in advance to code
no reviewer could read is worth nothing in a guard, least of all the one this
project exists for. Both are gone. A module that needs to write will ask when
it is written, which is when there is something to weigh.
The README says which tray it means
It used the one word for two things: the toolbar the transport sits on, then
the notification area Stellody waits in. Three lines apart, that read as a
claim that previous, play, stop and next were on the notification area's menu,
which they never were. The toolbar is now called the toolbar.
Nothing the application does has changed.
Stellody v0.1.0
Release notes
The first release. Stellody reads a FLAC library, shows it, plays it and never
writes to it.
Reading a library without touching it
The read-only guarantee is the reason the project exists, so it is enforced
rather than intended: one structural test proves the mutagen write surface is
unreachable from every module that can read tags; another proves that only
the modules owning Stellody's own state write to disk at all. Nothing in the
scanning or probing path writes anything.
A scan walks a folder you choose and caches each folder's result. A rescan
compares every file's size and modification time against that cache, so a
folder whose files are all unchanged is reused without opening one. On a
library of 510 folders and 4,870 files a cold scan takes about two and a half
seconds and a rescan about a third of a second.
What the walker skips is a named list of system directories and macOS stubs,
never a guess. An earlier version treated a leading dot as "hidden" and
silently swallowed two real albums.
Making sense of real, damaged libraries
A folder is one album. Sibling folders differing only by a disc marker merge
into one multi-disc set. Tags then supply the title, artist, date and genre,
each taken as the most common value the tracks carry. Grouping by tags was
tried first and measured: it fragmented one Mozart folder into five albums.
Where tags contradict something physical, the physical thing wins; every
fallback is recorded rather than hidden. A read-only health view lists exactly
what to repair, in a tagger of your own choosing. Stellody describes a damaged
tag; it never repairs one.
A track is a slice of a file rather than a file, so an album ripped as one FLAC
with a cue sheet behaves exactly like an album ripped as separate tracks. On
the reference library that is 163 albums out of 485, which makes it a main path
rather than an edge case.
Playing
The transport sits centred in the tray: previous, play toggling to pause, stop
and next. A track starts on a double click, on Return or from the right click
menu; the album plays on from there. The library highlight follows whatever
is playing, however it came to be playing. It moves only when the
track changes, so browsing while the music continues is not interrupted.
Along the bottom are volume with a slider, mute, shuffle and repeat. Shuffle
takes a permutation of the album and keeps playing whatever is already playing,
leading the scattered run with that track so the whole of the rest of the album
is still ahead of it. Repeat carries the end of the album round to its start
and keeps it there until it is turned off; it never settles on one track.
Shuffled, the album is scattered afresh each time round rather than replaying
the order it took last time; the new run never opens on the track that just
ended.
Shuffle and repeat light up while they are on rather than being struck through
while they are off, so the slash means one thing across the application: that
what the picture depicts is not happening. Each of the four is remembered
between sessions.
A new install and a reinstall both start with shuffle and repeat off. Stellody's
own directory outlives an uninstall unless it is asked to go, so without this a
reinstall came back wearing switches set months earlier. An update and a
downgrade are the same install carrying on, so they leave every choice alone;
a repair changes nothing at all.
Back returns to the beginning of the track in hand and waits there rather than
playing on, so the moment to carry on is the listener's. Pressing it again from
there goes to the track before, waiting at its beginning too, so repeated
presses walk back through the album at whatever pace suits. What decides between
the two is where the transport already is rather than how fast the button was
pressed: nothing here is timed. Under shuffle back always returns to the
beginning of the track in hand, because a scattered run is not the order the
tracks were heard in.
The stream is opened on the WASAPI device rather than on the multimedia default,
which is what actually produces sound on a modern Windows machine.
Coming and going
Only one Stellody runs at a time. Closing the window leaves it in the
notification area; a hidden window has no button on the taskbar, so opening
Stellody again from a shortcut used to start a second copy over the same
library. A second launch now asks the copy already running to come forward and
leaves, which is what opening it again meant. Ownership is a system
semaphore holding a shared memory claim; the ask crosses a local socket. All
three are the same objects on Windows, Linux and macOS; none of them is a
file left in a directory.
That ask is a word on the channel rather than the act of opening it. Anything
on the machine may open a named pipe; several kinds of Windows software
enumerate them as a matter of course, so a connection alone used to bring the
window up out of the tray with nobody having asked for it. The word is read now
and has to be the right one before the window moves. The copy that asks holds
its end of the channel until the word has been taken, since letting go the
moment it had written discarded the word along with it.
The window's close button asks what it should mean the first time it is
pressed, offering the notification area or a full quit; the tray is the
default and the answer can be remembered so it stops asking. That answer can
be taken back: "Ask again when I close" sits on the File menu and on the
notification area's own menu, because the window is hidden exactly when
somebody wants the question again. It is greyed out while there is nothing to
forget. A fresh install or a reinstall forgets it as well, since Stellody's
directory outlives an uninstall and an answer given to one install should not
quietly govern the next.
Quit means quit, from the tray's menu and from that prompt alike. Stellody does
not end when its last window closes, which is exactly what lets the cross leave
it running, so ending the application is said out loud rather than left to Qt.
Without that, Quit closed a window nobody could see and left the process
running, holding the tray icon and the claim to being the copy that runs. Where
there is no notification area at all, the cross ends Stellody rather than
leaving a process with nothing on screen.
Whether there is a notification area to wait in is decided by asking the
platform rather than by asking an icon whether it has appeared yet. An icon
shown a moment earlier has not necessarily been taken up by the shell; a launch
asked to start quietly would then open a window instead.
Getting about
Everything is reachable from the keyboard, in one explicit ring that follows the
order the window is drawn rather than the order Qt happened to build it. A
disabled control is never a stop. A ring belongs to a control, never to the pane
holding it; an item view shows its current row instead of wearing a
rectangle round everything.
Light and dark appearances, with the sort order, the chosen folder and the
switches all remembered.
Chrome that behaves like chrome
A read-only page is something to read, not something to act on, so clicking
anywhere in About, a licence or the health report no longer focuses the page
and draws a ring round it. The ring appears only when somebody tabs there,
which is the one time it says anything.
A page that fits its window is not a stop at all, since it scrolls nowhere. A
page that overflows keeps its place in the keyboard order, because a long text
with no controls of its own could not be read otherwise. Which of the two it is
gets decided again whenever the window is resized.
Installing
The About box states the copyright; the exe's own file properties are stamped
from the same constant, so the two cannot drift apart.
A per-user setup program, so Windows never asks for administrator rights. It
covers install, repair and removal, asks before replacing the files of a running
copy; it hands the foreground to the application before closing itself rather
than leaving a spent installer on screen. It offers to start Stellody when you
sign in, which brings it up in the tray rather than over whatever Windows has
just finished drawing.
Setup stays out of the library database entirely. Clearing the switches on a
fresh install leaves a note for the application to act on rather than opening
the store itself, so a setup program can never be what damages a library index.
A database that will not open is set aside whole and a fresh one opened in its
place, so Stellody comes up and rescans instead of refusing to start.
A launch that produces no window says why. Startup writes
%TEMP%\stellody-startup.log as it goes, so a copy that dies before it can
draw anything leaves a trail rather than nothing at all.
Saying thank you
A button at the far left of the bottom strip opens a donation page in your
browser. It is the only address Stellody knows; it is handed to the
desktop rather than fetched, so the local-first guarantee is untouched: the
browser does the asking and the application still opens no connection of its
own.
Not in this release
Nothing shows where a track has reached, so there is no elapsed time, no
progress bar and no way to seek within a track. Cover art, a grid view, search,
ratings, play counts, an equalizer and gapless transitions are not built.
Windows is the only platform.
Two controls are on screen for work that is not done: the view toggle and the
repair button on the health report, which also appears on the bottom strip.
Both are disabled and each says so in its tooltip, so nothing offers to do
something it cannot. The repair one is the nearer of the two: what every issue
should become is already worked out on each load, si...