46 Commits

Author SHA1 Message Date
921944e64e Replace README with a project sunsetting notice 2025-09-08 15:33:10 -05:00
9e00217cec Update changelog for 0.5.1-1 release 2025-06-09 22:38:00 -05:00
04ad890f16 Change default compression to xz level 9 2025-06-09 22:31:10 -05:00
a89558d5a7 Merge in upstream version 0.5.1 to Debian pkg 2025-06-09 22:30:46 -05:00
5b8bdaca4b Bump debian/changelog to verson 0.5.0-1 2025-06-09 22:30:31 -05:00
d8b08b46fc Merge in upstream version 0.5.0 to Debian pkg 2025-06-09 21:59:44 -05:00
b33d2ace99 Bump debian/changelog to version 0.4.0-1 2025-06-09 21:58:41 -05:00
5ddb8b020b Add build-depends on libssl-dev 2025-06-09 21:52:34 -05:00
3831f4e0c0 Merge in upstream version 0.4.0 to Debian pkg 2025-06-09 20:59:04 -05:00
d8ff8876b4 Bump debian/changelog to version 0.3-1 2025-06-09 20:57:21 -05:00
036b9d1a94 Merge in upstream version 0.3 to Debian pkg 2025-06-09 20:26:36 -05:00
8401d9eada Bump debian/changelog to version 0.2-1 2025-06-09 20:24:03 -05:00
be28bf0dc8 Adjust the copyright file a bit...
I'm going to mark Geoffrey as having the copyright range up to 2025
because that's when I'm actually assembling this branch. Not like this
needs to be made as-if it was done at that point.

The previous copyright file indicated "LGPL" was an option. I think I
had done that because of the "GPLv3 *or later*" phrasing. I don't think
that's how it works -- the LGPL is not a "newer version" of the GPL.
2025-06-09 20:07:33 -05:00
0857a02c77 Create a copyright file 2025-06-09 19:59:48 -05:00
e50d13b992 Update changelog via gbp dch 2025-06-09 19:59:40 -05:00
41f1593443 Drop the backported link ordering patch
Now that we're past the v0.2 release tag, there is no need to backport
the patch.
2025-06-09 19:58:05 -05:00
46652862d3 Merge in upstream version 0.2 to Debian pkg 2025-06-09 19:47:43 -05:00
5bd8a5de42 Bump debian/changelog to version 0.1-1 2025-06-09 19:38:18 -05:00
646a62afdb Backport a link order fix from upstream
Upstream made a fix for the linker ordering after marking v0.1. Since I
have the benefit of doing this *years after the fact*, I'll just
backport that thing instead of inventing my own fix.
2025-06-09 19:27:54 -05:00
169feb563f Name upstream and debian branches properly
Upstream keeps it's changes on "master". This may be the default for
`gbp`, but may *not* be. Explicitly set the upstream branch just to be
sure.

The Debian branch shouldn't be called "trunk" (or "main" or "master").
I'm calling it "deb" in case a real Debian maintainer picks up the
upstream project and wants to use the name "debian". It's configurable,
so hardly critical, but I may as well be a good neighbor and leave it
unused.
2025-06-09 19:16:48 -05:00
fb99a3783f Set upstream version tag in gbp.conf 2025-06-09 19:16:32 -05:00
a3d77ee98a Drop pbuilder settings from gbp.conf 2025-06-09 19:16:06 -05:00
runiq
e6fbb4f146 More Flatpak manifest cleanup
The flow should be clearer if every module is structured this way:

1. name
2. sources
3. buildsystem
4. config-opts
5. build-commands
6. post-install
7. cleanup
2025-03-16 20:17:06 +10:30
runiq
e4dc805422 Remove superfluous files from Flatpak 2025-03-16 20:17:03 +10:30
runiq
87ee0ed66b Add alsactl utility
Allows saving and loading device state with the Flatpak version. The
Gnome 47 SDK uses alsa-lib 1.2.12 [1] via the Freedesktop.org SDK [2],
so we use that here as well.

[1] https://gitlab.gnome.org/search?search=alsa&nav_source=navbar&project_id=456&group_id=8&search_code=true&repository_ref=47.4
[2] https://gitlab.com/freedesktop-sdk/freedesktop-sdk/-/blob/release/24.08/elements/components/alsa-lib.bst?ref_type=heads
2025-03-16 20:17:01 +10:30
Geoffrey D. Bennett
adeea461fd Change alsa_get_elem_int_values() to return longs rather than ints 2025-03-16 20:08:47 +10:30
Geoffrey D. Bennett
1f7bafbfc3 Update window-hardware with big 4th Gen and Vocaster models 2025-03-16 20:08:47 +10:30
Geoffrey D. Bennett
b8420ba31c Add support for rebooting devices using the FCP socket interface 2025-03-16 20:08:47 +10:30
Geoffrey D. Bennett
a5676eeb5a Replace hwdep check in window-startup.c with driver_type check
Since alsa.c already checks the hwdep version to determine the driver
type, window-startup.c doesn't need to do the same.
2025-03-16 20:08:47 +10:30
Geoffrey D. Bennett
9a33b92392 Don't attempt to attach unused routing_mixer_in_grid 2025-03-16 20:08:47 +10:30
Geoffrey D. Bennett
97f993db7b Add support for waiting for FCP driver initialisation
When a card using the FCP driver is added at runtime, we need to wait
for fcp-server to finish creating all the controls before we attempt
to enumerate them.
2025-03-16 20:08:47 +10:30
Geoffrey D. Bennett
6f0ab1890d Add driver type detection 2025-03-16 20:08:47 +10:30
Geoffrey D. Bennett
c88f7796f4 Move card init from alsa_scan_cards() to new card_init() function 2025-03-16 20:08:47 +10:30
Geoffrey D. Bennett
0b5b47ae66 Disable the startup menu option for 1st Gen devices 2025-03-16 20:08:47 +10:30
Geoffrey D. Bennett
b6117a501f Replace 1st Gen Startup Controls info with Startup Configuration
The Startup Controls information wasn't very useful, and the Startup
Configuration information is actually important.
2025-03-16 20:08:47 +10:30
Geoffrey D. Bennett
a34df84dfa Improve "settings keep resetting" FAQ entry 2025-03-16 20:08:47 +10:30
Pro-pra
6677e5c87d Use template spec with macros 2025-03-07 23:59:50 +10:30
Geoffrey D. Bennett
91fc3bbb03 Add information about alsa-state and alsa-restore to FAQ.md 2025-02-26 03:27:21 +10:30
Geoffrey D. Bennett
460b03c668 Replace '/" with ’/“/” in *.md 2025-02-26 03:27:21 +10:30
Geoffrey D. Bennett
8a2e5f5835 Add RTFM advice to FAQ.md 2025-02-26 03:27:21 +10:30
Geoffrey D. Bennett
72fd974da1 Update startup window no-startup-controls message
Replace the message suggesting a kernel upgrade because the 1st Gen
driver has no startup controls.
2025-02-26 02:23:24 +10:30
Geoffrey D. Bennett
e6166de04b Update 1st Gen doc to mention Level Meters and Startup Controls 2025-02-26 02:23:24 +10:30
Geoffrey D. Bennett
f0213eadb1 Replace -j4 with -j$(nproc) 2025-02-26 02:23:24 +10:30
Geoffrey D. Bennett
ae23674f21 Add small deadband to dial drag to stop double-click adjustments
Sometimes 0.5 < abs(offset_y) < 1 when double-clicking without moving
the mouse, causing the intended toggling between -inf and 0dB to not
work.

Fixes: #149.
2025-02-26 02:22:59 +10:30
Geoffrey D. Bennett
68e45e58a6 Remove unused start_x, start_y from gtk_dial_drag_gesture_update() 2025-02-26 02:07:55 +10:30
05ae063b90 Initial package check-in
The package should work properly, however the GTK4 dependency isn't
quite correct. The instructions from upstream suggest that the author is
using Fedora, not Debian. After testing real quick, it looks like Fedora
37 compiles properly, but Fedora 38 aborts with a deprecation warning
   (-Werror=deprecated-declarations). Fedora 39 does the same, of
course.
2024-05-29 18:02:01 -05:00
29 changed files with 1366 additions and 232 deletions

View File

@@ -23,7 +23,7 @@ jobs:
- name: Build from sources
run: |
make -C src -j4 PREFIX=/usr
make -C src -j$(nproc) PREFIX=/usr
- name: Prepare package workspace
run: |

62
FAQ.md
View File

