Open comments for this post
Did a bit of refactoring to accomodate for later NativeAOT support:
- Each view & viewmodel has to be registered as a service
- Moved to source-generated JSON handling
- Hopefully, NativeAOT will make the app noticeably faster when I publish the project
Added global usings, and split up the project for better platform-specific service organization
Fixed the delete button not stopping the sound (how did I manage to fail that??)
Replaced the loop toggle with an Assign Shortcut button for quick access
I think the latter will be used more often, but having the loop toggle update two buttons at once was really cool
Sounds can now be added from YouTube; they are cached for fast access (how else would it work xd)
The window is not a dialog, so you can still interact with the soundboard while waiting for download(s)
(Idk if dialogs prevent interactions on some desktop environments tbh)
This is not the final layout, but it looks decent for now: clicking on a video (left side) takes you to the details page (right side) in the same window
Fun fact: pasting a youtube link automatically opens the video view, letting you download it even while the details are loading (will have to fix that up a little)
Open comments for this post
More (almost zero) progress on global shortcuts: I’ve figured out the object path & destination from the Kotlin library zugaldia/stargate, but xdg-desktop-portal just crashes now upon calling CreateSession
Added a devices page to select the output device
- I tried to implement device switching by creating a separate Mixer, but SoundFlow already has functionality for that, so it became much simpler
- Refactored code to use the new SoundFlowDeviceManager
A “Stop All Sounds” shortcut can now be assigned to each input when clicking the gear icon next to it
Fixed shortcut assignment not working after switching pages
- Editing context is reopened on page change
- The
SelectionChanged event fired for every child control, not just the TabControl -> I now check for the source of the event
Attempted to add consistent text alignment in tab headers, that turned out to be stupid, so I just added a space after the Playbacks emoji
Removed the “Raise Maximum Volume” (a 0-150% range makes more sense imo)
Adjusted buttons in the sound editing view, this is not yet final
On the image you can see a pipewire graph I created, this is similar to how I want it to work
- A sink for soundboard output which can be forwarded to the primary output device (e.g. headphones)
- A mixer virtual device (discord doesn’t support sinks) that combines the microphone input and the soundboard sink, acting as a virtual mic which can be selected in apps
- From a bit of testing, it turns out that connecting a sink to the primary output device produces some annoying popping, so I’ll probably just link/unlink the app’s playback to/from the primary output device, too
Open comments for this post
Added pages & tabs to better separate UI
Activated inputs are now saved and loaded
Sound state is now displayed better, it includes missing file detection (exceptions are not yet handled)
- Using a MultiBinding and an IMultiValueConverter with an enum didn’t work for some reason
New page: playbacks
- It shows all sounds, their current time
- Will need a redesign
- Pro tip: don’t call Dispatcher.Post in a method you called Dispatcher.Post in (it will keep updating the UI but prevents user input, you can’t even close the window normally)
Did a bit of refactoring:
- AudioManager is now a service
- Removed the Host service, the desktop lifetime and the TopLevel will be injected
Added an overlay when a file dialog is open (because unlike windows, not all OSes/desktop environments prevent interactions in this situation)
Open comments for this post
Implemented input handling for the Launchpad Mini, now I’ll be able to press pads to play sounds
Creating the shortcuts system took a few iterations, I wasn’t happy with the code I wrote
Shortcuts can be removed even when the input method isn’t active, which wasn’t possible in an earlier iteration
Also implemented settings saving when the app exits
Open comments for this post
Added a proper UI for triggering sounds with modes similar to that of voicemod (start -> stop, start -> restart, play -> pause, duplicate)
I played around with 2 rows below the big button but that seemed to take up too much space, so I moved them to the sound editor (which isn’t fully functional yet)
On the right side you can see input methods, which will include global shortcuts later (DBus is confusing af, the win32 api might actually be easier to work with 💀)
(Yes, I’ve half-made a global keyboard handler for windows previously)
Emojis are fairly expressive imo, but there are tooltips that describe what each button does
The layout definitely needs improvements, but it’s something ig
Also implemented loading sounds on startup, as well as saving when a new sound is added
Open comments for this post
Created the very base of the project with Avalonia and SoundFlow, sound playback works
Spent a bunch of time trying to figure out the DBus interface for XDG global shortcuts (Linux part of keybinds):