Merge in upstream version 0.3 to Debian pkg

This commit is contained in:
2025-06-09 20:26:36 -05:00
27 changed files with 16121 additions and 177 deletions

View File

@@ -0,0 +1,56 @@
name: Build debian package
on:
release:
branches: '*'
types: [published]
env:
APP_NAME: alsa-scarlett-gui
APP_VERSION: ${{ github.event.release.tag_name }}
jobs:
build:
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v3
- name: Install build dependencies
run: |
sudo apt -y update
sudo apt -y install git make gcc libgtk-4-dev libasound2-dev
- name: Build from sources
run: |
make -C src -j4 PREFIX=/usr
- name: Prepare package workspace
run: |
mkdir -p ${{ github.workspace }}/deb-workspace/usr/bin \
${{ github.workspace }}/deb-workspace/usr/share/applications \
${{ github.workspace }}/deb-workspace/usr/share/icons/hicolor/256x256/apps \
${{ github.workspace }}/deb-workspace/usr/share/doc/${{ env.APP_NAME }}-${{ env.APP_VERSION }}
cp src/alsa-scarlett-gui ${{ github.workspace }}/deb-workspace/usr/bin/
cp src/vu.b4.alsa-scarlett-gui.desktop ${{ github.workspace }}/deb-workspace/usr/share/applications/
cp src/img/alsa-scarlett-gui.png ${{ github.workspace }}/deb-workspace/usr/share/icons/hicolor/256x256/apps/
cp -r *.md img demo ${{ github.workspace }}/deb-workspace/usr/share/doc/${{ env.APP_NAME }}-${{ env.APP_VERSION }}/
- name: Build debian package
uses: jiro4989/build-deb-action@v2
with:
package: ${{ env.APP_NAME }}
package_root: ${{ github.workspace }}/deb-workspace
maintainer: geoffreybennett
version: ${{ env.APP_VERSION }}
desc: ${{ env.APP_NAME }} is a Gtk4 GUI for the ALSA controls presented by the Linux kernel Focusrite Scarlett Gen 2/3 Mixer Driver.
- name: Upload Release Asset
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ github.event.release.upload_url }}
asset_path: ./${{ env.APP_NAME }}_${{ env.APP_VERSION }}_amd64.deb
asset_name: ${{ env.APP_NAME }}_${{ env.APP_VERSION }}_amd64.deb
asset_content_type: application/vnd.debian.binary-package

View File

@@ -0,0 +1,37 @@
name: Build flatpak package
on:
release:
branches: '*'
types: [published]
env:
APP_NAME: alsa-scarlett-gui
APP_VERSION: ${{ github.event.release.tag_name }}
jobs:
flatpak:
name: "Flatpak"
runs-on: ubuntu-latest
container:
image: bilelmoussaoui/flatpak-github-actions:gnome-45
options: --privileged
steps:
- uses: actions/checkout@v4
- name: Build flatpak package
uses: flatpak/flatpak-github-actions/flatpak-builder@v6
with:
bundle: ${{ env.APP_NAME }}.flatpak
manifest-path: vu.b4.alsa-scarlett-gui.yml
cache-key: flatpak-builder-${{ github.sha }}
- name: Upload Release Asset
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ github.event.release.upload_url }}
asset_path: ./${{ env.APP_NAME }}.flatpak
asset_name: ${{ env.APP_NAME }}_${{ env.APP_VERSION }}.flatpak
asset_content_type: application/octet-stream

2
.gitignore vendored
View File

@@ -5,3 +5,5 @@
alsa-scarlett-gui
alsa-scarlett-gui-resources.c
vu.b4.alsa-scarlett-gui.desktop
.flatpak-builder/
flatpak-build/

158
INSTALL.md Normal file
View File