@@ -24,7 +24,7 @@ deactivate MSD mode by holding down the 48V button while powering it
on).
However, to access the mixer, routing, and hardware-specific features,
you'll need the appropriate driver for your interface model.
youll need the appropriate driver for your interface model.
## MSD Mode?
@@ -34,7 +34,7 @@ you'll need the appropriate driver for your interface model.
If MSD Mode is enabled, you need to disable it and restart your
interface to get access to its full functionality.
When you plug the interface in, there'll be a tiny read-only virtual
When you plug the interface in, therell be a tiny read-only virtual
disk that has a link to the Focusrite product registration page; until
you turn off MSD Mode not all features of the interface will be
available.
@@ -46,7 +46,7 @@ powering on the interface, or by clicking the button in
If you do the recommended/required (depending on the model) firmware
update, MSD Mode will automatically be turned off.
## What is the purpose of these drivers if they're not needed for basic audio?
## What is the purpose of these drivers if theyre not needed for basic audio?
These drivers are for users who want more control over their
interface. They allow for detailed manipulation of:
@@ -72,13 +72,13 @@ The ALSA Scarlett Control Panel supports:
- **Vocaster**: One, Two
Note: The Scarlett 1st and 2nd Gen small interfaces (Solo, 2i2, 2i4)
don't have any software controls. All the controls are available from
the front panel, so they don't require the specialised drivers or this
dont have any software controls. All the controls are available from
the front panel, so they dont require the specialised drivers or this
GUI.
## Where are the options to set the sample rate and buffer size?
The ALSA Scarlett Control Panel doesn't handle audio input/output
The ALSA Scarlett Control Panel doesnt handle audio input/output
settings like sample rate and buffer size. These settings are managed
by the application using the soundcard, typically a sound server such
as PulseAudio, JACK, or PipeWire.
@@ -90,8 +90,58 @@ displays the current rate being used by applications. If it shows
Note that not all features are available at higher sample rates; refer
to the user manual of your interface for more information.
## Why do my settings keep resetting?
The settings in the ALSA Scarlett Control Panel are automatically
saved in the interface itself (all series except 1st Gen), so they
should persist across reboots, power cycles, USB disconnect/reconnect,
and even across different computers. This includes all routing,
mixing, and other control panel settings.
If you find that your settings are reverting whenever you plug your
interface in or power it back on, the most likely cause is the
`alsa-state` and `alsa-restore` systemd services. These services save
the state of ALSA controls on system shutdown to
`/var/lib/alsa/asound.state` and then restore it each time the device
is plugged in, potentially overwriting your interfaces stored
settings.
It can be rather annoying, wondering why your device is unusable or
needs to be reconfigured every time you plug it in or turn it on.
To fix this issue, disable these services:
```sh
sudo systemctl mask alsa-state
sudo systemctl mask alsa-restore
```
You can verify if this is the cause of your issues by:
1. Change some setting that is indicated on the device (the “Inst”
setting is a good).
2. Disconnect USB and notice the state of the setting on the device
has not changed.
3. Power cycle the device and notice the state of the setting on the
device has not changed.
4. Reconnect USB and notice the state of the setting on the device has
changed.
If the setting on the device changes at step 4, then the `alsa-state`
and `alsa-restore` services are the likely cause of your issues.
## Help?!
Have you read the User Guide for your interface? Its available
online: https://downloads.focusrite.com/focusrite and contains a lot
of helpful/useful/important information about your device.
You can skip the “Easy Start” and “Setting up your DAW” sections, but
the rest is well worth reading. Even the information about Focusrite
Control is useful, although not directly applicable, because it will
help you understand more about the possibilities of what you can do
with your device.
For help with the Scarlett2 and FCP kernel drivers:
https://github.com/geoffreybennett/linux-fcp/issues

View File

@@ -10,7 +10,7 @@ default:
@echo
@echo "If you want to build and install from source, please try:"
@echo " cd src"
@echo " make -j4"
@echo " make -j$(shell nproc)"
@echo " sudo make install"
@echo
@echo "This Makefile knows about packaging:"

View File

@@ -1,95 +1,8 @@
# ALSA Scarlett Control Panel (`alsa-scarlett-gui`)
`alsa-scarlett-gui` is a Gtk4 GUI for the ALSA controls presented by
the three Linux kernel Focusrite USB drivers:
- Upstream project here: https://github.com/geoffreybennett/alsa-scarlett-gui
- Debian's packaged version here: https://salsa.debian.org/doge-tech/alsa-scarlett-gui
- Scarlett 1st Gen Driver for ALSA
- Scarlett2 USB Protocol Mixer Driver
- FCP (Focusrite Control Protocol) Driver
This fork of the repo was started so I could write a Debian package manifest for the program. While I successfully made a working package, I had no intention of uploading it to the Debian archives -- I felt that I didn't have enough experience to bother the Debian maintainers with my nonsense. Someone else, however, [did upload one!](https://salsa.debian.org/doge-tech/alsa-scarlett-gui). That version has since been included with the Debian 13 release.
Supported interfaces:
- Scarlett 1st Gen 6i6, 8i6, 18i6, 18i8, 18i20
- Scarlett 2nd Gen 6i6, 18i8, 18i20
- Scarlett 3rd Gen Solo, 2i2, 4i4, 8i6, 18i8, 18i20
- Scarlett 4th Gen Solo, 2i2, 4i4, 16i16, 18i16, 18i20
- Clarett 2Pre, 4Pre, 8Pre USB
- Clarett+ 2Pre, 4Pre, 8Pre
- Vocaster One and Vocaster Two
## About
<img src="img/alsa-scarlett-gui.png" align="right">
All Focusrite USB audio interfaces are class compliant meaning that
they work “out of the box” on Linux as audio and MIDI interfaces
(although on Gen 3/4/Vocaster you need to disable MSD mode first for
full functionality). However, except for some of the smallest models,
they have a bunch of proprietary functionality that required a kernel
driver to be written specifically for those devices.
Unfortunately, actually using this functionality used to be quite an
awful experience. The existing applications like `alsamixer` and
`qasmixer` become completely user-hostile with the hundreds of
controls presented for the Gen 3 18i20. Even the smallest Gen 3 4i4
interface at last count had 84 ALSA controls.
Announcing the ALSA Scarlett Control Panel, now supporting all
Scarlett Gen 1, 2, 3, 4, Clarett, and Vocaster USB interfaces!
![Demonstration](img/demo.gif)
## Documentation
Refer to [INSTALL.md](docs/INSTALL.md) for prerequisites, how to
build, install, and run.
Refer to [USAGE.md](docs/USAGE.md) for general usage information and
known issues.
Information specific to various models:
- [Scarlett 1st Gen](docs/iface-1st-gen.md)
- [Scarlett 3rd Gen Solo and 2i2](docs/iface-small.md)
- [Scarlett 2nd Gen 6i6+, 3rd Gen 4i4+, Clarett USB, and
Clarett+](docs/iface-large.md)
- [Scarlett Small 4th Gen](docs/iface-4th-gen-small.md)
- [Scarlett Big 4th Gen](docs/iface-4th-gen-big.md)
## Donations
This program is Free Software, developed using my personal resources,
over hundreds of hours.
If you like this software, please consider a donation to say thank
you! Any donation is appreciated.
- https://liberapay.com/gdb
- https://paypal.me/gdbau
## License
Copyright 2022-2025 Geoffrey D. Bennett
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or (at
your option) any later version.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
## Disclaimer Third Parties
Focusrite, Scarlett, Clarett, and Vocaster are trademarks or
registered trademarks of Focusrite Audio Engineering Limited in
England, USA, and/or other countries. Use of these trademarks does not
imply any affiliation or endorsement of this software.
I'm archiving this repo because it is redundant with that package. I want to keep it around as something I made, while also making it clear that this project is dead.

View File

