36a122b8Simplify connection process
This patch refactors and simplifies connection process, which has been
messy as it was designed for C API. This refactor also removed the
unnecessary short-lived WebSocket connection on startup.
That unorganized `try_listen` / `start` methods have been pain point for
me. It was unclear how the class calls methods one by another, by
looking at class.
Elimination of startup short-lived WebSocket connection reduces startup
time. It was not a bothering one, but there is no technical reason to
close the established connection so this is good.
Shota FUJI
authored at
Shota FUJI
comitted at
42bdb450Remove third-party copyright notice
Plac for GTK4 no longer statically links to libraries.
Shota FUJI
authored at
Shota FUJI
comitted at
8ca06f40Fix extension registration errors in short time
Request handler at registration does not ignore ping request from Roon
server and tried to parse it as register response.
Shota FUJI
authored at
Shota FUJI
comitted at
417fbfc7Use SOOD parsing written in Vala
For faster compilation in Nix build (no downloading) and pure-Vala
challenge.
Shota FUJI
authored at
Shota FUJI
comitted at
d1962e17Fix seekbar behavior being flaky
Sometimes the seekbar remains disabled (`sensitive = false`) and
sometime it keeps previous tracks seek location after track changed.
These are due to mishandling of `seek_position`'s nullability.
Shota FUJI
authored at
Shota FUJI
comitted at
61dd1427Use Zone class directly for view model
`Zone` class became GObject.
Shota FUJI
authored at
Shota FUJI
comitted at
28bbf5cfUse json-glib instead of Zig module
To integrate to GLib ecosystem more.
I rejected json-glib before due to poor API, but the lure of "Vala only
codebase" was too attractive. While the new codebase is quite verbose,
overall line counts are lower than the before.
Due to C API deserializing and serializing code is not readable and
error-prone. I created `JsonHelper` module to mitigate the shitty API
but it's nowhere near perfect.
These code seriously need unit tests, but that would take a while. For
now, this is good enough.
Shota FUJI
authored at
Shota FUJI
comitted at
7ad3f9fePut space after type parameter's close angle
It was so ugly and stupid but I had no idea which uncrustify property is
the culprit.
Shota FUJI
authored at
Shota FUJI
comitted at
19824f68Rename namespace "Plac.V2" to "Plac"
V1 code is no longer there.
Shota FUJI
authored at
Shota FUJI
comitted at
7bd484b9Rewrite WS connection and messaging in Vala (GLib)
The added overheads, especially cognitive overhead, had been bothering
me long time. Communicating via plain C FFI also means the Zig part has
to take care of thread-safety *outside of* GLib main-loop, which comes
with noticeable performance penalty.
By implementing (almost) everything in Vala, thread unsafety and
performance penalty caused by locking have gone. Browser navigations are
much quicker and I'm yet to see a single unresponsed request.
JSON serializing and deserializing module is the only remaining Zig
code. Although I'd much like to this part to Vala as well, JSON handling
in Vala is horrible shit so I doubt the migration will happen in a
foreseeable future.
This patch just replaces the C API (in Zig) by Vala counterpart. I did
not application restructure or refactor or whatever. Those will make
this patch more difficult to view. The only difference (regression?) is
the connection object cannot withstand WebSocket connection closing.
However, in my limited testing, libsoup seems to keep WebSocket
connection even when computer is sleeping... so the chance of
disconnection will be lower than before therefore that's not a huge
problem.
Shota FUJI
authored at
Shota FUJI
comitted at
23e3c3b1Fix constructor functions for seriealizer use uint8[] rather than string
Shota FUJI
authored at
Shota FUJI
comitted at
1f8846d0JSON API for register request and response
This got individual commit because the request needs additional change
to API builder code.
Shota FUJI
authored at
Shota FUJI
comitted at
798ecc52Create Roon request and response handle library in Zig
Vala's (GTK ecosystem's) JSON parsing is dogshit.
Although I'd like to write an entire codebase in Vala, this is necessary
to maintain readability and quality.
This commit only contains browse request/response for brevity.
Shota FUJI
authored at
Shota FUJI
comitted at
6c1c34edCreate helper class for body extracting
This does not have actual JSON parsing, as parsing JSON in Vala is
totally mess, nightmare.
The only (?) seemingly-reliable library is json-glib. Documentation is
unorganized mess as usual in GTK-related project, so it does not dismiss
the value. Extremely imperative and quite verbose API is tolerable if
it's used for rare case such as string-to-enum conversion. The problem
is the library is not well integrated GLib ecosystem, despite it being
under GLib project. It has GObject serialization and deserialization
functionality, and they are bare minimum. No array support, top-level
MUST be an object... Imperative API also is full of footgun, such as
getting a data from node in mismatching type returns "NULL" or "0"...
In addition to that, I see no mention of "null or field omit" in methods
I checked.
That may okay as a C library, but definetely does not meet a quality
required to be used in high-level languages, Vala.
Little bit cumbersome, but seriealize and deserialize in Zig via FFI is
much much much cleaner and better. Considering how widespread JSON is, I
can't recommend Vala as a sole application development language to
anyone, especially the application involves networking. For GTK
application development, Rust would be the best choice nowadays?
Shota FUJI
authored at
Shota FUJI
comitted at
e2d16abdCreate MOO metadata parser in Vala
The first and primary reason is better integration to GTK ecosystem.
GObject, GString (null-terminated strings,) GError, etc... Bridging Zig
(or any other system language with C API export) to those are tedious
and error-prone task. If the extra allocations (copy) are necessary due
to the fucking null-terminated strings, why not writing the whole logic
in Vala? The burden of bridges outweighs the ergonomics of using Zig
with copy-every-string approach.
The second reason is I wanted to see what is like to write non-GUI code
in Vala, including unit testing. It turns out really bad, because of
null-terminated fucking string and lack of converting it to/from length
specified bytes.
Shota FUJI
authored at
Shota FUJI
comitted at
2c27fac8Extract Vala compilation step to individual file
I was trying to configure unit testing for Vala, but it was too
repetitive writing same "addSystemCommand" step.
This struct style is much cleaner and self-descriptiveto.
Shota FUJI
authored at
Shota FUJI
comitted at
f0733ed4Extract new core classes to individual files
It was really difficult to read or modify code due to lack of per-file
isolation (relying on manual namespacing.)
Shota FUJI
authored at
Shota FUJI
comitted at
9dfa25f8Remove unused file
modulemap is for using C API inside Swift (Xcode?)
Shota FUJI
authored at
Shota FUJI
comitted at
52424bbaMigrate server discovery to Vala
For tighter integration and make the whole app GLib-y.
Shota FUJI
authored at
Shota FUJI
comitted at
65062858Format Vala files
It seems changes to "uncrustify.cfg" has not been read by dprint.
Temporarily set "cacheKey" then reran, now every Vala files are
formatted.
Shota FUJI
authored at
Shota FUJI
comitted at
bbf35e5bArtwork download logic in Vala
I'd like to have most of logics in GTK-style. It technically is possible
to do in Zig, but doing that in Vala is more straightforward and
requires less effort, I guess.
As a result, overall display speed massively improved.
Shota FUJI
authored at
Shota FUJI
comitted at
e10485b3Use GListView instead of GListBox
This improves rendering performance.
Although this reverts "action menu" UI, I believe this is better and
easier to use. Plac for macOS has been using this "everything is list"
style and I prefer this over the popup menu.
Shota FUJI
authored at
Shota FUJI
comitted at
bc7b89c0Merge core/ and gtk-adwaita/ directories
There are no other package using core/ anymore.
Shota FUJI
authored at
Shota FUJI
comitted at
06b251d3Remove code related to CLI
I no longer use it. Memory errors should be tested with unit tests
and/or integrated tests using mock server.
Shota FUJI
authored at
Shota FUJI
comitted at
a363d624Remove code related to macOS client
Client application for Apple devices now has dedicated repository.
https://codeberg.org/pocka/plac-for-apple-platform
Shota FUJI
authored at
Shota FUJI
comitted at
d0a4ca5aUpdate README
To reflect the latest change. I should have renamed directory name too,
though.
Shota FUJI
authored at
Shota FUJI
comitted at
af84e446macos: Direct server host/port form for non-mac platforms
Every Apple platform but macOS disallows UDP multicast/broadcast without
very special permission.
Shota FUJI
authored at
Shota FUJI
comitted at
24da2347macos: Allow connection to server without server ID
Necessary to implement host/port connection for Apple platforms, as they
are not able to perform UDP multicast without special permission.
Shota FUJI
authored at
Shota FUJI
comitted at
d8502749macos: Use "String(localized:defaultValue)" instead Text
Surprisingly, texts extracted using "Text(_ key)" does not fallback to
default language. Instead, these use localization key (e.g.,
"PlaybackBar.Play".) This will be problematic for partial translations
in a future. For some reasons, texts extracted using
"String(localized:defaultValue)" do not behave the same, so the
"defaultValue" will be used for untranslated keys.
Shota FUJI
authored at
Shota FUJI
comitted at
f3aaca67macos: Change zone picker to icon button + popover
The previous label + listbox changes its width depends on available zone
names. In addition to that, there is no enough space for the upcoming
output control button.
Shota FUJI
authored at
Shota FUJI
comitted at
39a5e90cmacos: Fix cancelling extension registration not close connection
Roon UI piles up "<extension name> (Enable)" rows everytime user cancels
then reconnects.
Shota FUJI
authored at
Shota FUJI
comitted at
49f88cc6macos: Support multi window browsing
This enables opening multiple zones in a dedicated windows at the same
time. I don't use multiple zones, though.
Shota FUJI
authored at
Shota FUJI
comitted at
825761acmacos: Workaround Xcode silently run the whole app in background
Shota FUJI
authored at
Shota FUJI
comitted at
cfc3edc0macos: Delete "Frameworks" directory
No longer used. It's empty.
Shota FUJI
authored at
Shota FUJI
comitted at
041b7f55macos: Fix suboptimal loading cancel experience
Resetting saved server connection (ID, host, port) and token is soooo
annoying. This also provides disconnection flow to error screen.
Shota FUJI
authored at
Shota FUJI
comitted at
4fa35277macos: Automatic reconnection
No retry over, but I think this is enough for this app.
Shota FUJI
authored at
Shota FUJI
comitted at
b9e19ee0macos: Select default hierarchy on visionOS
It displays as split view too. Tested on simulator.
Shota FUJI
authored at
Shota FUJI
comitted at
9881e13bmacos: Include OS name in extension name
I tested the app in various emulators but everything registered as
"Plac macOS" is sooooo confusing and unhelpful. Which should I delete?
Which one is of iOS simulator?
I should have renamed directory name ("macos") too, but it's rather big
task. I'm not gonna deal with it for the time being.
Shota FUJI
authored at
Shota FUJI
comitted at
15b90ff0macos: Remove redundant class property
The `address` is basically equivalent of the tuple in open state's
associated value. Noticed during reading of the code for state machine
redesign.
Shota FUJI
authored at
Shota FUJI
comitted at
0839a4abmacos: Group browse items by estimated item category
API does not return item kind. It does return "hint" property, but it's
useless for this purpose. For example, album items has "Play Album"
entry and song entries. Both "Play Album" and song entries have same
"action_list" hint thus they are (from program's perspective,) same.
This simple heuristic I wrote, at least for my usage, correctly group
items most of the time. I may tweak the logic in a future, but it's good
enough for now.
Shota FUJI
authored at
Shota FUJI
comitted at
7a551a5amacos: Fix junky title animation between navigations
iOS/iPad OS runs an animate when a navigation stack changes.
This is especially significant on iPad, which performs scale in addition
to translation. Previous to this patch, navigating to a page triggers
junky layout change (whole list moves upwards after 300ms or so.)
Shota FUJI
authored at
Shota FUJI
comitted at
44ff5579macos: Smoother browsing action
Previous experience was like,
1) Tap an action
2) Navigate to a new stack
3) Immediately navigate back to the previous stack
As most of the browse action do not lead to a new stack,
I added a dedicated logic to handle browse action.
Shota FUJI
authored at
Shota FUJI
comitted at
5e233c43macos: Browsing preview
Although action (server-side pop) behavior is strange, it's okay for now
as I'm going to tidy navigations up later.
Shota FUJI
authored at
Shota FUJI
comitted at
99342ff9macos: Refactor top-level files
Those files were obscure and one had to open the files in order to find
what's inside (view? helpers? models?)
Now, those are nicely organized so no need to open each files to figure
out the category of the file.
Shota FUJI
authored at
Shota FUJI
comitted at
b2454bafmacos: Seekbar
It's waaaaaaay better than GTK-Adwaita app, thanks to sane API design.
I mean, inclusion of events for start/end of edit.
Shota FUJI
authored at
Shota FUJI
comitted at
62d7639dmacos: Insert marker comments into large files
These service files defines Roon API types, therefore they tend to grow
larger and are difficult to decompose.
Shota FUJI
authored at
Shota FUJI
comitted at
dd6e1534macos: Reconfigure preview for PlaybackBar view
TIL "MARK:" comment support for Xcode.
Shota FUJI
authored at
Shota FUJI
comitted at
d8414c2emacos: Use protocols to untie IO from UI code
For testability.
Shota FUJI
authored at
Shota FUJI
comitted at
87a170f9macos: Implement core logic in Swift
Managing long-live object and handling IO in C API was mistake.
Every Zig/Swift nicities are eliminated at C API boundary. It must be
stupid make/free (or retain/release) function calls and they always have
to be heap allocoated using cAllocator. Everything has to be thread-safe
by using manual reference counting. Good practices in each languages are
no longer available due to C API barrier.
Although I had to duplicated Roon API handling logic, I believe this
work is worth the added code. IO and concurrent things are done in a
Swift-y way, avoiding small heap allocations are now easier (I guess
it's already less than the previous?), and most importantly, I have
deeper understandings of Swift and Apple frameworks than before.
UI layer code is way cleaner than the before. Especially watching
incoming message is very ergnomic--I can just iterate on `compactMap`-ed
async iterator, as you can see in "plac/DataModel/ZoneDataModel.swift".
As a bonus, every async task now handles cancellation (e.g. closing
window) perfectly.
In terms of performance, I don't think there is any regression.
Moreover, I feel this rewrite version performs better. Not profiled
(I've never profiled Plac macOS app...) but playback control actions are
instant without any UI stutter. Considering it now uses more high-level
API provided by Apple, this rewrite should improve stability and
portability.
Despite of these good things, there is one I'm not satisfied
with--message parsing (MOO / SOOD.) Swift does not have a good
reader/writer interface unlike Zig. The closest thing is SwiftNIO's
`ByteBuffer`, but I avoided it to keep dependence to third-party
libraries lower (the repository is in Apple org, though.) I've
considered using Zig code for that part or write a dedicated C module
using Wuffs but abandoned the ideas too, because of Xcode signing
gotchas (ugh.)
Speaking of Xcode signing, the app now works on iOS simulator. It
probably won't work on real device due to multicast entitlement, but
this is huge advancement. Some entry point tweaks are necessary, like UI
for entering IP/port of Roon server. Revising suspension and resume is
also necessary. Not ready to use, but this is great starting point.
Overall, I'm satisfied the result and enjoyed this whole learning process.
Shota FUJI
authored at
Shota FUJI
comitted at
92b7d54fcore: C API for getting image URL
SwiftUI has AsyncImage view, which takes a URL.
Shota FUJI
authored at
Shota FUJI
comitted at
4cafdb7fmacos: Use Environment for passing connection down
Future views such as artwork requires connection, but passing a
connection down to each view via initializer is tedious.
Shota FUJI
authored at
Shota FUJI
comitted at
4570e084macos: Disconnect menu items
In GTK-Adwaita, it's easy thanks to "gsettings" CLI application. In
macOS, however, there seems to no way to clear an application's
"@AppStorage" data.
Shota FUJI
authored at
Shota FUJI
comitted at
cf516079macos: Accept Xcode project settings recommendation
It has been showing a warning and it was annoying.
Shota FUJI
authored at
Shota FUJI
comitted at
1dd7aab4macos: Change non-modified variable to immutable
Addressed a Xcode warning.
Shota FUJI
authored at
Shota FUJI
comitted at
afb2d6b4macos: Merge server discovery and main window
The former is (most of the case) shown once.
The reason I changed the payload of ".found" case is, without that, the
only reference will be "ConnectedView" and every updates to the View
would release then re-create a connection.
Shota FUJI
authored at
Shota FUJI
comitted at
d53ccec3macos: Save connected server ID and reconnect on launch
The current UX is not complete, as there is no way to disconnect.
Considering the usecase of connecting to more than one Roon server is
rare, the discovery window should be integrated into the main window.
Then it can conditionally render server discovery or connected view
without going to discovery view first.
Shota FUJI
authored at
Shota FUJI
comitted at
37c16ed0core: Allow clients to set custom extension ID/name/version
It has been pain to manage authorization tokens in Roon settings page.
Shota FUJI
authored at
Shota FUJI
comitted at
dfc4cec0macos: Display loading UI during extension authorization
It has been unclear what it's doing and what a user should do.
Shota FUJI
authored at
Shota FUJI
comitted at
8b8802c2macos: Display now playing texts (title and artist, mostly)
Shota FUJI
authored at
Shota FUJI
comitted at
9e6bf7bfmacos: Fix more than one element in array crashes application
I don't know how I got to that iteration code, but the
`UnsafePointer<T>.successor` is NOT a method to iterate over an array.
<https://codeberg.org/pocka/plac/issues/17>
Shota FUJI
authored at
Shota FUJI
comitted at
065d06d6core: Print debug log on macOS build
Ideally, integrating OSLog is the best. However, it's time-consuming and
a lot of work needs to be done. This is good for now.
Shota FUJI
authored at
Shota FUJI
comitted at
8fdfb08dgtk-adwaita: Remove "develop build" style from window
Even though there is some missing features (search and disconnect menu
option,) it's usable for my day-to-day usage. Now all concurrency and
memory bugs are fixed, this is the best timing to remove WIP label.
Shota FUJI
authored at
Shota FUJI
comitted at
5ed1b013core: Give WS read and event handlers dedicated threads
<https://codeberg.org/pocka/plac/issues/16>
Parsing and handling incoming message in the same thread that reads
WebSocket message from socket sometime drops WebSocket message, due to
the thread being busy. This redesign solves that by separating reading
and parsing/handling using dedicated threads.
Although volume change operation now feels little bit sluggish, no more
dropped response. Every operation is working correctly.
Shota FUJI
authored at
Shota FUJI
comitted at
12dfcdb9core: Fix potential race condition
Extremely rare, though (I saw only once.)
Shota FUJI
authored at
Shota FUJI
comitted at
03235177core: Output request ID on control request send log
"/control" endpoint suffers response loss as well as "/change_volume"
endpoint. Request ID helps debugging this, because it's visible on data
payload in Wireshark.
Shota FUJI
authored at
Shota FUJI
comitted at
05a6f716gtk-adwaita: Volume controls
While "it works," user experience is not great. For some reason,
response for "/change_volume" got lost even though my machine sees a TCP
packet. I also see this at "/control" endpoint too. However, "/seek"
endpoint, which is called more frequently, does not encounter this.
Most likely application problem given my experience on low-level
programming, but it could be packet issue (Roon Server) or transport
layer issue (websocket.zig or Linux?) I don't know, really.
Shota FUJI
authored at
Shota FUJI
comitted at
ba20af71gtk-adwaita: Connect to server directly via IP address and port
UDP multicast/broadcast is unreliable, especially in my environment
where Roon server (or the machine hosting it) randomly stops responding
to discovery query. Direct connection is really instant and I believe
this would improve normal UX too.
Shota FUJI
authored at
Shota FUJI
comitted at
4b536649core: Function to discovery server by IP address
Roon Server or my server machine reject replying to UDP
multicast/broadcast after several attempts. This functionality can be a
good way to avoid UDP multicast and broadcast issues.
Shota FUJI
authored at
Shota FUJI
comitted at
117a5ffagtk-adwaita: Fix "Zone" dropdown button stretched vertically
Shota FUJI
authored at
Shota FUJI
comitted at
e0f94d58gtk-adwaita: Fix duplicated requests sent after reconnection
<https://codeberg.org/pocka/plac/issues/13>
Establishing a new connection registers a new callback to various
signals without disconnecting stale ones, thus 1+(number of
reconnections) requests have been made.
Shota FUJI
authored at
Shota FUJI
comitted at
9de7aad5gtk-adwaita: Make playback toolbar layout tidier
It has been unorgnaized and scattered due to unaligned elements and
chaotic spacings.
Shota FUJI
authored at
Shota FUJI
comitted at
2fa47b61gtk-adwaita: Fix playback toolbar size changes depends on track text
If a track A contains non-Ascii text in title/subtitle and a track B
does not, changing A to B or vice-versa causes height change for
playback toolbar. This is because GTK.Label does not implement correct
line-height handling, as it seems to simply calculate the height using
the first font family and ignoring fallback fonts. Due to the lack of
proper API on GTK (propbably also on Pango,) I opted to hard-code
maximum size on each Gtk.Label.
<https://codeberg.org/pocka/plac/issues/9>
Shota FUJI
authored at
Shota FUJI
comitted at
b6093bebcore: Fix random crash on opening a page having images
This patch fixes random crash caused by race condition (use after free
and unexplainable memory errors such as malloc in glib,) by properly
guarding accesses to image download queue.
Inside `while` loop reading the downloads queue, it read without lock
and that caused reading of freed memory (`d == undefined`), thus
operations like `d.data.arc.ref()` and `allocator.destroy(d)` to be
invalid.
Because the race condition occurs on downloads queue, opening browse
page with massive items (200~) has been crashed the app frequently
compared to small number of items (~50). Also, longer the image takes to
load, more likely the crash to happens. So streaming service's browse
page is more prone to crash than local library.
With this change, I don't see random crash on Qobuz pages anymore.
In addition, for some mysterious reason, images load faster than before.
Definetely previous implementation did something wrong, as adding a lock
does not make things faster but slower...
<https://codeberg.org/pocka/plac/issues/15>
Shota FUJI
authored at
Shota FUJI
comitted at
3e838e95gtk-adwaita: Buttons to seek forward/backwards by 10 seconds
Seekbar is not comfortable to use.
Why 10 seconds, not 5 seconds? Because Adwaita has icons for 10 seconds
but 5 seconds.
Shota FUJI
authored at
Shota FUJI
comitted at
412d59f0gtk-adwaita: Fix cannot drag seekbar
<https://codeberg.org/pocka/plac/issues/14>
This is still not optimal, though. Ideally changes should debounce or
throttle to reduce the number of request. But this works without
crashing.
Shota FUJI
authored at
Shota FUJI
comitted at
9b107f4agtk-adwaita: Workaround for Roon API returns "[[id|text]]" labels
Shota FUJI
authored at
Shota FUJI
comitted at
e54e5874core: Label parsing function
Roon API returns "[[id|text]]" format strings for title and subtitles on
some browse paths. For example, in my environment, "Explore > Qobuz >
New Releases > Qobuz grand selection" returns items with subtitle in
this format, like "[[969850|Wes Montgomery]]". I don't think we'll get a
fix for this--Roon API is abandoned. Each client has to parse and throw
IDs and brackets away.
Shota FUJI
authored at
Shota FUJI
comitted at
63589eaagtk-adwaita: Remove useless function call
Also Vala compiler has been emitting a warning that the variable is
unused.
Shota FUJI
authored at
Shota FUJI
comitted at
cf275126gtk-adwaita: Fix space between rows react to clicks
<https://codeberg.org/pocka/plac/issues/5>
The bug was inside GTK4, and there seems no way to workaround from
application developer side. I was not happy about aesthetic of the
previous cards list, I simply changed the custom rows to regular one.
Shota FUJI
authored at
Shota FUJI
comitted at
26b2df71core: Fix segfault on opening "Track" page with release builds
The "node" inside while loop is a reference to the other thread's stack
variable, and there is no mechanism to block a creator function from
exiting. Since blocking a creator function could lead to unpleasing UX
(images at beginnings load slowly compared to later images,) I simply
changed the code to allocate nodes on heap and added RC.
Shota FUJI
authored at
Shota FUJI
comitted at
8a05c1ceInstall code formatter for Nix
Amount of Nix code is no longer little.
Shota FUJI
authored at
Shota FUJI
comitted at
5949d43cgtk-adwaita: Fix browse error locks browse UI into disabled state
Shota FUJI
authored at
Shota FUJI
comitted at
90a7baf9gtk-adwaita: Don't render non-actionable item as actionable
Shota FUJI
authored at
Shota FUJI
comitted at
d497c6aagtk-adwaita: Don't scroll after selecting/closing action menu popover
It's annoying.
Shota FUJI
authored at
Shota FUJI
comitted at
1683e5fdgtk-adwaita: Render action list as menu button
It was hard-to-grasp albeit not usable.
Shota FUJI
authored at
Shota FUJI
comitted at
70c1f75ecore: Cache downloaded images
Navigating through library pages (e.g. albums, artists) fetches same
images over and over. In order to reduce load to Roon Server, I added
stupid simple caching in front of image downloader. This significantly
reduces HTTP GET calls on my library, especially "Tracks" page.
The caching does almost nothing on Qobuz pages, though. In my testing,
Qobuz images takes more time to load and only playlists have lot of
duplicated images. Because of those, the existing "reuse ongoing GET
request" mechanism eliminates duplicated GETs thus almost all of
requests are unique. I don't believe this can be improved—nobody but
Qobuz (perhaps Roon too?) can control, optimize, and estimate data
appearance pattern on Qobuz pages.
This cache implementation does not look great, but it works well.
Shota FUJI
authored at
Shota FUJI
comitted at
bcf2497dcore: Download image using normal HTTP instead of WebSocket
Downloading large number of images through WebSocket easily clogs
connection and affects sending of other actions (e.g. playback control)
and receiving of events. By using normal HTTP via separate connection,
this no longer happens.
This patch finally enables me to open "Explore > Library Tracks" page.
Shota FUJI
authored at
Shota FUJI
comitted at
a6d963afcore: Relax timeouts
It was too short. Especially browse APIs frequently timed-out on Qobuz
pages.
Shota FUJI
authored at
Shota FUJI
comitted at
9fc84020core: Limit number of concurrent image downloads
To prevent server from choked. Unfortunately, due to high duplication,
"Library > Tracks" still timeouts and renders app unresponsive.
Shota FUJI
authored at
Shota FUJI
comitted at
7f2d5aebgtk-adwaita: Seek feature
GTK4's slider/range widget is shitty, thus this feature works shitty as
well. There are no "drag ended" equivalent signal and drag start emits
JUMP scroll type value change signal. Also, setting `false` to
`sensitive` resets focus so long jump using keyboard is impossible too.
Debouncing or throttling would help a little bit, but won't solve the
problem fundamentally. Seek change events sent by server would resets
drag operation.
Valadoc shows no result for "throttle/debounce" and GTK4 seems to have
no function and widget for that. Implementing debounce/throttle function
by hand, testing that, and adding additional delay to seek triggered
by seek is not acceptable given those won't work when a track is playing.
The only way to solve this is implementing custom widget, which means
re-implementing slider UI from scratch or carefully patching and
workarounding GtkRange's internal implementation. Both are
time-consuming, exhausting, negatively effects maintainability, and
stupid.
GTK4's rendered widget is great. Its API and abstraction are dogshit.
Shota FUJI
authored at
Shota FUJI
comitted at
c5b9431dgtk-adwaita: Automatic reconnection on server close
*Not tested*
Testing against Roon Server is really frustrating task.
Shota FUJI
authored at
Shota FUJI
comitted at
1a88a96ccore: Refactor to use constant defined in std
Did not notice the constant at the time of writing the logic.
Shota FUJI
authored at
Shota FUJI
comitted at
8116f858core: Do not send duplicated request for image downloads
Previously there were multiple requests made to the same image_key and
options pair. This is problematic on opening "Library > Tracks", because
the page has a lot of same images.
Shota FUJI
authored at
Shota FUJI
comitted at
94edd150gtk-adwaita: Remove browse items' angle icon from AT
It's just for presentation. To be honest, I have no idea what to label
it. "Arrow indicating next navigation"?
Shota FUJI
authored at
Shota FUJI
comitted at
659b1c11gtk-adwaita: Remove artwork from accessibility tree
I have no control over the image. Announcing it as "artwork of <track>"
does not bring new information.
Shota FUJI
authored at
Shota FUJI
comitted at
dad9c096core: Rename service modules
Names are not best (they are CamelCase instead of snake_case) but one
level less nesting is good enough for now.
Shota FUJI
authored at
Shota FUJI
comitted at
e23a985ccore: Upgrade libmoo (u64 request_id migration)
libmoo previously used i64 for request_id. While Roon server accepts
requests with i64 request_id, having negative number IDs looks weird.
Also, the current implementation starts from 0 thus half of the space
has been remaining unused. Using u64 for request_id just has pros.
Shota FUJI
authored at
Shota FUJI
comitted at
ca23543agtk-adwaita: Scroll to top on browser navigation
Although not ideal, better than restoring to nonsensical position.
Shota FUJI
authored at
Shota FUJI
comitted at
13eb02e0gtk-adwaita: Remove AppImage build
Built AppImage won't launch.
Shota FUJI
authored at
Shota FUJI
comitted at
5f1a9e50gtk-adwaita: build step for AppImage (broken)
While the step produces `Plac.AppImage`, built file does not run with
this error:
```
./zig-out/Plac.AppImage: error while loading shared libraries: libharfbuzz.so.0: cannot open shared object file: No such file or directory
```
harfbuzz is installed but AppImage can't load the non-bundled library.
I have no idea where is the problem: it could be Zig compiler, Nix,
linuxdeploy, or my environment. AppImage docs is pretty shallow and
scattered, recommended tools are questionable quality, but most
importantly, the whole concept seems not to work well with Nix.
Even if the underlying problem will be solved, this won't be in the
repository. Given many errors and quirks I've seen at this point, I
don't think it'll work in others' environments. Although it's not user
friendly, running `nix develop && zig build run` is way better than
CMake or Bazel or `configure` or whatever.
I'm going to put this commit in trunk as build scripts and newly added
files are useful for non-AppImage builds.
Shota FUJI
authored at
Shota FUJI
comitted at
d49fc523gtk-adwaita: Add app icon
Required for generating an AppImage file.
Shota FUJI
authored at
Shota FUJI
comitted at
9cde9cafgtk-adwaita: Suppress deprecation warnings from Vala compiler
See code comment for rationale.
Shota FUJI
authored at
Shota FUJI
comitted at
b6090f98gtk-adwaita: Remove unhelpful debug log
These lines were added to debug a particular problem, which has been
solved. As "what was changed" is unclear from log text, these are not
useful and are simply noise.
Shota FUJI
authored at
Shota FUJI
comitted at
81995d12core: Remove unnecessary internal slice fields
Those were there for easy access and release. However, manually
reconstructing a slice from a pointer (and a length) is not tedious or
difficult. 8 bytes to 24 bytes reduction per objects.
Shota FUJI
authored at
Shota FUJI
comitted at
fb7617abgtk-adwaita: Prevent navigations during relavant request
To avoid messing up Roon's server-side state management.
Clients have to carefuly mutate server-side state, fuck.
Shota FUJI
authored at
Shota FUJI
comitted at
c8a39931gtk-adwaita: Disable playback control during request
To prevent excess requests and such.
Shota FUJI
authored at
Shota FUJI
comitted at
8ac3a8fccore: Wait for control response
Responses have been logged as unhandled message at warning level.
Shota FUJI
authored at
Shota FUJI
comitted at
a621bc3agtk-adwaita: Fix connection error banner triggers warnings
Whenever connection error happens, GTK emits quite a few errors like:
```
Gtk-WARNING **: 10:28:43.818: Widget reports min height of 103 for width of 509, but min width of 184 for height of 46
```
where each numbers slightly varies between log lines. Instead of
addressing this stupid and cryptic warning, I choose to avoid the whole
layout shenanigans by overlaying the banner.
I feel how Flexbox is great nowadays.
Shota FUJI
authored at
Shota FUJI
comitted at
6bc46b51core: Fix non-small WebSocket response cause panic
websocket.zig has small max-size, and it was the culprit for GTK-Adwaita
app crashing on opening "Library > Tracks".
Shota FUJI
authored at
Shota FUJI
comitted at
627938aecli: Display image_key property of an album
This information is required for upcoming "image" command.
Shota FUJI
authored at
Shota FUJI
comitted at
f29f08c8gtk-adwaita: Add `run` step
It's vastly simpler than manually invoking schema complication and
specifying an output path of the step.
Shota FUJI
authored at
Shota FUJI
comitted at
c873534egtk-adwaita: Change browser background color
Why did I set the whole browser pane to "view" instead of making
"ListBox"'s "background"? I don't know.
Shota FUJI
authored at
Shota FUJI
comitted at
442a666dgtk-adwaita: Shrink browser title font size
It standed out too much.
The added margins are necessary for maintaining line-height when a back
button is absent.
Shota FUJI
authored at
Shota FUJI
comitted at
99f09410gtk-adwaita: Fix window can't be narrow
like 320px. GTK by default displays texts without wrapping thus the
loading message sets minimum window size to its length.
Shota FUJI
authored at
Shota FUJI
comitted at
7612e6b0gtk-adwaita: Browse view
It's not complete: crashes on large items (e.g. Library > Tracks),
everything is styled as list navigation, non "list" responses are
ignored, etc.
But it does the job. I have many things to do such as handling
connection close by server and implementing application menu.
Shota FUJI
authored at
Shota FUJI
comitted at
fdeba4e2cli: Albums command
To check memory errors for the browse module.
The new `disconnect` method in core is, for now, used only by CLI.
This command found a memory leak due connection module to forget
retaining a `browse.Result` struct to be returned. This would not be
obvious in GTK-Adwaita app, given how noisy Valgrind log because of
GTK/GLib things leak stuffs even with supp files.
Shota FUJI
authored at
Shota FUJI
comitted at
cf742d30core: Broadcast discovery query as well
I don't know which Roon's software or my network settings is the
problem though, discovery will be flaky randomly. Hope this improves.
Shota FUJI
authored at
Shota FUJI
comitted at
1a1e713bcore: Conditionally output memory release log
It's overwhelming for daily use.
Shota FUJI
authored at
Shota FUJI
comitted at
ea54f0fbgtk-adwaita: Reset seekbar to start when playback is empty
Previously, switching from playing zone to completely stopped (no queue
item) zone kept seekbar position. It was confusing.
Shota FUJI
authored at
Shota FUJI
comitted at
b2e3c347core: Fix event parsing error on playback complete
For some mysterious reason, Roon sends seek_change event without
seek_position field, even though it sets `null` on other occasion.
That has been causing MissingField error and that was the reason
playback complete not updating playback toolbar on GTK adwaita app.
Shota FUJI
authored at
Shota FUJI
comitted at
424d58b0core: Fix event parse error on prev-ing at last of queue
For some reason, prev-ing at the last of a queue sends seek_change event
with seek_position being null. That causes UnexpectedToken error on JSON
parsing.
Shota FUJI
authored at
Shota FUJI
comitted at
87e78be8core: Parse allowed actions for a zone
Required for playback controls.
Shota FUJI
authored at
Shota FUJI
comitted at
d6154cfdcore: Fix GLib error log terminates application
GLib's error level log terminates application, even though the function
is logging one and nothing says error is fatal to application. This
bullshit design is the root cause of app crashes when server closed a
connection.
Shota FUJI
authored at
Shota FUJI
comitted at
f0f5f054cli: Remove memcheck option
Most of the time I run cli, it's for checking memory leaks.
There is no usecase for disabling memcheck option.
Shota FUJI
authored at
Shota FUJI
comitted at
58c2a848cli: Switch to new core
I once considered removing "cli" together, but it's very useful at
debugging memory leaks and such.
Shota FUJI
authored at
Shota FUJI
comitted at
047caaf8core: Switch to Atomic Reference Counting
I don't know how to trigger access error on non-atomic variant though.
Shota FUJI
authored at
Shota FUJI
comitted at
63e467c0gtk-adwaita/core: Extract core logic to dedicated package
I found out this logic for Gtk-Adwaita can be used naturally in Swift.
Shota FUJI
authored at
Shota FUJI
comitted at
357690b0Rename "core" to "old_core"
I'd like to rewrite it from scratch but existing usage prevents that.
Shota FUJI
authored at
Shota FUJI
comitted at
f8d353fcgtk-adwaita: per app core instead of shared core
Writing a library that is comfortable to use both in Vala and in Swift
is really challenging. That makes library pretty C-ish, I mean barebone
manual memory management which is hard to use, design and implement.
By having dedicated Zig modules and extracting shared logic as a Zig
module instead of C library, development speed and application quality
will be improved thanks to more ergnomic API and natural memory
management (reference counting).
This commit does not include that "shared logic" part, because I have no
idea how macos/ part will go on.
Although the number of allocation massively increased due to heavy copy,
chance of memory leak or invalid writes (double-free, use-after-free)
is significantly lower compared to my previous shitty implementation.
Shota FUJI
authored at
Shota FUJI
comitted at
6d1b49caMigrate from devbox to Nix Flake
Turns out, versioned package manager powered by Nix, won't work.
Many libraries, especially runtime dependencies, suffers from duplicated
packages and application crashes with cryptic error messages.
Shota FUJI
authored at
Shota FUJI
comitted at
422c9306gtk-adwaita: Style zone list like menu
When navigating using keyboard, closing popover does not reset selection
state thus UI goes incorrect state where inactive row can be displayed
as active. However, I'm not going to spend times on details:
functionality first.
Shota FUJI
authored at
Shota FUJI
comitted at
3b7f83e8gtk-adwaita: Zone selection
Now user can switch zone to show in UI.
Shota FUJI
authored at
Shota FUJI
comitted at
4c605385gtk-adwaita: Fix closing on server selector doesn't exit application
Shota FUJI
authored at
Shota FUJI
comitted at
25cd076dcore: Use thread pool so every threads will be closed
Unterminated threads were noise on Valgrind.
Shota FUJI
authored at
Shota FUJI
comitted at
a6de2c9ecore: Fix size of struct containing `usize` being incorrect
Shota FUJI
authored at
Shota FUJI
comitted at
36158e3dgtk-adwaita: List zones and show playback state of the first one
UI is shitty but it at least demonstrates zone fetching functionality.
Shota FUJI
authored at
Shota FUJI
comitted at
e9531b48core/gtk-adwaita: Export mutex API
The initial plan was to complete every actions inside callbacks.
However, most UI libraries/frameworks requires main thread for accessing
UI. That means, state could be changed during the UI operation because
it's outside the callback's mutex locking.
Shota FUJI
authored at
Shota FUJI
comitted at
9ed3f8f9gtk-adwaita: Access GTK only from main thread
App was flaky due to off-thread accesses.
Shota FUJI
authored at
Shota FUJI
comitted at
1aa6eb97core: Disarm function should take context/user data too
Since functions are static and what makes "function for this context" is
a context pointer, disarm functions too have to take that.
Shota FUJI
authored at
Shota FUJI
comitted at
4b14946cDo not use swift-format@5.8
I thought it works okay even for Swift 6 source code given Swift 6
announcement post and various posts do not list syntax changes. They
seem to be "docs does not matter, we have migration tool!" people.
Somehow swift-format@5.8 rejects valid function call (in my case, it was
struct initializer) and if I commented the relavant section, it messed
code so badly that I had to "fix" every unnecessary stupid newlines.
Until nixpkgs or Swift team fixes build pipeline, I have to manually
invoke the latest swift-format via XCode. fuck.
Shota FUJI
authored at
Shota FUJI
comitted at
8a172f02gtk-adwaita: Save and restore connection
It's extremely flaky due to thread unsafety... I have to organize
callbacks sure.
Shota FUJI
authored at
Shota FUJI
comitted at
9435612bcore: Save connection state to a file
Previously I thought each apps having platform specific save logic would
be better than implementing it in the core. However, Vala has no simple
way to do that (had to import various GLib things). Apparently every
platform I plan to implement uses file system for state files, thus
implementing in the core is safe as long as it takes full file path.
Shota FUJI
authored at
Shota FUJI
comitted at
5dc2caa9core: Comment on why `scan_result` is not deinit-ed
I thought it's confusing during refactoring.
Shota FUJI
authored at
Shota FUJI
comitted at
6755b30bcore: Adhere init/deinit to guideline
This makes "who manages this memory" more obvious.
Shota FUJI
authored at
Shota FUJI
comitted at
8b399348core: Docs for code style
This is solo development project but I'm already confused due to
inconsistency. As there is no general Zig guidelines, I had to make a
one for this project.
For brevity, this commit does not touch Zig source code. This merely
creates a guideline.
Shota FUJI
authored at
Shota FUJI
comitted at
96637ddbgtk-adwaita: Migrate to the new Core API
This commit includes changes to Core: debug logging and fixing array of
structure to array of pointer for structure.
Although client code got simpler, I'm not sure accessing GTK from
callback function is okay. For now, every callbacks are invoked from
spawned thread and this means accessing GTK from non-UI thread.
Additional async-ing in Vala side might be necessary?
Shota FUJI
authored at
Shota FUJI
comitted at
43a74204core: Migrate to callback design
Forcing callers to take care of threads turned out a bad idea. That
requires core to be extremely simple, durable, and thread-safe. By
making majority of core's functionality threaded, clients do not have to
take a look inside to see whether a field is thread-safe or not.
Shota FUJI
authored at
Shota FUJI
comitted at
ebb7ce2egtk-adwaita: Fix runtime library error on macOS
libadwaita depends on gtk4 but devbox cannot resolve to same package as
the root one, so there are duplicated "gtk4" package therefore symbol
duplication error happens. I have no idea why this is not a problem on
Linux, though.
Shota FUJI
authored at
Shota FUJI
comitted at
ed3b9ab8gtk-adwaita: Init core app
I have no idea what to do next.
Flux-like state-action API? Simple struct with state properties and
callback functions like GObject? Completely lost.
Shota FUJI
authored at
Shota FUJI
comitted at
4f914150core/cli: Register extension to Roon
Code is messy. Logs should be proper logs not debug one.
Few places leaks memory. WebSocket read timeout should be configurable.
CLI should also store IP address and TCP port. Error handling is
nonexistent.
However, it works (TM). And if I optimize or tidy I/F up at this point,
there is high chance of the resulted code would be difficult to use.
Tidying I/F by seeing only one implementation (in this case, CLI) brings
other client hard time integrating. This project's main focus is native
GUI clients, not CLI. Thus, I should refactor/optimize at the time of
writing GTK or SwiftUI code. Let it evolve from worse state.
Shota FUJI
authored at
Shota FUJI
comitted at
190d510dcore: Move server discovery code to "server/" dir
I could not put playback related functionality to "lib.h" safely.
Shota FUJI
authored at
Shota FUJI
comitted at
dc5a9a93gtk-adwaita: Server discovery error handling
Loading is still work-in-progress, but error handling is okay.
There must be better way to disconnect a signal (error_detail_hid)
though.
Shota FUJI
authored at
Shota FUJI
comitted at
9423b7c4gtk-adwaita: Rename from "gtk"
I'm not going to do "pure GTK", as the primary reason to use GTK is
creating native looking GUI. If I freely build styles using GTK
components, it would then look alien due to web-by styles.
Shota FUJI
authored at
Shota FUJI
comitted at
fdd1d11acore: Find Roon Server by unique ID
Except the very initial setup, clients have previously connected
Server's unique ID. There is virtually no reason to perform enumerate
servers on a network in that case.
Shota FUJI
authored at
Shota FUJI
comitted at
488e6c8ccore/cli: Drop Zig API
The primary purpose of cli is to test C API. However, Zig's ideal API
design and one of C API is drastically different (esp. allocation), and
that makes designing C API difficult. This simplifies the process and
hopefully brings better C API with less memory mis-managements.
Shota FUJI
authored at
Shota FUJI
comitted at
38f47e6ccore: Fix memory access violation on macos app
I forgot C enum is platform int. No idea why this wasn't a problem on
Vala, though.
Shota FUJI
authored at
Shota FUJI
comitted at
627429dacore/macos: Import core from macos
https://mitchellh.com/writing/zig-and-swiftui
This blog post hugely helped me writing build scripts... I could not do
this without that blog post.
Shota FUJI
authored at
Shota FUJI
comitted at
e92280edRemove vala-language-server from tool installation
It requires Meson (no way) or Clang's `compile_commands.json` to
understand dependencies. While the latter looks simple, I'm not willing
to maintain duplicated compile command. If bug or unconvenience or
frustration or whatever reaches certain threshold, I'll reconsider
re-introducing the LS.
Shota FUJI
authored at
Shota FUJI
comitted at
7a323e0egtk: Display scanned Roon Servers
No empty state, no error handling, though.
Shota FUJI
authored at
Shota FUJI
comitted at
ff30d4c7core: Fix build fails on macOS
Interestingly, Zig smartly assigns `u31` as the type of `usec`.
```zig
@compileLog(@typeName(@TypeOf(usec)));
```
yields,
```
@as(*const [3:0]u8, "u31")
```
Shota FUJI
authored at
Shota FUJI
comitted at
647bb5b2Don't install Valgrind on macOS
It's marked as broken on darwin, despite search.nixos.org lists darwin
platforms at "Platforms" section.
Shota FUJI
authored at
Shota FUJI
comitted at
a079c8cdcore: Simpler memory management for "Server"
Although this increases memory allocation, API is simple and easier to
build C API.
Shota FUJI
authored at
Shota FUJI
comitted at
eefc813dgtk: Build GTK app using Zig build system
It's convenient, consistent, and reliable.
Goodbye, system CC's bullshit warnings.
Shota FUJI
authored at
Shota FUJI
comitted at
62d9a8b8cli: JSONL output for "server ls"
```
./zig-out/bin/plac server ls -f jsonl | jq
```
Shota FUJI
authored at
Shota FUJI
comitted at
9fc8db70core: Set HTTP port to ip_addr field
Having separate HTTP port and keeping UDP source port is wasteful and
not user friendly.
Shota FUJI
authored at
Shota FUJI
comitted at
9498d876cli: Improve memory debuggability
Now DebugAllocator can detect memory leaks.
Shota FUJI
authored at
Shota FUJI
comitted at
995d035ecore: Fix server list not deduped due to double free
```
valgrind --leak-check=full --show-leak-kinds=all --track-origins=yes --num-callers=15 -s ./zig-out/bin/plac server ls -c 10
```
When a same Roon Server responds more than one time, servers hashmap
gets corrupted entry due to having a free-d key.
Shota FUJI
authored at
Shota FUJI
comitted at
ce738568cli: Replace "calloc" build option with "memcheck" option
For more enriched debugging. Valgrind is super useful but Zig's
DebugAllocator displays more friendly message. It does not catch all
errors so Valgrind is still necessary.
Shota FUJI
authored at
Shota FUJI
comitted at
621870cdgtk: Fix build error on macOS
```
error: Failed to execute child process “pkg-config” (No such file or directory)
```
Shota FUJI
authored at
Shota FUJI
comitted at
5260c3begtk: GTK4 application project setup
I still have no idea how "libadwaita" alone supplies required
dependencies such as pango and glib. Without that, even adding those to
"packages" section, ld complains files are missing.
Ghostty has "libadwaita" and "gtk4" as dependencies for GTK4 so I
simply did the same.
Shota FUJI
authored at
Shota FUJI
comitted at
f11a7f77Manage tools using Devbox rather than mise-en-place/asdf
Vala, a programming language often(?) used in GTK world, is missing from
mise/asdf registries. I've been feeling itches while using mise/asdf due
to lack of packages. For example, REUSE tool, which I use for most of my
recent projects, does not exist in their registries.
I choose Devbox among the three options:
* devenv
* Nix Flake (without helper tools)
* Devbox
## devenv
This is the first tool I tried. Their website looks good, features
sounds good, and sample Nix file looks okay. Their getting started guide
starts with "devenv init", which creates not only their config file but
touches other toolings' files (`.gitignore` and `.envrc`). "init"
command without manual setup step, especially touching others' files is
big sign of shitty tooling design, but I continued hoping other parts
would be "okay". Unfortunately they weren't.
CLI "search" command emits hundres of warnings, and outputs table does not
check terminal width so it badly wraps and border characters gets in a way
that the output is nearly unreadable.
When I ran its shell command, it paused the execution with a warning
message about binary cache. So devenv by default uses creator's own paid
SaaS? I don't think just using devenv requires paid subscription, but
unclear writing and CLI tries to push Cachix service into users' Nix
config is no-no for me.
The tool seems to be a thin wrapper around Nix: it inherits some of
upstream's bad designs (e.g. absolutely worst error trace, "nix develop"
invokes "bash" regardless of the current shell).
Their website advertise "Version support." but very few selected
packages have that. Everything else relies on Nix's "use latest or die"
versioning schema. Considering devenv's "Language support" is just
import helpers for nixpkgs, this "Version support." feels like a false
advertising.
Half-baked YAML/Nix architecture prevents users from using overlays or
other flakes with "follows" input to reduce duplications. And using
Flake requires running Flake command ("nix develop --no-pure-eval")
instead of their CLI, which completely dismissed the value of their tool
for me. Also reading their docs are uncomfortable given the tool is not
good quality one:
> Many experienced Nix users prefer to use Nix flakes, although devenv
> is considered a superior interface since it's way simpler, but lacks
> integration with existing tooling.
Superior, huh?
There are still features not present in bare Nix/Flake, but I find those
scripts/tasks/tests not useful. If every developer has access to same
toolchains, why not simply write script? (JS or Python or Go or whatever)
Overall, I see no benefits over bare Nix/Flake or mise/asdf.
## Nix Flake
Nix the language is ugly and readability is mediocre (I maintain my
machines using Home Manager and still hard time *parsing* program.)
It's not good at handling toolchain versions and I don't believe people
not using Nix regularly can understand/write even *okay* quality code.
Combined with its worst of the worst debuggability, I mean error trace,
this is not something I'd like to maintain alongside application
development.
But most importantly, they still runs "bash" on "nix develop" even a
user uses zsh or fish. Hard pass.
## Devbox
Actually this was not in my radar initially, but found during figuring
best way to write Flake for monorepo.
It's not a kind of software I like: docs are next to a cloud offering,
docs site hosted on Vercel, corporate site calling nonsense-text-
generators-having-high-chance-of-makes-sense-response "AI" without
defining intelligence or artifical one, allowing JSONC for ".json" file
extension (fuck you M$ for starting this fucking tradition) and not
supporting ".jsonc" file extension.
But the tool itself is good actually.
* Config file is JSON rather than YAML.
* Config schema is concise and straightforward.
* CLI works great. No wrapping tables.
* CLI is fast.
* Structure of their docs website is *great*. I should steal from that.
* Supports versions, really.
It's hard to describe... UX for Devbox is similar to or better than
mise-en-place. Simplicity? No bullshit API design? I don't know.
I find this tool to be simpler to use and easier to understand compared
to other tools, even including non-Nix ones such as asdf, nvm, and mise.
I may encounter problems rooted to Devbox in a future. I may get
frustrated due to mistyping "debvoc" or something. But for now, I
believe Devbox is the best suited for this project (and my other
projects too.)
Shota FUJI
authored at
Shota FUJI
comitted at
4b704338Create a license file
I don't care someone using this for profit or whatever.
This project started because the status quo is terrible.
Shota FUJI
authored at
Shota FUJI
comitted at