@@ -0,0 +1,158 @@
# ALSA Scarlett Gen 2/3 Control Panel Installation
## Prerequisites
Linux Kernel with the ALSA Scarlett2 Protocol Driver.
- Use at least version 5.14 for Scarlett Gen 3 support and bug fixes
for the Gen 2 support.
- For Clarett+ 8Pre support, you need 6.1.
- For the other Clarett USB and Clarett+ models, you need 6.7.
- For the level meters to work, you need 6.7.
If you don't have 6.7, you can get the driver from here and build it
for your current kernel:
https://github.com/geoffreybennett/scarlett-gen2/releases/tag/v6.5.11c1
## Enabling the Driver
As of Linux 6.7 the driver is enabled by default and you can skip this
section.
If you're running a kernel before 6.7, the driver needs to be enabled
at module load time with the `device_setup=1` option to
insmod/modprobe. Create a file /etc/modprobe.d/scarlett.conf
containing the appropriate line for your device:
Scarlett Gen 2:
- 6i6: `options snd_usb_audio vid=0x1235 pid=0x8203 device_setup=1`
- 18i8: `options snd_usb_audio vid=0x1235 pid=0x8204 device_setup=1`
- 18i20: `options snd_usb_audio vid=0x1235 pid=0x8201 device_setup=1`
Scarlett Gen 3:
- Solo: `options snd_usb_audio vid=0x1235 pid=0x8211 device_setup=1`
- 2i2: `options snd_usb_audio vid=0x1235 pid=0x8210 device_setup=1`
- 4i4: `options snd_usb_audio vid=0x1235 pid=0x8212 device_setup=1`
- 8i6: `options snd_usb_audio vid=0x1235 pid=0x8213 device_setup=1`
- 18i8: `options snd_usb_audio vid=0x1235 pid=0x8214 device_setup=1`
- 18i20: `options snd_usb_audio vid=0x1235 pid=0x8215 device_setup=1`
Clarett+:
- 8Pre: `options snd_usb_audio vid=0x1235 pid=0x820c device_setup=1`
Or you can use a sledgehammer:
```
options snd_usb_audio device_setup=1,1,1,1
```
to pass that option to the first 4 USB audio devices.
To see if the driver is present and enabled: `dmesg | grep -i -A 5 -B
5 focusrite` should display information like:
```
New USB device found, idVendor=1235, idProduct=8215, bcdDevice= 6.0b
Product: Scarlett 18i20 USB
Focusrite Scarlett Gen 2/3 Mixer Driver enabled pid=0x8215
```
If the driver is disabled youll see a message like:
```
Focusrite Scarlett Gen 2/3 Mixer Driver disabled; use options
snd_usb_audio vid=0x1235 pid=0x8215 device_setup=1 to enable and
report any issues to g@b4.vu",
```
## Building and Running
On Fedora, the packages `alsa-lib-devel` and `gtk4-devel` need to be
installed:
```
sudo dnf -y install alsa-lib-devel gtk4-devel
```
On Ubuntu 22.04:
```
sudo apt -y install git make gcc libgtk-4-dev libasound2-dev
```
To download from github:
```
git clone https://github.com/geoffreybennett/alsa-scarlett-gui
cd alsa-scarlett-gui
```
To build:
```
cd src
make -j4
```
To run:
```
./alsa-scarlett-gui
```
You can install it into `/usr/local` (binary, desktop file, and icon)
with:
```
sudo make install
```
And uninstall with:
```
sudo make uninstall
```
Continue on to reading [USAGE.md](USAGE.md) for usage information and
known issues.
## Flatpak
With Flatpak, in any distro:
```
flatpak-builder --user --install --force-clean flatpak-build \
vu.b4.alsa-scarlett-gui.yml
```
Be sure to use `flatpak-build` as the directory where the flatpak is
built or hence you risk bundling the artifacts when comitting!
If you get messages like these:
```
Failed to init: Unable to find sdk org.gnome.Sdk version 45
Failed to init: Unable to find runtime org.gnome.Platform version 45
```
Then install them:
```
flatpak install org.gnome.Sdk
flatpak install org.gnome.Platform
```
If you get:
```
Looking for matches…
error: No remote refs found for org.gnome.Sdk
```
Then:
```
flatpak remote-add --user --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo
```

View File

@@ -355,7 +355,7 @@ driver hides this from you.
- 19× Hardware Inputs
- Analogue 12: Mic/Line/Inst In 12 (Air, Pad)
- Analogue 38: Mic/Line In 34 (Air, Pad)
- Analogue 38: Mic/Line In 38 (Air, Pad)
- Analogue 9: Talkback Mic
- S/PDIF 12
- ADAT 18

View File