@@ -1,35 +1,29 @@
Summary: ALSA Scarlett Control Panel
Name: alsa-scarlett-gui
Version: VERSION
Release: 1%{?dist}
License: GPLv3+ LGPLv3+
Url: https://github.com/geoffreybennett/alsa-scarlett-gui
Source: %{name}-%{version}.tar.gz
Summary: ALSA Scarlett Control Panel
Name: alsa-scarlett-gui
Version: VERSION
Release: 1%{?dist}
License: GPLv3+ LGPLv3+
Url: https://github.com/geoffreybennett/alsa-scarlett-gui
Source0: https://github.com/geoffreybennett/alsa-scarlett-gui/archive/refs/tags/%{version}.tar.gz?/%{name}-%{version}.tar.gz
BuildRequires: pkgconfig(alsa)
BuildRequires: pkgconfig(gtk4)
BuildRequires: pkgconfig(openssl)
%description
alsa-scarlett-gui is a Gtk4 GUI for the ALSA controls presented by the
Linux kernel Focusrite USB drivers.
%prep
%setup
%setup -q -n %{name}-%{version}/src
%build
make -C src -j4 VERSION=%{version} PREFIX=/usr
%make_build VERSION=%{version} PREFIX=%{_prefix}
%install
%make_install -C src PREFIX=/usr
DOCDIR=%{buildroot}/usr/share/doc/%{name}-%{version}
mkdir -p $DOCDIR/img
mkdir $DOCDIR/demo
mkdir $DOCDIR/docs
cp *.md $DOCDIR
cp img/* $DOCDIR/img
cp demo/* $DOCDIR/demo
cp docs/* $DOCDIR/docs
%make_install PREFIX=%{_prefix}
%files
%doc /usr/share/doc/%{name}-%{version}
/usr/bin/alsa-scarlett-gui
/usr/share/applications/vu.b4.alsa-scarlett-gui.desktop
/usr/share/icons/hicolor/256x256/apps/vu.b4.alsa-scarlett-gui.png
%doc ../img ../demo ../docs ../*.md
%{_bindir}/alsa-scarlett-gui
%{_datadir}/applications/vu.b4.alsa-scarlett-gui.desktop
%{_iconsdir}/hicolor/256x256/apps/vu.b4.alsa-scarlett-gui.png

410
debian/changelog vendored Normal file
View File

@@ -0,0 +1,410 @@
alsa-scarlett-gui (0.5.1-1) unstable; urgency=medium
[ Geoffrey D. Bennett ]
* Add RTFM advice to FAQ.md
* Replace '/" with /“/” in *.md
* Add information about alsa-state and alsa-restore to FAQ.md
[ Pro-pra ]
* Use template spec with macros
[ Geoffrey D. Bennett ]
* Improve "settings keep resetting" FAQ entry
* Replace 1st Gen Startup Controls info with Startup Configuration
* Disable the startup menu option for 1st Gen devices
* Move card init from alsa_scan_cards() to new card_init() function
* Add driver type detection
* Add support for waiting for FCP driver initialisation
* Don't attempt to attach unused routing_mixer_in_grid
* Replace hwdep check in window-startup.c with driver_type check
* Add support for rebooting devices using the FCP socket interface
* Update window-hardware with big 4th Gen and Vocaster models
* Change alsa_get_elem_int_values() to return longs rather than ints
[ runiq ]
* Add alsactl utility
* Remove superfluous files from Flatpak
* More Flatpak manifest cleanup
[ Robert Garrett ]
* Change default compression to xz level 9
-- Robert Garrett <robertgarrett404@gmail.com> Mon, 09 Jun 2025 22:37:54 -0500
alsa-scarlett-gui (0.5.0-1) unstable; urgency=medium
[ Geoffrey D. Bennett ]
* Move 4th Gen Solo 48V switch above the Air switch
[ Giorgio Reale ]
* Add 4rd Gen models to window-hardware.c
[ Geoffrey D. Bennett ]
* Fix widget-boolean.c to free data on button destruction
* Add Arch package dependency
* Fix Sample Rate button to be insensitive
* Override focus and colour CSS button styles
* Search $PATH and /usr/sbin for alsactl
* Add support for volatile buttons to widget-boolean.c
* Allow for boolean controls that are backwards
* Update widget-boolean to cache the icon widgets
* Switch to embedded SVG icons
[ Guillaume ]
* Add missing GTK and ALSA dependencies on deb package
[ Geoffrey D. Bennett ]
* Add -fPIE and -pie build flags to fix flatpak build under Fedora
* Download and include scarlett2 firmware in flatpak
* Make flatpak build faster
* Fix up deb and RPM package description & add docs
* Move level meter fields out of struct alsa_card
* Add peak display to the level meters
* Use snprintf() in widget-gain.c when printing floats
* Add peak value display to the level meters
* Fix link from FAQ.md to INSTALL.md
* Add const to get*elem*() char* function arguments
* Add 3rd Gen 18i8/18i20 S/PDIF/Digital I/O Mode startup controls
[ unhappy-ending ]
* Update Makefile to use $(CC) rather than cc
[ Geoffrey D. Bennett ]
* Replace cairo_show_text() in gtkdial.c with Pango
* Fix crash in window-level.c on_destroy()
* Update flatpak to GNOME 47
* Update logo
* Add get_elem_by_substr() to alsa.[ch]
* Add Scarlett 1st Gen demo state files
* Gen 1: Handle different names for clock source and sync status
* Gen 1: Mute switches are backwards
* Gen 1: Add 1st Gen devices to window-hardware.c
* Gen 1: Trigger support based on "Matrix" element presence
* Gen 1: Add PC_OFF port category
* Gen 1: Ignore control "index" value in saved configurations
* Gen 1: Parse and save config count field
* Gen 1: Move alsa-sim elem creation into alsa_config_to_new_elem()
* Gen 1: Add support for elements with count > 1 in saved config
* Gen 1: Add support for 1st Gen stereo elements
* Gen 1: Add support for 1st Gen mixer controls
* Gen 1: Add support for 1st Gen input controls
* Gen 1: Add support for 1st Gen output controls
* Wrap long line, fix reopen callback comment in alsa.c
* Update constants for new maximum number of mux inputs and meters
* Treat locked ALSA elements as read-only
* Handle interfaces with fixed mixer inputs
* Handle per-channel link buttons
* Update routing hover to highlight corresponding source sink
* Highlight mixer labels on dial hover
* Update gtkdial to support linear-volume controls
* Update alsa interface and gain widget to support linear volume
* Make perror("fopen") messages distinct
* Add support for two-control speaker switching and talkback
* Add support for new 4th Gen control names
* Simplify update_levels_controls()
* Add support for TLVs from the FCP driver
* Update alsa.c to handle differing FCP mixer element names
* Add support for Level Meter labels
* Fix output control column/mute tooltip handling
* Move card_destroy_callback() before alsa_card_callback()
* Call card_destroy_callback() when an ALSA element is removed
* Bump copyright year to 2025
* Update docs and such for 1st Gen and big 4th Gen support
* Add big 4th Gen demo files
* Make make clean do depclean too
* Undefine _FORTIFY_SOURCE before defining so GitHub can build the deb
* Update flatpak container image from gnome-45 to gnome-47
* Remove unused start_x, start_y from gtk_dial_drag_gesture_update()
* Add small deadband to dial drag to stop double-click adjustments
* Replace -j4 with -j$(nproc)
* Update 1st Gen doc to mention Level Meters and Startup Controls
* Update startup window no-startup-controls message
-- Robert Garrett <robertgarrett404@gmail.com> Mon, 09 Jun 2025 22:09:31 -0500
alsa-scarlett-gui (0.4.0-1) UNRELEASED; urgency=low
[ Guillaume ]
* Fix deb package icon install
[ Geoffrey D. Bennett ]
* Update Makefile to get version from $APP_VERSION
* Global replace "destination" with "sink"
[ fenugrec ]
* Replace deprecated gtk_widget_{show,hide} calls
* Reduce code duplication in menu.c
[ Geoffrey D. Bennett ]
* Add Clarett USB/Clarett+ models to window-hardware.c
* Pass APP_VERSION through flatpak-builder
* Check Firmware Version before enabling Levels menu item
* Remove user-control of level meters
* Improve layout for larger interfaces without speaker switching
* Fix the socket widget so that it will not shrink
* Allow the routing window to be resized and give it scrollbars
* Fix typo rounting -> routing
* Update drag_motion() to scroll the routing window
[ sporksnail ]
* src/Makefile: Respect CFLAGS from environment
[ Geoffrey D. Bennett ]
* Update README.md with Gen 4 info
* Update software name in INSTALL.md and USAGE.md
* Add info to INSTALL.md on how to check the kernel version
* Add Gtk4 info to INSTALL.md
* Fix typo in INSTALL.md driver disabled message
[ Jason A. Donenfeld ]
* Makefile: prefer distro cflags if specified
[ Geoffrey D. Bennett ]
* Add initial version of FAQ.md
* Add FUNDING.yml
* Add issue template
* Add Clarett info to INTERFACES.md
* Add TOC to INTERFACES.md
* Add link from USAGE.md to INTERFACES.md
* Allow the mixer window to be resized and give it scrollbars
* Update FAQ with more MSD info
* Fix long lines
* Add OpenSUSE package requirements
* Fix typo in INSTALL.md: comitting -> committing
* Move FUNDING.yml to the right spot
[ Jason A. Donenfeld ]
* gtkdial: use fabs() for double
[ Trent ]
* Add keyboard accelerators (aka shortcuts, hotkeys) for menu items.
[ Geoffrey D. Bennett ]
* Reformat keyboard accelerators to match existing code
* Remove keyboard accelerator mention from USAGE.md
* Split calc_valp() into calc_valp() and calc_valp_log()
* Fix dial to grab focus when clicked
* Fix dial to display focus indication
[ Nate Gallaher ]
* Clarify pad tooltip to specify attenuation amount
[ Geoffrey D. Bennett ]
* Remove gtk_widget_add_class()
* Fix is_elem_routing_snk() for Gen 4
* Remove lots of casts in create_routing_grid()
* Make the Level Meter check compatible with alsa-sim.c
* Remove repeated group by code in create_routing_grid()
* Add orientation parameter to routing_grid_label()
* Inline routing_grid_label() in create_routing_group_grid()
* Fix Presets button to be centered
* Add margin to socket widget
* Add support for routing the Gen 4 DSP I/O
* Allow for phantom power per-channel
* Remove hard-coded values from widget-gain.c and widget-volume.c
* Combine gain and volume widgets
* Center-align text in combo boxes
* Make boolean widget boolify value from alsa_get_elem_value()
* Explicitly order main window controls
* Add 4th Gen input controls
* Remove widgets from struct alsa_elem and add data to callbacks
* Add input select widget for 4th Gen 2i2 and 4i4
* Add 4th Gen 4i4 headphone volume knob control
* Add missing GtkDial scroll_begin() implementation
* Add bindings for pgup/pgdn/home/end to GtkDial
* Display -inf when volume/gain controls are at zero/off
* Don't round level meter values passed to GtkDial
* Fix widget-combo to check if the alsa elem is writable
* Simplify GtkDial calculations
* Bump copyright year
* Remove unused GtkDialFormatValueFunc from gtkdial.h
* Remove unused guint8 and gsize from gtkdial.c
* Remove irrelevant GDK_AVAILABLE_IN_ALL from gtkdial.h
* Reformat gtkdial.c to match rest of code
* Fix GtkDial:zero_db property comment
* Add scale to widget-gain.c struct gain
* Fix gtk_dial_new_with_range() to use calculated round_digits
* Allow for continuous dials
* Add page argument to gtk_dial_new_with_range()
* Fix typo range->dial in gtkdial.[ch]
* Remove inline from functions in gtkdial.c
* Move valp clamp and scale from calc_valp_log() to calc_valp()
* Add configurable taper to GtkDial
* Add support for piecewise linear interpolation taper to GtkDial
* Make GtkDial look better
* Make GtkDial dimmer if insensitive
* Remove bool_text from struct alsa_elem
* Move label into boolean controls and use button state to show status
* Remove "Analogue" from small Gen 3 device input labels
* Use CSS to set dark colour scheme
* Rewrite choose_line_colour() to work with a dark background
* Move 4th Gen Solo Air control up to be next to Inst control
* Add CSS classes to controls and add more colour
* Add widget-drop-down for Air
* Switch Clock Source to widget-drop-down
* Add 4th Gen Solo/2i2 Direct Monitor controls
* Add power status control for 4th Gen 4i4
* Update 3rd Gen Solo Direct Monitor control to match 4th Gen
* Remove now-unused widget-combo
* Add some red and grey
* Update about, etc. messages to include Gen 4/Clarett
* Add CSS for buttons that get dimmer when checked
* Use GtkTextView instead of GtkLabel in startup big_label()
* Add draw_slider() to remove some common code from dial_snapshot()
* Add GtkDial:can_control property
* Add 4th Gen Solo Mix switch
* Add off_db (deadband) to GtkDial for quiet signals
* Use GtkDial off_db (deadband) for level meters
* Remove struct dial_properties; cache values in struct _GtkDial
* Allow GtkDial to shrink more and reduce slider thickness
* Fix GtkDial to not recreate the cairo patterns on every draw
* Add colour to GtkDial level meters
* Prefix CSS styles so they don't apply to other windows
* Update the gain widget to support updating direct monitor mix controls
* Add routing group tooltips
* Fix GtkDial to not redraw the dial if the set value doesn't change
* Fix GtkDial to redraw on notify::sensitive signal
* Add red focus outline to GtkDial
* CSS fixes for buttons
* Retrieve and store the device serial number
* Don't export alsa_cards from alsa.c
* Add support for config reset
* Retrieve and store the device USB PID
* Move -lm into LDFLAGS
* Add support for firmware update
[ Antti-Pekka Meronen ]
* Include openssl-devel in Fedora installation instructions
[ Geoffrey D. Bennett ]
* Update OpenSUSE and Ubuntu package dependencies
* Remove fixed/mentioned-elsewhere issues from USAGE.md
* Don't set transient on modal window
* Make gain widget dB numbers smaller
* Add 4th Gen Solo, 2i2, and 4i4 demo files
* Don't show empty rows in levels window
* If there's an MSD control, add a reboot control too
* Reduce GtkDial circle brightness
* Make window-helper.c close the window when Esc is pressed
* Add missing static to populate_submenu() in menu.c
* Add gtk_widget_remove_css_classes_by_prefix() helper
* Add display of sample rate
* Display "+" before positive dB values in the gain widget
* Update gain widget to show no decimal places for scale > 0.5
* Add initial support for the Vocaster One and Two
* Store the best_firmware_version in struct alsa_card
* Prompt for firmware update if in MSD Mode and an update is available
* Add firmware info to the INSTALL.md Prerequisites section
* Update About dialog
* Update documentation for Scarlett 4th Gen and Vocaster
[ Robert Garrett ]
* Add build-depends on libssl-dev
-- Robert Garrett <robertgarrett404@gmail.com> Mon, 09 Jun 2025 21:57:36 -0500
alsa-scarlett-gui (0.3-1) UNRELEASED; urgency=low
[ Geoffrey D. Bennett ]
* Fix format-security warning in error.c
[ Sebastian Kaminski ]
* Fixed typo for 18i20 Gen 3 Mic/Line 3-8
[ Szabolcs Szőke ]
* Make routing sources and destinations the same width
[ Geoffrey D. Bennett ]
* Clarify comments and variable names in choose_line_colour()
[ Sebastian Kaminski ]
* Prevent the boolean widget from changing size when toggled
[ Geoffrey D. Bennett ]
* Add Ubuntu install and git download instructions
* Add Clarett support
* Fix typos in USAGE.md
* Fix building with Gtk 4.10
* Update README.md and USAGE.md with current driver information
* Add link to fundraiser for adding Scarlett Gen 4 support
* Fix input counting for Clarett+ series
* Update README and USAGE files with new Clarett info
* Split USAGE.md into INSTALL.md and USAGE.md
* Add Clarett Plus 2Pre and 4Pre demo files
* Update Clarett USB and Clarett+ status
* Apply correction curve to the dials
* Update README with Gen 4 and Vocaster info
* Specify full path to alsactl
[ David Cooper ]
* Add keyword to desktop file
[ Alejandro Domínguez ]
* Change icon file name
* Do not use deprecated or non-standard keys in desktop file
* Enable Flatpak packaging support
[ Guillaume ]
* Fix Error: icon alsa-scarlett-gui not found below...
* Remove commented rename-icon property
* Using github.com/flatpak/flatpak-github-actions
[ Geoffrey D. Bennett ]
* Fix iface-none.png image description
* Move flatpak instructions to INSTALL.md
* Update flatpak to gnome 45
* Add org.gnome.Platform and flathub to flatpak instructions
* Update INSTALL and README with Linux 6.7 info
[ sporksnail ]
* window-startup.c: fix typo
[ Geoffrey D. Bennett ]
* Add meter/level display
[ Guillaume ]
* Github action to build debian package on release
[ Robert Garrett ]
* Merge upstream version 0.3 & release package
-- Robert Garrett <robertgarrett404@gmail.com> Mon, 09 Jun 2025 20:36:56 -0500
alsa-scarlett-gui (0.2-1) UNRELEASED; urgency=low
[ Geoffrey D. Bennett ]
* Note lack of keyboard accelerators
* Add demo GIF
* Fix size of mixer output sockets on Gen 3 18i20 routing
* Reduce button padding as intended
* Display input labels across the top of the mixer window
* Reformat CSS to not be so squishy
* Change route-label hover background colour to work with dark theme
* Add desktop and icon files and install into the correct place
* Add copyright info to the Makefile
* Don't hardcode the version number in the about dialog
[ KottV ]
* Fix linking in OBS
[ Geoffrey D. Bennett ]
* Add help target to src/Makefile
* Add top-level Makefile and RPM spec file for packaging
[ Robert Garrett ]
* Drop the backported link ordering patch
* Update changelog via gbp dch
* Create a copyright file
* Adjust the copyright file a bit...
-- Robert Garrett <robertgarrett404@gmail.com> Mon, 09 Jun 2025 20:21:13 -0500
alsa-scarlett-gui (0.1-1) UNRELEASED; urgency=low
* Initial revision, starting up a package manifest.
* Drop pbuilder settings from gbp.conf
* Set upstream version tag in gbp.conf
* Name upstream and debian branches properly
* Backport a link order fix from upstream
-- Robert Garrett <robertgarrett404@gmail.com> Mon, 09 Jun 2025 19:37:00 -0500

16
debian/control vendored Normal file
View File

@@ -0,0 +1,16 @@
Source: alsa-scarlett-gui
Maintainer: Robert Garrett <robertgarrett404@gmail.com>
Section: misc
Priority: optional
Standards-Version: 4.6.2
Build-Depends:
debhelper-compat (= 13),
libasound2-dev,
libgtk-4-dev,
libssl-dev,
Package: alsa-scarlett-gui
Architecture: any
Depends: ${shlibs:Depends}, ${misc:Depends}
Description: GUI tool for Scarlett audio interfaces.
Uses an ALSA backend.

34
debian/copyright vendored Normal file
View File

@@ -0,0 +1,34 @@
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Source: https://github.com/geoffreybennett/alsa-scarlett-gui
Upstream-Name: alsa-scarlett-gui
Upstream-Contact: Geoffrey D. Bennet <g@b4.vu>
License: GPL-3.0-or-later or LGPL-3+
Files: *
Copyright:
2022-2025 Geoffrey D. Bennet <g@b4.vu>
2022 KottV <kv@kott.no-ip.biz>
License: GPL-3+
Files:
debian/*
Copyright: 2024-2025 Robert Garrett
License: GPL-3+
License: GPL-3.0+
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
.
On Debian systems, the full text of the GNU General Public
License Version 3 can be found in the file
`/usr/share/common-licenses/GPL-3`

8
debian/gbp.conf vendored Normal file
View File

@@ -0,0 +1,8 @@
[DEFAULT]
compression = xz
compression-level = 9
upstream-branch = master
debian-branch = deb
upstream-tag = %(version)s
pristine-tar = False

5
debian/rules vendored Executable file
View File

@@ -0,0 +1,5 @@
#!/usr/bin/make -f
%:
PREFIX=/usr dh $@ --sourcedirectory=src/

1
debian/source/format vendored Normal file
View File

@@ -0,0 +1 @@
3.0 (quilt)

View File

@@ -30,7 +30,7 @@ is not needed, useful, or supported for these models.
If your distribution doesnt include a recent-enough kernel for your
interface, you can get the latest driver from here and build it for
your current kernel if it's not too old (the Scarlett2 and FCP drivers
your current kernel if its not too old (the Scarlett2 and FCP drivers
are both maintained in the same tree here):
https://github.com/geoffreybennett/linux-fcp/releases
@@ -124,7 +124,7 @@ To build:
```
cd src
make -j4
make -j$(nproc)
```
To run:

View File

@@ -26,13 +26,22 @@ ALSA driver implementation that you should be aware of:
2. **State Update Issues**: The driver only updates the hardware state
when it thinks a setting needs to be changed. If the driver
incorrectly believes a control is already in the desired state, it
won't actually update the control.
wont actually update the control.
3. **Level Meters**: The driver does not support reading the level
meters from the hardware.
4. **Startup Configuration**: The driver is not able to save the
current configuration to the non-volatile memory of the device, so
youll need to reapply the desired configuration each time you
restart it (or write your preferred configuration using MixControl
on Windows or Mac).
### Recommended Workaround
To ensure your settings are properly applied:
1. Apply a "zero" configuration that sets all controls to values that
1. Apply a zero configuration that sets all controls to values that
are *not* what you desire.
2. Then apply your desired configuration
@@ -65,12 +74,12 @@ Global controls relate to the operation of the interface as a whole.
#### Clock Source
Clock Source selects where the interface receives its digital clock
from. If you aren't using S/PDIF or ADAT inputs, set this to Internal.
from. If you arent using S/PDIF or ADAT inputs, set this to Internal.
#### Sync Status
Sync Status indicates if the interface is locked to a valid digital
clock. If you aren't using S/PDIF or ADAT inputs and the status is
clock. If you arent using S/PDIF or ADAT inputs and the status is
Unlocked, change the Clock Source to Internal.
### Analogue Input Controls
@@ -131,16 +140,16 @@ from more than one source, use the mixer inputs and outputs:
The Presets menu can be used to clear all connections, or to set up
common configurations:
- The "Direct" preset sets up the usual configuration using the
- The Direct preset sets up the usual configuration using the
interface as a regular audio interface by connecting:
- all Hardware Inputs to PCM Inputs
- all PCM Outputs to Hardware Outputs
- The "Preamp" preset connects all Hardware Inputs to Hardware
- The Preamp preset connects all Hardware Inputs to Hardware
Outputs.
- The "Stereo Out" preset connects PCM 1 and 2 Outputs to pairs of
- The Stereo Out preset connects PCM 1 and 2 Outputs to pairs of
Hardware Outputs.
## Mixer

View File

@@ -10,7 +10,7 @@ with the big Scarlett 4th Gen interfaces:
### FCP Driver
The big 4th Gen interfaces are supported by a new “FCP” (Focusrite
Control Protocol) driver introduced in Linux 6.14. If you haven't
Control Protocol) driver introduced in Linux 6.14. If you havent
installed
[fcp-support](https://github.com/geoffreybennett/fcp-support) yet, you
need to do that (and update the firmware) before you can use

View File

@@ -5,10 +5,15 @@
#include <alsa/sound/uapi/tlv.h>
#include "alsa.h"
#include "scarlett2.h"
#include "scarlett2-firmware.h"
#include "scarlett2-ioctls.h"
#include "stringhelper.h"
#include "window-iface.h"
#define MAJOR_HWDEP_VERSION_SCARLETT2 1
#define MAJOR_HWDEP_VERSION_FCP 2
#define MAX_TLV_RANGE_SIZE 1024
// TLV type for channel labels
@@ -215,8 +220,8 @@ long alsa_get_elem_value(struct alsa_elem *elem) {
// for elements with multiple int values, return all the values
// the int array returned needs to be freed by the caller
int *alsa_get_elem_int_values(struct alsa_elem *elem) {
int *values = calloc(elem->count, sizeof(int));
long *alsa_get_elem_int_values(struct alsa_elem *elem) {
long *values = calloc(elem->count, sizeof(long));
if (elem->card->num == SIMULATED_CARD_NUM) {
for (int i = 0; i < elem->count; i++)
@@ -787,6 +792,77 @@ static void card_destroy_callback(void *data) {
}
}
// Complete card initialisation after the driver is ready
static void complete_card_init(struct alsa_card *card) {
// Get full element list and create main window
alsa_get_elem_list(card);
alsa_set_lr_nums(card);
alsa_get_routing_controls(card);
card->best_firmware_version = scarlett2_get_best_firmware_version(card->pid);
if (card->serial) {
// Call the reopen callbacks for this card
struct reopen_callback *rc = g_hash_table_lookup(
reopen_callbacks, card->serial
);
if (rc)
rc->callback(rc->data);
g_hash_table_remove(reopen_callbacks, card->serial);
}
create_card_window(card);
}
// Check if the Firmware Version control has a TLV and is locked,
// indicating the driver is ready
static int check_driver_ready(snd_ctl_elem_info_t *info) {
return snd_ctl_elem_info_is_tlv_readable(info) &&
snd_ctl_elem_info_is_locked(info);
}
// Check if the FCP driver is initialised
static void check_driver_init(
struct alsa_card *card, int numid, unsigned int mask
) {
// Ignore controls going away
if (mask == SND_CTL_EVENT_MASK_REMOVE)
return;
// Get the control's info
snd_ctl_elem_id_t *id;
snd_ctl_elem_info_t *info;
snd_ctl_elem_id_alloca(&id);
snd_ctl_elem_info_alloca(&info);
snd_ctl_elem_id_set_numid(id, numid);
snd_ctl_elem_info_set_id(info, id);
if (snd_ctl_elem_info(card->handle, info) < 0) {
fprintf(stderr, "error getting elem info %d\n", numid);
return;
}
const char *name = snd_ctl_elem_info_get_name(info);
// Check if it's the Firmware Version control being updated
if (strcmp(name, "Firmware Version"))
return;
// Check if the driver is ready
if (!check_driver_ready(info))
return;
// The driver is initialised; update the card's driver type
card->driver_type = DRIVER_TYPE_SOCKET;
// Complete the card initialisation
complete_card_init(card);
}
static gboolean alsa_card_callback(
GIOChannel *source,
GIOCondition condition,
@@ -818,6 +894,13 @@ static gboolean alsa_card_callback(
int numid = snd_ctl_event_elem_get_numid(event);
unsigned int mask = snd_ctl_event_elem_get_mask(event);
// Check if we're waiting for FCP driver to initialise and check if
// it's now ready
if (card->driver_type == DRIVER_TYPE_SOCKET_UNINIT) {
check_driver_init(card, numid, mask);
return 1;
}
if (mask == SND_CTL_EVENT_MASK_REMOVE) {
card_destroy_callback(card);
return 0;
@@ -1067,6 +1150,94 @@ static void alsa_get_serial_number(struct alsa_card *card) {
card->serial = strdup(serial);
}
// return true if the Firmware Version control exists and is writable
// and locked (i.e. the FCP server is running)
static int check_firmware_version_locked(struct alsa_card *card) {
snd_ctl_elem_id_t *id;
snd_ctl_elem_info_t *info;
snd_ctl_elem_id_alloca(&id);
snd_ctl_elem_info_alloca(&info);
// look for the Firmware Version control
snd_ctl_elem_id_set_interface(id, SND_CTL_ELEM_IFACE_CARD);
snd_ctl_elem_id_set_name(id, "Firmware Version");
snd_ctl_elem_info_set_id(info, id);
// no Firmware Version control found
int err = snd_ctl_elem_info(card->handle, info);
if (err < 0)
return 0;
return check_driver_ready(info);
}
// return the driver type for this card
// DRIVER_TYPE_NONE: no driver
// DRIVER_TYPE_HWDEP: Scarlett2 driver
// DRIVER_TYPE_SOCKET: FCP driver
// DRIVER_TYPE_SOCKET_UNINIT: FCP driver, but not initialised
static int get_driver_type(struct alsa_card *card) {
snd_hwdep_t *hwdep;
int err = scarlett2_open_card(card->device, &hwdep);
// no hwdep for this card - driver type none
if (err == -ENOENT)
return DRIVER_TYPE_NONE;
// if we get EPERM, it's FCP but no server running
if (err == -EPERM)
return DRIVER_TYPE_SOCKET_UNINIT;
// if we get EBUSY, it's FCP
if (err == -EBUSY)
// fcp-server locks the Firmware Version control when it has
// finished starting up
return check_firmware_version_locked(card) ?
DRIVER_TYPE_SOCKET : DRIVER_TYPE_SOCKET_UNINIT;
// failed to open hwdep
if (err < 0)
return DRIVER_TYPE_NONE;
// we can open hwdep, so now check the protocol version
int ver = scarlett2_get_protocol_version(hwdep);
scarlett2_close(hwdep);
// failed to get protocol version
if (ver < 0)
return DRIVER_TYPE_NONE;
// hwdep protocol version 1.x.x is Scarlett2 driver
if (SCARLETT2_HWDEP_VERSION_MAJOR(ver) == MAJOR_HWDEP_VERSION_SCARLETT2)
return DRIVER_TYPE_HWDEP;
// hwdep protocol version 2.x.x is FCP driver (but not initialised,
// because we were able to open the hwdep)
if (SCARLETT2_HWDEP_VERSION_MAJOR(ver) == MAJOR_HWDEP_VERSION_FCP)
return DRIVER_TYPE_SOCKET_UNINIT;
return DRIVER_TYPE_NONE;
}
static void card_init(struct alsa_card *card) {
alsa_get_usbid(card);
alsa_get_serial_number(card);
alsa_subscribe(card);
alsa_add_card_callback(card);
card->driver_type = get_driver_type(card);
// Driver not ready? Create the iface-waiting window
if (card->driver_type == DRIVER_TYPE_SOCKET_UNINIT) {
create_card_window(card);
return;
}
complete_card_init(card);
}
static void alsa_scan_cards(void) {
snd_ctl_card_info_t *info;
snd_ctl_t *ctl;
@@ -1110,30 +1281,7 @@ static void alsa_scan_cards(void) {
card->name = strdup(snd_ctl_card_info_get_name(info));
card->handle = ctl;
alsa_get_elem_list(card);
alsa_set_lr_nums(card);
alsa_get_routing_controls(card);
alsa_subscribe(card);
alsa_get_usbid(card);
alsa_get_serial_number(card);
card->best_firmware_version =
scarlett2_get_best_firmware_version(card->pid);
if (card->serial) {
// call the reopen callbacks for this card
struct reopen_callback *rc = g_hash_table_lookup(
reopen_callbacks, card->serial
);
if (rc)
rc->callback(rc->data);
g_hash_table_remove(reopen_callbacks, card->serial);
}
create_card_window(card);
alsa_add_card_callback(card);
card_init(card);
continue;

View File

@@ -41,6 +41,19 @@ enum {
HW_TYPE_COUNT
};
// driver types
// NONE is 1st Gen or Scarlett2 before hwdep support was added
// (no erase config or firmware update support)
// HWDEP is the Scarlett2 driver after hwdep support was added
// SOCKET is the FCP driver
enum {
DRIVER_TYPE_NONE,
DRIVER_TYPE_HWDEP,
DRIVER_TYPE_SOCKET,
DRIVER_TYPE_SOCKET_UNINIT,
DRIVER_TYPE_COUNT
};
// names for the hardware types
extern const char *hw_type_names[HW_TYPE_COUNT];
@@ -162,6 +175,7 @@ struct alsa_card {
uint32_t pid;
char *serial;
char *name;
int driver_type;
char *fcp_socket;
int best_firmware_version;
snd_ctl_t *handle;
@@ -226,7 +240,7 @@ void alsa_elem_add_callback(
int alsa_get_elem_type(struct alsa_elem *elem);
char *alsa_get_elem_name(struct alsa_elem *elem);
long alsa_get_elem_value(struct alsa_elem *elem);
int *alsa_get_elem_int_values(struct alsa_elem *elem);
long *alsa_get_elem_int_values(struct alsa_elem *elem);
void alsa_set_elem_value(struct alsa_elem *elem, long value);
int alsa_get_elem_writable(struct alsa_elem *elem);
int alsa_get_elem_volatile(struct alsa_elem *elem);

19
src/fcp-shared.c Normal file
View File

@@ -0,0 +1,19 @@
// SPDX-FileCopyrightText: 2024 Geoffrey D. Bennett <g@b4.vu>
// SPDX-License-Identifier: GPL-3.0-or-later
// Error messages
const char *fcp_socket_error_messages[] = {
"Success",
"Invalid magic",
"Invalid command",
"Invalid length",
"Invalid hash",
"Firmware PID does not match USB PID",
"Configuration error (check fcp-server log)",
"FCP communication error",
"Timeout",
"Read error",
"Write error",
"Not running leapfrog firmware",
"Invalid state"
};

80
src/fcp-shared.h Normal file
View File

@@ -0,0 +1,80 @@
// SPDX-FileCopyrightText: 2024 Geoffrey D. Bennett <g@b4.vu>
// SPDX-License-Identifier: GPL-3.0-or-later
#pragma once
#include <stdint.h>
// Error codes
#define FCP_SOCKET_ERR_INVALID_MAGIC 1
#define FCP_SOCKET_ERR_INVALID_COMMAND 2
#define FCP_SOCKET_ERR_INVALID_LENGTH 3
#define FCP_SOCKET_ERR_INVALID_HASH 4
#define FCP_SOCKET_ERR_INVALID_USB_ID 5
#define FCP_SOCKET_ERR_CONFIG 6
#define FCP_SOCKET_ERR_FCP 7
#define FCP_SOCKET_ERR_TIMEOUT 8
#define FCP_SOCKET_ERR_READ 9
#define FCP_SOCKET_ERR_WRITE 10
#define FCP_SOCKET_ERR_NOT_LEAPFROG 11
#define FCP_SOCKET_ERR_INVALID_STATE 12
#define FCP_SOCKET_ERR_MAX 12
// Protocol constants
#define FCP_SOCKET_PROTOCOL_VERSION 1
#define FCP_SOCKET_MAGIC_REQUEST 0x53
#define FCP_SOCKET_MAGIC_RESPONSE 0x73
// Maximum payload length (2MB)
#define MAX_PAYLOAD_LENGTH 2 * 1024 * 1024
// Request types
#define FCP_SOCKET_REQUEST_REBOOT 0x0001
#define FCP_SOCKET_REQUEST_CONFIG_ERASE 0x0002
#define FCP_SOCKET_REQUEST_APP_FIRMWARE_ERASE 0x0003
#define FCP_SOCKET_REQUEST_APP_FIRMWARE_UPDATE 0x0004
#define FCP_SOCKET_REQUEST_ESP_FIRMWARE_UPDATE 0x0005
// Response types
#define FCP_SOCKET_RESPONSE_VERSION 0x00
#define FCP_SOCKET_RESPONSE_SUCCESS 0x01
#define FCP_SOCKET_RESPONSE_ERROR 0x02
#define FCP_SOCKET_RESPONSE_PROGRESS 0x03
extern const char *fcp_socket_error_messages[];
// Message structures
#pragma pack(push, 1)
struct fcp_socket_msg_header {
uint8_t magic;
uint8_t msg_type;
uint32_t payload_length;
};
struct firmware_payload {
uint32_t size;
uint16_t usb_vid;
uint16_t usb_pid;
uint8_t sha256[32];
uint8_t md5[16];
uint8_t data[];
};
struct version_msg {
struct fcp_socket_msg_header header;
uint8_t version;
};
struct progress_msg {
struct fcp_socket_msg_header header;
uint8_t percent;
};
struct error_msg {
struct fcp_socket_msg_header header;
int16_t error_code;
};
#pragma pack(pop)

220
src/fcp-socket.c Normal file
View File

@@ -0,0 +1,220 @@
// SPDX-FileCopyrightText: 2024 Geoffrey D. Bennett <g@b4.vu>
// SPDX-License-Identifier: GPL-3.0-or-later
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/time.h>
#include <fcntl.h>
#include "fcp-shared.h"
#include "fcp-socket.h"
#include "error.h"
// Connect to the FCP socket server for the given card
int fcp_socket_connect(struct alsa_card *card) {
if (!card || !card->fcp_socket) {
fprintf(stderr, "FCP socket path is not available");
return -1;
}
int sock_fd = socket(AF_UNIX, SOCK_STREAM, 0);
if (sock_fd < 0) {
fprintf(stderr, "Cannot create socket: %s", strerror(errno));
return -1;
}
struct sockaddr_un addr = {
.sun_family = AF_UNIX
};
strncpy(addr.sun_path, card->fcp_socket, sizeof(addr.sun_path) - 1);
if (connect(sock_fd, (struct sockaddr*)&addr, sizeof(addr)) < 0) {
fprintf(stderr, "Cannot connect to server at %s: %s",
addr.sun_path, strerror(errno));
close(sock_fd);
return -1;
}
return sock_fd;
}
// Send a simple command with no payload to the server
int fcp_socket_send_command(int sock_fd, uint8_t command) {
struct fcp_socket_msg_header header = {
.magic = FCP_SOCKET_MAGIC_REQUEST,
.msg_type = command,
.payload_length = 0
};
if (write(sock_fd, &header, sizeof(header)) != sizeof(header)) {
fprintf(stderr, "Error sending command: %s", strerror(errno));
return -1;
}
return 0;
}
// Handle server responses from a command
int fcp_socket_handle_response(int sock_fd, bool show_progress) {
struct fcp_socket_msg_header header;
ssize_t bytes_read;
// Read response header
bytes_read = read(sock_fd, &header, sizeof(header));
if (bytes_read != sizeof(header)) {
if (bytes_read == 0) {
// Server closed the connection
return 0;
}
fprintf(stderr, "Error reading response header: %s", strerror(errno));
return -1;
}
// Verify the magic value
if (header.magic != FCP_SOCKET_MAGIC_RESPONSE) {
fprintf(stderr, "Invalid response magic: 0x%02x", header.magic);
return -1;
}
// Handle different response types
switch (header.msg_type) {
case FCP_SOCKET_RESPONSE_VERSION: {
// Protocol version response
uint8_t version;
bytes_read = read(sock_fd, &version, sizeof(version));
if (bytes_read != sizeof(version)) {
fprintf(stderr, "Error reading version: %s", strerror(errno));
return -1;
}
// Protocol version mismatch?
if (version != FCP_SOCKET_PROTOCOL_VERSION) {
fprintf(stderr, "Protocol version mismatch: expected %d, got %d",
FCP_SOCKET_PROTOCOL_VERSION, version);
return -1;
}
break;
}
case FCP_SOCKET_RESPONSE_SUCCESS:
// Command completed successfully
return 0;
case FCP_SOCKET_RESPONSE_ERROR: {
// Error response
int16_t error_code;
bytes_read = read(sock_fd, &error_code, sizeof(error_code));
if (bytes_read != sizeof(error_code)) {
fprintf(stderr, "Error reading error code: %s", strerror(errno));
return -1;
}
if (error_code > 0 && error_code <= FCP_SOCKET_ERR_MAX) {
fprintf(stderr, "Server error: %s", fcp_socket_error_messages[error_code]);
} else {
fprintf(stderr, "Unknown server error code: %d", error_code);
}
return -1;
}
case FCP_SOCKET_RESPONSE_PROGRESS: {
// Progress update
if (show_progress) {
uint8_t percent;
bytes_read = read(sock_fd, &percent, sizeof(percent));
if (bytes_read != sizeof(percent)) {
fprintf(stderr, "Error reading progress: %s", strerror(errno));
return -1;
}
fprintf(stderr, "\rProgress: %d%%", percent);
if (percent == 100)
fprintf(stderr, "\n");
} else {
// Skip the progress byte
uint8_t dummy;
if (read(sock_fd, &dummy, sizeof(dummy)) < 0) {
fprintf(stderr, "Error reading progress: %s", strerror(errno));
return -1;
}
}
// Continue reading responses
return fcp_socket_handle_response(sock_fd, show_progress);
}
default:
fprintf(stderr, "Unknown response type: 0x%02x", header.msg_type);
return -1;
}
return 0;
}
// Wait for server to disconnect (used after reboot command)
int fcp_socket_wait_for_disconnect(int sock_fd) {
fd_set rfds;
struct timeval tv, start_time, now;
char buf[1];
const int TIMEOUT_SECS = 2;
gettimeofday(&start_time, NULL);
while (1) {
FD_ZERO(&rfds);
FD_SET(sock_fd, &rfds);
gettimeofday(&now, NULL);
int elapsed = now.tv_sec - start_time.tv_sec;
if (elapsed >= TIMEOUT_SECS) {
fprintf(stderr, "Timeout waiting for server disconnect\n");
return -1;
}
tv.tv_sec = TIMEOUT_SECS - elapsed;
tv.tv_usec = 0;
int ret = select(sock_fd + 1, &rfds, NULL, NULL, &tv);
if (ret < 0) {
if (errno == EINTR)
continue;
fprintf(stderr, "Select error: %s\n", strerror(errno));
return -1;
}
if (ret > 0) {
// Try to read one byte
ssize_t n = read(sock_fd, buf, 1);
if (n < 0) {
if (errno == EINTR || errno == EAGAIN)
continue;
fprintf(stderr, "Read error: %s\n", strerror(errno));
return -1;
}
if (n == 0) {
// EOF received - server has disconnected
return 0;
}
// Ignore any data received, just keep waiting for EOF
}
}
}
// Reboot a device using the FCP socket interface
int fcp_socket_reboot_device(struct alsa_card *card) {
int sock_fd, ret = -1;
sock_fd = fcp_socket_connect(card);
if (sock_fd < 0)
return -1;
// Send reboot command and wait for server to disconnect
if (fcp_socket_send_command(sock_fd, FCP_SOCKET_REQUEST_REBOOT) == 0)
ret = fcp_socket_wait_for_disconnect(sock_fd);
close(sock_fd);
return ret;
}

27
src/fcp-socket.h Normal file
View File

@@ -0,0 +1,27 @@
// SPDX-FileCopyrightText: 2024 Geoffrey D. Bennett <g@b4.vu>
// SPDX-License-Identifier: GPL-3.0-or-later
#pragma once
#include <stdbool.h>
#include "alsa.h"
// Connect to the FCP socket server for the given card
// Returns socket file descriptor on success, -1 on error
int fcp_socket_connect(struct alsa_card *card);
// Send a simple command with no payload to the server
// Returns 0 on success, -1 on error
int fcp_socket_send_command(int sock_fd, uint8_t command);
// Handle server responses from a command
// Returns 0 on success, -1 on error
int fcp_socket_handle_response(int sock_fd, bool show_progress);
// Wait for server to disconnect (used after reboot command)
// Returns 0 if disconnected, -1 on timeout or error
int fcp_socket_wait_for_disconnect(int sock_fd);
// Reboot a device using the FCP socket interface
// Returns 0 on success, -1 on error
int fcp_socket_reboot_device(struct alsa_card *card);

View File

@@ -1490,16 +1490,25 @@ static void gtk_dial_drag_gesture_update(
double offset_y,
GtkDial *dial
) {
double start_x, start_y;
gtk_gesture_drag_get_start_point(gesture, &start_x, &start_y);
double mn = gtk_adjustment_get_lower(dial->adj);
double mx = gtk_adjustment_get_upper(dial->adj);
gboolean is_linear = gtk_dial_get_is_linear(dial);
double valp;
// add a 1px deadband to prevent double-click with zero mouse
// movement from changing the value from the toggled -inf/0dB value
// (sometimes we see an offset_y value that rounds to +/- 1 which
// causes the value to change after the double-click has set the
// value)
if (offset_y < -1) {
offset_y += 1;
} else if (offset_y < 1) {
offset_y = 0;
} else {
offset_y -= 1;
}
if (is_linear) {
double step = gtk_adjustment_get_step_increment(dial->adj);

117
src/iface-waiting.c Normal file
View File

@@ -0,0 +1,117 @@
// SPDX-FileCopyrightText: 2025 Geoffrey D. Bennett <g@b4.vu>
// SPDX-License-Identifier: GPL-3.0-or-later
#include <gtk/gtk.h>
#include "alsa.h"
#include "iface-waiting.h"
#include "scarlett2-ioctls.h"
#include "window-iface.h"
// Structure to hold timeout-related widgets
struct timeout_data {
GtkWidget *box;
GtkWidget *spinner;
GtkWidget *message_label;
guint timeout_id;
};
// Timeout callback function
static gboolean on_timeout(gpointer user_data) {
struct timeout_data *data = (struct timeout_data *)user_data;
// Remove spinner
gtk_box_remove(GTK_BOX(data->box), data->spinner);
// Update message with clickable link
if (data->message_label && GTK_IS_WIDGET(data->message_label))
gtk_label_set_markup(
GTK_LABEL(data->message_label),
"Driver not detected. Please ensure "
"<span font='monospace'>fcp-server</span> from "
"<a href=\"https://github.com/geoffreybennett/fcp-support\">"
"https://github.com/geoffreybennett/fcp-support</a> "
"has been installed."
);
// Reset the timeout ID since it won't be called again
data->timeout_id = 0;
// Return FALSE to prevent the timeout from repeating
return FALSE;
}
// Weak reference callback for cleanup
static void on_widget_dispose(gpointer data, GObject *where_the_object_was) {
struct timeout_data *timeout_data = (struct timeout_data *)data;
// Cancel the timeout if it's still active
if (timeout_data->timeout_id > 0)
g_source_remove(timeout_data->timeout_id);
// Free the data structure
g_free(timeout_data);
}
GtkWidget *create_iface_waiting_main(struct alsa_card *card) {
struct timeout_data *data;
// Main vertical box
GtkWidget *box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 20);
gtk_widget_set_margin_start(box, 40);
gtk_widget_set_margin_end(box, 40);
gtk_widget_set_margin_top(box, 40);
gtk_widget_set_margin_bottom(box, 40);
// Heading
GtkWidget *label = gtk_label_new(NULL);
gtk_label_set_markup(GTK_LABEL(label),
"<span weight='bold' size='large'>Waiting for FCP Server</span>");
gtk_box_append(GTK_BOX(box), label);
// Add picture (scaled down properly)
GtkWidget *picture_box = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
gtk_widget_set_hexpand(picture_box, TRUE);
gtk_widget_set_halign(picture_box, GTK_ALIGN_CENTER);
GtkWidget *picture = gtk_picture_new_for_resource(
"/vu/b4/alsa-scarlett-gui/icons/vu.b4.alsa-scarlett-gui.png"
);
gtk_picture_set_can_shrink(GTK_PICTURE(picture), TRUE);
gtk_widget_set_size_request(picture, 128, 128);
gtk_box_append(GTK_BOX(picture_box), picture);
gtk_box_append(GTK_BOX(box), picture_box);
// Add spinner
GtkWidget *spinner = gtk_spinner_new();
gtk_spinner_start(GTK_SPINNER(spinner));
gtk_widget_set_size_request(spinner, 48, 48);
gtk_box_append(GTK_BOX(box), spinner);
// Description
label = gtk_label_new(
"Waiting for the user-space FCP driver to initialise..."
);
gtk_label_set_wrap(GTK_LABEL(label), TRUE);
gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_CENTER);
gtk_label_set_max_width_chars(GTK_LABEL(label), 1);
gtk_widget_set_hexpand(label, TRUE);
gtk_widget_set_halign(label, GTK_ALIGN_FILL);
gtk_box_append(GTK_BOX(box), label);
// Setup timeout
data = g_new(struct timeout_data, 1);
data->box = box;
data->spinner = spinner;
data->message_label = label;
// Set timeout
data->timeout_id = g_timeout_add_seconds(5, on_timeout, data);
// Ensure data is freed when the box is destroyed
g_object_weak_ref(G_OBJECT(box), on_widget_dispose, data);
return box;
}

8
src/iface-waiting.h Normal file
View File

@@ -0,0 +1,8 @@
// SPDX-FileCopyrightText: 2025 Geoffrey D. Bennett <g@b4.vu>
// SPDX-License-Identifier: GPL-3.0-or-later
#pragma once
#include "alsa.h"
GtkWidget *create_iface_waiting_main(struct alsa_card *card);

View File

@@ -30,13 +30,9 @@ struct hw_info gen_2_info[] = {
{ }
};
struct hw_info gen_3_small_info[] = {
struct hw_info gen_3_info[] = {
{ "Scarlett Solo 3rd Gen" },
{ "Scarlett 2i2 3rd Gen" },
{ }
};
struct hw_info gen_3_big_info[] = {
{ "Scarlett 4i4 3rd Gen" },
{ "Scarlett 8i6 3rd Gen" },
{ "Scarlett 18i8 3rd Gen" },
@@ -48,6 +44,9 @@ struct hw_info gen_4_info[] = {
{ "Scarlett Solo 4th Gen" },
{ "Scarlett 2i2 4th Gen" },
{ "Scarlett 4i4 4th Gen" },
{ "Scarlett 16i16 4th Gen" },
{ "Scarlett 18i16 4th Gen" },
{ "Scarlett 18i20 4th Gen" },
{ }
};
@@ -65,6 +64,12 @@ struct hw_info clarett_plus_info[] = {
{ }
};
struct hw_info vocaster_info[] = {
{ "Vocaster One" },
{ "Vocaster Two" },
{ }
};
struct hw_cat hw_cat[] = {
{ "1st Gen",
gen_1_info
@@ -72,11 +77,8 @@ struct hw_cat hw_cat[] = {
{ "2nd Gen",
gen_2_info
},
{ "Small 3rd Gen",
gen_3_small_info
},
{ "Big 3rd Gen",
gen_3_big_info
{ "3rd Gen",
gen_3_info
},
{ "4th Gen",
gen_4_info
@@ -87,6 +89,9 @@ struct hw_cat hw_cat[] = {
{ "Clarett+",
clarett_plus_info
},
{ "Vocaster",
vocaster_info
},
{ }
};

View File

@@ -8,6 +8,7 @@
#include "iface-none.h"
#include "iface-unknown.h"
#include "iface-update.h"
#include "iface-waiting.h"
#include "main.h"
#include "menu.h"
#include "window-iface.h"
@@ -21,11 +22,34 @@ void create_card_window(struct alsa_card *card) {
gtk_window_destroy(GTK_WINDOW(no_cards_window));
no_cards_window = NULL;
}
window_count++;
// Replacing an existing window
if (card->window_main)
gtk_window_destroy(GTK_WINDOW(card->window_main));
// New window
else
window_count++;
int has_startup = true;
int has_mixer = true;
// Check if the FCP driver is not initialised yet
if (card->driver_type == DRIVER_TYPE_SOCKET_UNINIT) {
card->window_main_contents = create_iface_waiting_main(card);
has_startup = false;
has_mixer = false;
// Create minimal window with only the waiting interface
card->window_main = gtk_application_window_new(app);
gtk_window_set_resizable(GTK_WINDOW(card->window_main), FALSE);
gtk_window_set_title(GTK_WINDOW(card->window_main), card->name);
gtk_window_set_child(GTK_WINDOW(card->window_main), card->window_main_contents);
gtk_widget_set_visible(card->window_main, TRUE);
return;
}
struct alsa_elem *msd_elem =
get_elem_by_name(card->elems, "MSD Mode Switch");
int in_msd_mode = msd_elem && alsa_get_elem_value(msd_elem);
@@ -54,6 +78,7 @@ void create_card_window(struct alsa_card *card) {
// Scarlett Gen 1
} else if (get_elem_by_prefix(card->elems, "Matrix")) {
card->window_main_contents = create_iface_mixer_main(card);
has_startup = false;
// Scarlett Gen 2, Gen 3 4i4+, Gen 4, Clarett, or Vocaster
} else if (get_elem_by_prefix(card->elems, "Mixer")) {

View File

@@ -38,7 +38,7 @@ static int update_levels_controls(void *user_data) {
struct alsa_elem *level_meter_elem = data->level_meter_elem;
int *values = alsa_get_elem_int_values(level_meter_elem);
long *values = alsa_get_elem_int_values(level_meter_elem);
gtk_dial_peak_tick();

View File

@@ -279,9 +279,10 @@ static void create_routing_grid(struct alsa_card *card) {
routing_grid, card->routing_dsp_out_grid, dsp_col_num, 3, 1, 1
);
}
gtk_grid_attach(
routing_grid, card->routing_mixer_in_grid, mix_col_num, 0, 1, 1
);
if (!card->has_fixed_mixer_inputs)
gtk_grid_attach(
routing_grid, card->routing_mixer_in_grid, mix_col_num, 0, 1, 1
);
gtk_grid_attach(
routing_grid, card->routing_mixer_out_grid, mix_col_num, 3, 1, 1
);

View File

@@ -3,6 +3,7 @@
#include "device-reset-config.h"
#include "device-update-firmware.h"
#include "fcp-socket.h"
#include "gtkhelper.h"
#include "scarlett2.h"
#include "scarlett2-ioctls.h"
@@ -10,8 +11,6 @@
#include "widget-drop-down.h"
#include "window-startup.h"
#define REQUIRED_HWDEP_VERSION_MAJOR 1
static GtkWidget *small_label(const char *text) {
GtkWidget *w = gtk_label_new(NULL);
@@ -238,21 +237,32 @@ static void add_reset_action(
}
static void reboot_device(GtkWidget *button, struct alsa_card *card) {
snd_hwdep_t *hwdep;
int err = 0;
int err = scarlett2_open_card(card->device, &hwdep);
if (err < 0) {
fprintf(stderr, "unable to open hwdep interface: %s\n", snd_strerror(err));
return;
// HWDEP (Scarlett2) driver type
if (card->driver_type == DRIVER_TYPE_HWDEP) {
snd_hwdep_t *hwdep;
err = scarlett2_open_card(card->device, &hwdep);
if (err < 0) {
fprintf(stderr, "unable to open hwdep interface: %s\n", snd_strerror(err));
return;
}
err = scarlett2_reboot(hwdep);
if (err < 0) {
fprintf(stderr, "unable to reboot device: %s\n", snd_strerror(err));
return;
}
scarlett2_close(hwdep);
// Socket (FCP) driver type
} else if (card->driver_type == DRIVER_TYPE_SOCKET) {
err = fcp_socket_reboot_device(card);
if (err < 0)
fprintf(stderr, "unable to reboot device via socket\n");
}
err = scarlett2_reboot(hwdep);
if (err < 0) {
fprintf(stderr, "unable to reboot device: %s\n", snd_strerror(err));
return;
}
scarlett2_close(hwdep);
}
static void add_reset_actions(
@@ -261,38 +271,10 @@ static void add_reset_actions(
int *grid_y,
int show_reboot_option
) {
// simulated cards don't support hwdep
if (!card->device)
if (card->driver_type != DRIVER_TYPE_HWDEP &&
card->driver_type != DRIVER_TYPE_SOCKET)
return;
snd_hwdep_t *hwdep;
int err = scarlett2_open_card(card->device, &hwdep);
if (err < 0) {
fprintf(stderr, "unable to open hwdep interface: %s\n", snd_strerror(err));
return;
}
int ver = scarlett2_get_protocol_version(hwdep);
if (ver < 0) {
fprintf(stderr, "unable to get protocol version: %s\n", snd_strerror(ver));
return;
}
if (SCARLETT2_HWDEP_VERSION_MAJOR(ver) != REQUIRED_HWDEP_VERSION_MAJOR) {
fprintf(
stderr,
"Unsupported hwdep protocol version %d.%d.%d on card %s\n",
SCARLETT2_HWDEP_VERSION_MAJOR(ver),
SCARLETT2_HWDEP_VERSION_MINOR(ver),
SCARLETT2_HWDEP_VERSION_SUBMINOR(ver),
card->device
);
return;
}
scarlett2_close(hwdep);
// Add reboot action if there is a control that requires a reboot
// to take effect
if (show_reboot_option) {
@@ -354,8 +336,7 @@ static void add_reset_actions(
static void add_no_startup_controls_msg(GtkWidget *grid) {
GtkWidget *w = big_label(
"It appears that there are no startup controls. You probably "
"need to upgrade your kernel to see something here."
"This device/driver combo appears to have no startup controls."
);
gtk_grid_attach(GTK_GRID(grid), w, 0, 0, 1, 1);
}

View File

@@ -17,10 +17,45 @@ finish-args:
# Point to the firmware directory
- --env=SCARLETT2_FIRMWARE_DIR=/app/lib/firmware/scarlett2
modules:
- name: alsa-utils
sources:
- type: archive
url: https://www.alsa-project.org/files/pub/lib/alsa-lib-1.2.12.tar.bz2
sha256: 4868cd908627279da5a634f468701625be8cc251d84262c7e5b6a218391ad0d2
dest: .deps/alsa-lib
- type: archive
url: https://www.alsa-project.org/files/pub/utils/alsa-utils-1.2.12.tar.bz2
sha256: 98bc6677d0c0074006679051822324a0ab0879aea558a8f68b511780d30cd924
buildsystem: autotools
config-opts:
# We are only interested in alsactl
- --bindir=/app/null
- --with-udev-rules-dir=/app/null
- --with-systemdsystemunitdir=/app/null
# https://github.com/alsa-project/alsa-utils/issues/33
- --enable-alsa-topology
- --disable-alsaconf
- --disable-alsatest
- --disable-alsabat-backend-tiny
- --disable-alsamixer
- --disable-alsaloop
- --disable-nhlt
- --disable-xmlto
- --disable-rst2man
- --with-alsa-inc-prefix=.deps/alsa-lib/include
post-install:
- install -Dm755 /app/sbin/alsactl /app/bin/alsactl
cleanup:
- /lib/debug
- /lib/alsa-topology
- /null
- /sbin
- /share/alsa
- /share/locale
- /share/man
- /share/runtime
- /share/sounds
- name: alsa-scarlett-gui
buildsystem: simple
build-commands:
- make -j8 install PREFIX=$FLATPAK_DEST
sources:
- type: dir
path: ./src
@@ -28,13 +63,18 @@ modules:
# - type: git
# url: https://github.com/geoffreybennett/alsa-scarlett-gui.git
# tag: "0.2"
- name: scarlett2-firmware
buildsystem: simple
build-commands:
- mkdir -p $FLATPAK_DEST/lib/firmware/scarlett2
- cp -a LICENSE.Focusrite firmware/* $FLATPAK_DEST/lib/firmware/scarlett2
- make -j8 install PREFIX=$FLATPAK_DEST
cleanup:
- /lib/debug
- /lib/source
- name: scarlett2-firmware
sources:
- type: archive
url: https://github.com/geoffreybennett/scarlett2-firmware/archive/refs/tags/2128b.tar.gz
sha256: 4a17fdbe2110855c2f7f6cfc5ea1894943a6e58770f3dff5ef283961f8ae2a03
buildsystem: simple
build-commands:
- mkdir -p $FLATPAK_DEST/lib/firmware/scarlett2
- cp -a LICENSE.Focusrite firmware/* $FLATPAK_DEST/lib/firmware/scarlett2