@@ -1,30 +1,35 @@
# ALSA Scarlett Gen 2/3 Control Panel (`alsa-scarlett-gui`)
`alsa-scarlett-gui` is a Gtk4 GUI for the ALSA controls presented by
the Linux kernel Focusrite Scarlett Gen 2/3 Mixer Driver.
the Linux kernel Focusrite Scarlett Gen 2/3/Clarett USB/Clarett+ Mixer
Driver.
## About
<img src="src/img/alsa-scarlett-gui-logo.png" align="right">
The Focusrite Scarlett interfaces are class compliant USB audio
interfaces meaning that they work “out of the box” on Linux as audio
and MIDI interfaces (although on Gen 3 you need to disable MSD mode
first). However, the Gen 2 6i6+ and Gen 3 4i4+ interfaces have a bunch
of proprietary functionality that required a kernel driver to be
written specifically for those devices.
The 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 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.
Linux kernel support (“ALSA Focusrite Scarlett Gen 2/3 Mixer Driver”)
for the proprietary functionality of Gen 2 devices was first added in
5.4 and Gen 3 devices in 5.14.
for the proprietary functionality was first added in:
- Scarlett Gen 2: Linux 5.4 (bugs fixed in Linux 5.14)
- Scarlett Gen 3: Linux 5.14
- Clarett+ 8Pre: Linux 6.1
- Clarett 2Pre/4Pre/8Pre USB, Clarett+ 2Pre/4Pre: Linux 6.7
Unfortunately, actually using this functionality was quite awful. 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.
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 Gen 2/3 Control Panel!
Announcing the ALSA Scarlett Gen 2/3 (and Clarett USB/Clarett+!)
Control Panel!
![Demonstration](img/demo.gif)
@@ -33,28 +38,43 @@ report a bug).
## Documentation
Refer to [USAGE.md](USAGE.md) for prerequisites, instructions, usage
information, and known issues.
Refer to [INSTALL.md](INSTALL.md) for prerequisites, how to build,
install, and run.
Refer to [USAGE.md](USAGE.md) for usage information and known issues.
## Donations
This program is Free Software, developed using my personal resources,
over hundreds of hours. Focusrite did not support the development of
the driver or this control panel in any way. Thanks to Laurent
Debricon who got me started on the Gen 3 drivers by donating a 4i4.
over hundreds of hours.
If you like it, please consider a donation to say thank you as it was
expensive to purchase one of each model for development and testing!
Any donation is appreciated.
If you like this software, please consider a donation to say thank you
as it was expensive to purchase one of each model for development and
testing! Any donation is appreciated.
- https://liberapay.com/gdb
- https://paypal.me/gdbau
Thank you!
## Scarlett Gen 4 Support
Focusrite recently released 3 new "Generation 4" interfaces: Solo,
2i2, and 4i4. Thanks to all the Linux Musicians who donated so I could
purchase one of each Gen 4 interface: https://gofund.me/ae997781,
support for these is coming soon.
The overwhelming response to the GoFundMe also got the attention of
Focusrite. They offered to send me any devices that I didn't already
have, and also said that for any future product releases, they will do
their utmost to send me devices in advance.
## Vocaster Support
Vocaster One and Two support will be coming once I've completed the
Scarlett 4th Gen support.
## License
Copyright 2022 Geoffrey D. Bennett
Copyright 2022-2023 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
@@ -71,7 +91,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
## Disclaimer Third Parties
Focusrite and Scarlett 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.
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.

117
USAGE.md
View File

@@ -1,95 +1,16 @@
# ALSA Scarlett Gen 2/3 Control Panel Usage
## Prerequisites
Refer to [INSTALL.md](INSTALL.md) for prerequisites, how to build,
install, and run.
Linux Kernel with the ALSA Scarlett Gen 2/3 mixer driver. Use at least
version 5.14 for Scarlett Gen 3 support and bug fixes for the Gen 2
support.
As of Linux 5.17, the driver is still disabled by default and needs to
be enabled at module load time with the `device_setup=1` option to
insmod/modprobe. Create a file /etc/modprobe.d/scarlett.conf
containing the appropriate line for your device:
Gen 2:
- 6i6: `options snd_usb_audio vid=0x1235 pid=0x8203 device_setup=1`
- 18i8: `options snd_usb_audio vid=0x1235 pid=0x8204 device_setup=1`
- 18i20: `options snd_usb_audio vid=0x1235 pid=0x8201 device_setup=1`
Gen 3:
- Solo: `options snd_usb_audio vid=0x1235 pid=0x8211 device_setup=1`
- 2i2: `options snd_usb_audio vid=0x1235 pid=0x8210 device_setup=1`
- 4i4: `options snd_usb_audio vid=0x1235 pid=0x8212 device_setup=1`
- 8i6: `options snd_usb_audio vid=0x1235 pid=0x8213 device_setup=1`
- 18i8: `options snd_usb_audio vid=0x1235 pid=0x8214 device_setup=1`
- 18i20: `options snd_usb_audio vid=0x1235 pid=0x8215 device_setup=1`
Or you can use a sledgehammer:
```
options snd_usb_audio device_setup=1,1,1,1
```
to pass that option to the first 4 USB audio devices.
To see if the driver is present and enabled: `dmesg | grep -i -A 5 -B
5 scarlett` should display information like:
```
New USB device found, idVendor=1235, idProduct=8215, bcdDevice= 6.0b
Product: Scarlett 18i20 USB
Focusrite Scarlett Gen 2/3 Mixer Driver enabled pid=0x8215
```
If the driver is disabled youll see a message like:
```
Focusrite Scarlett Gen 2/3 Mixer Driver disabled; use options
snd_usb_audio vid=0x1235 pid=0x8215 device_setup=1 to enable and
report any issues to g@b4.vu",
```
## Building and Running
On Fedora, the packages `alsa-lib-devel` and `gtk4-devel` need to be
installed:
```
sudo dnf -y install alsa-lib-devel gtk4-devel
```
To build:
```
cd src
make -j4
```
To run:
```
./alsa-scarlett-gui
```
You can install it into `/usr/local` (binary, desktop file, and icon)
with:
```
sudo make install
```
And uninstall with:
```
sudo make uninstall
```
For usage instructions, read on...
## No interface connected
If no interface is detected (usually because there isnt one
connected!) youll see this window:
![MSD Mode](img/iface-none.png)
![No Interface Connected](img/iface-none.png)
Plug in an interface or select the menu option File → Interface
Simulation and load a demo file to make more interesting things
@@ -125,11 +46,11 @@ The one control not accessible from the front panel is “Phantom Power
Persistence” (menu option View → Startup) which controls the Phantom
Power state when the interface is powered on.
## Gen 2 6i6+ and Gen 3 4i4+ Interfaces
## Gen 2 6i6+, Gen 3 4i4+, Clarett USB, and Clarett+ Interfaces
The Gen 2 6i6+ and Gen 3 4i4+ interfaces have many controls available.
The controls are split between 4 windows, 3 of which are by default
hidden.
The Gen 2 6i6+, Gen 3 4i4+, and Clarett interfaces have many controls
available. The controls are split between 4 windows, 3 of which are by
default hidden.
The main window has:
- Global Controls
@@ -223,7 +144,7 @@ level/impedance. When plugging in microphones or line-level equipment
to the input, set it to “Line”. The “Inst” setting is for instrument
with pickups such as guitars.
#### Air (Gen 3 only)
#### Air (Gen 3, Clarett USB, and Clarett+ only)
Enabling Air will transform your recordings and inspire you while
making music.
@@ -250,7 +171,7 @@ configuration (menu option View → Startup).
### Analogue Output Controls
The analogue output controls let you set the output volume (gain) on
the analogue line out and headphones outputs. All interfaces support
the analogue line out and headphone outputs. All interfaces support
setting the gain and muting individual channels.
Click and drag up/down to change the volume, or use your mouse scroll
@@ -272,7 +193,7 @@ channels are disabled.
There are “mute” and “dim” (reduce volume) buttons below the “HW” dial
which affect only the outputs with “HW” control enabled. The Gen 3
18i8 doesnt have physical buttons or indicator lights for these
control, but the 18i20 devices do.
controls, but the 18i20 devices do.
On the other (smaller) interfaces, the big volume knob on the front of
the interface controls the volume of the Line 1 and 2 outputs. This is
@@ -329,13 +250,13 @@ configuration:
#### Loopback
Gen 2 interfaces have as many PCM Inputs as Hardware Inputs. Gen 3
interfaces have two more PCM Inputs which the proprietary driver
restricts to being “Loopback” inputs.
Gen 2, Clarett USB, and Clarett+ interfaces have as many PCM Inputs as
Hardware Inputs. Gen 3 interfaces have two more PCM Inputs which
Focusrite Control uses as “Loopback” inputs.
The “Loopback” feature advertised for Gen 3 devices is actually a
limitation of the propretary Focusrite Control software. Both Gen 2
and Gen 3 devices support full reassignment of the PCM Inputs, so you
limitation of the proprietary Focusrite Control software. All devices
(except Solo/2i2) support full reassignment of the PCM Inputs, so you
can have any PCM Input as a “Loopback” or assigned to any other
source.
@@ -351,7 +272,7 @@ to a PCM Input.
If you use the Routing window to connect Sources to Mixer Inputs and
Mixer Outputs to Destinations, then you can use the Mixer window to
set the amount of each Mixer Input that is sent to each Mixer Output
using a matrix of controls.
using a matrix of controls:
![Mixer Window](img/window-mixer.png)
@@ -433,8 +354,8 @@ menu option File → Interface Simulation to load.
- Cant select (focus) the gain/volume controls or use a keyboard to
adjust them.
- Level (monitoring) doesnt work yet and is disabled (needs kernel
driver update).
- Level meters dont work if you're not running the driver from Linux
6.7.
- Load/Save uses `alsactl` which will be confused if the ALSA
interface name (e.g. `USB`) changes.

View File

@@ -30,4 +30,4 @@ cp demo/* $DOCDIR/demo
%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/alsa-scarlett-gui.png
/usr/share/icons/hicolor/256x256/apps/vu.b4.alsa-scarlett-gui.png

4147
demo/Clarett Plus 2Pre.state Normal file

File diff suppressed because it is too large Load Diff

5041
demo/Clarett Plus 4Pre.state Normal file

File diff suppressed because it is too large Load Diff

6455
demo/Clarett Plus 8Pre.state Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -10,6 +10,7 @@ DEPFLAGS = -MT $@ -MMD -MP -MF $(DEPDIR)/$*.d
CFLAGS := -Wall -Werror -ggdb -fno-omit-frame-pointer -O2 -D_FORTIFY_SOURCE=2
CFLAGS += -DVERSION=\"$(VERSION)\"
CFLAGS += -Wno-error=deprecated-declarations
PKG_CONFIG=pkg-config
@@ -37,7 +38,9 @@ XML_OBJ := $(patsubst %.xml,%.c,$(XML_SRC))
SRCS := $(sort $(wildcard *.c) $(XML_OBJ))
OBJS := $(patsubst %.c,%.o,$(SRCS))
TARGET := alsa-scarlett-gui
DESKTOP_FILE := vu.b4.$(TARGET).desktop
DOMAIN_PREFIX := vu.b4
DESKTOP_FILE := $(DOMAIN_PREFIX).$(TARGET).desktop
ICON_FILE := $(DOMAIN_PREFIX).$(TARGET).png
GLIB_COMPILE_RESOURCES := $(shell $(PKG_CONFIG) --variable=glib_compile_resources gio-2.0)
@@ -75,13 +78,13 @@ install: all
install -d $(BINDIR)
install -m 755 $(TARGET) $(BINDIR)
install -d $(ICONDIR)
install -m 644 img/$(TARGET).png $(ICONDIR)
install -m 644 img/$(ICON_FILE) $(ICONDIR)
install -d $(DESKTOPDIR)
install -m 644 $(DESKTOP_FILE) $(DESKTOPDIR)
uninstall:
rm -f $(BINDIR)/$(TARGET)
rm -f $(ICONDIR)/$(TARGET).png
rm -f $(ICONDIR)/$(ICON_FILE)
rm -f $(DESKTOPDIR)/$(DESKTOP_FILE)
help:

View File

@@ -1,9 +1,11 @@
.route-label {
font-size: smaller;
border-radius: 3px;
}
.route-label:hover {
background: @theme_selected_bg_color;
outline: 2px solid @theme_selected_bg_color;
}
.route-label:drop(active) {

View File

@@ -505,7 +505,8 @@ void alsa_scan_cards(void) {
if (err < 0)
goto next;
if (strncmp(snd_ctl_card_info_get_name(info), "Scarlett", 8) != 0)
if (strncmp(snd_ctl_card_info_get_name(info), "Scarlett", 8) != 0 &&
strncmp(snd_ctl_card_info_get_name(info), "Clarett", 7) != 0)
goto next;
// is there already an entry for this card in alsa_cards?

View File

@@ -14,6 +14,7 @@ void show_error(GtkWindow *w, char *s) {
GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_MODAL,
GTK_MESSAGE_ERROR,
GTK_BUTTONS_CLOSE,
"%s",
s
);
gtk_widget_show(dialog);

View File

@@ -15,7 +15,7 @@ static void run_alsactl(
GtkWindow *w = GTK_WINDOW(card->window_main);
gchar *argv[] = {
"alsactl", cmd, card->device, "-f", fn, NULL
"/usr/sbin/alsactl", cmd, card->device, "-f", fn, NULL
};
gchar *stdout;
gchar *stderr;

View File

@@ -141,7 +141,19 @@ static void dial_measure(GtkWidget *widget,
static inline double calc_valp(double val, double mn, double mx)
{
return (val - mn)/(mx-mn);
if (val <= mn)
return 0.0;
if (val >= mx)
return 1.0;
// convert val from mn..mx to 0..1
val = (val - mn)/(mx-mn);
// 10^(val - 1) converts it to 0.1..1 with a nice curve
val = pow(10, val - 1);
// convert to 0..1 again
return (val - 0.1) / 0.9;
}
static inline double calc_val(double valp, double mn, double mx)

View File

@@ -155,9 +155,8 @@ static void create_input_controls(
) {
GArray *elems = card->elems;
// there's consistently a pad capture for each analogue input that
// has a control
int input_count = get_max_elem_by_name(elems, "Line", "Pad Capture Switch");
// find how many inputs have switches
int input_count = get_max_elem_by_name(elems, "Line", "Capture Switch");
// Only the 18i20 Gen 2 has no input controls
if (!input_count)

Binary file not shown.

After

Width:  |  Height:  |  Size: 61 KiB

View File

@@ -125,7 +125,7 @@ GMenu *create_app_menu(GtkApplication *app) {
g_menu_append_submenu(menu, "_View", G_MENU_MODEL(view_menu));
g_menu_append(view_menu, "_Routing", "win.routing");
g_menu_append(view_menu, "_Mixer", "win.mixer");
//g_menu_append(view_menu, "_Levels", "win.levels");
g_menu_append(view_menu, "_Levels", "win.levels");
g_menu_append(view_menu, "_Startup", "win.startup");
GMenu *help_menu = g_menu_new();

View File

@@ -17,37 +17,55 @@ static void choose_line_colour(
double *g,
double *b
) {
int odd_in = r_src->lr_num & 1;
int odd_out = r_dst->elem->lr_num & 1;
int in2 = ((r_src->lr_num - 1) / 2 & 1);
int out2 = ((r_dst->elem->lr_num - 1) / 2 & 1);
// left channels have odd numbers
// right channels have even numbers
int odd_src = r_src->lr_num & 1;
int odd_dst = r_dst->elem->lr_num & 1;
if (odd_in && odd_out) {
// for colouring, pair channels up
// 0 for odd pairs, 1 for even pairs
int src2 = ((r_src->lr_num - 1) / 2 & 1);
int dst2 = ((r_dst->elem->lr_num - 1) / 2 & 1);
// left -> left, black
if (odd_src && odd_dst) {
*r = 0;
*g = 0;
*b = 0;
} else if (!odd_in && !odd_out) {
// right -> right, red
} else if (!odd_src && !odd_dst) {
*r = 1;
*g = 0;
*b = 0;
} else if (odd_in) {
// left -> right, dark green
} else if (odd_src) {
*r = 0;
*g = 0.25;
*b = 0;
// right -> left, dark brown/olive
} else {
*r = 0.25;
*g = 0.25;
*b = 0;
}
// mix <-> non-mix, add blue
if ((r_src->port_category == PC_MIX) !=
(r_dst->port_category == PC_MIX)) {
*b = 0.5;
}
if (in2) {
// even input pairs, lighten red and green components
if (src2) {
*r = (*r + 1) / 2;
*g = (*g + 1) / 2;
}
if (out2) {
// even output pairs, lighten blue component
if (dst2) {
*b = (*b + 1) / 2;
}
}

View File

@@ -1,9 +1,7 @@
[Desktop Entry]
Encoding=UTF-8
Value=1.5
Type=Application
Name=ALSA Scarlett Gen 2/3 Control Panel
Icon=alsa-scarlett-gui
Icon=vu.b4.alsa-scarlett-gui
Exec=PREFIX/bin/alsa-scarlett-gui
Categories=GTK;AudioVideo;Audio;Mixer;
Keywords=focusrite;

View File

@@ -9,6 +9,18 @@ static void button_clicked(GtkWidget *widget, struct alsa_elem *elem) {
alsa_set_elem_value(elem, value);
}
static void toggle_button_set_text(struct alsa_elem *elem, const char *text) {
if (!text)
return;
if (*text == '*') {
GtkWidget *icon = gtk_image_new_from_icon_name(text + 1);
gtk_button_set_child(GTK_BUTTON(elem->widget), icon);
} else {
gtk_button_set_label(GTK_BUTTON(elem->widget), text);
}
}
static void toggle_button_updated(struct alsa_elem *elem) {
int is_writable = alsa_get_elem_writable(elem);
gtk_widget_set_sensitive(elem->widget, is_writable);
@@ -16,17 +28,7 @@ static void toggle_button_updated(struct alsa_elem *elem) {
int value = alsa_get_elem_value(elem);
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(elem->widget), value);
const char *text = elem->bool_text[value];
if (text) {
if (*text == '*') {
GtkWidget *icon = gtk_image_new_from_icon_name(text + 1);
gtk_button_set_child(GTK_BUTTON(elem->widget), icon);
} else {
gtk_button_set_label(
GTK_BUTTON(elem->widget), elem->bool_text[value]
);
}
}
toggle_button_set_text(elem, elem->bool_text[value]);
}
GtkWidget *make_boolean_alsa_elem(
@@ -44,6 +46,24 @@ GtkWidget *make_boolean_alsa_elem(
elem->bool_text[0] = disabled_text;
elem->bool_text[1] = enabled_text;
// find the maximum width and height of both possible labels
int max_width = 0, max_height = 0;
for (int i = 0; i < 2; i++) {
toggle_button_set_text(elem, elem->bool_text[i]);
GtkRequisition *size = gtk_requisition_new();
gtk_widget_get_preferred_size(button, size, NULL);
if (size->width > max_width)
max_width = size->width;
if (size->height > max_height)
max_height = size->height;
}
// set the widget minimum size to the maximum label size so that the
// widget doesn't change size when the label changes
gtk_widget_set_size_request(button, max_width, max_height);
toggle_button_updated(elem);
return button;

View File

@@ -24,7 +24,17 @@ static int update_levels_controls(void *user_data) {
// go through the ports in that category
for (int j = 0; j < card->routing_out_count[i]; j++) {
GtkWidget *meter = card->meters[meter_num];
gtk_dial_set_value(GTK_DIAL(meter), values[meter_num]);
double value = 20 * log10(values[meter_num] / 4095.0);
int int_value;
if (value < -80)
int_value = -80;
else if (value > 0)
int_value = 0;
else
int_value = round(value);
gtk_dial_set_value(GTK_DIAL(meter), int_value);
meter_num++;
}
}
@@ -93,7 +103,7 @@ GtkWidget *create_levels_controls(struct alsa_card *card) {
count_labels[j] = add_count_label(grid, j);
// create the meter widget and attach to the grid
GtkWidget *meter = gtk_dial_new_with_range(0, 4096, 1);
GtkWidget *meter = gtk_dial_new_with_range(-80, 0, 1);
card->meters[meter_num++] = meter;
gtk_grid_attach(GTK_GRID(grid), meter, j + 1, i + 1, 1, 1);
}

View File

@@ -107,8 +107,9 @@ static void get_routing_dsts(struct alsa_card *card) {
assert(j == count);
}
static void routing_grid_label(char *s, GtkGrid *g) {
static void routing_grid_label(char *s, GtkGrid *g, GtkAlign align) {
GtkWidget *l = gtk_label_new(s);
gtk_widget_set_halign(l, align);
gtk_grid_attach(g, l, 0, 0, 1, 1);
}
@@ -301,16 +302,16 @@ static void create_routing_grid(struct alsa_card *card) {
gtk_widget_set_hexpand(card->routing_mixer_in_grid, TRUE);
gtk_widget_set_hexpand(card->routing_mixer_out_grid, TRUE);
gtk_widget_set_align(
card->routing_hw_in_grid, GTK_ALIGN_END, GTK_ALIGN_CENTER
card->routing_hw_in_grid, GTK_ALIGN_FILL, GTK_ALIGN_CENTER
);
gtk_widget_set_align(
card->routing_pcm_in_grid, GTK_ALIGN_END, GTK_ALIGN_CENTER
card->routing_pcm_in_grid, GTK_ALIGN_FILL, GTK_ALIGN_CENTER
);
gtk_widget_set_align(
card->routing_hw_out_grid, GTK_ALIGN_START, GTK_ALIGN_CENTER
card->routing_hw_out_grid, GTK_ALIGN_FILL, GTK_ALIGN_CENTER
);
gtk_widget_set_align(
card->routing_pcm_out_grid, GTK_ALIGN_START, GTK_ALIGN_CENTER
card->routing_pcm_out_grid, GTK_ALIGN_FILL, GTK_ALIGN_CENTER
);
gtk_widget_set_align(
card->routing_mixer_in_grid, GTK_ALIGN_CENTER, GTK_ALIGN_END
@@ -319,10 +320,18 @@ static void create_routing_grid(struct alsa_card *card) {
card->routing_mixer_out_grid, GTK_ALIGN_CENTER, GTK_ALIGN_START
);
routing_grid_label("Hardware Inputs", GTK_GRID(card->routing_hw_in_grid));
routing_grid_label("Hardware Outputs", GTK_GRID(card->routing_hw_out_grid));
routing_grid_label("PCM Outputs", GTK_GRID(card->routing_pcm_in_grid));
routing_grid_label("PCM Inputs", GTK_GRID(card->routing_pcm_out_grid));
routing_grid_label(
"Hardware Inputs", GTK_GRID(card->routing_hw_in_grid), GTK_ALIGN_END
);
routing_grid_label(
"Hardware Outputs", GTK_GRID(card->routing_hw_out_grid), GTK_ALIGN_START
);
routing_grid_label(
"PCM Outputs", GTK_GRID(card->routing_pcm_in_grid), GTK_ALIGN_END
);
routing_grid_label(
"PCM Inputs", GTK_GRID(card->routing_pcm_out_grid), GTK_ALIGN_START
);
GtkWidget *src_label = gtk_label_new("\nSources →");
gtk_label_set_justify(GTK_LABEL(src_label), GTK_JUSTIFY_CENTER);
@@ -645,11 +654,17 @@ static void make_src_routing_widget(
GtkWidget *label = gtk_label_new(name);
gtk_box_append(GTK_BOX(box), label);
gtk_widget_add_class(box, "route-label");
if (orientation == GTK_ORIENTATION_HORIZONTAL) {
gtk_widget_set_halign(label, GTK_ALIGN_END);
gtk_widget_set_hexpand(label, TRUE);
}
}
if (orientation == GTK_ORIENTATION_HORIZONTAL) {
gtk_box_append(GTK_BOX(box), socket);
gtk_widget_set_halign(box, GTK_ALIGN_END);
gtk_widget_set_halign(box, GTK_ALIGN_FILL);
gtk_widget_set_hexpand(box, TRUE);
} else {
gtk_box_prepend(GTK_BOX(box), socket);
gtk_widget_set_margin_start(box, 5);
@@ -703,7 +718,10 @@ static void make_dst_routing_widget(
gtk_widget_set_margin_end(box, 5);
} else {
gtk_box_prepend(GTK_BOX(box), socket);
gtk_widget_set_halign(box, GTK_ALIGN_START);
gtk_widget_set_halign(box, GTK_ALIGN_FILL);
gtk_widget_set_hexpand(box, TRUE);
gtk_widget_set_hexpand(label, TRUE);
gtk_widget_set_halign(label, GTK_ALIGN_START);
}
// handle clicks on the box

View File

@@ -86,7 +86,7 @@ static void add_phantom_persistence_control(
GtkWidget *w;
w = small_label("Phantom Power Persistance");
w = small_label("Phantom Power Persistence");
gtk_grid_attach(GTK_GRID(grid), w, 0, *grid_y, 1, 1);
w = make_boolean_alsa_elem(phantom, "Disabled", "Enabled");

View File

@@ -0,0 +1,25 @@
app-id: vu.b4.alsa-scarlett-gui
runtime: org.gnome.Platform
runtime-version: "45"
sdk: org.gnome.Sdk
command: alsa-scarlett-gui
finish-args:
# X11 + XShm access
- --share=ipc
- --socket=fallback-x11
# Wayland access
- --socket=wayland
# Needs access to ALSA device nodes:
- --device=all
modules:
- name: alsa-scarlett-gui
buildsystem: simple
build-commands:
- make install PREFIX=$FLATPAK_DEST
sources:
- type: dir
path: ./src
# Use the following and remove the above for Flathub publishing
# - type: git
# url: https://github.com/geoffreybennett/alsa-scarlett-gui.git
# tag: "0.2"